3 * Copyright 2016-2017 Lyft Inc.
5 * Licensed under Apache License 2.0. See LICENSE.apache for terms.
13 namespace opentracing
{
14 BEGIN_OPENTRACING_ABI_NAMESPACE
15 namespace mocktracer
{
16 static constexpr char CHAR_TABLE
[] =
17 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
19 // Conversion table is taken from
20 // https://opensource.apple.com/source/QuickTimeStreamingServer/QuickTimeStreamingServer-452/CommonUtilitiesLib/base64.c
21 static const unsigned char REVERSE_LOOKUP_TABLE
[256] = {
22 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
23 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
24 64, 64, 64, 64, 64, 62, 64, 64, 64, 63, 52, 53, 54, 55, 56, 57, 58, 59, 60,
25 61, 64, 64, 64, 64, 64, 64, 64, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
26 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 64, 64, 64, 64,
27 64, 64, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42,
28 43, 44, 45, 46, 47, 48, 49, 50, 51, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
29 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
30 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
31 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
32 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
33 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
34 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
35 64, 64, 64, 64, 64, 64, 64, 64, 64};
37 std::string
Base64::decode(const char* input
, size_t length
) {
38 if (length
% 4 || length
== 0) {
42 // First position of "valid" padding character.
43 uint64_t first_padding_index
= length
;
44 int max_length
= static_cast<int>(length
) / 4 * 3;
45 // At most last two chars can be '='.
46 if (input
[length
- 1] == '=') {
48 first_padding_index
= length
- 1;
49 if (input
[length
- 2] == '=') {
51 first_padding_index
= length
- 2;
55 result
.reserve(static_cast<size_t>(max_length
));
57 uint64_t bytes_left
= length
;
58 uint64_t cur_read
= 0;
60 // Read input string by group of 4 chars, length of input string must be
61 // divided evenly by 4. Decode 4 chars 6 bits each into 3 chars 8 bits each.
62 while (bytes_left
> 0) {
63 // Take first 6 bits from 1st converted char and first 2 bits from 2nd
64 // converted char, make 8 bits char from it. Use conversion table to map
65 // char to decoded value (value is between 0 and 63 inclusive for a valid
67 const unsigned char a
=
68 REVERSE_LOOKUP_TABLE
[static_cast<uint32_t>(input
[cur_read
])];
69 const unsigned char b
=
70 REVERSE_LOOKUP_TABLE
[static_cast<uint32_t>(input
[cur_read
+ 1])];
71 if (a
== 64 || b
== 64) {
72 // Input contains an invalid character.
75 result
.push_back(static_cast<char>(a
<< 2 | b
>> 4));
76 const unsigned char c
=
77 REVERSE_LOOKUP_TABLE
[static_cast<uint32_t>(input
[cur_read
+ 2])];
79 // Decoded value 64 means invalid character unless we already know it is a
80 // valid padding. If so, following characters are all padding. Also we
81 // should check there are no unused bits.
83 if (first_padding_index
!= cur_read
+ 2) {
84 // Input contains an invalid character.
87 // There are unused bits at tail.
93 // Take last 4 bits from 2nd converted char and 4 first bits from 3rd
95 result
.push_back(static_cast<char>(b
<< 4 | c
>> 2));
97 const unsigned char d
=
98 REVERSE_LOOKUP_TABLE
[static_cast<uint32_t>(input
[cur_read
+ 3])];
100 if (first_padding_index
!= cur_read
+ 3) {
101 // Input contains an invalid character.
104 // There are unused bits at tail.
110 // Take last 2 bits from 3rd converted char and all(6) bits from 4th
112 result
.push_back(static_cast<char>(c
<< 6 | d
));
121 void Base64::encodeBase(const uint8_t cur_char
, uint64_t pos
, uint8_t& next_c
,
125 ret
.push_back(CHAR_TABLE
[cur_char
>> 2]);
126 next_c
= static_cast<uint8_t>((cur_char
& 0x03) << 4);
129 ret
.push_back(CHAR_TABLE
[next_c
| (cur_char
>> 4)]);
130 next_c
= static_cast<uint8_t>((cur_char
& 0x0f) << 2);
133 ret
.push_back(CHAR_TABLE
[next_c
| (cur_char
>> 6)]);
134 ret
.push_back(CHAR_TABLE
[cur_char
& 0x3f]);
140 void Base64::encodeLast(uint64_t pos
, uint8_t last_char
, std::string
& ret
) {
143 ret
.push_back(CHAR_TABLE
[last_char
]);
148 ret
.push_back(CHAR_TABLE
[last_char
]);
156 std::string
Base64::encode(const char* input
, uint64_t length
) {
157 uint64_t output_length
= (length
+ 2) / 3 * 4;
159 ret
.reserve(output_length
);
164 for (uint64_t i
= 0; i
< length
; ++i
) {
165 encodeBase(static_cast<uint8_t>(input
[i
]), pos
++, next_c
, ret
);
168 encodeLast(pos
, next_c
, ret
);
172 } // namespace mocktracer
173 END_OPENTRACING_ABI_NAMESPACE
174 } // namespace opentracing