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