/*
								+----------------------------------+
								|                                  |
								|  ***   Base64 coder class   ***  |
								|                                  |
								|   Copyright © -tHE SWINe- 2009   |
								|                                  |
								|             Base64.h             |
								|                                  |
								+----------------------------------+
*/

#pragma once
#ifndef __BASE64_CODING_INCLUDED
#define __BASE64_CODING_INCLUDED

/**
 *	@file Base64.h
 *	@author -tHE SWINe-
 *	@date 2009
 *	@brief Base-64 encoding implementations
 *
 *	@date 2009-09-29
 *
 *	added CBase64 class, implementing RFC 1421 (RFC 4648 if BASE64_NO_WHITESPACE is defined)
 *
 *	the difference between CModifiedBase64 and CBase64 being CBase64 has fixed alphabet and
 *	when encoding, it pads output with '=' characters so output size is divisible by four.
 *	also, (if BASE64_NO_WHITESPACE is not defined) CBase64 adds line end/feed character pair
 *	so no output line has more than 64 (printable - not counting cr/lf) characters on it.
 *	when decoding, CBase64 ignores whitespace characters (if BASE64_NO_WHITESPACE is not
 *	defined) in the input stream and implements canonical checks (if BASE64_CANONICAL_CHECK
 *	is defined; see RFC). these efforts are to simplify processing by automatically
 *	adding / removing whitespace and padding. note it does not ignore characters other than
 *	whitespace, therefore making "covert channel" data unlikely to pass (it would have to
 *	be encoded as series of spaces in BASE64 data). it adds some issues about calculating
 *	size of decoded output - there may be arbitrary amount of whitespace - so the function
 *	returns upper bound instead, making CBase64 able to encode a bit less data (2.91 GB)
 *	than CModifiedBase64 is (3 GB), this is due to 4 GB memory cap for x86 applications.
 *
 *	on the other side CBase64 is a bit more practical / simpler to use.
 *
 *	@note RFC 4648 can be effectively implemented with CModifiedBase64 using default alphabet
 *	and manually adding / removing padding characters.
 *
 *	@date 2009-10-11
 *
 *	replaced stl container ::resize() by stl_ut::Resize_*() to avoid unhandled
 *	std::bad_alloc
 *
 *	@date 2012-06-19
 *
 *	Moved multiple inclusion guard before file documentation comment.
 *
 *	@date 2014-07-31
 *
 *	Added destination buffer size parameter to all the functions to increase security.
 *	Note that the change should not affect code that uses TBuffer or std::string for
 *	storing the encoded / decoded data. The changes only apply to the low-level functions.
 *
 */

#include "Integer.h"
#include "Buffer.h"
#include "StlUtils.h"

/**
 *	@def BASE64_NO_WHITESPACE
 *
 *	This macro disables CBase64::Encode adding newline after each 64
 *	Base-64 characters and as well makes CBase64::n_Decode fail when
 *	whitespace characters are present in input stream (as described in RFC 4648).
 *	In case this macro is not defined, CBase64 works as defined in RFC 1421.
 *
 *	@note This has no effect on CModifiedBase64 methods.
 */
//#define BASE64_NO_WHITESPACE

/**
 *	@def BASE64_CANONICAL_CHECK
 *
 *	This macro enables CBase64::n_Decode to check for bits that are not
 *	used in decoded data to be zero (this happens at the end, when padding
 *	characters are used). In case bits are nonzero, decoding fails.
 *
 *	@note This has no effect on CModifiedBase64::Decode which doesn't
 *		implement this check.
 */
#define BASE64_CANONICAL_CHECK

/**
 *	@brief simple Base-64 encoding class
 *
 *	Simple Base-64 encoding class (as described in RFC 4648),
 *	except in case BASE64_NO_WHITESPACE is not defined, it adds line breaks
 *	after each 64 Base-64 characters when encoding and ignores whitespace
 *	when decoding (as defined in RFC 1421).
 *
 *	@note This only performs encoding/decoding on buffers (not on streams).
 *	@note Encoding routines don't append terminating zero to output data.
 */
class CBase64 {
private:
	static const int m_p_inverse_table[256];

public:
	/**
	 *	This normally equals to global size_t type,
	 *	however, in case __LARGE_BUFFER__ is defined,
	 *	uint64_t is used instead
	 */
#ifdef __LARGE_BUFFER__
	typedef TBuffer::size_t size_t;
#endif // __LARGE_BUFFER__

	/**
	 *	@brief returns maximal size of data to be encoded
	 *
	 *	@return Returns maximal size of data to be encoded
	 *		(ratio of original and Base-64 encoded data is 6:8,
	 *		therefore for 4GB buffer limit, this returns 3GB,
	 *		which is largest possible amount of input data that
	 *		can be encoded to Base-64 without crossing 4BG limit).
	 */
	static inline size_t n_Max_EncodeSize();

	/**
	 *	@brief calculates size of encoding output
	 *
	 *	@param[in] n_input is input data size, in bytes.
	 *
	 *	@return Returns size of buffer (in bytes) to contain n_input encoded bytes.
	 *
	 *	@note n_input must be less or equal to n_Max_EncodeSize().
	 */
	static inline size_t n_EncodedSize(size_t n_input);

	/**
	 *	@brief calculates size of decoding output
	 *
	 *	@param[in] n_input is input data size, in bytes.
	 *
	 *	@return returns upper bound of size of buffer (in bytes) to contain n_input
	 *		decoded bytes (encoded data may contain whitespace, then will the
	 *		size of decoded output be smaller).
	 */
	static inline size_t n_DecodedSize_UpperBound(size_t n_input);

	/**
	 *	@brief Base-64 encoding routine
	 *
	 *	generic data encoding routine; encodes contents of p_src_data buffer and stores
	 *	it in p_dest buffer.
	 *
	 *	@param[in] n_dest_size is size of the destination buffer, in bytes
	 *	@param[out] p_dest is destination buffer (must be allocated to n_EncodedSize(n_src_size) bytes).
	 *	@param[in] n_src_size is input data size (must be less or equal to n_Max_EncodeSize() bytes).
	 *	@param[in] p_src_data is buffer, containing data to be encoded.
	 *
	 *	@return Returns true on success, false on failure (input buffer size
	 *		exceeding n_Max_EncodeSize()).
	 *
	 *	@note Encoding increases data size in 4:3 ratio, so there's n_Max_EncodeSize() limit
	 *		(for x86 application it's 3GB, so the result wouldn't exceed 4GB).
	 */
	static bool Encode(size_t n_dest_size, void *p_dest, size_t n_src_size, const void *p_src_data);

	/**
	 *	@brief Base-64 decoding routine
	 *
	 *	Generic data decoding routine; decodes contents of p_src_data buffer and stores
	 *	it in p_dest buffer (must be allocated to n_DecodedSize_UpperBound(n_src_size) bytes).
	 *
	 *	@param[in] n_dest_size is size of the destination buffer, in bytes
	 *	@param[out] p_dest is destination buffer.
	 *	@param[in] p_src_data is pointer to Base-64 encoded data.
	 *	@param[in] n_src_size is size of input data buffer in bytes.
	 *
	 *	@return Returns number of bytes written to dest buffer on success, zero on failure.
	 *		(watch out for empty input buffer!; can't return negative number,
	 *		size_t may be unsigned)
	 */
	static size_t n_Decode(size_t n_dest_size, void *p_dest, size_t n_src_size, const void *p_src_data);

	/**
	 *	@brief data encoding routine overload
	 *
	 *	Encodes contents of r_t_src buffer and stores it in p_dest buffer
	 *	(must be allocated to n_DecodedSize(n_src_size) bytes).
	 *
	 *	@param[in] n_dest_size is size of the destination buffer, in bytes
	 *	@param[out] p_dest is destination buffer.
	 *	@param[in] r_t_src is input data buffer (must be at most n_Max_EncodeSize() bytes large).
	 *
	 *	@return Returns true on success, false on failure (input buffer size
	 *		exceeding n_Max_EncodeSize()).
	 *
	 *	@note Rncoding increases data size in 4:3 ratio, so there's n_Max_EncodeSize() limit
	 *		(for x86 application it's 3GB, so the result wouldn't exceed 4GB).
	 */
	static inline bool Encode(size_t n_dest_size, void *p_dest, const TBuffer &r_t_src);

	/**
	 *	@brief data encoding routine overload
	 *
	 *	Encodes contents of r_t_src buffer and stores it in r_t_dest buffer
	 *	(rewrites original contents, does not concatenate).
	 *
	 *	@param[out] r_t_dest is destination buffer.
	 *	@param[in] r_t_src is input data buffer (must be at most n_Max_EncodeSize() bytes large).
	 *
	 *	@return Returns true on success, false on failure (not enough memory or
	 *		input buffer size exceeding n_Max_EncodeSize()).
	 *
	 *	@note Encoding increases data size in 4:3 ratio, so there's n_Max_EncodeSize() limit
	 *		(for x86 application it's 3GB, so the result wouldn't exceed 4GB).
	 */
	static inline bool Encode(TBuffer &r_t_dest, const TBuffer &r_t_src);

