annotate modules/base64/base64.hpp @ 575:0f6501d6df34

Base64: reduce column limit
author David Demelier <markand@malikania.fr>
date Tue, 19 Jul 2016 22:35:42 +0200
parents f48bb09bccc7
children
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
517
00f1789a49fa Base64: resurrection
David Demelier <markand@malikania.fr>
parents:
diff changeset
1 /*
00f1789a49fa Base64: resurrection
David Demelier <markand@malikania.fr>
parents:
diff changeset
2 * base64.hpp -- base64 encoding and decoding
00f1789a49fa Base64: resurrection
David Demelier <markand@malikania.fr>
parents:
diff changeset
3 *
00f1789a49fa Base64: resurrection
David Demelier <markand@malikania.fr>
parents:
diff changeset
4 * Copyright (c) 2013-2016 David Demelier <markand@malikania.fr>
00f1789a49fa Base64: resurrection
David Demelier <markand@malikania.fr>
parents:
diff changeset
5 *
00f1789a49fa Base64: resurrection
David Demelier <markand@malikania.fr>
parents:
diff changeset
6 * Permission to use, copy, modify, and/or distribute this software for any
00f1789a49fa Base64: resurrection
David Demelier <markand@malikania.fr>
parents:
diff changeset
7 * purpose with or without fee is hereby granted, provided that the above
00f1789a49fa Base64: resurrection
David Demelier <markand@malikania.fr>
parents:
diff changeset
8 * copyright notice and this permission notice appear in all copies.
00f1789a49fa Base64: resurrection
David Demelier <markand@malikania.fr>
parents:
diff changeset
9 *
00f1789a49fa Base64: resurrection
David Demelier <markand@malikania.fr>
parents:
diff changeset
10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
00f1789a49fa Base64: resurrection
David Demelier <markand@malikania.fr>
parents:
diff changeset
11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
00f1789a49fa Base64: resurrection
David Demelier <markand@malikania.fr>
parents:
diff changeset
12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
00f1789a49fa Base64: resurrection
David Demelier <markand@malikania.fr>
parents:
diff changeset
13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
00f1789a49fa Base64: resurrection
David Demelier <markand@malikania.fr>
parents:
diff changeset
14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
00f1789a49fa Base64: resurrection
David Demelier <markand@malikania.fr>
parents:
diff changeset
15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
00f1789a49fa Base64: resurrection
David Demelier <markand@malikania.fr>
parents:
diff changeset
16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
00f1789a49fa Base64: resurrection
David Demelier <markand@malikania.fr>
parents:
diff changeset
17 */
00f1789a49fa Base64: resurrection
David Demelier <markand@malikania.fr>
parents:
diff changeset
18
00f1789a49fa Base64: resurrection
David Demelier <markand@malikania.fr>
parents:
diff changeset
19 #ifndef BASE64_HPP
00f1789a49fa Base64: resurrection
David Demelier <markand@malikania.fr>
parents:
diff changeset
20 #define BASE64_HPP
00f1789a49fa Base64: resurrection
David Demelier <markand@malikania.fr>
parents:
diff changeset
21
00f1789a49fa Base64: resurrection
David Demelier <markand@malikania.fr>
parents:
diff changeset
22 /**
00f1789a49fa Base64: resurrection
David Demelier <markand@malikania.fr>
parents:
diff changeset
23 * \file base64.hpp
00f1789a49fa Base64: resurrection
David Demelier <markand@malikania.fr>
parents:
diff changeset
24 * \brief Base64 encoding and decoding.
00f1789a49fa Base64: resurrection
David Demelier <markand@malikania.fr>
parents:
diff changeset
25 * \author David Demelier <markand@malikania.fr>
00f1789a49fa Base64: resurrection
David Demelier <markand@malikania.fr>
parents:
diff changeset
26 */
00f1789a49fa Base64: resurrection
David Demelier <markand@malikania.fr>
parents:
diff changeset
27
00f1789a49fa Base64: resurrection
David Demelier <markand@malikania.fr>
parents:
diff changeset
28 /**
00f1789a49fa Base64: resurrection
David Demelier <markand@malikania.fr>
parents:
diff changeset
29 * \page Base64 Base64
00f1789a49fa Base64: resurrection
David Demelier <markand@malikania.fr>
parents:
diff changeset
30 * \brief Base64 encoding and decoding.
00f1789a49fa Base64: resurrection
David Demelier <markand@malikania.fr>
parents:
diff changeset
31 *
575
0f6501d6df34 Base64: reduce column limit
David Demelier <markand@malikania.fr>
parents: 548
diff changeset
32 * The %base64 library let you encode and decode %base64 data from std::string
0f6501d6df34 Base64: reduce column limit
David Demelier <markand@malikania.fr>
parents: 548
diff changeset
33 * and iterators.
517
00f1789a49fa Base64: resurrection
David Demelier <markand@malikania.fr>
parents:
diff changeset
34 *
00f1789a49fa Base64: resurrection
David Demelier <markand@malikania.fr>
parents:
diff changeset
35 * ## Encoding
00f1789a49fa Base64: resurrection
David Demelier <markand@malikania.fr>
parents:
diff changeset
36 *
00f1789a49fa Base64: resurrection
David Demelier <markand@malikania.fr>
parents:
diff changeset
37 * You can encode like this:
00f1789a49fa Base64: resurrection
David Demelier <markand@malikania.fr>
parents:
diff changeset
38 *
00f1789a49fa Base64: resurrection
David Demelier <markand@malikania.fr>
parents:
diff changeset
39 * ````cpp
00f1789a49fa Base64: resurrection
David Demelier <markand@malikania.fr>
parents:
diff changeset
40 * std::string b64 = base64::encode("Hello world!");
00f1789a49fa Base64: resurrection
David Demelier <markand@malikania.fr>
parents:
diff changeset
41 * ````
00f1789a49fa Base64: resurrection
David Demelier <markand@malikania.fr>
parents:
diff changeset
42 *
00f1789a49fa Base64: resurrection
David Demelier <markand@malikania.fr>
parents:
diff changeset
43 * ## Decoding
00f1789a49fa Base64: resurrection
David Demelier <markand@malikania.fr>
parents:
diff changeset
44 *
00f1789a49fa Base64: resurrection
David Demelier <markand@malikania.fr>
parents:
diff changeset
45 * And you can decode like this:
00f1789a49fa Base64: resurrection
David Demelier <markand@malikania.fr>
parents:
diff changeset
46 *
00f1789a49fa Base64: resurrection
David Demelier <markand@malikania.fr>
parents:
diff changeset
47 * ````
00f1789a49fa Base64: resurrection
David Demelier <markand@malikania.fr>
parents:
diff changeset
48 * try {
548
f48bb09bccc7 Misc: huge cleanup, switch to spaces
David Demelier <markand@malikania.fr>
parents: 517
diff changeset
49 * std::string text = base64::decode(msg);
517
00f1789a49fa Base64: resurrection
David Demelier <markand@malikania.fr>
parents:
diff changeset
50 * } catch (const std::exception &ex) {
548
f48bb09bccc7 Misc: huge cleanup, switch to spaces
David Demelier <markand@malikania.fr>
parents: 517
diff changeset
51 * std::cerr << ex.what() << std::endl;
517
00f1789a49fa Base64: resurrection
David Demelier <markand@malikania.fr>
parents:
diff changeset
52 * }
00f1789a49fa Base64: resurrection
David Demelier <markand@malikania.fr>
parents:
diff changeset
53 * ````
00f1789a49fa Base64: resurrection
David Demelier <markand@malikania.fr>
parents:
diff changeset
54 */
00f1789a49fa Base64: resurrection
David Demelier <markand@malikania.fr>
parents:
diff changeset
55
00f1789a49fa Base64: resurrection
David Demelier <markand@malikania.fr>
parents:
diff changeset
56 #include <cassert>
00f1789a49fa Base64: resurrection
David Demelier <markand@malikania.fr>
parents:
diff changeset
57 #include <cctype>
00f1789a49fa Base64: resurrection
David Demelier <markand@malikania.fr>
parents:
diff changeset
58 #include <stdexcept>
00f1789a49fa Base64: resurrection
David Demelier <markand@malikania.fr>
parents:
diff changeset
59 #include <string>
00f1789a49fa Base64: resurrection
David Demelier <markand@malikania.fr>
parents:
diff changeset
60
00f1789a49fa Base64: resurrection
David Demelier <markand@malikania.fr>
parents:
diff changeset
61 /**
00f1789a49fa Base64: resurrection
David Demelier <markand@malikania.fr>
parents:
diff changeset
62 * \brief main %base64 namespace.
00f1789a49fa Base64: resurrection
David Demelier <markand@malikania.fr>
parents:
diff changeset
63 */
00f1789a49fa Base64: resurrection
David Demelier <markand@malikania.fr>
parents:
diff changeset
64 namespace base64 {
00f1789a49fa Base64: resurrection
David Demelier <markand@malikania.fr>
parents:
diff changeset
65
00f1789a49fa Base64: resurrection
David Demelier <markand@malikania.fr>
parents:
diff changeset
66 /**
00f1789a49fa Base64: resurrection
David Demelier <markand@malikania.fr>
parents:
diff changeset
67 * Check if the character is a %base64 character, A-Za-z0-9 and +/.
00f1789a49fa Base64: resurrection
David Demelier <markand@malikania.fr>
parents:
diff changeset
68 *
00f1789a49fa Base64: resurrection
David Demelier <markand@malikania.fr>
parents:
diff changeset
69 * \param ch the character to test
00f1789a49fa Base64: resurrection
David Demelier <markand@malikania.fr>
parents:
diff changeset
70 * \return true if valid
00f1789a49fa Base64: resurrection
David Demelier <markand@malikania.fr>
parents:
diff changeset
71 */
00f1789a49fa Base64: resurrection
David Demelier <markand@malikania.fr>
parents:
diff changeset
72 inline bool isBase64(char ch) noexcept
00f1789a49fa Base64: resurrection
David Demelier <markand@malikania.fr>
parents:
diff changeset
73 {
548
f48bb09bccc7 Misc: huge cleanup, switch to spaces
David Demelier <markand@malikania.fr>
parents: 517
diff changeset
74 return std::isalnum(ch) != 0 || ch == '+' || ch == '/';
517
00f1789a49fa Base64: resurrection
David Demelier <markand@malikania.fr>
parents:
diff changeset
75 }
00f1789a49fa Base64: resurrection
David Demelier <markand@malikania.fr>
parents:
diff changeset
76
00f1789a49fa Base64: resurrection
David Demelier <markand@malikania.fr>
parents:
diff changeset
77 /**
575
0f6501d6df34 Base64: reduce column limit
David Demelier <markand@malikania.fr>
parents: 548
diff changeset
78 * Check if the given character is a valid character in %base64 string,
0f6501d6df34 Base64: reduce column limit
David Demelier <markand@malikania.fr>
parents: 548
diff changeset
79 * including '='.
517
00f1789a49fa Base64: resurrection
David Demelier <markand@malikania.fr>
parents:
diff changeset
80 *
00f1789a49fa Base64: resurrection
David Demelier <markand@malikania.fr>
parents:
diff changeset
81 * \param ch the character
00f1789a49fa Base64: resurrection
David Demelier <markand@malikania.fr>
parents:
diff changeset
82 * \return true if the character is valid
00f1789a49fa Base64: resurrection
David Demelier <markand@malikania.fr>
parents:
diff changeset
83 */
00f1789a49fa Base64: resurrection
David Demelier <markand@malikania.fr>
parents:
diff changeset
84 inline bool isValid(char ch) noexcept
00f1789a49fa Base64: resurrection
David Demelier <markand@malikania.fr>
parents:
diff changeset
85 {
548
f48bb09bccc7 Misc: huge cleanup, switch to spaces
David Demelier <markand@malikania.fr>
parents: 517
diff changeset
86 return isBase64(ch) || ch == '=';
517
00f1789a49fa Base64: resurrection
David Demelier <markand@malikania.fr>
parents:
diff changeset
87 }
00f1789a49fa Base64: resurrection
David Demelier <markand@malikania.fr>
parents:
diff changeset
88
00f1789a49fa Base64: resurrection
David Demelier <markand@malikania.fr>
parents:
diff changeset
89 /**
00f1789a49fa Base64: resurrection
David Demelier <markand@malikania.fr>
parents:
diff changeset
90 * Get the %base64 character from the 6-bits value.
00f1789a49fa Base64: resurrection
David Demelier <markand@malikania.fr>
parents:
diff changeset
91 *
00f1789a49fa Base64: resurrection
David Demelier <markand@malikania.fr>
parents:
diff changeset
92 * \pre value must be valid (< 64)
00f1789a49fa Base64: resurrection
David Demelier <markand@malikania.fr>
parents:
diff changeset
93 * \param value the value
00f1789a49fa Base64: resurrection
David Demelier <markand@malikania.fr>
parents:
diff changeset
94 * \return the %base64 character for value
00f1789a49fa Base64: resurrection
David Demelier <markand@malikania.fr>
parents:
diff changeset
95 */
00f1789a49fa Base64: resurrection
David Demelier <markand@malikania.fr>
parents:
diff changeset
96 inline char lookup(unsigned char value) noexcept
00f1789a49fa Base64: resurrection
David Demelier <markand@malikania.fr>
parents:
diff changeset
97 {
548
f48bb09bccc7 Misc: huge cleanup, switch to spaces
David Demelier <markand@malikania.fr>
parents: 517
diff changeset
98 static const char *table = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
517
00f1789a49fa Base64: resurrection
David Demelier <markand@malikania.fr>
parents:
diff changeset
99
548
f48bb09bccc7 Misc: huge cleanup, switch to spaces
David Demelier <markand@malikania.fr>
parents: 517
diff changeset
100 assert(value < 64);
517
00f1789a49fa Base64: resurrection
David Demelier <markand@malikania.fr>
parents:
diff changeset
101
548
f48bb09bccc7 Misc: huge cleanup, switch to spaces
David Demelier <markand@malikania.fr>
parents: 517
diff changeset
102 return table[value];
517
00f1789a49fa Base64: resurrection
David Demelier <markand@malikania.fr>
parents:
diff changeset
103 }
00f1789a49fa Base64: resurrection
David Demelier <markand@malikania.fr>
parents:
diff changeset
104
00f1789a49fa Base64: resurrection
David Demelier <markand@malikania.fr>
parents:
diff changeset
105 /**
00f1789a49fa Base64: resurrection
David Demelier <markand@malikania.fr>
parents:
diff changeset
106 * Get the integer value from the %base64 character.
00f1789a49fa Base64: resurrection
David Demelier <markand@malikania.fr>
parents:
diff changeset
107 *
00f1789a49fa Base64: resurrection
David Demelier <markand@malikania.fr>
parents:
diff changeset
108 * \pre isBase64(ch)
00f1789a49fa Base64: resurrection
David Demelier <markand@malikania.fr>
parents:
diff changeset
109 * \param ch the %base64 character
00f1789a49fa Base64: resurrection
David Demelier <markand@malikania.fr>
parents:
diff changeset
110 * \return the integer value for the %base64 character ch
00f1789a49fa Base64: resurrection
David Demelier <markand@malikania.fr>
parents:
diff changeset
111 * ````
00f1789a49fa Base64: resurrection
David Demelier <markand@malikania.fr>
parents:
diff changeset
112 * auto b64 = base64::rlookup('D') // 3
00f1789a49fa Base64: resurrection
David Demelier <markand@malikania.fr>
parents:
diff changeset
113 * ````
00f1789a49fa Base64: resurrection
David Demelier <markand@malikania.fr>
parents:
diff changeset
114 */
00f1789a49fa Base64: resurrection
David Demelier <markand@malikania.fr>
parents:
diff changeset
115 inline unsigned char rlookup(char ch) noexcept
00f1789a49fa Base64: resurrection
David Demelier <markand@malikania.fr>
parents:
diff changeset
116 {
548
f48bb09bccc7 Misc: huge cleanup, switch to spaces
David Demelier <markand@malikania.fr>
parents: 517
diff changeset
117 assert(isBase64(ch));
517
00f1789a49fa Base64: resurrection
David Demelier <markand@malikania.fr>
parents:
diff changeset
118
548
f48bb09bccc7 Misc: huge cleanup, switch to spaces
David Demelier <markand@malikania.fr>
parents: 517
diff changeset
119 if (ch >= '0' && ch <= '9')
f48bb09bccc7 Misc: huge cleanup, switch to spaces
David Demelier <markand@malikania.fr>
parents: 517
diff changeset
120 return static_cast<unsigned char>(ch + 4);
f48bb09bccc7 Misc: huge cleanup, switch to spaces
David Demelier <markand@malikania.fr>
parents: 517
diff changeset
121 if (ch >= 'A' && ch <= 'Z')
f48bb09bccc7 Misc: huge cleanup, switch to spaces
David Demelier <markand@malikania.fr>
parents: 517
diff changeset
122 return static_cast<unsigned char>(ch - 65);
f48bb09bccc7 Misc: huge cleanup, switch to spaces
David Demelier <markand@malikania.fr>
parents: 517
diff changeset
123 if (ch >= 'a' && ch <= 'z')
f48bb09bccc7 Misc: huge cleanup, switch to spaces
David Demelier <markand@malikania.fr>
parents: 517
diff changeset
124 return static_cast<unsigned char>(ch - 71);
517
00f1789a49fa Base64: resurrection
David Demelier <markand@malikania.fr>
parents:
diff changeset
125
548
f48bb09bccc7 Misc: huge cleanup, switch to spaces
David Demelier <markand@malikania.fr>
parents: 517
diff changeset
126 return (ch == '+') ? 62U : 63U;
517
00f1789a49fa Base64: resurrection
David Demelier <markand@malikania.fr>
parents:
diff changeset
127 }
00f1789a49fa Base64: resurrection
David Demelier <markand@malikania.fr>
parents:
diff changeset
128
00f1789a49fa Base64: resurrection
David Demelier <markand@malikania.fr>
parents:
diff changeset
129 /**
00f1789a49fa Base64: resurrection
David Demelier <markand@malikania.fr>
parents:
diff changeset
130 * Encode the input to the output.
00f1789a49fa Base64: resurrection
David Demelier <markand@malikania.fr>
parents:
diff changeset
131 *
00f1789a49fa Base64: resurrection
David Demelier <markand@malikania.fr>
parents:
diff changeset
132 * Requirements:
00f1789a49fa Base64: resurrection
David Demelier <markand@malikania.fr>
parents:
diff changeset
133 * - **InputIt** must be [InputIterator](http://en.cppreference.com/w/cpp/concept/InputIterator)
00f1789a49fa Base64: resurrection
David Demelier <markand@malikania.fr>
parents:
diff changeset
134 * - **OutputIt** must be [OutputIterator](http://en.cppreference.com/w/cpp/concept/OutputIterator)
00f1789a49fa Base64: resurrection
David Demelier <markand@malikania.fr>
parents:
diff changeset
135 *
00f1789a49fa Base64: resurrection
David Demelier <markand@malikania.fr>
parents:
diff changeset
136 * \param input the beginning
00f1789a49fa Base64: resurrection
David Demelier <markand@malikania.fr>
parents:
diff changeset
137 * \param end the end of the data
00f1789a49fa Base64: resurrection
David Demelier <markand@malikania.fr>
parents:
diff changeset
138 * \param output the output destination
00f1789a49fa Base64: resurrection
David Demelier <markand@malikania.fr>
parents:
diff changeset
139 * \return output
00f1789a49fa Base64: resurrection
David Demelier <markand@malikania.fr>
parents:
diff changeset
140 */
00f1789a49fa Base64: resurrection
David Demelier <markand@malikania.fr>
parents:
diff changeset
141 template <typename InputIt, typename OutputIt>
00f1789a49fa Base64: resurrection
David Demelier <markand@malikania.fr>
parents:
diff changeset
142 OutputIt encode(InputIt input, InputIt end, OutputIt output)
00f1789a49fa Base64: resurrection
David Demelier <markand@malikania.fr>
parents:
diff changeset
143 {
548
f48bb09bccc7 Misc: huge cleanup, switch to spaces
David Demelier <markand@malikania.fr>
parents: 517
diff changeset
144 while (input != end) {
f48bb09bccc7 Misc: huge cleanup, switch to spaces
David Demelier <markand@malikania.fr>
parents: 517
diff changeset
145 char inputbuf[3] = { 0, 0, 0 };
f48bb09bccc7 Misc: huge cleanup, switch to spaces
David Demelier <markand@malikania.fr>
parents: 517
diff changeset
146 int count;
517
00f1789a49fa Base64: resurrection
David Demelier <markand@malikania.fr>
parents:
diff changeset
147
548
f48bb09bccc7 Misc: huge cleanup, switch to spaces
David Demelier <markand@malikania.fr>
parents: 517
diff changeset
148 for (count = 0; count < 3 && input != end; ++count)
f48bb09bccc7 Misc: huge cleanup, switch to spaces
David Demelier <markand@malikania.fr>
parents: 517
diff changeset
149 inputbuf[count] = *input++;
517
00f1789a49fa Base64: resurrection
David Demelier <markand@malikania.fr>
parents:
diff changeset
150
548
f48bb09bccc7 Misc: huge cleanup, switch to spaces
David Demelier <markand@malikania.fr>
parents: 517
diff changeset
151 *output++ = lookup(inputbuf[0] >> 2 & 0x3f);
f48bb09bccc7 Misc: huge cleanup, switch to spaces
David Demelier <markand@malikania.fr>
parents: 517
diff changeset
152 *output++ = lookup((inputbuf[0] << 4 & 0x3f) | (inputbuf[1] >> 4 & 0x0f));
f48bb09bccc7 Misc: huge cleanup, switch to spaces
David Demelier <markand@malikania.fr>
parents: 517
diff changeset
153 *output++ = (count < 2) ? '=' : lookup((inputbuf[1] << 2 & 0x3c) | (inputbuf[2] >> 6 & 0x03));
f48bb09bccc7 Misc: huge cleanup, switch to spaces
David Demelier <markand@malikania.fr>
parents: 517
diff changeset
154 *output++ = (count < 3) ? '=' : lookup(inputbuf[2] & 0x3f);
f48bb09bccc7 Misc: huge cleanup, switch to spaces
David Demelier <markand@malikania.fr>
parents: 517
diff changeset
155 }
517
00f1789a49fa Base64: resurrection
David Demelier <markand@malikania.fr>
parents:
diff changeset
156
548
f48bb09bccc7 Misc: huge cleanup, switch to spaces
David Demelier <markand@malikania.fr>
parents: 517
diff changeset
157 return output;
517
00f1789a49fa Base64: resurrection
David Demelier <markand@malikania.fr>
parents:
diff changeset
158 }
00f1789a49fa Base64: resurrection
David Demelier <markand@malikania.fr>
parents:
diff changeset
159
00f1789a49fa Base64: resurrection
David Demelier <markand@malikania.fr>
parents:
diff changeset
160 /**
00f1789a49fa Base64: resurrection
David Demelier <markand@malikania.fr>
parents:
diff changeset
161 * Decode the input to the output.
00f1789a49fa Base64: resurrection
David Demelier <markand@malikania.fr>
parents:
diff changeset
162 *
00f1789a49fa Base64: resurrection
David Demelier <markand@malikania.fr>
parents:
diff changeset
163 * Requirements:
00f1789a49fa Base64: resurrection
David Demelier <markand@malikania.fr>
parents:
diff changeset
164 * - **InputIt** must be [InputIterator](http://en.cppreference.com/w/cpp/concept/InputIterator)
00f1789a49fa Base64: resurrection
David Demelier <markand@malikania.fr>
parents:
diff changeset
165 * - **OutputIt** must be [OutputIterator](http://en.cppreference.com/w/cpp/concept/OutputIterator)
00f1789a49fa Base64: resurrection
David Demelier <markand@malikania.fr>
parents:
diff changeset
166 *
00f1789a49fa Base64: resurrection
David Demelier <markand@malikania.fr>
parents:
diff changeset
167 * \param input the beginning
00f1789a49fa Base64: resurrection
David Demelier <markand@malikania.fr>
parents:
diff changeset
168 * \param end the end of the data
00f1789a49fa Base64: resurrection
David Demelier <markand@malikania.fr>
parents:
diff changeset
169 * \param output the output destination
00f1789a49fa Base64: resurrection
David Demelier <markand@malikania.fr>
parents:
diff changeset
170 * \return output
00f1789a49fa Base64: resurrection
David Demelier <markand@malikania.fr>
parents:
diff changeset
171 * \throw std::invalid_argument on bad %base64 string
00f1789a49fa Base64: resurrection
David Demelier <markand@malikania.fr>
parents:
diff changeset
172 */
00f1789a49fa Base64: resurrection
David Demelier <markand@malikania.fr>
parents:
diff changeset
173 template <typename InputIt, typename OutputIt>
00f1789a49fa Base64: resurrection
David Demelier <markand@malikania.fr>
parents:
diff changeset
174 OutputIt decode(InputIt input, InputIt end, OutputIt output)
00f1789a49fa Base64: resurrection
David Demelier <markand@malikania.fr>
parents:
diff changeset
175 {
548
f48bb09bccc7 Misc: huge cleanup, switch to spaces
David Demelier <markand@malikania.fr>
parents: 517
diff changeset
176 while (input != end) {
f48bb09bccc7 Misc: huge cleanup, switch to spaces
David Demelier <markand@malikania.fr>
parents: 517
diff changeset
177 char inputbuf[4] = { -1, -1, -1, -1 };
f48bb09bccc7 Misc: huge cleanup, switch to spaces
David Demelier <markand@malikania.fr>
parents: 517
diff changeset
178 int count;
517
00f1789a49fa Base64: resurrection
David Demelier <markand@malikania.fr>
parents:
diff changeset
179
548
f48bb09bccc7 Misc: huge cleanup, switch to spaces
David Demelier <markand@malikania.fr>
parents: 517
diff changeset
180 for (count = 0; count < 4 && input != end; ++count) {
f48bb09bccc7 Misc: huge cleanup, switch to spaces
David Demelier <markand@malikania.fr>
parents: 517
diff changeset
181 // Check if the character is valid and get its value.
f48bb09bccc7 Misc: huge cleanup, switch to spaces
David Demelier <markand@malikania.fr>
parents: 517
diff changeset
182 if ((*input == '=' && count <= 1) || !isValid(*input))
f48bb09bccc7 Misc: huge cleanup, switch to spaces
David Demelier <markand@malikania.fr>
parents: 517
diff changeset
183 throw std::invalid_argument("invalid base64 string");
f48bb09bccc7 Misc: huge cleanup, switch to spaces
David Demelier <markand@malikania.fr>
parents: 517
diff changeset
184 if (isBase64(*input))
f48bb09bccc7 Misc: huge cleanup, switch to spaces
David Demelier <markand@malikania.fr>
parents: 517
diff changeset
185 inputbuf[count] = static_cast<char>(rlookup(*input));
517
00f1789a49fa Base64: resurrection
David Demelier <markand@malikania.fr>
parents:
diff changeset
186
548
f48bb09bccc7 Misc: huge cleanup, switch to spaces
David Demelier <markand@malikania.fr>
parents: 517
diff changeset
187 input++;
f48bb09bccc7 Misc: huge cleanup, switch to spaces
David Demelier <markand@malikania.fr>
parents: 517
diff changeset
188 }
517
00f1789a49fa Base64: resurrection
David Demelier <markand@malikania.fr>
parents:
diff changeset
189
548
f48bb09bccc7 Misc: huge cleanup, switch to spaces
David Demelier <markand@malikania.fr>
parents: 517
diff changeset
190 if (count != 4)
f48bb09bccc7 Misc: huge cleanup, switch to spaces
David Demelier <markand@malikania.fr>
parents: 517
diff changeset
191 throw std::invalid_argument("truncated string");
517
00f1789a49fa Base64: resurrection
David Demelier <markand@malikania.fr>
parents:
diff changeset
192
548
f48bb09bccc7 Misc: huge cleanup, switch to spaces
David Demelier <markand@malikania.fr>
parents: 517
diff changeset
193 *output++ = static_cast<char>(((inputbuf[0] << 2) & 0xfc) | ((inputbuf[1] >> 4) & 0x03));
517
00f1789a49fa Base64: resurrection
David Demelier <markand@malikania.fr>
parents:
diff changeset
194
548
f48bb09bccc7 Misc: huge cleanup, switch to spaces
David Demelier <markand@malikania.fr>
parents: 517
diff changeset
195 if (inputbuf[2] != -1)
f48bb09bccc7 Misc: huge cleanup, switch to spaces
David Demelier <markand@malikania.fr>
parents: 517
diff changeset
196 *output++ = static_cast<char>(((inputbuf[1] << 4) & 0xf0) | ((inputbuf[2] >> 2) & 0x0f));
f48bb09bccc7 Misc: huge cleanup, switch to spaces
David Demelier <markand@malikania.fr>
parents: 517
diff changeset
197 if (inputbuf[3] != -1) {
f48bb09bccc7 Misc: huge cleanup, switch to spaces
David Demelier <markand@malikania.fr>
parents: 517
diff changeset
198 // "XY=Z" is not allowed.
f48bb09bccc7 Misc: huge cleanup, switch to spaces
David Demelier <markand@malikania.fr>
parents: 517
diff changeset
199 if (inputbuf[2] == -1)
f48bb09bccc7 Misc: huge cleanup, switch to spaces
David Demelier <markand@malikania.fr>
parents: 517
diff changeset
200 throw std::invalid_argument("invalid base64 string");
517
00f1789a49fa Base64: resurrection
David Demelier <markand@malikania.fr>
parents:
diff changeset
201
548
f48bb09bccc7 Misc: huge cleanup, switch to spaces
David Demelier <markand@malikania.fr>
parents: 517
diff changeset
202 *output++ = static_cast<char>(((inputbuf[2] << 6) & 0xc0) | (inputbuf[3] & 0x3f));
f48bb09bccc7 Misc: huge cleanup, switch to spaces
David Demelier <markand@malikania.fr>
parents: 517
diff changeset
203 }
f48bb09bccc7 Misc: huge cleanup, switch to spaces
David Demelier <markand@malikania.fr>
parents: 517
diff changeset
204 }
517
00f1789a49fa Base64: resurrection
David Demelier <markand@malikania.fr>
parents:
diff changeset
205
548
f48bb09bccc7 Misc: huge cleanup, switch to spaces
David Demelier <markand@malikania.fr>
parents: 517
diff changeset
206 return output;
517
00f1789a49fa Base64: resurrection
David Demelier <markand@malikania.fr>
parents:
diff changeset
207 }
00f1789a49fa Base64: resurrection
David Demelier <markand@malikania.fr>
parents:
diff changeset
208
00f1789a49fa Base64: resurrection
David Demelier <markand@malikania.fr>
parents:
diff changeset
209 /**
00f1789a49fa Base64: resurrection
David Demelier <markand@malikania.fr>
parents:
diff changeset
210 * Encode a string.
00f1789a49fa Base64: resurrection
David Demelier <markand@malikania.fr>
parents:
diff changeset
211 *
00f1789a49fa Base64: resurrection
David Demelier <markand@malikania.fr>
parents:
diff changeset
212 * \param input the input string
00f1789a49fa Base64: resurrection
David Demelier <markand@malikania.fr>
parents:
diff changeset
213 * \return the %base64 formatted string
00f1789a49fa Base64: resurrection
David Demelier <markand@malikania.fr>
parents:
diff changeset
214 */
00f1789a49fa Base64: resurrection
David Demelier <markand@malikania.fr>
parents:
diff changeset
215 inline std::string encode(const std::string &input)
00f1789a49fa Base64: resurrection
David Demelier <markand@malikania.fr>
parents:
diff changeset
216 {
548
f48bb09bccc7 Misc: huge cleanup, switch to spaces
David Demelier <markand@malikania.fr>
parents: 517
diff changeset
217 std::string result;
517
00f1789a49fa Base64: resurrection
David Demelier <markand@malikania.fr>
parents:
diff changeset
218
548
f48bb09bccc7 Misc: huge cleanup, switch to spaces
David Demelier <markand@malikania.fr>
parents: 517
diff changeset
219 encode(input.begin(), input.end(), std::back_inserter(result));
517
00f1789a49fa Base64: resurrection
David Demelier <markand@malikania.fr>
parents:
diff changeset
220
548
f48bb09bccc7 Misc: huge cleanup, switch to spaces
David Demelier <markand@malikania.fr>
parents: 517
diff changeset
221 return result;
517
00f1789a49fa Base64: resurrection
David Demelier <markand@malikania.fr>
parents:
diff changeset
222 }
00f1789a49fa Base64: resurrection
David Demelier <markand@malikania.fr>
parents:
diff changeset
223
00f1789a49fa Base64: resurrection
David Demelier <markand@malikania.fr>
parents:
diff changeset
224 /**
00f1789a49fa Base64: resurrection
David Demelier <markand@malikania.fr>
parents:
diff changeset
225 * Decode a string.
00f1789a49fa Base64: resurrection
David Demelier <markand@malikania.fr>
parents:
diff changeset
226 *
00f1789a49fa Base64: resurrection
David Demelier <markand@malikania.fr>
parents:
diff changeset
227 * \param input the %base64 formatted string
00f1789a49fa Base64: resurrection
David Demelier <markand@malikania.fr>
parents:
diff changeset
228 * \return the original string
00f1789a49fa Base64: resurrection
David Demelier <markand@malikania.fr>
parents:
diff changeset
229 * \throw std::invalid_argument on bad %base64 string
00f1789a49fa Base64: resurrection
David Demelier <markand@malikania.fr>
parents:
diff changeset
230 */
00f1789a49fa Base64: resurrection
David Demelier <markand@malikania.fr>
parents:
diff changeset
231 inline std::string decode(const std::string &input)
00f1789a49fa Base64: resurrection
David Demelier <markand@malikania.fr>
parents:
diff changeset
232 {
548
f48bb09bccc7 Misc: huge cleanup, switch to spaces
David Demelier <markand@malikania.fr>
parents: 517
diff changeset
233 std::string result;
517
00f1789a49fa Base64: resurrection
David Demelier <markand@malikania.fr>
parents:
diff changeset
234
548
f48bb09bccc7 Misc: huge cleanup, switch to spaces
David Demelier <markand@malikania.fr>
parents: 517
diff changeset
235 decode(input.begin(), input.end(), std::back_inserter(result));
517
00f1789a49fa Base64: resurrection
David Demelier <markand@malikania.fr>
parents:
diff changeset
236
548
f48bb09bccc7 Misc: huge cleanup, switch to spaces
David Demelier <markand@malikania.fr>
parents: 517
diff changeset
237 return result;
517
00f1789a49fa Base64: resurrection
David Demelier <markand@malikania.fr>
parents:
diff changeset
238 }
00f1789a49fa Base64: resurrection
David Demelier <markand@malikania.fr>
parents:
diff changeset
239
00f1789a49fa Base64: resurrection
David Demelier <markand@malikania.fr>
parents:
diff changeset
240 } // !base64
00f1789a49fa Base64: resurrection
David Demelier <markand@malikania.fr>
parents:
diff changeset
241
00f1789a49fa Base64: resurrection
David Demelier <markand@malikania.fr>
parents:
diff changeset
242 #endif // !BASE64_HPP