blob: 77d7e7835b8b25ab5ebc2395112d1570e95496fb [file] [log] [blame]
Austin Schuh36244a12019-09-21 17:52:38 -07001// Copyright 2017 The Abseil Authors.
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// https://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15// This file tests string processing functions related to numeric values.
16
17#include "absl/strings/numbers.h"
18
19#include <sys/types.h>
20#include <cfenv> // NOLINT(build/c++11)
21#include <cinttypes>
22#include <climits>
23#include <cmath>
24#include <cstddef>
25#include <cstdint>
26#include <cstdio>
27#include <cstdlib>
28#include <cstring>
29#include <limits>
30#include <numeric>
31#include <random>
32#include <set>
33#include <string>
34#include <vector>
35
36#include "gmock/gmock.h"
37#include "gtest/gtest.h"
38#include "absl/base/internal/raw_logging.h"
39#include "absl/strings/str_cat.h"
40
41#include "absl/strings/internal/numbers_test_common.h"
42#include "absl/strings/internal/pow10_helper.h"
43
44namespace {
45
46using absl::numbers_internal::kSixDigitsToBufferSize;
47using absl::numbers_internal::safe_strto32_base;
48using absl::numbers_internal::safe_strto64_base;
49using absl::numbers_internal::safe_strtou32_base;
50using absl::numbers_internal::safe_strtou64_base;
51using absl::numbers_internal::SixDigitsToBuffer;
52using absl::strings_internal::Itoa;
53using absl::strings_internal::strtouint32_test_cases;
54using absl::strings_internal::strtouint64_test_cases;
55using absl::SimpleAtoi;
56using testing::Eq;
57using testing::MatchesRegex;
58
59// Number of floats to test with.
60// 5,000,000 is a reasonable default for a test that only takes a few seconds.
61// 1,000,000,000+ triggers checking for all possible mantissa values for
62// double-precision tests. 2,000,000,000+ triggers checking for every possible
63// single-precision float.
64const int kFloatNumCases = 5000000;
65
66// This is a slow, brute-force routine to compute the exact base-10
67// representation of a double-precision floating-point number. It
68// is useful for debugging only.
69std::string PerfectDtoa(double d) {
70 if (d == 0) return "0";
71 if (d < 0) return "-" + PerfectDtoa(-d);
72
73 // Basic theory: decompose d into mantissa and exp, where
74 // d = mantissa * 2^exp, and exp is as close to zero as possible.
75 int64_t mantissa, exp = 0;
76 while (d >= 1ULL << 63) ++exp, d *= 0.5;
77 while ((mantissa = d) != d) --exp, d *= 2.0;
78
79 // Then convert mantissa to ASCII, and either double it (if
80 // exp > 0) or halve it (if exp < 0) repeatedly. "halve it"
81 // in this case means multiplying it by five and dividing by 10.
82 constexpr int maxlen = 1100; // worst case is actually 1030 or so.
83 char buf[maxlen + 5];
84 for (int64_t num = mantissa, pos = maxlen; --pos >= 0;) {
85 buf[pos] = '0' + (num % 10);
86 num /= 10;
87 }
88 char* begin = &buf[0];
89 char* end = buf + maxlen;
90 for (int i = 0; i != exp; i += (exp > 0) ? 1 : -1) {
91 int carry = 0;
92 for (char* p = end; --p != begin;) {
93 int dig = *p - '0';
94 dig = dig * (exp > 0 ? 2 : 5) + carry;
95 carry = dig / 10;
96 dig %= 10;
97 *p = '0' + dig;
98 }
99 }
100 if (exp < 0) {
101 // "dividing by 10" above means we have to add the decimal point.
102 memmove(end + 1 + exp, end + exp, 1 - exp);
103 end[exp] = '.';
104 ++end;
105 }
106 while (*begin == '0' && begin[1] != '.') ++begin;
107 return {begin, end};
108}
109
110TEST(ToString, PerfectDtoa) {
111 EXPECT_THAT(PerfectDtoa(1), Eq("1"));
112 EXPECT_THAT(PerfectDtoa(0.1),
113 Eq("0.1000000000000000055511151231257827021181583404541015625"));
114 EXPECT_THAT(PerfectDtoa(1e24), Eq("999999999999999983222784"));
115 EXPECT_THAT(PerfectDtoa(5e-324), MatchesRegex("0.0000.*625"));
116 for (int i = 0; i < 100; ++i) {
117 for (double multiplier :
118 {1e-300, 1e-200, 1e-100, 0.1, 1.0, 10.0, 1e100, 1e300}) {
119 double d = multiplier * i;
120 std::string s = PerfectDtoa(d);
121 EXPECT_DOUBLE_EQ(d, strtod(s.c_str(), nullptr));
122 }
123 }
124}
125
126template <typename integer>
127struct MyInteger {
128 integer i;
129 explicit constexpr MyInteger(integer i) : i(i) {}
130 constexpr operator integer() const { return i; }
131
132 constexpr MyInteger operator+(MyInteger other) const { return i + other.i; }
133 constexpr MyInteger operator-(MyInteger other) const { return i - other.i; }
134 constexpr MyInteger operator*(MyInteger other) const { return i * other.i; }
135 constexpr MyInteger operator/(MyInteger other) const { return i / other.i; }
136
137 constexpr bool operator<(MyInteger other) const { return i < other.i; }
138 constexpr bool operator<=(MyInteger other) const { return i <= other.i; }
139 constexpr bool operator==(MyInteger other) const { return i == other.i; }
140 constexpr bool operator>=(MyInteger other) const { return i >= other.i; }
141 constexpr bool operator>(MyInteger other) const { return i > other.i; }
142 constexpr bool operator!=(MyInteger other) const { return i != other.i; }
143
144 integer as_integer() const { return i; }
145};
146
147typedef MyInteger<int64_t> MyInt64;
148typedef MyInteger<uint64_t> MyUInt64;
149
150void CheckInt32(int32_t x) {
151 char buffer[absl::numbers_internal::kFastToBufferSize];
152 char* actual = absl::numbers_internal::FastIntToBuffer(x, buffer);
153 std::string expected = std::to_string(x);
154 EXPECT_EQ(expected, std::string(buffer, actual)) << " Input " << x;
155
156 char* generic_actual = absl::numbers_internal::FastIntToBuffer(x, buffer);
157 EXPECT_EQ(expected, std::string(buffer, generic_actual)) << " Input " << x;
158}
159
160void CheckInt64(int64_t x) {
161 char buffer[absl::numbers_internal::kFastToBufferSize + 3];
162 buffer[0] = '*';
163 buffer[23] = '*';
164 buffer[24] = '*';
165 char* actual = absl::numbers_internal::FastIntToBuffer(x, &buffer[1]);
166 std::string expected = std::to_string(x);
167 EXPECT_EQ(expected, std::string(&buffer[1], actual)) << " Input " << x;
168 EXPECT_EQ(buffer[0], '*');
169 EXPECT_EQ(buffer[23], '*');
170 EXPECT_EQ(buffer[24], '*');
171
172 char* my_actual =
173 absl::numbers_internal::FastIntToBuffer(MyInt64(x), &buffer[1]);
174 EXPECT_EQ(expected, std::string(&buffer[1], my_actual)) << " Input " << x;
175}
176
177void CheckUInt32(uint32_t x) {
178 char buffer[absl::numbers_internal::kFastToBufferSize];
179 char* actual = absl::numbers_internal::FastIntToBuffer(x, buffer);
180 std::string expected = std::to_string(x);
181 EXPECT_EQ(expected, std::string(buffer, actual)) << " Input " << x;
182
183 char* generic_actual = absl::numbers_internal::FastIntToBuffer(x, buffer);
184 EXPECT_EQ(expected, std::string(buffer, generic_actual)) << " Input " << x;
185}
186
187void CheckUInt64(uint64_t x) {
188 char buffer[absl::numbers_internal::kFastToBufferSize + 1];
189 char* actual = absl::numbers_internal::FastIntToBuffer(x, &buffer[1]);
190 std::string expected = std::to_string(x);
191 EXPECT_EQ(expected, std::string(&buffer[1], actual)) << " Input " << x;
192
193 char* generic_actual = absl::numbers_internal::FastIntToBuffer(x, &buffer[1]);
194 EXPECT_EQ(expected, std::string(&buffer[1], generic_actual))
195 << " Input " << x;
196
197 char* my_actual =
198 absl::numbers_internal::FastIntToBuffer(MyUInt64(x), &buffer[1]);
199 EXPECT_EQ(expected, std::string(&buffer[1], my_actual)) << " Input " << x;
200}
201
202void CheckHex64(uint64_t v) {
203 char expected[16 + 1];
204 std::string actual = absl::StrCat(absl::Hex(v, absl::kZeroPad16));
205 snprintf(expected, sizeof(expected), "%016" PRIx64, static_cast<uint64_t>(v));
206 EXPECT_EQ(expected, actual) << " Input " << v;
207}
208
209TEST(Numbers, TestFastPrints) {
210 for (int i = -100; i <= 100; i++) {
211 CheckInt32(i);
212 CheckInt64(i);
213 }
214 for (int i = 0; i <= 100; i++) {
215 CheckUInt32(i);
216 CheckUInt64(i);
217 }
218 // Test min int to make sure that works
219 CheckInt32(INT_MIN);
220 CheckInt32(INT_MAX);
221 CheckInt64(LONG_MIN);
222 CheckInt64(uint64_t{1000000000});
223 CheckInt64(uint64_t{9999999999});
224 CheckInt64(uint64_t{100000000000000});
225 CheckInt64(uint64_t{999999999999999});
226 CheckInt64(uint64_t{1000000000000000000});
227 CheckInt64(uint64_t{1199999999999999999});
228 CheckInt64(int64_t{-700000000000000000});
229 CheckInt64(LONG_MAX);
230 CheckUInt32(std::numeric_limits<uint32_t>::max());
231 CheckUInt64(uint64_t{1000000000});
232 CheckUInt64(uint64_t{9999999999});
233 CheckUInt64(uint64_t{100000000000000});
234 CheckUInt64(uint64_t{999999999999999});
235 CheckUInt64(uint64_t{1000000000000000000});
236 CheckUInt64(uint64_t{1199999999999999999});
237 CheckUInt64(std::numeric_limits<uint64_t>::max());
238
239 for (int i = 0; i < 10000; i++) {
240 CheckHex64(i);
241 }
242 CheckHex64(uint64_t{0x123456789abcdef0});
243}
244
245template <typename int_type, typename in_val_type>
246void VerifySimpleAtoiGood(in_val_type in_value, int_type exp_value) {
247 std::string s = absl::StrCat(in_value);
248 int_type x = static_cast<int_type>(~exp_value);
249 EXPECT_TRUE(SimpleAtoi(s, &x))
250 << "in_value=" << in_value << " s=" << s << " x=" << x;
251 EXPECT_EQ(exp_value, x);
252 x = static_cast<int_type>(~exp_value);
253 EXPECT_TRUE(SimpleAtoi(s.c_str(), &x));
254 EXPECT_EQ(exp_value, x);
255}
256
257template <typename int_type, typename in_val_type>
258void VerifySimpleAtoiBad(in_val_type in_value) {
259 std::string s = absl::StrCat(in_value);
260 int_type x;
261 EXPECT_FALSE(SimpleAtoi(s, &x));
262 EXPECT_FALSE(SimpleAtoi(s.c_str(), &x));
263}
264
265TEST(NumbersTest, Atoi) {
266 // SimpleAtoi(absl::string_view, int32_t)
267 VerifySimpleAtoiGood<int32_t>(0, 0);
268 VerifySimpleAtoiGood<int32_t>(42, 42);
269 VerifySimpleAtoiGood<int32_t>(-42, -42);
270
271 VerifySimpleAtoiGood<int32_t>(std::numeric_limits<int32_t>::min(),
272 std::numeric_limits<int32_t>::min());
273 VerifySimpleAtoiGood<int32_t>(std::numeric_limits<int32_t>::max(),
274 std::numeric_limits<int32_t>::max());
275
276 // SimpleAtoi(absl::string_view, uint32_t)
277 VerifySimpleAtoiGood<uint32_t>(0, 0);
278 VerifySimpleAtoiGood<uint32_t>(42, 42);
279 VerifySimpleAtoiBad<uint32_t>(-42);
280
281 VerifySimpleAtoiBad<uint32_t>(std::numeric_limits<int32_t>::min());
282 VerifySimpleAtoiGood<uint32_t>(std::numeric_limits<int32_t>::max(),
283 std::numeric_limits<int32_t>::max());
284 VerifySimpleAtoiGood<uint32_t>(std::numeric_limits<uint32_t>::max(),
285 std::numeric_limits<uint32_t>::max());
286 VerifySimpleAtoiBad<uint32_t>(std::numeric_limits<int64_t>::min());
287 VerifySimpleAtoiBad<uint32_t>(std::numeric_limits<int64_t>::max());
288 VerifySimpleAtoiBad<uint32_t>(std::numeric_limits<uint64_t>::max());
289
290 // SimpleAtoi(absl::string_view, int64_t)
291 VerifySimpleAtoiGood<int64_t>(0, 0);
292 VerifySimpleAtoiGood<int64_t>(42, 42);
293 VerifySimpleAtoiGood<int64_t>(-42, -42);
294
295 VerifySimpleAtoiGood<int64_t>(std::numeric_limits<int32_t>::min(),
296 std::numeric_limits<int32_t>::min());
297 VerifySimpleAtoiGood<int64_t>(std::numeric_limits<int32_t>::max(),
298 std::numeric_limits<int32_t>::max());
299 VerifySimpleAtoiGood<int64_t>(std::numeric_limits<uint32_t>::max(),
300 std::numeric_limits<uint32_t>::max());
301 VerifySimpleAtoiGood<int64_t>(std::numeric_limits<int64_t>::min(),
302 std::numeric_limits<int64_t>::min());
303 VerifySimpleAtoiGood<int64_t>(std::numeric_limits<int64_t>::max(),
304 std::numeric_limits<int64_t>::max());
305 VerifySimpleAtoiBad<int64_t>(std::numeric_limits<uint64_t>::max());
306
307 // SimpleAtoi(absl::string_view, uint64_t)
308 VerifySimpleAtoiGood<uint64_t>(0, 0);
309 VerifySimpleAtoiGood<uint64_t>(42, 42);
310 VerifySimpleAtoiBad<uint64_t>(-42);
311
312 VerifySimpleAtoiBad<uint64_t>(std::numeric_limits<int32_t>::min());
313 VerifySimpleAtoiGood<uint64_t>(std::numeric_limits<int32_t>::max(),
314 std::numeric_limits<int32_t>::max());
315 VerifySimpleAtoiGood<uint64_t>(std::numeric_limits<uint32_t>::max(),
316 std::numeric_limits<uint32_t>::max());
317 VerifySimpleAtoiBad<uint64_t>(std::numeric_limits<int64_t>::min());
318 VerifySimpleAtoiGood<uint64_t>(std::numeric_limits<int64_t>::max(),
319 std::numeric_limits<int64_t>::max());
320 VerifySimpleAtoiGood<uint64_t>(std::numeric_limits<uint64_t>::max(),
321 std::numeric_limits<uint64_t>::max());
322
323 // Some other types
324 VerifySimpleAtoiGood<int>(-42, -42);
325 VerifySimpleAtoiGood<int32_t>(-42, -42);
326 VerifySimpleAtoiGood<uint32_t>(42, 42);
327 VerifySimpleAtoiGood<unsigned int>(42, 42);
328 VerifySimpleAtoiGood<int64_t>(-42, -42);
329 VerifySimpleAtoiGood<long>(-42, -42); // NOLINT(runtime/int)
330 VerifySimpleAtoiGood<uint64_t>(42, 42);
331 VerifySimpleAtoiGood<size_t>(42, 42);
332 VerifySimpleAtoiGood<std::string::size_type>(42, 42);
333}
334
335TEST(NumbersTest, Atoenum) {
336 enum E01 {
337 E01_zero = 0,
338 E01_one = 1,
339 };
340
341 VerifySimpleAtoiGood<E01>(E01_zero, E01_zero);
342 VerifySimpleAtoiGood<E01>(E01_one, E01_one);
343
344 enum E_101 {
345 E_101_minusone = -1,
346 E_101_zero = 0,
347 E_101_one = 1,
348 };
349
350 VerifySimpleAtoiGood<E_101>(E_101_minusone, E_101_minusone);
351 VerifySimpleAtoiGood<E_101>(E_101_zero, E_101_zero);
352 VerifySimpleAtoiGood<E_101>(E_101_one, E_101_one);
353
354 enum E_bigint {
355 E_bigint_zero = 0,
356 E_bigint_one = 1,
357 E_bigint_max31 = static_cast<int32_t>(0x7FFFFFFF),
358 };
359
360 VerifySimpleAtoiGood<E_bigint>(E_bigint_zero, E_bigint_zero);
361 VerifySimpleAtoiGood<E_bigint>(E_bigint_one, E_bigint_one);
362 VerifySimpleAtoiGood<E_bigint>(E_bigint_max31, E_bigint_max31);
363
364 enum E_fullint {
365 E_fullint_zero = 0,
366 E_fullint_one = 1,
367 E_fullint_max31 = static_cast<int32_t>(0x7FFFFFFF),
368 E_fullint_min32 = INT32_MIN,
369 };
370
371 VerifySimpleAtoiGood<E_fullint>(E_fullint_zero, E_fullint_zero);
372 VerifySimpleAtoiGood<E_fullint>(E_fullint_one, E_fullint_one);
373 VerifySimpleAtoiGood<E_fullint>(E_fullint_max31, E_fullint_max31);
374 VerifySimpleAtoiGood<E_fullint>(E_fullint_min32, E_fullint_min32);
375
376 enum E_biguint {
377 E_biguint_zero = 0,
378 E_biguint_one = 1,
379 E_biguint_max31 = static_cast<uint32_t>(0x7FFFFFFF),
380 E_biguint_max32 = static_cast<uint32_t>(0xFFFFFFFF),
381 };
382
383 VerifySimpleAtoiGood<E_biguint>(E_biguint_zero, E_biguint_zero);
384 VerifySimpleAtoiGood<E_biguint>(E_biguint_one, E_biguint_one);
385 VerifySimpleAtoiGood<E_biguint>(E_biguint_max31, E_biguint_max31);
386 VerifySimpleAtoiGood<E_biguint>(E_biguint_max32, E_biguint_max32);
387}
388
389TEST(stringtest, safe_strto32_base) {
390 int32_t value;
391 EXPECT_TRUE(safe_strto32_base("0x34234324", &value, 16));
392 EXPECT_EQ(0x34234324, value);
393
394 EXPECT_TRUE(safe_strto32_base("0X34234324", &value, 16));
395 EXPECT_EQ(0x34234324, value);
396
397 EXPECT_TRUE(safe_strto32_base("34234324", &value, 16));
398 EXPECT_EQ(0x34234324, value);
399
400 EXPECT_TRUE(safe_strto32_base("0", &value, 16));
401 EXPECT_EQ(0, value);
402
403 EXPECT_TRUE(safe_strto32_base(" \t\n -0x34234324", &value, 16));
404 EXPECT_EQ(-0x34234324, value);
405
406 EXPECT_TRUE(safe_strto32_base(" \t\n -34234324", &value, 16));
407 EXPECT_EQ(-0x34234324, value);
408
409 EXPECT_TRUE(safe_strto32_base("7654321", &value, 8));
410 EXPECT_EQ(07654321, value);
411
412 EXPECT_TRUE(safe_strto32_base("-01234", &value, 8));
413 EXPECT_EQ(-01234, value);
414
415 EXPECT_FALSE(safe_strto32_base("1834", &value, 8));
416
417 // Autodetect base.
418 EXPECT_TRUE(safe_strto32_base("0", &value, 0));
419 EXPECT_EQ(0, value);
420
421 EXPECT_TRUE(safe_strto32_base("077", &value, 0));
422 EXPECT_EQ(077, value); // Octal interpretation
423
424 // Leading zero indicates octal, but then followed by invalid digit.
425 EXPECT_FALSE(safe_strto32_base("088", &value, 0));
426
427 // Leading 0x indicated hex, but then followed by invalid digit.
428 EXPECT_FALSE(safe_strto32_base("0xG", &value, 0));
429
430 // Base-10 version.
431 EXPECT_TRUE(safe_strto32_base("34234324", &value, 10));
432 EXPECT_EQ(34234324, value);
433
434 EXPECT_TRUE(safe_strto32_base("0", &value, 10));
435 EXPECT_EQ(0, value);
436
437 EXPECT_TRUE(safe_strto32_base(" \t\n -34234324", &value, 10));
438 EXPECT_EQ(-34234324, value);
439
440 EXPECT_TRUE(safe_strto32_base("34234324 \n\t ", &value, 10));
441 EXPECT_EQ(34234324, value);
442
443 // Invalid ints.
444 EXPECT_FALSE(safe_strto32_base("", &value, 10));
445 EXPECT_FALSE(safe_strto32_base(" ", &value, 10));
446 EXPECT_FALSE(safe_strto32_base("abc", &value, 10));
447 EXPECT_FALSE(safe_strto32_base("34234324a", &value, 10));
448 EXPECT_FALSE(safe_strto32_base("34234.3", &value, 10));
449
450 // Out of bounds.
451 EXPECT_FALSE(safe_strto32_base("2147483648", &value, 10));
452 EXPECT_FALSE(safe_strto32_base("-2147483649", &value, 10));
453
454 // String version.
455 EXPECT_TRUE(safe_strto32_base(std::string("0x1234"), &value, 16));
456 EXPECT_EQ(0x1234, value);
457
458 // Base-10 std::string version.
459 EXPECT_TRUE(safe_strto32_base("1234", &value, 10));
460 EXPECT_EQ(1234, value);
461}
462
463TEST(stringtest, safe_strto32_range) {
464 // These tests verify underflow/overflow behaviour.
465 int32_t value;
466 EXPECT_FALSE(safe_strto32_base("2147483648", &value, 10));
467 EXPECT_EQ(std::numeric_limits<int32_t>::max(), value);
468
469 EXPECT_TRUE(safe_strto32_base("-2147483648", &value, 10));
470 EXPECT_EQ(std::numeric_limits<int32_t>::min(), value);
471
472 EXPECT_FALSE(safe_strto32_base("-2147483649", &value, 10));
473 EXPECT_EQ(std::numeric_limits<int32_t>::min(), value);
474}
475
476TEST(stringtest, safe_strto64_range) {
477 // These tests verify underflow/overflow behaviour.
478 int64_t value;
479 EXPECT_FALSE(safe_strto64_base("9223372036854775808", &value, 10));
480 EXPECT_EQ(std::numeric_limits<int64_t>::max(), value);
481
482 EXPECT_TRUE(safe_strto64_base("-9223372036854775808", &value, 10));
483 EXPECT_EQ(std::numeric_limits<int64_t>::min(), value);
484
485 EXPECT_FALSE(safe_strto64_base("-9223372036854775809", &value, 10));
486 EXPECT_EQ(std::numeric_limits<int64_t>::min(), value);
487}
488
489TEST(stringtest, safe_strto32_leading_substring) {
490 // These tests verify this comment in numbers.h:
491 // On error, returns false, and sets *value to: [...]
492 // conversion of leading substring if available ("123@@@" -> 123)
493 // 0 if no leading substring available
494 int32_t value;
495 EXPECT_FALSE(safe_strto32_base("04069@@@", &value, 10));
496 EXPECT_EQ(4069, value);
497
498 EXPECT_FALSE(safe_strto32_base("04069@@@", &value, 8));
499 EXPECT_EQ(0406, value);
500
501 EXPECT_FALSE(safe_strto32_base("04069balloons", &value, 10));
502 EXPECT_EQ(4069, value);
503
504 EXPECT_FALSE(safe_strto32_base("04069balloons", &value, 16));
505 EXPECT_EQ(0x4069ba, value);
506
507 EXPECT_FALSE(safe_strto32_base("@@@", &value, 10));
508 EXPECT_EQ(0, value); // there was no leading substring
509}
510
511TEST(stringtest, safe_strto64_leading_substring) {
512 // These tests verify this comment in numbers.h:
513 // On error, returns false, and sets *value to: [...]
514 // conversion of leading substring if available ("123@@@" -> 123)
515 // 0 if no leading substring available
516 int64_t value;
517 EXPECT_FALSE(safe_strto64_base("04069@@@", &value, 10));
518 EXPECT_EQ(4069, value);
519
520 EXPECT_FALSE(safe_strto64_base("04069@@@", &value, 8));
521 EXPECT_EQ(0406, value);
522
523 EXPECT_FALSE(safe_strto64_base("04069balloons", &value, 10));
524 EXPECT_EQ(4069, value);
525
526 EXPECT_FALSE(safe_strto64_base("04069balloons", &value, 16));
527 EXPECT_EQ(0x4069ba, value);
528
529 EXPECT_FALSE(safe_strto64_base("@@@", &value, 10));
530 EXPECT_EQ(0, value); // there was no leading substring
531}
532
533TEST(stringtest, safe_strto64_base) {
534 int64_t value;
535 EXPECT_TRUE(safe_strto64_base("0x3423432448783446", &value, 16));
536 EXPECT_EQ(int64_t{0x3423432448783446}, value);
537
538 EXPECT_TRUE(safe_strto64_base("3423432448783446", &value, 16));
539 EXPECT_EQ(int64_t{0x3423432448783446}, value);
540
541 EXPECT_TRUE(safe_strto64_base("0", &value, 16));
542 EXPECT_EQ(0, value);
543
544 EXPECT_TRUE(safe_strto64_base(" \t\n -0x3423432448783446", &value, 16));
545 EXPECT_EQ(int64_t{-0x3423432448783446}, value);
546
547 EXPECT_TRUE(safe_strto64_base(" \t\n -3423432448783446", &value, 16));
548 EXPECT_EQ(int64_t{-0x3423432448783446}, value);
549
550 EXPECT_TRUE(safe_strto64_base("123456701234567012", &value, 8));
551 EXPECT_EQ(int64_t{0123456701234567012}, value);
552
553 EXPECT_TRUE(safe_strto64_base("-017777777777777", &value, 8));
554 EXPECT_EQ(int64_t{-017777777777777}, value);
555
556 EXPECT_FALSE(safe_strto64_base("19777777777777", &value, 8));
557
558 // Autodetect base.
559 EXPECT_TRUE(safe_strto64_base("0", &value, 0));
560 EXPECT_EQ(0, value);
561
562 EXPECT_TRUE(safe_strto64_base("077", &value, 0));
563 EXPECT_EQ(077, value); // Octal interpretation
564
565 // Leading zero indicates octal, but then followed by invalid digit.
566 EXPECT_FALSE(safe_strto64_base("088", &value, 0));
567
568 // Leading 0x indicated hex, but then followed by invalid digit.
569 EXPECT_FALSE(safe_strto64_base("0xG", &value, 0));
570
571 // Base-10 version.
572 EXPECT_TRUE(safe_strto64_base("34234324487834466", &value, 10));
573 EXPECT_EQ(int64_t{34234324487834466}, value);
574
575 EXPECT_TRUE(safe_strto64_base("0", &value, 10));
576 EXPECT_EQ(0, value);
577
578 EXPECT_TRUE(safe_strto64_base(" \t\n -34234324487834466", &value, 10));
579 EXPECT_EQ(int64_t{-34234324487834466}, value);
580
581 EXPECT_TRUE(safe_strto64_base("34234324487834466 \n\t ", &value, 10));
582 EXPECT_EQ(int64_t{34234324487834466}, value);
583
584 // Invalid ints.
585 EXPECT_FALSE(safe_strto64_base("", &value, 10));
586 EXPECT_FALSE(safe_strto64_base(" ", &value, 10));
587 EXPECT_FALSE(safe_strto64_base("abc", &value, 10));
588 EXPECT_FALSE(safe_strto64_base("34234324487834466a", &value, 10));
589 EXPECT_FALSE(safe_strto64_base("34234487834466.3", &value, 10));
590
591 // Out of bounds.
592 EXPECT_FALSE(safe_strto64_base("9223372036854775808", &value, 10));
593 EXPECT_FALSE(safe_strto64_base("-9223372036854775809", &value, 10));
594
595 // String version.
596 EXPECT_TRUE(safe_strto64_base(std::string("0x1234"), &value, 16));
597 EXPECT_EQ(0x1234, value);
598
599 // Base-10 std::string version.
600 EXPECT_TRUE(safe_strto64_base("1234", &value, 10));
601 EXPECT_EQ(1234, value);
602}
603
604const size_t kNumRandomTests = 10000;
605
606template <typename IntType>
607void test_random_integer_parse_base(bool (*parse_func)(absl::string_view,
608 IntType* value,
609 int base)) {
610 using RandomEngine = std::minstd_rand0;
611 std::random_device rd;
612 RandomEngine rng(rd());
613 std::uniform_int_distribution<IntType> random_int(
614 std::numeric_limits<IntType>::min());
615 std::uniform_int_distribution<int> random_base(2, 35);
616 for (size_t i = 0; i < kNumRandomTests; i++) {
617 IntType value = random_int(rng);
618 int base = random_base(rng);
619 std::string str_value;
620 EXPECT_TRUE(Itoa<IntType>(value, base, &str_value));
621 IntType parsed_value;
622
623 // Test successful parse
624 EXPECT_TRUE(parse_func(str_value, &parsed_value, base));
625 EXPECT_EQ(parsed_value, value);
626
627 // Test overflow
628 EXPECT_FALSE(
629 parse_func(absl::StrCat(std::numeric_limits<IntType>::max(), value),
630 &parsed_value, base));
631
632 // Test underflow
633 if (std::numeric_limits<IntType>::min() < 0) {
634 EXPECT_FALSE(
635 parse_func(absl::StrCat(std::numeric_limits<IntType>::min(), value),
636 &parsed_value, base));
637 } else {
638 EXPECT_FALSE(parse_func(absl::StrCat("-", value), &parsed_value, base));
639 }
640 }
641}
642
643TEST(stringtest, safe_strto32_random) {
644 test_random_integer_parse_base<int32_t>(&safe_strto32_base);
645}
646TEST(stringtest, safe_strto64_random) {
647 test_random_integer_parse_base<int64_t>(&safe_strto64_base);
648}
649TEST(stringtest, safe_strtou32_random) {
650 test_random_integer_parse_base<uint32_t>(&safe_strtou32_base);
651}
652TEST(stringtest, safe_strtou64_random) {
653 test_random_integer_parse_base<uint64_t>(&safe_strtou64_base);
654}
655
656TEST(stringtest, safe_strtou32_base) {
657 for (int i = 0; strtouint32_test_cases()[i].str != nullptr; ++i) {
658 const auto& e = strtouint32_test_cases()[i];
659 uint32_t value;
660 EXPECT_EQ(e.expect_ok, safe_strtou32_base(e.str, &value, e.base))
661 << "str=\"" << e.str << "\" base=" << e.base;
662 if (e.expect_ok) {
663 EXPECT_EQ(e.expected, value) << "i=" << i << " str=\"" << e.str
664 << "\" base=" << e.base;
665 }
666 }
667}
668
669TEST(stringtest, safe_strtou32_base_length_delimited) {
670 for (int i = 0; strtouint32_test_cases()[i].str != nullptr; ++i) {
671 const auto& e = strtouint32_test_cases()[i];
672 std::string tmp(e.str);
673 tmp.append("12"); // Adds garbage at the end.
674
675 uint32_t value;
676 EXPECT_EQ(e.expect_ok,
677 safe_strtou32_base(absl::string_view(tmp.data(), strlen(e.str)),
678 &value, e.base))
679 << "str=\"" << e.str << "\" base=" << e.base;
680 if (e.expect_ok) {
681 EXPECT_EQ(e.expected, value) << "i=" << i << " str=" << e.str
682 << " base=" << e.base;
683 }
684 }
685}
686
687TEST(stringtest, safe_strtou64_base) {
688 for (int i = 0; strtouint64_test_cases()[i].str != nullptr; ++i) {
689 const auto& e = strtouint64_test_cases()[i];
690 uint64_t value;
691 EXPECT_EQ(e.expect_ok, safe_strtou64_base(e.str, &value, e.base))
692 << "str=\"" << e.str << "\" base=" << e.base;
693 if (e.expect_ok) {
694 EXPECT_EQ(e.expected, value) << "str=" << e.str << " base=" << e.base;
695 }
696 }
697}
698
699TEST(stringtest, safe_strtou64_base_length_delimited) {
700 for (int i = 0; strtouint64_test_cases()[i].str != nullptr; ++i) {
701 const auto& e = strtouint64_test_cases()[i];
702 std::string tmp(e.str);
703 tmp.append("12"); // Adds garbage at the end.
704
705 uint64_t value;
706 EXPECT_EQ(e.expect_ok,
707 safe_strtou64_base(absl::string_view(tmp.data(), strlen(e.str)),
708 &value, e.base))
709 << "str=\"" << e.str << "\" base=" << e.base;
710 if (e.expect_ok) {
711 EXPECT_EQ(e.expected, value) << "str=\"" << e.str << "\" base=" << e.base;
712 }
713 }
714}
715
716// feenableexcept() and fedisableexcept() are missing on macOS, MSVC,
717// and WebAssembly.
718#if defined(_MSC_VER) || defined(__APPLE__) || defined(__EMSCRIPTEN__)
719#define ABSL_MISSING_FEENABLEEXCEPT 1
720#define ABSL_MISSING_FEDISABLEEXCEPT 1
721#endif
722
723class SimpleDtoaTest : public testing::Test {
724 protected:
725 void SetUp() override {
726 // Store the current floating point env & clear away any pending exceptions.
727 feholdexcept(&fp_env_);
728#ifndef ABSL_MISSING_FEENABLEEXCEPT
729 // Turn on floating point exceptions.
730 feenableexcept(FE_DIVBYZERO | FE_INVALID | FE_OVERFLOW);
731#endif
732 }
733
734 void TearDown() override {
735 // Restore the floating point environment to the original state.
736 // In theory fedisableexcept is unnecessary; fesetenv will also do it.
737 // In practice, our toolchains have subtle bugs.
738#ifndef ABSL_MISSING_FEDISABLEEXCEPT
739 fedisableexcept(FE_DIVBYZERO | FE_INVALID | FE_OVERFLOW);
740#endif
741 fesetenv(&fp_env_);
742 }
743
744 std::string ToNineDigits(double value) {
745 char buffer[16]; // more than enough for %.9g
746 snprintf(buffer, sizeof(buffer), "%.9g", value);
747 return buffer;
748 }
749
750 fenv_t fp_env_;
751};
752
753// Run the given runnable functor for "cases" test cases, chosen over the
754// available range of float. pi and e and 1/e are seeded, and then all
755// available integer powers of 2 and 10 are multiplied against them. In
756// addition to trying all those values, we try the next higher and next lower
757// float, and then we add additional test cases evenly distributed between them.
758// Each test case is passed to runnable as both a positive and negative value.
759template <typename R>
760void ExhaustiveFloat(uint32_t cases, R&& runnable) {
761 runnable(0.0f);
762 runnable(-0.0f);
763 if (cases >= 2e9) { // more than 2 billion? Might as well run them all.
764 for (float f = 0; f < std::numeric_limits<float>::max(); ) {
765 f = nextafterf(f, std::numeric_limits<float>::max());
766 runnable(-f);
767 runnable(f);
768 }
769 return;
770 }
771 std::set<float> floats = {3.4028234e38f};
772 for (float f : {1.0, 3.14159265, 2.718281828, 1 / 2.718281828}) {
773 for (float testf = f; testf != 0; testf *= 0.1f) floats.insert(testf);
774 for (float testf = f; testf != 0; testf *= 0.5f) floats.insert(testf);
775 for (float testf = f; testf < 3e38f / 2; testf *= 2.0f)
776 floats.insert(testf);
777 for (float testf = f; testf < 3e38f / 10; testf *= 10) floats.insert(testf);
778 }
779
780 float last = *floats.begin();
781
782 runnable(last);
783 runnable(-last);
784 int iters_per_float = cases / floats.size();
785 if (iters_per_float == 0) iters_per_float = 1;
786 for (float f : floats) {
787 if (f == last) continue;
788 float testf = std::nextafter(last, std::numeric_limits<float>::max());
789 runnable(testf);
790 runnable(-testf);
791 last = testf;
792 if (f == last) continue;
793 double step = (double{f} - last) / iters_per_float;
794 for (double d = last + step; d < f; d += step) {
795 testf = d;
796 if (testf != last) {
797 runnable(testf);
798 runnable(-testf);
799 last = testf;
800 }
801 }
802 testf = std::nextafter(f, 0.0f);
803 if (testf > last) {
804 runnable(testf);
805 runnable(-testf);
806 last = testf;
807 }
808 if (f != last) {
809 runnable(f);
810 runnable(-f);
811 last = f;
812 }
813 }
814}
815
816TEST_F(SimpleDtoaTest, ExhaustiveDoubleToSixDigits) {
817 uint64_t test_count = 0;
818 std::vector<double> mismatches;
819 auto checker = [&](double d) {
820 if (d != d) return; // rule out NaNs
821 ++test_count;
822 char sixdigitsbuf[kSixDigitsToBufferSize] = {0};
823 SixDigitsToBuffer(d, sixdigitsbuf);
824 char snprintfbuf[kSixDigitsToBufferSize] = {0};
825 snprintf(snprintfbuf, kSixDigitsToBufferSize, "%g", d);
826 if (strcmp(sixdigitsbuf, snprintfbuf) != 0) {
827 mismatches.push_back(d);
828 if (mismatches.size() < 10) {
829 ABSL_RAW_LOG(ERROR, "%s",
830 absl::StrCat("Six-digit failure with double. ", "d=", d,
831 "=", d, " sixdigits=", sixdigitsbuf,
832 " printf(%g)=", snprintfbuf)
833 .c_str());
834 }
835 }
836 };
837 // Some quick sanity checks...
838 checker(5e-324);
839 checker(1e-308);
840 checker(1.0);
841 checker(1.000005);
842 checker(1.7976931348623157e308);
843 checker(0.00390625);
844#ifndef _MSC_VER
845 // on MSVC, snprintf() rounds it to 0.00195313. SixDigitsToBuffer() rounds it
846 // to 0.00195312 (round half to even).
847 checker(0.001953125);
848#endif
849 checker(0.005859375);
850 // Some cases where the rounding is very very close
851 checker(1.089095e-15);
852 checker(3.274195e-55);
853 checker(6.534355e-146);
854 checker(2.920845e+234);
855
856 if (mismatches.empty()) {
857 test_count = 0;
858 ExhaustiveFloat(kFloatNumCases, checker);
859
860 test_count = 0;
861 std::vector<int> digit_testcases{
862 100000, 100001, 100002, 100005, 100010, 100020, 100050, 100100, // misc
863 195312, 195313, // 1.953125 is a case where we round down, just barely.
864 200000, 500000, 800000, // misc mid-range cases
865 585937, 585938, // 5.859375 is a case where we round up, just barely.
866 900000, 990000, 999000, 999900, 999990, 999996, 999997, 999998, 999999};
867 if (kFloatNumCases >= 1e9) {
868 // If at least 1 billion test cases were requested, user wants an
869 // exhaustive test. So let's test all mantissas, too.
870 constexpr int min_mantissa = 100000, max_mantissa = 999999;
871 digit_testcases.resize(max_mantissa - min_mantissa + 1);
872 std::iota(digit_testcases.begin(), digit_testcases.end(), min_mantissa);
873 }
874
875 for (int exponent = -324; exponent <= 308; ++exponent) {
876 double powten = absl::strings_internal::Pow10(exponent);
877 if (powten == 0) powten = 5e-324;
878 if (kFloatNumCases >= 1e9) {
879 // The exhaustive test takes a very long time, so log progress.
880 char buf[kSixDigitsToBufferSize];
881 ABSL_RAW_LOG(
882 INFO, "%s",
883 absl::StrCat("Exp ", exponent, " powten=", powten, "(", powten,
884 ") (",
885 std::string(buf, SixDigitsToBuffer(powten, buf)), ")")
886 .c_str());
887 }
888 for (int digits : digit_testcases) {
889 if (exponent == 308 && digits >= 179769) break; // don't overflow!
890 double digiform = (digits + 0.5) * 0.00001;
891 double testval = digiform * powten;
892 double pretestval = nextafter(testval, 0);
893 double posttestval = nextafter(testval, 1.7976931348623157e308);
894 checker(testval);
895 checker(pretestval);
896 checker(posttestval);
897 }
898 }
899 } else {
900 EXPECT_EQ(mismatches.size(), 0);
901 for (size_t i = 0; i < mismatches.size(); ++i) {
902 if (i > 100) i = mismatches.size() - 1;
903 double d = mismatches[i];
904 char sixdigitsbuf[kSixDigitsToBufferSize] = {0};
905 SixDigitsToBuffer(d, sixdigitsbuf);
906 char snprintfbuf[kSixDigitsToBufferSize] = {0};
907 snprintf(snprintfbuf, kSixDigitsToBufferSize, "%g", d);
908 double before = nextafter(d, 0.0);
909 double after = nextafter(d, 1.7976931348623157e308);
910 char b1[32], b2[kSixDigitsToBufferSize];
911 ABSL_RAW_LOG(
912 ERROR, "%s",
913 absl::StrCat(
914 "Mismatch #", i, " d=", d, " (", ToNineDigits(d), ")",
915 " sixdigits='", sixdigitsbuf, "'", " snprintf='", snprintfbuf,
916 "'", " Before.=", PerfectDtoa(before), " ",
917 (SixDigitsToBuffer(before, b2), b2),
918 " vs snprintf=", (snprintf(b1, sizeof(b1), "%g", before), b1),
919 " Perfect=", PerfectDtoa(d), " ", (SixDigitsToBuffer(d, b2), b2),
920 " vs snprintf=", (snprintf(b1, sizeof(b1), "%g", d), b1),
921 " After.=.", PerfectDtoa(after), " ",
922 (SixDigitsToBuffer(after, b2), b2),
923 " vs snprintf=", (snprintf(b1, sizeof(b1), "%g", after), b1))
924 .c_str());
925 }
926 }
927}
928
929TEST(StrToInt32, Partial) {
930 struct Int32TestLine {
931 std::string input;
932 bool status;
933 int32_t value;
934 };
935 const int32_t int32_min = std::numeric_limits<int32_t>::min();
936 const int32_t int32_max = std::numeric_limits<int32_t>::max();
937 Int32TestLine int32_test_line[] = {
938 {"", false, 0},
939 {" ", false, 0},
940 {"-", false, 0},
941 {"123@@@", false, 123},
942 {absl::StrCat(int32_min, int32_max), false, int32_min},
943 {absl::StrCat(int32_max, int32_max), false, int32_max},
944 };
945
946 for (const Int32TestLine& test_line : int32_test_line) {
947 int32_t value = -2;
948 bool status = safe_strto32_base(test_line.input, &value, 10);
949 EXPECT_EQ(test_line.status, status) << test_line.input;
950 EXPECT_EQ(test_line.value, value) << test_line.input;
951 value = -2;
952 status = safe_strto32_base(test_line.input, &value, 10);
953 EXPECT_EQ(test_line.status, status) << test_line.input;
954 EXPECT_EQ(test_line.value, value) << test_line.input;
955 value = -2;
956 status = safe_strto32_base(absl::string_view(test_line.input), &value, 10);
957 EXPECT_EQ(test_line.status, status) << test_line.input;
958 EXPECT_EQ(test_line.value, value) << test_line.input;
959 }
960}
961
962TEST(StrToUint32, Partial) {
963 struct Uint32TestLine {
964 std::string input;
965 bool status;
966 uint32_t value;
967 };
968 const uint32_t uint32_max = std::numeric_limits<uint32_t>::max();
969 Uint32TestLine uint32_test_line[] = {
970 {"", false, 0},
971 {" ", false, 0},
972 {"-", false, 0},
973 {"123@@@", false, 123},
974 {absl::StrCat(uint32_max, uint32_max), false, uint32_max},
975 };
976
977 for (const Uint32TestLine& test_line : uint32_test_line) {
978 uint32_t value = 2;
979 bool status = safe_strtou32_base(test_line.input, &value, 10);
980 EXPECT_EQ(test_line.status, status) << test_line.input;
981 EXPECT_EQ(test_line.value, value) << test_line.input;
982 value = 2;
983 status = safe_strtou32_base(test_line.input, &value, 10);
984 EXPECT_EQ(test_line.status, status) << test_line.input;
985 EXPECT_EQ(test_line.value, value) << test_line.input;
986 value = 2;
987 status = safe_strtou32_base(absl::string_view(test_line.input), &value, 10);
988 EXPECT_EQ(test_line.status, status) << test_line.input;
989 EXPECT_EQ(test_line.value, value) << test_line.input;
990 }
991}
992
993TEST(StrToInt64, Partial) {
994 struct Int64TestLine {
995 std::string input;
996 bool status;
997 int64_t value;
998 };
999 const int64_t int64_min = std::numeric_limits<int64_t>::min();
1000 const int64_t int64_max = std::numeric_limits<int64_t>::max();
1001 Int64TestLine int64_test_line[] = {
1002 {"", false, 0},
1003 {" ", false, 0},
1004 {"-", false, 0},
1005 {"123@@@", false, 123},
1006 {absl::StrCat(int64_min, int64_max), false, int64_min},
1007 {absl::StrCat(int64_max, int64_max), false, int64_max},
1008 };
1009
1010 for (const Int64TestLine& test_line : int64_test_line) {
1011 int64_t value = -2;
1012 bool status = safe_strto64_base(test_line.input, &value, 10);
1013 EXPECT_EQ(test_line.status, status) << test_line.input;
1014 EXPECT_EQ(test_line.value, value) << test_line.input;
1015 value = -2;
1016 status = safe_strto64_base(test_line.input, &value, 10);
1017 EXPECT_EQ(test_line.status, status) << test_line.input;
1018 EXPECT_EQ(test_line.value, value) << test_line.input;
1019 value = -2;
1020 status = safe_strto64_base(absl::string_view(test_line.input), &value, 10);
1021 EXPECT_EQ(test_line.status, status) << test_line.input;
1022 EXPECT_EQ(test_line.value, value) << test_line.input;
1023 }
1024}
1025
1026TEST(StrToUint64, Partial) {
1027 struct Uint64TestLine {
1028 std::string input;
1029 bool status;
1030 uint64_t value;
1031 };
1032 const uint64_t uint64_max = std::numeric_limits<uint64_t>::max();
1033 Uint64TestLine uint64_test_line[] = {
1034 {"", false, 0},
1035 {" ", false, 0},
1036 {"-", false, 0},
1037 {"123@@@", false, 123},
1038 {absl::StrCat(uint64_max, uint64_max), false, uint64_max},
1039 };
1040
1041 for (const Uint64TestLine& test_line : uint64_test_line) {
1042 uint64_t value = 2;
1043 bool status = safe_strtou64_base(test_line.input, &value, 10);
1044 EXPECT_EQ(test_line.status, status) << test_line.input;
1045 EXPECT_EQ(test_line.value, value) << test_line.input;
1046 value = 2;
1047 status = safe_strtou64_base(test_line.input, &value, 10);
1048 EXPECT_EQ(test_line.status, status) << test_line.input;
1049 EXPECT_EQ(test_line.value, value) << test_line.input;
1050 value = 2;
1051 status = safe_strtou64_base(absl::string_view(test_line.input), &value, 10);
1052 EXPECT_EQ(test_line.status, status) << test_line.input;
1053 EXPECT_EQ(test_line.value, value) << test_line.input;
1054 }
1055}
1056
1057TEST(StrToInt32Base, PrefixOnly) {
1058 struct Int32TestLine {
1059 std::string input;
1060 bool status;
1061 int32_t value;
1062 };
1063 Int32TestLine int32_test_line[] = {
1064 { "", false, 0 },
1065 { "-", false, 0 },
1066 { "-0", true, 0 },
1067 { "0", true, 0 },
1068 { "0x", false, 0 },
1069 { "-0x", false, 0 },
1070 };
1071 const int base_array[] = { 0, 2, 8, 10, 16 };
1072
1073 for (const Int32TestLine& line : int32_test_line) {
1074 for (const int base : base_array) {
1075 int32_t value = 2;
1076 bool status = safe_strto32_base(line.input.c_str(), &value, base);
1077 EXPECT_EQ(line.status, status) << line.input << " " << base;
1078 EXPECT_EQ(line.value, value) << line.input << " " << base;
1079 value = 2;
1080 status = safe_strto32_base(line.input, &value, base);
1081 EXPECT_EQ(line.status, status) << line.input << " " << base;
1082 EXPECT_EQ(line.value, value) << line.input << " " << base;
1083 value = 2;
1084 status = safe_strto32_base(absl::string_view(line.input), &value, base);
1085 EXPECT_EQ(line.status, status) << line.input << " " << base;
1086 EXPECT_EQ(line.value, value) << line.input << " " << base;
1087 }
1088 }
1089}
1090
1091TEST(StrToUint32Base, PrefixOnly) {
1092 struct Uint32TestLine {
1093 std::string input;
1094 bool status;
1095 uint32_t value;
1096 };
1097 Uint32TestLine uint32_test_line[] = {
1098 { "", false, 0 },
1099 { "0", true, 0 },
1100 { "0x", false, 0 },
1101 };
1102 const int base_array[] = { 0, 2, 8, 10, 16 };
1103
1104 for (const Uint32TestLine& line : uint32_test_line) {
1105 for (const int base : base_array) {
1106 uint32_t value = 2;
1107 bool status = safe_strtou32_base(line.input.c_str(), &value, base);
1108 EXPECT_EQ(line.status, status) << line.input << " " << base;
1109 EXPECT_EQ(line.value, value) << line.input << " " << base;
1110 value = 2;
1111 status = safe_strtou32_base(line.input, &value, base);
1112 EXPECT_EQ(line.status, status) << line.input << " " << base;
1113 EXPECT_EQ(line.value, value) << line.input << " " << base;
1114 value = 2;
1115 status = safe_strtou32_base(absl::string_view(line.input), &value, base);
1116 EXPECT_EQ(line.status, status) << line.input << " " << base;
1117 EXPECT_EQ(line.value, value) << line.input << " " << base;
1118 }
1119 }
1120}
1121
1122TEST(StrToInt64Base, PrefixOnly) {
1123 struct Int64TestLine {
1124 std::string input;
1125 bool status;
1126 int64_t value;
1127 };
1128 Int64TestLine int64_test_line[] = {
1129 { "", false, 0 },
1130 { "-", false, 0 },
1131 { "-0", true, 0 },
1132 { "0", true, 0 },
1133 { "0x", false, 0 },
1134 { "-0x", false, 0 },
1135 };
1136 const int base_array[] = { 0, 2, 8, 10, 16 };
1137
1138 for (const Int64TestLine& line : int64_test_line) {
1139 for (const int base : base_array) {
1140 int64_t value = 2;
1141 bool status = safe_strto64_base(line.input.c_str(), &value, base);
1142 EXPECT_EQ(line.status, status) << line.input << " " << base;
1143 EXPECT_EQ(line.value, value) << line.input << " " << base;
1144 value = 2;
1145 status = safe_strto64_base(line.input, &value, base);
1146 EXPECT_EQ(line.status, status) << line.input << " " << base;
1147 EXPECT_EQ(line.value, value) << line.input << " " << base;
1148 value = 2;
1149 status = safe_strto64_base(absl::string_view(line.input), &value, base);
1150 EXPECT_EQ(line.status, status) << line.input << " " << base;
1151 EXPECT_EQ(line.value, value) << line.input << " " << base;
1152 }
1153 }
1154}
1155
1156TEST(StrToUint64Base, PrefixOnly) {
1157 struct Uint64TestLine {
1158 std::string input;
1159 bool status;
1160 uint64_t value;
1161 };
1162 Uint64TestLine uint64_test_line[] = {
1163 { "", false, 0 },
1164 { "0", true, 0 },
1165 { "0x", false, 0 },
1166 };
1167 const int base_array[] = { 0, 2, 8, 10, 16 };
1168
1169 for (const Uint64TestLine& line : uint64_test_line) {
1170 for (const int base : base_array) {
1171 uint64_t value = 2;
1172 bool status = safe_strtou64_base(line.input.c_str(), &value, base);
1173 EXPECT_EQ(line.status, status) << line.input << " " << base;
1174 EXPECT_EQ(line.value, value) << line.input << " " << base;
1175 value = 2;
1176 status = safe_strtou64_base(line.input, &value, base);
1177 EXPECT_EQ(line.status, status) << line.input << " " << base;
1178 EXPECT_EQ(line.value, value) << line.input << " " << base;
1179 value = 2;
1180 status = safe_strtou64_base(absl::string_view(line.input), &value, base);
1181 EXPECT_EQ(line.status, status) << line.input << " " << base;
1182 EXPECT_EQ(line.value, value) << line.input << " " << base;
1183 }
1184 }
1185}
1186
1187} // namespace