Last active
April 17, 2017 01:01
-
-
Save FergusInLondon/47010962253e65d636fc98ebef74fad1 to your computer and use it in GitHub Desktop.
Base 64 Encoding in C
This file contains 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 <stdio.h> | |
#include <stdlib.h> | |
#define FIRST_SIX_INDEX (buf[0] & 0xfc) >> 2 | |
#define SECOND_SIX_INDEX ((buf[0] & 0x03) << 4) + ((buf[1] & 0xf0) >> 4) | |
#define THIRD_SIX_INDEX ((buf[1] & 0x0f) << 2) + ((buf[2] & 0xc0) >> 6) | |
#define FOURTH_SIX_INDEX buf[2] & 0x3f | |
char base64_map[]="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/="; | |
char * | |
base64_encode(const unsigned char *src, size_t len) { | |
char *encoded = malloc( ((len/3) * 4) + 1); | |
int encoded_counter = 0, cursor = 0; | |
unsigned char buf[3]; | |
/* Process the string 3 bytes at a time, allowing us to generate the | |
corresponding 4 6-bit values for the base64 representation */ | |
for (; (cursor+3) < len; cursor += 3) { | |
// Buffer 3 bytes | |
buf[0] = *(src + cursor ); | |
buf[1] = *(src + (cursor + 1) ); | |
buf[2] = *(src + (cursor + 2) ); | |
// Use bitmask macros to find the corresponding value in the base64 map | |
encoded[encoded_counter++] = base64_map[ FIRST_SIX_INDEX ]; | |
encoded[encoded_counter++] = base64_map[ SECOND_SIX_INDEX ]; | |
encoded[encoded_counter++] = base64_map[ THIRD_SIX_INDEX ]; | |
encoded[encoded_counter++] = base64_map[ FOURTH_SIX_INDEX ]; | |
} | |
/* If a remainder is available, we do a very similar process - but we also | |
ensure that the output string is padded to a multiple of 4 - using '=' */ | |
if ((len-cursor) > 0) { | |
// Buffer final bytes, unused space should be nullified. | |
for (int j = 0; j < 3; j++) { | |
if (cursor < len) { | |
buf[j] = *(src + cursor++); | |
continue; | |
} | |
buf[j] = '\0'; | |
} | |
// First remainder will always be valid, fallback to '=' (64 on map) on | |
// subsequent output values. | |
encoded[encoded_counter++] = base64_map[ FIRST_SIX_INDEX ]; | |
encoded[encoded_counter++] = base64_map[ (SECOND_SIX_INDEX > 0) ? SECOND_SIX_INDEX : 64 ]; | |
encoded[encoded_counter++] = base64_map[ (THIRD_SIX_INDEX > 0) ? THIRD_SIX_INDEX : 64 ]; | |
encoded[encoded_counter++] = base64_map[ (FOURTH_SIX_INDEX > 0) ? FOURTH_SIX_INDEX : 64 ]; | |
} | |
encoded[encoded_counter++] = '\0'; | |
return encoded; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment