1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "base/strings/string_number_conversions.h"
6
7 #include <errno.h>
8 #include <limits.h>
9 #include <stddef.h>
10 #include <stdint.h>
11 #include <stdio.h>
12
13 #include <cmath>
14 #include <limits>
15
16 #include "base/format_macros.h"
17 #include "base/macros.h"
18 #include "base/strings/stringprintf.h"
19 #include "base/strings/utf_string_conversions.h"
20 #include "testing/gtest/include/gtest/gtest.h"
21
22 namespace base {
23
24 namespace {
25
26 template <typename INT>
27 struct IntToStringTest {
28 INT num;
29 const char* sexpected;
30 const char* uexpected;
31 };
32
33 } // namespace
34
TEST(StringNumberConversionsTest,IntToString)35 TEST(StringNumberConversionsTest, IntToString) {
36 static const IntToStringTest<int> int_tests[] = {
37 { 0, "0", "0" },
38 { -1, "-1", "4294967295" },
39 { std::numeric_limits<int>::max(), "2147483647", "2147483647" },
40 { std::numeric_limits<int>::min(), "-2147483648", "2147483648" },
41 };
42 static const IntToStringTest<int64_t> int64_tests[] = {
43 {0, "0", "0"},
44 {-1, "-1", "18446744073709551615"},
45 {
46 std::numeric_limits<int64_t>::max(), "9223372036854775807",
47 "9223372036854775807",
48 },
49 {std::numeric_limits<int64_t>::min(), "-9223372036854775808",
50 "9223372036854775808"},
51 };
52
53 for (size_t i = 0; i < arraysize(int_tests); ++i) {
54 const IntToStringTest<int>* test = &int_tests[i];
55 EXPECT_EQ(IntToString(test->num), test->sexpected);
56 EXPECT_EQ(IntToString16(test->num), UTF8ToUTF16(test->sexpected));
57 EXPECT_EQ(UintToString(test->num), test->uexpected);
58 EXPECT_EQ(UintToString16(test->num), UTF8ToUTF16(test->uexpected));
59 }
60 for (size_t i = 0; i < arraysize(int64_tests); ++i) {
61 const IntToStringTest<int64_t>* test = &int64_tests[i];
62 EXPECT_EQ(Int64ToString(test->num), test->sexpected);
63 EXPECT_EQ(Int64ToString16(test->num), UTF8ToUTF16(test->sexpected));
64 EXPECT_EQ(Uint64ToString(test->num), test->uexpected);
65 EXPECT_EQ(Uint64ToString16(test->num), UTF8ToUTF16(test->uexpected));
66 }
67 }
68
TEST(StringNumberConversionsTest,Uint64ToString)69 TEST(StringNumberConversionsTest, Uint64ToString) {
70 static const struct {
71 uint64_t input;
72 std::string output;
73 } cases[] = {
74 {0, "0"},
75 {42, "42"},
76 {INT_MAX, "2147483647"},
77 {std::numeric_limits<uint64_t>::max(), "18446744073709551615"},
78 };
79
80 for (size_t i = 0; i < arraysize(cases); ++i)
81 EXPECT_EQ(cases[i].output, Uint64ToString(cases[i].input));
82 }
83
TEST(StringNumberConversionsTest,SizeTToString)84 TEST(StringNumberConversionsTest, SizeTToString) {
85 size_t size_t_max = std::numeric_limits<size_t>::max();
86 std::string size_t_max_string = StringPrintf("%" PRIuS, size_t_max);
87
88 static const struct {
89 size_t input;
90 std::string output;
91 } cases[] = {
92 {0, "0"},
93 {9, "9"},
94 {42, "42"},
95 {INT_MAX, "2147483647"},
96 {2147483648U, "2147483648"},
97 #if SIZE_MAX > 4294967295U
98 {99999999999U, "99999999999"},
99 #endif
100 {size_t_max, size_t_max_string},
101 };
102
103 for (size_t i = 0; i < arraysize(cases); ++i)
104 EXPECT_EQ(cases[i].output, Uint64ToString(cases[i].input));
105 }
106
TEST(StringNumberConversionsTest,StringToInt)107 TEST(StringNumberConversionsTest, StringToInt) {
108 static const struct {
109 std::string input;
110 int output;
111 bool success;
112 } cases[] = {
113 {"0", 0, true},
114 {"42", 42, true},
115 {"42\x99", 42, false},
116 {"\x99" "42\x99", 0, false},
117 {"-2147483648", INT_MIN, true},
118 {"2147483647", INT_MAX, true},
119 {"", 0, false},
120 {" 42", 42, false},
121 {"42 ", 42, false},
122 {"\t\n\v\f\r 42", 42, false},
123 {"blah42", 0, false},
124 {"42blah", 42, false},
125 {"blah42blah", 0, false},
126 {"-273.15", -273, false},
127 {"+98.6", 98, false},
128 {"--123", 0, false},
129 {"++123", 0, false},
130 {"-+123", 0, false},
131 {"+-123", 0, false},
132 {"-", 0, false},
133 {"-2147483649", INT_MIN, false},
134 {"-99999999999", INT_MIN, false},
135 {"2147483648", INT_MAX, false},
136 {"99999999999", INT_MAX, false},
137 };
138
139 for (size_t i = 0; i < arraysize(cases); ++i) {
140 int output = 0;
141 EXPECT_EQ(cases[i].success, StringToInt(cases[i].input, &output));
142 EXPECT_EQ(cases[i].output, output);
143
144 string16 utf16_input = UTF8ToUTF16(cases[i].input);
145 output = 0;
146 EXPECT_EQ(cases[i].success, StringToInt(utf16_input, &output));
147 EXPECT_EQ(cases[i].output, output);
148 }
149
150 // One additional test to verify that conversion of numbers in strings with
151 // embedded NUL characters. The NUL and extra data after it should be
152 // interpreted as junk after the number.
153 const char input[] = "6\06";
154 std::string input_string(input, arraysize(input) - 1);
155 int output;
156 EXPECT_FALSE(StringToInt(input_string, &output));
157 EXPECT_EQ(6, output);
158
159 string16 utf16_input = UTF8ToUTF16(input_string);
160 output = 0;
161 EXPECT_FALSE(StringToInt(utf16_input, &output));
162 EXPECT_EQ(6, output);
163
164 output = 0;
165 const char16 negative_wide_input[] = { 0xFF4D, '4', '2', 0};
166 EXPECT_FALSE(StringToInt(string16(negative_wide_input), &output));
167 EXPECT_EQ(0, output);
168 }
169
TEST(StringNumberConversionsTest,StringToUint)170 TEST(StringNumberConversionsTest, StringToUint) {
171 static const struct {
172 std::string input;
173 unsigned output;
174 bool success;
175 } cases[] = {
176 {"0", 0, true},
177 {"42", 42, true},
178 {"42\x99", 42, false},
179 {"\x99" "42\x99", 0, false},
180 {"-2147483648", 0, false},
181 {"2147483647", INT_MAX, true},
182 {"", 0, false},
183 {" 42", 42, false},
184 {"42 ", 42, false},
185 {"\t\n\v\f\r 42", 42, false},
186 {"blah42", 0, false},
187 {"42blah", 42, false},
188 {"blah42blah", 0, false},
189 {"-273.15", 0, false},
190 {"+98.6", 98, false},
191 {"--123", 0, false},
192 {"++123", 0, false},
193 {"-+123", 0, false},
194 {"+-123", 0, false},
195 {"-", 0, false},
196 {"-2147483649", 0, false},
197 {"-99999999999", 0, false},
198 {"4294967295", UINT_MAX, true},
199 {"4294967296", UINT_MAX, false},
200 {"99999999999", UINT_MAX, false},
201 };
202
203 for (size_t i = 0; i < arraysize(cases); ++i) {
204 unsigned output = 0;
205 EXPECT_EQ(cases[i].success, StringToUint(cases[i].input, &output));
206 EXPECT_EQ(cases[i].output, output);
207
208 string16 utf16_input = UTF8ToUTF16(cases[i].input);
209 output = 0;
210 EXPECT_EQ(cases[i].success, StringToUint(utf16_input, &output));
211 EXPECT_EQ(cases[i].output, output);
212 }
213
214 // One additional test to verify that conversion of numbers in strings with
215 // embedded NUL characters. The NUL and extra data after it should be
216 // interpreted as junk after the number.
217 const char input[] = "6\06";
218 std::string input_string(input, arraysize(input) - 1);
219 unsigned output;
220 EXPECT_FALSE(StringToUint(input_string, &output));
221 EXPECT_EQ(6U, output);
222
223 string16 utf16_input = UTF8ToUTF16(input_string);
224 output = 0;
225 EXPECT_FALSE(StringToUint(utf16_input, &output));
226 EXPECT_EQ(6U, output);
227
228 output = 0;
229 const char16 negative_wide_input[] = { 0xFF4D, '4', '2', 0};
230 EXPECT_FALSE(StringToUint(string16(negative_wide_input), &output));
231 EXPECT_EQ(0U, output);
232 }
233
TEST(StringNumberConversionsTest,StringToInt64)234 TEST(StringNumberConversionsTest, StringToInt64) {
235 static const struct {
236 std::string input;
237 int64_t output;
238 bool success;
239 } cases[] = {
240 {"0", 0, true},
241 {"42", 42, true},
242 {"-2147483648", INT_MIN, true},
243 {"2147483647", INT_MAX, true},
244 {"-2147483649", INT64_C(-2147483649), true},
245 {"-99999999999", INT64_C(-99999999999), true},
246 {"2147483648", INT64_C(2147483648), true},
247 {"99999999999", INT64_C(99999999999), true},
248 {"9223372036854775807", std::numeric_limits<int64_t>::max(), true},
249 {"-9223372036854775808", std::numeric_limits<int64_t>::min(), true},
250 {"09", 9, true},
251 {"-09", -9, true},
252 {"", 0, false},
253 {" 42", 42, false},
254 {"42 ", 42, false},
255 {"0x42", 0, false},
256 {"\t\n\v\f\r 42", 42, false},
257 {"blah42", 0, false},
258 {"42blah", 42, false},
259 {"blah42blah", 0, false},
260 {"-273.15", -273, false},
261 {"+98.6", 98, false},
262 {"--123", 0, false},
263 {"++123", 0, false},
264 {"-+123", 0, false},
265 {"+-123", 0, false},
266 {"-", 0, false},
267 {"-9223372036854775809", std::numeric_limits<int64_t>::min(), false},
268 {"-99999999999999999999", std::numeric_limits<int64_t>::min(), false},
269 {"9223372036854775808", std::numeric_limits<int64_t>::max(), false},
270 {"99999999999999999999", std::numeric_limits<int64_t>::max(), false},
271 };
272
273 for (size_t i = 0; i < arraysize(cases); ++i) {
274 int64_t output = 0;
275 EXPECT_EQ(cases[i].success, StringToInt64(cases[i].input, &output));
276 EXPECT_EQ(cases[i].output, output);
277
278 string16 utf16_input = UTF8ToUTF16(cases[i].input);
279 output = 0;
280 EXPECT_EQ(cases[i].success, StringToInt64(utf16_input, &output));
281 EXPECT_EQ(cases[i].output, output);
282 }
283
284 // One additional test to verify that conversion of numbers in strings with
285 // embedded NUL characters. The NUL and extra data after it should be
286 // interpreted as junk after the number.
287 const char input[] = "6\06";
288 std::string input_string(input, arraysize(input) - 1);
289 int64_t output;
290 EXPECT_FALSE(StringToInt64(input_string, &output));
291 EXPECT_EQ(6, output);
292
293 string16 utf16_input = UTF8ToUTF16(input_string);
294 output = 0;
295 EXPECT_FALSE(StringToInt64(utf16_input, &output));
296 EXPECT_EQ(6, output);
297 }
298
TEST(StringNumberConversionsTest,StringToUint64)299 TEST(StringNumberConversionsTest, StringToUint64) {
300 static const struct {
301 std::string input;
302 uint64_t output;
303 bool success;
304 } cases[] = {
305 {"0", 0, true},
306 {"42", 42, true},
307 {"-2147483648", 0, false},
308 {"2147483647", INT_MAX, true},
309 {"-2147483649", 0, false},
310 {"-99999999999", 0, false},
311 {"2147483648", UINT64_C(2147483648), true},
312 {"99999999999", UINT64_C(99999999999), true},
313 {"9223372036854775807", std::numeric_limits<int64_t>::max(), true},
314 {"-9223372036854775808", 0, false},
315 {"09", 9, true},
316 {"-09", 0, false},
317 {"", 0, false},
318 {" 42", 42, false},
319 {"42 ", 42, false},
320 {"0x42", 0, false},
321 {"\t\n\v\f\r 42", 42, false},
322 {"blah42", 0, false},
323 {"42blah", 42, false},
324 {"blah42blah", 0, false},
325 {"-273.15", 0, false},
326 {"+98.6", 98, false},
327 {"--123", 0, false},
328 {"++123", 0, false},
329 {"-+123", 0, false},
330 {"+-123", 0, false},
331 {"-", 0, false},
332 {"-9223372036854775809", 0, false},
333 {"-99999999999999999999", 0, false},
334 {"9223372036854775808", UINT64_C(9223372036854775808), true},
335 {"99999999999999999999", std::numeric_limits<uint64_t>::max(), false},
336 {"18446744073709551615", std::numeric_limits<uint64_t>::max(), true},
337 {"18446744073709551616", std::numeric_limits<uint64_t>::max(), false},
338 };
339
340 for (size_t i = 0; i < arraysize(cases); ++i) {
341 uint64_t output = 0;
342 EXPECT_EQ(cases[i].success, StringToUint64(cases[i].input, &output));
343 EXPECT_EQ(cases[i].output, output);
344
345 string16 utf16_input = UTF8ToUTF16(cases[i].input);
346 output = 0;
347 EXPECT_EQ(cases[i].success, StringToUint64(utf16_input, &output));
348 EXPECT_EQ(cases[i].output, output);
349 }
350
351 // One additional test to verify that conversion of numbers in strings with
352 // embedded NUL characters. The NUL and extra data after it should be
353 // interpreted as junk after the number.
354 const char input[] = "6\06";
355 std::string input_string(input, arraysize(input) - 1);
356 uint64_t output;
357 EXPECT_FALSE(StringToUint64(input_string, &output));
358 EXPECT_EQ(6U, output);
359
360 string16 utf16_input = UTF8ToUTF16(input_string);
361 output = 0;
362 EXPECT_FALSE(StringToUint64(utf16_input, &output));
363 EXPECT_EQ(6U, output);
364 }
365
TEST(StringNumberConversionsTest,StringToSizeT)366 TEST(StringNumberConversionsTest, StringToSizeT) {
367 size_t size_t_max = std::numeric_limits<size_t>::max();
368 std::string size_t_max_string = StringPrintf("%" PRIuS, size_t_max);
369
370 static const struct {
371 std::string input;
372 size_t output;
373 bool success;
374 } cases[] = {
375 {"0", 0, true},
376 {"42", 42, true},
377 {"-2147483648", 0, false},
378 {"2147483647", INT_MAX, true},
379 {"-2147483649", 0, false},
380 {"-99999999999", 0, false},
381 {"2147483648", 2147483648U, true},
382 #if SIZE_MAX > 4294967295U
383 {"99999999999", 99999999999U, true},
384 #endif
385 {"-9223372036854775808", 0, false},
386 {"09", 9, true},
387 {"-09", 0, false},
388 {"", 0, false},
389 {" 42", 42, false},
390 {"42 ", 42, false},
391 {"0x42", 0, false},
392 {"\t\n\v\f\r 42", 42, false},
393 {"blah42", 0, false},
394 {"42blah", 42, false},
395 {"blah42blah", 0, false},
396 {"-273.15", 0, false},
397 {"+98.6", 98, false},
398 {"--123", 0, false},
399 {"++123", 0, false},
400 {"-+123", 0, false},
401 {"+-123", 0, false},
402 {"-", 0, false},
403 {"-9223372036854775809", 0, false},
404 {"-99999999999999999999", 0, false},
405 {"999999999999999999999999", size_t_max, false},
406 {size_t_max_string, size_t_max, true},
407 };
408
409 for (size_t i = 0; i < arraysize(cases); ++i) {
410 size_t output = 0;
411 EXPECT_EQ(cases[i].success, StringToSizeT(cases[i].input, &output));
412 EXPECT_EQ(cases[i].output, output);
413
414 string16 utf16_input = UTF8ToUTF16(cases[i].input);
415 output = 0;
416 EXPECT_EQ(cases[i].success, StringToSizeT(utf16_input, &output));
417 EXPECT_EQ(cases[i].output, output);
418 }
419
420 // One additional test to verify that conversion of numbers in strings with
421 // embedded NUL characters. The NUL and extra data after it should be
422 // interpreted as junk after the number.
423 const char input[] = "6\06";
424 std::string input_string(input, arraysize(input) - 1);
425 size_t output;
426 EXPECT_FALSE(StringToSizeT(input_string, &output));
427 EXPECT_EQ(6U, output);
428
429 string16 utf16_input = UTF8ToUTF16(input_string);
430 output = 0;
431 EXPECT_FALSE(StringToSizeT(utf16_input, &output));
432 EXPECT_EQ(6U, output);
433 }
434
TEST(StringNumberConversionsTest,HexStringToInt)435 TEST(StringNumberConversionsTest, HexStringToInt) {
436 static const struct {
437 std::string input;
438 int64_t output;
439 bool success;
440 } cases[] = {
441 {"0", 0, true},
442 {"42", 66, true},
443 {"-42", -66, true},
444 {"+42", 66, true},
445 {"7fffffff", INT_MAX, true},
446 {"-80000000", INT_MIN, true},
447 {"80000000", INT_MAX, false}, // Overflow test.
448 {"-80000001", INT_MIN, false}, // Underflow test.
449 {"0x42", 66, true},
450 {"-0x42", -66, true},
451 {"+0x42", 66, true},
452 {"0x7fffffff", INT_MAX, true},
453 {"-0x80000000", INT_MIN, true},
454 {"-80000000", INT_MIN, true},
455 {"80000000", INT_MAX, false}, // Overflow test.
456 {"-80000001", INT_MIN, false}, // Underflow test.
457 {"0x0f", 15, true},
458 {"0f", 15, true},
459 {" 45", 0x45, false},
460 {"\t\n\v\f\r 0x45", 0x45, false},
461 {" 45", 0x45, false},
462 {"45 ", 0x45, false},
463 {"45:", 0x45, false},
464 {"efgh", 0xef, false},
465 {"0xefgh", 0xef, false},
466 {"hgfe", 0, false},
467 {"-", 0, false},
468 {"", 0, false},
469 {"0x", 0, false},
470 };
471
472 for (size_t i = 0; i < arraysize(cases); ++i) {
473 int output = 0;
474 EXPECT_EQ(cases[i].success, HexStringToInt(cases[i].input, &output));
475 EXPECT_EQ(cases[i].output, output);
476 }
477 // One additional test to verify that conversion of numbers in strings with
478 // embedded NUL characters. The NUL and extra data after it should be
479 // interpreted as junk after the number.
480 const char input[] = "0xc0ffee\0" "9";
481 std::string input_string(input, arraysize(input) - 1);
482 int output;
483 EXPECT_FALSE(HexStringToInt(input_string, &output));
484 EXPECT_EQ(0xc0ffee, output);
485 }
486
TEST(StringNumberConversionsTest,HexStringToUInt)487 TEST(StringNumberConversionsTest, HexStringToUInt) {
488 static const struct {
489 std::string input;
490 uint32_t output;
491 bool success;
492 } cases[] = {
493 {"0", 0, true},
494 {"42", 0x42, true},
495 {"-42", 0, false},
496 {"+42", 0x42, true},
497 {"7fffffff", INT_MAX, true},
498 {"-80000000", 0, false},
499 {"ffffffff", 0xffffffff, true},
500 {"DeadBeef", 0xdeadbeef, true},
501 {"0x42", 0x42, true},
502 {"-0x42", 0, false},
503 {"+0x42", 0x42, true},
504 {"0x7fffffff", INT_MAX, true},
505 {"-0x80000000", 0, false},
506 {"0xffffffff", std::numeric_limits<uint32_t>::max(), true},
507 {"0XDeadBeef", 0xdeadbeef, true},
508 {"0x7fffffffffffffff", std::numeric_limits<uint32_t>::max(),
509 false}, // Overflow test.
510 {"-0x8000000000000000", 0, false},
511 {"0x8000000000000000", std::numeric_limits<uint32_t>::max(),
512 false}, // Overflow test.
513 {"-0x8000000000000001", 0, false},
514 {"0xFFFFFFFFFFFFFFFF", std::numeric_limits<uint32_t>::max(),
515 false}, // Overflow test.
516 {"FFFFFFFFFFFFFFFF", std::numeric_limits<uint32_t>::max(),
517 false}, // Overflow test.
518 {"0x0000000000000000", 0, true},
519 {"0000000000000000", 0, true},
520 {"1FFFFFFFFFFFFFFFF", std::numeric_limits<uint32_t>::max(),
521 false}, // Overflow test.
522 {"0x0f", 0x0f, true},
523 {"0f", 0x0f, true},
524 {" 45", 0x45, false},
525 {"\t\n\v\f\r 0x45", 0x45, false},
526 {" 45", 0x45, false},
527 {"45 ", 0x45, false},
528 {"45:", 0x45, false},
529 {"efgh", 0xef, false},
530 {"0xefgh", 0xef, false},
531 {"hgfe", 0, false},
532 {"-", 0, false},
533 {"", 0, false},
534 {"0x", 0, false},
535 };
536
537 for (size_t i = 0; i < arraysize(cases); ++i) {
538 uint32_t output = 0;
539 EXPECT_EQ(cases[i].success, HexStringToUInt(cases[i].input, &output));
540 EXPECT_EQ(cases[i].output, output);
541 }
542 // One additional test to verify that conversion of numbers in strings with
543 // embedded NUL characters. The NUL and extra data after it should be
544 // interpreted as junk after the number.
545 const char input[] = "0xc0ffee\0" "9";
546 std::string input_string(input, arraysize(input) - 1);
547 uint32_t output;
548 EXPECT_FALSE(HexStringToUInt(input_string, &output));
549 EXPECT_EQ(0xc0ffeeU, output);
550 }
551
TEST(StringNumberConversionsTest,HexStringToInt64)552 TEST(StringNumberConversionsTest, HexStringToInt64) {
553 static const struct {
554 std::string input;
555 int64_t output;
556 bool success;
557 } cases[] = {
558 {"0", 0, true},
559 {"42", 66, true},
560 {"-42", -66, true},
561 {"+42", 66, true},
562 {"40acd88557b", INT64_C(4444444448123), true},
563 {"7fffffff", INT_MAX, true},
564 {"-80000000", INT_MIN, true},
565 {"ffffffff", 0xffffffff, true},
566 {"DeadBeef", 0xdeadbeef, true},
567 {"0x42", 66, true},
568 {"-0x42", -66, true},
569 {"+0x42", 66, true},
570 {"0x40acd88557b", INT64_C(4444444448123), true},
571 {"0x7fffffff", INT_MAX, true},
572 {"-0x80000000", INT_MIN, true},
573 {"0xffffffff", 0xffffffff, true},
574 {"0XDeadBeef", 0xdeadbeef, true},
575 {"0x7fffffffffffffff", std::numeric_limits<int64_t>::max(), true},
576 {"-0x8000000000000000", std::numeric_limits<int64_t>::min(), true},
577 {"0x8000000000000000", std::numeric_limits<int64_t>::max(),
578 false}, // Overflow test.
579 {"-0x8000000000000001", std::numeric_limits<int64_t>::min(),
580 false}, // Underflow test.
581 {"0x0f", 15, true},
582 {"0f", 15, true},
583 {" 45", 0x45, false},
584 {"\t\n\v\f\r 0x45", 0x45, false},
585 {" 45", 0x45, false},
586 {"45 ", 0x45, false},
587 {"45:", 0x45, false},
588 {"efgh", 0xef, false},
589 {"0xefgh", 0xef, false},
590 {"hgfe", 0, false},
591 {"-", 0, false},
592 {"", 0, false},
593 {"0x", 0, false},
594 };
595
596 for (size_t i = 0; i < arraysize(cases); ++i) {
597 int64_t output = 0;
598 EXPECT_EQ(cases[i].success, HexStringToInt64(cases[i].input, &output));
599 EXPECT_EQ(cases[i].output, output);
600 }
601 // One additional test to verify that conversion of numbers in strings with
602 // embedded NUL characters. The NUL and extra data after it should be
603 // interpreted as junk after the number.
604 const char input[] = "0xc0ffee\0" "9";
605 std::string input_string(input, arraysize(input) - 1);
606 int64_t output;
607 EXPECT_FALSE(HexStringToInt64(input_string, &output));
608 EXPECT_EQ(0xc0ffee, output);
609 }
610
TEST(StringNumberConversionsTest,HexStringToUInt64)611 TEST(StringNumberConversionsTest, HexStringToUInt64) {
612 static const struct {
613 std::string input;
614 uint64_t output;
615 bool success;
616 } cases[] = {
617 {"0", 0, true},
618 {"42", 66, true},
619 {"-42", 0, false},
620 {"+42", 66, true},
621 {"40acd88557b", INT64_C(4444444448123), true},
622 {"7fffffff", INT_MAX, true},
623 {"-80000000", 0, false},
624 {"ffffffff", 0xffffffff, true},
625 {"DeadBeef", 0xdeadbeef, true},
626 {"0x42", 66, true},
627 {"-0x42", 0, false},
628 {"+0x42", 66, true},
629 {"0x40acd88557b", INT64_C(4444444448123), true},
630 {"0x7fffffff", INT_MAX, true},
631 {"-0x80000000", 0, false},
632 {"0xffffffff", 0xffffffff, true},
633 {"0XDeadBeef", 0xdeadbeef, true},
634 {"0x7fffffffffffffff", std::numeric_limits<int64_t>::max(), true},
635 {"-0x8000000000000000", 0, false},
636 {"0x8000000000000000", UINT64_C(0x8000000000000000), true},
637 {"-0x8000000000000001", 0, false},
638 {"0xFFFFFFFFFFFFFFFF", std::numeric_limits<uint64_t>::max(), true},
639 {"FFFFFFFFFFFFFFFF", std::numeric_limits<uint64_t>::max(), true},
640 {"0x0000000000000000", 0, true},
641 {"0000000000000000", 0, true},
642 {"1FFFFFFFFFFFFFFFF", std::numeric_limits<uint64_t>::max(),
643 false}, // Overflow test.
644 {"0x0f", 15, true},
645 {"0f", 15, true},
646 {" 45", 0x45, false},
647 {"\t\n\v\f\r 0x45", 0x45, false},
648 {" 45", 0x45, false},
649 {"45 ", 0x45, false},
650 {"45:", 0x45, false},
651 {"efgh", 0xef, false},
652 {"0xefgh", 0xef, false},
653 {"hgfe", 0, false},
654 {"-", 0, false},
655 {"", 0, false},
656 {"0x", 0, false},
657 };
658
659 for (size_t i = 0; i < arraysize(cases); ++i) {
660 uint64_t output = 0;
661 EXPECT_EQ(cases[i].success, HexStringToUInt64(cases[i].input, &output));
662 EXPECT_EQ(cases[i].output, output);
663 }
664 // One additional test to verify that conversion of numbers in strings with
665 // embedded NUL characters. The NUL and extra data after it should be
666 // interpreted as junk after the number.
667 const char input[] = "0xc0ffee\0" "9";
668 std::string input_string(input, arraysize(input) - 1);
669 uint64_t output;
670 EXPECT_FALSE(HexStringToUInt64(input_string, &output));
671 EXPECT_EQ(0xc0ffeeU, output);
672 }
673
TEST(StringNumberConversionsTest,HexStringToBytes)674 TEST(StringNumberConversionsTest, HexStringToBytes) {
675 static const struct {
676 const std::string input;
677 const char* output;
678 size_t output_len;
679 bool success;
680 } cases[] = {
681 {"0", "", 0, false}, // odd number of characters fails
682 {"00", "\0", 1, true},
683 {"42", "\x42", 1, true},
684 {"-42", "", 0, false}, // any non-hex value fails
685 {"+42", "", 0, false},
686 {"7fffffff", "\x7f\xff\xff\xff", 4, true},
687 {"80000000", "\x80\0\0\0", 4, true},
688 {"deadbeef", "\xde\xad\xbe\xef", 4, true},
689 {"DeadBeef", "\xde\xad\xbe\xef", 4, true},
690 {"0x42", "", 0, false}, // leading 0x fails (x is not hex)
691 {"0f", "\xf", 1, true},
692 {"45 ", "\x45", 1, false},
693 {"efgh", "\xef", 1, false},
694 {"", "", 0, false},
695 {"0123456789ABCDEF", "\x01\x23\x45\x67\x89\xAB\xCD\xEF", 8, true},
696 {"0123456789ABCDEF012345",
697 "\x01\x23\x45\x67\x89\xAB\xCD\xEF\x01\x23\x45", 11, true},
698 };
699
700
701 for (size_t i = 0; i < arraysize(cases); ++i) {
702 std::vector<uint8_t> output;
703 std::vector<uint8_t> compare;
704 EXPECT_EQ(cases[i].success, HexStringToBytes(cases[i].input, &output)) <<
705 i << ": " << cases[i].input;
706 for (size_t j = 0; j < cases[i].output_len; ++j)
707 compare.push_back(static_cast<uint8_t>(cases[i].output[j]));
708 ASSERT_EQ(output.size(), compare.size()) << i << ": " << cases[i].input;
709 EXPECT_TRUE(std::equal(output.begin(), output.end(), compare.begin())) <<
710 i << ": " << cases[i].input;
711 }
712 }
713
TEST(StringNumberConversionsTest,StringToDouble)714 TEST(StringNumberConversionsTest, StringToDouble) {
715 static const struct {
716 std::string input;
717 double output;
718 bool success;
719 } cases[] = {
720 {"0", 0.0, true},
721 {"42", 42.0, true},
722 {"-42", -42.0, true},
723 {"123.45", 123.45, true},
724 {"-123.45", -123.45, true},
725 {"+123.45", 123.45, true},
726 {"2.99792458e8", 299792458.0, true},
727 {"149597870.691E+3", 149597870691.0, true},
728 {"6.", 6.0, true},
729 {"9e99999999999999999999", std::numeric_limits<double>::infinity(),
730 false},
731 {"-9e99999999999999999999", -std::numeric_limits<double>::infinity(),
732 false},
733 {"1e-2", 0.01, true},
734 {"42 ", 42.0, false},
735 {" 1e-2", 0.01, false},
736 {"1e-2 ", 0.01, false},
737 {"-1E-7", -0.0000001, true},
738 {"01e02", 100, true},
739 {"2.3e15", 2.3e15, true},
740 {"\t\n\v\f\r -123.45e2", -12345.0, false},
741 {"+123 e4", 123.0, false},
742 {"123e ", 123.0, false},
743 {"123e", 123.0, false},
744 {" 2.99", 2.99, false},
745 {"1e3.4", 1000.0, false},
746 {"nothing", 0.0, false},
747 {"-", 0.0, false},
748 {"+", 0.0, false},
749 {"", 0.0, false},
750 };
751
752 for (size_t i = 0; i < arraysize(cases); ++i) {
753 double output;
754 errno = 1;
755 EXPECT_EQ(cases[i].success, StringToDouble(cases[i].input, &output))
756 << "for input=" << cases[i].input << "got output=" << output;
757 if (cases[i].success)
758 EXPECT_EQ(1, errno) << i; // confirm that errno is unchanged.
759 EXPECT_DOUBLE_EQ(cases[i].output, output);
760 }
761
762 // One additional test to verify that conversion of numbers in strings with
763 // embedded NUL characters. The NUL and extra data after it should be
764 // interpreted as junk after the number.
765 const char input[] = "3.14\0" "159";
766 std::string input_string(input, arraysize(input) - 1);
767 double output;
768 EXPECT_FALSE(StringToDouble(input_string, &output));
769 EXPECT_DOUBLE_EQ(3.14, output);
770 }
771
TEST(StringNumberConversionsTest,DoubleToString)772 TEST(StringNumberConversionsTest, DoubleToString) {
773 static const struct {
774 double input;
775 const char* expected;
776 } cases[] = {
777 {0.0, "0.0"},
778 {1.25, "1.25"},
779 {1.33518e+012, "1335180000000.0"},
780 {1.33489e+012, "1334890000000.0"},
781 {1.33505e+012, "1335050000000.0"},
782 {1.33545e+009, "1335450000.0"},
783 {1.33503e+009, "1335030000.0"},
784 };
785
786 for (size_t i = 0; i < arraysize(cases); ++i) {
787 EXPECT_EQ(cases[i].expected, DoubleToString(cases[i].input));
788 }
789
790 // The following two values were seen in crashes in the wild.
791 const char input_bytes[8] = {0, 0, 0, 0, '\xee', '\x6d', '\x73', '\x42'};
792 double input = 0;
793 memcpy(&input, input_bytes, arraysize(input_bytes));
794 EXPECT_EQ("1335179083776.0", DoubleToString(input));
795 const char input_bytes2[8] =
796 {0, 0, 0, '\xa0', '\xda', '\x6c', '\x73', '\x42'};
797 input = 0;
798 memcpy(&input, input_bytes2, arraysize(input_bytes2));
799 EXPECT_EQ("1334890332160.0", DoubleToString(input));
800 }
801
TEST(StringNumberConversionsTest,HexEncode)802 TEST(StringNumberConversionsTest, HexEncode) {
803 std::string hex(HexEncode(NULL, 0));
804 EXPECT_EQ(hex.length(), 0U);
805 unsigned char bytes[] = {0x01, 0xff, 0x02, 0xfe, 0x03, 0x80, 0x81};
806 hex = HexEncode(bytes, sizeof(bytes));
807 EXPECT_EQ(hex.compare("01FF02FE038081"), 0);
808 }
809
810 } // namespace base
811