Open Model Railroad Network (OpenMRN)
Loading...
Searching...
No Matches
Base64.cxx
Go to the documentation of this file.
1
35#include "utils/Base64.hxx"
36
37#include <stdint.h>
38#include "utils/macros.h"
39
40static const char nib64[] =
41 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
42
43std::string base64_encode(const std::string &binary)
44{
45 std::string ret;
46 ret.reserve((binary.size() + 2) / 3 * 4);
47 unsigned ofs = 0;
48 while (ofs + 3 <= binary.size())
49 {
50 uint32_t d = (((uint8_t)binary[ofs]) << 16) //
51 | (((uint8_t)binary[ofs + 1]) << 8) //
52 | (((uint8_t)binary[ofs + 2]));
53 ret.push_back(nib64[(d >> 18) & 63]);
54 ret.push_back(nib64[(d >> 12) & 63]);
55 ret.push_back(nib64[(d >> 6) & 63]);
56 ret.push_back(nib64[(d >> 0) & 63]);
57 ofs += 3;
58 }
59 if (ofs + 1 == binary.size())
60 {
61 uint32_t d = (((uint8_t)binary[ofs]) << 16);
62 ret.push_back(nib64[(d >> 18) & 63]);
63 ret.push_back(nib64[(d >> 12) & 63]);
64 ret.push_back('=');
65 ret.push_back('=');
66 }
67 else if (ofs + 2 == binary.size())
68 {
69 uint32_t d = (((uint8_t)binary[ofs]) << 16) //
70 | (((uint8_t)binary[ofs + 1]) << 8);
71 ret.push_back(nib64[(d >> 18) & 63]);
72 ret.push_back(nib64[(d >> 12) & 63]);
73 ret.push_back(nib64[(d >> 6) & 63]);
74 ret.push_back('=');
75 }
76 return ret;
77}
78
83unsigned nib64_to_byte(char c)
84{
85 switch (c)
86 {
87 case '=':
88 return 64;
89 case '-':
90 case '+':
91 return 62;
92 case '_':
93 case '/':
94 return 63;
95 default:
96 break;
97 }
98 if ('A' <= c && c <= 'Z')
99 {
100 return c - 'A';
101 }
102 if ('a' <= c && c <= 'z')
103 {
104 return c - 'a' + 26;
105 }
106 if ('0' <= c && c <= '9')
107 {
108 return c - '0' + 52;
109 }
110 return 65;
111}
112
113bool base64_decode(const std::string &base64, std::string *data)
114{
115 HASSERT(data);
116 data->clear();
117 unsigned a = 0;
118 unsigned have = 0; // how many bits we have in the accumulator
119 unsigned ofs = 0; // next input byte.
120 while (ofs < base64.size())
121 {
122 int nib = nib64_to_byte(base64[ofs++]);
123 if (nib >= 65)
124 return false;
125 if (nib == 64)
126 return true;
127 a <<= 6;
128 a |= (nib & 63);
129 have += 6;
130 if (have >= 8)
131 {
132 data->push_back((char)((a >> (have - 8)) & 0xff));
133 have -= 8;
134 }
135 }
136 return true;
137}
std::string base64_encode(const std::string &binary)
Performs encoding of data in base64 format.
Definition Base64.cxx:43
unsigned nib64_to_byte(char c)
Decode a single base64 nibble.
Definition Base64.cxx:83
bool base64_decode(const std::string &base64, std::string *data)
Performs decoding of data from base64 format to binary.
Definition Base64.cxx:113
#define HASSERT(x)
Checks that the value of expression x is true, else terminates the current process.
Definition macros.h:138