Initial source commit

This commit is contained in:
Tony Bark 2025-10-03 02:19:59 -04:00
commit f1384c11ee
335 changed files with 52715 additions and 0 deletions

View 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;
}