Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(201)

Side by Side Diff: base/string_util.cc

Issue 159510: Rewrite StringToInt traits for dealing with non-32-bit longs. (Closed)
Patch Set: Created 11 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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
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 }
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698