small text and comment changes
[rocksndiamonds.git] / src / libgame / base64.c
1 // ============================================================================
2 // Artsoft Retro-Game Library
3 // ----------------------------------------------------------------------------
4 // (c) 1995-2021 by Artsoft Entertainment
5 //                  Holger Schemel
6 //                  info@artsoft.org
7 //                  https://www.artsoft.org/
8 // ----------------------------------------------------------------------------
9 // base64.c
10 // ============================================================================
11
12 /*
13
14   https://github.com/superwills/NibbleAndAHalf
15   base64.h -- Fast base64 encoding and decoding.
16   version 1.0.0, April 17, 2013 143a
17
18   Copyright (C) 2013 William Sherif
19
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.
23
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:
27
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.
35
36   William Sherif
37   will.sherif@gmail.com
38
39   YWxsIHlvdXIgYmFzZSBhcmUgYmVsb25nIHRvIHVz
40
41 */
42
43 // ----------------------------------------------------------------------------
44 // Base64 encoder/decoder code was altered for integration in Rocks'n'Diamonds
45 // ----------------------------------------------------------------------------
46
47 #include <stdio.h>
48 #include <stdlib.h>
49
50 #include "base64.h"
51
52
53 static const char *b64encode =
54   "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
55
56 int base64_encoded_size(int unencoded_size)
57 {
58   int mod = unencoded_size % 3;
59   int pad = (mod > 0 ? 3 - mod : 0);
60
61   return 4 * (unencoded_size + pad) / 3 + 1;
62 }
63
64 void base64_encode(char *encoded_data,
65                    const void *unencoded_ptr, int unencoded_size)
66 {
67   const byte *unencoded_data = (const byte *)unencoded_ptr;
68   char *ptr = encoded_data;
69   int i;
70
71   int mod = unencoded_size % 3;
72   int pad = (mod > 0 ? 3 - mod : 0);
73
74   for (i = 0; i <= unencoded_size - 3; i += 3)
75   {
76     byte byte0 = unencoded_data[i];
77     byte byte1 = unencoded_data[i + 1];
78     byte byte2 = unencoded_data[i + 2];
79
80     *ptr++ = b64encode[byte0 >> 2];
81     *ptr++ = b64encode[((byte0 & 0x03) << 4) + (byte1 >> 4)];
82     *ptr++ = b64encode[((byte1 & 0x0f) << 2) + (byte2 >> 6)];
83     *ptr++ = b64encode[byte2 & 0x3f];
84   }
85
86   if (pad == 1)
87   {
88     byte byte0 = unencoded_data[i];
89     byte byte1 = unencoded_data[i + 1];
90
91     *ptr++ = b64encode[byte0 >> 2];
92     *ptr++ = b64encode[((byte0 & 0x03) << 4) + (byte1 >> 4)];
93     *ptr++ = b64encode[((byte1 & 0x0f) << 2)];
94     *ptr++ = '=';
95   }
96   else if (pad == 2)
97   {
98     byte byte0 = unencoded_data[i];
99
100     *ptr++ = b64encode[byte0 >> 2];
101     *ptr++ = b64encode[(byte0 & 0x03) << 4];
102     *ptr++ = '=';
103     *ptr++ = '=';
104   }
105
106   *ptr++ = '\0';
107 }
108
109 static const byte b64decode[] =
110 {
111    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,       //   0
112    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,       //  16
113    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, 62,  0,  0,  0, 63,       //  32
114   52, 53, 54, 55, 56, 57, 58, 59, 60, 61,  0,  0,  0,  0,  0,  0,       //  48
115
116    0,  0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14,       //  64
117   15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25,  0,  0,  0,  0,  0,       //  80
118    0, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,       //  96
119   41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51,  0,  0,  0,  0,  0,       // 112
120
121    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,       // 128
122    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,       // 144
123    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,       // 160
124    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,       // 176
125
126    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,       // 192
127    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,       // 208
128    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,       // 224
129    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,       // 240
130 };
131
132 int base64_decoded_size(const char *encoded_data)
133 {
134   int encoded_size = strlen(encoded_data);
135
136   if (encoded_size < 2)
137     return 0;
138
139   int pad = 0;
140
141   if (encoded_data[encoded_size - 1] == '=')
142     pad++;
143   if (encoded_data[encoded_size - 2] == '=')
144     pad++;
145
146   return 3 * encoded_size / 4 - pad;
147 }
148
149 void base64_decode(byte *decoded_data, const char *encoded_ptr)
150 {
151   const byte *encoded_data = (const byte *)encoded_ptr;
152   byte *ptr = decoded_data;
153   int encoded_size = strlen(encoded_ptr);
154   int i;
155
156   if (encoded_size < 2)
157     return;
158
159   int pad = 0;
160
161   if (encoded_data[encoded_size - 1] == '=')
162     pad++;
163   if (encoded_data[encoded_size - 2] == '=')
164     pad++;
165
166   for (i = 0; i <= encoded_size - 4 - pad; i += 4)
167   {
168     byte byte0 = b64decode[encoded_data[i]];
169     byte byte1 = b64decode[encoded_data[i + 1]];
170     byte byte2 = b64decode[encoded_data[i + 2]];
171     byte byte3 = b64decode[encoded_data[i + 3]];
172
173     *ptr++ = (byte0 << 2) | (byte1 >> 4);
174     *ptr++ = (byte1 << 4) | (byte2 >> 2);
175     *ptr++ = (byte2 << 6) | (byte3);
176   }
177
178   if (pad == 1)
179   {
180     byte byte0 = b64decode[encoded_data[i]];
181     byte byte1 = b64decode[encoded_data[i + 1]];
182     byte byte2 = b64decode[encoded_data[i + 2]];
183
184     *ptr++ = (byte0 << 2) | (byte1 >> 4);
185     *ptr++ = (byte1 << 4) | (byte2 >> 2);
186   }
187   else if (pad == 2)
188   {
189     byte byte0 = b64decode[encoded_data[i]];
190     byte byte1 = b64decode[encoded_data[i + 1]];
191
192     *ptr++ = (byte0 << 2) | (byte1 >> 4);
193   }
194 }