]> Git Repo - VerusCoin.git/blame - src/utilstrencodings.cpp
Cleanup and complete basic currency launch changes
[VerusCoin.git] / src / utilstrencodings.cpp
CommitLineData
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
bc909a7a 4// file COPYING or https://www.opensource.org/licenses/mit-license.php .
ad49c256
WL
5
6#include "utilstrencodings.h"
7
8#include "tinyformat.h"
9
352058e8
CF
10#include <cstdlib>
11#include <cstring>
771d5002 12#include <errno.h>
b174b7e3 13#include <iomanip>
771d5002 14#include <limits>
611116d4 15
ad49c256
WL
16using namespace std;
17
3c1db170
M
18static const string CHARS_ALPHA_NUM = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
19
20static const string SAFE_CHARS[] =
21{
22 CHARS_ALPHA_NUM + " .,;_/:?@()", // SAFE_CHARS_DEFAULT
5efc2365
AD
23 CHARS_ALPHA_NUM + " .,;_?@", // SAFE_CHARS_UA_COMMENT
24 CHARS_ALPHA_NUM + "!*'();:@&=+$,/?#[]-_.~%" // SAFE_CHARS_URI
3c1db170
M
25};
26
27string SanitizeString(const string& str, int rule)
ad49c256
WL
28{
29 string strResult;
30 for (std::string::size_type i = 0; i < str.size(); i++)
31 {
3c1db170 32 if (SAFE_CHARS[rule].find(str[i]) != std::string::npos)
ad49c256
WL
33 strResult.push_back(str[i]);
34 }
35 return strResult;
36}
37
9064d73b
S
38string SanitizeFilename(const string& str)
39{
40 /**
41 * safeChars chosen to restrict filename, keeping it simple to avoid cross-platform issues.
42 * http://stackoverflow.com/a/2306003
43 */
44 static string safeChars("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890");
45 string strResult;
46 for (std::string::size_type i = 0; i < str.size(); i++)
47 {
48 if (safeChars.find(str[i]) != std::string::npos)
49 strResult.push_back(str[i]);
50 }
51 return strResult;
52}
53
b174b7e3
JG
54std::string HexInt(uint32_t val)
55{
56 std::stringstream ss;
57 ss << std::setfill('0') << std::setw(sizeof(uint32_t) * 2) << std::hex << val;
58 return ss.str();
59}
60
072099d7
S
61uint32_t ParseHexToUInt32(const std::string& str) {
62 std::istringstream converter(str);
63 uint32_t value;
64 converter >> std::hex >> value;
65 return value;
66}
67
ad49c256
WL
68const signed char p_util_hexdigit[256] =
69{ -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
70 -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
71 -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
72 0,1,2,3,4,5,6,7,8,9,-1,-1,-1,-1,-1,-1,
73 -1,0xa,0xb,0xc,0xd,0xe,0xf,-1,-1,-1,-1,-1,-1,-1,-1,-1,
74 -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
75 -1,0xa,0xb,0xc,0xd,0xe,0xf,-1,-1,-1,-1,-1,-1,-1,-1,-1,
76 -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
77 -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
78 -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
79 -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
80 -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
81 -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
82 -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
83 -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
84 -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, };
85
86signed char HexDigit(char c)
87{
88 return p_util_hexdigit[(unsigned char)c];
89}
90
91bool IsHex(const string& str)
92{
352058e8 93 for(std::string::const_iterator it(str.begin()); it != str.end(); ++it)
ad49c256 94 {
352058e8 95 if (HexDigit(*it) < 0)
ad49c256
WL
96 return false;
97 }
98 return (str.size() > 0) && (str.size()%2 == 0);
99}
100
101vector<unsigned char> ParseHex(const char* psz)
102{
103 // convert hex dump to vector
104 vector<unsigned char> vch;
105 while (true)
106 {
107 while (isspace(*psz))
108 psz++;
109 signed char c = HexDigit(*psz++);
110 if (c == (signed char)-1)
111 break;
112 unsigned char n = (c << 4);
113 c = HexDigit(*psz++);
114 if (c == (signed char)-1)
115 break;
116 n |= c;
117 vch.push_back(n);
118 }
119 return vch;
120}
121
122vector<unsigned char> ParseHex(const string& str)
123{
124 return ParseHex(str.c_str());
125}
126
127string EncodeBase64(const unsigned char* pch, size_t len)
128{
129 static const char *pbase64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
130
6a2cc8dd
PW
131 std::string str;
132 str.reserve(((len + 2) / 3) * 4);
133 ConvertBits<8, 6, true>([&](int v) { str += pbase64[v]; }, pch, pch + len);
134 while (str.size() % 4) str += '=';
135 return str;
ad49c256
WL
136}
137
138string EncodeBase64(const string& str)
139{
140 return EncodeBase64((const unsigned char*)str.c_str(), str.size());
141}
142
143vector<unsigned char> DecodeBase64(const char* p, bool* pfInvalid)
144{
145 static const int decode64_table[256] =
146 {
147 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
148 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
149 -1, -1, -1, 62, -1, -1, -1, 63, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -1, -1,
150 -1, -1, -1, -1, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
151 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, -1, -1, 26, 27, 28,
152 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48,
153 49, 50, 51, -1, -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, -1, -1, -1, -1,
155 -1, -1, -1, -1, -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, -1, -1, -1, -1,
157 -1, -1, -1, -1, -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, -1, -1, -1, -1,
159 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
160 };
161
6a2cc8dd
PW
162 const char* e = p;
163 std::vector<uint8_t> val;
164 val.reserve(strlen(p));
165 while (*p != 0) {
166 int x = decode64_table[(unsigned char)*p];
167 if (x == -1) break;
168 val.push_back(x);
169 ++p;
ad49c256
WL
170 }
171
6a2cc8dd
PW
172 std::vector<unsigned char> ret;
173 ret.reserve((val.size() * 3) / 4);
174 bool valid = ConvertBits<6, 8, false>([&](unsigned char c) { ret.push_back(c); }, val.begin(), val.end());
175
176 const char* q = p;
177 while (valid && *p != 0) {
178 if (*p != '=') {
179 valid = false;
180 break;
ad49c256 181 }
6a2cc8dd
PW
182 ++p;
183 }
184 valid = valid && (p - e) % 4 == 0 && p - q < 4;
185 if (pfInvalid) *pfInvalid = !valid;
ad49c256 186
6a2cc8dd 187 return ret;
ad49c256
WL
188}
189
190string DecodeBase64(const string& str)
191{
192 vector<unsigned char> vchRet = DecodeBase64(str.c_str());
018cec7c 193 return (vchRet.size() == 0) ? string() : string((const char*)&vchRet[0], vchRet.size());
ad49c256
WL
194}
195
196string EncodeBase32(const unsigned char* pch, size_t len)
197{
198 static const char *pbase32 = "abcdefghijklmnopqrstuvwxyz234567";
199
6a2cc8dd
PW
200 std::string str;
201 str.reserve(((len + 4) / 5) * 8);
202 ConvertBits<8, 5, true>([&](int v) { str += pbase32[v]; }, pch, pch + len);
203 while (str.size() % 8) str += '=';
204 return str;
ad49c256
WL
205}
206
207string EncodeBase32(const string& str)
208{
209 return EncodeBase32((const unsigned char*)str.c_str(), str.size());
210}
211
212vector<unsigned char> DecodeBase32(const char* p, bool* pfInvalid)
213{
214 static const int decode32_table[256] =
215 {
216 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
217 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
218 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 26, 27, 28, 29, 30, 31, -1, -1, -1, -1,
219 -1, -1, -1, -1, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
220 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, -1, -1, 0, 1, 2,
221 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22,
222 23, 24, 25, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
223 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
224 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
225 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
226 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
227 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
228 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
229 };
230
6a2cc8dd
PW
231 const char* e = p;
232 std::vector<uint8_t> val;
233 val.reserve(strlen(p));
234 while (*p != 0) {
235 int x = decode32_table[(unsigned char)*p];
236 if (x == -1) break;
237 val.push_back(x);
238 ++p;
ad49c256
WL
239 }
240
6a2cc8dd
PW
241 std::vector<unsigned char> ret;
242 ret.reserve((val.size() * 5) / 8);
243 bool valid = ConvertBits<5, 8, false>([&](unsigned char c) { ret.push_back(c); }, val.begin(), val.end());
244
245 const char* q = p;
246 while (valid && *p != 0) {
247 if (*p != '=') {
248 valid = false;
249 break;
ad49c256 250 }
6a2cc8dd
PW
251 ++p;
252 }
253 valid = valid && (p - e) % 8 == 0 && p - q < 8;
254 if (pfInvalid) *pfInvalid = !valid;
ad49c256 255
6a2cc8dd 256 return ret;
ad49c256
WL
257}
258
259string DecodeBase32(const string& str)
260{
261 vector<unsigned char> vchRet = DecodeBase32(str.c_str());
018cec7c 262 return (vchRet.size() == 0) ? string() : string((const char*)&vchRet[0], vchRet.size());
ad49c256
WL
263}
264
5960d700
WL
265static bool ParsePrechecks(const std::string& str)
266{
267 if (str.empty()) // No empty string allowed
268 return false;
269 if (str.size() >= 1 && (isspace(str[0]) || isspace(str[str.size()-1]))) // No padding allowed
270 return false;
271 if (str.size() != strlen(str.c_str())) // No embedded NUL characters allowed
272 return false;
273 return true;
274}
275
ad49c256
WL
276bool ParseInt32(const std::string& str, int32_t *out)
277{
5960d700
WL
278 if (!ParsePrechecks(str))
279 return false;
ad49c256
WL
280 char *endp = NULL;
281 errno = 0; // strtol will not set errno if valid
282 long int n = strtol(str.c_str(), &endp, 10);
5960d700 283 if(out) *out = (int32_t)n;
ad49c256
WL
284 // Note that strtol returns a *long int*, so even if strtol doesn't report a over/underflow
285 // we still have to check that the returned value is within the range of an *int32_t*. On 64-bit
286 // platforms the size of these types may be different.
287 return endp && *endp == 0 && !errno &&
288 n >= std::numeric_limits<int32_t>::min() &&
289 n <= std::numeric_limits<int32_t>::max();
290}
291
5960d700
WL
292bool ParseInt64(const std::string& str, int64_t *out)
293{
294 if (!ParsePrechecks(str))
295 return false;
296 char *endp = NULL;
297 errno = 0; // strtoll will not set errno if valid
298 long long int n = strtoll(str.c_str(), &endp, 10);
299 if(out) *out = (int64_t)n;
300 // Note that strtoll returns a *long long int*, so even if strtol doesn't report a over/underflow
301 // we still have to check that the returned value is within the range of an *int64_t*.
302 return endp && *endp == 0 && !errno &&
303 n >= std::numeric_limits<int64_t>::min() &&
304 n <= std::numeric_limits<int64_t>::max();
305}
306
307bool ParseDouble(const std::string& str, double *out)
308{
309 if (!ParsePrechecks(str))
310 return false;
311 if (str.size() >= 2 && str[0] == '0' && str[1] == 'x') // No hexadecimal floats allowed
312 return false;
a8c22cc4
WL
313 std::istringstream text(str);
314 text.imbue(std::locale::classic());
315 double result;
316 text >> result;
317 if(out) *out = result;
318 return text.eof() && !text.fail();
5960d700
WL
319}
320
db954a65 321std::string FormatParagraph(const std::string& in, size_t width, size_t indent)
ad49c256
WL
322{
323 std::stringstream out;
324 size_t col = 0;
325 size_t ptr = 0;
326 while(ptr < in.size())
327 {
328 // Find beginning of next word
329 ptr = in.find_first_not_of(' ', ptr);
330 if (ptr == std::string::npos)
331 break;
332 // Find end of next word
333 size_t endword = in.find_first_of(' ', ptr);
334 if (endword == std::string::npos)
335 endword = in.size();
336 // Add newline and indentation if this wraps over the allowed width
337 if (col > 0)
338 {
339 if ((col + endword - ptr) > width)
340 {
341 out << '\n';
342 for(size_t i=0; i<indent; ++i)
343 out << ' ';
344 col = 0;
345 } else
346 out << ' ';
347 }
348 // Append word
349 out << in.substr(ptr, endword - ptr);
83b81f6c 350 col += endword - ptr + 1;
ad49c256
WL
351 ptr = endword;
352 }
353 return out.str();
354}
355
356std::string i64tostr(int64_t n)
357{
358 return strprintf("%d", n);
359}
360
361std::string itostr(int n)
362{
363 return strprintf("%d", n);
364}
365
366int64_t atoi64(const char* psz)
367{
368#ifdef _MSC_VER
369 return _atoi64(psz);
370#else
371 return strtoll(psz, NULL, 10);
372#endif
373}
374
375int64_t atoi64(const std::string& str)
376{
377#ifdef _MSC_VER
378 return _atoi64(str.c_str());
379#else
380 return strtoll(str.c_str(), NULL, 10);
381#endif
382}
383
384int atoi(const std::string& str)
385{
386 return atoi(str.c_str());
387}
fed500e2
WL
388
389/** Upper bound for mantissa.
390 * 10^18-1 is the largest arbitrary decimal that will fit in a signed 64-bit integer.
391 * Larger integers cannot consist of arbitrary combinations of 0-9:
392 *
393 * 999999999999999999 1^18-1
394 * 9223372036854775807 (1<<63)-1 (max int64_t)
395 * 9999999999999999999 1^19-1 (would overflow)
396 */
397static const int64_t UPPER_BOUND = 1000000000000000000LL - 1LL;
398
399/** Helper function for ParseFixedPoint */
400static inline bool ProcessMantissaDigit(char ch, int64_t &mantissa, int &mantissa_tzeros)
401{
402 if(ch == '0')
403 ++mantissa_tzeros;
404 else {
405 for (int i=0; i<=mantissa_tzeros; ++i) {
406 if (mantissa > (UPPER_BOUND / 10LL))
407 return false; /* overflow */
408 mantissa *= 10;
409 }
410 mantissa += ch - '0';
411 mantissa_tzeros = 0;
412 }
413 return true;
414}
415
416bool ParseFixedPoint(const std::string &val, int decimals, int64_t *amount_out)
417{
418 int64_t mantissa = 0;
419 int64_t exponent = 0;
420 int mantissa_tzeros = 0;
421 bool mantissa_sign = false;
422 bool exponent_sign = false;
423 int ptr = 0;
424 int end = val.size();
425 int point_ofs = 0;
426
427 if (ptr < end && val[ptr] == '-') {
428 mantissa_sign = true;
429 ++ptr;
430 }
431 if (ptr < end)
432 {
433 if (val[ptr] == '0') {
434 /* pass single 0 */
435 ++ptr;
436 } else if (val[ptr] >= '1' && val[ptr] <= '9') {
437 while (ptr < end && val[ptr] >= '0' && val[ptr] <= '9') {
438 if (!ProcessMantissaDigit(val[ptr], mantissa, mantissa_tzeros))
439 return false; /* overflow */
440 ++ptr;
441 }
442 } else return false; /* missing expected digit */
443 } else return false; /* empty string or loose '-' */
444 if (ptr < end && val[ptr] == '.')
445 {
446 ++ptr;
447 if (ptr < end && val[ptr] >= '0' && val[ptr] <= '9')
448 {
449 while (ptr < end && val[ptr] >= '0' && val[ptr] <= '9') {
450 if (!ProcessMantissaDigit(val[ptr], mantissa, mantissa_tzeros))
451 return false; /* overflow */
452 ++ptr;
453 ++point_ofs;
454 }
455 } else return false; /* missing expected digit */
456 }
457 if (ptr < end && (val[ptr] == 'e' || val[ptr] == 'E'))
458 {
459 ++ptr;
460 if (ptr < end && val[ptr] == '+')
461 ++ptr;
462 else if (ptr < end && val[ptr] == '-') {
463 exponent_sign = true;
464 ++ptr;
465 }
466 if (ptr < end && val[ptr] >= '0' && val[ptr] <= '9') {
467 while (ptr < end && val[ptr] >= '0' && val[ptr] <= '9') {
468 if (exponent > (UPPER_BOUND / 10LL))
469 return false; /* overflow */
470 exponent = exponent * 10 + val[ptr] - '0';
471 ++ptr;
472 }
473 } else return false; /* missing expected digit */
474 }
475 if (ptr != end)
476 return false; /* trailing garbage */
477
478 /* finalize exponent */
479 if (exponent_sign)
480 exponent = -exponent;
481 exponent = exponent - point_ofs + mantissa_tzeros;
482
483 /* finalize mantissa */
484 if (mantissa_sign)
485 mantissa = -mantissa;
486
487 /* convert to one 64-bit fixed-point value */
488 exponent += decimals;
489 if (exponent < 0)
490 return false; /* cannot represent values smaller than 10^-decimals */
491 if (exponent >= 18)
492 return false; /* cannot represent values larger than or equal to 10^(18-decimals) */
493
494 for (int i=0; i < exponent; ++i) {
495 if (mantissa > (UPPER_BOUND / 10LL) || mantissa < -(UPPER_BOUND / 10LL))
496 return false; /* overflow */
497 mantissa *= 10;
498 }
499 if (mantissa > UPPER_BOUND || mantissa < -UPPER_BOUND)
500 return false; /* overflow */
501
502 if (amount_out)
503 *amount_out = mantissa;
504
505 return true;
506}
507
This page took 0.217167 seconds and 4 git commands to generate.