	/**
	 *	@brief data encoding routine overload
	 *
	 *	Encodes contents of r_t_src buffer and stores it in r_s_dest string
	 *	(rewrites original contents, does not concatenate).
	 *
	 *	@param[out] r_s_dest is destination string.
	 *	@param[in] r_t_src is input data buffer (must be at most n_Max_EncodeSize() bytes large).
	 *
	 *	@return Returns true on success, false on failure (not enough memory or
	 *		input buffer size exceeding n_Max_EncodeSize()).
	 *
	 *	@note Encoding increases data size in 4:3 ratio, so there's n_Max_EncodeSize() limit
	 *		(for x86 application it's 3GB, so the result wouldn't exceed 4GB).
	 */
	static inline bool Encode(std::string &r_s_dest, const TBuffer &r_t_src);

	/**
	 *	@brief data encoding routine overload
	 *
	 *	Encodes contents of p_src_data buffer and stores it in r_t_dest buffer
	 *	(rewrites original contents, does not concatenate).
	 *
	 *	@param[out] r_t_dest is destination buffer.
	 *	@param[in] n_src_size is input data size (must be less or equal to n_Max_EncodeSize() bytes).
	 *	@param[in] p_src_data is buffer, containing data to be encoded.
	 *
	 *	@return Returns true on success, false on failure (not enough memory or
	 *		  input buffer size exceeding n_Max_EncodeSize()).
	 *
	 *	@note Encoding increases data size in 4:3 ratio, so there's n_Max_EncodeSize() limit
	 *		(for x86 application it's 3GB, so the result wouldn't exceed 4GB).
	 */
	static inline bool Encode(TBuffer &r_t_dest, size_t n_src_size, const void *p_src_data);

	/**
	 *	@brief data encoding routine overload
	 *
	 *	Encodes contents of p_src_data buffer and stores it in r_s_dest string
	 *	(rewrites original contents, does not concatenate).
	 *
	 *	@param[out] r_s_dest is destination string.
	 *	@param[in] n_src_size is input data size (must be less or equal to n_Max_EncodeSize() bytes).
	 *	@param[in] p_src_data is buffer, containing data to be encoded.
	 *
	 *	@return Returns true on success, false on failure (not enough memory or
	 *		  input buffer size exceeding n_Max_EncodeSize()).
	 *
	 *	@note Encoding increases data size in 4:3 ratio, so there's n_Max_EncodeSize() limit
	 *		(for x86 application it's 3GB, so the result wouldn't exceed 4GB).
	 */
	static inline bool Encode(std::string &r_s_dest, size_t n_src_size, const void *p_src_data);

	/**
	 *	@brief data decoding routine overload
	 *
	 *	Decodes contents of r_t_src buffer and stores it in r_t_dest buffer
	 *	(rewrites original contents, does not concatenate).
	 *
	 *	@param[out] r_t_dest is destination buffer
	 *	@param[in] r_t_src is buffer, containing input data
	 *
	 *	@return Returns number of bytes written to dest buffer on success, zero on failure
	 *		(watch out for empty input buffer!; can't return negative number,
	 *		size_t may be unsigned)
	 */
	static inline size_t n_Decode(TBuffer &r_t_dest, const TBuffer &r_t_src);

	/**
	 *	@brief data decoding routine overload
	 *
	 *	Decodes contents of p_src_data buffer and stores it in r_t_dest buffer
	 *	(rewrites original contents, does not concatenate).
	 *
	 *	@param[out] r_t_dest is destination buffer
	 *	@param[in] p_src_data is pointer to Base-64 encoded data
	 *	@param[in] n_src_size is size of input data buffer in bytes
	 *
	 *	@return Returns number of bytes written to dest buffer on success, zero on failure
	 *		(watch out for empty input buffer!; can't return negative number,
	 *		size_t may be unsigned)
	 */
	static inline size_t n_Decode(TBuffer &r_t_dest, size_t n_src_size, const void *p_src_data);

