]> git.proxmox.com Git - ceph.git/blob - ceph/src/jaegertracing/opentracing-cpp/mocktracer/src/base64.cpp
update source to Ceph Pacific 16.2.2
[ceph.git] / ceph / src / jaegertracing / opentracing-cpp / mocktracer / src / base64.cpp
1 /*
2 * Envoy
3 * Copyright 2016-2017 Lyft Inc.
4 *
5 * Licensed under Apache License 2.0. See LICENSE.apache for terms.
6 */
7
8 #include "base64.h"
9
10 #include <cstdint>
11 #include <string>
12
13 namespace opentracing {
14 BEGIN_OPENTRACING_ABI_NAMESPACE
15 namespace mocktracer {
16 static constexpr char CHAR_TABLE[] =
17 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
18
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};
36
37 std::string Base64::decode(const char* input, size_t length) {
38 if (length % 4 || length == 0) {
39 return {};
40 }
41
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] == '=') {
47 max_length--;
48 first_padding_index = length - 1;
49 if (input[length - 2] == '=') {
50 max_length--;
51 first_padding_index = length - 2;
52 }
53 }
54 std::string result;
55 result.reserve(static_cast<size_t>(max_length));
56
57 uint64_t bytes_left = length;
58 uint64_t cur_read = 0;
59
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
66 // character).
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.
73 return {};
74 }
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])];
78
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.
82 if (c == 64) {
83 if (first_padding_index != cur_read + 2) {
84 // Input contains an invalid character.
85 return {};
86 } else if (b & 15) {
87 // There are unused bits at tail.
88 return {};
89 } else {
90 return result;
91 }
92 }
93 // Take last 4 bits from 2nd converted char and 4 first bits from 3rd
94 // converted char.
95 result.push_back(static_cast<char>(b << 4 | c >> 2));
96
97 const unsigned char d =
98 REVERSE_LOOKUP_TABLE[static_cast<uint32_t>(input[cur_read + 3])];
99 if (d == 64) {
100 if (first_padding_index != cur_read + 3) {
101 // Input contains an invalid character.
102 return {};
103 } else if (c & 3) {
104 // There are unused bits at tail.
105 return {};
106 } else {
107 return result;
108 }
109 }
110 // Take last 2 bits from 3rd converted char and all(6) bits from 4th
111 // converted char.
112 result.push_back(static_cast<char>(c << 6 | d));
113
114 cur_read += 4;
115 bytes_left -= 4;
116 }
117
118 return result;
119 }
120
121 void Base64::encodeBase(const uint8_t cur_char, uint64_t pos, uint8_t& next_c,
122 std::string& ret) {
123 switch (pos % 3) {
124 case 0:
125 ret.push_back(CHAR_TABLE[cur_char >> 2]);
126 next_c = static_cast<uint8_t>((cur_char & 0x03) << 4);
127 break;
128 case 1:
129 ret.push_back(CHAR_TABLE[next_c | (cur_char >> 4)]);
130 next_c = static_cast<uint8_t>((cur_char & 0x0f) << 2);
131 break;
132 case 2:
133 ret.push_back(CHAR_TABLE[next_c | (cur_char >> 6)]);
134 ret.push_back(CHAR_TABLE[cur_char & 0x3f]);
135 next_c = 0;
136 break;
137 }
138 }
139
140 void Base64::encodeLast(uint64_t pos, uint8_t last_char, std::string& ret) {
141 switch (pos % 3) {
142 case 1:
143 ret.push_back(CHAR_TABLE[last_char]);
144 ret.push_back('=');
145 ret.push_back('=');
146 break;
147 case 2:
148 ret.push_back(CHAR_TABLE[last_char]);
149 ret.push_back('=');
150 break;
151 default:
152 break;
153 }
154 }
155
156 std::string Base64::encode(const char* input, uint64_t length) {
157 uint64_t output_length = (length + 2) / 3 * 4;
158 std::string ret;
159 ret.reserve(output_length);
160
161 uint64_t pos = 0;
162 uint8_t next_c = 0;
163
164 for (uint64_t i = 0; i < length; ++i) {
165 encodeBase(static_cast<uint8_t>(input[i]), pos++, next_c, ret);
166 }
167
168 encodeLast(pos, next_c, ret);
169
170 return ret;
171 }
172 } // namespace mocktracer
173 END_OPENTRACING_ABI_NAMESPACE
174 } // namespace opentracing