Index: base/string_util.cc |
diff --git a/base/string_util.cc b/base/string_util.cc |
index 2f20d780e9b3fa48a958e0b7a70eaef8a1283f85..b456376ee4460d10de3ecfb45fbdbb112a504fa5 100644 |
--- a/base/string_util.cc |
+++ b/base/string_util.cc |
@@ -94,24 +94,53 @@ bool StringToNumber(const typename StringToNumberTraits::string_type& input, |
traits::valid_func(input); |
} |
-class StringToLongTraits { |
+static int strtoi(const char *nptr, char **endptr, int base) { |
+ long res = strtol(nptr, endptr, base); |
+#if __LP64__ |
+ // Long is 64-bits, we have to handle under/overflow ourselves. |
+ if (res > kint32max) { |
+ res = kint32max; |
+ errno = ERANGE; |
+ } else if (res < kint32min) { |
+ res = kint32min; |
+ errno = ERANGE; |
+ } |
+#endif |
+ return static_cast<int>(res); |
+} |
+ |
+static unsigned int strtoui(const char *nptr, char **endptr, int base) { |
+ unsigned long res = strtoul(nptr, endptr, base); |
+#if __LP64__ |
+ // Long is 64-bits, we have to handle under/overflow ourselves. Test to see |
+ // if the result can fit into 32-bits (as signed or unsigned). |
+ if (static_cast<int>(static_cast<long>(res)) != static_cast<long>(res) && |
+ static_cast<unsigned int>(res) != res) { |
+ res = kuint32max; |
+ errno = ERANGE; |
+ } |
+#endif |
+ return static_cast<unsigned int>(res); |
+} |
+ |
+class StringToIntTraits { |
public: |
typedef std::string string_type; |
- typedef long value_type; |
+ typedef int value_type; |
static const int kBase = 10; |
static inline value_type convert_func(const string_type::value_type* str, |
string_type::value_type** endptr) { |
- return strtol(str, endptr, kBase); |
+ return strtoi(str, endptr, kBase); |
} |
static inline bool valid_func(const string_type& str) { |
return !str.empty() && !isspace(str[0]); |
} |
}; |
-class String16ToLongTraits { |
+class String16ToIntTraits { |
public: |
typedef string16 string_type; |
- typedef long value_type; |
+ typedef int value_type; |
static const int kBase = 10; |
static inline value_type convert_func(const string_type::value_type* str, |
string_type::value_type** endptr) { |
@@ -120,7 +149,7 @@ class String16ToLongTraits { |
#elif defined(WCHAR_T_IS_UTF32) |
std::string ascii_string = UTF16ToASCII(string16(str)); |
char* ascii_end = NULL; |
- value_type ret = strtol(ascii_string.c_str(), &ascii_end, kBase); |
+ value_type ret = strtoi(ascii_string.c_str(), &ascii_end, kBase); |
if (ascii_string.c_str() + ascii_string.length() == ascii_end) { |
*endptr = |
const_cast<string_type::value_type*>(str) + ascii_string.length(); |
@@ -179,24 +208,24 @@ class String16ToInt64Traits { |
// For the HexString variants, use the unsigned variants like strtoul for |
// convert_func so that input like "0x80000000" doesn't result in an overflow. |
-class HexStringToLongTraits { |
+class HexStringToIntTraits { |
public: |
typedef std::string string_type; |
- typedef long value_type; |
+ typedef int value_type; |
static const int kBase = 16; |
static inline value_type convert_func(const string_type::value_type* str, |
string_type::value_type** endptr) { |
- return strtoul(str, endptr, kBase); |
+ return strtoui(str, endptr, kBase); |
} |
static inline bool valid_func(const string_type& str) { |
return !str.empty() && !isspace(str[0]); |
} |
}; |
-class HexString16ToLongTraits { |
+class HexString16ToIntTraits { |
public: |
typedef string16 string_type; |
- typedef long value_type; |
+ typedef int value_type; |
static const int kBase = 16; |
static inline value_type convert_func(const string_type::value_type* str, |
string_type::value_type** endptr) { |
@@ -205,7 +234,7 @@ class HexString16ToLongTraits { |
#elif defined(WCHAR_T_IS_UTF32) |
std::string ascii_string = UTF16ToASCII(string16(str)); |
char* ascii_end = NULL; |
- value_type ret = strtoul(ascii_string.c_str(), &ascii_end, kBase); |
+ value_type ret = strtoui(ascii_string.c_str(), &ascii_end, kBase); |
if (ascii_string.c_str() + ascii_string.length() == ascii_end) { |
*endptr = |
const_cast<string_type::value_type*>(str) + ascii_string.length(); |
@@ -1440,21 +1469,12 @@ bool MatchPattern(const std::string& eval, const std::string& pattern) { |
return MatchPatternT(eval.c_str(), pattern.c_str()); |
} |
-// For the various *ToInt conversions, there are no *ToIntTraits classes to use |
-// because there's no such thing as strtoi. Use *ToLongTraits through a cast |
-// instead, requiring that long and int are compatible and equal-width. They |
-// are on our target platforms. |
- |
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)); |
+ return StringToNumber<StringToIntTraits>(input, output); |
} |
bool StringToInt(const string16& input, int* output) { |
- COMPILE_ASSERT(sizeof(int) == sizeof(long), cannot_wcstol_to_int); |
- return StringToNumber<String16ToLongTraits>(input, |
- reinterpret_cast<long*>(output)); |
+ return StringToNumber<String16ToIntTraits>(input, output); |
} |
bool StringToInt64(const std::string& input, int64* output) { |
@@ -1466,15 +1486,11 @@ bool StringToInt64(const string16& input, int64* 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)); |
+ return StringToNumber<HexStringToIntTraits>(input, output); |
} |
bool HexStringToInt(const string16& input, int* output) { |
- COMPILE_ASSERT(sizeof(int) == sizeof(long), cannot_wcstol_to_int); |
- return StringToNumber<HexString16ToLongTraits>( |
- input, reinterpret_cast<long*>(output)); |
+ return StringToNumber<HexString16ToIntTraits>(input, output); |
} |
namespace { |