annotate modules/base64/base64.h @ 488:b280d7aca160

Json: add typed valueOr for objects and arrays
author David Demelier <markand@malikania.fr>
date Fri, 13 Nov 2015 19:53:38 +0100
parents 7ee8da32da98
children
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
486
7ee8da32da98 Unify all in modules/
David Demelier <markand@malikania.fr>
parents:
diff changeset
1 /*
7ee8da32da98 Unify all in modules/
David Demelier <markand@malikania.fr>
parents:
diff changeset
2 * base64.h -- base64 encoding and decoding
7ee8da32da98 Unify all in modules/
David Demelier <markand@malikania.fr>
parents:
diff changeset
3 *
7ee8da32da98 Unify all in modules/
David Demelier <markand@malikania.fr>
parents:
diff changeset
4 * Copyright (c) 2013-2015 David Demelier <markand@malikania.fr>
7ee8da32da98 Unify all in modules/
David Demelier <markand@malikania.fr>
parents:
diff changeset
5 *
7ee8da32da98 Unify all in modules/
David Demelier <markand@malikania.fr>
parents:
diff changeset
6 * Permission to use, copy, modify, and/or distribute this software for any
7ee8da32da98 Unify all in modules/
David Demelier <markand@malikania.fr>
parents:
diff changeset
7 * purpose with or without fee is hereby granted, provided that the above
7ee8da32da98 Unify all in modules/
David Demelier <markand@malikania.fr>
parents:
diff changeset
8 * copyright notice and this permission notice appear in all copies.
7ee8da32da98 Unify all in modules/
David Demelier <markand@malikania.fr>
parents:
diff changeset
9 *
7ee8da32da98 Unify all in modules/
David Demelier <markand@malikania.fr>
parents:
diff changeset
10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
7ee8da32da98 Unify all in modules/
David Demelier <markand@malikania.fr>
parents:
diff changeset
11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
7ee8da32da98 Unify all in modules/
David Demelier <markand@malikania.fr>
parents:
diff changeset
12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
7ee8da32da98 Unify all in modules/
David Demelier <markand@malikania.fr>
parents:
diff changeset
13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
7ee8da32da98 Unify all in modules/
David Demelier <markand@malikania.fr>
parents:
diff changeset
14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
7ee8da32da98 Unify all in modules/
David Demelier <markand@malikania.fr>
parents:
diff changeset
15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
7ee8da32da98 Unify all in modules/
David Demelier <markand@malikania.fr>
parents:
diff changeset
16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
7ee8da32da98 Unify all in modules/
David Demelier <markand@malikania.fr>
parents:
diff changeset
17 */
7ee8da32da98 Unify all in modules/
David Demelier <markand@malikania.fr>
parents:
diff changeset
18
7ee8da32da98 Unify all in modules/
David Demelier <markand@malikania.fr>
parents:
diff changeset
19 #ifndef _BASE_64_H_
7ee8da32da98 Unify all in modules/
David Demelier <markand@malikania.fr>
parents:
diff changeset
20 #define _BASE_64_H_
7ee8da32da98 Unify all in modules/
David Demelier <markand@malikania.fr>
parents:
diff changeset
21
7ee8da32da98 Unify all in modules/
David Demelier <markand@malikania.fr>
parents:
diff changeset
22 /**
7ee8da32da98 Unify all in modules/
David Demelier <markand@malikania.fr>
parents:
diff changeset
23 * @file Base64.h
7ee8da32da98 Unify all in modules/
David Demelier <markand@malikania.fr>
parents:
diff changeset
24 * @brief Base64 encoding and decoding
7ee8da32da98 Unify all in modules/
David Demelier <markand@malikania.fr>
parents:
diff changeset
25 */
7ee8da32da98 Unify all in modules/
David Demelier <markand@malikania.fr>
parents:
diff changeset
26
7ee8da32da98 Unify all in modules/
David Demelier <markand@malikania.fr>
parents:
diff changeset
27 #include <stdexcept>
7ee8da32da98 Unify all in modules/
David Demelier <markand@malikania.fr>
parents:
diff changeset
28 #include <string>
7ee8da32da98 Unify all in modules/
David Demelier <markand@malikania.fr>
parents:
diff changeset
29
7ee8da32da98 Unify all in modules/
David Demelier <markand@malikania.fr>
parents:
diff changeset
30 namespace base64 {
7ee8da32da98 Unify all in modules/
David Demelier <markand@malikania.fr>
parents:
diff changeset
31
7ee8da32da98 Unify all in modules/
David Demelier <markand@malikania.fr>
parents:
diff changeset
32 /**
7ee8da32da98 Unify all in modules/
David Demelier <markand@malikania.fr>
parents:
diff changeset
33 * Get the base 64 character from the 6-bits value.
7ee8da32da98 Unify all in modules/
David Demelier <markand@malikania.fr>
parents:
diff changeset
34 *
7ee8da32da98 Unify all in modules/
David Demelier <markand@malikania.fr>
parents:
diff changeset
35 * @pre value must be valid
7ee8da32da98 Unify all in modules/
David Demelier <markand@malikania.fr>
parents:
diff changeset
36 * @param value the value
7ee8da32da98 Unify all in modules/
David Demelier <markand@malikania.fr>
parents:
diff changeset
37 */
7ee8da32da98 Unify all in modules/
David Demelier <markand@malikania.fr>
parents:
diff changeset
38 unsigned char lookup(unsigned int value) noexcept;
7ee8da32da98 Unify all in modules/
David Demelier <markand@malikania.fr>
parents:
diff changeset
39
7ee8da32da98 Unify all in modules/
David Demelier <markand@malikania.fr>
parents:
diff changeset
40 /**
7ee8da32da98 Unify all in modules/
David Demelier <markand@malikania.fr>
parents:
diff changeset
41 * Get the integer value from the base 64 character.
7ee8da32da98 Unify all in modules/
David Demelier <markand@malikania.fr>
parents:
diff changeset
42 *
7ee8da32da98 Unify all in modules/
David Demelier <markand@malikania.fr>
parents:
diff changeset
43 * @pre ch must be a valid base 64 character but not '='
7ee8da32da98 Unify all in modules/
David Demelier <markand@malikania.fr>
parents:
diff changeset
44 * @param ch the base64 character
7ee8da32da98 Unify all in modules/
David Demelier <markand@malikania.fr>
parents:
diff changeset
45 */
7ee8da32da98 Unify all in modules/
David Demelier <markand@malikania.fr>
parents:
diff changeset
46 unsigned int rlookup(unsigned char ch);
7ee8da32da98 Unify all in modules/
David Demelier <markand@malikania.fr>
parents:
diff changeset
47
7ee8da32da98 Unify all in modules/
David Demelier <markand@malikania.fr>
parents:
diff changeset
48 /**
7ee8da32da98 Unify all in modules/
David Demelier <markand@malikania.fr>
parents:
diff changeset
49 * Check if the given character is a valid base 64 character.
7ee8da32da98 Unify all in modules/
David Demelier <markand@malikania.fr>
parents:
diff changeset
50 *
7ee8da32da98 Unify all in modules/
David Demelier <markand@malikania.fr>
parents:
diff changeset
51 * @param char the character
7ee8da32da98 Unify all in modules/
David Demelier <markand@malikania.fr>
parents:
diff changeset
52 * @return true if the character is valid
7ee8da32da98 Unify all in modules/
David Demelier <markand@malikania.fr>
parents:
diff changeset
53 */
7ee8da32da98 Unify all in modules/
David Demelier <markand@malikania.fr>
parents:
diff changeset
54 bool isValid(unsigned char) noexcept;
7ee8da32da98 Unify all in modules/
David Demelier <markand@malikania.fr>
parents:
diff changeset
55
7ee8da32da98 Unify all in modules/
David Demelier <markand@malikania.fr>
parents:
diff changeset
56 /**
7ee8da32da98 Unify all in modules/
David Demelier <markand@malikania.fr>
parents:
diff changeset
57 * Encode the input to the output. Requirements:
7ee8da32da98 Unify all in modules/
David Demelier <markand@malikania.fr>
parents:
diff changeset
58 * InputIt must be InputIterator
7ee8da32da98 Unify all in modules/
David Demelier <markand@malikania.fr>
parents:
diff changeset
59 * OutputIt must be OutputIterator
7ee8da32da98 Unify all in modules/
David Demelier <markand@malikania.fr>
parents:
diff changeset
60 *
7ee8da32da98 Unify all in modules/
David Demelier <markand@malikania.fr>
parents:
diff changeset
61 * @param input the beginning
7ee8da32da98 Unify all in modules/
David Demelier <markand@malikania.fr>
parents:
diff changeset
62 * @param end the end of the data
7ee8da32da98 Unify all in modules/
David Demelier <markand@malikania.fr>
parents:
diff changeset
63 * @param output the output destination
7ee8da32da98 Unify all in modules/
David Demelier <markand@malikania.fr>
parents:
diff changeset
64 * @return output
7ee8da32da98 Unify all in modules/
David Demelier <markand@malikania.fr>
parents:
diff changeset
65 */
7ee8da32da98 Unify all in modules/
David Demelier <markand@malikania.fr>
parents:
diff changeset
66 template <typename InputIt, typename OutputIt>
7ee8da32da98 Unify all in modules/
David Demelier <markand@malikania.fr>
parents:
diff changeset
67 OutputIt encode(InputIt input, InputIt end, OutputIt output)
7ee8da32da98 Unify all in modules/
David Demelier <markand@malikania.fr>
parents:
diff changeset
68 {
7ee8da32da98 Unify all in modules/
David Demelier <markand@malikania.fr>
parents:
diff changeset
69 while (input != end) {
7ee8da32da98 Unify all in modules/
David Demelier <markand@malikania.fr>
parents:
diff changeset
70 char inputbuf[3] = { 0, 0, 0 };
7ee8da32da98 Unify all in modules/
David Demelier <markand@malikania.fr>
parents:
diff changeset
71 int count;
7ee8da32da98 Unify all in modules/
David Demelier <markand@malikania.fr>
parents:
diff changeset
72
7ee8da32da98 Unify all in modules/
David Demelier <markand@malikania.fr>
parents:
diff changeset
73 for (count = 0; count < 3 && input != end; ++count) {
7ee8da32da98 Unify all in modules/
David Demelier <markand@malikania.fr>
parents:
diff changeset
74 inputbuf[count] = *input++;
7ee8da32da98 Unify all in modules/
David Demelier <markand@malikania.fr>
parents:
diff changeset
75 }
7ee8da32da98 Unify all in modules/
David Demelier <markand@malikania.fr>
parents:
diff changeset
76
7ee8da32da98 Unify all in modules/
David Demelier <markand@malikania.fr>
parents:
diff changeset
77 *output++ = lookup(inputbuf[0] >> 2 & 0x3f);
7ee8da32da98 Unify all in modules/
David Demelier <markand@malikania.fr>
parents:
diff changeset
78 *output++ = lookup((inputbuf[0] << 4 & 0x3f) | (inputbuf[1] >> 4 & 0x0f));
7ee8da32da98 Unify all in modules/
David Demelier <markand@malikania.fr>
parents:
diff changeset
79 *output++ = (count < 2) ? '=' : lookup((inputbuf[1] << 2 & 0x3c) | (inputbuf[2] >> 6 & 0x03));
7ee8da32da98 Unify all in modules/
David Demelier <markand@malikania.fr>
parents:
diff changeset
80 *output++ = (count < 3) ? '=' : lookup(inputbuf[2] & 0x3f);
7ee8da32da98 Unify all in modules/
David Demelier <markand@malikania.fr>
parents:
diff changeset
81 }
7ee8da32da98 Unify all in modules/
David Demelier <markand@malikania.fr>
parents:
diff changeset
82
7ee8da32da98 Unify all in modules/
David Demelier <markand@malikania.fr>
parents:
diff changeset
83 return output;
7ee8da32da98 Unify all in modules/
David Demelier <markand@malikania.fr>
parents:
diff changeset
84 }
7ee8da32da98 Unify all in modules/
David Demelier <markand@malikania.fr>
parents:
diff changeset
85
7ee8da32da98 Unify all in modules/
David Demelier <markand@malikania.fr>
parents:
diff changeset
86 /**
7ee8da32da98 Unify all in modules/
David Demelier <markand@malikania.fr>
parents:
diff changeset
87 * Decode the input to the output. Requirements:
7ee8da32da98 Unify all in modules/
David Demelier <markand@malikania.fr>
parents:
diff changeset
88 * InputIt must be InputIterator
7ee8da32da98 Unify all in modules/
David Demelier <markand@malikania.fr>
parents:
diff changeset
89 * OutputIt must be OutputIterator
7ee8da32da98 Unify all in modules/
David Demelier <markand@malikania.fr>
parents:
diff changeset
90 *
7ee8da32da98 Unify all in modules/
David Demelier <markand@malikania.fr>
parents:
diff changeset
91 * @param input the beginning
7ee8da32da98 Unify all in modules/
David Demelier <markand@malikania.fr>
parents:
diff changeset
92 * @param end the end of the data
7ee8da32da98 Unify all in modules/
David Demelier <markand@malikania.fr>
parents:
diff changeset
93 * @param output the output destination
7ee8da32da98 Unify all in modules/
David Demelier <markand@malikania.fr>
parents:
diff changeset
94 * @return output
7ee8da32da98 Unify all in modules/
David Demelier <markand@malikania.fr>
parents:
diff changeset
95 * @throw std::invalid_argument on bad base64 string
7ee8da32da98 Unify all in modules/
David Demelier <markand@malikania.fr>
parents:
diff changeset
96 */
7ee8da32da98 Unify all in modules/
David Demelier <markand@malikania.fr>
parents:
diff changeset
97 template <typename InputIt, typename OutputIt>
7ee8da32da98 Unify all in modules/
David Demelier <markand@malikania.fr>
parents:
diff changeset
98 OutputIt decode(InputIt input, InputIt end, OutputIt output)
7ee8da32da98 Unify all in modules/
David Demelier <markand@malikania.fr>
parents:
diff changeset
99 {
7ee8da32da98 Unify all in modules/
David Demelier <markand@malikania.fr>
parents:
diff changeset
100 while (input != end) {
7ee8da32da98 Unify all in modules/
David Demelier <markand@malikania.fr>
parents:
diff changeset
101 char inputbuf[4] = { -1, -1, -1, -1 };
7ee8da32da98 Unify all in modules/
David Demelier <markand@malikania.fr>
parents:
diff changeset
102 int count;
7ee8da32da98 Unify all in modules/
David Demelier <markand@malikania.fr>
parents:
diff changeset
103
7ee8da32da98 Unify all in modules/
David Demelier <markand@malikania.fr>
parents:
diff changeset
104 for (count = 0; count < 4 && input != end; ++count) {
7ee8da32da98 Unify all in modules/
David Demelier <markand@malikania.fr>
parents:
diff changeset
105 if (*input != '=') {
7ee8da32da98 Unify all in modules/
David Demelier <markand@malikania.fr>
parents:
diff changeset
106 /* Check if the character is valid and get its value */
7ee8da32da98 Unify all in modules/
David Demelier <markand@malikania.fr>
parents:
diff changeset
107 if (isValid(*input)) {
7ee8da32da98 Unify all in modules/
David Demelier <markand@malikania.fr>
parents:
diff changeset
108 inputbuf[count] = rlookup(*input);
7ee8da32da98 Unify all in modules/
David Demelier <markand@malikania.fr>
parents:
diff changeset
109 } else {
7ee8da32da98 Unify all in modules/
David Demelier <markand@malikania.fr>
parents:
diff changeset
110 throw std::invalid_argument{"invalid base64 string"};
7ee8da32da98 Unify all in modules/
David Demelier <markand@malikania.fr>
parents:
diff changeset
111 }
7ee8da32da98 Unify all in modules/
David Demelier <markand@malikania.fr>
parents:
diff changeset
112 } else {
7ee8da32da98 Unify all in modules/
David Demelier <markand@malikania.fr>
parents:
diff changeset
113 /* A base 64 string cannot start with "=" or "==" */
7ee8da32da98 Unify all in modules/
David Demelier <markand@malikania.fr>
parents:
diff changeset
114 if (count == 0 || count == 1) {
7ee8da32da98 Unify all in modules/
David Demelier <markand@malikania.fr>
parents:
diff changeset
115 throw std::invalid_argument{"invalid or truncated base64 string"};
7ee8da32da98 Unify all in modules/
David Demelier <markand@malikania.fr>
parents:
diff changeset
116 }
7ee8da32da98 Unify all in modules/
David Demelier <markand@malikania.fr>
parents:
diff changeset
117 }
7ee8da32da98 Unify all in modules/
David Demelier <markand@malikania.fr>
parents:
diff changeset
118
7ee8da32da98 Unify all in modules/
David Demelier <markand@malikania.fr>
parents:
diff changeset
119 input++;
7ee8da32da98 Unify all in modules/
David Demelier <markand@malikania.fr>
parents:
diff changeset
120 }
7ee8da32da98 Unify all in modules/
David Demelier <markand@malikania.fr>
parents:
diff changeset
121
7ee8da32da98 Unify all in modules/
David Demelier <markand@malikania.fr>
parents:
diff changeset
122 if (count != 4) {
7ee8da32da98 Unify all in modules/
David Demelier <markand@malikania.fr>
parents:
diff changeset
123 throw std::invalid_argument("truncated string");
7ee8da32da98 Unify all in modules/
David Demelier <markand@malikania.fr>
parents:
diff changeset
124 }
7ee8da32da98 Unify all in modules/
David Demelier <markand@malikania.fr>
parents:
diff changeset
125
7ee8da32da98 Unify all in modules/
David Demelier <markand@malikania.fr>
parents:
diff changeset
126 *output++ = static_cast<unsigned char>(((inputbuf[0] << 2) & 0xfc) | ((inputbuf[1] >> 4) & 0x03));
7ee8da32da98 Unify all in modules/
David Demelier <markand@malikania.fr>
parents:
diff changeset
127
7ee8da32da98 Unify all in modules/
David Demelier <markand@malikania.fr>
parents:
diff changeset
128 if (inputbuf[2] != -1) {
7ee8da32da98 Unify all in modules/
David Demelier <markand@malikania.fr>
parents:
diff changeset
129 *output++ = static_cast<unsigned char>(((inputbuf[1] << 4) & 0xf0) | ((inputbuf[2] >> 2) & 0x0f));
7ee8da32da98 Unify all in modules/
David Demelier <markand@malikania.fr>
parents:
diff changeset
130 }
7ee8da32da98 Unify all in modules/
David Demelier <markand@malikania.fr>
parents:
diff changeset
131 if (inputbuf[3] != -1) {
7ee8da32da98 Unify all in modules/
David Demelier <markand@malikania.fr>
parents:
diff changeset
132 /* "XY=Z" is not allowed */
7ee8da32da98 Unify all in modules/
David Demelier <markand@malikania.fr>
parents:
diff changeset
133 if (inputbuf[2] == -1) {
7ee8da32da98 Unify all in modules/
David Demelier <markand@malikania.fr>
parents:
diff changeset
134 throw std::invalid_argument{"invalid base64 string"};
7ee8da32da98 Unify all in modules/
David Demelier <markand@malikania.fr>
parents:
diff changeset
135 }
7ee8da32da98 Unify all in modules/
David Demelier <markand@malikania.fr>
parents:
diff changeset
136
7ee8da32da98 Unify all in modules/
David Demelier <markand@malikania.fr>
parents:
diff changeset
137 *output++ = static_cast<unsigned char>(((inputbuf[2] << 6) & 0xc0) | (inputbuf[3] & 0x3f));
7ee8da32da98 Unify all in modules/
David Demelier <markand@malikania.fr>
parents:
diff changeset
138 }
7ee8da32da98 Unify all in modules/
David Demelier <markand@malikania.fr>
parents:
diff changeset
139 }
7ee8da32da98 Unify all in modules/
David Demelier <markand@malikania.fr>
parents:
diff changeset
140
7ee8da32da98 Unify all in modules/
David Demelier <markand@malikania.fr>
parents:
diff changeset
141 return output;
7ee8da32da98 Unify all in modules/
David Demelier <markand@malikania.fr>
parents:
diff changeset
142 }
7ee8da32da98 Unify all in modules/
David Demelier <markand@malikania.fr>
parents:
diff changeset
143
7ee8da32da98 Unify all in modules/
David Demelier <markand@malikania.fr>
parents:
diff changeset
144 /**
7ee8da32da98 Unify all in modules/
David Demelier <markand@malikania.fr>
parents:
diff changeset
145 * Encode a string.
7ee8da32da98 Unify all in modules/
David Demelier <markand@malikania.fr>
parents:
diff changeset
146 *
7ee8da32da98 Unify all in modules/
David Demelier <markand@malikania.fr>
parents:
diff changeset
147 * @param input the input string
7ee8da32da98 Unify all in modules/
David Demelier <markand@malikania.fr>
parents:
diff changeset
148 * @return the base64 formatted string
7ee8da32da98 Unify all in modules/
David Demelier <markand@malikania.fr>
parents:
diff changeset
149 */
7ee8da32da98 Unify all in modules/
David Demelier <markand@malikania.fr>
parents:
diff changeset
150 std::string encode(const std::string &input);
7ee8da32da98 Unify all in modules/
David Demelier <markand@malikania.fr>
parents:
diff changeset
151
7ee8da32da98 Unify all in modules/
David Demelier <markand@malikania.fr>
parents:
diff changeset
152 /**
7ee8da32da98 Unify all in modules/
David Demelier <markand@malikania.fr>
parents:
diff changeset
153 * Decode a string.
7ee8da32da98 Unify all in modules/
David Demelier <markand@malikania.fr>
parents:
diff changeset
154 *
7ee8da32da98 Unify all in modules/
David Demelier <markand@malikania.fr>
parents:
diff changeset
155 * @param input the base64 formatted string
7ee8da32da98 Unify all in modules/
David Demelier <markand@malikania.fr>
parents:
diff changeset
156 * @return the original string
7ee8da32da98 Unify all in modules/
David Demelier <markand@malikania.fr>
parents:
diff changeset
157 * @throw std::invalid_argument on bad base64 string
7ee8da32da98 Unify all in modules/
David Demelier <markand@malikania.fr>
parents:
diff changeset
158 */
7ee8da32da98 Unify all in modules/
David Demelier <markand@malikania.fr>
parents:
diff changeset
159 std::string decode(const std::string &input);
7ee8da32da98 Unify all in modules/
David Demelier <markand@malikania.fr>
parents:
diff changeset
160
7ee8da32da98 Unify all in modules/
David Demelier <markand@malikania.fr>
parents:
diff changeset
161 } // !base64
7ee8da32da98 Unify all in modules/
David Demelier <markand@malikania.fr>
parents:
diff changeset
162
7ee8da32da98 Unify all in modules/
David Demelier <markand@malikania.fr>
parents:
diff changeset
163 #endif // !_BASE_64_H_