| OLD | NEW |
| 1 // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "base/string_util.h" | 5 #include "base/string_util.h" |
| 6 | 6 |
| 7 #include "build/build_config.h" | 7 #include "build/build_config.h" |
| 8 | 8 |
| 9 #include <ctype.h> | 9 #include <ctype.h> |
| 10 #include <errno.h> | 10 #include <errno.h> |
| (...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 87 // does not begin with a parseable number. endptr is compared to the | 87 // does not begin with a parseable number. endptr is compared to the |
| 88 // expected end given the string's stated length to correctly catch cases | 88 // expected end given the string's stated length to correctly catch cases |
| 89 // where the string contains embedded NUL characters. | 89 // where the string contains embedded NUL characters. |
| 90 // - valid_func determines that the input is not in preferred form. | 90 // - valid_func determines that the input is not in preferred form. |
| 91 return errno == 0 && | 91 return errno == 0 && |
| 92 !input.empty() && | 92 !input.empty() && |
| 93 input.c_str() + input.length() == endptr && | 93 input.c_str() + input.length() == endptr && |
| 94 traits::valid_func(input); | 94 traits::valid_func(input); |
| 95 } | 95 } |
| 96 | 96 |
| 97 class StringToLongTraits { | 97 static int strtoi(const char *nptr, char **endptr, int base) { |
| 98 long res = strtol(nptr, endptr, base); |
| 99 #if __LP64__ |
| 100 // Long is 64-bits, we have to handle under/overflow ourselves. |
| 101 if (res > kint32max) { |
| 102 res = kint32max; |
| 103 errno = ERANGE; |
| 104 } else if (res < kint32min) { |
| 105 res = kint32min; |
| 106 errno = ERANGE; |
| 107 } |
| 108 #endif |
| 109 return static_cast<int>(res); |
| 110 } |
| 111 |
| 112 static unsigned int strtoui(const char *nptr, char **endptr, int base) { |
| 113 unsigned long res = strtoul(nptr, endptr, base); |
| 114 #if __LP64__ |
| 115 // Long is 64-bits, we have to handle under/overflow ourselves. Test to see |
| 116 // if the result can fit into 32-bits (as signed or unsigned). |
| 117 if (static_cast<int>(static_cast<long>(res)) != static_cast<long>(res) && |
| 118 static_cast<unsigned int>(res) != res) { |
| 119 res = kuint32max; |
| 120 errno = ERANGE; |
| 121 } |
| 122 #endif |
| 123 return static_cast<unsigned int>(res); |
| 124 } |
| 125 |
| 126 class StringToIntTraits { |
| 98 public: | 127 public: |
| 99 typedef std::string string_type; | 128 typedef std::string string_type; |
| 100 typedef long value_type; | 129 typedef int value_type; |
| 101 static const int kBase = 10; | 130 static const int kBase = 10; |
| 102 static inline value_type convert_func(const string_type::value_type* str, | 131 static inline value_type convert_func(const string_type::value_type* str, |
| 103 string_type::value_type** endptr) { | 132 string_type::value_type** endptr) { |
| 104 return strtol(str, endptr, kBase); | 133 return strtoi(str, endptr, kBase); |
| 105 } | 134 } |
| 106 static inline bool valid_func(const string_type& str) { | 135 static inline bool valid_func(const string_type& str) { |
| 107 return !str.empty() && !isspace(str[0]); | 136 return !str.empty() && !isspace(str[0]); |
| 108 } | 137 } |
| 109 }; | 138 }; |
| 110 | 139 |
| 111 class String16ToLongTraits { | 140 class String16ToIntTraits { |
| 112 public: | 141 public: |
| 113 typedef string16 string_type; | 142 typedef string16 string_type; |
| 114 typedef long value_type; | 143 typedef int value_type; |
| 115 static const int kBase = 10; | 144 static const int kBase = 10; |
| 116 static inline value_type convert_func(const string_type::value_type* str, | 145 static inline value_type convert_func(const string_type::value_type* str, |
| 117 string_type::value_type** endptr) { | 146 string_type::value_type** endptr) { |
| 118 #if defined(WCHAR_T_IS_UTF16) | 147 #if defined(WCHAR_T_IS_UTF16) |
| 119 return wcstol(str, endptr, kBase); | 148 return wcstol(str, endptr, kBase); |
| 120 #elif defined(WCHAR_T_IS_UTF32) | 149 #elif defined(WCHAR_T_IS_UTF32) |
| 121 std::string ascii_string = UTF16ToASCII(string16(str)); | 150 std::string ascii_string = UTF16ToASCII(string16(str)); |
| 122 char* ascii_end = NULL; | 151 char* ascii_end = NULL; |
| 123 value_type ret = strtol(ascii_string.c_str(), &ascii_end, kBase); | 152 value_type ret = strtoi(ascii_string.c_str(), &ascii_end, kBase); |
| 124 if (ascii_string.c_str() + ascii_string.length() == ascii_end) { | 153 if (ascii_string.c_str() + ascii_string.length() == ascii_end) { |
| 125 *endptr = | 154 *endptr = |
| 126 const_cast<string_type::value_type*>(str) + ascii_string.length(); | 155 const_cast<string_type::value_type*>(str) + ascii_string.length(); |
| 127 } | 156 } |
| 128 return ret; | 157 return ret; |
| 129 #endif | 158 #endif |
| 130 } | 159 } |
| 131 static inline bool valid_func(const string_type& str) { | 160 static inline bool valid_func(const string_type& str) { |
| 132 return !str.empty() && !iswspace(str[0]); | 161 return !str.empty() && !iswspace(str[0]); |
| 133 } | 162 } |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 172 #endif | 201 #endif |
| 173 } | 202 } |
| 174 static inline bool valid_func(const string_type& str) { | 203 static inline bool valid_func(const string_type& str) { |
| 175 return !str.empty() && !iswspace(str[0]); | 204 return !str.empty() && !iswspace(str[0]); |
| 176 } | 205 } |
| 177 }; | 206 }; |
| 178 | 207 |
| 179 // For the HexString variants, use the unsigned variants like strtoul for | 208 // For the HexString variants, use the unsigned variants like strtoul for |
| 180 // convert_func so that input like "0x80000000" doesn't result in an overflow. | 209 // convert_func so that input like "0x80000000" doesn't result in an overflow. |
| 181 | 210 |
| 182 class HexStringToLongTraits { | 211 class HexStringToIntTraits { |
| 183 public: | 212 public: |
| 184 typedef std::string string_type; | 213 typedef std::string string_type; |
| 185 typedef long value_type; | 214 typedef int value_type; |
| 186 static const int kBase = 16; | 215 static const int kBase = 16; |
| 187 static inline value_type convert_func(const string_type::value_type* str, | 216 static inline value_type convert_func(const string_type::value_type* str, |
| 188 string_type::value_type** endptr) { | 217 string_type::value_type** endptr) { |
| 189 return strtoul(str, endptr, kBase); | 218 return strtoui(str, endptr, kBase); |
| 190 } | 219 } |
| 191 static inline bool valid_func(const string_type& str) { | 220 static inline bool valid_func(const string_type& str) { |
| 192 return !str.empty() && !isspace(str[0]); | 221 return !str.empty() && !isspace(str[0]); |
| 193 } | 222 } |
| 194 }; | 223 }; |
| 195 | 224 |
| 196 class HexString16ToLongTraits { | 225 class HexString16ToIntTraits { |
| 197 public: | 226 public: |
| 198 typedef string16 string_type; | 227 typedef string16 string_type; |
| 199 typedef long value_type; | 228 typedef int value_type; |
| 200 static const int kBase = 16; | 229 static const int kBase = 16; |
| 201 static inline value_type convert_func(const string_type::value_type* str, | 230 static inline value_type convert_func(const string_type::value_type* str, |
| 202 string_type::value_type** endptr) { | 231 string_type::value_type** endptr) { |
| 203 #if defined(WCHAR_T_IS_UTF16) | 232 #if defined(WCHAR_T_IS_UTF16) |
| 204 return wcstoul(str, endptr, kBase); | 233 return wcstoul(str, endptr, kBase); |
| 205 #elif defined(WCHAR_T_IS_UTF32) | 234 #elif defined(WCHAR_T_IS_UTF32) |
| 206 std::string ascii_string = UTF16ToASCII(string16(str)); | 235 std::string ascii_string = UTF16ToASCII(string16(str)); |
| 207 char* ascii_end = NULL; | 236 char* ascii_end = NULL; |
| 208 value_type ret = strtoul(ascii_string.c_str(), &ascii_end, kBase); | 237 value_type ret = strtoui(ascii_string.c_str(), &ascii_end, kBase); |
| 209 if (ascii_string.c_str() + ascii_string.length() == ascii_end) { | 238 if (ascii_string.c_str() + ascii_string.length() == ascii_end) { |
| 210 *endptr = | 239 *endptr = |
| 211 const_cast<string_type::value_type*>(str) + ascii_string.length(); | 240 const_cast<string_type::value_type*>(str) + ascii_string.length(); |
| 212 } | 241 } |
| 213 return ret; | 242 return ret; |
| 214 #endif | 243 #endif |
| 215 } | 244 } |
| 216 static inline bool valid_func(const string_type& str) { | 245 static inline bool valid_func(const string_type& str) { |
| 217 return !str.empty() && !iswspace(str[0]); | 246 return !str.empty() && !iswspace(str[0]); |
| 218 } | 247 } |
| (...skipping 1214 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1433 } | 1462 } |
| 1434 | 1463 |
| 1435 bool MatchPattern(const std::wstring& eval, const std::wstring& pattern) { | 1464 bool MatchPattern(const std::wstring& eval, const std::wstring& pattern) { |
| 1436 return MatchPatternT(eval.c_str(), pattern.c_str()); | 1465 return MatchPatternT(eval.c_str(), pattern.c_str()); |
| 1437 } | 1466 } |
| 1438 | 1467 |
| 1439 bool MatchPattern(const std::string& eval, const std::string& pattern) { | 1468 bool MatchPattern(const std::string& eval, const std::string& pattern) { |
| 1440 return MatchPatternT(eval.c_str(), pattern.c_str()); | 1469 return MatchPatternT(eval.c_str(), pattern.c_str()); |
| 1441 } | 1470 } |
| 1442 | 1471 |
| 1443 // For the various *ToInt conversions, there are no *ToIntTraits classes to use | |
| 1444 // because there's no such thing as strtoi. Use *ToLongTraits through a cast | |
| 1445 // instead, requiring that long and int are compatible and equal-width. They | |
| 1446 // are on our target platforms. | |
| 1447 | |
| 1448 bool StringToInt(const std::string& input, int* output) { | 1472 bool StringToInt(const std::string& input, int* output) { |
| 1449 COMPILE_ASSERT(sizeof(int) == sizeof(long), cannot_strtol_to_int); | 1473 return StringToNumber<StringToIntTraits>(input, output); |
| 1450 return StringToNumber<StringToLongTraits>(input, | |
| 1451 reinterpret_cast<long*>(output)); | |
| 1452 } | 1474 } |
| 1453 | 1475 |
| 1454 bool StringToInt(const string16& input, int* output) { | 1476 bool StringToInt(const string16& input, int* output) { |
| 1455 COMPILE_ASSERT(sizeof(int) == sizeof(long), cannot_wcstol_to_int); | 1477 return StringToNumber<String16ToIntTraits>(input, output); |
| 1456 return StringToNumber<String16ToLongTraits>(input, | |
| 1457 reinterpret_cast<long*>(output)); | |
| 1458 } | 1478 } |
| 1459 | 1479 |
| 1460 bool StringToInt64(const std::string& input, int64* output) { | 1480 bool StringToInt64(const std::string& input, int64* output) { |
| 1461 return StringToNumber<StringToInt64Traits>(input, output); | 1481 return StringToNumber<StringToInt64Traits>(input, output); |
| 1462 } | 1482 } |
| 1463 | 1483 |
| 1464 bool StringToInt64(const string16& input, int64* output) { | 1484 bool StringToInt64(const string16& input, int64* output) { |
| 1465 return StringToNumber<String16ToInt64Traits>(input, output); | 1485 return StringToNumber<String16ToInt64Traits>(input, output); |
| 1466 } | 1486 } |
| 1467 | 1487 |
| 1468 bool HexStringToInt(const std::string& input, int* output) { | 1488 bool HexStringToInt(const std::string& input, int* output) { |
| 1469 COMPILE_ASSERT(sizeof(int) == sizeof(long), cannot_strtol_to_int); | 1489 return StringToNumber<HexStringToIntTraits>(input, output); |
| 1470 return StringToNumber<HexStringToLongTraits>(input, | |
| 1471 reinterpret_cast<long*>(output)); | |
| 1472 } | 1490 } |
| 1473 | 1491 |
| 1474 bool HexStringToInt(const string16& input, int* output) { | 1492 bool HexStringToInt(const string16& input, int* output) { |
| 1475 COMPILE_ASSERT(sizeof(int) == sizeof(long), cannot_wcstol_to_int); | 1493 return StringToNumber<HexString16ToIntTraits>(input, output); |
| 1476 return StringToNumber<HexString16ToLongTraits>( | |
| 1477 input, reinterpret_cast<long*>(output)); | |
| 1478 } | 1494 } |
| 1479 | 1495 |
| 1480 namespace { | 1496 namespace { |
| 1481 | 1497 |
| 1482 template<class CHAR> | 1498 template<class CHAR> |
| 1483 bool HexDigitToIntT(const CHAR digit, uint8* val) { | 1499 bool HexDigitToIntT(const CHAR digit, uint8* val) { |
| 1484 if (digit >= '0' && digit <= '9') | 1500 if (digit >= '0' && digit <= '9') |
| 1485 *val = digit - '0'; | 1501 *val = digit - '0'; |
| 1486 else if (digit >= 'a' && digit <= 'f') | 1502 else if (digit >= 'a' && digit <= 'f') |
| 1487 *val = 10 + digit - 'a'; | 1503 *val = 10 + digit - 'a'; |
| (...skipping 161 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1649 // Each input byte creates two output hex characters. | 1665 // Each input byte creates two output hex characters. |
| 1650 std::string ret(size * 2, '\0'); | 1666 std::string ret(size * 2, '\0'); |
| 1651 | 1667 |
| 1652 for (size_t i = 0; i < size; ++i) { | 1668 for (size_t i = 0; i < size; ++i) { |
| 1653 char b = reinterpret_cast<const char*>(bytes)[i]; | 1669 char b = reinterpret_cast<const char*>(bytes)[i]; |
| 1654 ret[(i * 2)] = kHexChars[(b >> 4) & 0xf]; | 1670 ret[(i * 2)] = kHexChars[(b >> 4) & 0xf]; |
| 1655 ret[(i * 2) + 1] = kHexChars[b & 0xf]; | 1671 ret[(i * 2) + 1] = kHexChars[b & 0xf]; |
| 1656 } | 1672 } |
| 1657 return ret; | 1673 return ret; |
| 1658 } | 1674 } |
| OLD | NEW |