diff options
author | Eelco Dolstra <eelco.dolstra@logicblox.com> | 2015-02-09T14·09+0100 |
---|---|---|
committer | Eelco Dolstra <eelco.dolstra@logicblox.com> | 2015-02-10T10·33+0100 |
commit | a596c525ad3ca86226cdb8094b91a578b23c1dae (patch) | |
tree | 04e09211da695cc2d2d72eac119be18dbd370c1c /src/libutil/util.cc | |
parent | 70cae879e3c3f5c3fba906ba5ec220f84cff1d61 (diff) |
Add base64 encoder/decoder
Diffstat (limited to 'src/libutil/util.cc')
-rw-r--r-- | src/libutil/util.cc | 59 |
1 files changed, 59 insertions, 0 deletions
diff --git a/src/libutil/util.cc b/src/libutil/util.cc index 4f3010880286..be0a9bf317d1 100644 --- a/src/libutil/util.cc +++ b/src/libutil/util.cc @@ -1208,4 +1208,63 @@ string filterANSIEscapes(const string & s, bool nixOnly) } +static char base64Chars[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; + + +string base64Encode(const string & s) +{ + string res; + int data = 0, nbits = 0; + + for (char c : s) { + data = data << 8 | (unsigned char) c; + nbits += 8; + while (nbits >= 6) { + nbits -= 6; + res.push_back(base64Chars[data >> nbits & 0x3f]); + } + } + + if (nbits) res.push_back(base64Chars[data << (6 - nbits) & 0x3f]); + while (res.size() % 4) res.push_back('='); + + return res; +} + + +string base64Decode(const string & s) +{ + bool init = false; + char decode[256]; + if (!init) { + // FIXME: not thread-safe. + memset(decode, -1, sizeof(decode)); + for (int i = 0; i < 64; i++) + decode[(int) base64Chars[i]] = i; + init = true; + } + + string res; + unsigned int d = 0, bits = 0; + + for (char c : s) { + if (c == '=') break; + if (c == '\n') continue; + + char digit = decode[(unsigned char) c]; + if (digit == -1) + throw Error("invalid character in Base64 string"); + + bits += 6; + d = d << 6 | digit; + if (bits >= 8) { + res.push_back(d >> (bits - 8) & 0xff); + bits -= 8; + } + } + + return res; +} + + } |