1 // ============================================================================
2 // Artsoft Retro-Game Library
3 // ----------------------------------------------------------------------------
4 // (c) 1995-2021 by Artsoft Entertainment
7 // https://www.artsoft.org/
8 // ----------------------------------------------------------------------------
10 // ============================================================================
14 https://github.com/superwills/NibbleAndAHalf
15 base64.h -- Fast base64 encoding and decoding.
16 version 1.0.0, April 17, 2013 143a
18 Copyright (C) 2013 William Sherif
20 This software is provided 'as-is', without any express or implied
21 warranty. In no event will the authors be held liable for any damages
22 arising from the use of this software.
24 Permission is granted to anyone to use this software for any purpose,
25 including commercial applications, and to alter it and redistribute it
26 freely, subject to the following restrictions:
28 1. The origin of this software must not be misrepresented; you must not
29 claim that you wrote the original software. If you use this software
30 in a product, an acknowledgment in the product documentation would be
31 appreciated but is not required.
32 2. Altered source versions must be plainly marked as such, and must not be
33 misrepresented as being the original software.
34 3. This notice may not be removed or altered from any source distribution.
39 YWxsIHlvdXIgYmFzZSBhcmUgYmVsb25nIHRvIHVz
49 const static char* b64="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/" ;
52 const static unsigned char unb64[]={
53 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //10
54 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //20
55 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //30
56 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //40
57 0, 0, 0, 62, 0, 0, 0, 63, 52, 53, //50
58 54, 55, 56, 57, 58, 59, 60, 61, 0, 0, //60
59 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, //70
60 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, //80
61 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, //90
62 25, 0, 0, 0, 0, 0, 0, 26, 27, 28, //100
63 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, //110
64 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, //120
65 49, 50, 51, 0, 0, 0, 0, 0, 0, 0, //130
66 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //140
67 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //150
68 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //160
69 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //170
70 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //180
71 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //190
72 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //200
73 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //210
74 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //220
75 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //230
76 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //240
77 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //250
79 }; // This array has 256 elements
81 // Converts binary data of length=len to base64 characters.
82 // Length of the resultant string is stored in flen
83 // (you must pass pointer flen).
84 char* base64( const void* binaryData, int len, int *flen )
86 const unsigned char* bin = (const unsigned char*) binaryData ;
89 int rc = 0 ; // result counter
90 int byteNo ; // I need this after the loop
92 int modulusLen = len % 3 ;
93 int pad = ((modulusLen&1)<<1) + ((modulusLen&2)>>1) ; // 2 gives 1 and 1 gives 2, but 0 gives 0.
95 *flen = 4*(len + pad)/3 ;
96 res = (char*) malloc( *flen + 1 ) ; // and one for the null
99 puts( "ERROR: base64 could not allocate enough memory." ) ;
100 puts( "I must stop because I could not get enough" ) ;
104 for( byteNo = 0 ; byteNo <= len-3 ; byteNo+=3 )
106 unsigned char BYTE0=bin[byteNo];
107 unsigned char BYTE1=bin[byteNo+1];
108 unsigned char BYTE2=bin[byteNo+2];
109 res[rc++] = b64[ BYTE0 >> 2 ] ;
110 res[rc++] = b64[ ((0x3&BYTE0)<<4) + (BYTE1 >> 4) ] ;
111 res[rc++] = b64[ ((0x0f&BYTE1)<<2) + (BYTE2>>6) ] ;
112 res[rc++] = b64[ 0x3f&BYTE2 ] ;
117 res[rc++] = b64[ bin[byteNo] >> 2 ] ;
118 res[rc++] = b64[ (0x3&bin[byteNo])<<4 ] ;
124 res[rc++] = b64[ bin[byteNo] >> 2 ] ;
125 res[rc++] = b64[ ((0x3&bin[byteNo])<<4) + (bin[byteNo+1] >> 4) ] ;
126 res[rc++] = b64[ (0x0f&bin[byteNo+1])<<2 ] ;
130 res[rc]=0; // NULL TERMINATOR! ;)
134 unsigned char* unbase64( const char* ascii, int len, int *flen )
136 const unsigned char *safeAsciiPtr = (const unsigned char*)ascii ;
142 if( len < 2 ) { // 2 accesses below would be OOB.
143 // catch empty string, return NULL as result.
144 puts( "ERROR: You passed an invalid base64 string (too short). You get NULL back." ) ;
148 if( safeAsciiPtr[ len-1 ]=='=' ) ++pad ;
149 if( safeAsciiPtr[ len-2 ]=='=' ) ++pad ;
151 *flen = 3*len/4 - pad ;
152 bin = (unsigned char*)malloc( *flen ) ;
155 puts( "ERROR: unbase64 could not allocate enough memory." ) ;
156 puts( "I must stop because I could not get enough" ) ;
160 for( charNo=0; charNo <= len - 4 - pad ; charNo+=4 )
162 int A=unb64[safeAsciiPtr[charNo]];
163 int B=unb64[safeAsciiPtr[charNo+1]];
164 int C=unb64[safeAsciiPtr[charNo+2]];
165 int D=unb64[safeAsciiPtr[charNo+3]];
167 bin[cb++] = (A<<2) | (B>>4) ;
168 bin[cb++] = (B<<4) | (C>>2) ;
169 bin[cb++] = (C<<6) | (D) ;
174 int A=unb64[safeAsciiPtr[charNo]];
175 int B=unb64[safeAsciiPtr[charNo+1]];
176 int C=unb64[safeAsciiPtr[charNo+2]];
178 bin[cb++] = (A<<2) | (B>>4) ;
179 bin[cb++] = (B<<4) | (C>>2) ;
183 int A=unb64[safeAsciiPtr[charNo]];
184 int B=unb64[safeAsciiPtr[charNo+1]];
186 bin[cb++] = (A<<2) | (B>>4) ;