Index: base/string_util.cc |
diff --git a/base/string_util.cc b/base/string_util.cc |
index 4c2769389b23a99a1a2ef9eda7d0d3e03ddf6d9e..ae24d30f1641fd8bc3347eec9b58427e6745ad06 100644 |
--- a/base/string_util.cc |
+++ b/base/string_util.cc |
@@ -4,6 +4,8 @@ |
#include "base/string_util.h" |
+#include "build/build_config.h" |
+ |
#include <ctype.h> |
#include <errno.h> |
#include <math.h> |
@@ -21,6 +23,7 @@ |
#include "base/basictypes.h" |
#include "base/logging.h" |
#include "base/singleton.h" |
+#include "third_party/dmg_fp/dmg_fp.h" |
namespace { |
@@ -86,13 +89,14 @@ 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) { |
+ typename StringToNumberTraits::value_type* output, |
+ base::LocaleDependence locale_dependent) { |
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); |
+ &endptr, locale_dependent == base::LOCALE_DEPENDENT); |
*output = value; |
// Cases to return false: |
@@ -116,7 +120,8 @@ 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) { |
+ string_type::value_type** endptr, |
+ bool locale_dependent) { |
return strtol(str, endptr, kBase); |
} |
static inline bool valid_func(const string_type& str) { |
@@ -130,7 +135,8 @@ 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) { |
+ string_type::value_type** endptr, |
+ bool locale_dependent) { |
return wcstol(str, endptr, kBase); |
} |
static inline bool valid_func(const string_type& str) { |
@@ -144,7 +150,8 @@ 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) { |
+ string_type::value_type** endptr, |
+ bool locale_dependent) { |
#ifdef OS_WIN |
return _strtoi64(str, endptr, kBase); |
#else // assume OS_POSIX |
@@ -162,7 +169,8 @@ 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) { |
+ string_type::value_type** endptr, |
+ bool locale_dependent) { |
#ifdef OS_WIN |
return _wcstoi64(str, endptr, kBase); |
#else // assume OS_POSIX |
@@ -183,7 +191,8 @@ 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) { |
+ string_type::value_type** endptr, |
+ bool locale_dependent) { |
return strtoul(str, endptr, kBase); |
} |
static inline bool valid_func(const string_type& str) { |
@@ -197,7 +206,8 @@ 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) { |
+ string_type::value_type** endptr, |
+ bool locale_dependent) { |
return wcstoul(str, endptr, kBase); |
} |
static inline bool valid_func(const string_type& str) { |
@@ -210,8 +220,13 @@ 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) { |
- return strtod(str, endptr); |
+ string_type::value_type** endptr, |
+ bool locale_dependent) { |
+ if (locale_dependent) { |
+ return strtod(str, endptr); |
+ } else { |
+ return dmg_fp::strtod(str, endptr); |
+ } |
} |
static inline bool valid_func(const string_type& str) { |
return !str.empty() && !isspace(str[0]); |
@@ -223,8 +238,21 @@ 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) { |
- return wcstod(str, endptr); |
+ string_type::value_type** endptr, |
+ bool locale_dependent) { |
+ if (base::LOCALE_DEPENDENT == locale_dependent) { |
+ return wcstod(str, endptr); |
+ } else { |
+ // We are going to do some interesting things here, just because |
+ // dmg_fp::strtod does not like wchar_t. Converting to ASCII should |
+ // be fine. |
+ |
+ // 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); |
+ |
+ std::string ascii_string = WideToASCII(std::wstring(str)); |
+ return StringToDouble(ascii_string, base::LOCALE_INDEPENDENT); |
+ } |
} |
static inline bool valid_func(const string_type& str) { |
return !str.empty() && !iswspace(str[0]); |
@@ -273,6 +301,46 @@ 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 |
@@ -992,6 +1060,22 @@ 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); |
@@ -1331,41 +1415,36 @@ 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)); |
+ reinterpret_cast<long*>(output), |
+ base::LOCALE_DEPENDENT); |
} |
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)); |
+ reinterpret_cast<long*>(output), |
+ base::LOCALE_DEPENDENT); |
} |
bool StringToInt64(const std::string& input, int64* output) { |
- return StringToNumber<StringToInt64Traits>(input, output); |
+ return StringToNumber<StringToInt64Traits>(input, output, base::LOCALE_DEPENDENT); |
} |
bool StringToInt64(const std::wstring& input, int64* output) { |
- return StringToNumber<WStringToInt64Traits>(input, output); |
+ return StringToNumber<WStringToInt64Traits>(input, output, base::LOCALE_DEPENDENT); |
} |
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)); |
+ reinterpret_cast<long*>(output), |
+ base::LOCALE_DEPENDENT); |
} |
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)); |
-} |
- |
-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); |
+ input, reinterpret_cast<long*>(output), base::LOCALE_DEPENDENT); |
} |
int StringToInt(const std::string& value) { |
@@ -1404,18 +1483,6 @@ int HexStringToInt(const std::wstring& value) { |
return result; |
} |
-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 |