comparison C++/modules/Base64/base64.h @ 485:898d8b29a4f1

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