Mercurial > code
changeset 238:b97d75a78e22
Add Base64, base64 encoding and decoding
author | David Demelier <markand@malikania.fr> |
---|---|
date | Thu, 11 Sep 2014 17:21:51 +0200 |
parents | 887d43215b90 |
children | d9409b338f2f |
files | C++/Base64.cpp C++/Base64.h |
diffstat | 2 files changed, 194 insertions(+), 0 deletions(-) [+] |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/C++/Base64.cpp Thu Sep 11 17:21:51 2014 +0200 @@ -0,0 +1,66 @@ +/* + * Base64.cpp -- base64 encoding and decoding + * + * Copyright (c) 2013, 2014 David Demelier <markand@malikania.fr> + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include <iterator> +#include <sstream> + +#include "Base64.h" + +char Base64::lookup(int value) noexcept +{ + static const char table[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; + + return table[value]; +} + +int Base64::rlookup(char ch) +{ + if (ch == '+') + return 62; + if (ch == '/') + return 63; + + if (ch >= '0' && ch <= '9') + return ch + 4; + if (ch >= 'A' && ch <= 'Z') + return ch - 65; + if (ch >= 'a' && ch <= 'z') + return ch - 71; + + throw std::invalid_argument("not a valid base64 string"); +} + +std::string Base64::encode(const std::string &input) +{ + std::string result; + std::istringstream iss(input, std::istringstream::in); + + encode(std::istreambuf_iterator<char>(iss), std::istreambuf_iterator<char>(), std::back_inserter(result)); + + return result; +} + +std::string Base64::decode(const std::string &input) +{ + std::string result; + std::istringstream iss(input, std::istringstream::in); + + decode(std::istreambuf_iterator<char>(iss), std::istreambuf_iterator<char>(), std::back_inserter(result)); + + return result; +} \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/C++/Base64.h Thu Sep 11 17:21:51 2014 +0200 @@ -0,0 +1,128 @@ +/* + * Base64.h -- base64 encoding and decoding + * + * Copyright (c) 2013, 2014 David Demelier <markand@malikania.fr> + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef _BASE_64_H_ +#define _BASE_64_H_ + +/** + * @file Base64.h + * @brief Base64 encoding and decoding + */ + +#include <stdexcept> +#include <string> + +/** + * @class Base64 + * @brief Encode and decode Base64 data + */ +class Base64 { +public: + /** + * Get the base 64 character from the 6-bits value. + * + * @param value the value + */ + static char lookup(int value) noexcept; + + /** + * Get the integer value from the base 64 character. + * + * @param ch the base64 character + */ + static int rlookup(char ch); + + /** + * Encode the input to the output. Requirements: + * InputIt must be InputIterator + * OutputIt must be OutputIterator + * + * @param input the beginning + * @param end the end of the data + * @output the output destination + */ + template <typename InputIt, typename OutputIt> + static void encode(InputIt input, InputIt end, OutputIt output) + { + while (input != end) { + char inputbuf[3] = { 0, 0, 0 }; + int count; + + for (count = 0; count < 3 && input != end; ++count) + inputbuf[count] = *input++; + + *output++ = lookup(inputbuf[0] >> 2 & 0x3f); + *output++ = lookup(inputbuf[0] << 4 & 0x3f | inputbuf[1] >> 4 & 0x0f); + *output++ = (count < 2) ? '=' : lookup(inputbuf[1] << 2 & 0x3c | inputbuf[2] >> 6 & 0x03); + *output++ = (count < 3) ? '=' : lookup(inputbuf[2] & 0x3f); + } + } + + /** + * Decode the input to the output. Requirements: + * InputIt must be InputIterator + * OutputIt must be OutputIterator + * + * @param input the beginning + * @param end the end of the data + * @output the output destination + * @throw std::invalid_argument on bad base64 string + */ + template <typename InputIt, typename OutputIt> + static void decode(InputIt input, InputIt end, OutputIt output) + { + while (input != end) { + char inputbuf[4] = { 0, 0, 0, 0 }; + int count; + + for (count = 0; count < 4 && input != end; ++count) { + inputbuf[count] = (*input == '=') ? '=' : rlookup(*input); + input++; + } + + if (count != 4) + throw std::invalid_argument("truncated string"); + + *output++ = inputbuf[0] << 2 & 0xfc | inputbuf[1] >> 4 & 0x03; + + if (inputbuf[2] != '=') + *output++ = inputbuf[1] << 4 & 0xf0 | inputbuf[2] >> 2 & 0x0f; + if (inputbuf[3] != '=') + *output++ = inputbuf[2] << 6 & 0xc0 | inputbuf[3] & 0x3f; + } + } + + /** + * Encode a string. + * + * @param input the input string + * @return the base64 formatted string + */ + static std::string encode(const std::string &input); + + /** + * Decode a string. + * + * @param input the base64 formatted string + * @return the original string + * @throw std::invalid_argument on bad base64 string + */ + static std::string decode(const std::string &input); +}; + +#endif // !_BASE_64_H_ \ No newline at end of file