	/**
	 *	@brief data decoding routine overload
	 *
	 *	Decodes contents of r_s_src string and stores it in r_t_dest buffer
	 *	(rewrites original contents, does not concatenate).
	 *
	 *	@param[out] r_t_dest is destination buffer
	 *	@param[in] r_s_src is string, containing input data
	 *
	 *	@return Returns number of bytes written to dest buffer on success, zero on failure
	 *		  (watch out for empty input buffer!; can't return negative number,
	 *		  size_t may be unsigned).
	 */
	static inline size_t n_Decode(TBuffer &r_t_dest, const std::string &r_s_src);

	/**
	 *	@brief data decoding routine overload
	 *
	 *	Decodes contents of r_s_src string and stores it in r_t_dest buffer
	 *	(rewrites original contents, does not concatenate).
	 *
	 *	@param[out] r_t_dest is destination buffer
	 *	@param[in] p_s_src is null-terminated string, containing input data
	 *
	 *	@return Returns number of bytes written to dest buffer on success, zero on failure
	 *		(watch out for empty input buffer!; can't return negative number,
	 *		size_t may be unsigned).
	 */
	static inline size_t n_Decode(TBuffer &r_t_dest, const char *p_s_src);

	/**
	 *	@brief data decoding routine overload
	 *
	 *	Decodes contents of r_t_src buffer and stores it in p_dest buffer
	 *	(must be allocated to n_DecodedSize(n_src_size) bytes).
	 *
	 *	@param[in] n_dest_size is size of the destination buffer, in bytes
	 *	@param[out] p_dest is destination buffer
	 *	@param[in] r_t_src is buffer, containing input data
	 *
	 *	@return Returns number of bytes written to dest buffer on success, zero on failure
	 *		(watch out for empty input buffer!; can't return negative number,
	 *		size_t may be unsigned).
	 */
	static inline size_t n_Decode(size_t n_dest_size, void *p_dest, const TBuffer &r_t_src);

	/**
	 *	@brief data decoding routine overload
	 *
	 *	Decodes contents of r_s_src string and stores it in p_dest buffer
	 *	(must be allocated to n_DecodedSize(n_src_size) bytes).
	 *
	 *	@param[in] n_dest_size is size of the destination buffer, in bytes
	 *	@param[out] p_dest is destination buffer
	 *	@param[in] r_s_src is string, containing input data
	 *
	 *	@return Returns number of bytes written to dest buffer on success, zero on failure
	 *		(watch out for empty input buffer!; can't return negative number,
	 *		size_t may be unsigned).
	 */
	static inline size_t n_Decode(size_t n_dest_size, void *p_dest, const std::string &r_s_src);

	/**
	 *	@brief data decoding routine overload
	 *
	 *	Decodes contents of r_s_src string and stores it in p_dest buffer
	 *	(must be allocated to n_DecodedSize(n_src_size) bytes).
	 *
	 *	@param[in] n_dest_size is size of the destination buffer, in bytes
	 *	@param[out] p_dest is destination buffer
	 *	@param[in] p_s_src is null-terminated string, containing input data
	 *
	 *	@return Returns number of bytes written to dest buffer on success, zero on failure
	 *		(watch out for empty input buffer!; can't return negative number,
	 *		size_t may be unsigned).
	 */
	static inline size_t n_Decode(size_t n_dest_size, void *p_dest, const char *p_s_src);
};

/**
 *	@brief simple Modified Base-64 encoding class
 *
 *	@note This only performs encoding/decoding on buffers (not on streams)
 *		and decoding can only be performed on buffers, containing no
 *		whitespace / other characters, not belonging to Base-64 character set
 *		(making it faster, but also not mime-compliant).
 *	@note By default A-Za-z0-9+/ characters are used and no padding
 *		characters are inserted / removed (similar to UTF-7).
 */
class CModifiedBase64 {
public:
	/**
	 *	@brief simple inverse character-mapping table
	 */
	class CInverseTable {
		int m_p_decode[256]; /**< @brief inverse table data */

	public:
		/**
		 *	Default constructor; creates table of 256 indices,
		 *	containing positions of characters in p_s_encode_chars, or -1 in
		 *	case character with given ordinal value doesn't occur in p_s_encode_chars.
		 *
		 *	@param[in] p_s_encode_chars is array of 64 different characters, which
		 *		will be used to encode Base-64 (referred to as "alphabet" in RFC).
		 */
		CInverseTable(const char *p_s_encode_chars = CModifiedBase64::p_s_DefaultEncodeChars());

