From Wikipedia:
Base64 is a group of similar binary-to-text encoding schemes that represent binary data in an ASCII string format by translating it into a radix-64 representation. The term Base64 originates from a specific MIME content transfer encoding.
Base64 encoding schemes are commonly used when there is a need to encode binary data that needs to be stored and transferred over media that is designed to deal with textual data. This is to ensure that the data remains intact without modification during transport. Base64 is commonly used in a number of applications, including email via MIME, and storing complex data in XML.
Below is an implementation of such an encoder I have created.
/******************************************************************************* * @file: base64_encoder.c * @author: Matthew Giassa * @email: matthew@giassa.net * @copyright: Matthew Giassa, 2014 * @brief: Base64 encoder for testing purposes. */ /******************************************************************************* * Preprocessor Directives ******************************************************************************/ /* System Includes */ #include <stdio.h> #include <errno.h> #include <stdlib.h> #include <string.h> #include <stdint.h> /* Project Includes */ /******************************************************************************* * Macros and Constants ******************************************************************************/ #define EOK (0) const char base64_map[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" \ "abcdefghijklmnopqrstuvwxyz" \ "0123456789+/"; #define MAX_STR_LEN (32) #define NUM_STRINGS (8) #define NUM_MAPS (4) /******************************************************************************* * Abstract Data Types ******************************************************************************/ typedef struct base64_t { uint32_t payload; size_t numTokens; char map[NUM_MAPS]; size_t numMappings; } base64_t; /******************************************************************************* * Private Function Prototypes ******************************************************************************/ /******************************************************************************* * Function Definitions ******************************************************************************/ int main(void) { /* Assuming we are provided an ASCII text stream that, at the minimum, * prefixes all hex values with "0x", delimits individual values with a * space (ie: ' ') character, and provides us with at least one complete * value, and no incomplete values or broken strings. */ char str[NUM_STRINGS][MAX_STR_LEN] = { "0x00 0x45 0xF2", "0x01 0x45 0xF2", "0x00 0x20", "0x00 0x00 0x00", "0x00 0x00", "0x00", "0x01", "0xFF", }; const char delim[2] = " "; char *token; int i, j; /* Create an array of structures to hold information on our bitstreams */ base64_t* b; if ((b = calloc(NUM_STRINGS, sizeof(base64_t))) == NULL) { printf("Memory allocation error; Aborting\n"); return (-ENOMEM); } /* Parse the input bitstreams and store as integers */ for (i=0; i<NUM_STRINGS; i++) { /* Get the first token */ token = strtok(str[i], delim); /* Parse remaining tokens and convert to uint */ for (j=0; token!= NULL; j++) { unsigned tmp = (unsigned)strtoul(token, NULL, 0); b[i].payload = ((b[i].payload << 8) & 0xFFFF00) | tmp; printf("Byte#%d:0x%02X ", j, tmp); token = strtok(NULL, delim); } b[i].numTokens = j; printf(" - Final Payload:0x%06X\n", b[i].payload); } /* Convert saved data to the requested mappings */ const int idxMax = 4; for (i=0; i<NUM_STRINGS; i++) { for (j=0; j<4; j++) { if (b[i].payload == 0) { b[i].map[0] = '='; b[i].numMappings = 1; break; } else { b[i].map[j] = base64_map[((b[i].payload & (0x3F<<(6*(3-j))) ) >> (6*(3-j)))]; b[i].numMappings++; } } } /* Print final results */ for (i=0; i<NUM_STRINGS; i++) { for (j=0; j<b[i].numMappings; j++) { printf(" Stream %d: Mapping %d: %c\n", i, j, b[i].map[j]); } printf("\n"); } /* Clean up */ free(b); return 0; }