comparison OrthancFramework/Resources/ThirdParty/base64/base64.cpp @ 4044:d25f4c0fa160 framework

splitting code into OrthancFramework and OrthancServer
author Sebastien Jodogne <s.jodogne@gmail.com>
date Wed, 10 Jun 2020 20:30:34 +0200
parents Resources/ThirdParty/base64/base64.cpp@79178122842c
children
comparison
equal deleted inserted replaced
4043:6c6239aec462 4044:d25f4c0fa160
1 /*
2 base64.cpp and base64.h
3
4 Copyright (C) 2004-2008 René Nyffenegger
5
6 This source code is provided 'as-is', without any express or implied
7 warranty. In no event will the author be held liable for any damages
8 arising from the use of this software.
9
10 Permission is granted to anyone to use this software for any purpose,
11 including commercial applications, and to alter it and redistribute it
12 freely, subject to the following restrictions:
13
14 1. The origin of this source code must not be misrepresented; you must not
15 claim that you wrote the original source code. If you use this source code
16 in a product, an acknowledgment in the product documentation would be
17 appreciated but is not required.
18
19 2. Altered source versions must be plainly marked as such, and must not be
20 misrepresented as being the original source code.
21
22 3. This notice may not be removed or altered from any source distribution.
23
24 René Nyffenegger rene.nyffenegger@adp-gmbh.ch
25
26 ------------------------------
27 This version has been modified (changed the interface + use another decoding algorithm
28 inspired from https://stackoverflow.com/a/34571089 which was faster)
29 */
30
31 #include "base64.h"
32 #include <string.h>
33 #include <vector>
34
35 static const std::string base64_chars =
36 "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
37 "abcdefghijklmnopqrstuvwxyz"
38 "0123456789+/";
39
40 static inline bool is_base64(unsigned char c) {
41 return (isalnum(c) || (c == '+') || (c == '/'));
42 }
43
44 void base64_encode(std::string& result, const std::string& stringToEncode)
45 {
46 const unsigned char* bytes_to_encode = reinterpret_cast<const unsigned char*>
47 (stringToEncode.size() > 0 ? &stringToEncode[0] : NULL);
48 size_t in_len = stringToEncode.size();
49
50 result.reserve(result.size() + in_len * 4 / 3 + 10);
51
52 int i = 0;
53 int j = 0;
54 unsigned char char_array_3[3];
55 unsigned char char_array_4[4];
56
57 while (in_len--) {
58 char_array_3[i++] = *(bytes_to_encode++);
59 if (i == 3) {
60 char_array_4[0] = (char_array_3[0] & 0xfc) >> 2;
61 char_array_4[1] = ((char_array_3[0] & 0x03) << 4) + ((char_array_3[1] & 0xf0) >> 4);
62 char_array_4[2] = ((char_array_3[1] & 0x0f) << 2) + ((char_array_3[2] & 0xc0) >> 6);
63 char_array_4[3] = char_array_3[2] & 0x3f;
64
65 for(i = 0; (i <4) ; i++)
66 result += base64_chars[char_array_4[i]];
67 i = 0;
68 }
69 }
70
71 if (i)
72 {
73 for(j = i; j < 3; j++)
74 char_array_3[j] = '\0';
75
76 char_array_4[0] = (char_array_3[0] & 0xfc) >> 2;
77 char_array_4[1] = ((char_array_3[0] & 0x03) << 4) + ((char_array_3[1] & 0xf0) >> 4);
78 char_array_4[2] = ((char_array_3[1] & 0x0f) << 2) + ((char_array_3[2] & 0xc0) >> 6);
79 char_array_4[3] = char_array_3[2] & 0x3f;
80
81 for (j = 0; (j < i + 1); j++)
82 result += base64_chars[char_array_4[j]];
83
84 while((i++ < 3))
85 result += '=';
86
87 }
88 }
89
90 // old code from René Nyffenegger. This code is slower
91 void base64_decode_old(std::string& result, const std::string& encoded_string) {
92 size_t in_len = encoded_string.size();
93 int i = 0;
94 int j = 0;
95 int in_ = 0;
96 unsigned char char_array_4[4], char_array_3[3];
97
98 result.reserve(result.size() + in_len * 3 / 4 + 10);
99
100 while (in_len-- && ( encoded_string[in_] != '=') && is_base64(encoded_string[in_])) {
101 char_array_4[i++] = encoded_string[in_]; in_++;
102 if (i ==4) {
103 for (i = 0; i <4; i++)
104 char_array_4[i] = base64_chars.find(char_array_4[i]);
105
106 char_array_3[0] = (char_array_4[0] << 2) + ((char_array_4[1] & 0x30) >> 4);
107 char_array_3[1] = ((char_array_4[1] & 0xf) << 4) + ((char_array_4[2] & 0x3c) >> 2);
108 char_array_3[2] = ((char_array_4[2] & 0x3) << 6) + char_array_4[3];
109
110 for (i = 0; (i < 3); i++)
111 result += char_array_3[i];
112 i = 0;
113 }
114 }
115
116 if (i) {
117 for (j = i; j <4; j++)
118 char_array_4[j] = 0;
119
120 for (j = 0; j <4; j++)
121 char_array_4[j] = base64_chars.find(char_array_4[j]);
122
123 char_array_3[0] = (char_array_4[0] << 2) + ((char_array_4[1] & 0x30) >> 4);
124 char_array_3[1] = ((char_array_4[1] & 0xf) << 4) + ((char_array_4[2] & 0x3c) >> 2);
125 char_array_3[2] = ((char_array_4[2] & 0x3) << 6) + char_array_4[3];
126
127 for (j = 0; (j < i - 1); j++)
128 result += char_array_3[j];
129 }
130 }
131
132
133 // new code from https://stackoverflow.com/a/34571089
134 // note that the encoding algorithm from this page was slower (and bugged !)
135 // this code is not using std::vector::find
136
137 // static init equivalent to:
138 // decode_indexes.assign(256, -1);
139 // for (int i=0; i<64; ++i)
140 // decode_indexes[base64_chars[i]] = i;
141
142 static const int decode_indexes[] = {
143 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
144 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
145 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 62, -1, -1, -1, 63,
146 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -1, -1, -1, -1, -1, -1,
147 -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
148 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, -1,
149 -1, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
150 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, -1, -1, -1, -1, -1,
151 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
152 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
153 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
154 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
155 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
156 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
157 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
158 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
159 };
160
161
162 void base64_decode(std::string& result, const std::string &stringToDecode) {
163
164 result.reserve(result.size() + stringToDecode.size() * 3 / 4 + 10);
165
166 int val=0, valb=-8;
167 for (std::string::const_iterator c = stringToDecode.begin(); c != stringToDecode.end(); ++c)
168 {
169 size_t index = static_cast<size_t>(*c);
170 if (decode_indexes[index] == -1)
171 break;
172 val = (val<<6) + decode_indexes[index];
173 valb += 6;
174 if (valb>=0) {
175 result.push_back(char((val>>valb)&0xFF));
176 valb-=8;
177 }
178 }
179 }