		/**
		 *	@return Returns table with 256 elements, when indexed by character codes,
		 *		yields zero-based index of a given character in the string, given to
		 *		constructor or -1 in case the string didn't contain such character.
		 *
		 *	@note Use of type int here is justified by fact that on most of today's
		 *		architectures it's faster to work with data on 4B boundaries.
		 */
		inline const int *p_Table() const;
	};

private:
	static const CInverseTable m_default_inverse_table;

public:
	/**
	 *	This normally equals to global size_t type,
	 *	however, in case __LARGE_BUFFER__ is defined,
	 *	uint64_t is used instead.
	 */
#ifdef __LARGE_BUFFER__
	typedef TBuffer::size_t size_t;
#endif // __LARGE_BUFFER__

	/**
	 *	@brief returns maximal size of data to be encoded
	 *
	 *	@return Returns maximal size of data to be encoded
	 *		(ratio of original and Base-64 encoded data is 6:8,
	 *		therefore for 4GB buffer limit, this returns 3GB,
	 *		which is largest possible amount of input data that
	 *		can be encoded to Base-64 without crossing 4BG limit).
	 */
	static inline size_t n_Max_EncodeSize();

	/**
	 *	@brief calculates size, needed for encoding output
	 *
	 *	@param[in] n_input is size of input data in bytes
	 *
	 *	@return Returns size of buffer (in bytes) to contain encoded data.
	 *
	 *	@note n_input must be less or equal to n_Max_EncodeSize()
	 */
	static inline size_t n_EncodedSize(size_t n_input);

	/**
	 *	@brief calculates size, needed for decoding output
	 *
	 *	@param[in] n_input is size of input (encoded) data in bytes
	 *
	 *	@return Returns size of buffer (in bytes) to contain decoded data.
	 */
	static inline size_t n_DecodedSize(size_t n_input);

	/**
	 *	@brief gets default Base-64 alphabet
	 *
	 *	@return Returns default encoding character table
	 *
	 *	@note The returned string contains 64 different (us-ascii)
	 *		characters that are used to represent 6-bit values
	 *		(referred to as "alphabet" in RFC)..
	 */
	static inline const char *p_s_DefaultEncodeChars();

	/**
	 *	@brief gets default Base-64 alphabet inverse
	 *
	 *	@return Returns default decoding character index table.
	 *
	 *	@note The returned table contains 256 entries, containing
	 *		zero-based character position of each of characters in
	 *		p_s_DefaultEncodeChars(), indexed by character codes.
	 *		table contains -1 for characters not being present in
	 *		p_s_DefaultEncodeChars().
	 *	@note Use of type int here is justified by fact that on most of today's
	 *		architectures it's faster to work with data on 4B boundaries.
	 */
	static inline const int *p_DefaultDecodeTable();

	/**
	 *	@brief Base-64 encoding routine
	 *
	 *	Generic data encoding routine; encodes contents of p_src_data buffer and stores
	 *	it in p_dest buffer.
	 *
	 *	@param[in] n_dest_size is size of the destination buffer, in bytes
	 *	@param[out] p_dest is destination buffer (must be allocated to n_EncodedSize(n_src_size) bytes)
	 *	@param[in] n_src_size is input data size (must be less or equal to n_Max_EncodeSize() bytes)
	 *	@param[in] p_src_data is buffer, containing data to be encoded
	 *	@param[in] p_s_encode_chars must be string containing 64 different characters,
	 *		preferably representable using some basic encoding such as iso-8859-1
	 *		so they can be printed / viewed by pretty much any kind of system.
	 *
	 *	@return Returns true on success, false on failure (input buffer size
	 *		  exceeding n_Max_EncodeSize()).
	 *
	 *	@note Inverse mapping table of p_s_encode_chars is required for decoding.
	 *	@note Encoding increases data size in 4:3 ratio, so there's n_Max_EncodeSize() limit
	 *		  (for x86 application it's 3GB, so the result wouldn't exceed 4GB).
	 */
	static bool Encode(size_t n_dest_size, void *p_dest, size_t n_src_size,
		const void *p_src_data, const char *p_s_encode_chars = p_s_DefaultEncodeChars());

