identt
bin2ascii.h
Go to the documentation of this file.
1 
34 #ifndef __BIN2ASCII_H__
35 #define __BIN2ASCII_H__
36 
37 #include <string>
38 #include <stdexcept>
39 
40 inline std::string hex2bin(const std::string &s)
41 {
42  if (s.size() % 2)
43  throw std::runtime_error("Odd hex data size");
44  static const char lookup[] = ""
45  "\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80" // 0x00
46  "\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80" // 0x10
47  "\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80" // 0x20
48  "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x80\x80\x80\x80\x80\x80" // 0x30
49  "\x80\x0a\x0b\x0c\x0d\x0e\x0f\x80\x80\x80\x80\x80\x80\x80\x80\x80" // 0x40
50  "\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80" // 0x50
51  "\x80\x0a\x0b\x0c\x0d\x0e\x0f\x80\x80\x80\x80\x80\x80\x80\x80\x80" // 0x60
52  "\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80" // 0x70
53  "\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80" // 0x80
54  "\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80" // 0x90
55  "\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80" // 0xa0
56  "\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80" // 0xb0
57  "\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80" // 0xc0
58  "\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80" // 0xd0
59  "\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80" // 0xe0
60  "\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80" // 0xf0
61  "";
62  std::string r;
63  r.reserve(s.size() / 2);
64  for (size_t i = 0; i < s.size(); i += 2) {
65  char hi = lookup[static_cast<unsigned char>(s[i])];
66  char lo = lookup[static_cast<unsigned char>(s[i+1])];
67  if (0x80 & (hi | lo))
68  throw std::runtime_error("Invalid hex data: " + s.substr(i, 6));
69  r.push_back((hi << 4) | lo);
70  }
71  return r;
72 }
73 
74 inline std::string bin2hex(const std::string &s)
75 {
76  static const char lookup[] = "0123456789abcdef";
77  std::string r;
78  r.reserve(s.size() * 2);
79  for (size_t i = 0; i < s.size(); i++) {
80  unsigned char hi = s[i] >> 4;
81  unsigned char lo = s[i] & 0xf;
82  r.push_back(lookup[hi]);
83  r.push_back(lookup[lo]);
84  }
85  return r;
86 }
87 
88 inline void b64_strip(std::string &s)
89 {
90  if (s.empty()) return;
91  while (s.back()=='=') s.pop_back();
92 }
93 
94 inline void b64_strip(std::string* s)
95 {
96  if (s->empty()) return;
97  while (s->back()=='=') s->pop_back();
98 }
99 
100 inline void b64_sanit(std::string &s)
101 {
102  size_t pad=3 - ((s.length() + 3) % 4);
103  if (pad>0) s.resize(s.length()+pad,'=');
104 }
105 
106 inline void b64_sanit(std::string* s)
107 {
108  size_t pad=3 - ((s->length() + 3) % 4);
109  if (pad>0) s->resize(s->length()+pad,'=');
110 }
111 
112 inline std::string b64_encode(const std::string &s, bool strip=false)
113 {
114  typedef unsigned char u1;
115  static const char lookup[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
116  const u1 * data = (const u1 *) s.c_str();
117  std::string r;
118  r.reserve(s.size() * 4 / 3 + 3);
119  for (size_t i = 0; i < s.size(); i += 3) {
120  unsigned n = data[i] << 16;
121  if (i + 1 < s.size()) n |= data[i + 1] << 8;
122  if (i + 2 < s.size()) n |= data[i + 2];
123 
124  u1 n0 = (u1)(n >> 18) & 0x3f;
125  u1 n1 = (u1)(n >> 12) & 0x3f;
126  u1 n2 = (u1)(n >> 6) & 0x3f;
127  u1 n3 = (u1)(n ) & 0x3f;
128 
129  r.push_back(lookup[n0]);
130  r.push_back(lookup[n1]);
131  if (i + 1 < s.size()) r.push_back(lookup[n2]);
132  if (i + 2 < s.size()) r.push_back(lookup[n3]);
133  }
134  if (!strip) {
135  for (size_t i = 0; i < (3 - s.size() % 3) % 3; i++)
136  r.push_back('=');
137  }
138  return r;
139 }
140 
141 inline std::string b64_encode_strip(const std::string &s)
142 {
143  return b64_encode(s,true);
144 }
145 
146 inline std::string b64_decode(const std::string &s)
147 {
148  typedef unsigned char u1;
149  static const char lookup[] = ""
150  "\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80" // 0x00
151  "\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80" // 0x10
152  "\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x3e\x80\x80\x80\x3f" // 0x20
153  "\x34\x35\x36\x37\x38\x39\x3a\x3b\x3c\x3d\x80\x80\x80\x00\x80\x80" // 0x30
154  "\x80\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e" // 0x40
155  "\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x80\x80\x80\x80\x80" // 0x50
156  "\x80\x1a\x1b\x1c\x1d\x1e\x1f\x20\x21\x22\x23\x24\x25\x26\x27\x28" // 0x60
157  "\x29\x2a\x2b\x2c\x2d\x2e\x2f\x30\x31\x32\x33\x80\x80\x80\x80\x80" // 0x70
158  "\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80" // 0x80
159  "\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80" // 0x90
160  "\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80" // 0xa0
161  "\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80" // 0xb0
162  "\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80" // 0xc0
163  "\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80" // 0xd0
164  "\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80" // 0xe0
165  "\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80" // 0xf0
166  "";
167  std::string r;
168  if (!s.size()) return r;
169  if (s.size() % 4)
170  throw std::runtime_error("Invalid base64 data size");
171  size_t pad = 0;
172  if (s[s.size() - 1] == '=') pad++;
173  if (s[s.size() - 2] == '=') pad++;
174 
175  r.reserve(s.size() * 3 / 4 + 3);
176  for (size_t i = 0; i < s.size(); i += 4) {
177  u1 n0 = lookup[(u1) s[i+0]];
178  u1 n1 = lookup[(u1) s[i+1]];
179  u1 n2 = lookup[(u1) s[i+2]];
180  u1 n3 = lookup[(u1) s[i+3]];
181  if (0x80 & (n0 | n1 | n2 | n3))
182  throw std::runtime_error("Invalid hex data: " + s.substr(i, 4));
183  unsigned n = (n0 << 18) | (n1 << 12) | (n2 << 6) | n3;
184  r.push_back((n >> 16) & 0xff);
185  if (s[i+2] != '=') r.push_back((n >> 8) & 0xff);
186  if (s[i+3] != '=') r.push_back((n ) & 0xff);
187  }
188  return r;
189 }
190 
191 inline std::string b64_sanit_decode(const std::string &s)
192 {
193  std::string t=s;
194  b64_sanit(t);
195  return b64_decode(t);
196 }
197 #endif//__BIN2ASCII_H__