GCC Code Coverage Report


Directory: src/gate/
File: src/gate/encode/base64.c
Date: 2025-09-14 13:10:38
Exec Total Coverage
Lines: 147 194 75.8%
Functions: 10 11 90.9%
Branches: 55 94 58.5%

Line Branch Exec Source
1 /* GATE PROJECT LICENSE:
2 +----------------------------------------------------------------------------+
3 | Copyright(c) 2018-2025, Stefan Meislinger <sm@opengate.at> |
4 | All rights reserved. |
5 | |
6 | Redistribution and use in source and binary forms, with or without |
7 | modification, are permitted provided that the following conditions are met:|
8 | |
9 | 1. Redistributions of source code must retain the above copyright notice, |
10 | this list of conditions and the following disclaimer. |
11 | 2. Redistributions in binary form must reproduce the above copyright |
12 | notice, this list of conditions and the following disclaimer in the |
13 | documentation and/or other materials provided with the distribution. |
14 | |
15 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"|
16 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
17 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
18 | ARE DISCLAIMED.IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE |
19 | LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
20 | CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
21 | SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
22 | INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
23 | CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
24 | ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF |
25 | THE POSSIBILITY OF SUCH DAMAGE. |
26 +----------------------------------------------------------------------------+
27 */
28
29 #include "gate/encode/base64.h"
30 #include "gate/strings.h"
31 #include "gate/results.h"
32
33 static char const* const base64_chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
34 static char const base64_nullchar = '=';
35
36 27 void gate_base64_enc3(char const* inputTriple, char* outputQuad)
37 {
38 27 outputQuad[0] = base64_chars[((gate_uint8_t)inputTriple[0] >> 2) & 0x3f];
39 27 outputQuad[1] = base64_chars[(((gate_uint8_t)inputTriple[0] & 0x03) << 4) | (((gate_uint8_t)inputTriple[1] >> 4) & 0x0f)];
40 27 outputQuad[2] = base64_chars[(((gate_uint8_t)inputTriple[1] & 0x0f) << 2) | (((gate_uint8_t)inputTriple[2] >> 6) & 0x03)];
41 27 outputQuad[3] = base64_chars[(gate_uint8_t)inputTriple[2] & 0x3f];
42 27 }
43
44 3 void gate_base64_enc2(char const* inputTuple, char* outputQuad)
45 {
46 3 outputQuad[0] = base64_chars[((gate_uint8_t)inputTuple[0] >> 2) & 0x3f];
47 3 outputQuad[1] = base64_chars[(((gate_uint8_t)inputTuple[0] & 0x03) << 4) | (((gate_uint8_t)inputTuple[1] >> 4) & 0x0f)];
48 3 outputQuad[2] = base64_chars[((gate_uint8_t)inputTuple[1] & 0x0f) << 2];
49 3 outputQuad[3] = base64_nullchar;
50 3 }
51
52 void gate_base64_enc1(char const* inputByte, char* outputQuad)
53 {
54 outputQuad[0] = base64_chars[((gate_uint8_t)inputByte[0] >> 2) & 0x3f];
55 outputQuad[1] = base64_chars[((gate_uint8_t)inputByte[0] & 0x3) << 4];
56 outputQuad[2] = base64_nullchar;
57 outputQuad[3] = base64_nullchar;
58 }
59
60 30 gate_size_t gate_base64_dec(char const* inputQuad, char* outputTriple)
61 {
62 30 gate_size_t pos1 = gate_str_char_pos(base64_chars, 64, inputQuad[0], 0);
63 30 gate_size_t pos2 = gate_str_char_pos(base64_chars, 64, inputQuad[1], 0);
64 30 gate_size_t pos3 = gate_str_char_pos(base64_chars, 64, inputQuad[2], 0);
65 30 gate_size_t pos4 = gate_str_char_pos(base64_chars, 64, inputQuad[3], 0);
66 30 gate_size_t ret = 0;
67 30 gate_uint32_t quad = 0;
68
69 do
70 {
71
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 30 times.
30 if (pos1 == GATE_STR_NPOS)
72 {
73 break;
74 }
75 30 quad |= (gate_uint32_t)pos1 << 18;
76
77
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 30 times.
30 if (pos2 == GATE_STR_NPOS)
78 {
79 break;
80 }
81 30 quad |= (gate_uint32_t)pos2 << 12;
82 30 outputTriple[0] = (char)(gate_uint8_t)((quad >> 16) & 0xff);
83 30 ++ret;
84
85
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 30 times.
30 if (pos3 == GATE_STR_NPOS)
86 {
87 break;
88 }
89 30 quad |= (gate_uint32_t)pos3 << 6;
90 30 outputTriple[1] = (char)(gate_uint8_t)((quad >> 8) & 0xff);
91 30 ++ret;
92
93
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 27 times.
30 if (pos4 == GATE_STR_NPOS)
94 {
95 3 break;
96 }
97 27 quad |= (gate_uint32_t)pos4;
98 27 outputTriple[2] = (char)(gate_uint8_t)(quad & 0xff);
99 27 ++ret;
100
101 } while (0);
102
103 30 return ret;
104 }
105
106
107 1 gate_result_t gate_base64_encode(gate_string_t const* src, gate_strbuilder_t* dst)
108 {
109 1 gate_result_t ret = GATE_RESULT_OK;
110 1 char const* ptr = src->str;
111 1 gate_size_t len = src->length;
112 char buffer[4];
113
114
2/2
✓ Branch 0 taken 9 times.
✓ Branch 1 taken 1 times.
10 while (len >= 3)
115 {
116 9 gate_base64_enc3(ptr, buffer);
117
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 9 times.
9 if (4 != gate_strbuilder_append_text(dst, buffer, 4))
118 {
119 ret = GATE_RESULT_OUTOFMEMORY;
120 break;
121 }
122 9 len -= 3;
123 9 ptr += 3;
124 }
125
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if (GATE_SUCCEEDED(ret))
126 {
127
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (len == 1)
128 {
129 gate_base64_enc1(ptr, buffer);
130 if (4 != gate_strbuilder_append_text(dst, buffer, 4))
131 {
132 ret = GATE_RESULT_OUTOFMEMORY;
133 }
134 }
135
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if (len == 2)
136 {
137 1 gate_base64_enc2(ptr, buffer);
138
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
1 if (4 != gate_strbuilder_append_text(dst, buffer, 4))
139 {
140 ret = GATE_RESULT_OUTOFMEMORY;
141 }
142 }
143 }
144
145 1 return ret;
146 }
147 2 gate_result_t gate_base64_encode_stream(gate_stream_t* src, gate_stream_t* dst)
148 {
149 gate_result_t ret;
150 char srcbuffer[GATE_MAX_COPYBUFFER_LENGTH * 3 / 4];
151 char dstbuffer[GATE_MAX_COPYBUFFER_LENGTH];
152 gate_size_t returned;
153 gate_size_t converted;
154 gate_size_t written;
155 char const* ptrsrc;
156 char* ptrdst;
157
158 for (;;)
159 {
160 2 ret = gate_stream_read_block(src, srcbuffer, sizeof(srcbuffer), &returned);
161
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (GATE_FAILED(ret))
162 {
163 break;
164 }
165
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1 times.
2 if (returned == 0)
166 {
167 1 break;
168 }
169 1 ptrsrc = srcbuffer;
170 1 ptrdst = dstbuffer;
171 1 converted = 0;
172
2/2
✓ Branch 0 taken 9 times.
✓ Branch 1 taken 1 times.
10 while (returned >= 3)
173 {
174 9 gate_base64_enc3(ptrsrc, ptrdst);
175 9 ptrsrc += 3;
176 9 returned -= 3;
177 9 ptrdst += 4;
178 9 converted += 4;
179 }
180
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (returned == 1)
181 {
182 gate_base64_enc1(ptrsrc, ptrdst);
183 converted += 4;
184 }
185
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if (returned == 2)
186 {
187 1 gate_base64_enc2(ptrsrc, ptrdst);
188 1 converted += 4;
189 }
190
191 1 ret = gate_stream_write_block(dst, dstbuffer, converted, &written);
192
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (GATE_FAILED(ret))
193 {
194 break;
195 }
196 }
197
198 1 return ret;
199 }
200
201 1 gate_result_t gate_base64_encode_buffer(char const* src, gate_size_t srclength, char* dst, gate_size_t* dstlength)
202 {
203 gate_result_t ret;
204 1 gate_size_t b64length = (srclength / 3) * 4;
205 1 char const* ptrsrc = src;
206 1 char* ptrdst = dst;
207
208 do
209 {
210
2/4
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 1 times.
1 if ((srclength == 0) || (dstlength == NULL))
211 {
212 ret = GATE_RESULT_INVALIDARG;
213 break;
214 }
215
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if ((srclength % 3) != 0)
216 {
217 1 b64length += 4;
218 }
219
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (*dstlength < b64length)
220 {
221 ret = GATE_RESULT_BUFFERTOOSMALL;
222 *dstlength = b64length;
223 break;
224 }
225 1 *dstlength = b64length;
226
2/4
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 1 times.
1 if ((src == NULL) || (dst == NULL))
227 {
228 ret = GATE_RESULT_INVALIDARG;
229 break;
230 }
231
232
2/2
✓ Branch 0 taken 9 times.
✓ Branch 1 taken 1 times.
10 while (srclength >= 3)
233 {
234 9 gate_base64_enc3(ptrsrc, ptrdst);
235 9 ptrsrc += 3;
236 9 srclength -= 3;
237 9 ptrdst += 4;
238 }
239
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (srclength == 1)
240 {
241 gate_base64_enc1(ptrsrc, ptrdst);
242 }
243
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 else if (srclength == 2)
244 {
245 1 gate_base64_enc2(ptrsrc, ptrdst);
246 }
247 1 ret = GATE_RESULT_OK;
248 } while (0);
249
250 1 return ret;
251 }
252
253
254 1 static gate_size_t gate_base64_decode_block(char const* src, gate_size_t srclength, char* dst, gate_size_t dstlength)
255 {
256 1 gate_size_t ret = 0;
257 gate_size_t tmp;
258
259
3/4
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 10 times.
✗ Branch 3 not taken.
11 while ((srclength >= 4) && (dstlength >= 3))
260 {
261 10 tmp = gate_base64_dec(src, dst);
262
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 10 times.
10 if (tmp == 0)
263 {
264 break;
265 }
266 10 ret += tmp;
267 10 src += 4;
268 10 srclength -= 4;
269 10 dst += tmp;
270 10 dstlength -= tmp;
271 }
272
273 1 return ret;
274 }
275
276 1 gate_result_t gate_base64_decode(gate_string_t const* src, gate_strbuilder_t* dst)
277 {
278 gate_result_t ret;
279 1 char const* ptrsrc = src->str;
280 1 gate_size_t length = src->length;
281 gate_size_t declength;
282 char buffer[3];
283
284
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if ((length % 4) != 0)
285 {
286 ret = GATE_RESULT_INVALIDINPUT;
287 }
288 else
289 {
290 1 ret = GATE_RESULT_OK;
291
1/2
✓ Branch 0 taken 10 times.
✗ Branch 1 not taken.
10 while (length != 0)
292 {
293 10 declength = gate_base64_dec(ptrsrc, buffer);
294
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 10 times.
10 if (declength == 0)
295 {
296 ret = GATE_RESULT_INVALIDINPUT;
297 break;
298 }
299 10 length -= 4;
300 10 ptrsrc += 4;
301
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 10 times.
10 if (declength != gate_strbuilder_append_text(dst, buffer, declength))
302 {
303 ret = GATE_RESULT_OUTOFMEMORY;
304 break;
305 }
306
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 9 times.
10 if (declength < 3)
307 {
308 1 break;
309 }
310 }
311 }
312
313 1 return ret;
314 }
315 1 gate_result_t gate_base64_decode_stream(gate_stream_t* src, gate_stream_t* dst)
316 {
317 1 gate_result_t ret = GATE_RESULT_OK;
318 char srcbuffer[GATE_MAX_COPYBUFFER_LENGTH];
319 char dstbuffer[GATE_MAX_COPYBUFFER_LENGTH * 3 / 4];
320 gate_size_t returned;
321 gate_size_t converted;
322 gate_size_t written;
323
324
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 while (GATE_SUCCEEDED(ret))
325 {
326 2 ret = gate_stream_read_block(src, srcbuffer, sizeof(srcbuffer), &returned);
327
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (GATE_FAILED(ret))
328 {
329 break;
330 }
331
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1 times.
2 if (returned == 0)
332 {
333 1 break;
334 }
335
336 1 converted = gate_base64_decode_block(srcbuffer, returned, dstbuffer, sizeof(dstbuffer));
337
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (converted == 0)
338 {
339 ret = GATE_RESULT_INVALIDINPUT;
340 break;
341 }
342
343 1 ret = gate_stream_write_block(dst, dstbuffer, converted, &written);
344
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (GATE_FAILED(ret))
345 {
346 break;
347 }
348 }
349
350 1 return ret;
351 }
352
353 1 gate_result_t gate_base64_decode_buffer(char const* src, gate_size_t srclength, char* dst, gate_size_t* dstlength)
354 {
355 gate_result_t ret;
356 gate_size_t outlength;
357 gate_size_t lendecoded;
358 1 char const* ptrsrc = src;
359 1 char* ptrdst = dst;
360
361 do
362 {
363
2/4
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 1 times.
1 if ((srclength == 0) || (dstlength == NULL))
364 {
365 ret = GATE_RESULT_INVALIDARG;
366 break;
367 }
368
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if ((srclength % 4) != 0)
369 {
370 srclength -= (srclength % 4);
371 }
372 1 outlength = (srclength / 4) * 3;
373
374
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (*dstlength < outlength)
375 {
376 ret = GATE_RESULT_BUFFERTOOSMALL;
377 *dstlength = outlength;
378 break;
379 }
380
2/4
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 1 times.
1 if ((src == NULL) || (dst == NULL))
381 {
382 ret = GATE_RESULT_INVALIDARG;
383 break;
384 }
385
386 1 ret = GATE_RESULT_OK;
387 1 outlength = 0;
388
2/2
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 1 times.
11 while (srclength >= 4)
389 {
390 10 lendecoded = gate_base64_dec(ptrsrc, ptrdst);
391
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 10 times.
10 if (lendecoded == 0)
392 {
393 ret = GATE_RESULT_INVALIDINPUT;
394 break;
395 }
396 10 ptrsrc += 4;
397 10 srclength -= 4;
398 10 ptrdst += lendecoded;
399 10 outlength += lendecoded;
400 }
401 1 *dstlength = outlength;
402 } while (0);
403
404 1 return ret;
405 }
406