	/**
	 *	@brief Base-64 decoding routine
	 *
	 *	Generic data decoding routine; decodes contents of p_src_data buffer and stores
	 *	it in p_dest buffer (must be allocated to n_DecodedSize(n_src_size) bytes).
	 *
	 *	@param[in] n_dest_size is size of the destination buffer, in bytes
	 *	@param[out] p_dest is destination buffer
	 *	@param[in] p_src_data is pointer to Base-64 encoded data
	 *	@param[in] n_src_size is size of input data buffer in bytes
	 *	@param[in] p_inverse_coding_table is pointer to inverse coding table, such as the one
	 *		returned by p_DefaultDecodeTable() (refer to function documentation
	 *		for further details).
	 *
	 *	@return Returns true on success, false on failure (invalid characters being
	 *		present in input buffer).
	 */
	static bool Decode(size_t n_dest_size, void *p_dest, size_t n_src_size, const void *p_src_data,
		const int *p_inverse_coding_table = p_DefaultDecodeTable());

	/**
	 *	@brief data encoding routine overload
	 *
	 *	Encodes contents of r_t_src buffer and stores it in p_dest buffer
	 *	(must be allocated to n_DecodedSize(n_src_size) bytes).
	 *
	 *	@param[in] n_dest_size is size of the destination buffer, in bytes
	 *	@param[out] p_dest is destination buffer
	 *	@param[in] r_t_src is input data buffer (must be at most n_Max_EncodeSize() bytes large)
	 *	@param[in] p_s_encode_chars must be string containing 64 different characters,
	 *		preferably representable using some basic encoding such as iso-8859-1
	 *		so they can be printed / viewed by pretty much any kind of system
	 *
	 *	@return Returns true on success, false on failure (input buffer size
	 *		  exceeding n_Max_EncodeSize()).
	 *
	 *	@note inverse mapping table of p_s_encode_chars is required for decoding
	 *	@note encoding increases data size in 4:3 ratio, so there's n_Max_EncodeSize() limit
	 *		(for x86 application it's 3GB, so the result wouldn't exceed 4GB)
	 */
	static inline bool Encode(size_t n_dest_size, void *p_dest, const TBuffer &r_t_src,
		const char *p_s_encode_chars = p_s_DefaultEncodeChars());

	/**
	 *	@brief data encoding routine overload
	 *
	 *	Encodes contents of r_t_src buffer and stores it in r_t_dest buffer
	 *	(rewrites original contents, does not concatenate).
	 *
	 *	@param[out] r_t_dest is destination buffer
	 *	@param[in] r_t_src is input data buffer (must be at most n_Max_EncodeSize() bytes large)
	 *	@param[in] p_s_encode_chars must be string containing 64 different characters,
	 *		preferably representable using some basic encoding such as iso-8859-1
	 *		so they can be printed / viewed by pretty much any kind of system
	 *
	 *	@return Returns true on success, false on failure (input buffer size
	 *		exceeding n_Max_EncodeSize()).
	 *
	 *	@note inverse mapping table of p_s_encode_chars is required for decoding
	 *	@note encoding increases data size in 4:3 ratio, so there's n_Max_EncodeSize() limit
	 *		(for x86 application it's 3GB, so the result wouldn't exceed 4GB)
	 */
	static inline bool Encode(TBuffer &r_t_dest, const TBuffer &r_t_src,
		const char *p_s_encode_chars = p_s_DefaultEncodeChars());

	/**
	 *	@brief data encoding routine overload
	 *
	 *	Encodes contents of r_t_src buffer and stores it in r_s_dest string
	 *	(rewrites original contents, does not concatenate).
	 *
	 *	@param[out] r_s_dest is destination string
	 *	@param[in] r_t_src is input data buffer (must be at most n_Max_EncodeSize() bytes large)
	 *	@param[in] p_s_encode_chars must be string containing 64 different characters,
	 *		preferably representable using some basic encoding such as iso-8859-1
	 *		so they can be printed / viewed by pretty much any kind of system
	 *
	 *	@return Returns true on success, false on failure (input buffer size
	 *		exceeding n_Max_EncodeSize()).
	 *
	 *	@note inverse mapping table of p_s_encode_chars is required for decoding
	 *	@note encoding increases data size in 4:3 ratio, so there's n_Max_EncodeSize() limit
	 *		(for x86 application it's 3GB, so the result wouldn't exceed 4GB)
	 */
	static inline bool Encode(std::string &r_s_dest, const TBuffer &r_t_src,
		const char *p_s_encode_chars = p_s_DefaultEncodeChars());

