LibSWOC++ 1.5.14
Solid Wall of C++
Loading...
Searching...
No Matches
TextView.cc
Go to the documentation of this file.
1// SPDX-License-Identifier: Apache-2.0
2// Copyright Apache Software Foundation 2019
11
12#include "swoc/TextView.h"
13#include <cctype>
14#include <sstream>
15
16using namespace swoc::literals;
17
18namespace swoc { inline namespace SWOC_VERSION_NS {
19
21const int8_t svtoi_convert[256] = {
22 /* [can't do this nicely because clang format won't allow exdented comments]
23 0 1 2 3 4 5 6 7 8 9 A B C D E F
24 */
25 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 00
26 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 10
27 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 20
28 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, -1, -1, -1, -1, -1, -1, // 30
29 -1, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, // 40
30 25, 26, 27, 28, 20, 30, 31, 32, 33, 34, 35, -1, -1, -1, -1, -1, // 50
31 -1, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, // 60
32 25, 26, 27, 28, 20, 30, 31, 32, 33, 34, 35, -1, -1, -1, -1, -1, // 70
33 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 80
34 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 90
35 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // A0
36 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // B0
37 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // C0
38 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // D0
39 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // E0
40 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // F0
41};
43
44intmax_t
45svtoi(TextView src, TextView *out, int base) {
46 static constexpr uintmax_t ABS_MAX = std::numeric_limits<intmax_t>::max();
47 static constexpr uintmax_t ABS_MIN = uintmax_t(std::numeric_limits<intmax_t>::min());
48 intmax_t zret = 0;
49
50 if (src.ltrim_if(&isspace)) {
51 TextView parsed;
52 const char *start = src.data();
53 bool neg = false;
54 if ('-' == *src) {
55 ++src;
56 neg = true;
57 } else if ('+' == *src) {
58 ++src;
59 }
60 auto n = svtou(src, &parsed, base);
61 if (!parsed.empty()) {
62 if (out) {
63 out->assign(start, parsed.data_end());
64 }
65 if (neg) {
66 uintmax_t temp = std::min<uintmax_t>(n, ABS_MIN);
67 if (temp == ABS_MIN) {
68 zret = std::numeric_limits<intmax_t>::min();
69 } else {
70 zret = -intmax_t(temp);
71 }
72 } else {
73 zret = std::min(n, ABS_MAX);
74 }
75 }
76 }
77 return zret;
78}
79
80uintmax_t
81svtou(TextView src, TextView *out, int base) {
82 uintmax_t zret = 0;
83
84 if (out) {
85 out->clear();
86 }
87
88 if (src.ltrim_if(&isspace).size()) {
89 auto origin = src.data(); // cache to handle prefix skipping.
90 // If base is 0, it wasn't specified - check for standard base prefixes
91 if (0 == base) {
92 base = 10;
93 if ('0' == *src) {
94 ++src;
95 base = 8;
96 if (src) {
97 switch (*src) {
98 case 'x':
99 case 'X':
100 ++src;
101 base = 16;
102 break;
103 case 'b':
104 case 'B':
105 ++src;
106 base = 2;
107 break;
108 }
109 }
110 }
111 }
112 if (!(1 <= base && base <= 36)) {
113 return 0;
114 }
115
116 // For performance in common cases, use the templated conversion.
117 switch (base) {
118 case 2:
119 zret = svto_radix<2>(src);
120 break;
121 case 8:
122 zret = svto_radix<8>(src);
123 break;
124 case 10:
125 zret = svto_radix<10>(src);
126 break;
127 case 16:
128 zret = svto_radix<16>(src);
129 break;
130 default: {
131 static constexpr auto MAX = std::numeric_limits<uintmax_t>::max();
132 const auto OVERFLOW_LIMIT = MAX / base;
133 intmax_t v = 0;
134 while (src.size() && (0 <= (v = svtoi_convert[static_cast<unsigned char>(*src)])) && v < base) {
135 ++src;
136 if (zret <= OVERFLOW_LIMIT && uintmax_t(v) <= (MAX - (zret *= base))) {
137 zret += v;
138 } else {
139 zret = MAX;
140 }
141 }
142 break;
143 }
144 }
145
146 if (out) {
147 out->assign(origin, src.data());
148 }
149 }
150 return zret;
151}
152
153double
155 // @return 10^e
156 auto pow10 = [](int e) -> double {
157 double zret = 1.0;
158 double scale = 10.0;
159 if (e < 0) { // flip the scale and make @a e positive.
160 e = -e;
161 scale = 0.1;
162 }
163
164 // Walk the bits in the exponent @a e and multiply the scale for set bits.
165 while (e) {
166 if (e & 1) {
167 zret *= scale;
168 }
169 scale *= scale;
170 e >>= 1;
171 }
172 return zret;
173 };
174
175 if (text.empty()) {
176 return 0;
177 }
178
179 auto org_text = text; // save this to update @a parsed.
180 // Check just once and dump to a local copy if needed.
181 TextView local_parsed;
182 if (!parsed) {
183 parsed = &local_parsed;
184 }
185
186 // Handle leading sign.
187 int sign = 1;
188 if (*text == '-') {
189 ++text;
190 sign = -1;
191 } else if (*text == '+') {
192 ++text;
193 }
194 // Parse the leading whole part as an integer.
195 intmax_t whole = svto_radix<10>(text);
196 parsed->assign(org_text.data(), text.data());
197
198 if (text.empty()) {
199 return whole;
200 }
201
202 double frac = 0.0;
203 if (*text == '.') { // fractional part.
204 ++text;
205 double scale = 0.1;
206 while (text && isdigit(*text)) {
207 frac += scale * (*text++ - '0');
208 scale /= 10.0;
209 }
210 }
211
212 double exp = 1.0;
213 if (text.starts_with_nocase("e")) {
214 int exp_sign = 1;
215 ++text;
216 if (text) {
217 if (*text == '+') {
218 ++text;
219 } else if (*text == '-') {
220 ++text;
221 exp_sign = -1;
222 }
223 }
224 auto exp_part = svto_radix<10>(text);
225 exp = pow10(exp_part * exp_sign);
226 }
227
228 parsed->assign(org_text.data(), text.data());
229 return sign * (whole + frac) * exp;
230}
231
232// Do the template instantiations.
233template std::ostream &TextView::stream_write(std::ostream &, const TextView &) const;
234
235}} // namespace swoc::SWOC_VERSION_NS
236
237namespace std {
238ostream &
239operator<<(ostream &os, const swoc::TextView &b) {
240 if (os.good()) {
241 b.stream_write<ostream>(os, b);
242 os.width(0);
243 }
244 return os;
245}
246} // namespace std
uintmax_t svto_radix(TextView &src)
Definition TextView.h:1059
Stream & stream_write(Stream &os, const TextView &b) const
bool starts_with_nocase(std::string_view const &prefix) const noexcept
self_type & clear()
Clear the view (become an empty view).
self_type & assign(char *&c_str)
Stream & stream_write(Stream &os, const TextView &b) const
self_type & ltrim_if(F const &pred)
constexpr value_type const * data_end() const noexcept
constexpr value_type const * data() const noexcept
STL namespace.
For template deduction guides.
Definition ArenaWriter.cc:9
double svtod(swoc::TextView text, swoc::TextView *parsed)
Definition TextView.cc:154
const int8_t svtoi_convert[256]
uintmax_t svtou(TextView src, TextView *out, int base)
Definition TextView.cc:81
intmax_t svtoi(TextView src, TextView *out, int base)
Definition TextView.cc:45