Initial source commit
This commit is contained in:
commit
f1384c11ee
335 changed files with 52715 additions and 0 deletions
453
minorGems/formats/encodingUtils.cpp
Normal file
453
minorGems/formats/encodingUtils.cpp
Normal file
|
@ -0,0 +1,453 @@
|
|||
/*
|
||||
* Modification History
|
||||
*
|
||||
* 2003-August-22 Jason Rohrer
|
||||
* Created.
|
||||
*
|
||||
* 2003-September-22 Jason Rohrer
|
||||
* Added base64 encoding.
|
||||
*
|
||||
* 2004-March-21 Jason Rohrer
|
||||
* Fixed a variable scoping and redefinition bug pointed out by Benjamin Meyer.
|
||||
*/
|
||||
|
||||
|
||||
#include "encodingUtils.h"
|
||||
|
||||
|
||||
#include "minorGems/util/SimpleVector.h"
|
||||
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
|
||||
|
||||
char fourBitIntToHex( int inInt ) {
|
||||
char outChar[2];
|
||||
|
||||
if( inInt < 10 ) {
|
||||
sprintf( outChar, "%d", inInt );
|
||||
}
|
||||
else {
|
||||
switch( inInt ) {
|
||||
case 10:
|
||||
outChar[0] = 'A';
|
||||
break;
|
||||
case 11:
|
||||
outChar[0] = 'B';
|
||||
break;
|
||||
case 12:
|
||||
outChar[0] = 'C';
|
||||
break;
|
||||
case 13:
|
||||
outChar[0] = 'D';
|
||||
break;
|
||||
case 14:
|
||||
outChar[0] = 'E';
|
||||
break;
|
||||
case 15:
|
||||
outChar[0] = 'F';
|
||||
break;
|
||||
default:
|
||||
outChar[0] = '0';
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return outChar[0];
|
||||
}
|
||||
|
||||
|
||||
|
||||
// returns -1 if inHex is not a valid hex character
|
||||
int hexToFourBitInt( char inHex ) {
|
||||
int returnInt;
|
||||
|
||||
switch( inHex ) {
|
||||
case '0':
|
||||
returnInt = 0;
|
||||
break;
|
||||
case '1':
|
||||
returnInt = 1;
|
||||
break;
|
||||
case '2':
|
||||
returnInt = 2;
|
||||
break;
|
||||
case '3':
|
||||
returnInt = 3;
|
||||
break;
|
||||
case '4':
|
||||
returnInt = 4;
|
||||
break;
|
||||
case '5':
|
||||
returnInt = 5;
|
||||
break;
|
||||
case '6':
|
||||
returnInt = 6;
|
||||
break;
|
||||
case '7':
|
||||
returnInt = 7;
|
||||
break;
|
||||
case '8':
|
||||
returnInt = 8;
|
||||
break;
|
||||
case '9':
|
||||
returnInt = 9;
|
||||
break;
|
||||
case 'A':
|
||||
case 'a':
|
||||
returnInt = 10;
|
||||
break;
|
||||
case 'B':
|
||||
case 'b':
|
||||
returnInt = 11;
|
||||
break;
|
||||
case 'C':
|
||||
case 'c':
|
||||
returnInt = 12;
|
||||
break;
|
||||
case 'D':
|
||||
case 'd':
|
||||
returnInt = 13;
|
||||
break;
|
||||
case 'E':
|
||||
case 'e':
|
||||
returnInt = 14;
|
||||
break;
|
||||
case 'F':
|
||||
case 'f':
|
||||
returnInt = 15;
|
||||
break;
|
||||
default:
|
||||
returnInt = -1;
|
||||
break;
|
||||
}
|
||||
|
||||
return returnInt;
|
||||
}
|
||||
|
||||
|
||||
|
||||
char *hexEncode( unsigned char *inData, int inDataLength ) {
|
||||
|
||||
char *resultHexString = new char[ inDataLength * 2 + 1 ];
|
||||
int hexStringIndex = 0;
|
||||
|
||||
for( int i=0; i<inDataLength; i++ ) {
|
||||
|
||||
unsigned char currentByte = inData[ i ];
|
||||
|
||||
int highBits = 0xF & ( currentByte >> 4 );
|
||||
int lowBits = 0xF & ( currentByte );
|
||||
|
||||
resultHexString[ hexStringIndex ] = fourBitIntToHex( highBits );
|
||||
hexStringIndex++;
|
||||
|
||||
resultHexString[ hexStringIndex ] = fourBitIntToHex( lowBits );
|
||||
hexStringIndex++;
|
||||
}
|
||||
|
||||
resultHexString[ hexStringIndex ] = '\0';
|
||||
|
||||
return resultHexString;
|
||||
}
|
||||
|
||||
|
||||
|
||||
unsigned char *hexDecode( char *inHexString ) {
|
||||
|
||||
int hexLength = strlen( inHexString );
|
||||
|
||||
if( hexLength % 2 != 0 ) {
|
||||
// hex strings must be even in length
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int dataLength = hexLength / 2;
|
||||
|
||||
unsigned char *rawData = new unsigned char[ dataLength ];
|
||||
|
||||
|
||||
for( int i=0; i<dataLength; i++ ) {
|
||||
|
||||
int highBits = hexToFourBitInt( inHexString[ 2 * i ] );
|
||||
int lowBits = hexToFourBitInt( inHexString[ 2 * i + 1 ] );
|
||||
|
||||
if( highBits == -1 || lowBits == -1 ) {
|
||||
delete [] rawData;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
rawData[i] = (unsigned char)( highBits << 4 | lowBits );
|
||||
}
|
||||
|
||||
return rawData;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* These tables were taken from the GNU Privacy Guard source code.
|
||||
*
|
||||
* Wow... writing base64 functions would have been much more difficult
|
||||
* without these tables, especially the reverse table.
|
||||
*/
|
||||
|
||||
|
||||
|
||||
// The base-64 character list
|
||||
// Maps base64 binary numbers to ascii characters
|
||||
static const char *binaryToAscii =
|
||||
"ABCDEFGHIJKLMNOPQRSTUVWXYZ"
|
||||
"abcdefghijklmnopqrstuvwxyz"
|
||||
"0123456789+/";
|
||||
|
||||
// The reverse base-64 list
|
||||
// Maps ascii characters to base64 binary numbers
|
||||
static unsigned char asciiToBinary[256] = {
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3e, 0xff, 0xff, 0xff, 0x3f,
|
||||
0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06,
|
||||
0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12,
|
||||
0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23, 0x24,
|
||||
0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30,
|
||||
0x31, 0x32, 0x33, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff };
|
||||
|
||||
|
||||
char *base64Encode( unsigned char *inData, int inDataLength,
|
||||
char inBreakLines ) {
|
||||
|
||||
SimpleVector<char> *encodingVector = new SimpleVector<char>();
|
||||
|
||||
int numInLine = 0;
|
||||
|
||||
// take groups of 3 data bytes and map them to 4 base64 digits
|
||||
for( int i=0; i<inDataLength; i=i+3 ) {
|
||||
|
||||
if( i+2 < inDataLength ) {
|
||||
// not at end yet
|
||||
|
||||
unsigned int block =
|
||||
inData[i] << 16 |
|
||||
inData[i+1] << 8 |
|
||||
inData[i+2];
|
||||
|
||||
// base64 digits, with digitA at left
|
||||
unsigned int digitA = 0x3F & ( block >> 18 );
|
||||
unsigned int digitB = 0x3F & ( block >> 12 );
|
||||
unsigned int digitC = 0x3F & ( block >> 6 );
|
||||
unsigned int digitD = 0x3F & ( block );
|
||||
|
||||
encodingVector->push_back( binaryToAscii[ digitA ] );
|
||||
encodingVector->push_back( binaryToAscii[ digitB ] );
|
||||
encodingVector->push_back( binaryToAscii[ digitC ] );
|
||||
encodingVector->push_back( binaryToAscii[ digitD ] );
|
||||
numInLine += 4;
|
||||
|
||||
if( inBreakLines && numInLine == 76 ) {
|
||||
// break the line
|
||||
encodingVector->push_back( '\r' );
|
||||
encodingVector->push_back( '\n' );
|
||||
numInLine = 0;
|
||||
}
|
||||
|
||||
}
|
||||
else {
|
||||
// at end
|
||||
int numLeft = inDataLength - i;
|
||||
|
||||
switch( numLeft ) {
|
||||
case 0:
|
||||
// no padding
|
||||
break;
|
||||
case 1: {
|
||||
// two digits, two pads
|
||||
unsigned int block =
|
||||
inData[i] << 16 |
|
||||
0;
|
||||
unsigned int digitA = 0x3F & ( block >> 18 );
|
||||
unsigned int digitB = 0x3F & ( block >> 12 );
|
||||
|
||||
encodingVector->push_back( binaryToAscii[ digitA ] );
|
||||
encodingVector->push_back( binaryToAscii[ digitB ] );
|
||||
|
||||
encodingVector->push_back( '=' );
|
||||
encodingVector->push_back( '=' );
|
||||
break;
|
||||
}
|
||||
case 2: {
|
||||
// three digits, one pad
|
||||
unsigned int block =
|
||||
inData[i] << 16 |
|
||||
inData[i+1] << 8 |
|
||||
0;
|
||||
|
||||
// base64 digits, with digitA at left
|
||||
unsigned int digitA = 0x3F & ( block >> 18 );
|
||||
unsigned int digitB = 0x3F & ( block >> 12 );
|
||||
unsigned int digitC = 0x3F & ( block >> 6 );
|
||||
|
||||
encodingVector->push_back( binaryToAscii[ digitA ] );
|
||||
encodingVector->push_back( binaryToAscii[ digitB ] );
|
||||
encodingVector->push_back( binaryToAscii[ digitC ] );
|
||||
encodingVector->push_back( '=' );
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
// done with all data
|
||||
i = inDataLength;
|
||||
}
|
||||
}
|
||||
|
||||
char *returnString = encodingVector->getElementString();
|
||||
|
||||
delete encodingVector;
|
||||
|
||||
return returnString;
|
||||
}
|
||||
|
||||
|
||||
|
||||
unsigned char *base64Decode( char *inBase64String,
|
||||
int *outDataLength ) {
|
||||
|
||||
SimpleVector<unsigned char> *decodedVector =
|
||||
new SimpleVector<unsigned char>();
|
||||
|
||||
|
||||
|
||||
int encodingLength = strlen( inBase64String );
|
||||
|
||||
SimpleVector<unsigned char> *binaryEncodingVector =
|
||||
new SimpleVector<unsigned char>();
|
||||
|
||||
int i;
|
||||
for( i=0; i<encodingLength; i++ ) {
|
||||
unsigned char currentChar = (unsigned char)( inBase64String[i] );
|
||||
|
||||
unsigned char currentBinary = asciiToBinary[ currentChar ];
|
||||
|
||||
if( currentBinary != 0xFF ) {
|
||||
// in range
|
||||
binaryEncodingVector->push_back( currentBinary );
|
||||
}
|
||||
}
|
||||
|
||||
int binaryEncodingLength = binaryEncodingVector->size();
|
||||
|
||||
unsigned char *binaryEncoding = binaryEncodingVector->getElementArray();
|
||||
delete binaryEncodingVector;
|
||||
|
||||
int blockCount = binaryEncodingLength / 4;
|
||||
|
||||
if( binaryEncodingLength % 4 != 0 ) {
|
||||
// extra, 0-padded block
|
||||
blockCount += 1;
|
||||
}
|
||||
|
||||
|
||||
|
||||
// take groups of 4 encoded digits and map them to 3 data bytes
|
||||
for( i=0; i<binaryEncodingLength; i=i+4 ) {
|
||||
|
||||
if( i+3 < binaryEncodingLength ) {
|
||||
// not at end yet
|
||||
|
||||
unsigned int block =
|
||||
binaryEncoding[i] << 18 |
|
||||
binaryEncoding[i+1] << 12 |
|
||||
binaryEncoding[i+2] << 6 |
|
||||
binaryEncoding[i+3];
|
||||
|
||||
// data byte digits, with digitA at left
|
||||
unsigned int digitA = 0xFF & ( block >> 16 );
|
||||
unsigned int digitB = 0xFF & ( block >> 8 );
|
||||
unsigned int digitC = 0xFF & ( block );
|
||||
|
||||
decodedVector->push_back( digitA );
|
||||
decodedVector->push_back( digitB );
|
||||
decodedVector->push_back( digitC );
|
||||
}
|
||||
else {
|
||||
// at end
|
||||
int numLeft = binaryEncodingLength - i;
|
||||
|
||||
switch( numLeft ) {
|
||||
case 0:
|
||||
// no padding
|
||||
break;
|
||||
case 1: {
|
||||
// impossible
|
||||
break;
|
||||
}
|
||||
case 2: {
|
||||
// two base64 digits, one data byte
|
||||
unsigned int block =
|
||||
binaryEncoding[i] << 18 |
|
||||
binaryEncoding[i+1] << 12 |
|
||||
0;
|
||||
|
||||
// data byte digits, with digitA at left
|
||||
unsigned int digitA = 0xFF & ( block >> 16 );
|
||||
|
||||
decodedVector->push_back( digitA );
|
||||
break;
|
||||
}
|
||||
case 3: {
|
||||
// three base64 digits, two data bytes
|
||||
unsigned int block =
|
||||
binaryEncoding[i] << 18 |
|
||||
binaryEncoding[i+1] << 12 |
|
||||
binaryEncoding[i+2] << 6 |
|
||||
0;
|
||||
|
||||
// data byte digits, with digitA at left
|
||||
unsigned int digitA = 0xFF & ( block >> 16 );
|
||||
unsigned int digitB = 0xFF & ( block >> 8 );
|
||||
|
||||
|
||||
decodedVector->push_back( digitA );
|
||||
decodedVector->push_back( digitB );
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
// done with all data
|
||||
i = binaryEncodingLength;
|
||||
}
|
||||
}
|
||||
|
||||
delete [] binaryEncoding;
|
||||
|
||||
|
||||
*outDataLength = decodedVector->size();
|
||||
unsigned char* returnData = decodedVector->getElementArray();
|
||||
|
||||
delete decodedVector;
|
||||
|
||||
return returnData;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
Loading…
Add table
Add a link
Reference in a new issue