diff options
author | deanm@chromium.org <deanm@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-07-28 17:34:43 +0000 |
---|---|---|
committer | deanm@chromium.org <deanm@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-07-28 17:34:43 +0000 |
commit | 641cbaa5f6e2799044622e415c39722c05e37938 (patch) | |
tree | 0cb2617b418a525b69a0e3121712431d57e1e847 /base/string_util.cc | |
parent | 419247b22a41448a297f65cd697d7ef15f873e33 (diff) | |
download | chromium_src-641cbaa5f6e2799044622e415c39722c05e37938.zip chromium_src-641cbaa5f6e2799044622e415c39722c05e37938.tar.gz chromium_src-641cbaa5f6e2799044622e415c39722c05e37938.tar.bz2 |
Rewrite StringToInt traits for dealing with non-32-bit longs.
Review URL: http://codereview.chromium.org/159510
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@21855 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'base/string_util.cc')
-rw-r--r-- | base/string_util.cc | 74 |
1 files changed, 45 insertions, 29 deletions
diff --git a/base/string_util.cc b/base/string_util.cc index 2f20d78..b456376 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 { |