Created
July 11, 2015 22:19
-
-
Save dalemyers/7af163b7a4b170e9701a to your computer and use it in GitHub Desktop.
A simple ASCII text compressor using base 64 encoding
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <math.h> | |
#include <stdio.h> | |
#include <stdlib.h> | |
#include <stdint.h> | |
#include <string.h> | |
#define CHARACTERS_LENGTH 62 | |
char initialised = 0; | |
char *characters; | |
void initialise(){ | |
uint8_t tempChars[] = {'\0', 'A','B','C','D','E','F','G','H', | |
'I','J','K','L','M','N','O','P', | |
'Q','R','S','T','U','V','W','X', | |
'Y','Z','0','1','2','3','4','5', | |
'6','7','8','9',' ','.',',','<', | |
'>','/','?',';',':','|','"','!', | |
'@','#','%','&','*','(',')','-', | |
'_','=','+','\'','$'}; | |
characters = malloc(sizeof(uint8_t) * CHARACTERS_LENGTH); | |
memcpy(characters,tempChars,CHARACTERS_LENGTH); | |
initialised = 1; | |
} | |
int stringLength(uint8_t* inputData){ | |
int byteNum = 0; | |
int bitNum = 8; | |
uint8_t current = 0; | |
while(1){ | |
if(bitNum == 8){ | |
current = (inputData[byteNum] >> 2) & 0x3F; | |
bitNum = 2; | |
} else if(bitNum == 6) { | |
current = inputData[byteNum] & 0x3F; | |
byteNum++; | |
bitNum = 8; | |
} else if(bitNum == 4) { | |
current = (inputData[byteNum] << 2) & 0x3C; | |
byteNum++; | |
current = current | ((inputData[byteNum] >> 6) & 0x03); | |
bitNum = 6; | |
} else if(bitNum == 2) { | |
current = (inputData[byteNum] << 4) & 0x30; | |
byteNum++; | |
current = current | ((inputData[byteNum] >> 4) & 0x0F); | |
bitNum = 4; | |
} | |
if(!current) return byteNum; | |
} | |
} | |
void printHexString(uint8_t* string){ | |
int stringLen = stringLength(string); | |
int i = 0; | |
for(i = 0; i < stringLen; i++){ | |
printf("%.2X ",(uint8_t)(*(string + i))); | |
} | |
printf("\n"); | |
} | |
void printIntString(uint8_t* string){ | |
int stringLen = stringLength(string); | |
int i = 0; | |
for(i = 0; i < stringLen; i++){ | |
printf("%d ",(uint8_t)(*(string + i))); | |
} | |
printf("\n"); | |
} | |
uint8_t findPosition(uint8_t* character, uint8_t* array, uint8_t arrayLength){ | |
int i = 0; | |
for(i = 0; i < arrayLength; i++){ | |
uint8_t current = *character; | |
if(current >=97 && current <= 123){ | |
current = current - 32; | |
} | |
if(current == array[i]){ | |
return i; | |
} | |
} | |
printf("Character not found: %c\n",(char)(*character)); | |
return 0xFF; | |
} | |
uint8_t getCharacter(uint8_t index, uint8_t* array, uint8_t arrayLength){ | |
if(index > arrayLength) return 0xFF; | |
return (uint8_t)(*(array + index)); | |
} | |
uint8_t* encodedData(uint8_t *string){ | |
if(!initialised) initialise(); | |
int stringBitLength = strlen((char*)string) * 6; | |
int outputLength = (int)ceil((double)stringBitLength / 8.0); | |
if(stringBitLength % 8 == 0) outputLength++; | |
outputLength++; | |
uint8_t *returnData = malloc(sizeof(uint8_t) * outputLength); | |
int i = 0; | |
int byteNum = 0; | |
int bitNum = 8; | |
for(i = 0; i < outputLength; i++){ | |
returnData[i] = '\0'; | |
} | |
for(i = 0; i < strlen((char*)string); i++){ | |
int value = findPosition((string + i),characters,CHARACTERS_LENGTH); | |
if(value == 0xFF) continue; | |
if(bitNum == 8){ | |
returnData[byteNum] = (value << 2) & 0xFC; | |
bitNum = 2; | |
} else if(bitNum == 6) { | |
returnData[byteNum] = (returnData[byteNum] & 0xC0) | (value & 0x3F); | |
byteNum++; | |
bitNum = 8; | |
} else if(bitNum == 4) { | |
returnData[byteNum] = (returnData[byteNum] & 0xF0) | ((value >> 2) & 0x0F); | |
byteNum++; | |
returnData[byteNum] = (returnData[byteNum] & 0x3F) | ((value << 6) & 0xC0); | |
bitNum = 6; | |
} else if(bitNum == 2) { | |
returnData[byteNum] = (returnData[byteNum] & 0xFC) | ((value >> 4) & 0x03); | |
byteNum++; | |
returnData[byteNum] = (returnData[byteNum] & 0x0F) | ((value << 4) & 0xF0); | |
bitNum = 4; | |
} | |
} | |
return returnData; | |
} | |
uint8_t* decodedData(uint8_t *string){ | |
if(!initialised) initialise(); | |
int stringBitLength = stringLength(string) * 8; | |
int outputLength = (int)ceil((double)stringBitLength / 6.0); | |
if(stringBitLength % 6 == 0) outputLength++; | |
outputLength++; | |
uint8_t *inputData = malloc(stringLength(string) + 1); | |
memcpy(inputData,string,stringLength(string)); | |
inputData[stringLength(string)] = '\0'; | |
uint8_t *returnData = malloc(sizeof(uint8_t) * outputLength); | |
int i = 0; | |
int byteNum = 0; | |
int bitNum = 8; | |
uint8_t current = 0; | |
for(i = 0; i < outputLength; i++){ | |
returnData[i] = '\0'; | |
} | |
for(i = 0; i < outputLength; i++){ | |
if(bitNum == 8){ | |
current = (inputData[byteNum] >> 2) & 0x3F; | |
bitNum = 2; | |
} else if(bitNum == 6) { | |
current = inputData[byteNum] & 0x3F; | |
byteNum++; | |
bitNum = 8; | |
} else if(bitNum == 4) { | |
current = (inputData[byteNum] << 2) & 0x3C; | |
byteNum++; | |
current = current | ((inputData[byteNum] >> 6) & 0x03); | |
bitNum = 6; | |
} else if(bitNum == 2) { | |
current = (inputData[byteNum] << 4) & 0x30; | |
byteNum++; | |
current = current | ((inputData[byteNum] >> 4) & 0x0F); | |
bitNum = 4; | |
} | |
uint8_t character = getCharacter(current,characters,CHARACTERS_LENGTH); | |
if(character == 0xFF) continue; | |
*(returnData + i) = (uint8_t)character; | |
} | |
return returnData; | |
} | |
int main(int argc, char* argv[]){ | |
char *testString; | |
if(argc > 1){ | |
testString = argv[1]; | |
char *encodedString = encodedData(testString); | |
printHexString(encodedString); | |
char *decodedString = decodedData(encodedString); | |
printf("DECODED STRING: %s\n",decodedString); | |
} | |
} | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment