Commit 88ed598e authored by Brett Wilson's avatar Brett Wilson Committed by Commit Bot

Convert <Num>ToString functions to use an overload.

This avoids needing to manually encode the type in the function call
as the correct variant will automatically be called for the input type.

Inline forwarding versions are left in the header for backwards
compatibility. These will be replaced in future patches.

Adds a Double->String16 conversion variant. Even though this is
currently never used, it feels like we should have this variant available.

Change-Id: I96ed8bb9100e8dbae3e4eff86edd3d1cfa040f8f
Reviewed-on: https://chromium-review.googlesource.com/772974
Commit-Queue: Brett Wilson <brettw@chromium.org>
Reviewed-by: default avatarDaniel Cheng <dcheng@chromium.org>
Cr-Commit-Position: refs/heads/master@{#517237}
parent 4312e796
...@@ -15,6 +15,7 @@ ...@@ -15,6 +15,7 @@
#include "base/logging.h" #include "base/logging.h"
#include "base/numerics/safe_math.h" #include "base/numerics/safe_math.h"
#include "base/scoped_clear_errno.h" #include "base/scoped_clear_errno.h"
#include "base/strings/utf_string_conversions.h"
#include "base/third_party/dmg_fp/dmg_fp.h" #include "base/third_party/dmg_fp/dmg_fp.h"
namespace base { namespace base {
...@@ -328,53 +329,65 @@ bool String16ToIntImpl(const StringPiece16& input, VALUE* output) { ...@@ -328,53 +329,65 @@ bool String16ToIntImpl(const StringPiece16& input, VALUE* output) {
} // namespace } // namespace
std::string IntToString(int value) { std::string NumberToString(int32_t value) {
return IntToStringT<std::string, int>::IntToString(value); return IntToStringT<std::string, int32_t>::IntToString(value);
} }
string16 IntToString16(int value) { string16 NumberToString16(int32_t value) {
return IntToStringT<string16, int>::IntToString(value); return IntToStringT<string16, int32_t>::IntToString(value);
} }
std::string UintToString(unsigned int value) { std::string NumberToString(uint32_t value) {
return IntToStringT<std::string, unsigned int>::IntToString(value); return IntToStringT<std::string, uint32_t>::IntToString(value);
} }
string16 UintToString16(unsigned int value) { string16 NumberToString16(uint32_t value) {
return IntToStringT<string16, unsigned int>::IntToString(value); return IntToStringT<string16, uint32_t>::IntToString(value);
} }
std::string Int64ToString(int64_t value) { std::string NumberToString(int64_t value) {
return IntToStringT<std::string, int64_t>::IntToString(value); return IntToStringT<std::string, int64_t>::IntToString(value);
} }
string16 Int64ToString16(int64_t value) { string16 NumberToString16(int64_t value) {
return IntToStringT<string16, int64_t>::IntToString(value); return IntToStringT<string16, int64_t>::IntToString(value);
} }
std::string Uint64ToString(uint64_t value) { std::string NumberToString(uint64_t value) {
return IntToStringT<std::string, uint64_t>::IntToString(value); return IntToStringT<std::string, uint64_t>::IntToString(value);
} }
string16 Uint64ToString16(uint64_t value) { string16 NumberToString16(uint64_t value) {
return IntToStringT<string16, uint64_t>::IntToString(value); return IntToStringT<string16, uint64_t>::IntToString(value);
} }
std::string SizeTToString(size_t value) { #if defined(OS_MACOSX)
std::string NumberToString(size_t value) {
return IntToStringT<std::string, size_t>::IntToString(value); return IntToStringT<std::string, size_t>::IntToString(value);
} }
string16 SizeTToString16(size_t value) { string16 NumberToString16(size_t value) {
return IntToStringT<string16, size_t>::IntToString(value); return IntToStringT<string16, size_t>::IntToString(value);
} }
#endif
std::string DoubleToString(double value) { std::string NumberToString(double value) {
// According to g_fmt.cc, it is sufficient to declare a buffer of size 32. // According to g_fmt.cc, it is sufficient to declare a buffer of size 32.
char buffer[32]; char buffer[32];
dmg_fp::g_fmt(buffer, value); dmg_fp::g_fmt(buffer, value);
return std::string(buffer); return std::string(buffer);
} }
base::string16 NumberToString16(double value) {
// According to g_fmt.cc, it is sufficient to declare a buffer of size 32.
char buffer[32];
dmg_fp::g_fmt(buffer, value);
// The number will be ASCII. This creates the string using the "input
// iterator" variant which promotes from 8-bit to 16-bit via "=".
return base::string16(&buffer[0], &buffer[strlen(buffer)]);
}
bool StringToInt(const StringPiece& input, int* output) { bool StringToInt(const StringPiece& input, int* output) {
return StringToIntImpl(input, output); return StringToIntImpl(input, output);
} }
......
...@@ -14,6 +14,7 @@ ...@@ -14,6 +14,7 @@
#include "base/base_export.h" #include "base/base_export.h"
#include "base/strings/string16.h" #include "base/strings/string16.h"
#include "base/strings/string_piece.h" #include "base/strings/string_piece.h"
#include "build/build_config.h"
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
// IMPORTANT MESSAGE FROM YOUR SPONSOR // IMPORTANT MESSAGE FROM YOUR SPONSOR
...@@ -39,24 +40,66 @@ namespace base { ...@@ -39,24 +40,66 @@ namespace base {
// Number -> string conversions ------------------------------------------------ // Number -> string conversions ------------------------------------------------
BASE_EXPORT std::string IntToString(int value); // Ignores locale! see warning above.
BASE_EXPORT string16 IntToString16(int value); BASE_EXPORT std::string NumberToString(int32_t value);
BASE_EXPORT std::string NumberToString(uint32_t value);
BASE_EXPORT std::string UintToString(unsigned value); BASE_EXPORT std::string NumberToString(int64_t value);
BASE_EXPORT string16 UintToString16(unsigned value); BASE_EXPORT std::string NumberToString(uint64_t value);
BASE_EXPORT std::string NumberToString(double value);
BASE_EXPORT std::string Int64ToString(int64_t value);
BASE_EXPORT string16 Int64ToString16(int64_t value); BASE_EXPORT base::string16 NumberToString16(int32_t value);
BASE_EXPORT base::string16 NumberToString16(uint32_t value);
BASE_EXPORT std::string Uint64ToString(uint64_t value); BASE_EXPORT base::string16 NumberToString16(int64_t value);
BASE_EXPORT string16 Uint64ToString16(uint64_t value); BASE_EXPORT base::string16 NumberToString16(uint64_t value);
BASE_EXPORT base::string16 NumberToString16(double value);
BASE_EXPORT std::string SizeTToString(size_t value);
BASE_EXPORT string16 SizeTToString16(size_t value); // Compilers seem to disagree about whether size_t is a different name for
// uint32_t/uint64_t, or whether it's a completely different type that requires
// DoubleToString converts the double to a string format that ignores the // a conversion. Therefore, a size_t version must exist for some compilers (to
// locale. If you want to use locale specific formatting, use ICU. // avoid ambiguous call errors), but must not exist for others (to avoid
BASE_EXPORT std::string DoubleToString(double value); // multiple definition errors).
#if defined(OS_MACOSX)
BASE_EXPORT std::string NumberToString(size_t value);
BASE_EXPORT base::string16 NumberToString16(size_t value);
#endif
// Type-specific naming for backwards compatibility.
//
// TODO(brettw) these should be removed and callers converted to the overloaded
// "NumberToString" variant.
inline std::string IntToString(int value) {
return NumberToString(value);
}
inline string16 IntToString16(int value) {
return NumberToString16(value);
}
inline std::string UintToString(unsigned value) {
return NumberToString(value);
}
inline string16 UintToString16(unsigned value) {
return NumberToString16(value);
}
inline std::string Int64ToString(int64_t value) {
return NumberToString(value);
}
inline string16 Int64ToString16(int64_t value) {
return NumberToString16(value);
}
inline std::string Uint64ToString(uint64_t value) {
return NumberToString(value);
}
inline string16 Uint64ToString16(uint64_t value) {
return NumberToString16(value);
}
inline std::string SizeTToString(size_t value) {
return NumberToString(value);
}
inline string16 SizeTToString16(size_t value) {
return NumberToString16(value);
}
inline std::string DoubleToString(double value) {
return NumberToString(value);
}
// String -> number conversions ------------------------------------------------ // String -> number conversions ------------------------------------------------
......
...@@ -25,7 +25,7 @@ namespace base { ...@@ -25,7 +25,7 @@ namespace base {
namespace { namespace {
template <typename INT> template <typename INT>
struct IntToStringTest { struct NumberToStringTest {
INT num; INT num;
const char* sexpected; const char* sexpected;
const char* uexpected; const char* uexpected;
...@@ -33,14 +33,14 @@ struct IntToStringTest { ...@@ -33,14 +33,14 @@ struct IntToStringTest {
} // namespace } // namespace
TEST(StringNumberConversionsTest, IntToString) { TEST(StringNumberConversionsTest, NumberToString) {
static const IntToStringTest<int> int_tests[] = { static const NumberToStringTest<int> int_tests[] = {
{ 0, "0", "0" }, {0, "0", "0"},
{ -1, "-1", "4294967295" }, {-1, "-1", "4294967295"},
{ std::numeric_limits<int>::max(), "2147483647", "2147483647" }, {std::numeric_limits<int>::max(), "2147483647", "2147483647"},
{ std::numeric_limits<int>::min(), "-2147483648", "2147483648" }, {std::numeric_limits<int>::min(), "-2147483648", "2147483648"},
}; };
static const IntToStringTest<int64_t> int64_tests[] = { static const NumberToStringTest<int64_t> int64_tests[] = {
{0, "0", "0"}, {0, "0", "0"},
{-1, "-1", "18446744073709551615"}, {-1, "-1", "18446744073709551615"},
{ {
...@@ -52,18 +52,20 @@ TEST(StringNumberConversionsTest, IntToString) { ...@@ -52,18 +52,20 @@ TEST(StringNumberConversionsTest, IntToString) {
}; };
for (size_t i = 0; i < arraysize(int_tests); ++i) { for (size_t i = 0; i < arraysize(int_tests); ++i) {
const IntToStringTest<int>* test = &int_tests[i]; const NumberToStringTest<int>& test = int_tests[i];
EXPECT_EQ(IntToString(test->num), test->sexpected); EXPECT_EQ(NumberToString(test.num), test.sexpected);
EXPECT_EQ(IntToString16(test->num), UTF8ToUTF16(test->sexpected)); EXPECT_EQ(NumberToString16(test.num), UTF8ToUTF16(test.sexpected));
EXPECT_EQ(UintToString(test->num), test->uexpected); EXPECT_EQ(NumberToString(static_cast<unsigned>(test.num)), test.uexpected);
EXPECT_EQ(UintToString16(test->num), UTF8ToUTF16(test->uexpected)); EXPECT_EQ(NumberToString16(static_cast<unsigned>(test.num)),
UTF8ToUTF16(test.uexpected));
} }
for (size_t i = 0; i < arraysize(int64_tests); ++i) { for (size_t i = 0; i < arraysize(int64_tests); ++i) {
const IntToStringTest<int64_t>* test = &int64_tests[i]; const NumberToStringTest<int64_t>& test = int64_tests[i];
EXPECT_EQ(Int64ToString(test->num), test->sexpected); EXPECT_EQ(NumberToString(test.num), test.sexpected);
EXPECT_EQ(Int64ToString16(test->num), UTF8ToUTF16(test->sexpected)); EXPECT_EQ(NumberToString16(test.num), UTF8ToUTF16(test.sexpected));
EXPECT_EQ(Uint64ToString(test->num), test->uexpected); EXPECT_EQ(NumberToString(static_cast<uint64_t>(test.num)), test.uexpected);
EXPECT_EQ(Uint64ToString16(test->num), UTF8ToUTF16(test->uexpected)); EXPECT_EQ(NumberToString16(static_cast<uint64_t>(test.num)),
UTF8ToUTF16(test.uexpected));
} }
} }
...@@ -79,7 +81,7 @@ TEST(StringNumberConversionsTest, Uint64ToString) { ...@@ -79,7 +81,7 @@ TEST(StringNumberConversionsTest, Uint64ToString) {
}; };
for (size_t i = 0; i < arraysize(cases); ++i) for (size_t i = 0; i < arraysize(cases); ++i)
EXPECT_EQ(cases[i].output, Uint64ToString(cases[i].input)); EXPECT_EQ(cases[i].output, NumberToString(cases[i].input));
} }
TEST(StringNumberConversionsTest, SizeTToString) { TEST(StringNumberConversionsTest, SizeTToString) {
...@@ -102,7 +104,7 @@ TEST(StringNumberConversionsTest, SizeTToString) { ...@@ -102,7 +104,7 @@ TEST(StringNumberConversionsTest, SizeTToString) {
}; };
for (size_t i = 0; i < arraysize(cases); ++i) for (size_t i = 0; i < arraysize(cases); ++i)
EXPECT_EQ(cases[i].output, SizeTToString(cases[i].input)); EXPECT_EQ(cases[i].output, NumberToString(cases[i].input));
} }
TEST(StringNumberConversionsTest, StringToInt) { TEST(StringNumberConversionsTest, StringToInt) {
...@@ -826,19 +828,20 @@ TEST(StringNumberConversionsTest, DoubleToString) { ...@@ -826,19 +828,20 @@ TEST(StringNumberConversionsTest, DoubleToString) {
}; };
for (size_t i = 0; i < arraysize(cases); ++i) { for (size_t i = 0; i < arraysize(cases); ++i) {
EXPECT_EQ(cases[i].expected, DoubleToString(cases[i].input)); EXPECT_EQ(cases[i].expected, NumberToString(cases[i].input));
EXPECT_EQ(cases[i].expected, UTF16ToUTF8(NumberToString16(cases[i].input)));
} }
// The following two values were seen in crashes in the wild. // The following two values were seen in crashes in the wild.
const char input_bytes[8] = {0, 0, 0, 0, '\xee', '\x6d', '\x73', '\x42'}; const char input_bytes[8] = {0, 0, 0, 0, '\xee', '\x6d', '\x73', '\x42'};
double input = 0; double input = 0;
memcpy(&input, input_bytes, arraysize(input_bytes)); memcpy(&input, input_bytes, arraysize(input_bytes));
EXPECT_EQ("1335179083776", DoubleToString(input)); EXPECT_EQ("1335179083776", NumberToString(input));
const char input_bytes2[8] = const char input_bytes2[8] =
{0, 0, 0, '\xa0', '\xda', '\x6c', '\x73', '\x42'}; {0, 0, 0, '\xa0', '\xda', '\x6c', '\x73', '\x42'};
input = 0; input = 0;
memcpy(&input, input_bytes2, arraysize(input_bytes2)); memcpy(&input, input_bytes2, arraysize(input_bytes2));
EXPECT_EQ("1334890332160", DoubleToString(input)); EXPECT_EQ("1334890332160", NumberToString(input));
} }
TEST(StringNumberConversionsTest, HexEncode) { TEST(StringNumberConversionsTest, HexEncode) {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment