Skip to content

Instantly share code, notes, and snippets.

@lqt0223
Created January 25, 2018 06:05
Show Gist options
  • Save lqt0223/9d774864306d2308966e8b8b13c04b70 to your computer and use it in GitHub Desktop.
Save lqt0223/9d774864306d2308966e8b8b13c04b70 to your computer and use it in GitHub Desktop.
22 Base64 Encoding
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define B64_UNIT_BYTE_SIZE 3
int b64_readbytes(char* src, int count) {
int result = 0;
for (int i = 0; i < count; i++, src++) {
result += *src;
if (i != count - 1) {
result <<= 8;
}
}
return result;
}
int b64_cleanbuffer(char* dest, int count) {
for (int i = 0; i < count; i++) {
dest[i] = 0x0;
}
return 0;
}
int b64_map_to_ascii_code(int b64code) {
// +
if (b64code == 62) {
return 43;
// /
} else if (b64code == 63) {
return 47;
// lower case
} else if (b64code >= 26 && b64code <= 51) {
return b64code + 71;
// upper case
} else if (b64code >= 0 && b64code <= 25) {
return b64code + 65;
// numerical
} else if (b64code >= 52 && b64code <= 61) {
return b64code - 4;
// error
} else {
return -1;
}
}
int b64_strcpy(char* dest, char* src, int size) {
for (int i = 0; i < size; i++) {
dest[i] = src[i];
}
return 0;
}
int b64_encode_unit(char* encoded, int src, int padsize) {
int mask1 = 0x3F;
int mask2 = mask1 << 6;
int mask3 = mask2 << 6;
int mask4 = mask3 << 6;
encoded[0] = b64_map_to_ascii_code((src & mask4) >> 18);
encoded[1] = b64_map_to_ascii_code((src & mask3) >> 12);
encoded[2] = b64_map_to_ascii_code((src & mask2) >> 6);
encoded[3] = b64_map_to_ascii_code((src & mask1));
if (padsize == 1) {
encoded[3] = 61;
} else if (padsize == 2) {
encoded[2] = 61;
encoded[3] = 61;
}
encoded[4] = 0x0;
return 0;
}
int b64_encode_str(char* dest, char* src, int src_size) {
char* encoded = (char*)malloc(sizeof(char) * 4);
int remainder = src_size % 3;
int i = 0;
while (i < src_size - remainder) {
int byte = b64_readbytes(src + i, B64_UNIT_BYTE_SIZE);
b64_encode_unit(encoded, byte, 0);
b64_strcpy(dest, encoded, 4);
i += B64_UNIT_BYTE_SIZE;
dest += 4;
}
// handling remainder
if (remainder == 1) {
int byte = src[src_size - 1];
byte <<= 16;
b64_encode_unit(encoded, byte, 2);
b64_strcpy(dest, encoded, 4);
} else if (remainder == 2) {
int byte = (src[src_size - 2] << 8) + src[src_size - 1];
byte <<= 8;
b64_encode_unit(encoded, byte, 1);
b64_strcpy(dest, encoded, 4);
}
free(encoded);
return 0;
}
int b64_encode_file_write_header(FILE* fp, char* mime) {
fprintf(fp, "data:%s;base64,", mime);
return 0;
}
int b64_encode_file(char* dest, char* src, char* mime) {
FILE* fp = fopen(src, "rb");
FILE* fp_out = fopen(dest, "w");
b64_encode_file_write_header(fp_out, mime);
char* encoded = (char*)malloc(sizeof(char) * 4);
int read = 0, byte = 0, count = 0;
while((read = fgetc(fp)) != EOF) {
switch (count) {
case 0:
case 1: {
byte += read;
byte <<= 8;
break;
}
case 2: {
byte += read;
b64_encode_unit(encoded, byte, 0);
fwrite(encoded, 4, 1, fp_out);
b64_cleanbuffer(encoded, 4);
byte = 0;
break;
}
}
count++;
if (count == 3) {
count = 0;
}
}
// handling remainder
if (count == 2) {
byte <<= 16;
b64_encode_unit(encoded, byte, 1);
fwrite(encoded, 4, 1, fp_out);
} else if (count == 1) {
byte <<= 8;
b64_encode_unit(encoded, byte, 2);
fwrite(encoded, 4, 1, fp_out);
}
fclose(fp_out);
free(encoded);
return 0;
}
int main() {
// read file from src, write the base64 encoded data uri to dest
char mime[] = "image/jpeg";
char src[] = "Directory of binary file to encode...";
char dest[] = "Directory of encoded data uri to export...";
b64_encode_file(dest, src, mime);
// encode string from src, write the base64 encoded string to dest
char src2[] = "hello";
char dest2[1024];
int size = strlen(src2);
b64_encode_str(dest2, src2, size);
printf("%s\n", dest2);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment