Mercurial > hg > orthanc
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 } |