MySQL 8.3.0
Source Code Documentation
base64.h
Go to the documentation of this file.
1/*
2 Copyright (c) 2018, 2023, Oracle and/or its affiliates.
3
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License, version 2.0,
6 as published by the Free Software Foundation.
7
8 This program is also distributed with certain software (including
9 but not limited to OpenSSL) that is licensed under separate terms,
10 as designated in a particular file or component or in included license
11 documentation. The authors of MySQL hereby grant you an additional
12 permission to link the program and your derivative works with the
13 separately licensed software that they have included with MySQL.
14
15 This program is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU General Public License for more details.
19
20 You should have received a copy of the GNU General Public License
21 along with this program; if not, write to the Free Software
22 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
23*/
24
25#ifndef MYSQLROUTER_HTTP_BASE64_INCLUDED
26#define MYSQLROUTER_HTTP_BASE64_INCLUDED
27
29
30#include <algorithm> // min
31#include <array>
32#include <cstdint>
33#include <stdexcept>
34#include <string>
35#include <utility> // index_sequence
36#include <vector>
37
38enum class Base64Endianess { LITTLE, BIG };
39
40/**
41 * Generic Base64 codec.
42 *
43 * Base64 comes in many flavours:
44 *
45 * - RFC4648 used by HTTP
46 * - crypt
47 * - bcrypt
48 * - pbkdf2 in MCF
49 * - UUencode
50 *
51 * they differ by
52 *
53 * - alphabet
54 * - endianness
55 * - padding
56 *
57 * Base64Impl provides generic encode and decode methods which are parametrized
58 * by Endianness, Padding.
59 *
60 * Parametrization with templates allows to provide:
61 *
62 * - one implementation for all combinations
63 * - without extra runtime overhead as dead code is removed by the compiler
64 *
65 * Endianness
66 * =========
67 *
68 * Little Endian
69 * -------------
70 *
71 * using Alphabet=Crypt
72 *
73 * octet(hex): 55
74 * uint32: ........ ........ 01010101 (LSB)
75 * uint32: ...... ...... ....01 010101 (LSB)
76 * sextet(hex): 1 15
77 * Alphabet: / J
78 *
79 * Out: J/
80 *
81 *
82 * Big Endian
83 * ----------
84 *
85 * using Alphabet=Crypt
86 *
87 * octet(hex): 55
88 * uint32: 01010101 ........ ........ (LSB)
89 * uint32: 010101 01.... ...... ...... (LSB)
90 * sextet(hex): 15 10
91 * Alphabet: J E
92 *
93 * Out: JE
94 *
95 * Padding
96 * =======
97 *
98 * If padding is defined mandatory,
99 *
100 * - at encode() each group of 4 sextets is filled by with the padding
101 * character.
102 * - at decode() input must have padding.
103 *
104 * If padding is not mandatory,
105 *
106 * - at encode() no padding is added.
107 * - at decode() padding is accepted, but not required.
108 */
109
110/*
111 * TODO: look into
112 *
113 * - http://0x80.pl/notesen/2015-12-27-base64-encoding.html
114 * - http://0x80.pl/notesen/2016-01-12-sse-base64-encoding.html
115 * - http://0x80.pl/notesen/2016-01-17-sse-base64-decoding.html
116 * - http://alfredklomp.com/programming/sse-base64/
117 * - https://github.com/lemire/fastbase64
118 */
120 public:
121 /**
122 * type of all alphabet.
123 */
124 using alphabet_type = std::array<char, 64>;
125
126 /**
127 * type of all inverse mappings of alphabets.
128 *
129 * - -1 invalid
130 * - 0-63 position into alphabet
131 */
132 using inverse_alphabet_type = std::array<int8_t, 256>;
133
134 template <Base64Endianess endianess, bool PaddingMandatory, char PaddingChar>
135 static std::vector<uint8_t> decode(
136 const std::string &encoded,
137 const inverse_alphabet_type &inverse_alphabet) {
138 std::vector<uint8_t> out((encoded.size() + 3) / 4 * 3);
139
140 constexpr unsigned int shift_pos_0 =
141 endianess == Base64Endianess::BIG ? 16 : 0;
142 constexpr unsigned int shift_pos_1 =
143 endianess == Base64Endianess::BIG ? 8 : 8;
144 constexpr unsigned int shift_pos_2 =
145 endianess == Base64Endianess::BIG ? 0 : 16;
146
147 auto out_it = out.begin();
148 auto data_it = encoded.cbegin();
149 const auto data_end_it = encoded.cend();
150 while (const size_t data_left = std::distance(data_it, data_end_it)) {
151 if (data_left < 2) {
152 throw std::runtime_error("invalid sequence");
153 }
154
155 if (PaddingMandatory && (data_left < 4)) {
156 throw std::runtime_error("missing padding");
157 }
158
159 uint32_t v = 0;
160 bool is_padding = false;
161 const size_t max_rounds = std::min(size_t{4}, data_left);
162 uint32_t sextets = 0;
163 for (size_t cnt = 0; cnt < max_rounds; ++cnt) {
164 const uint8_t b64 = *(data_it++);
165 if (is_padding && b64 != PaddingChar) {
166 throw std::runtime_error("invalid char, expected padding");
167 }
168 const int8_t c = (inverse_alphabet[b64]);
169
170 if (c == -1) {
171 if (data_left <= 4 && cnt >= 2 && b64 == PaddingChar) {
172 // padding is ok at the end
173 is_padding = true;
174 } else {
175 throw std::runtime_error(std::string("invalid char"));
176 }
177 }
178
179 // add new 6 bits
180 if (!is_padding) {
181 if (endianess == Base64Endianess::BIG) {
182 v |= c << (6 * (3 - cnt));
183 } else {
184 v |= c << (6 * cnt);
185 }
186 sextets++;
187 }
188 }
189
190 // 3 * 6bit b64 = 18bits translates to 16bit (2 bits extra)
191 // 2 * 6bit b64 = 12bits translates to 8bit (4 bits extra)
192 //
193 // They must be 0b0 to ensure only one b64 value
194 // maps to one 8bit version and the other way around.
195 //
196 // Example
197 // ------
198 //
199 // WWU= -> Ye -> WWU=
200 //
201 // 0x14
202 // ...... ...... 010100
203 // ........ ........ xx
204 //
205 // WWW= -> Ye -> WWU=
206 //
207 // 0x16
208 // ...... ...... 010110
209 // ........ ........ xx
210 //
211 switch (sextets) {
212 case 2:
213 *(out_it++) = static_cast<uint8_t>(v >> shift_pos_0);
214
215 if (0 != static_cast<uint8_t>(v >> shift_pos_1)) {
216 throw std::runtime_error("unused bits");
217 }
218 break;
219 case 3:
220 *(out_it++) = static_cast<uint8_t>(v >> shift_pos_0);
221 *(out_it++) = static_cast<uint8_t>(v >> shift_pos_1);
222
223 if (0 != static_cast<uint8_t>(v >> shift_pos_2)) {
224 throw std::runtime_error("unused bits");
225 }
226 break;
227 case 4:
228 *(out_it++) = static_cast<uint8_t>(v >> shift_pos_0);
229 *(out_it++) = static_cast<uint8_t>(v >> shift_pos_1);
230 *(out_it++) = static_cast<uint8_t>(v >> shift_pos_2);
231 break;
232 }
233 }
234
235 out.resize(std::distance(out.begin(), out_it));
236
237 return out;
238 }
239
240 template <Base64Endianess endianess, bool PaddingMandatory, char PaddingChar>
241 static std::string encode(const std::vector<uint8_t> &data,
242 const alphabet_type &alphabet) {
243 std::string out;
244 // ensure we have enough space
245 out.resize((data.size() + 2) / 3 * 4);
246
247 constexpr unsigned int shift_pos_0 =
248 endianess == Base64Endianess::BIG ? 16 : 0;
249 constexpr unsigned int shift_pos_1 =
250 endianess == Base64Endianess::BIG ? 8 : 8;
251 constexpr unsigned int shift_pos_2 =
252 endianess == Base64Endianess::BIG ? 0 : 16;
253
254 auto out_it = out.begin();
255 auto data_it = data.begin();
256 const auto data_end_it = data.end();
257 while (const size_t data_left = std::distance(data_it, data_end_it)) {
258 // consume 3 bytes, if we have them
259 uint32_t v = 0;
260
261 size_t padding_pos = 4; // no padding
262 switch (data_left) {
263 case 1:
264 v |= (*(data_it++)) << shift_pos_0;
265 padding_pos = 2; // out-byte 2 and 3 are padding
266 break;
267 case 2:
268 v |= (*(data_it++)) << shift_pos_0;
269 v |= (*(data_it++)) << shift_pos_1;
270 padding_pos = 3; // out-byte 3 is padding
271 break;
272 default:
273 v |= (*(data_it++)) << shift_pos_0;
274 v |= (*(data_it++)) << shift_pos_1;
275 v |= (*(data_it++)) << shift_pos_2;
276 break;
277 }
278
279 // and base64-encode them
280 size_t cnt;
281 for (cnt = 0; cnt < 4; ++cnt) {
282 if (cnt >= padding_pos) {
283 break;
284 }
285
286 size_t pos;
287 if (endianess == Base64Endianess::BIG) {
288 // take the upper 6 bit and shift left each round
289 pos = (v & (0x3f << (3 * 6))) >> 3 * 6;
290 v <<= 6;
291 } else {
292 // take the lower 6 bit and shift right each round
293 pos = v & 0x3f;
294 v >>= 6;
295 }
296 *(out_it++) = alphabet.at(pos);
297 }
298
299 if (PaddingMandatory) {
300 // apply padding if needed
301 for (; cnt < 4; ++cnt) {
302 *(out_it++) = PaddingChar;
303 }
304 }
305 }
306 out.resize(std::distance(out.begin(), out_it));
307
308 return out;
309 }
310};
311
312namespace Base64Alphabet {
313
314/**
315 * type of all alphabet.
316 */
318
319/**
320 * type of all inverse mappings of alphabets.
321 *
322 * - -1 invalid
323 * - 0-63 position into alphabet
324 */
326
327namespace detail {
328/**
329 * find position of char in alphabet.
330 *
331 * @returns position in alphabet
332 * @retval -1 if not found
333 */
334constexpr int8_t find_pos_of_char(const alphabet_type &v, uint8_t character,
335 size_t v_ndx = 0) {
336 // ensure that -1 and 255 don't overlap
337 static_assert(alphabet_type().size() <= 128,
338 "alphabet MUST less <= 128 chars");
339 return (v_ndx >= v.size() ? -1
340 : (v[v_ndx] == static_cast<char>(character))
341 ? static_cast<uint8_t>(v_ndx)
342 : find_pos_of_char(v, character, v_ndx + 1));
343}
344
345// hand-roll std::make_index_sequence<256> as SunCC 12.6 runs into:
346//
347// Error: Templates nested too deeply (recursively?).
348//
349// for std::make_index_sequence<n> with n > 255
350//
351// see: https://community.oracle.com/thread/4070120
352//
353// There exists a workaround:
354//
355// > The compiler has an undocumented "Q option" (or "Wizard option") that
356// > lets you increase the allowed depth:
357// >
358// > -Qoption ccfe -tmpldepth=N
359// > -W0,-tmpldepth=N
360//
361// but here we go the hand-rolled version of what std::make_index_sequence<256>
362// would have generated instead.
363
364using ndx_256 = std::index_sequence<
365 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20,
366 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39,
367 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58,
368 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77,
369 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96,
370 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112,
371 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127,
372 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142,
373 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157,
374 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172,
375 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187,
376 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202,
377 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217,
378 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232,
379 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247,
380 248, 249, 250, 251, 252, 253, 254, 255>;
381
382/**
383 * build inverse-alphabet.
384 *
385 * calls find_pos_by_char() for each element of ndx_256
386 *
387 * based on C++11 parameter pack.
388 */
389template <std::size_t... I>
391 std::index_sequence<I...>) {
392 return {{find_pos_of_char(v, I)...}};
393}
394
395/**
396 * inverse
397 */
399 return make_inverse_array(v, ndx_256{});
400}
401} // namespace detail
402
403class Base64 {
404 public:
406 {'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', // 0x00
407 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', //
408 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', // 0x10
409 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', //
410 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', // 0x20
411 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', //
412 'w', 'x', 'y', 'z', '0', '1', '2', '3', // 0x30
413 '4', '5', '6', '7', '8', '9', '+', '/'}};
414
417};
418
420 public:
422 {'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', // 0x00
423 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', //
424 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', // 0x10
425 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', //
426 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', // 0x20
427 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', //
428 'w', 'x', 'y', 'z', '0', '1', '2', '3', // 0x30
429 '4', '5', '6', '7', '8', '9', '-', '_'}};
430
433};
434
435/**
436 * Base64 alphabet for MCF.
437 *
438 * same as Base64 from RFC4648, but different altchars to fit the needs of MCF
439 *
440 * altchars
441 * : . and /
442 *
443 * paddingchar
444 * : =
445 *
446 * padding mandatory
447 * : no
448 */
449class Mcf {
450 public:
452 {'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', // 0x00
453 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', //
454 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', // 0x10
455 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', //
456 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', // 0x20
457 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', //
458 'w', 'x', 'y', 'z', '0', '1', '2', '3', // 0x30
459 '4', '5', '6', '7', '8', '9', '.', '/'}};
460
463};
464
465class Crypt {
466 public:
468 {'.', '/', '0', '1', '2', '3', '4', '5', // 0x00
469 '6', '7', '8', '9', 'A', 'B', 'C', 'D', //
470 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', // 0x10
471 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', //
472 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', // 0x20
473 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', //
474 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', // 0x30
475 's', 't', 'u', 'v', 'w', 'x', 'y', 'z'}};
476
479};
480
481class Bcrypt {
482 public:
484 {'.', '/', 'A', 'B', 'C', 'D', 'E', 'F', // 0x00
485 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', //
486 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', // 0x10
487 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', //
488 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', // 0x20
489 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', //
490 'u', 'v', 'w', 'x', 'y', 'z', '0', '1', // 0x30
491 '2', '3', '4', '5', '6', '7', '8', '9'}};
492
495};
496
497class Uuencode {
498 public:
500 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, // 0x00
501 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
502 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, // 0x10
503 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
504 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, // 0x20
505 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f,
506 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, // 0x30
507 0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f,
508 }};
509
512};
513} // namespace Base64Alphabet
514
515/**
516 * Base64 codec base class.
517 */
518template <class Alphabet, Base64Endianess E, bool PaddingMandatory,
519 char PaddingChar>
521 public:
522 /**
523 * decode a base64 encoded string to binary.
524 *
525 * @pre encoded only contains alphabet
526 *
527 * @throws std::runtime_error if preconditions are not met
528 * @returns binary representation
529 */
530 static std::vector<uint8_t> decode(const std::string &encoded) {
531 return Base64Impl::decode<E, PaddingMandatory, PaddingChar>(
532 encoded, Alphabet::inverse_alphabet);
533 }
534
535 /**
536 * encode binary to base64.
537 */
538 static std::string encode(const std::vector<uint8_t> &decoded) {
539 return Base64Impl::encode<E, PaddingMandatory, PaddingChar>(
540 decoded, Alphabet::alphabet);
541 }
542};
543
544/**
545 * 'base64' alphabet from RFC4648.
546 *
547 * also used by:
548 *
549 * - uuencode-base64
550 * - data URI scheme (RFC2397)
551 *
552 * alphabet
553 * : `ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/`
554 *
555 * padding mandatory
556 * : yes, with =
557 */
558using Base64 =
560
561/**
562 * 'base64url' URL and Filename-safe Base64 alphabet from RFC4648.
563 *
564 * '+' and '/' in 'base64' have special meaning in URLs and would need
565 * to be URL-encoded.
566 *
567 * alphabet
568 * : `ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_`
569 *
570 * padding mandatory
571 * : yes, with =
572 */
575
576/**
577 * Base64 alphabet for MCF's pbkdf2 methods.
578 *
579 * alphabet
580 * : `ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789./`
581 *
582 * padding mandatory
583 * : no
584 */
587
588/**
589 * Radix64 for crypt (little-endian).
590 *
591 * alphabet
592 * : `./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz`
593 *
594 * padding mandatory
595 * : no
596 */
599
600/**
601 * Radix64 for crypt (big-endian).
602 *
603 * @see Radix64Crypt
604 */
607
608/**
609 * Radix64 for bcrypt.
610 *
611 * alphabet
612 * : `./ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789`
613 *
614 * padding mandatory
615 * : no
616 */
619
620/**
621 * Radix64 for traditional Uuencode.
622 *
623 * alphabet
624 * : 0x32...0x95
625 *
626 * padding mandatory
627 * : yes, with accent
628 */
631
632#endif
Definition: base64.h:419
static constexpr inverse_alphabet_type HTTP_COMMON_EXPORT inverse_alphabet
Definition: base64.h:431
static constexpr alphabet_type HTTP_COMMON_EXPORT alphabet
Definition: base64.h:421
Definition: base64.h:403
static constexpr alphabet_type HTTP_COMMON_EXPORT alphabet
Definition: base64.h:405
static constexpr inverse_alphabet_type HTTP_COMMON_EXPORT inverse_alphabet
Definition: base64.h:415
Definition: base64.h:481
static constexpr alphabet_type HTTP_COMMON_EXPORT alphabet
Definition: base64.h:483
static constexpr inverse_alphabet_type HTTP_COMMON_EXPORT inverse_alphabet
Definition: base64.h:493
Definition: base64.h:465
static constexpr alphabet_type HTTP_COMMON_EXPORT alphabet
Definition: base64.h:467
static constexpr inverse_alphabet_type HTTP_COMMON_EXPORT inverse_alphabet
Definition: base64.h:477
Base64 alphabet for MCF.
Definition: base64.h:449
static constexpr alphabet_type HTTP_COMMON_EXPORT alphabet
Definition: base64.h:451
static constexpr inverse_alphabet_type HTTP_COMMON_EXPORT inverse_alphabet
Definition: base64.h:461
Definition: base64.h:497
static constexpr alphabet_type HTTP_COMMON_EXPORT alphabet
Definition: base64.h:499
static constexpr inverse_alphabet_type HTTP_COMMON_EXPORT inverse_alphabet
Definition: base64.h:510
Base64 codec base class.
Definition: base64.h:520
static std::string encode(const std::vector< uint8_t > &decoded)
encode binary to base64.
Definition: base64.h:538
static std::vector< uint8_t > decode(const std::string &encoded)
decode a base64 encoded string to binary.
Definition: base64.h:530
Generic Base64 codec.
Definition: base64.h:119
static std::vector< uint8_t > decode(const std::string &encoded, const inverse_alphabet_type &inverse_alphabet)
Definition: base64.h:135
static std::string encode(const std::vector< uint8_t > &data, const alphabet_type &alphabet)
Definition: base64.h:241
std::array< int8_t, 256 > inverse_alphabet_type
type of all inverse mappings of alphabets.
Definition: base64.h:132
std::array< char, 64 > alphabet_type
type of all alphabet.
Definition: base64.h:124
#define HTTP_COMMON_EXPORT
Definition: http_common_export.h:39
constexpr inverse_alphabet_type inverse(const alphabet_type &v)
inverse
Definition: base64.h:398
constexpr int8_t find_pos_of_char(const alphabet_type &v, uint8_t character, size_t v_ndx=0)
find position of char in alphabet.
Definition: base64.h:334
std::index_sequence< 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255 > ndx_256
Definition: base64.h:380
constexpr inverse_alphabet_type make_inverse_array(const alphabet_type &v, std::index_sequence< I... >)
build inverse-alphabet.
Definition: base64.h:390
Definition: base64.h:312
Base64Impl::inverse_alphabet_type inverse_alphabet_type
type of all inverse mappings of alphabets.
Definition: base64.h:325
Base64Impl::alphabet_type alphabet_type
type of all alphabet.
Definition: base64.h:317
Definition: ut0tuple.h:56
bool distance(const dd::Spatial_reference_system *srs, const Geometry *g1, const Geometry *g2, double *distance, bool *is_null) noexcept
Computes the distance between two geometries.
Definition: distance.cc:39
Base64Endianess
Definition: base64.h:38