7 #ifndef CPPWAMP_BASE64_HPP
8 #define CPPWAMP_BASE64_HPP
14 #include "../config.hpp"
15 #include "../erroror.hpp"
27 template <
typename TSink>
28 static void encode(
const void* data, std::size_t size, TSink& sink)
32 auto byte =
static_cast<const Byte*
>(data);
33 auto end =
byte + size;
36 quad[0] = charFromSextet( (*
byte >> 2) & 0x3f );
37 sextet = (*
byte << 4) & 0x30;
42 sextet |= (*
byte >> 4) & 0x0f;
43 quad[1] = charFromSextet(sextet);
44 sextet = (*
byte << 2) & 0x3c;
49 sextet |= (*
byte >> 6) & 0x03;
50 quad[2] = charFromSextet(sextet);
51 quad[3] = charFromSextet( *
byte & 0x3f );
56 quad[2] = charFromSextet(sextet);
62 quad[1] = charFromSextet(sextet);
67 using SinkByte =
typename TSink::value_type;
68 auto ptr =
reinterpret_cast<const SinkByte*
>(quad.data());
69 sink.append(ptr, quad.size());
73 template <
typename TOutputByteContainer>
74 CPPWAMP_NODISCARD
static std::error_code
75 decode(
const void* data,
size_t length, TOutputByteContainer& output)
82 ErrorOr<Triplet> triplet;
83 auto str =
static_cast<const char*
>(data);
84 const char* quad = str;
85 auto end = str + length - 4;
87 for (; quad < end; quad += 4)
89 triplet = tripletFromQuad(quad,
false);
91 return triplet.error();
92 append(*triplet, output);
95 assert((quad + 4) == (str + length));
97 unsigned lastTripletCount = 1;
98 triplet = tripletFromQuad(quad,
true);
100 return triplet.error();
101 if (quad[0] == pad || quad[1] == pad)
110 lastTripletCount = (quad[3] == pad) ? 2 : 3;
112 triplet = tripletFromQuad(quad,
true);
114 return triplet.error();
115 append(*triplet, lastTripletCount, output);
121 using Byte = uint8_t;
122 using Triplet = std::array<Byte, 3>;
123 using Quad = std::array<char, 4>;
125 static constexpr
char pad =
'=';
127 static char charFromSextet(uint8_t sextet)
129 static const char alphabet[] =
131 'A',
'B',
'C',
'D',
'E',
'F',
'G',
'H',
132 'I',
'J',
'K',
'L',
'M',
'N',
'O',
'P',
133 'Q',
'R',
'S',
'T',
'U',
'V',
'W',
'X',
134 'Y',
'Z',
'a',
'b',
'c',
'd',
'e',
'f',
135 'g',
'h',
'i',
'j',
'k',
'l',
'm',
'n',
136 'o',
'p',
'q',
'r',
's',
't',
'u',
'v',
137 'w',
'x',
'y',
'z',
'0',
'1',
'2',
'3',
138 '4',
'5',
'6',
'7',
'8',
'9',
'+',
'/'
140 assert(sextet <
sizeof(alphabet));
141 return alphabet[sextet];
144 static ErrorOr<Triplet> tripletFromQuad(
const char* quad,
bool padAllowed)
146 std::array<Byte, 4> sextet;
147 for (
unsigned i=0; i<4; ++i)
149 auto s = sextetFromChar(quad[i], padAllowed);
151 return makeUnexpected(s.error());
152 sextet[i] = s.value();
155 triplet[0] = ((sextet[0] << 2) & 0xfc) | ((sextet[1] >> 4) & 0x03);
156 triplet[1] = ((sextet[1] << 4) & 0xf0) | ((sextet[2] >> 2) & 0x0f);
157 triplet[2] = ((sextet[2] << 6) & 0xc0) | ((sextet[3] ) & 0x3f);
161 static ErrorOr<Byte> sextetFromChar(
char c,
bool padAllowed)
163 static const uint8_t table[] =
165 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
166 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
167 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
168 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
169 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
172 0xff, 0xff, 0xff, 0x3e, 0xff, 0xff, 0xff, 0x3f,
175 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b,
178 0x3c, 0x3d, 0xff, 0xff, 0xff, 0x00, 0xff, 0xff,
181 0xff, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06,
184 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e,
187 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16,
190 0x17, 0x18, 0x19, 0xff, 0xff, 0xff, 0xff, 0xff,
193 0xff, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20,
196 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28,
199 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30,
202 0x31, 0x32, 0x33, 0xff, 0xff, 0xff, 0xff, 0xff,
204 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
205 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
206 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
207 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
208 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
209 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
210 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
211 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
212 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
213 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
214 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
215 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
216 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
217 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
218 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
219 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
222 if (!padAllowed && c == pad)
225 uint8_t sextet = table[index];
232 template <
typename TOutputByteContainer>
233 static void append(Triplet triplet,
size_t length,
234 TOutputByteContainer& output)
236 using OutputByte =
typename TOutputByteContainer::value_type;
237 auto data =
reinterpret_cast<const OutputByte*
>(triplet.data());
238 output.insert(output.end(), data, data + length);
241 template <
typename TOutputByteContainer>
242 static void append(Triplet triplet, TOutputByteContainer& output)
244 append(triplet, triplet.size(), output);
252 #endif // CPPWAMP_BASE64_HPP