Nut/OS  4.10.3
API Reference
base64_encode.c
Go to the documentation of this file.
00001 /*
00002  * Copyright (C) 2009 by Thermotemp GmbH. All rights reserved.
00003  *
00004  * Redistribution and use in source and binary forms, with or without
00005  * modification, are permitted provided that the following conditions
00006  * are met:
00007  *
00008  * 1. Redistributions of source code must retain the above copyright
00009  *    notice, this list of conditions and the following disclaimer.
00010  * 2. Redistributions in binary form must reproduce the above copyright
00011  *    notice, this list of conditions and the following disclaimer in the
00012  *    documentation and/or other materials provided with the distribution.
00013  * 3. Neither the name of the copyright holders nor the names of
00014  *    contributors may be used to endorse or promote products derived
00015  *    from this software without specific prior written permission.
00016  *
00017  * THIS SOFTWARE IS PROVIDED BY THERMOTEMP GMBH AND CONTRIBUTORS
00018  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
00019  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
00020  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THERMOTEMP
00021  * GMBH OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 
00022  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 
00023  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
00024  * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
00025  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
00026  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
00027  * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
00028  * SUCH DAMAGE.
00029  *
00030  * For additional information see http://www.ethernut.de/
00031  */
00032 
00053 #include <stdint.h>
00054 #include <string.h>
00055 
00056 #include <sys/heap.h>
00057 #include <sys/types.h>
00062 
00063 static prog_char base64etab[64] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
00064 
00077 char *NutEncodeBase64(CONST char* str)
00078 {
00079     char    *encoded;
00080     size_t  length;
00081     size_t  encoded_length;
00082     int     idx, enc_pos;
00083     int32_t bits;
00084     int     cols;
00085     int     char_count; 
00086     
00087     /* Calculate buffer size for encoded data 
00088      * 8 Bit code converted into 6 Bit code ==> encoded code will be 4/3 larger
00089      * The algorithm will padd the encoded data with == so that the resulting 
00090      * length can be exactly deviced by 3
00091      * Also every 72 chars a <cr><lf> will be added
00092      */
00093     
00094     length = strlen(str);
00095     
00096     /* Calc the base code length, add one to the inital length to have space for rounding errors */
00097     encoded_length = ((length + 1) * 4) / 3;
00098     /* Add the size for the padding characters */
00099     encoded_length += encoded_length % 3;
00100     /* Now add the space for the inserted <cr><lf> characters and add one byte for the end of string NUL character*/
00101     encoded_length += (encoded_length / 72) * 2 + 3;
00102     /* Allocate the memory. */;
00103     encoded = NutHeapAlloc(encoded_length);
00104     
00105     if (encoded == NULL) return NULL;
00106     
00107     enc_pos = 0;
00108     char_count = 0;
00109     bits = 0;
00110     cols = 0;
00111     
00112     for (idx = 0; idx < length; idx ++) {
00113         bits += (int32_t)str[idx];
00114         char_count ++;
00115         if (char_count == 3) {
00116             encoded[enc_pos++] = PRG_RDB(&base64etab[(bits >> 18) & 0x3f]);
00117             encoded[enc_pos++] = PRG_RDB(&base64etab[(bits >> 12) & 0x3f]);
00118             encoded[enc_pos++] = PRG_RDB(&base64etab[(bits >> 6) & 0x3f]);
00119             encoded[enc_pos++] = PRG_RDB(&base64etab[bits & 0x3f]);
00120             cols += 4;
00121             if (cols == 72) {
00122                 encoded[enc_pos++] = '\r';
00123                 encoded[enc_pos++] = '\n';
00124                 cols =0;
00125             }
00126             bits = 0;
00127             char_count = 0;
00128         } else {
00129             bits <<= 8;
00130         }
00131     }
00132     
00133     if (char_count != 0) {
00134         bits <<= 16 - (8 * char_count);
00135         encoded[enc_pos++] = PRG_RDB(&base64etab[bits >> 18]);
00136         encoded[enc_pos++] = PRG_RDB(&base64etab[(bits >> 12) & 0x3f]);
00137         if (char_count == 1) {
00138             encoded[enc_pos++] = '=';
00139             encoded[enc_pos++] = '=';
00140         } else {
00141             encoded[enc_pos++] = PRG_RDB(&base64etab[(bits >> 6) & 0x3f]);
00142             encoded[enc_pos++] = '=';
00143         }
00144     }
00145     encoded[enc_pos] = '\0';
00146     return encoded;
00147 }
00148