line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
#include "from_chars.h" |
2
|
|
|
|
|
|
|
#include // isspace |
3
|
|
|
|
|
|
|
#include // memcpy |
4
|
|
|
|
|
|
|
#include |
5
|
|
|
|
|
|
|
|
6
|
|
|
|
|
|
|
namespace panda { |
7
|
|
|
|
|
|
|
|
8
|
|
|
|
|
|
|
static unsigned _index[256]; |
9
|
|
|
|
|
|
|
static char _rindex[36]; |
10
|
|
|
|
|
|
|
|
11
|
18
|
|
|
|
|
|
static bool _init () { |
12
|
4626
|
100
|
|
|
|
|
for (auto& val : _index) val = 255; |
13
|
198
|
100
|
|
|
|
|
for (int i = 0; i <= 9; ++i) _index['0' + i] = i; |
14
|
486
|
100
|
|
|
|
|
for (int i = 0; i <= 25; ++i) _index['a' + i] = i+10; |
15
|
486
|
100
|
|
|
|
|
for (int i = 0; i <= 25; ++i) _index['A' + i] = i+10; |
16
|
198
|
100
|
|
|
|
|
for (int i = 0; i <= 9; ++i) _rindex[i] = '0' + i; |
17
|
486
|
100
|
|
|
|
|
for (int i = 0; i <= 25; ++i) _rindex[i + 10] = 'a' + i; |
18
|
18
|
|
|
|
|
|
return true; |
19
|
|
|
|
|
|
|
} |
20
|
18
|
|
|
|
|
|
static const bool _inited = _init(); |
21
|
|
|
|
|
|
|
|
22
|
758
|
|
|
|
|
|
static inline bool _is_space (unsigned char ch) { return std::isspace(ch); } |
23
|
|
|
|
|
|
|
//static inline bool _is_space (unsigned wchar_t ch) { return std::iswspace(ch); } |
24
|
|
|
|
|
|
|
|
25
|
|
|
|
|
|
|
template |
26
|
|
|
|
|
|
|
static inline bool _find_sign (const C*& ptr, const C* const end) { |
27
|
|
|
|
|
|
|
if (ptr == end) return false; |
28
|
|
|
|
|
|
|
|
29
|
|
|
|
|
|
|
bool minus = false; |
30
|
|
|
|
|
|
|
if (*ptr == '-') { ++ptr; minus = true; } |
31
|
|
|
|
|
|
|
else if (*ptr == '+') ++ptr; |
32
|
|
|
|
|
|
|
|
33
|
|
|
|
|
|
|
return minus; |
34
|
|
|
|
|
|
|
} |
35
|
|
|
|
|
|
|
|
36
|
|
|
|
|
|
|
template |
37
|
223
|
|
|
|
|
|
static inline UT _parse (const UC*& ptr, const UC* const end, unsigned base, UT max, bool& overflow) { |
38
|
223
|
|
|
|
|
|
UT res = 0; |
39
|
223
|
|
|
|
|
|
UT maxmp = max / base; |
40
|
223
|
|
|
|
|
|
overflow = false; |
41
|
|
|
|
|
|
|
|
42
|
909
|
0
|
|
|
|
|
for (; ptr != end; ++ptr) { |
|
|
100
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
43
|
|
|
|
|
|
|
if (sizeof(UC) > 1 && *ptr > 255) break; |
44
|
792
|
|
|
|
|
|
auto val = _index[*ptr]; |
45
|
792
|
0
|
|
|
|
|
if (val >= base) break; |
|
|
100
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
46
|
718
|
0
|
|
|
|
|
if (res > maxmp) { overflow = true; res = max; break; } |
|
|
100
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
47
|
702
|
|
|
|
|
|
res *= base; |
48
|
702
|
0
|
|
|
|
|
if (val > (UT)(max - res)) { overflow = true; res = max; break; } |
|
|
100
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
49
|
686
|
|
|
|
|
|
res += val; |
50
|
|
|
|
|
|
|
} |
51
|
|
|
|
|
|
|
|
52
|
1050
|
0
|
|
|
|
|
if (overflow) for (; ptr != end; ++ptr) if ((sizeof(UC) > 1 && *ptr > 255) || _index[*ptr] >= base) break; // move to the end of the number |
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
53
|
|
|
|
|
|
|
|
54
|
223
|
|
|
|
|
|
return res; |
55
|
|
|
|
|
|
|
} |
56
|
|
|
|
|
|
|
|
57
|
|
|
|
|
|
|
template |
58
|
99
|
|
|
|
|
|
static inline typename std::enable_if::value, from_chars_result>::type _from_chars (const C* s, const C* send, UT& value, unsigned base) { |
59
|
|
|
|
|
|
|
using UC = typename std::make_unsigned::type; |
60
|
99
|
|
|
|
|
|
const UC* ptr = (const UC*)s; |
61
|
99
|
|
|
|
|
|
const UC* const end = (const UC*)send; |
62
|
99
|
0
|
|
|
|
|
if (base < 2 || base > 36) base = 10; |
|
|
0
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
63
|
|
|
|
|
|
|
|
64
|
155
|
0
|
|
|
|
|
while (ptr != end && _is_space(*ptr)) ++ptr; // skip whitespaces in the beginning |
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
65
|
|
|
|
|
|
|
|
66
|
|
|
|
|
|
|
bool overflow; |
67
|
99
|
|
|
|
|
|
auto tmp = ptr; |
68
|
99
|
|
|
|
|
|
value = _parse(ptr, end, base, std::numeric_limits::max(), overflow); |
69
|
|
|
|
|
|
|
|
70
|
99
|
0
|
|
|
|
|
if (ptr - tmp == 0) return {s, make_error_code(std::errc::invalid_argument)}; |
|
|
100
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
71
|
74
|
0
|
|
|
|
|
if (overflow) return {(const C*)ptr, make_error_code(std::errc::result_out_of_range)}; |
|
|
100
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
72
|
99
|
|
|
|
|
|
return {(const C*)ptr, std::error_code()}; |
73
|
|
|
|
|
|
|
} |
74
|
|
|
|
|
|
|
|
75
|
|
|
|
|
|
|
template |
76
|
124
|
|
|
|
|
|
static inline typename std::enable_if::value, from_chars_result>::type _from_chars (const C* s, const C* send, T& value, unsigned base) { |
77
|
|
|
|
|
|
|
using UC = typename std::make_unsigned::type; |
78
|
|
|
|
|
|
|
using UT = typename std::make_unsigned::type; |
79
|
124
|
|
|
|
|
|
const UC* ptr = (const UC*)s; |
80
|
124
|
|
|
|
|
|
const UC* const end = (const UC*)send; |
81
|
124
|
0
|
|
|
|
|
if (base < 2 || base > 36) base = 10; |
|
|
0
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
82
|
|
|
|
|
|
|
|
83
|
232
|
0
|
|
|
|
|
while (ptr != end && _is_space(*ptr)) ++ptr; // skip whitespaces in the beginning |
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
84
|
|
|
|
|
|
|
|
85
|
124
|
|
|
|
|
|
bool minus = false; |
86
|
124
|
0
|
|
|
|
|
if (ptr != end && *ptr == '-') { ++ptr; minus = true; } |
|
|
0
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
87
|
|
|
|
|
|
|
bool overflow; |
88
|
124
|
|
|
|
|
|
auto tmp = ptr; |
89
|
|
|
|
|
|
|
|
90
|
124
|
0
|
|
|
|
|
if (minus) { |
|
|
100
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
91
|
48
|
|
|
|
|
|
UT max = (UT)std::numeric_limits::max() - (T)(std::numeric_limits::max() + std::numeric_limits::min()); |
92
|
48
|
|
|
|
|
|
UT tmp = _parse(ptr, end, base, max, overflow); |
93
|
48
|
|
|
|
|
|
value = (T)0 - tmp; |
94
|
|
|
|
|
|
|
} else { |
95
|
76
|
|
|
|
|
|
value = _parse(ptr, end, base, (UT)std::numeric_limits::max(), overflow); |
96
|
|
|
|
|
|
|
} |
97
|
|
|
|
|
|
|
|
98
|
124
|
0
|
|
|
|
|
if (ptr - tmp == 0) return {s, make_error_code(std::errc::invalid_argument)}; |
|
|
100
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
99
|
108
|
0
|
|
|
|
|
if (overflow) return {(const C*)ptr, make_error_code(std::errc::result_out_of_range)}; |
|
|
100
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
100
|
124
|
|
|
|
|
|
return {(const C*)ptr, std::error_code()}; |
101
|
|
|
|
|
|
|
} |
102
|
|
|
|
|
|
|
|
103
|
62
|
|
|
|
|
|
from_chars_result from_chars (const char* first, const char* last, int8_t& value, int base) { return _from_chars (first, last, value, base); } |
104
|
62
|
|
|
|
|
|
from_chars_result from_chars (const char* first, const char* last, int16_t& value, int base) { return _from_chars (first, last, value, base); } |
105
|
62
|
|
|
|
|
|
from_chars_result from_chars (const char* first, const char* last, int& value, int base) { return _from_chars (first, last, value, base); } |
106
|
62
|
|
|
|
|
|
from_chars_result from_chars (const char* first, const char* last, long& value, int base) { return _from_chars (first, last, value, base); } |
107
|
0
|
|
|
|
|
|
from_chars_result from_chars (const char* first, const char* last, long long& value, int base) { return _from_chars (first, last, value, base); } |
108
|
46
|
|
|
|
|
|
from_chars_result from_chars (const char* first, const char* last, uint8_t& value, int base) { return _from_chars (first, last, value, base); } |
109
|
46
|
|
|
|
|
|
from_chars_result from_chars (const char* first, const char* last, uint16_t& value, int base) { return _from_chars (first, last, value, base); } |
110
|
46
|
|
|
|
|
|
from_chars_result from_chars (const char* first, const char* last, unsigned& value, int base) { return _from_chars (first, last, value, base); } |
111
|
60
|
|
|
|
|
|
from_chars_result from_chars (const char* first, const char* last, unsigned long& value, int base) { return _from_chars (first, last, value, base); } |
112
|
0
|
|
|
|
|
|
from_chars_result from_chars (const char* first, const char* last, unsigned long long& value, int base) { return _from_chars(first, last, value, base); } |
113
|
|
|
|
|
|
|
|
114
|
|
|
|
|
|
|
template |
115
|
51
|
|
|
|
|
|
static inline C* _compile (C* ptr, UT value, int base) { |
116
|
152
|
0
|
|
|
|
|
do { |
|
|
0
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
117
|
152
|
|
|
|
|
|
*--ptr = _rindex[value % base]; |
118
|
152
|
|
|
|
|
|
value /= base; |
119
|
|
|
|
|
|
|
} while (value != 0); |
120
|
51
|
|
|
|
|
|
return ptr; |
121
|
|
|
|
|
|
|
} |
122
|
|
|
|
|
|
|
|
123
|
|
|
|
|
|
|
template |
124
|
24
|
|
|
|
|
|
static inline typename std::enable_if::value, to_chars_result>::type _to_chars (C* d, C* dend, UT value, int base) { |
125
|
24
|
0
|
|
|
|
|
if (base < 2 || base > 36) base = 10; |
|
|
0
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
126
|
24
|
|
|
|
|
|
int maxsize = std::ceil(std::numeric_limits::digits * std::log(2) / std::log(base)); /* enough for UT-bit integer represented in given base */ |
127
|
24
|
|
|
|
|
|
char strval[maxsize]; |
128
|
24
|
|
|
|
|
|
char* end = strval + maxsize; |
129
|
24
|
|
|
|
|
|
char* begin = _compile(end, value, base); |
130
|
24
|
|
|
|
|
|
auto len = end - begin; |
131
|
24
|
0
|
|
|
|
|
if (dend - d < len) return {dend, make_error_code(std::errc::value_too_large)}; |
|
|
100
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
132
|
20
|
|
|
|
|
|
std::memcpy(d, begin, len); |
133
|
24
|
|
|
|
|
|
return {d + len, std::error_code()}; |
134
|
|
|
|
|
|
|
} |
135
|
|
|
|
|
|
|
|
136
|
|
|
|
|
|
|
template |
137
|
27
|
|
|
|
|
|
static inline typename std::enable_if::value, to_chars_result>::type _to_chars (C* d, C* dend, T value, int base) { |
138
|
|
|
|
|
|
|
using UT = typename std::make_unsigned::type; |
139
|
27
|
0
|
|
|
|
|
if (base < 2 || base > 36) base = 10; |
|
|
0
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
140
|
27
|
|
|
|
|
|
int maxsize = std::ceil(std::numeric_limits::digits * std::log(2) / std::log(base) + 1); |
141
|
27
|
|
|
|
|
|
char strval[maxsize]; |
142
|
27
|
|
|
|
|
|
char* end = strval + maxsize; |
143
|
|
|
|
|
|
|
char* begin; |
144
|
|
|
|
|
|
|
|
145
|
27
|
0
|
|
|
|
|
if (value >= 0) begin = _compile(end, value, base); |
|
|
50
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
146
|
|
|
|
|
|
|
else { |
147
|
0
|
|
|
|
|
|
UT positive_value = (UT)std::numeric_limits::max() - (T)(std::numeric_limits::max() + value); |
148
|
0
|
|
|
|
|
|
begin = _compile(end, positive_value, base); |
149
|
0
|
|
|
|
|
|
*--begin = '-'; |
150
|
|
|
|
|
|
|
} |
151
|
|
|
|
|
|
|
|
152
|
27
|
|
|
|
|
|
auto len = end - begin; |
153
|
27
|
0
|
|
|
|
|
if (dend - d < len) return {dend, make_error_code(std::errc::value_too_large)}; |
|
|
100
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
154
|
23
|
|
|
|
|
|
std::memcpy(d, begin, len); |
155
|
27
|
|
|
|
|
|
return {d + len, std::error_code()}; |
156
|
|
|
|
|
|
|
} |
157
|
|
|
|
|
|
|
|
158
|
12
|
|
|
|
|
|
to_chars_result to_chars (char* first, char* last, int8_t value, int base) { return _to_chars (first, last, value, base); } |
159
|
12
|
|
|
|
|
|
to_chars_result to_chars (char* first, char* last, int16_t value, int base) { return _to_chars (first, last, value, base); } |
160
|
18
|
|
|
|
|
|
to_chars_result to_chars (char* first, char* last, int value, int base) { return _to_chars (first, last, value, base); } |
161
|
12
|
|
|
|
|
|
to_chars_result to_chars (char* first, char* last, long value, int base) { return _to_chars (first, last, value, base); } |
162
|
0
|
|
|
|
|
|
to_chars_result to_chars (char* first, char* last, long long value, int base) { return _to_chars (first, last, value, base); } |
163
|
12
|
|
|
|
|
|
to_chars_result to_chars (char* first, char* last, uint8_t value, int base) { return _to_chars (first, last, value, base); } |
164
|
12
|
|
|
|
|
|
to_chars_result to_chars (char* first, char* last, uint16_t value, int base) { return _to_chars(first, last, value, base); } |
165
|
12
|
|
|
|
|
|
to_chars_result to_chars (char* first, char* last, unsigned value, int base) { return _to_chars(first, last, value, base); } |
166
|
12
|
|
|
|
|
|
to_chars_result to_chars (char* first, char* last, unsigned long value, int base) { return _to_chars(first, last, value, base); } |
167
|
0
|
|
|
|
|
|
to_chars_result to_chars (char* first, char* last, unsigned long long value, int base) { return _to_chars(first, last, value, base); } |
168
|
|
|
|
|
|
|
|
169
|
72
|
50
|
|
|
|
|
} |
|
|
50
|
|
|
|
|
|