Created
March 12, 2013 07:28
-
-
Save kballenegger/5140933 to your computer and use it in GitHub Desktop.
Base 64 encoding / decoding routines written in C.
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
| // out must be cb_b642bytes_outsize(sizeof(in)-1) aka cb_b642bytes_outsize(strlen(in)) | |
| // returns length of out, (which *may* be zero-padded) if return val > cb_b642bytes_outsize | |
| static inline int cb_b642bytes_outsize(int insize) { return ((insize-insize%4)+(insize%4==0?0:4))/4*3; } | |
| int cb_b642bytes(unsigned char *out, const char *in); | |
| // out must be cb_bytes2b64_outsize(sizeof(in)) | |
| // returns null-terminated string | |
| static inline int cb_bytes2b64_outsize(int insize) { return ((insize-insize%3)+(insize%3==0?0:3))/3*4+1; } | |
| void cb_bytes2b64(char *out, const unsigned char *in, int in_length); |
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
| static const unsigned char base64_table[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; | |
| int cb_b642bytes(unsigned char *out, const char *in) { | |
| // technically, the string should be =-padded, but it'll still work if it isn't :) | |
| unsigned char *write = out; | |
| int in_len = strlen(in); | |
| int i = 0; int last_i = 0; | |
| char tuple[4] = {0,0,0,0}; | |
| for (int c = 0; c < in_len; c++) { | |
| if (c < in_len) { | |
| char index = 0; | |
| for (; index < sizeof(base64_table)-1+1; index++) { | |
| if (base64_table[index] == in[c]) break; | |
| } | |
| if (index >= sizeof(base64_table)-1) continue; // out of bounds | |
| // we've found a good character, and index contains its numerical value | |
| tuple[i++%4] = index; | |
| } | |
| // every tuple | |
| if (i > last_i && (i%4 == 0 || c+2>=in_len)) { | |
| last_i = i; | |
| // inverse conversion | |
| for (int j = 0; j < (i%4==0 ? 4 : i%4); j++) { | |
| switch (j) { | |
| case 1: { | |
| *(write++) = (tuple[0] << 2) | (tuple[1] >> 4); | |
| } break; | |
| case 2: { | |
| *(write++) = (tuple[1] << 4) | (tuple[2] >> 2); | |
| } break; | |
| case 3: { | |
| *(write++) = (tuple[2] << 6) | tuple[3]; | |
| } break; | |
| default: break; | |
| } | |
| } | |
| } | |
| } | |
| // fill remainder of buffer with zeros. unnecessary but safer and cheap | |
| // for (unsigned char *to_zero = write; to_zero < out + cb_bytes2b64_outsize(in_len); to_zero++) { | |
| // *to_zero = 0; | |
| // } | |
| return write - out; | |
| } | |
| void cb_bytes2b64(char *out, const unsigned char *in, int in_length) { | |
| int mod = in_length % 3; | |
| for (int i = 0; i < in_length; i+=3) { | |
| int last = in_length-i <= 3; | |
| unsigned char in_word[3] = {0,0,0}; | |
| memcpy(&in_word, in+i, last ? sizeof(in_word) - (3-mod)%3 : sizeof(in_word)); | |
| // in ab ef gh | |
| // out e f g h | |
| *(out++) = base64_table[(in_word[0] >> 2)]; | |
| *(out++) = base64_table[((in_word[0] << 4) & 63) | (in_word[1] >> 4)]; | |
| *(out++) = base64_table[((in_word[1] << 2) & 63) | (in_word[2] >> 6)]; | |
| *(out++) = base64_table[(in_word[2] & 63)]; | |
| } | |
| if (mod == 1) *(out-2) = '='; | |
| if (mod >= 1) *(out-1) = '='; | |
| *(out) = 0; | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment