Doug Anson / Base64

Dependents:   GSMandSdWork

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers Base64.cpp Source File

Base64.cpp

Go to the documentation of this file.
00001 /**
00002  * @file    Base64.cpp
00003  * @brief   Base64 encoding and decoding (DERIVED WORK)
00004  * @author  David Smart, Smartware Computing, Doug Anson ARM
00005  * @version 1.0
00006  * @see     
00007  *
00008  * Copyright (c) 2014
00009  *
00010  * Licensed under the Apache License, Version 2.0 (the "License");
00011  * you may not use this file except in compliance with the License.
00012  * You may obtain a copy of the License at
00013  *
00014  *     http://www.apache.org/licenses/LICENSE-2.0
00015  *
00016  * Unless required by applicable law or agreed to in writing, software
00017  * distributed under the License is distributed on an "AS IS" BASIS,
00018  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00019  * See the License for the specific language governing permissions and
00020  * limitations under the License.
00021  *
00022  * @note Copyright © 2013 by Smartware Computing, all rights reserved.
00023  *     Individuals may use this application for evaluation or non-commercial
00024  *     purposes. Within this restriction, changes may be made to this application
00025  *     as long as this copyright notice is retained. The user shall make
00026  *     clear that their work is a derived work, and not the original.
00027  *     Users of this application and sources accept this application "as is" and
00028  *     shall hold harmless Smartware Computing, for any undesired results while
00029  *     using this application - whether real or imagined.
00030  *
00031  * author David Smart, Smartware Computing
00032  */
00033  
00034 #ifndef WIN32
00035 #include "mbed.h"
00036 #else
00037 #include "windows.h"
00038 typedef unsigned int uint32_t;
00039 #endif
00040 #include "Base64.h"
00041 
00042 static const char encoding_table[] = {
00043     'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H',
00044     'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P',
00045     'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X',
00046     'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f',
00047     'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n',
00048     'o', 'p', 'q', 'r', 's', 't', 'u', 'v',
00049     'w', 'x', 'y', 'z', '0', '1', '2', '3',
00050     '4', '5', '6', '7', '8', '9', '+', '/'
00051 };
00052 
00053 static const int mod_table[] = {0, 2, 1};
00054 
00055 Base64::Base64()
00056 {
00057     decoding_table = NULL;
00058 }
00059 
00060 Base64::~Base64()
00061 {
00062     if (decoding_table)
00063         free(decoding_table);
00064 }
00065 
00066 
00067 char * Base64::Encode(const char *data, size_t input_length, size_t *output_length)
00068 {
00069     *output_length = 4 * ((input_length + 2) / 3);
00070 
00071     char *encoded_data = (char *)malloc(*output_length+1);  // often used for text, so add room for NULL
00072     if (encoded_data == NULL) return NULL;
00073 
00074     for (unsigned int i = 0, j = 0; i < input_length;) {
00075 
00076         uint32_t octet_a = i < input_length ? data[i++] : 0;
00077         uint32_t octet_b = i < input_length ? data[i++] : 0;
00078         uint32_t octet_c = i < input_length ? data[i++] : 0;
00079 
00080         uint32_t triple = (octet_a << 0x10) + (octet_b << 0x08) + octet_c;
00081 
00082         encoded_data[j++] = encoding_table[(triple >> 3 * 6) & 0x3F];
00083         encoded_data[j++] = encoding_table[(triple >> 2 * 6) & 0x3F];
00084         encoded_data[j++] = encoding_table[(triple >> 1 * 6) & 0x3F];
00085         encoded_data[j++] = encoding_table[(triple >> 0 * 6) & 0x3F];
00086     }
00087 
00088     for (int i = 0; i < mod_table[input_length % 3]; i++)
00089         encoded_data[*output_length - 1 - i] = '=';
00090 
00091     encoded_data[*output_length] = '\0';    // as a courtesy to text users
00092     return encoded_data;
00093 }
00094 
00095 
00096 char * Base64::Decode(const char *data, size_t input_length, size_t *output_length)
00097 {
00098     if (decoding_table == NULL)
00099         build_decoding_table();
00100 
00101     if (input_length % 4 != 0) 
00102         return NULL;
00103 
00104     *output_length = input_length / 4 * 3;
00105     if (data[input_length - 1] == '=') (*output_length)--;
00106     if (data[input_length - 2] == '=') (*output_length)--;
00107 
00108     char *decoded_data = (char *)malloc(*output_length+1);  // often used for text, so add room for NULL
00109     if (decoded_data == NULL) 
00110         return NULL;
00111 
00112     for (unsigned int i = 0, j = 0; i < input_length;) {
00113 
00114         uint32_t sextet_a = data[i] == '=' ? 0 & i++ : decoding_table[data[i++]];
00115         uint32_t sextet_b = data[i] == '=' ? 0 & i++ : decoding_table[data[i++]];
00116         uint32_t sextet_c = data[i] == '=' ? 0 & i++ : decoding_table[data[i++]];
00117         uint32_t sextet_d = data[i] == '=' ? 0 & i++ : decoding_table[data[i++]];
00118 
00119         uint32_t triple = (sextet_a << 3 * 6)
00120                           + (sextet_b << 2 * 6)
00121                           + (sextet_c << 1 * 6)
00122                           + (sextet_d << 0 * 6);
00123 
00124         if (j < *output_length) 
00125             decoded_data[j++] = (triple >> 2 * 8) & 0xFF;
00126         if (j < *output_length) 
00127             decoded_data[j++] = (triple >> 1 * 8) & 0xFF;
00128         if (j < *output_length) 
00129             decoded_data[j++] = (triple >> 0 * 8) & 0xFF;
00130     }
00131     decoded_data[*output_length] = '\0';    // as a courtesy to text users
00132     return decoded_data;
00133 }
00134 
00135 
00136 void Base64::build_decoding_table()
00137 {
00138     decoding_table = (char *)malloc(256);
00139 
00140     for (int i = 0; i < 64; i++)
00141         decoding_table[(unsigned char) encoding_table[i]] = i;
00142 }