summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--base/json_reader.cc3
-rw-r--r--base/json_reader_unittest.cc7
-rw-r--r--base/json_writer.cc2
-rw-r--r--base/string_util.cc164
-rw-r--r--base/string_util.h30
-rw-r--r--base/third_party/dmg_fp/dmg_fp.h3
6 files changed, 78 insertions, 131 deletions
diff --git a/base/json_reader.cc b/base/json_reader.cc
index 15d43cc..c0e019b 100644
--- a/base/json_reader.cc
+++ b/base/json_reader.cc
@@ -329,8 +329,7 @@ bool JSONReader::DecodeNumber(const Token& token, Value** node) {
}
double num_double;
- if (base::StringToDouble(num_string, &num_double, base::LOCALE_INDEPENDENT) &&
- base::IsFinite(num_double)) {
+ if (StringToDouble(num_string, &num_double) && base::IsFinite(num_double)) {
*node = Value::CreateRealValue(num_double);
return true;
}
diff --git a/base/json_reader_unittest.cc b/base/json_reader_unittest.cc
index 4339be1..ebc7062 100644
--- a/base/json_reader_unittest.cc
+++ b/base/json_reader_unittest.cc
@@ -183,6 +183,12 @@ TEST(JSONReaderTest, Reading) {
root = NULL;
ASSERT_FALSE(JSONReader::JsonToValue("NaN", &root, false, false));
ASSERT_FALSE(root);
+ root = NULL;
+ ASSERT_FALSE(JSONReader::JsonToValue("nan", &root, false, false));
+ ASSERT_FALSE(root);
+ root = NULL;
+ ASSERT_FALSE(JSONReader::JsonToValue("inf", &root, false, false));
+ ASSERT_FALSE(root);
// Invalid number formats
root = NULL;
@@ -495,4 +501,3 @@ TEST(JSONReaderTest, Reading) {
ASSERT_FALSE(JSONReader::Read("10", &root, false));
ASSERT_FALSE(JSONReader::Read("\"root\"", &root, false));
}
-
diff --git a/base/json_writer.cc b/base/json_writer.cc
index 4782eb55b..0da2925 100644
--- a/base/json_writer.cc
+++ b/base/json_writer.cc
@@ -58,7 +58,7 @@ void JSONWriter::BuildJSONString(const Value* const node, int depth) {
double value;
bool result = node->GetAsReal(&value);
DCHECK(result);
- std::string real = base::DoubleToString(value, base::LOCALE_INDEPENDENT);
+ std::string real = DoubleToString(value);
// Ensure that the number has a .0 if there's no decimal or 'e'. This
// makes sure that when we read the JSON back, it's interpreted as a
// real rather than an int.
diff --git a/base/string_util.cc b/base/string_util.cc
index 4cc67d7..b77a7fe 100644
--- a/base/string_util.cc
+++ b/base/string_util.cc
@@ -89,14 +89,13 @@ static bool CompareParameter(const ReplacementOffset& elem1,
// should check for leading whitespace.
template<typename StringToNumberTraits>
bool StringToNumber(const typename StringToNumberTraits::string_type& input,
- typename StringToNumberTraits::value_type* output,
- base::LocaleDependence locale_dependent) {
+ typename StringToNumberTraits::value_type* output) {
typedef StringToNumberTraits traits;
errno = 0; // Thread-safe? It is on at least Mac, Linux, and Windows.
typename traits::string_type::value_type* endptr = NULL;
typename traits::value_type value = traits::convert_func(input.c_str(),
- &endptr, locale_dependent == base::LOCALE_DEPENDENT);
+ &endptr);
*output = value;
// Cases to return false:
@@ -120,8 +119,7 @@ class StringToLongTraits {
typedef long value_type;
static const int kBase = 10;
static inline value_type convert_func(const string_type::value_type* str,
- string_type::value_type** endptr,
- bool locale_dependent) {
+ string_type::value_type** endptr) {
return strtol(str, endptr, kBase);
}
static inline bool valid_func(const string_type& str) {
@@ -135,8 +133,7 @@ class WStringToLongTraits {
typedef long value_type;
static const int kBase = 10;
static inline value_type convert_func(const string_type::value_type* str,
- string_type::value_type** endptr,
- bool locale_dependent) {
+ string_type::value_type** endptr) {
return wcstol(str, endptr, kBase);
}
static inline bool valid_func(const string_type& str) {
@@ -150,8 +147,7 @@ class StringToInt64Traits {
typedef int64 value_type;
static const int kBase = 10;
static inline value_type convert_func(const string_type::value_type* str,
- string_type::value_type** endptr,
- bool locale_dependent) {
+ string_type::value_type** endptr) {
#ifdef OS_WIN
return _strtoi64(str, endptr, kBase);
#else // assume OS_POSIX
@@ -169,8 +165,7 @@ class WStringToInt64Traits {
typedef int64 value_type;
static const int kBase = 10;
static inline value_type convert_func(const string_type::value_type* str,
- string_type::value_type** endptr,
- bool locale_dependent) {
+ string_type::value_type** endptr) {
#ifdef OS_WIN
return _wcstoi64(str, endptr, kBase);
#else // assume OS_POSIX
@@ -191,8 +186,7 @@ class HexStringToLongTraits {
typedef long value_type;
static const int kBase = 16;
static inline value_type convert_func(const string_type::value_type* str,
- string_type::value_type** endptr,
- bool locale_dependent) {
+ string_type::value_type** endptr) {
return strtoul(str, endptr, kBase);
}
static inline bool valid_func(const string_type& str) {
@@ -206,8 +200,7 @@ class HexWStringToLongTraits {
typedef long value_type;
static const int kBase = 16;
static inline value_type convert_func(const string_type::value_type* str,
- string_type::value_type** endptr,
- bool locale_dependent) {
+ string_type::value_type** endptr) {
return wcstoul(str, endptr, kBase);
}
static inline bool valid_func(const string_type& str) {
@@ -220,13 +213,8 @@ class StringToDoubleTraits {
typedef std::string string_type;
typedef double value_type;
static inline value_type convert_func(const string_type::value_type* str,
- string_type::value_type** endptr,
- bool locale_dependent) {
- if (locale_dependent) {
- return strtod(str, endptr);
- } else {
- return dmg_fp::strtod(str, endptr);
- }
+ string_type::value_type** endptr) {
+ return dmg_fp::strtod(str, endptr);
}
static inline bool valid_func(const string_type& str) {
return !str.empty() && !isspace(str[0]);
@@ -238,25 +226,20 @@ class WStringToDoubleTraits {
typedef std::wstring string_type;
typedef double value_type;
static inline value_type convert_func(const string_type::value_type* str,
- string_type::value_type** endptr,
- bool locale_dependent) {
- if (locale_dependent) {
- return wcstod(str, endptr);
- } else {
- // Because dmg_fp::strtod does not like wchar_t, we convert it to ASCII.
- // In theory, this should be safe, but it's possible that wide chars
- // might get ignored by accident causing something to be parsed when it
- // shouldn't.
- std::string ascii_string = WideToASCII(std::wstring(str));
- char* ascii_end = NULL;
- value_type ret = dmg_fp::strtod(ascii_string.c_str(), &ascii_end);
- if (ascii_string.c_str() + ascii_string.length() == ascii_end) {
- // Put endptr at end of input string, so it's not recognized as an error.
- *endptr = const_cast<string_type::value_type*>(str) + wcslen(str);
- }
-
- return ret;
+ string_type::value_type** endptr) {
+ // Because dmg_fp::strtod does not like wchar_t, we convert it to ASCII.
+ // In theory, this should be safe, but it's possible that wide chars
+ // might get ignored by accident causing something to be parsed when it
+ // shouldn't.
+ std::string ascii_string = WideToASCII(std::wstring(str));
+ char* ascii_end = NULL;
+ value_type ret = dmg_fp::strtod(ascii_string.c_str(), &ascii_end);
+ if (ascii_string.c_str() + ascii_string.length() == ascii_end) {
+ // Put endptr at end of input string, so it's not recognized as an error.
+ *endptr = const_cast<string_type::value_type*>(str) + wcslen(str);
}
+
+ return ret;
}
static inline bool valid_func(const string_type& str) {
return !str.empty() && !iswspace(str[0]);
@@ -305,45 +288,6 @@ bool IsWprintfFormatPortable(const wchar_t* format) {
return true;
}
-std::string DoubleToString(double value, LocaleDependence locale_dependent) {
- if (LOCALE_DEPENDENT == locale_dependent) {
- return StringPrintf("%g", value);
- } else {
- char buffer[32];
- dmg_fp::g_fmt(buffer, value);
- return std::string(buffer);
- }
-}
-
-std::wstring DoubleToWString(double value, LocaleDependence locale_dependent) {
- return ASCIIToWide(DoubleToString(value, locale_dependent));
-}
-
-bool StringToDouble(const std::string& input, double* output,
- LocaleDependence locale_dependent) {
- return StringToNumber<StringToDoubleTraits>(input, output,
- locale_dependent);
-}
-
-bool StringToDouble(const std::wstring& input, double* output,
- LocaleDependence locale_dependent) {
- return StringToNumber<WStringToDoubleTraits>(input, output,
- locale_dependent);
-}
-
-double StringToDouble(const std::string& value,
- LocaleDependence locale_dependent) {
- double result;
- StringToDouble(value, &result, locale_dependent);
- return result;
-}
-
-double StringToDouble(const std::wstring& value,
- LocaleDependence locale_dependent) {
- double result;
- StringToDouble(value, &result, locale_dependent);
- return result;
-}
} // namespace base
@@ -1054,6 +998,17 @@ std::wstring Uint64ToWString(uint64 value) {
IntToString(value);
}
+std::string DoubleToString(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);
+ return std::string(buffer);
+}
+
+std::wstring DoubleToWString(double value) {
+ return ASCIIToWide(DoubleToString(value));
+}
+
inline void StringAppendV(std::string* dst, const char* format, va_list ap) {
StringAppendVT<char>(dst, format, ap);
}
@@ -1064,22 +1019,6 @@ inline void StringAppendV(std::wstring* dst,
StringAppendVT<wchar_t>(dst, format, ap);
}
-bool StringToDouble(const std::string& input, double* output) {
- return StringToDouble(input, output, base::LOCALE_DEPENDENT);
-}
-
-bool StringToDouble(const std::wstring& input, double* output) {
- return StringToDouble(input, output, base::LOCALE_DEPENDENT);
-}
-
-double StringToDouble(const std::string& value) {
- return StringToDouble(value, base::LOCALE_DEPENDENT);
-}
-
-double StringToDouble(const std::wstring& value) {
- return StringToDouble(value, base::LOCALE_DEPENDENT);
-}
-
std::string StringPrintf(const char* format, ...) {
va_list ap;
va_start(ap, format);
@@ -1419,36 +1358,33 @@ bool MatchPattern(const std::string& eval, const std::string& pattern) {
bool StringToInt(const std::string& input, int* output) {
COMPILE_ASSERT(sizeof(int) == sizeof(long), cannot_strtol_to_int);
return StringToNumber<StringToLongTraits>(input,
- reinterpret_cast<long*>(output),
- base::LOCALE_DEPENDENT);
+ reinterpret_cast<long*>(output));
}
bool StringToInt(const std::wstring& input, int* output) {
COMPILE_ASSERT(sizeof(int) == sizeof(long), cannot_wcstol_to_int);
return StringToNumber<WStringToLongTraits>(input,
- reinterpret_cast<long*>(output),
- base::LOCALE_DEPENDENT);
+ reinterpret_cast<long*>(output));
}
bool StringToInt64(const std::string& input, int64* output) {
- return StringToNumber<StringToInt64Traits>(input, output, base::LOCALE_DEPENDENT);
+ return StringToNumber<StringToInt64Traits>(input, output);
}
bool StringToInt64(const std::wstring& input, int64* output) {
- return StringToNumber<WStringToInt64Traits>(input, output, base::LOCALE_DEPENDENT);
+ return StringToNumber<WStringToInt64Traits>(input, output);
}
bool HexStringToInt(const std::string& input, int* output) {
COMPILE_ASSERT(sizeof(int) == sizeof(long), cannot_strtol_to_int);
return StringToNumber<HexStringToLongTraits>(input,
- reinterpret_cast<long*>(output),
- base::LOCALE_DEPENDENT);
+ reinterpret_cast<long*>(output));
}
bool HexStringToInt(const std::wstring& input, int* output) {
COMPILE_ASSERT(sizeof(int) == sizeof(long), cannot_wcstol_to_int);
return StringToNumber<HexWStringToLongTraits>(
- input, reinterpret_cast<long*>(output), base::LOCALE_DEPENDENT);
+ input, reinterpret_cast<long*>(output));
}
int StringToInt(const std::string& value) {
@@ -1487,6 +1423,26 @@ int HexStringToInt(const std::wstring& value) {
return result;
}
+bool StringToDouble(const std::string& input, double* output) {
+ return StringToNumber<StringToDoubleTraits>(input, output);
+}
+
+bool StringToDouble(const std::wstring& input, double* output) {
+ return StringToNumber<WStringToDoubleTraits>(input, output);
+}
+
+double StringToDouble(const std::string& value) {
+ double result;
+ StringToDouble(value, &result);
+ return result;
+}
+
+double StringToDouble(const std::wstring& value) {
+ double result;
+ StringToDouble(value, &result);
+ return result;
+}
+
// The following code is compatible with the OpenBSD lcpy interface. See:
// http://www.gratisoft.us/todd/papers/strlcpy.html
// ftp://ftp.openbsd.org/pub/OpenBSD/src/lib/libc/string/{wcs,str}lcpy.c
diff --git a/base/string_util.h b/base/string_util.h
index 488d4a2..71c4991 100644
--- a/base/string_util.h
+++ b/base/string_util.h
@@ -95,23 +95,6 @@ size_t wcslcpy(wchar_t* dst, const wchar_t* src, size_t dst_size);
// This function is intended to be called from base::vswprintf.
bool IsWprintfFormatPortable(const wchar_t* format);
-enum LocaleDependence {
- LOCALE_DEPENDENT,
- LOCALE_INDEPENDENT
-};
-
-std::string DoubleToString(double value, LocaleDependence locale_dependent);
-std::wstring DoubleToWString(double value, LocaleDependence locale_dependent);
-
-bool StringToDouble(const std::string& input, double* output,
- LocaleDependence locale_dependent);
-bool StringToDouble(const std::wstring& input, double* output,
- LocaleDependence locale_dependent);
-double StringToDouble(const std::string& value,
- LocaleDependence locale_dependent);
-double StringToDouble(const std::wstring& value,
- LocaleDependence locale_dependent);
-
} // namespace base
#if defined(OS_WIN)
@@ -370,7 +353,10 @@ std::string Int64ToString(int64 value);
std::wstring Int64ToWString(int64 value);
std::string Uint64ToString(uint64 value);
std::wstring Uint64ToWString(uint64 value);
-
+// The DoubleToString methods convert the double to a string format that
+// ignores the locale. If you want to use locale specific formatting, use ICU.
+std::string DoubleToString(double value);
+std::wstring DoubleToWString(double value);
// Perform a best-effort conversion of the input string to a numeric type,
// setting |*output| to the result of the conversion. Returns true for
@@ -391,9 +377,10 @@ bool HexStringToInt(const std::wstring& input, int* output);
// For floating-point conversions, only conversions of input strings in decimal
// form are defined to work. Behavior with strings representing floating-point
-// numbers in hexadecimal, and strings representing non-fininte values (such
-// as NaN and inf) is undefined. Otherwise, these behave the same as the
-// integral variants above. By default, locale-dependent variant is used.
+// numbers in hexadecimal, and strings representing non-fininte values (such as
+// NaN and inf) is undefined. Otherwise, these behave the same as the integral
+// variants. This expects the input string to NOT be specific to the locale.
+// If your input is locale specific, use ICU to read the number.
bool StringToDouble(const std::string& input, double* output);
bool StringToDouble(const std::wstring& input, double* output);
@@ -406,7 +393,6 @@ int64 StringToInt64(const std::string& value);
int64 StringToInt64(const std::wstring& value);
int HexStringToInt(const std::string& value);
int HexStringToInt(const std::wstring& value);
-// By default, locale-dependent variant is used.
double StringToDouble(const std::string& value);
double StringToDouble(const std::wstring& value);
diff --git a/base/third_party/dmg_fp/dmg_fp.h b/base/third_party/dmg_fp/dmg_fp.h
index 21c7c97..4795397 100644
--- a/base/third_party/dmg_fp/dmg_fp.h
+++ b/base/third_party/dmg_fp/dmg_fp.h
@@ -21,7 +21,8 @@ char* dtoa(double d, int mode, int ndigits,
// Must be used to free values returned by dtoa.
void freedtoa(char* s);
-// Store the closest decimal approximation to x in b.
+// Store the closest decimal approximation to x in b (null terminated).
+// Returns a pointer to b. It is sufficient for |b| to be 32 characters.
char* g_fmt(char* b, double x);
} // namespace dmg_fp