]>
Commit | Line | Data |
---|---|---|
ad49c256 | 1 | // Copyright (c) 2009-2010 Satoshi Nakamoto |
f914f1a7 | 2 | // Copyright (c) 2009-2014 The Bitcoin Core developers |
c63a73d1 | 3 | // Distributed under the MIT software license, see the accompanying |
ad49c256 WL |
4 | // file COPYING or http://www.opensource.org/licenses/mit-license.php. |
5 | ||
6 | #include "utilstrencodings.h" | |
7 | ||
8 | #include "tinyformat.h" | |
9 | ||
352058e8 CF |
10 | #include <cstdlib> |
11 | #include <cstring> | |
771d5002 PK |
12 | #include <errno.h> |
13 | #include <limits> | |
611116d4 | 14 | |
ad49c256 WL |
15 | using namespace std; |
16 | ||
ad49c256 WL |
17 | string SanitizeString(const string& str) |
18 | { | |
32231795 CF |
19 | /** |
20 | * safeChars chosen to allow simple messages/URLs/email addresses, but avoid anything | |
21 | * even possibly remotely dangerous like & or > | |
22 | */ | |
23 | static string safeChars("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890 .,;_/:?@()"); | |
ad49c256 WL |
24 | string strResult; |
25 | for (std::string::size_type i = 0; i < str.size(); i++) | |
26 | { | |
27 | if (safeChars.find(str[i]) != std::string::npos) | |
28 | strResult.push_back(str[i]); | |
29 | } | |
30 | return strResult; | |
31 | } | |
32 | ||
9064d73b S |
33 | string SanitizeFilename(const string& str) |
34 | { | |
35 | /** | |
36 | * safeChars chosen to restrict filename, keeping it simple to avoid cross-platform issues. | |
37 | * http://stackoverflow.com/a/2306003 | |
38 | */ | |
39 | static string safeChars("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890"); | |
40 | string strResult; | |
41 | for (std::string::size_type i = 0; i < str.size(); i++) | |
42 | { | |
43 | if (safeChars.find(str[i]) != std::string::npos) | |
44 | strResult.push_back(str[i]); | |
45 | } | |
46 | return strResult; | |
47 | } | |
48 | ||
ad49c256 WL |
49 | const signed char p_util_hexdigit[256] = |
50 | { -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, | |
51 | -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, | |
52 | -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, | |
53 | 0,1,2,3,4,5,6,7,8,9,-1,-1,-1,-1,-1,-1, | |
54 | -1,0xa,0xb,0xc,0xd,0xe,0xf,-1,-1,-1,-1,-1,-1,-1,-1,-1, | |
55 | -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, | |
56 | -1,0xa,0xb,0xc,0xd,0xe,0xf,-1,-1,-1,-1,-1,-1,-1,-1,-1, | |
57 | -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, | |
58 | -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, | |
59 | -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, | |
60 | -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, | |
61 | -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, | |
62 | -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, | |
63 | -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, | |
64 | -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, | |
65 | -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, }; | |
66 | ||
67 | signed char HexDigit(char c) | |
68 | { | |
69 | return p_util_hexdigit[(unsigned char)c]; | |
70 | } | |
71 | ||
72 | bool IsHex(const string& str) | |
73 | { | |
352058e8 | 74 | for(std::string::const_iterator it(str.begin()); it != str.end(); ++it) |
ad49c256 | 75 | { |
352058e8 | 76 | if (HexDigit(*it) < 0) |
ad49c256 WL |
77 | return false; |
78 | } | |
79 | return (str.size() > 0) && (str.size()%2 == 0); | |
80 | } | |
81 | ||
82 | vector<unsigned char> ParseHex(const char* psz) | |
83 | { | |
84 | // convert hex dump to vector | |
85 | vector<unsigned char> vch; | |
86 | while (true) | |
87 | { | |
88 | while (isspace(*psz)) | |
89 | psz++; | |
90 | signed char c = HexDigit(*psz++); | |
91 | if (c == (signed char)-1) | |
92 | break; | |
93 | unsigned char n = (c << 4); | |
94 | c = HexDigit(*psz++); | |
95 | if (c == (signed char)-1) | |
96 | break; | |
97 | n |= c; | |
98 | vch.push_back(n); | |
99 | } | |
100 | return vch; | |
101 | } | |
102 | ||
103 | vector<unsigned char> ParseHex(const string& str) | |
104 | { | |
105 | return ParseHex(str.c_str()); | |
106 | } | |
107 | ||
108 | string EncodeBase64(const unsigned char* pch, size_t len) | |
109 | { | |
110 | static const char *pbase64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; | |
111 | ||
112 | string strRet=""; | |
113 | strRet.reserve((len+2)/3*4); | |
114 | ||
115 | int mode=0, left=0; | |
116 | const unsigned char *pchEnd = pch+len; | |
117 | ||
118 | while (pch<pchEnd) | |
119 | { | |
120 | int enc = *(pch++); | |
121 | switch (mode) | |
122 | { | |
123 | case 0: // we have no bits | |
124 | strRet += pbase64[enc >> 2]; | |
125 | left = (enc & 3) << 4; | |
126 | mode = 1; | |
127 | break; | |
128 | ||
129 | case 1: // we have two bits | |
130 | strRet += pbase64[left | (enc >> 4)]; | |
131 | left = (enc & 15) << 2; | |
132 | mode = 2; | |
133 | break; | |
134 | ||
135 | case 2: // we have four bits | |
136 | strRet += pbase64[left | (enc >> 6)]; | |
137 | strRet += pbase64[enc & 63]; | |
138 | mode = 0; | |
139 | break; | |
140 | } | |
141 | } | |
142 | ||
143 | if (mode) | |
144 | { | |
145 | strRet += pbase64[left]; | |
146 | strRet += '='; | |
147 | if (mode == 1) | |
148 | strRet += '='; | |
149 | } | |
150 | ||
151 | return strRet; | |
152 | } | |
153 | ||
154 | string EncodeBase64(const string& str) | |
155 | { | |
156 | return EncodeBase64((const unsigned char*)str.c_str(), str.size()); | |
157 | } | |
158 | ||
159 | vector<unsigned char> DecodeBase64(const char* p, bool* pfInvalid) | |
160 | { | |
161 | static const int decode64_table[256] = | |
162 | { | |
163 | -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, | |
164 | -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, | |
165 | -1, -1, -1, 62, -1, -1, -1, 63, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -1, -1, | |
166 | -1, -1, -1, -1, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, | |
167 | 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, -1, -1, 26, 27, 28, | |
168 | 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, | |
169 | 49, 50, 51, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, | |
170 | -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, | |
171 | -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, | |
172 | -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, | |
173 | -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, | |
174 | -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, | |
175 | -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 | |
176 | }; | |
177 | ||
178 | if (pfInvalid) | |
179 | *pfInvalid = false; | |
180 | ||
181 | vector<unsigned char> vchRet; | |
182 | vchRet.reserve(strlen(p)*3/4); | |
183 | ||
184 | int mode = 0; | |
185 | int left = 0; | |
186 | ||
187 | while (1) | |
188 | { | |
189 | int dec = decode64_table[(unsigned char)*p]; | |
190 | if (dec == -1) break; | |
191 | p++; | |
192 | switch (mode) | |
193 | { | |
194 | case 0: // we have no bits and get 6 | |
195 | left = dec; | |
196 | mode = 1; | |
197 | break; | |
198 | ||
199 | case 1: // we have 6 bits and keep 4 | |
200 | vchRet.push_back((left<<2) | (dec>>4)); | |
201 | left = dec & 15; | |
202 | mode = 2; | |
203 | break; | |
204 | ||
205 | case 2: // we have 4 bits and get 6, we keep 2 | |
206 | vchRet.push_back((left<<4) | (dec>>2)); | |
207 | left = dec & 3; | |
208 | mode = 3; | |
209 | break; | |
210 | ||
211 | case 3: // we have 2 bits and get 6 | |
212 | vchRet.push_back((left<<6) | dec); | |
213 | mode = 0; | |
214 | break; | |
215 | } | |
216 | } | |
217 | ||
218 | if (pfInvalid) | |
219 | switch (mode) | |
220 | { | |
221 | case 0: // 4n base64 characters processed: ok | |
222 | break; | |
223 | ||
224 | case 1: // 4n+1 base64 character processed: impossible | |
225 | *pfInvalid = true; | |
226 | break; | |
227 | ||
228 | case 2: // 4n+2 base64 characters processed: require '==' | |
229 | if (left || p[0] != '=' || p[1] != '=' || decode64_table[(unsigned char)p[2]] != -1) | |
230 | *pfInvalid = true; | |
231 | break; | |
232 | ||
233 | case 3: // 4n+3 base64 characters processed: require '=' | |
234 | if (left || p[0] != '=' || decode64_table[(unsigned char)p[1]] != -1) | |
235 | *pfInvalid = true; | |
236 | break; | |
237 | } | |
238 | ||
239 | return vchRet; | |
240 | } | |
241 | ||
242 | string DecodeBase64(const string& str) | |
243 | { | |
244 | vector<unsigned char> vchRet = DecodeBase64(str.c_str()); | |
018cec7c | 245 | return (vchRet.size() == 0) ? string() : string((const char*)&vchRet[0], vchRet.size()); |
ad49c256 WL |
246 | } |
247 | ||
248 | string EncodeBase32(const unsigned char* pch, size_t len) | |
249 | { | |
250 | static const char *pbase32 = "abcdefghijklmnopqrstuvwxyz234567"; | |
251 | ||
252 | string strRet=""; | |
253 | strRet.reserve((len+4)/5*8); | |
254 | ||
255 | int mode=0, left=0; | |
256 | const unsigned char *pchEnd = pch+len; | |
257 | ||
258 | while (pch<pchEnd) | |
259 | { | |
260 | int enc = *(pch++); | |
261 | switch (mode) | |
262 | { | |
263 | case 0: // we have no bits | |
264 | strRet += pbase32[enc >> 3]; | |
265 | left = (enc & 7) << 2; | |
266 | mode = 1; | |
267 | break; | |
268 | ||
269 | case 1: // we have three bits | |
270 | strRet += pbase32[left | (enc >> 6)]; | |
271 | strRet += pbase32[(enc >> 1) & 31]; | |
272 | left = (enc & 1) << 4; | |
273 | mode = 2; | |
274 | break; | |
275 | ||
276 | case 2: // we have one bit | |
277 | strRet += pbase32[left | (enc >> 4)]; | |
278 | left = (enc & 15) << 1; | |
279 | mode = 3; | |
280 | break; | |
281 | ||
282 | case 3: // we have four bits | |
283 | strRet += pbase32[left | (enc >> 7)]; | |
284 | strRet += pbase32[(enc >> 2) & 31]; | |
285 | left = (enc & 3) << 3; | |
286 | mode = 4; | |
287 | break; | |
288 | ||
289 | case 4: // we have two bits | |
290 | strRet += pbase32[left | (enc >> 5)]; | |
291 | strRet += pbase32[enc & 31]; | |
292 | mode = 0; | |
293 | } | |
294 | } | |
295 | ||
296 | static const int nPadding[5] = {0, 6, 4, 3, 1}; | |
297 | if (mode) | |
298 | { | |
299 | strRet += pbase32[left]; | |
300 | for (int n=0; n<nPadding[mode]; n++) | |
301 | strRet += '='; | |
302 | } | |
303 | ||
304 | return strRet; | |
305 | } | |
306 | ||
307 | string EncodeBase32(const string& str) | |
308 | { | |
309 | return EncodeBase32((const unsigned char*)str.c_str(), str.size()); | |
310 | } | |
311 | ||
312 | vector<unsigned char> DecodeBase32(const char* p, bool* pfInvalid) | |
313 | { | |
314 | static const int decode32_table[256] = | |
315 | { | |
316 | -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, | |
317 | -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, | |
318 | -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 26, 27, 28, 29, 30, 31, -1, -1, -1, -1, | |
319 | -1, -1, -1, -1, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, | |
320 | 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, -1, -1, 0, 1, 2, | |
321 | 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, | |
322 | 23, 24, 25, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, | |
323 | -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, | |
324 | -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, | |
325 | -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, | |
326 | -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, | |
327 | -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, | |
328 | -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 | |
329 | }; | |
330 | ||
331 | if (pfInvalid) | |
332 | *pfInvalid = false; | |
333 | ||
334 | vector<unsigned char> vchRet; | |
335 | vchRet.reserve((strlen(p))*5/8); | |
336 | ||
337 | int mode = 0; | |
338 | int left = 0; | |
339 | ||
340 | while (1) | |
341 | { | |
342 | int dec = decode32_table[(unsigned char)*p]; | |
343 | if (dec == -1) break; | |
344 | p++; | |
345 | switch (mode) | |
346 | { | |
347 | case 0: // we have no bits and get 5 | |
348 | left = dec; | |
349 | mode = 1; | |
350 | break; | |
351 | ||
352 | case 1: // we have 5 bits and keep 2 | |
353 | vchRet.push_back((left<<3) | (dec>>2)); | |
354 | left = dec & 3; | |
355 | mode = 2; | |
356 | break; | |
357 | ||
358 | case 2: // we have 2 bits and keep 7 | |
359 | left = left << 5 | dec; | |
360 | mode = 3; | |
361 | break; | |
362 | ||
363 | case 3: // we have 7 bits and keep 4 | |
364 | vchRet.push_back((left<<1) | (dec>>4)); | |
365 | left = dec & 15; | |
366 | mode = 4; | |
367 | break; | |
368 | ||
369 | case 4: // we have 4 bits, and keep 1 | |
370 | vchRet.push_back((left<<4) | (dec>>1)); | |
371 | left = dec & 1; | |
372 | mode = 5; | |
373 | break; | |
374 | ||
375 | case 5: // we have 1 bit, and keep 6 | |
376 | left = left << 5 | dec; | |
377 | mode = 6; | |
378 | break; | |
379 | ||
380 | case 6: // we have 6 bits, and keep 3 | |
381 | vchRet.push_back((left<<2) | (dec>>3)); | |
382 | left = dec & 7; | |
383 | mode = 7; | |
384 | break; | |
385 | ||
386 | case 7: // we have 3 bits, and keep 0 | |
387 | vchRet.push_back((left<<5) | dec); | |
388 | mode = 0; | |
389 | break; | |
390 | } | |
391 | } | |
392 | ||
393 | if (pfInvalid) | |
394 | switch (mode) | |
395 | { | |
396 | case 0: // 8n base32 characters processed: ok | |
397 | break; | |
398 | ||
399 | case 1: // 8n+1 base32 characters processed: impossible | |
400 | case 3: // +3 | |
401 | case 6: // +6 | |
402 | *pfInvalid = true; | |
403 | break; | |
404 | ||
405 | case 2: // 8n+2 base32 characters processed: require '======' | |
406 | if (left || p[0] != '=' || p[1] != '=' || p[2] != '=' || p[3] != '=' || p[4] != '=' || p[5] != '=' || decode32_table[(unsigned char)p[6]] != -1) | |
407 | *pfInvalid = true; | |
408 | break; | |
409 | ||
410 | case 4: // 8n+4 base32 characters processed: require '====' | |
411 | if (left || p[0] != '=' || p[1] != '=' || p[2] != '=' || p[3] != '=' || decode32_table[(unsigned char)p[4]] != -1) | |
412 | *pfInvalid = true; | |
413 | break; | |
414 | ||
415 | case 5: // 8n+5 base32 characters processed: require '===' | |
416 | if (left || p[0] != '=' || p[1] != '=' || p[2] != '=' || decode32_table[(unsigned char)p[3]] != -1) | |
417 | *pfInvalid = true; | |
418 | break; | |
419 | ||
420 | case 7: // 8n+7 base32 characters processed: require '=' | |
421 | if (left || p[0] != '=' || decode32_table[(unsigned char)p[1]] != -1) | |
422 | *pfInvalid = true; | |
423 | break; | |
424 | } | |
425 | ||
426 | return vchRet; | |
427 | } | |
428 | ||
429 | string DecodeBase32(const string& str) | |
430 | { | |
431 | vector<unsigned char> vchRet = DecodeBase32(str.c_str()); | |
018cec7c | 432 | return (vchRet.size() == 0) ? string() : string((const char*)&vchRet[0], vchRet.size()); |
ad49c256 WL |
433 | } |
434 | ||
5960d700 WL |
435 | static bool ParsePrechecks(const std::string& str) |
436 | { | |
437 | if (str.empty()) // No empty string allowed | |
438 | return false; | |
439 | if (str.size() >= 1 && (isspace(str[0]) || isspace(str[str.size()-1]))) // No padding allowed | |
440 | return false; | |
441 | if (str.size() != strlen(str.c_str())) // No embedded NUL characters allowed | |
442 | return false; | |
443 | return true; | |
444 | } | |
445 | ||
ad49c256 WL |
446 | bool ParseInt32(const std::string& str, int32_t *out) |
447 | { | |
5960d700 WL |
448 | if (!ParsePrechecks(str)) |
449 | return false; | |
ad49c256 WL |
450 | char *endp = NULL; |
451 | errno = 0; // strtol will not set errno if valid | |
452 | long int n = strtol(str.c_str(), &endp, 10); | |
5960d700 | 453 | if(out) *out = (int32_t)n; |
ad49c256 WL |
454 | // Note that strtol returns a *long int*, so even if strtol doesn't report a over/underflow |
455 | // we still have to check that the returned value is within the range of an *int32_t*. On 64-bit | |
456 | // platforms the size of these types may be different. | |
457 | return endp && *endp == 0 && !errno && | |
458 | n >= std::numeric_limits<int32_t>::min() && | |
459 | n <= std::numeric_limits<int32_t>::max(); | |
460 | } | |
461 | ||
5960d700 WL |
462 | bool ParseInt64(const std::string& str, int64_t *out) |
463 | { | |
464 | if (!ParsePrechecks(str)) | |
465 | return false; | |
466 | char *endp = NULL; | |
467 | errno = 0; // strtoll will not set errno if valid | |
468 | long long int n = strtoll(str.c_str(), &endp, 10); | |
469 | if(out) *out = (int64_t)n; | |
470 | // Note that strtoll returns a *long long int*, so even if strtol doesn't report a over/underflow | |
471 | // we still have to check that the returned value is within the range of an *int64_t*. | |
472 | return endp && *endp == 0 && !errno && | |
473 | n >= std::numeric_limits<int64_t>::min() && | |
474 | n <= std::numeric_limits<int64_t>::max(); | |
475 | } | |
476 | ||
477 | bool ParseDouble(const std::string& str, double *out) | |
478 | { | |
479 | if (!ParsePrechecks(str)) | |
480 | return false; | |
481 | if (str.size() >= 2 && str[0] == '0' && str[1] == 'x') // No hexadecimal floats allowed | |
482 | return false; | |
483 | char *endp = NULL; | |
484 | errno = 0; // strtod will not set errno if valid | |
485 | double n = strtod(str.c_str(), &endp); | |
486 | if(out) *out = n; | |
487 | return endp && *endp == 0 && !errno; | |
488 | } | |
489 | ||
ad49c256 WL |
490 | std::string FormatParagraph(const std::string in, size_t width, size_t indent) |
491 | { | |
492 | std::stringstream out; | |
493 | size_t col = 0; | |
494 | size_t ptr = 0; | |
495 | while(ptr < in.size()) | |
496 | { | |
497 | // Find beginning of next word | |
498 | ptr = in.find_first_not_of(' ', ptr); | |
499 | if (ptr == std::string::npos) | |
500 | break; | |
501 | // Find end of next word | |
502 | size_t endword = in.find_first_of(' ', ptr); | |
503 | if (endword == std::string::npos) | |
504 | endword = in.size(); | |
505 | // Add newline and indentation if this wraps over the allowed width | |
506 | if (col > 0) | |
507 | { | |
508 | if ((col + endword - ptr) > width) | |
509 | { | |
510 | out << '\n'; | |
511 | for(size_t i=0; i<indent; ++i) | |
512 | out << ' '; | |
513 | col = 0; | |
514 | } else | |
515 | out << ' '; | |
516 | } | |
517 | // Append word | |
518 | out << in.substr(ptr, endword - ptr); | |
83b81f6c | 519 | col += endword - ptr + 1; |
ad49c256 WL |
520 | ptr = endword; |
521 | } | |
522 | return out.str(); | |
523 | } | |
524 | ||
525 | std::string i64tostr(int64_t n) | |
526 | { | |
527 | return strprintf("%d", n); | |
528 | } | |
529 | ||
530 | std::string itostr(int n) | |
531 | { | |
532 | return strprintf("%d", n); | |
533 | } | |
534 | ||
535 | int64_t atoi64(const char* psz) | |
536 | { | |
537 | #ifdef _MSC_VER | |
538 | return _atoi64(psz); | |
539 | #else | |
540 | return strtoll(psz, NULL, 10); | |
541 | #endif | |
542 | } | |
543 | ||
544 | int64_t atoi64(const std::string& str) | |
545 | { | |
546 | #ifdef _MSC_VER | |
547 | return _atoi64(str.c_str()); | |
548 | #else | |
549 | return strtoll(str.c_str(), NULL, 10); | |
550 | #endif | |
551 | } | |
552 | ||
553 | int atoi(const std::string& str) | |
554 | { | |
555 | return atoi(str.c_str()); | |
556 | } | |
fed500e2 WL |
557 | |
558 | /** Upper bound for mantissa. | |
559 | * 10^18-1 is the largest arbitrary decimal that will fit in a signed 64-bit integer. | |
560 | * Larger integers cannot consist of arbitrary combinations of 0-9: | |
561 | * | |
562 | * 999999999999999999 1^18-1 | |
563 | * 9223372036854775807 (1<<63)-1 (max int64_t) | |
564 | * 9999999999999999999 1^19-1 (would overflow) | |
565 | */ | |
566 | static const int64_t UPPER_BOUND = 1000000000000000000LL - 1LL; | |
567 | ||
568 | /** Helper function for ParseFixedPoint */ | |
569 | static inline bool ProcessMantissaDigit(char ch, int64_t &mantissa, int &mantissa_tzeros) | |
570 | { | |
571 | if(ch == '0') | |
572 | ++mantissa_tzeros; | |
573 | else { | |
574 | for (int i=0; i<=mantissa_tzeros; ++i) { | |
575 | if (mantissa > (UPPER_BOUND / 10LL)) | |
576 | return false; /* overflow */ | |
577 | mantissa *= 10; | |
578 | } | |
579 | mantissa += ch - '0'; | |
580 | mantissa_tzeros = 0; | |
581 | } | |
582 | return true; | |
583 | } | |
584 | ||
585 | bool ParseFixedPoint(const std::string &val, int decimals, int64_t *amount_out) | |
586 | { | |
587 | int64_t mantissa = 0; | |
588 | int64_t exponent = 0; | |
589 | int mantissa_tzeros = 0; | |
590 | bool mantissa_sign = false; | |
591 | bool exponent_sign = false; | |
592 | int ptr = 0; | |
593 | int end = val.size(); | |
594 | int point_ofs = 0; | |
595 | ||
596 | if (ptr < end && val[ptr] == '-') { | |
597 | mantissa_sign = true; | |
598 | ++ptr; | |
599 | } | |
600 | if (ptr < end) | |
601 | { | |
602 | if (val[ptr] == '0') { | |
603 | /* pass single 0 */ | |
604 | ++ptr; | |
605 | } else if (val[ptr] >= '1' && val[ptr] <= '9') { | |
606 | while (ptr < end && val[ptr] >= '0' && val[ptr] <= '9') { | |
607 | if (!ProcessMantissaDigit(val[ptr], mantissa, mantissa_tzeros)) | |
608 | return false; /* overflow */ | |
609 | ++ptr; | |
610 | } | |
611 | } else return false; /* missing expected digit */ | |
612 | } else return false; /* empty string or loose '-' */ | |
613 | if (ptr < end && val[ptr] == '.') | |
614 | { | |
615 | ++ptr; | |
616 | if (ptr < end && val[ptr] >= '0' && val[ptr] <= '9') | |
617 | { | |
618 | while (ptr < end && val[ptr] >= '0' && val[ptr] <= '9') { | |
619 | if (!ProcessMantissaDigit(val[ptr], mantissa, mantissa_tzeros)) | |
620 | return false; /* overflow */ | |
621 | ++ptr; | |
622 | ++point_ofs; | |
623 | } | |
624 | } else return false; /* missing expected digit */ | |
625 | } | |
626 | if (ptr < end && (val[ptr] == 'e' || val[ptr] == 'E')) | |
627 | { | |
628 | ++ptr; | |
629 | if (ptr < end && val[ptr] == '+') | |
630 | ++ptr; | |
631 | else if (ptr < end && val[ptr] == '-') { | |
632 | exponent_sign = true; | |
633 | ++ptr; | |
634 | } | |
635 | if (ptr < end && val[ptr] >= '0' && val[ptr] <= '9') { | |
636 | while (ptr < end && val[ptr] >= '0' && val[ptr] <= '9') { | |
637 | if (exponent > (UPPER_BOUND / 10LL)) | |
638 | return false; /* overflow */ | |
639 | exponent = exponent * 10 + val[ptr] - '0'; | |
640 | ++ptr; | |
641 | } | |
642 | } else return false; /* missing expected digit */ | |
643 | } | |
644 | if (ptr != end) | |
645 | return false; /* trailing garbage */ | |
646 | ||
647 | /* finalize exponent */ | |
648 | if (exponent_sign) | |
649 | exponent = -exponent; | |
650 | exponent = exponent - point_ofs + mantissa_tzeros; | |
651 | ||
652 | /* finalize mantissa */ | |
653 | if (mantissa_sign) | |
654 | mantissa = -mantissa; | |
655 | ||
656 | /* convert to one 64-bit fixed-point value */ | |
657 | exponent += decimals; | |
658 | if (exponent < 0) | |
659 | return false; /* cannot represent values smaller than 10^-decimals */ | |
660 | if (exponent >= 18) | |
661 | return false; /* cannot represent values larger than or equal to 10^(18-decimals) */ | |
662 | ||
663 | for (int i=0; i < exponent; ++i) { | |
664 | if (mantissa > (UPPER_BOUND / 10LL) || mantissa < -(UPPER_BOUND / 10LL)) | |
665 | return false; /* overflow */ | |
666 | mantissa *= 10; | |
667 | } | |
668 | if (mantissa > UPPER_BOUND || mantissa < -UPPER_BOUND) | |
669 | return false; /* overflow */ | |
670 | ||
671 | if (amount_out) | |
672 | *amount_out = mantissa; | |
673 | ||
674 | return true; | |
675 | } | |
676 |