GCC Code Coverage Report


Directory: src/gate/
File: src/gate/encode/base64.c
Date: 2025-12-12 23:40:09
Exec Total Coverage
Lines: 151 197 76.6%
Functions: 10 11 90.9%
Branches: 57 98 58.2%

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 #include "gate/debugging.h"
33
34 static char const* const base64_chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
35 static char const base64_nullchar = '=';
36
37 27 void gate_base64_enc3(char const* inputTriple, char* outputQuad)
38 {
39 27 outputQuad[0] = base64_chars[((gate_uint8_t)inputTriple[0] >> 2) & 0x3f];
40 27 outputQuad[1] = base64_chars[(((gate_uint8_t)inputTriple[0] & 0x03) << 4) | (((gate_uint8_t)inputTriple[1] >> 4) & 0x0f)];
41 27 outputQuad[2] = base64_chars[(((gate_uint8_t)inputTriple[1] & 0x0f) << 2) | (((gate_uint8_t)inputTriple[2] >> 6) & 0x03)];
42 27 outputQuad[3] = base64_chars[(gate_uint8_t)inputTriple[2] & 0x3f];
43 27 }
44
45 3 void gate_base64_enc2(char const* inputTuple, char* outputQuad)
46 {
47 3 outputQuad[0] = base64_chars[((gate_uint8_t)inputTuple[0] >> 2) & 0x3f];
48 3 outputQuad[1] = base64_chars[(((gate_uint8_t)inputTuple[0] & 0x03) << 4) | (((gate_uint8_t)inputTuple[1] >> 4) & 0x0f)];
49 3 outputQuad[2] = base64_chars[((gate_uint8_t)inputTuple[1] & 0x0f) << 2];
50 3 outputQuad[3] = base64_nullchar;
51 3 }
52
53 void gate_base64_enc1(char const* inputByte, char* outputQuad)
54 {
55 outputQuad[0] = base64_chars[((gate_uint8_t)inputByte[0] >> 2) & 0x3f];
56 outputQuad[1] = base64_chars[((gate_uint8_t)inputByte[0] & 0x3) << 4];
57 outputQuad[2] = base64_nullchar;
58 outputQuad[3] = base64_nullchar;
59 }
60
61 30 gate_size_t gate_base64_dec(char const* inputQuad, char* outputTriple)
62 {
63 30 gate_size_t pos1 = gate_str_char_pos(base64_chars, 64, inputQuad[0], 0);
64 30 gate_size_t pos2 = gate_str_char_pos(base64_chars, 64, inputQuad[1], 0);
65 30 gate_size_t pos3 = gate_str_char_pos(base64_chars, 64, inputQuad[2], 0);
66 30 gate_size_t pos4 = gate_str_char_pos(base64_chars, 64, inputQuad[3], 0);
67 30 gate_size_t ret = 0;
68 30 gate_uint32_t quad = 0;
69
70 do
71 {
72
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 30 times.
30 if (pos1 == GATE_STR_NPOS)
73 {
74 break;
75 }
76 30 quad |= (gate_uint32_t)pos1 << 18;
77
78
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 30 times.
30 if (pos2 == GATE_STR_NPOS)
79 {
80 break;
81 }
82 30 quad |= (gate_uint32_t)pos2 << 12;
83 30 outputTriple[0] = (char)(gate_uint8_t)((quad >> 16) & 0xff);
84 30 ++ret;
85
86
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 30 times.
30 if (pos3 == GATE_STR_NPOS)
87 {
88 break;
89 }
90 30 quad |= (gate_uint32_t)pos3 << 6;
91 30 outputTriple[1] = (char)(gate_uint8_t)((quad >> 8) & 0xff);
92 30 ++ret;
93
94
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 27 times.
30 if (pos4 == GATE_STR_NPOS)
95 {
96 3 break;
97 }
98 27 quad |= (gate_uint32_t)pos4;
99 27 outputTriple[2] = (char)(gate_uint8_t)(quad & 0xff);
100 27 ++ret;
101
102 } while (0);
103
104 30 return ret;
105 }
106
107
108 1 gate_result_t gate_base64_encode(gate_string_t const* src, gate_strbuilder_t* dst)
109 {
110 1 gate_result_t ret = GATE_RESULT_OK;
111 1 char const* ptr = src->str;
112 1 gate_size_t len = src->length;
113 char buffer[4];
114
115
2/2
✓ Branch 0 taken 9 times.
✓ Branch 1 taken 1 times.
10 while (len >= 3)
116 {
117 9 gate_base64_enc3(ptr, buffer);
118
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 9 times.
9 if (4 != gate_strbuilder_append_text(dst, buffer, 4))
119 {
120 ret = GATE_RESULT_OUTOFMEMORY;
121 break;
122 }
123 9 len -= 3;
124 9 ptr += 3;
125 }
126
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if (GATE_SUCCEEDED(ret))
127 {
128
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (len == 1)
129 {
130 gate_base64_enc1(ptr, buffer);
131 if (4 != gate_strbuilder_append_text(dst, buffer, 4))
132 {
133 ret = GATE_RESULT_OUTOFMEMORY;
134 }
135 }
136
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if (len == 2)
137 {
138 1 gate_base64_enc2(ptr, buffer);
139
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
1 if (4 != gate_strbuilder_append_text(dst, buffer, 4))
140 {
141 ret = GATE_RESULT_OUTOFMEMORY;
142 }
143 }
144 }
145
146 1 return ret;
147 }
148 2 gate_result_t gate_base64_encode_stream(gate_stream_t* src, gate_stream_t* dst)
149 {
150 gate_result_t ret;
151 char srcbuffer[GATE_MAX_COPYBUFFER_LENGTH * 3 / 4];
152 char dstbuffer[GATE_MAX_COPYBUFFER_LENGTH];
153 gate_size_t returned;
154 gate_size_t converted;
155 gate_size_t written;
156
157 for (;;)
158 1 {
159 2 char const* ptrsrc = srcbuffer;
160 2 char* ptrdst = dstbuffer;
161 2 ret = gate_stream_read_block(src, srcbuffer, sizeof(srcbuffer), &returned);
162
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (GATE_FAILED(ret))
163 {
164 break;
165 }
166
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1 times.
2 if (returned == 0)
167 {
168 1 break;
169 }
170 1 converted = 0;
171
2/2
✓ Branch 0 taken 9 times.
✓ Branch 1 taken 1 times.
10 while (returned >= 3)
172 {
173 9 gate_base64_enc3(ptrsrc, ptrdst);
174 9 ptrsrc += 3;
175 9 returned -= 3;
176 9 ptrdst += 4;
177 9 converted += 4;
178 }
179
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (returned == 1)
180 {
181 gate_base64_enc1(ptrsrc, ptrdst);
182 converted += 4;
183 }
184
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if (returned == 2)
185 {
186 1 gate_base64_enc2(ptrsrc, ptrdst);
187 1 converted += 4;
188 }
189
190 1 ret = gate_stream_write_block(dst, dstbuffer, converted, &written);
191
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (GATE_FAILED(ret))
192 {
193 break;
194 }
195 }
196
197 1 return ret;
198 }
199
200 1 gate_result_t gate_base64_encode_buffer(char const* src, gate_size_t srclength, char* dst, gate_size_t* dstlength)
201 {
202 gate_result_t ret;
203 1 gate_size_t b64length = (srclength / 3) * 4;
204 1 char const* ptrsrc = src;
205 1 char* ptrdst = dst;
206
207 do
208 {
209
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))
210 {
211 ret = GATE_RESULT_INVALIDARG;
212 break;
213 }
214
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if ((srclength % 3) != 0)
215 {
216 1 b64length += 4;
217 }
218
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (*dstlength < b64length)
219 {
220 ret = GATE_RESULT_BUFFERTOOSMALL;
221 *dstlength = b64length;
222 break;
223 }
224 1 *dstlength = b64length;
225
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))
226 {
227 ret = GATE_RESULT_INVALIDARG;
228 break;
229 }
230
231
2/2
✓ Branch 0 taken 9 times.
✓ Branch 1 taken 1 times.
10 while (srclength >= 3)
232 {
233 9 gate_base64_enc3(ptrsrc, ptrdst);
234 9 ptrsrc += 3;
235 9 srclength -= 3;
236 9 ptrdst += 4;
237 }
238
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (srclength == 1)
239 {
240 gate_base64_enc1(ptrsrc, ptrdst);
241 }
242
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 else if (srclength == 2)
243 {
244 1 gate_base64_enc2(ptrsrc, ptrdst);
245 }
246 1 ret = GATE_RESULT_OK;
247 } while (0);
248
249 1 return ret;
250 }
251
252
253 1 static gate_size_t gate_base64_decode_block(char const* src, gate_size_t srclength, char* dst, gate_size_t dstlength)
254 {
255 1 gate_size_t ret = 0;
256 gate_size_t tmp;
257
258
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))
259 {
260 10 tmp = gate_base64_dec(src, dst);
261
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 10 times.
10 if (tmp == 0)
262 {
263 break;
264 }
265 10 ret += tmp;
266 10 src += 4;
267 10 srclength -= 4;
268 10 dst += tmp;
269 10 dstlength -= tmp;
270 }
271
272 1 return ret;
273 }
274
275 1 gate_result_t gate_base64_decode(gate_string_t const* src, gate_strbuilder_t* dst)
276 {
277 gate_result_t ret;
278 char const* ptrsrc;
279 gate_size_t length;
280
281
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 GATE_DEBUG_ASSERT(src != NULL);
282
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 GATE_DEBUG_ASSERT(dst != NULL);
283
284 1 ptrsrc = src->str;
285 1 length = src->length;
286
287
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if ((length % 4) != 0)
288 {
289 ret = GATE_RESULT_INVALIDINPUT;
290 }
291 else
292 {
293 1 ret = GATE_RESULT_OK;
294
1/2
✓ Branch 0 taken 10 times.
✗ Branch 1 not taken.
10 while (length != 0)
295 {
296 char buffer[3];
297 10 gate_size_t declength = gate_base64_dec(ptrsrc, buffer);
298
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 10 times.
10 if (declength == 0)
299 {
300 ret = GATE_RESULT_INVALIDINPUT;
301 1 break;
302 }
303 10 length -= 4;
304 10 ptrsrc += 4;
305
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 10 times.
10 if (declength != gate_strbuilder_append_text(dst, buffer, declength))
306 {
307 ret = GATE_RESULT_OUTOFMEMORY;
308 break;
309 }
310
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 9 times.
10 if (declength < 3)
311 {
312 1 break;
313 }
314 }
315 }
316
317 1 return ret;
318 }
319 1 gate_result_t gate_base64_decode_stream(gate_stream_t* src, gate_stream_t* dst)
320 {
321 1 gate_result_t ret = GATE_RESULT_OK;
322 char srcbuffer[GATE_MAX_COPYBUFFER_LENGTH];
323 char dstbuffer[GATE_MAX_COPYBUFFER_LENGTH * 3 / 4];
324 gate_size_t returned;
325 gate_size_t converted;
326 gate_size_t written;
327
328
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 while (GATE_SUCCEEDED(ret))
329 {
330 2 ret = gate_stream_read_block(src, srcbuffer, sizeof(srcbuffer), &returned);
331
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (GATE_FAILED(ret))
332 {
333 break;
334 }
335
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1 times.
2 if (returned == 0)
336 {
337 1 break;
338 }
339
340 1 converted = gate_base64_decode_block(srcbuffer, returned, dstbuffer, sizeof(dstbuffer));
341
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (converted == 0)
342 {
343 ret = GATE_RESULT_INVALIDINPUT;
344 break;
345 }
346
347 1 ret = gate_stream_write_block(dst, dstbuffer, converted, &written);
348
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (GATE_FAILED(ret))
349 {
350 break;
351 }
352 }
353
354 1 return ret;
355 }
356
357 1 gate_result_t gate_base64_decode_buffer(char const* src, gate_size_t srclength, char* dst, gate_size_t* dstlength)
358 {
359 gate_result_t ret;
360 gate_size_t outlength;
361 gate_size_t lendecoded;
362 1 char const* ptrsrc = src;
363 1 char* ptrdst = dst;
364
365 do
366 {
367
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))
368 {
369 ret = GATE_RESULT_INVALIDARG;
370 break;
371 }
372
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if ((srclength % 4) != 0)
373 {
374 srclength -= (srclength % 4);
375 }
376 1 outlength = (srclength / 4) * 3;
377
378
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (*dstlength < outlength)
379 {
380 ret = GATE_RESULT_BUFFERTOOSMALL;
381 *dstlength = outlength;
382 break;
383 }
384
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))
385 {
386 ret = GATE_RESULT_INVALIDARG;
387 break;
388 }
389
390 1 ret = GATE_RESULT_OK;
391 1 outlength = 0;
392
2/2
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 1 times.
11 while (srclength >= 4)
393 {
394 10 lendecoded = gate_base64_dec(ptrsrc, ptrdst);
395
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 10 times.
10 if (lendecoded == 0)
396 {
397 ret = GATE_RESULT_INVALIDINPUT;
398 break;
399 }
400 10 ptrsrc += 4;
401 10 srclength -= 4;
402 10 ptrdst += lendecoded;
403 10 outlength += lendecoded;
404 }
405 1 *dstlength = outlength;
406 } while (0);
407
408 1 return ret;
409 }
410