OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 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/strings/string_number_conversions.h" | 5 #include "base/strings/string_number_conversions.h" |
6 | 6 |
7 #include <ctype.h> | 7 #include <ctype.h> |
8 #include <errno.h> | 8 #include <errno.h> |
9 #include <stdlib.h> | 9 #include <stdlib.h> |
10 #include <wctype.h> | 10 #include <wctype.h> |
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
56 } | 56 } |
57 }; | 57 }; |
58 | 58 |
59 // Utility to convert a character to a digit in a given base | 59 // Utility to convert a character to a digit in a given base |
60 template<typename CHAR, int BASE, bool BASE_LTE_10> class BaseCharToDigit { | 60 template<typename CHAR, int BASE, bool BASE_LTE_10> class BaseCharToDigit { |
61 }; | 61 }; |
62 | 62 |
63 // Faster specialization for bases <= 10 | 63 // Faster specialization for bases <= 10 |
64 template<typename CHAR, int BASE> class BaseCharToDigit<CHAR, BASE, true> { | 64 template<typename CHAR, int BASE> class BaseCharToDigit<CHAR, BASE, true> { |
65 public: | 65 public: |
66 static bool Convert(CHAR c, uint8* digit) { | 66 static bool Convert(CHAR c, uint8_t* digit) { |
67 if (c >= '0' && c < '0' + BASE) { | 67 if (c >= '0' && c < '0' + BASE) { |
68 *digit = static_cast<uint8>(c - '0'); | 68 *digit = static_cast<uint8_t>(c - '0'); |
69 return true; | 69 return true; |
70 } | 70 } |
71 return false; | 71 return false; |
72 } | 72 } |
73 }; | 73 }; |
74 | 74 |
75 // Specialization for bases where 10 < base <= 36 | 75 // Specialization for bases where 10 < base <= 36 |
76 template<typename CHAR, int BASE> class BaseCharToDigit<CHAR, BASE, false> { | 76 template<typename CHAR, int BASE> class BaseCharToDigit<CHAR, BASE, false> { |
77 public: | 77 public: |
78 static bool Convert(CHAR c, uint8* digit) { | 78 static bool Convert(CHAR c, uint8_t* digit) { |
79 if (c >= '0' && c <= '9') { | 79 if (c >= '0' && c <= '9') { |
80 *digit = c - '0'; | 80 *digit = c - '0'; |
81 } else if (c >= 'a' && c < 'a' + BASE - 10) { | 81 } else if (c >= 'a' && c < 'a' + BASE - 10) { |
82 *digit = c - 'a' + 10; | 82 *digit = c - 'a' + 10; |
83 } else if (c >= 'A' && c < 'A' + BASE - 10) { | 83 } else if (c >= 'A' && c < 'A' + BASE - 10) { |
84 *digit = c - 'A' + 10; | 84 *digit = c - 'A' + 10; |
85 } else { | 85 } else { |
86 return false; | 86 return false; |
87 } | 87 } |
88 return true; | 88 return true; |
89 } | 89 } |
90 }; | 90 }; |
91 | 91 |
92 template<int BASE, typename CHAR> bool CharToDigit(CHAR c, uint8* digit) { | 92 template <int BASE, typename CHAR> |
| 93 bool CharToDigit(CHAR c, uint8_t* digit) { |
93 return BaseCharToDigit<CHAR, BASE, BASE <= 10>::Convert(c, digit); | 94 return BaseCharToDigit<CHAR, BASE, BASE <= 10>::Convert(c, digit); |
94 } | 95 } |
95 | 96 |
96 // There is an IsUnicodeWhitespace for wchars defined in string_util.h, but it | 97 // There is an IsUnicodeWhitespace for wchars defined in string_util.h, but it |
97 // is locale independent, whereas the functions we are replacing were | 98 // is locale independent, whereas the functions we are replacing were |
98 // locale-dependent. TBD what is desired, but for the moment let's not | 99 // locale-dependent. TBD what is desired, but for the moment let's not |
99 // introduce a change in behaviour. | 100 // introduce a change in behaviour. |
100 template<typename CHAR> class WhitespaceHelper { | 101 template<typename CHAR> class WhitespaceHelper { |
101 }; | 102 }; |
102 | 103 |
(...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
179 } | 180 } |
180 | 181 |
181 // Note: no performance difference was found when using template | 182 // Note: no performance difference was found when using template |
182 // specialization to remove this check in bases other than 16 | 183 // specialization to remove this check in bases other than 16 |
183 if (traits::kBase == 16 && end - begin > 2 && *begin == '0' && | 184 if (traits::kBase == 16 && end - begin > 2 && *begin == '0' && |
184 (*(begin + 1) == 'x' || *(begin + 1) == 'X')) { | 185 (*(begin + 1) == 'x' || *(begin + 1) == 'X')) { |
185 begin += 2; | 186 begin += 2; |
186 } | 187 } |
187 | 188 |
188 for (const_iterator current = begin; current != end; ++current) { | 189 for (const_iterator current = begin; current != end; ++current) { |
189 uint8 new_digit = 0; | 190 uint8_t new_digit = 0; |
190 | 191 |
191 if (!CharToDigit<traits::kBase>(*current, &new_digit)) { | 192 if (!CharToDigit<traits::kBase>(*current, &new_digit)) { |
192 return false; | 193 return false; |
193 } | 194 } |
194 | 195 |
195 if (current != begin) { | 196 if (current != begin) { |
196 if (!Sign::CheckBounds(output, new_digit)) { | 197 if (!Sign::CheckBounds(output, new_digit)) { |
197 return false; | 198 return false; |
198 } | 199 } |
199 *output *= traits::kBase; | 200 *output *= traits::kBase; |
200 } | 201 } |
201 | 202 |
202 Sign::Increment(new_digit, output); | 203 Sign::Increment(new_digit, output); |
203 } | 204 } |
204 return true; | 205 return true; |
205 } | 206 } |
206 }; | 207 }; |
207 | 208 |
208 class Positive : public Base<Positive> { | 209 class Positive : public Base<Positive> { |
209 public: | 210 public: |
210 static bool CheckBounds(value_type* output, uint8 new_digit) { | 211 static bool CheckBounds(value_type* output, uint8_t new_digit) { |
211 if (*output > static_cast<value_type>(traits::max() / traits::kBase) || | 212 if (*output > static_cast<value_type>(traits::max() / traits::kBase) || |
212 (*output == static_cast<value_type>(traits::max() / traits::kBase) && | 213 (*output == static_cast<value_type>(traits::max() / traits::kBase) && |
213 new_digit > traits::max() % traits::kBase)) { | 214 new_digit > traits::max() % traits::kBase)) { |
214 *output = traits::max(); | 215 *output = traits::max(); |
215 return false; | 216 return false; |
216 } | 217 } |
217 return true; | 218 return true; |
218 } | 219 } |
219 static void Increment(uint8 increment, value_type* output) { | 220 static void Increment(uint8_t increment, value_type* output) { |
220 *output += increment; | 221 *output += increment; |
221 } | 222 } |
222 }; | 223 }; |
223 | 224 |
224 class Negative : public Base<Negative> { | 225 class Negative : public Base<Negative> { |
225 public: | 226 public: |
226 static bool CheckBounds(value_type* output, uint8 new_digit) { | 227 static bool CheckBounds(value_type* output, uint8_t new_digit) { |
227 if (*output < traits::min() / traits::kBase || | 228 if (*output < traits::min() / traits::kBase || |
228 (*output == traits::min() / traits::kBase && | 229 (*output == traits::min() / traits::kBase && |
229 new_digit > 0 - traits::min() % traits::kBase)) { | 230 new_digit > 0 - traits::min() % traits::kBase)) { |
230 *output = traits::min(); | 231 *output = traits::min(); |
231 return false; | 232 return false; |
232 } | 233 } |
233 return true; | 234 return true; |
234 } | 235 } |
235 static void Increment(uint8 increment, value_type* output) { | 236 static void Increment(uint8_t increment, value_type* output) { |
236 *output -= increment; | 237 *output -= increment; |
237 } | 238 } |
238 }; | 239 }; |
239 }; | 240 }; |
240 | 241 |
241 template<typename ITERATOR, typename VALUE, int BASE> | 242 template<typename ITERATOR, typename VALUE, int BASE> |
242 class BaseIteratorRangeToNumberTraits { | 243 class BaseIteratorRangeToNumberTraits { |
243 public: | 244 public: |
244 typedef ITERATOR iterator_type; | 245 typedef ITERATOR iterator_type; |
245 typedef VALUE value_type; | 246 typedef VALUE value_type; |
246 static value_type min() { | 247 static value_type min() { |
247 return std::numeric_limits<value_type>::min(); | 248 return std::numeric_limits<value_type>::min(); |
248 } | 249 } |
249 static value_type max() { | 250 static value_type max() { |
250 return std::numeric_limits<value_type>::max(); | 251 return std::numeric_limits<value_type>::max(); |
251 } | 252 } |
252 static const int kBase = BASE; | 253 static const int kBase = BASE; |
253 }; | 254 }; |
254 | 255 |
255 template<typename ITERATOR> | 256 template<typename ITERATOR> |
256 class BaseHexIteratorRangeToIntTraits | 257 class BaseHexIteratorRangeToIntTraits |
257 : public BaseIteratorRangeToNumberTraits<ITERATOR, int, 16> { | 258 : public BaseIteratorRangeToNumberTraits<ITERATOR, int, 16> { |
258 }; | 259 }; |
259 | 260 |
260 template<typename ITERATOR> | 261 template <typename ITERATOR> |
261 class BaseHexIteratorRangeToUIntTraits | 262 class BaseHexIteratorRangeToUIntTraits |
262 : public BaseIteratorRangeToNumberTraits<ITERATOR, uint32, 16> { | 263 : public BaseIteratorRangeToNumberTraits<ITERATOR, uint32_t, 16> {}; |
263 }; | |
264 | 264 |
265 template<typename ITERATOR> | 265 template <typename ITERATOR> |
266 class BaseHexIteratorRangeToInt64Traits | 266 class BaseHexIteratorRangeToInt64Traits |
267 : public BaseIteratorRangeToNumberTraits<ITERATOR, int64, 16> { | 267 : public BaseIteratorRangeToNumberTraits<ITERATOR, int64_t, 16> {}; |
268 }; | |
269 | 268 |
270 template<typename ITERATOR> | 269 template <typename ITERATOR> |
271 class BaseHexIteratorRangeToUInt64Traits | 270 class BaseHexIteratorRangeToUInt64Traits |
272 : public BaseIteratorRangeToNumberTraits<ITERATOR, uint64, 16> { | 271 : public BaseIteratorRangeToNumberTraits<ITERATOR, uint64_t, 16> {}; |
273 }; | |
274 | 272 |
275 typedef BaseHexIteratorRangeToIntTraits<StringPiece::const_iterator> | 273 typedef BaseHexIteratorRangeToIntTraits<StringPiece::const_iterator> |
276 HexIteratorRangeToIntTraits; | 274 HexIteratorRangeToIntTraits; |
277 | 275 |
278 typedef BaseHexIteratorRangeToUIntTraits<StringPiece::const_iterator> | 276 typedef BaseHexIteratorRangeToUIntTraits<StringPiece::const_iterator> |
279 HexIteratorRangeToUIntTraits; | 277 HexIteratorRangeToUIntTraits; |
280 | 278 |
281 typedef BaseHexIteratorRangeToInt64Traits<StringPiece::const_iterator> | 279 typedef BaseHexIteratorRangeToInt64Traits<StringPiece::const_iterator> |
282 HexIteratorRangeToInt64Traits; | 280 HexIteratorRangeToInt64Traits; |
283 | 281 |
284 typedef BaseHexIteratorRangeToUInt64Traits<StringPiece::const_iterator> | 282 typedef BaseHexIteratorRangeToUInt64Traits<StringPiece::const_iterator> |
285 HexIteratorRangeToUInt64Traits; | 283 HexIteratorRangeToUInt64Traits; |
286 | 284 |
287 template<typename STR> | 285 template <typename STR> |
288 bool HexStringToBytesT(const STR& input, std::vector<uint8>* output) { | 286 bool HexStringToBytesT(const STR& input, std::vector<uint8_t>* output) { |
289 DCHECK_EQ(output->size(), 0u); | 287 DCHECK_EQ(output->size(), 0u); |
290 size_t count = input.size(); | 288 size_t count = input.size(); |
291 if (count == 0 || (count % 2) != 0) | 289 if (count == 0 || (count % 2) != 0) |
292 return false; | 290 return false; |
293 for (uintptr_t i = 0; i < count / 2; ++i) { | 291 for (uintptr_t i = 0; i < count / 2; ++i) { |
294 uint8 msb = 0; // most significant 4 bits | 292 uint8_t msb = 0; // most significant 4 bits |
295 uint8 lsb = 0; // least significant 4 bits | 293 uint8_t lsb = 0; // least significant 4 bits |
296 if (!CharToDigit<16>(input[i * 2], &msb) || | 294 if (!CharToDigit<16>(input[i * 2], &msb) || |
297 !CharToDigit<16>(input[i * 2 + 1], &lsb)) | 295 !CharToDigit<16>(input[i * 2 + 1], &lsb)) |
298 return false; | 296 return false; |
299 output->push_back((msb << 4) | lsb); | 297 output->push_back((msb << 4) | lsb); |
300 } | 298 } |
301 return true; | 299 return true; |
302 } | 300 } |
303 | 301 |
304 template <typename VALUE, int BASE> | 302 template <typename VALUE, int BASE> |
305 class StringPieceToNumberTraits | 303 class StringPieceToNumberTraits |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
338 } | 336 } |
339 | 337 |
340 std::string UintToString(unsigned int value) { | 338 std::string UintToString(unsigned int value) { |
341 return IntToStringT<std::string, unsigned int>::IntToString(value); | 339 return IntToStringT<std::string, unsigned int>::IntToString(value); |
342 } | 340 } |
343 | 341 |
344 string16 UintToString16(unsigned int value) { | 342 string16 UintToString16(unsigned int value) { |
345 return IntToStringT<string16, unsigned int>::IntToString(value); | 343 return IntToStringT<string16, unsigned int>::IntToString(value); |
346 } | 344 } |
347 | 345 |
348 std::string Int64ToString(int64 value) { | 346 std::string Int64ToString(int64_t value) { |
349 return IntToStringT<std::string, int64>::IntToString(value); | 347 return IntToStringT<std::string, int64_t>::IntToString(value); |
350 } | 348 } |
351 | 349 |
352 string16 Int64ToString16(int64 value) { | 350 string16 Int64ToString16(int64_t value) { |
353 return IntToStringT<string16, int64>::IntToString(value); | 351 return IntToStringT<string16, int64_t>::IntToString(value); |
354 } | 352 } |
355 | 353 |
356 std::string Uint64ToString(uint64 value) { | 354 std::string Uint64ToString(uint64_t value) { |
357 return IntToStringT<std::string, uint64>::IntToString(value); | 355 return IntToStringT<std::string, uint64_t>::IntToString(value); |
358 } | 356 } |
359 | 357 |
360 string16 Uint64ToString16(uint64 value) { | 358 string16 Uint64ToString16(uint64_t value) { |
361 return IntToStringT<string16, uint64>::IntToString(value); | 359 return IntToStringT<string16, uint64_t>::IntToString(value); |
362 } | 360 } |
363 | 361 |
364 std::string SizeTToString(size_t value) { | 362 std::string SizeTToString(size_t value) { |
365 return IntToStringT<std::string, size_t>::IntToString(value); | 363 return IntToStringT<std::string, size_t>::IntToString(value); |
366 } | 364 } |
367 | 365 |
368 string16 SizeTToString16(size_t value) { | 366 string16 SizeTToString16(size_t value) { |
369 return IntToStringT<string16, size_t>::IntToString(value); | 367 return IntToStringT<string16, size_t>::IntToString(value); |
370 } | 368 } |
371 | 369 |
(...skipping 13 matching lines...) Expand all Loading... |
385 } | 383 } |
386 | 384 |
387 bool StringToUint(const StringPiece& input, unsigned* output) { | 385 bool StringToUint(const StringPiece& input, unsigned* output) { |
388 return StringToIntImpl(input, output); | 386 return StringToIntImpl(input, output); |
389 } | 387 } |
390 | 388 |
391 bool StringToUint(const StringPiece16& input, unsigned* output) { | 389 bool StringToUint(const StringPiece16& input, unsigned* output) { |
392 return String16ToIntImpl(input, output); | 390 return String16ToIntImpl(input, output); |
393 } | 391 } |
394 | 392 |
395 bool StringToInt64(const StringPiece& input, int64* output) { | 393 bool StringToInt64(const StringPiece& input, int64_t* output) { |
396 return StringToIntImpl(input, output); | 394 return StringToIntImpl(input, output); |
397 } | 395 } |
398 | 396 |
399 bool StringToInt64(const StringPiece16& input, int64* output) { | 397 bool StringToInt64(const StringPiece16& input, int64_t* output) { |
400 return String16ToIntImpl(input, output); | 398 return String16ToIntImpl(input, output); |
401 } | 399 } |
402 | 400 |
403 bool StringToUint64(const StringPiece& input, uint64* output) { | 401 bool StringToUint64(const StringPiece& input, uint64_t* output) { |
404 return StringToIntImpl(input, output); | 402 return StringToIntImpl(input, output); |
405 } | 403 } |
406 | 404 |
407 bool StringToUint64(const StringPiece16& input, uint64* output) { | 405 bool StringToUint64(const StringPiece16& input, uint64_t* output) { |
408 return String16ToIntImpl(input, output); | 406 return String16ToIntImpl(input, output); |
409 } | 407 } |
410 | 408 |
411 bool StringToSizeT(const StringPiece& input, size_t* output) { | 409 bool StringToSizeT(const StringPiece& input, size_t* output) { |
412 return StringToIntImpl(input, output); | 410 return StringToIntImpl(input, output); |
413 } | 411 } |
414 | 412 |
415 bool StringToSizeT(const StringPiece16& input, size_t* output) { | 413 bool StringToSizeT(const StringPiece16& input, size_t* output) { |
416 return String16ToIntImpl(input, output); | 414 return String16ToIntImpl(input, output); |
417 } | 415 } |
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
458 ret[(i * 2) + 1] = kHexChars[b & 0xf]; | 456 ret[(i * 2) + 1] = kHexChars[b & 0xf]; |
459 } | 457 } |
460 return ret; | 458 return ret; |
461 } | 459 } |
462 | 460 |
463 bool HexStringToInt(const StringPiece& input, int* output) { | 461 bool HexStringToInt(const StringPiece& input, int* output) { |
464 return IteratorRangeToNumber<HexIteratorRangeToIntTraits>::Invoke( | 462 return IteratorRangeToNumber<HexIteratorRangeToIntTraits>::Invoke( |
465 input.begin(), input.end(), output); | 463 input.begin(), input.end(), output); |
466 } | 464 } |
467 | 465 |
468 bool HexStringToUInt(const StringPiece& input, uint32* output) { | 466 bool HexStringToUInt(const StringPiece& input, uint32_t* output) { |
469 return IteratorRangeToNumber<HexIteratorRangeToUIntTraits>::Invoke( | 467 return IteratorRangeToNumber<HexIteratorRangeToUIntTraits>::Invoke( |
470 input.begin(), input.end(), output); | 468 input.begin(), input.end(), output); |
471 } | 469 } |
472 | 470 |
473 bool HexStringToInt64(const StringPiece& input, int64* output) { | 471 bool HexStringToInt64(const StringPiece& input, int64_t* output) { |
474 return IteratorRangeToNumber<HexIteratorRangeToInt64Traits>::Invoke( | 472 return IteratorRangeToNumber<HexIteratorRangeToInt64Traits>::Invoke( |
475 input.begin(), input.end(), output); | 473 input.begin(), input.end(), output); |
476 } | 474 } |
477 | 475 |
478 bool HexStringToUInt64(const StringPiece& input, uint64* output) { | 476 bool HexStringToUInt64(const StringPiece& input, uint64_t* output) { |
479 return IteratorRangeToNumber<HexIteratorRangeToUInt64Traits>::Invoke( | 477 return IteratorRangeToNumber<HexIteratorRangeToUInt64Traits>::Invoke( |
480 input.begin(), input.end(), output); | 478 input.begin(), input.end(), output); |
481 } | 479 } |
482 | 480 |
483 bool HexStringToBytes(const std::string& input, std::vector<uint8>* output) { | 481 bool HexStringToBytes(const std::string& input, std::vector<uint8_t>* output) { |
484 return HexStringToBytesT(input, output); | 482 return HexStringToBytesT(input, output); |
485 } | 483 } |
486 | 484 |
487 } // namespace base | 485 } // namespace base |
OLD | NEW |