	/**
	 *	@brief data encoding routine overload
	 *
	 *	Encodes contents of p_src_data buffer and stores it in r_t_dest buffer
	 *	(rewrites original contents, does not concatenate).
	 *
	 *	@param[out] r_t_dest is destination buffer
	 *	@param[in] n_src_size is input data size (must be less or equal to n_Max_EncodeSize() bytes)
	 *	@param[in] p_src_data is buffer, containing data to be encoded
	 *	@param[in] p_s_encode_chars must be string containing 64 different characters,
	 *		preferably representable using some basic encoding such as iso-8859-1
	 *		so they can be printed / viewed by pretty much any kind of system
	 *
	 *	@return Returns true on success, false on failure (input buffer size
	 *		exceeding n_Max_EncodeSize()).
	 *
	 *	@note inverse mapping table of p_s_encode_chars is required for decoding
	 *	@note encoding increases data size in 4:3 ratio, so there's n_Max_EncodeSize() limit
	 *		(for x86 application it's 3GB, so the result wouldn't exceed 4GB)
	 */
	static inline bool Encode(TBuffer &r_t_dest, size_t n_src_size, const void *p_src_data,
		const char *p_s_encode_chars = p_s_DefaultEncodeChars());

	/**
	 *	@brief data encoding routine overload
	 *
	 *	Encodes contents of p_src_data buffer and stores it in r_s_dest string
	 *	(rewrites original contents, does not concatenate).
	 *
	 *	@param[out] r_s_dest is destination string
	 *	@param[in] n_src_size is input data size (must be less or equal to n_Max_EncodeSize() bytes)
	 *	@param[in] p_src_data is buffer, containing data to be encoded
	 *	@param[in] p_s_encode_chars must be string containing 64 different characters,
	 *		preferably representable using some basic encoding such as iso-8859-1
	 *		so they can be printed / viewed by pretty much any kind of system
	 *
	 *	@return Returns true on success, false on failure (input buffer size
	 *		exceeding n_Max_EncodeSize()).
	 *
	 *	@note inverse mapping table of p_s_encode_chars is required for decoding
	 *	@note encoding increases data size in 4:3 ratio, so there's n_Max_EncodeSize() limit
	 *		(for x86 application it's 3GB, so the result wouldn't exceed 4GB)
	 */
	static inline bool Encode(std::string &r_s_dest, size_t n_src_size, const void *p_src_data,
		const char *p_s_encode_chars = p_s_DefaultEncodeChars());

	/**
	 *	@brief data decoding routine overload
	 *
	 *	Decodes contents of r_t_src buffer and stores it in r_t_dest buffer
	 *	(rewrites original contents, does not concatenate).
	 *
	 *	@param[out] r_t_dest is destination buffer
	 *	@param[in] r_t_src is buffer, containing input data
	 *	@param[in] p_inverse_coding_table is pointer to inverse coding table, such as the one
	 *		returned by p_DefaultDecodeTable() (refer to function documentation
	 *		for further details)
	 *
	 *	@return Returns true on success, false on failure (not enough memory,
	 *		or invalid characters being present in input sequence).
	 *
	 *	@note There may be no whitespace characters in input data.
	 */
	static inline bool Decode(TBuffer &r_t_dest, const TBuffer &r_t_src,
		const int *p_inverse_coding_table = p_DefaultDecodeTable());

	/**
	 *	@brief data decoding routine overload
	 *
	 *	Decodes contents of p_src_data buffer and stores it in r_t_dest buffer
	 *	(rewrites original contents, does not concatenate).
	 *
	 *	@param[out] r_t_dest is destination buffer
	 *	@param[in] p_src_data is pointer to Base-64 encoded data
	 *	@param[in] n_src_size is size of input data buffer in bytes
	 *	@param[in] p_inverse_coding_table is pointer to inverse coding table, such as the one
	 *		returned by p_DefaultDecodeTable() (refer to function documentation
	 *		for further details)
	 *
	 *	@return Returns true on success, false on failure (not enough memory,
	 *		or invalid characters being present in input sequence).
	 *
	 *	@note There may be no whitespace characters in input data.
	 */
	static inline bool Decode(TBuffer &r_t_dest, size_t n_src_size, const void *p_src_data,
		const int *p_inverse_coding_table = p_DefaultDecodeTable());

