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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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