mirror of
https://github.com/chromium/crashpad.git
synced 2025-03-19 18:03:47 +00:00
Switch all string-number conversion to use fundamental types, and add long to the list.
Change-Id: I9244df09415f9d46262e2b8d04b64d7c4f786436 Reviewed-on: https://chromium-review.googlesource.com/c/crashpad/crashpad/+/1565287 Commit-Queue: Eric Astor <epastor@google.com> Reviewed-by: Mark Mentovai <mark@chromium.org>
This commit is contained in:
parent
ad49fcfad6
commit
e50676dcf2
@ -97,15 +97,34 @@ struct StringToUnsignedIntTraits
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
struct StringToInt64Traits
|
struct StringToLongTraits
|
||||||
: public StringToSignedIntegerTraits<int64_t, int64_t> {
|
: public StringToSignedIntegerTraits<long, long long> {
|
||||||
static LongType Convert(const char* str, char** end, int base) {
|
static LongType Convert(const char* str, char** end, int base) {
|
||||||
return strtoll(str, end, base);
|
return strtoll(str, end, base);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
struct StringToUnsignedInt64Traits
|
struct StringToUnsignedLongTraits
|
||||||
: public StringToUnsignedIntegerTraits<uint64_t, uint64_t> {
|
: public StringToUnsignedIntegerTraits<unsigned long, unsigned long long> {
|
||||||
|
static LongType Convert(const char* str, char** end, int base) {
|
||||||
|
if (str[0] == '-') {
|
||||||
|
*end = const_cast<char*>(str);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return strtoull(str, end, base);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct StringToLongLongTraits
|
||||||
|
: public StringToSignedIntegerTraits<long long, long long> {
|
||||||
|
static LongType Convert(const char* str, char** end, int base) {
|
||||||
|
return strtoll(str, end, base);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct StringToUnsignedLongLongTraits
|
||||||
|
: public StringToUnsignedIntegerTraits<unsigned long long,
|
||||||
|
unsigned long long> {
|
||||||
static LongType Convert(const char* str, char** end, int base) {
|
static LongType Convert(const char* str, char** end, int base) {
|
||||||
if (str[0] == '-') {
|
if (str[0] == '-') {
|
||||||
*end = const_cast<char*>(str);
|
*end = const_cast<char*>(str);
|
||||||
@ -136,7 +155,7 @@ bool StringToIntegerInternal(const std::string& string,
|
|||||||
end != string.data() + string.length()) {
|
end != string.data() + string.length()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
*number = result;
|
*number = static_cast<IntType>(result);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -152,12 +171,21 @@ bool StringToNumber(const std::string& string, unsigned int* number) {
|
|||||||
return StringToIntegerInternal<StringToUnsignedIntTraits>(string, number);
|
return StringToIntegerInternal<StringToUnsignedIntTraits>(string, number);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool StringToNumber(const std::string& string, int64_t* number) {
|
bool StringToNumber(const std::string& string, long* number) {
|
||||||
return StringToIntegerInternal<StringToInt64Traits>(string, number);
|
return StringToIntegerInternal<StringToLongTraits>(string, number);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool StringToNumber(const std::string& string, uint64_t* number) {
|
bool StringToNumber(const std::string& string, unsigned long* number) {
|
||||||
return StringToIntegerInternal<StringToUnsignedInt64Traits>(string, number);
|
return StringToIntegerInternal<StringToUnsignedLongTraits>(string, number);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool StringToNumber(const std::string& string, long long* number) {
|
||||||
|
return StringToIntegerInternal<StringToLongLongTraits>(string, number);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool StringToNumber(const std::string& string, unsigned long long* number) {
|
||||||
|
return StringToIntegerInternal<StringToUnsignedLongLongTraits>(string,
|
||||||
|
number);
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace crashpad
|
} // namespace crashpad
|
||||||
|
@ -56,8 +56,10 @@ namespace crashpad {
|
|||||||
//! where such prefix recognition is desirable.
|
//! where such prefix recognition is desirable.
|
||||||
bool StringToNumber(const std::string& string, int* number);
|
bool StringToNumber(const std::string& string, int* number);
|
||||||
bool StringToNumber(const std::string& string, unsigned int* number);
|
bool StringToNumber(const std::string& string, unsigned int* number);
|
||||||
bool StringToNumber(const std::string& string, int64_t* number);
|
bool StringToNumber(const std::string& string, long* number);
|
||||||
bool StringToNumber(const std::string& string, uint64_t* number);
|
bool StringToNumber(const std::string& string, unsigned long* number);
|
||||||
|
bool StringToNumber(const std::string& string, long long* number);
|
||||||
|
bool StringToNumber(const std::string& string, unsigned long long* number);
|
||||||
//! \}
|
//! \}
|
||||||
|
|
||||||
} // namespace crashpad
|
} // namespace crashpad
|
||||||
|
@ -16,30 +16,39 @@
|
|||||||
|
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
|
|
||||||
|
#include <array>
|
||||||
#include <limits>
|
#include <limits>
|
||||||
|
#include <type_traits>
|
||||||
|
|
||||||
#include "base/stl_util.h"
|
#include "base/stl_util.h"
|
||||||
#include "gtest/gtest.h"
|
#include "gtest/gtest.h"
|
||||||
|
|
||||||
namespace crashpad {
|
#define STRINGIFY(a) STR(a)
|
||||||
namespace test {
|
#define STR(a) #a
|
||||||
namespace {
|
|
||||||
|
|
||||||
TEST(StringNumberConversion, StringToInt) {
|
template <typename TValueType>
|
||||||
static constexpr struct {
|
struct TestSpecification {
|
||||||
const char* string;
|
const char* string;
|
||||||
bool valid;
|
bool valid;
|
||||||
int value;
|
TValueType value;
|
||||||
} kTestData[] = {
|
};
|
||||||
|
|
||||||
|
// Signed 32-bit test data
|
||||||
|
template <typename TIntType,
|
||||||
|
typename std::enable_if<std::is_integral<TIntType>::value &&
|
||||||
|
std::is_signed<TIntType>::value &&
|
||||||
|
(sizeof(TIntType) == 4)>::type* = nullptr>
|
||||||
|
static constexpr std::array<TestSpecification<TIntType>, 61> kTestDataFunc() {
|
||||||
|
return {{
|
||||||
{"", false, 0},
|
{"", false, 0},
|
||||||
{"0", true, 0},
|
{"0", true, 0},
|
||||||
{"1", true, 1},
|
{"1", true, 1},
|
||||||
{"2147483647", true, std::numeric_limits<int>::max()},
|
{"2147483647", true, std::numeric_limits<TIntType>::max()},
|
||||||
{"2147483648", false, 0},
|
{"2147483648", false, 0},
|
||||||
{"4294967295", false, 0},
|
{"4294967295", false, 0},
|
||||||
{"4294967296", false, 0},
|
{"4294967296", false, 0},
|
||||||
{"-1", true, -1},
|
{"-1", true, -1},
|
||||||
{"-2147483648", true, std::numeric_limits<int>::min()},
|
{"-2147483648", true, std::numeric_limits<TIntType>::min()},
|
||||||
{"-2147483649", false, 0},
|
{"-2147483649", false, 0},
|
||||||
{"00", true, 0},
|
{"00", true, 0},
|
||||||
{"01", true, 1},
|
{"01", true, 1},
|
||||||
@ -50,12 +59,12 @@ TEST(StringNumberConversion, StringToInt) {
|
|||||||
{"+0x20", true, 32},
|
{"+0x20", true, 32},
|
||||||
{"0xf", true, 15},
|
{"0xf", true, 15},
|
||||||
{"0xg", false, 0},
|
{"0xg", false, 0},
|
||||||
{"0x7fffffff", true, std::numeric_limits<int>::max()},
|
{"0x7fffffff", true, std::numeric_limits<TIntType>::max()},
|
||||||
{"0x7FfFfFfF", true, std::numeric_limits<int>::max()},
|
{"0x7FfFfFfF", true, std::numeric_limits<TIntType>::max()},
|
||||||
{"0x80000000", false, 0},
|
{"0x80000000", false, 0},
|
||||||
{"0xFFFFFFFF", false, 0},
|
{"0xFFFFFFFF", false, 0},
|
||||||
{"-0x7fffffff", true, -2147483647},
|
{"-0x7fffffff", true, -2147483647},
|
||||||
{"-0x80000000", true, std::numeric_limits<int>::min()},
|
{"-0x80000000", true, std::numeric_limits<TIntType>::min()},
|
||||||
{"-0x80000001", false, 0},
|
{"-0x80000001", false, 0},
|
||||||
{"-0xffffffff", false, 0},
|
{"-0xffffffff", false, 0},
|
||||||
{"0x100000000", false, 0},
|
{"0x100000000", false, 0},
|
||||||
@ -92,45 +101,22 @@ TEST(StringNumberConversion, StringToInt) {
|
|||||||
{"9223372036854775809", false, 0},
|
{"9223372036854775809", false, 0},
|
||||||
{"18446744073709551615", false, 0},
|
{"18446744073709551615", false, 0},
|
||||||
{"18446744073709551616", false, 0},
|
{"18446744073709551616", false, 0},
|
||||||
};
|
}};
|
||||||
|
|
||||||
for (size_t index = 0; index < base::size(kTestData); ++index) {
|
|
||||||
int value;
|
|
||||||
bool valid = StringToNumber(kTestData[index].string, &value);
|
|
||||||
if (kTestData[index].valid) {
|
|
||||||
EXPECT_TRUE(valid) << "index " << index << ", string "
|
|
||||||
<< kTestData[index].string;
|
|
||||||
if (valid) {
|
|
||||||
EXPECT_EQ(value, kTestData[index].value)
|
|
||||||
<< "index " << index << ", string " << kTestData[index].string;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
EXPECT_FALSE(valid) << "index " << index << ", string "
|
|
||||||
<< kTestData[index].string << ", value " << value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Ensure that embedded NUL characters are treated as bad input. The string
|
|
||||||
// is split to avoid MSVC warning:
|
|
||||||
// "decimal digit terminates octal escape sequence".
|
|
||||||
static constexpr char input[] = "6\000" "6";
|
|
||||||
std::string input_string(input, base::size(input) - 1);
|
|
||||||
int output;
|
|
||||||
EXPECT_FALSE(StringToNumber(input_string, &output));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(StringNumberConversion, StringToUnsignedInt) {
|
// Unsigned 32-bit test data
|
||||||
static constexpr struct {
|
template <typename TIntType,
|
||||||
const char* string;
|
typename std::enable_if<std::is_integral<TIntType>::value &&
|
||||||
bool valid;
|
!std::is_signed<TIntType>::value &&
|
||||||
unsigned int value;
|
(sizeof(TIntType) == 4)>::type* = nullptr>
|
||||||
} kTestData[] = {
|
static constexpr std::array<TestSpecification<TIntType>, 61> kTestDataFunc() {
|
||||||
|
return {{
|
||||||
{"", false, 0},
|
{"", false, 0},
|
||||||
{"0", true, 0},
|
{"0", true, 0},
|
||||||
{"1", true, 1},
|
{"1", true, 1},
|
||||||
{"2147483647", true, 2147483647},
|
{"2147483647", true, 2147483647},
|
||||||
{"2147483648", true, 2147483648},
|
{"2147483648", true, 2147483648},
|
||||||
{"4294967295", true, std::numeric_limits<unsigned int>::max()},
|
{"4294967295", true, std::numeric_limits<TIntType>::max()},
|
||||||
{"4294967296", false, 0},
|
{"4294967296", false, 0},
|
||||||
{"-1", false, 0},
|
{"-1", false, 0},
|
||||||
{"-2147483648", false, 0},
|
{"-2147483648", false, 0},
|
||||||
@ -186,9 +172,121 @@ TEST(StringNumberConversion, StringToUnsignedInt) {
|
|||||||
{"9223372036854775809", false, 0},
|
{"9223372036854775809", false, 0},
|
||||||
{"18446744073709551615", false, 0},
|
{"18446744073709551615", false, 0},
|
||||||
{"18446744073709551616", false, 0},
|
{"18446744073709551616", false, 0},
|
||||||
};
|
}};
|
||||||
|
}
|
||||||
|
|
||||||
for (size_t index = 0; index < base::size(kTestData); ++index) {
|
// Signed 64-bit test data
|
||||||
|
template <typename TIntType,
|
||||||
|
typename std::enable_if<std::is_integral<TIntType>::value &&
|
||||||
|
std::is_signed<TIntType>::value &&
|
||||||
|
(sizeof(TIntType) == 8)>::type* = nullptr>
|
||||||
|
static constexpr std::array<TestSpecification<TIntType>, 24> kTestDataFunc() {
|
||||||
|
return {{
|
||||||
|
{"", false, 0},
|
||||||
|
{"0", true, 0},
|
||||||
|
{"1", true, 1},
|
||||||
|
{"2147483647", true, 2147483647},
|
||||||
|
{"2147483648", true, 2147483648},
|
||||||
|
{"4294967295", true, 4294967295},
|
||||||
|
{"4294967296", true, 4294967296},
|
||||||
|
{"9223372036854775807", true, std::numeric_limits<TIntType>::max()},
|
||||||
|
{"9223372036854775808", false, 0},
|
||||||
|
{"18446744073709551615", false, 0},
|
||||||
|
{"18446744073709551616", false, 0},
|
||||||
|
{"-1", true, -1},
|
||||||
|
{"-2147483648", true, INT64_C(-2147483648)},
|
||||||
|
{"-2147483649", true, INT64_C(-2147483649)},
|
||||||
|
{"-9223372036854775808", true, std::numeric_limits<TIntType>::min()},
|
||||||
|
{"-9223372036854775809", false, 0},
|
||||||
|
{"0x7fffffffffffffff", true, std::numeric_limits<TIntType>::max()},
|
||||||
|
{"0x8000000000000000", false, 0},
|
||||||
|
{"0xffffffffffffffff", false, 0},
|
||||||
|
{"0x10000000000000000", false, 0},
|
||||||
|
{"-0x7fffffffffffffff", true, -9223372036854775807},
|
||||||
|
{"-0x8000000000000000", true, std::numeric_limits<TIntType>::min()},
|
||||||
|
{"-0x8000000000000001", false, 0},
|
||||||
|
{"0x7Fffffffffffffff", true, std::numeric_limits<TIntType>::max()},
|
||||||
|
}};
|
||||||
|
}
|
||||||
|
|
||||||
|
// Unsigned 64-bit test data
|
||||||
|
template <typename TIntType,
|
||||||
|
typename std::enable_if<std::is_integral<TIntType>::value &&
|
||||||
|
!std::is_signed<TIntType>::value &&
|
||||||
|
(sizeof(TIntType) == 8)>::type* = nullptr>
|
||||||
|
static constexpr std::array<TestSpecification<TIntType>, 25> kTestDataFunc() {
|
||||||
|
return {{
|
||||||
|
{"", false, 0},
|
||||||
|
{"0", true, 0},
|
||||||
|
{"1", true, 1},
|
||||||
|
{"2147483647", true, 2147483647},
|
||||||
|
{"2147483648", true, 2147483648},
|
||||||
|
{"4294967295", true, 4294967295},
|
||||||
|
{"4294967296", true, 4294967296},
|
||||||
|
{"9223372036854775807", true, 9223372036854775807},
|
||||||
|
{"9223372036854775808", true, 9223372036854775808u},
|
||||||
|
{"18446744073709551615", true, std::numeric_limits<TIntType>::max()},
|
||||||
|
{"18446744073709551616", false, 0},
|
||||||
|
{"-1", false, 0},
|
||||||
|
{"-2147483648", false, 0},
|
||||||
|
{"-2147483649", false, 0},
|
||||||
|
{"-2147483648", false, 0},
|
||||||
|
{"-9223372036854775808", false, 0},
|
||||||
|
{"-9223372036854775809", false, 0},
|
||||||
|
{"0x7fffffffffffffff", true, 9223372036854775807},
|
||||||
|
{"0x8000000000000000", true, 9223372036854775808u},
|
||||||
|
{"0xffffffffffffffff", true, std::numeric_limits<TIntType>::max()},
|
||||||
|
{"0x10000000000000000", false, 0},
|
||||||
|
{"-0x7fffffffffffffff", false, 0},
|
||||||
|
{"-0x8000000000000000", false, 0},
|
||||||
|
{"-0x8000000000000001", false, 0},
|
||||||
|
{"0xFfffffffffffffff", true, std::numeric_limits<TIntType>::max()},
|
||||||
|
}};
|
||||||
|
}
|
||||||
|
|
||||||
|
// This string is split to avoid MSVC warning:
|
||||||
|
// "decimal digit terminates octal escape sequence".
|
||||||
|
static constexpr char kEmbeddedNullInputRaw[] = "6\000" "6";
|
||||||
|
|
||||||
|
namespace crashpad {
|
||||||
|
namespace test {
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
TEST(StringNumberConversion, StringToInt) {
|
||||||
|
static_assert(sizeof(int) == 4, "Test only configured for 32-bit int.");
|
||||||
|
static constexpr auto kTestData = kTestDataFunc<int>();
|
||||||
|
|
||||||
|
for (size_t index = 0; index < kTestData.size(); ++index) {
|
||||||
|
int value;
|
||||||
|
bool valid = StringToNumber(kTestData[index].string, &value);
|
||||||
|
if (kTestData[index].valid) {
|
||||||
|
EXPECT_TRUE(valid) << "index " << index << ", string "
|
||||||
|
<< kTestData[index].string;
|
||||||
|
if (valid) {
|
||||||
|
EXPECT_EQ(value, kTestData[index].value)
|
||||||
|
<< "index " << index << ", string " << kTestData[index].string;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
EXPECT_FALSE(valid) << "index " << index << ", string "
|
||||||
|
<< kTestData[index].string << ", value " << value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Ensure that embedded NUL characters are treated as bad input. The string
|
||||||
|
// is split to avoid MSVC warning:
|
||||||
|
// "decimal digit terminates octal escape sequence".
|
||||||
|
int output;
|
||||||
|
std::string kEmbeddedNullInput(kEmbeddedNullInputRaw,
|
||||||
|
base::size(kEmbeddedNullInputRaw) - 1);
|
||||||
|
EXPECT_FALSE(StringToNumber(kEmbeddedNullInput, &output));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(StringNumberConversion, StringToUnsignedInt) {
|
||||||
|
static_assert(sizeof(unsigned int) == 4,
|
||||||
|
"Test only configured for 32-bit unsigned int.");
|
||||||
|
static constexpr auto kTestData = kTestDataFunc<unsigned int>();
|
||||||
|
|
||||||
|
for (size_t index = 0; index < kTestData.size(); ++index) {
|
||||||
unsigned int value;
|
unsigned int value;
|
||||||
bool valid = StringToNumber(kTestData[index].string, &value);
|
bool valid = StringToNumber(kTestData[index].string, &value);
|
||||||
if (kTestData[index].valid) {
|
if (kTestData[index].valid) {
|
||||||
@ -207,46 +305,20 @@ TEST(StringNumberConversion, StringToUnsignedInt) {
|
|||||||
// Ensure that embedded NUL characters are treated as bad input. The string
|
// Ensure that embedded NUL characters are treated as bad input. The string
|
||||||
// is split to avoid MSVC warning:
|
// is split to avoid MSVC warning:
|
||||||
// "decimal digit terminates octal escape sequence".
|
// "decimal digit terminates octal escape sequence".
|
||||||
static constexpr char input[] = "6\000" "6";
|
|
||||||
std::string input_string(input, base::size(input) - 1);
|
|
||||||
unsigned int output;
|
unsigned int output;
|
||||||
EXPECT_FALSE(StringToNumber(input_string, &output));
|
std::string kEmbeddedNullInput(kEmbeddedNullInputRaw,
|
||||||
|
base::size(kEmbeddedNullInputRaw) - 1);
|
||||||
|
EXPECT_FALSE(StringToNumber(kEmbeddedNullInput, &output));
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(StringNumberConversion, StringToInt64) {
|
TEST(StringNumberConversion, StringToLong) {
|
||||||
static constexpr struct {
|
static_assert(
|
||||||
const char* string;
|
sizeof(long) == 4 || sizeof(long) == 8,
|
||||||
bool valid;
|
"Test not configured for " STRINGIFY(__SIZEOF_LONG__) "-byte long");
|
||||||
int64_t value;
|
static constexpr auto kTestData = kTestDataFunc<long>();
|
||||||
} kTestData[] = {
|
|
||||||
{"", false, 0},
|
|
||||||
{"0", true, 0},
|
|
||||||
{"1", true, 1},
|
|
||||||
{"2147483647", true, 2147483647},
|
|
||||||
{"2147483648", true, 2147483648},
|
|
||||||
{"4294967295", true, 4294967295},
|
|
||||||
{"4294967296", true, 4294967296},
|
|
||||||
{"9223372036854775807", true, std::numeric_limits<int64_t>::max()},
|
|
||||||
{"9223372036854775808", false, 0},
|
|
||||||
{"18446744073709551615", false, 0},
|
|
||||||
{"18446744073709551616", false, 0},
|
|
||||||
{"-1", true, -1},
|
|
||||||
{"-2147483648", true, INT64_C(-2147483648)},
|
|
||||||
{"-2147483649", true, INT64_C(-2147483649)},
|
|
||||||
{"-9223372036854775808", true, std::numeric_limits<int64_t>::min()},
|
|
||||||
{"-9223372036854775809", false, 0},
|
|
||||||
{"0x7fffffffffffffff", true, std::numeric_limits<int64_t>::max()},
|
|
||||||
{"0x8000000000000000", false, 0},
|
|
||||||
{"0xffffffffffffffff", false, 0},
|
|
||||||
{"0x10000000000000000", false, 0},
|
|
||||||
{"-0x7fffffffffffffff", true, -9223372036854775807},
|
|
||||||
{"-0x8000000000000000", true, std::numeric_limits<int64_t>::min()},
|
|
||||||
{"-0x8000000000000001", false, 0},
|
|
||||||
{"0x7Fffffffffffffff", true, std::numeric_limits<int64_t>::max()},
|
|
||||||
};
|
|
||||||
|
|
||||||
for (size_t index = 0; index < base::size(kTestData); ++index) {
|
for (size_t index = 0; index < kTestData.size(); ++index) {
|
||||||
int64_t value;
|
long value;
|
||||||
bool valid = StringToNumber(kTestData[index].string, &value);
|
bool valid = StringToNumber(kTestData[index].string, &value);
|
||||||
if (kTestData[index].valid) {
|
if (kTestData[index].valid) {
|
||||||
EXPECT_TRUE(valid) << "index " << index << ", string "
|
EXPECT_TRUE(valid) << "index " << index << ", string "
|
||||||
@ -262,41 +334,58 @@ TEST(StringNumberConversion, StringToInt64) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(StringNumberConversion, StringToUnsignedInt64) {
|
TEST(StringNumberConversion, StringToUnsignedLong) {
|
||||||
static constexpr struct {
|
static_assert(
|
||||||
const char* string;
|
sizeof(long) == 4 || sizeof(long) == 8,
|
||||||
bool valid;
|
"Test not configured for " STRINGIFY(__SIZEOF_LONG__) "-byte long");
|
||||||
uint64_t value;
|
static constexpr auto kTestData = kTestDataFunc<unsigned long>();
|
||||||
} kTestData[] = {
|
|
||||||
{"", false, 0},
|
|
||||||
{"0", true, 0},
|
|
||||||
{"1", true, 1},
|
|
||||||
{"2147483647", true, 2147483647},
|
|
||||||
{"2147483648", true, 2147483648},
|
|
||||||
{"4294967295", true, 4294967295},
|
|
||||||
{"4294967296", true, 4294967296},
|
|
||||||
{"9223372036854775807", true, 9223372036854775807},
|
|
||||||
{"9223372036854775808", true, 9223372036854775808u},
|
|
||||||
{"18446744073709551615", true, std::numeric_limits<uint64_t>::max()},
|
|
||||||
{"18446744073709551616", false, 0},
|
|
||||||
{"-1", false, 0},
|
|
||||||
{"-2147483648", false, 0},
|
|
||||||
{"-2147483649", false, 0},
|
|
||||||
{"-2147483648", false, 0},
|
|
||||||
{"-9223372036854775808", false, 0},
|
|
||||||
{"-9223372036854775809", false, 0},
|
|
||||||
{"0x7fffffffffffffff", true, 9223372036854775807},
|
|
||||||
{"0x8000000000000000", true, 9223372036854775808u},
|
|
||||||
{"0xffffffffffffffff", true, std::numeric_limits<uint64_t>::max()},
|
|
||||||
{"0x10000000000000000", false, 0},
|
|
||||||
{"-0x7fffffffffffffff", false, 0},
|
|
||||||
{"-0x8000000000000000", false, 0},
|
|
||||||
{"-0x8000000000000001", false, 0},
|
|
||||||
{"0xFfffffffffffffff", true, std::numeric_limits<uint64_t>::max()},
|
|
||||||
};
|
|
||||||
|
|
||||||
for (size_t index = 0; index < base::size(kTestData); ++index) {
|
for (size_t index = 0; index < kTestData.size(); ++index) {
|
||||||
uint64_t value;
|
unsigned long value;
|
||||||
|
bool valid = StringToNumber(kTestData[index].string, &value);
|
||||||
|
if (kTestData[index].valid) {
|
||||||
|
EXPECT_TRUE(valid) << "index " << index << ", string "
|
||||||
|
<< kTestData[index].string;
|
||||||
|
if (valid) {
|
||||||
|
EXPECT_EQ(value, kTestData[index].value)
|
||||||
|
<< "index " << index << ", string " << kTestData[index].string;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
EXPECT_FALSE(valid) << "index " << index << ", string "
|
||||||
|
<< kTestData[index].string << ", value " << value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(StringNumberConversion, StringToLongLong) {
|
||||||
|
static_assert(sizeof(long long) == 8,
|
||||||
|
"Test only configured for 64-bit long long.");
|
||||||
|
static constexpr auto kTestData = kTestDataFunc<long long>();
|
||||||
|
|
||||||
|
for (size_t index = 0; index < kTestData.size(); ++index) {
|
||||||
|
long long value;
|
||||||
|
bool valid = StringToNumber(kTestData[index].string, &value);
|
||||||
|
if (kTestData[index].valid) {
|
||||||
|
EXPECT_TRUE(valid) << "index " << index << ", string "
|
||||||
|
<< kTestData[index].string;
|
||||||
|
if (valid) {
|
||||||
|
EXPECT_EQ(value, kTestData[index].value)
|
||||||
|
<< "index " << index << ", string " << kTestData[index].string;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
EXPECT_FALSE(valid) << "index " << index << ", string "
|
||||||
|
<< kTestData[index].string << ", value " << value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(StringNumberConversion, StringToUnsignedLongLong) {
|
||||||
|
static_assert(sizeof(unsigned long long) == 8,
|
||||||
|
"Test only configured for 64-bit unsigned long long.");
|
||||||
|
static constexpr auto kTestData = kTestDataFunc<unsigned long long>();
|
||||||
|
|
||||||
|
for (size_t index = 0; index < kTestData.size(); ++index) {
|
||||||
|
unsigned long long value;
|
||||||
bool valid = StringToNumber(kTestData[index].string, &value);
|
bool valid = StringToNumber(kTestData[index].string, &value);
|
||||||
if (kTestData[index].valid) {
|
if (kTestData[index].valid) {
|
||||||
EXPECT_TRUE(valid) << "index " << index << ", string "
|
EXPECT_TRUE(valid) << "index " << index << ", string "
|
||||||
|
Loading…
x
Reference in New Issue
Block a user