	/**
	 *	@brief data decoding routine overload
	 *
	 *	Decodes contents of r_s_src string and stores it in r_t_dest buffer
	 *	(rewrites original contents, does not concatenate).
	 *
	 *	@param[out] r_t_dest is destination buffer
	 *	@param[in] r_s_src is string, containing input data
	 *	@param[in] p_inverse_coding_table is pointer to inverse coding table, such as the one
	 *		returned by p_DefaultDecodeTable() (refer to function documentation
	 *		for further details)
	 *
	 *	@return Returns true on success, false on failure (not enough memory,
	 *		or invalid characters being present in input sequence).
	 *
	 *	@note There may be no whitespace characters in input data.
	 */
	static inline bool Decode(TBuffer &r_t_dest, const std::string &r_s_src,
		const int *p_inverse_coding_table = p_DefaultDecodeTable());

	/**
	 *	@brief data decoding routine overload
	 *
	 *	Decodes contents of r_s_src string and stores it in r_t_dest buffer
	 *	(rewrites original contents, does not concatenate).
	 *
	 *	@param[out] r_t_dest is destination buffer
	 *	@param[in] p_s_src is null-terminated string, containing input data
	 *	@param[in] p_inverse_coding_table is pointer to inverse coding table, such as the one
	 *		returned by p_DefaultDecodeTable() (refer to function documentation
	 *		for further details)
	 *
	 *	@return Returns true on success, false on failure (not enough memory,
	 *		or invalid characters being present in input sequence).
	 *
	 *	@note There may be no whitespace characters in input data.
	 */
	static inline bool Decode(TBuffer &r_t_dest, const char *p_s_src,
		const int *p_inverse_coding_table = p_DefaultDecodeTable());

	/**
	 *	@brief data decoding routine overload
	 *
	 *	Decodes contents of r_t_src buffer and stores it in p_dest buffer
	 *	(must be allocated to n_DecodedSize(n_src_size) bytes).
	 *
	 *	@param[in] n_dest_size is size of the destination buffer, in bytes
	 *	@param[out] p_dest is destination buffer
	 *	@param[in] r_t_src is buffer, containing input data
	 *	@param[in] p_inverse_coding_table is pointer to inverse coding table, such as the one
	 *		returned by p_DefaultDecodeTable() (refer to function documentation
	 *		for further details)
	 *
	 *	@return Returns true on success, false on failure (invalid
	 *		characters being present in input sequence).
	 *
	 *	@note There may be no whitespace characters in input data.
	 */
	static inline bool Decode(size_t n_dest_size, void *p_dest, const TBuffer &r_t_src,
		const int *p_inverse_coding_table = p_DefaultDecodeTable());

	/**
	 *	@brief data decoding routine overload
	 *
	 *	Decodes contents of r_s_src string and stores it in p_dest buffer
	 *	(must be allocated to n_DecodedSize(n_src_size) bytes).
	 *
	 *	@param[in] n_dest_size is size of the destination buffer, in bytes
	 *	@param[out] p_dest is destination buffer
	 *	@param[in] r_s_src is string, containing input data
	 *	@param[in] p_inverse_coding_table is pointer to inverse coding table, such as the one
	 *		returned by p_DefaultDecodeTable() (refer to function documentation
	 *		for further details)
	 *
	 *	@return Returns true on success, false on failure (invalid
	 *		characters being present in input sequence).
	 *
	 *	@note There may be no whitespace characters in input data.
	 */
	static inline bool Decode(size_t n_dest_size, void *p_dest, const std::string &r_s_src,
		const int *p_inverse_coding_table = p_DefaultDecodeTable());

	/**
	 *	@brief data decoding routine overload
	 *
	 *	Decodes contents of r_s_src string and stores it in p_dest buffer
	 *	(must be allocated to n_DecodedSize(n_src_size) bytes).
	 *
	 *	@param[in] n_dest_size is size of the destination buffer, in bytes
	 *	@param[out] p_dest is destination buffer
	 *	@param[in] p_s_src is null-terminated string, containing input data
	 *	@param[in] p_inverse_coding_table is pointer to inverse coding table, such as the one
	 *		returned by p_DefaultDecodeTable() (refer to function documentation
	 *		for further details)
	 *
	 *	@return Returns true on success, false on failure (invalid
	 *		characters being present in input sequence).
	 *
	 *	@note There may be no whitespace characters in input data.
	 */
	static inline bool Decode(size_t n_dest_size, void *p_dest, const char *p_s_src,
		const int *p_inverse_coding_table = p_DefaultDecodeTable());
};

#include "Base64.inl"

#endif // !__BASE64_CODING_INCLUDED
