REDAC HybridController
Firmware for LUCIDAC/REDAC Teensy
Loading...
Searching...
No Matches
etl_base64.h
Go to the documentation of this file.
1// This file comes from ETL 20.38.10 because platformio only has version 20.38.2...
2
3//*************************************************************************
5//*************************************************************************///\file
6
7/******************************************************************************
8The MIT License(MIT)
9Embedded Template Library.
10https://github.com/ETLCPP/etl
11https://www.etlcpp.com
12Copyright(c) 2023 John Wellbelove
13Permission is hereby granted, free of charge, to any person obtaining a copy
14of this software and associated documentation files(the "Software"), to deal
15in the Software without restriction, including without limitation the rights
16to use, copy, modify, merge, publish, distribute, sublicense, and / or sell
17copies of the Software, and to permit persons to whom the Software is
18furnished to do so, subject to the following conditions :
19The above copyright notice and this permission notice shall be included in all
20copies or substantial portions of the Software.
21THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
22IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
23FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE
24AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
25LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
26OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
27SOFTWARE.
28******************************************************************************/
29
30#ifndef ETL_BASE64_INCLUDED
31#define ETL_BASE64_INCLUDED
32
33#include "etl/platform.h"
34#include "etl/span.h"
35#include "etl/static_assert.h"
36#include "etl/error_handler.h"
37#include "etl/exception.h"
38#include "etl/type_traits.h"
39#include "etl/binary.h"
40#include "etl/algorithm.h"
41#include "etl/integral_limits.h"
42#include "etl/iterator.h"
43#include "etl/string.h"
44
45#include <stdint.h>
46
47#if ETL_USING_STL
48 #include <string>
49#endif
50
51namespace etl
52{
53 //***************************************************************************
55 //***************************************************************************
56 class base64_exception : public etl::exception
57 {
58 public:
59
60 base64_exception(string_type reason_, string_type file_name_, numeric_type line_number_)
61 : exception(reason_, file_name_, line_number_)
62 {
63 }
64 };
65
66 //***************************************************************************
68 //***************************************************************************
70 {
71 public:
72
73 base64_overflow(string_type file_name_, numeric_type line_number_)
74 : base64_exception("DONT USE EXCEPTIONS ANYWEAY", file_name_, line_number_)
75 {
76 }
77 };
78
79 //*************************************************************************
81 //*************************************************************************
82 class base64
83 {
84 public:
85
86 //*************************************************************************
88 //*************************************************************************
89 template <typename T>
90 ETL_CONSTEXPR14
91 static
92 typename etl::enable_if<etl::is_integral<T>::value && (etl::integral_limits<T>::bits == 8U), size_t>::type
93 encode(const T* input, size_t input_length, char* output, size_t output_length)
94 {
95 if (input_length == 0U)
96 {
97 return 0;
98 }
99
100 // Figure out if the output buffer is large enough.
101 size_t required_output_length = encode_size(input_length);
102
103 ETL_ASSERT_OR_RETURN_VALUE(output_length >= required_output_length, ETL_ERROR(base64_overflow), 0U);
104
105 const T* p_in = input;
106 const T* p_in_end = input + input_length;
107
108 char* p_out = output;
109 char* p_out_end = output + required_output_length;
110
111 int next_sextet = First_Sextet;
112
113 // Step through the input buffer, creating the output sextets.
114 while (p_in != p_in_end)
115 {
116 T c = *p_in;
117 char index = 0;
118
119 switch (next_sextet)
120 {
121 //**************************
122 case First_Sextet:
123 {
124 index = static_cast<char>((*p_in & b11111100) >> 2);
125 next_sextet = Second_Sextet;
126 break;
127 }
128
129 //**************************
130 case Second_Sextet:
131 {
132 index = static_cast<char>((c & b00000011) << 4);
133 ++p_in;
134
135 // Next byte valid?
136 if (p_in != p_in_end)
137 {
138 index = index | ((*p_in & b11110000) >> 4);
139 }
140 next_sextet = Third_Sextet;
141 break;
142 }
143
144 //**************************
145 case Third_Sextet:
146 {
147 index = (c & b00001111) << 2;
148 ++p_in;
149
150 // Next byte valid?
151 if (p_in != p_in_end)
152 {
153 index = index | static_cast<char>((*p_in & b11000000) >> 6);
154 }
155 next_sextet = Fourth_Sextet;
156 break;
157 }
158
159 //**************************
160 case Fourth_Sextet:
161 {
162 index = static_cast<char>(c & b00111111);
163 ++p_in;
164 next_sextet = First_Sextet;
165 break;
166 }
167
168 //**************************
169 default:
170 {
171 // Should never get here.
172 assert(false);
173 break;
174 }
175 }
176
177 *p_out = get_sextet_from_index(index);
178 ++p_out;
179 }
180
181 // Pad out the end of the output buffer.
182 while (p_out != p_out_end)
183 {
184 *p_out++ = padding();
185 }
186
187 return static_cast<size_t>(etl::distance(output, p_out));
188 }
189
190 //*************************************************************************
192 //*************************************************************************
193 template <typename T>
194 ETL_CONSTEXPR14
195 static
196 typename etl::enable_if<etl::is_integral<T>::value && (etl::integral_limits<T>::bits == 8U), size_t>::type
197 encode(const T* input_begin, const T* input_end, char* output_begin, char* output_end)
198 {
199 return encode(input_begin, static_cast<size_t>(etl::distance(input_begin, input_end)),
200 output_begin, static_cast<size_t>(etl::distance(output_begin, output_end)));
201 }
202
203 //*************************************************************************
205 //*************************************************************************
206 template <typename T, size_t Length1, size_t Length2>
207 ETL_CONSTEXPR14
208 static
209 typename etl::enable_if<etl::is_integral<T>::value && (etl::integral_limits<T>::bits == 8U), size_t>::type
210 encode(const etl::span<const T, Length1>& input_span,
211 const etl::span<char, Length2>& output_span)
212 {
213 return encode(input_span.begin(), input_span.size(),
214 output_span.begin(), output_span.size());
215 }
216
217 //*************************************************************************
219 //*************************************************************************
220 template <typename T>
221 ETL_CONSTEXPR14
222 static
223 typename etl::enable_if<etl::is_integral<T>::value && (etl::integral_limits<T>::bits == 8U), size_t>::type
224 encode(const T* input_begin, size_t input_length,
225 etl::istring& output)
226 {
227 output.resize(etl::base64::encode_size(input_length));
228
229 return encode(input_begin, input_length,
230 output.data(), output.size());
231 }
232
233 //*************************************************************************
235 //*************************************************************************
236 template <typename T>
237 ETL_CONSTEXPR14
238 static
239 typename etl::enable_if<etl::is_integral<T>::value && (etl::integral_limits<T>::bits == 8U), size_t>::type
240 encode(const T* input_begin, const T* input_end,
241 etl::istring& output)
242 {
243 output.resize(etl::base64::encode_size(etl::distance(input_begin, input_end)));
244
245 return encode(input_begin, static_cast<size_t>(etl::distance(input_begin, input_end)),
246 output.data(), output.size());
247 }
248
249 //*************************************************************************
251 //*************************************************************************
252 template <typename T, size_t Length1>
253 ETL_CONSTEXPR14
254 static
255 typename etl::enable_if<etl::is_integral<T>::value && (etl::integral_limits<T>::bits == 8U), size_t>::type
256 encode(const etl::span<const T, Length1>& input_span,
257 etl::istring& output)
258 {
259 output.resize(etl::base64::encode_size(Length1));
260
261 return encode(input_span.begin(), input_span.size(),
262 output.data(), output.size());
263 }
264
265 //*************************************************************************
267 //*************************************************************************
268 ETL_NODISCARD
269 ETL_CONSTEXPR14
270 static
271 size_t encode_size(size_t input_length)
272 {
273 size_t required_output_length = (input_length * 8U) / 6U;
274
275 if ((input_length % 3U) != 0U)
276 {
277 while ((required_output_length % 4U) != 0)
278 {
279 ++required_output_length;
280 }
281 }
282
283 return required_output_length;
284 }
285
286 //*************************************************************************
288 //*************************************************************************
289 template <typename T>
290 ETL_CONSTEXPR14
291 static
292 typename etl::enable_if<etl::is_integral<T>::value && (etl::integral_limits<T>::bits == 8U), size_t>::type
293 decode(const char* input, size_t input_length, T* output, size_t output_length)
294 {
295 if (input_length == 0)
296 {
297 return 0;
298 }
299
300 // Figure out if the output buffer is large enough.
301 size_t required_output_length = etl::base64::decode_size(input, input_length);
302
303 ETL_ASSERT_OR_RETURN_VALUE(output_length >= required_output_length, ETL_ERROR(base64_overflow), 0U);
304
305 const char* p_in = input;
306 const char* p_in_end = input + input_length;
307
308 T* p_out = output;
309
310 T c = 0;
311 int next_sextet = First_Sextet;
312
313 // Step through the input buffer, creating the output binary.
314 while (p_in != p_in_end)
315 {
316 char sextet = *p_in++; // Get the sextet as a T.
317
318 if (sextet == padding())
319 {
320 break;
321 }
322
323 char index = get_index_from_sextet(sextet);
324
325 switch (next_sextet)
326 {
327 //**************************
328 case First_Sextet:
329 {
330 c = (index & b00111111) << 2;
331 next_sextet = Second_Sextet;
332 break;
333 }
334
335 //**************************
336 case Second_Sextet:
337 {
338 c |= (index & b00110000) >> 4;
339 *p_out++ = static_cast<T>(c);
340 c = (index & b00001111) << 4;
341 next_sextet = Third_Sextet;
342 break;
343 }
344
345 //**************************
346 case Third_Sextet:
347 {
348 c |= (index & b00111100) >> 2;
349 *p_out++ = static_cast<T>(c);
350 c = (index & b00000011) << 6;
351 next_sextet = Fourth_Sextet;
352 break;
353 }
354
355 //**************************
356 case Fourth_Sextet:
357 {
358 c |= (index & b00111111);
359 *p_out++ = static_cast<T>(c);
360 next_sextet = First_Sextet;
361 break;
362 }
363
364 //**************************
365 default:
366 {
367 // Should never get here.
368 assert(false);
369 break;
370 }
371 }
372 }
373
374 return static_cast<size_t>(etl::distance(output, p_out));
375 }
376
377 //*************************************************************************
379 //*************************************************************************
380 template <typename T>
381 ETL_CONSTEXPR14
382 static
383 typename etl::enable_if<etl::is_integral<T>::value && (etl::integral_limits<T>::bits == 8U), size_t>::type
384 decode(const char* input_begin, const char* input_end, T* output_begin, T* output_end)
385 {
386 return decode(input_begin, static_cast<size_t>(etl::distance(input_begin, input_end)),
387 output_begin, static_cast<size_t>(etl::distance(output_begin, output_end)));
388 }
389
390 //*************************************************************************
392 //*************************************************************************
393 template <typename T, size_t Length1, size_t Length2>
394 ETL_CONSTEXPR14
395 static
396 typename etl::enable_if<etl::is_integral<T>::value && (etl::integral_limits<T>::bits == 8U), size_t>::type
397 decode(const etl::span<const char, Length1>& input_span,
398 const etl::span<T, Length2>& output_span)
399 {
400 return decode(input_span.begin(), input_span.size(),
401 output_span.begin(), output_span.size());
402 }
403
404 //*************************************************************************
406 //*************************************************************************
407 ETL_NODISCARD
408 ETL_CONSTEXPR14
409 static size_t decode_size(const char* input, size_t input_length)
410 {
411 if (input_length == 0U)
412 {
413 return 0U;
414 }
415
416 // Figure out the minimum output buffer size.
417 size_t length = static_cast<size_t>(etl::distance(input, etl::find(input, input + input_length, padding())) - 1);
418 size_t required_output_length = length - (length / 4U);
419
420 return required_output_length;
421 }
422
423 private:
424
425 //*************************************************************************
427 enum
428 {
429 First_Sextet,
430 Second_Sextet,
431 Third_Sextet,
432 Fourth_Sextet
433 };
434
435 // Sextets
436 // 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H',
437 // 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P',
438 // 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X',
439 // 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f',
440 // 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n',
441 // 'o', 'p', 'q', 'r', 's', 't', 'u', 'v',
442 // 'w', 'x', 'y', 'z', '0', '1', '2', '3',
443 // '4', '5', '6', '7', '8', '9', '+', '/'
444
445 //*************************************************************************
446 // Translates an index into a sextet
447 //*************************************************************************
448 ETL_CONSTEXPR14 static char get_sextet_from_index(char index)
449 {
450 if ((index >= 0) && (index < 26))
451 {
452 return 'A' + index;
453 }
454 else if ((index >= 26) && (index < 52))
455 {
456 index -= 26;
457 return 'a' + index;
458 }
459 else if ((index >= 52) && (index < 62))
460 {
461 index -= 52;
462 return '0' + index;
463 }
464 else if (index == 62)
465 {
466 return '+';
467 }
468 else if (index == 63)
469 {
470 return '/';
471 }
472 else
473 {
474 // Should never get here.
475 assert(false);
476 return padding();
477 }
478 }
479
480 //*************************************************************************
481 // Translates a sextet into an index
482 //*************************************************************************
483 ETL_CONSTEXPR14 static char get_index_from_sextet(char sextet)
484 {
485 if ((sextet >= 'A') && (sextet <= 'Z'))
486 {
487 return sextet - 'A';
488 }
489 else if ((sextet >= 'a') && (sextet <= 'z'))
490 {
491 return sextet - 'a' + 26;
492 }
493 else if ((sextet >= '0') && (sextet <= '9'))
494 {
495 return sextet - '0' + 52;
496 }
497 else if (sextet == '+')
498 {
499 return 62;
500 }
501 else if (sextet == '/')
502 {
503 return 63;
504 }
505 else
506 {
507 // Should never get here.
508 assert(false);
509 return 0;
510 }
511 }
512
513 //*************************************************************************
515 //*************************************************************************
516 ETL_NODISCARD
517 ETL_CONSTEXPR14
518 static char padding()
519 {
520 return '=';
521 }
522 };
523}
524
525#endif
Exception base for base64.
Definition etl_base64.h:57
base64_exception(string_type reason_, string_type file_name_, numeric_type line_number_)
Definition etl_base64.h:60
Memory misalignment exception.
Definition etl_base64.h:70
base64_overflow(string_type file_name_, numeric_type line_number_)
Definition etl_base64.h:73
Codec for Base64.
Definition etl_base64.h:83
static ETL_CONSTEXPR14 etl::enable_if< etl::is_integral< T >::value &&(etl::integral_limits< T >::bits==8U), size_t >::type encode(const T *input, size_t input_length, char *output, size_t output_length)
Encode to Base64 from and to pointer/length.
Definition etl_base64.h:93
static ETL_CONSTEXPR14 etl::enable_if< etl::is_integral< T >::value &&(etl::integral_limits< T >::bits==8U), size_t >::type decode(const char *input, size_t input_length, T *output, size_t output_length)
Decode from Base64 from and to pointer/length.
Definition etl_base64.h:293
static ETL_CONSTEXPR14 etl::enable_if< etl::is_integral< T >::value &&(etl::integral_limits< T >::bits==8U), size_t >::type encode(const etl::span< const T, Length1 > &input_span, const etl::span< char, Length2 > &output_span)
Encode to Base64 from and to span/span.
Definition etl_base64.h:210
static ETL_CONSTEXPR14 etl::enable_if< etl::is_integral< T >::value &&(etl::integral_limits< T >::bits==8U), size_t >::type decode(const char *input_begin, const char *input_end, T *output_begin, T *output_end)
Decode from Base64 from and to pointer/pointer.
Definition etl_base64.h:384
static ETL_CONSTEXPR14 etl::enable_if< etl::is_integral< T >::value &&(etl::integral_limits< T >::bits==8U), size_t >::type encode(const T *input_begin, const T *input_end, char *output_begin, char *output_end)
Encode to Base64 from and to pointer/pointer.
Definition etl_base64.h:197
static ETL_CONSTEXPR14 etl::enable_if< etl::is_integral< T >::value &&(etl::integral_limits< T >::bits==8U), size_t >::type decode(const etl::span< const char, Length1 > &input_span, const etl::span< T, Length2 > &output_span)
Decode from Base64 from and to span/span.
Definition etl_base64.h:397
ETL_NODISCARD static ETL_CONSTEXPR14 size_t encode_size(size_t input_length)
Calculates the buffer size required to encode to Base64.
Definition etl_base64.h:271
static ETL_CONSTEXPR14 etl::enable_if< etl::is_integral< T >::value &&(etl::integral_limits< T >::bits==8U), size_t >::type encode(const T *input_begin, size_t input_length, etl::istring &output)
Encode to Base64 from pointer/length to etl::istring.
Definition etl_base64.h:224
static ETL_CONSTEXPR14 etl::enable_if< etl::is_integral< T >::value &&(etl::integral_limits< T >::bits==8U), size_t >::type encode(const T *input_begin, const T *input_end, etl::istring &output)
Encode to Base64 from pointer/pointer to etl::istring.
Definition etl_base64.h:240
static ETL_CONSTEXPR14 etl::enable_if< etl::is_integral< T >::value &&(etl::integral_limits< T >::bits==8U), size_t >::type encode(const etl::span< const T, Length1 > &input_span, etl::istring &output)
Encode to Base64 from span to etl::istring.
Definition etl_base64.h:256
ETL_NODISCARD static ETL_CONSTEXPR14 size_t decode_size(const char *input, size_t input_length)
Calculates the buffer size required to decode from Base64.
Definition etl_base64.h:409
Decode from Base64 from and to pointer/length.
Definition etl_base64.h:52
FLASHMEM void index(awot::Request &req, awot::Response &res)
Definition server.cpp:120