stdex
Additional custom or not Standard C++ covered algorithms
Loading...
Searching...
No Matches
base64.h
1/*
2 SPDX-License-Identifier: MIT
3 Copyright © 2016-2022 Amebis
4*/
5
6#pragma once
7
8#include "sal.h"
9#include <string>
10#include <vector>
11
12
13namespace stdex
14{
19 {
20 public:
24 base64_enc() noexcept : num(0)
25 {
26 buf[0] = 0;
27 buf[1] = 0;
28 buf[2] = 0;
29 }
30
31
40 template<class _Elem, class _Traits, class _Ax>
41 void encode(_Inout_ std::basic_string<_Elem, _Traits, _Ax> &out, _In_bytecount_(size) const void *data, _In_ size_t size, _In_opt_ bool is_last = true)
42 {
43 assert(data || !size);
44
45 // Preallocate output
46 out.reserve(out.size() + enc_size(size));
47
48 // Convert data character by character.
49 for (size_t i = 0;; i++) {
50 if (num >= 3) {
51 encode(out);
52 num = 0;
53 }
54
55 if (i >= size)
56 break;
57
58 buf[num++] = reinterpret_cast<const unsigned char*>(data)[i];
59 }
60
61 // If this is the last block, flush the buffer.
62 if (is_last && num) {
63 encode(out, num);
64 num = 0;
65 }
66 }
67
68
72 void clear() noexcept
73 {
74 num = 0;
75 }
76
77
85 size_t enc_size(_In_ size_t size) const noexcept
86 {
87 return ((num + size + 2)/3)*4;
88 }
89
90
91 protected:
95 template<class _Elem, class _Traits, class _Ax>
96 void encode(_Inout_ std::basic_string<_Elem, _Traits, _Ax> &out)
97 {
98 out += base64_enc_lookup[ buf[0] >> 2 ];
99 out += base64_enc_lookup[((buf[0] << 4) | (buf[1] >> 4)) & 0x3f];
100 out += base64_enc_lookup[((buf[1] << 2) | (buf[2] >> 6)) & 0x3f];
101 out += base64_enc_lookup[ buf[2] & 0x3f];
102 }
103
104
108 template<class _Elem, class _Traits, class _Ax>
109 void encode(_Inout_ std::basic_string<_Elem, _Traits, _Ax> &out, _In_ size_t size)
110 {
111 if (size > 0) {
112 out += base64_enc_lookup[buf[0] >> 2];
113 if (size > 1) {
114 out += base64_enc_lookup[((buf[0] << 4) | (buf[1] >> 4)) & 0x3f];
115 if (size > 2) {
116 out += base64_enc_lookup[((buf[1] << 2) | (buf[2] >> 6)) & 0x3f];
117 out += base64_enc_lookup[buf[2] & 0x3f];
118 } else {
119 out += base64_enc_lookup[(buf[1] << 2) & 0x3f];
120 out += '=';
121 }
122 } else {
123 out += base64_enc_lookup[(buf[0] << 4) & 0x3f];
124 out += '=';
125 out += '=';
126 }
127 } else {
128 out += '=';
129 out += '=';
130 out += '=';
131 out += '=';
132 }
133 }
134
135
136 protected:
137 unsigned char buf[3];
138 size_t num;
139 };
140
141
143 static const char base64_enc_lookup[64] = {
144 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P',
145 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f',
146 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v',
147 'w', 'x', 'y', 'z', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '/'
148 };
150
151
156 {
157 public:
161 base64_dec() noexcept : num(0)
162 {
163 buf[0] = 0;
164 buf[1] = 0;
165 buf[2] = 0;
166 buf[3] = 0;
167 }
168
169
178 template<class _Ty, class _Ax, class _Tchr>
179 void decode(_Inout_ std::vector<_Ty, _Ax> &out, _Out_ bool &is_last, _In_z_count_(size) const _Tchr *data, _In_ size_t size)
180 {
181 is_last = false;
182
183 // Trim data size to first terminator.
184 for (size_t k = 0; k < size; k++)
185 if (!data[k]) { size = k; break; }
186
187 // Preallocate output
188 out.reserve(out.size() + dec_size(size));
189
190 for (size_t i = 0;; i++) {
191 if (num >= 4) {
192 // Buffer full; decode it.
193 size_t nibbles = decode(out);
194 num = 0;
195 if (nibbles < 3) {
196 is_last = true;
197 break;
198 }
199 }
200
201 if (i >= size)
202 break;
203
204 int x = data[i];
205 if ((buf[num] = x < _countof(base64_dec_lookup) ? base64_dec_lookup[x] : 255) != 255)
206 num++;
207 }
208 }
209
210
214 void clear() noexcept
215 {
216 num = 0;
217 }
218
219
227 size_t dec_size(_In_ size_t size) const noexcept
228 {
229 return ((num + size + 3)/4)*3;
230 }
231
232
233 protected:
237 template<class _Ty, class _Ax>
238 size_t decode(_Inout_ std::vector<_Ty, _Ax> &out)
239 {
240 out.push_back((_Ty)(((buf[0] << 2) | (buf[1] >> 4)) & 0xff));
241 if (buf[2] < 64) {
242 out.push_back((_Ty)(((buf[1] << 4) | (buf[2] >> 2)) & 0xff));
243 if (buf[3] < 64) {
244 out.push_back((_Ty)(((buf[2] << 6) | buf[3]) & 0xff));
245 return 3;
246 } else
247 return 2;
248 } else
249 return 1;
250 }
251
252
253 protected:
254 unsigned char buf[4];
255 size_t num;
256 };
257
258
260 static const unsigned char base64_dec_lookup[256] = {
261 /* 0 1 2 3 4 5 6 7 8 9 A B C D E F */
262 /* 0 */ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
263 /* 1 */ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
264 /* 2 */ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 62, 255, 255, 255, 63,
265 /* 3 */ 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 255, 255, 255, 64, 255, 255,
266 /* 4 */ 255, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
267 /* 5 */ 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 255, 255, 255, 255, 255,
268 /* 6 */ 255, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
269 /* 7 */ 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 255, 255, 255, 255, 255,
270 /* 8 */ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
271 /* 9 */ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
272 /* A */ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
273 /* B */ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
274 /* C */ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
275 /* D */ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
276 /* E */ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
277 /* F */ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255
278 };
280}
Base64 decoding session.
Definition: base64.h:156
size_t num
Number of bytes used in buf
Definition: base64.h:255
base64_dec() noexcept
Constructs blank decoding session.
Definition: base64.h:161
void decode(std::vector< _Ty, _Ax > &out, bool &is_last, const _Tchr *data, size_t size)
Decodes one block of information, and appends it to the output.
Definition: base64.h:179
size_t dec_size(size_t size) const noexcept
Returns maximum decoded size.
Definition: base64.h:227
size_t decode(std::vector< _Ty, _Ax > &out)
Decodes one complete internal buffer of data.
Definition: base64.h:238
void clear() noexcept
Resets decoding session.
Definition: base64.h:214
unsigned char buf[4]
Internal buffer.
Definition: base64.h:254
Base64 encoding session.
Definition: base64.h:19
void encode(std::basic_string< _Elem, _Traits, _Ax > &out, const void *data, size_t size, bool is_last=true)
Encodes one block of information, and appends it to the output.
Definition: base64.h:41
unsigned char buf[3]
Internal buffer.
Definition: base64.h:137
void encode(std::basic_string< _Elem, _Traits, _Ax > &out)
Encodes one complete internal buffer of data.
Definition: base64.h:96
size_t num
Number of bytes used in buf
Definition: base64.h:138
void encode(std::basic_string< _Elem, _Traits, _Ax > &out, size_t size)
Encodes partial internal buffer of data.
Definition: base64.h:109
base64_enc() noexcept
Constructs blank encoding session.
Definition: base64.h:24
void clear() noexcept
Resets encoding session.
Definition: base64.h:72
size_t enc_size(size_t size) const noexcept
Returns maximum encoded size.
Definition: base64.h:85