OLD | NEW |
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 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_number_conversions.h" | 5 #include "base/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 274 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
285 typedef VALUE value_type; | 285 typedef VALUE value_type; |
286 static value_type min() { | 286 static value_type min() { |
287 return std::numeric_limits<value_type>::min(); | 287 return std::numeric_limits<value_type>::min(); |
288 } | 288 } |
289 static value_type max() { | 289 static value_type max() { |
290 return std::numeric_limits<value_type>::max(); | 290 return std::numeric_limits<value_type>::max(); |
291 } | 291 } |
292 static const int kBase = BASE; | 292 static const int kBase = BASE; |
293 }; | 293 }; |
294 | 294 |
| 295 typedef BaseIteratorRangeToNumberTraits<std::string::const_iterator, int, 10> |
| 296 IteratorRangeToIntTraits; |
| 297 typedef BaseIteratorRangeToNumberTraits<string16::const_iterator, int, 10> |
| 298 WideIteratorRangeToIntTraits; |
| 299 typedef BaseIteratorRangeToNumberTraits<std::string::const_iterator, int64, 10> |
| 300 IteratorRangeToInt64Traits; |
| 301 typedef BaseIteratorRangeToNumberTraits<string16::const_iterator, int64, 10> |
| 302 WideIteratorRangeToInt64Traits; |
| 303 |
| 304 typedef BaseIteratorRangeToNumberTraits<const char*, int, 10> |
| 305 CharBufferToIntTraits; |
| 306 typedef BaseIteratorRangeToNumberTraits<const char16*, int, 10> |
| 307 WideCharBufferToIntTraits; |
| 308 typedef BaseIteratorRangeToNumberTraits<const char*, int64, 10> |
| 309 CharBufferToInt64Traits; |
| 310 typedef BaseIteratorRangeToNumberTraits<const char16*, int64, 10> |
| 311 WideCharBufferToInt64Traits; |
| 312 |
295 template<typename ITERATOR> | 313 template<typename ITERATOR> |
296 class BaseHexIteratorRangeToIntTraits | 314 class BaseHexIteratorRangeToIntTraits |
297 : public BaseIteratorRangeToNumberTraits<ITERATOR, int, 16> { | 315 : public BaseIteratorRangeToNumberTraits<ITERATOR, int, 16> { |
298 public: | 316 public: |
299 // Allow parsing of 0xFFFFFFFF, which is technically an overflow | 317 // Allow parsing of 0xFFFFFFFF, which is technically an overflow |
300 static unsigned int max() { | 318 static unsigned int max() { |
301 return std::numeric_limits<unsigned int>::max(); | 319 return std::numeric_limits<unsigned int>::max(); |
302 } | 320 } |
303 }; | 321 }; |
304 | 322 |
305 typedef BaseHexIteratorRangeToIntTraits<StringPiece::const_iterator> | 323 typedef BaseHexIteratorRangeToIntTraits<std::string::const_iterator> |
306 HexIteratorRangeToIntTraits; | 324 HexIteratorRangeToIntTraits; |
| 325 typedef BaseHexIteratorRangeToIntTraits<const char*> |
| 326 HexCharBufferToIntTraits; |
307 | 327 |
308 template<typename STR> | 328 template<typename STR> |
309 bool HexStringToBytesT(const STR& input, std::vector<uint8>* output) { | 329 bool HexStringToBytesT(const STR& input, std::vector<uint8>* output) { |
310 DCHECK_EQ(output->size(), 0u); | 330 DCHECK_EQ(output->size(), 0u); |
311 size_t count = input.size(); | 331 size_t count = input.size(); |
312 if (count == 0 || (count % 2) != 0) | 332 if (count == 0 || (count % 2) != 0) |
313 return false; | 333 return false; |
314 for (uintptr_t i = 0; i < count / 2; ++i) { | 334 for (uintptr_t i = 0; i < count / 2; ++i) { |
315 uint8 msb = 0; // most significant 4 bits | 335 uint8 msb = 0; // most significant 4 bits |
316 uint8 lsb = 0; // least significant 4 bits | 336 uint8 lsb = 0; // least significant 4 bits |
317 if (!CharToDigit<16>(input[i * 2], &msb) || | 337 if (!CharToDigit<16>(input[i * 2], &msb) || |
318 !CharToDigit<16>(input[i * 2 + 1], &lsb)) | 338 !CharToDigit<16>(input[i * 2 + 1], &lsb)) |
319 return false; | 339 return false; |
320 output->push_back((msb << 4) | lsb); | 340 output->push_back((msb << 4) | lsb); |
321 } | 341 } |
322 return true; | 342 return true; |
323 } | 343 } |
324 | 344 |
325 template <typename VALUE, int BASE> | |
326 class StringPieceToNumberTraits | |
327 : public BaseIteratorRangeToNumberTraits<StringPiece::const_iterator, | |
328 VALUE, | |
329 BASE> {}; | |
330 | |
331 template <typename VALUE> | |
332 bool StringToIntImpl(const StringPiece& input, VALUE* output) { | |
333 return IteratorRangeToNumber<StringPieceToNumberTraits<VALUE, 10> >::Invoke( | |
334 input.begin(), input.end(), output); | |
335 } | |
336 | |
337 template <typename VALUE, int BASE> | |
338 class StringPiece16ToNumberTraits | |
339 : public BaseIteratorRangeToNumberTraits<StringPiece16::const_iterator, | |
340 VALUE, | |
341 BASE> {}; | |
342 | |
343 template <typename VALUE> | |
344 bool String16ToIntImpl(const StringPiece16& input, VALUE* output) { | |
345 return IteratorRangeToNumber<StringPiece16ToNumberTraits<VALUE, 10> >::Invoke( | |
346 input.begin(), input.end(), output); | |
347 } | |
348 | |
349 } // namespace | 345 } // namespace |
350 | 346 |
351 std::string IntToString(int value) { | 347 std::string IntToString(int value) { |
352 return IntToStringT<std::string, int, unsigned int, true>:: | 348 return IntToStringT<std::string, int, unsigned int, true>:: |
353 IntToString(value); | 349 IntToString(value); |
354 } | 350 } |
355 | 351 |
356 string16 IntToString16(int value) { | 352 string16 IntToString16(int value) { |
357 return IntToStringT<string16, int, unsigned int, true>:: | 353 return IntToStringT<string16, int, unsigned int, true>:: |
358 IntToString(value); | 354 IntToString(value); |
(...skipping 28 matching lines...) Expand all Loading... |
387 IntToString(value); | 383 IntToString(value); |
388 } | 384 } |
389 | 385 |
390 std::string DoubleToString(double value) { | 386 std::string DoubleToString(double value) { |
391 // According to g_fmt.cc, it is sufficient to declare a buffer of size 32. | 387 // According to g_fmt.cc, it is sufficient to declare a buffer of size 32. |
392 char buffer[32]; | 388 char buffer[32]; |
393 dmg_fp::g_fmt(buffer, value); | 389 dmg_fp::g_fmt(buffer, value); |
394 return std::string(buffer); | 390 return std::string(buffer); |
395 } | 391 } |
396 | 392 |
397 bool StringToInt(const StringPiece& input, int* output) { | 393 bool StringToInt(const std::string& input, int* output) { |
398 return StringToIntImpl(input, output); | 394 return IteratorRangeToNumber<IteratorRangeToIntTraits>::Invoke(input.begin(), |
| 395 input.end(), |
| 396 output); |
399 } | 397 } |
400 | 398 |
401 bool StringToInt(const StringPiece16& input, int* output) { | 399 bool StringToInt(std::string::const_iterator begin, |
402 return String16ToIntImpl(input, output); | 400 std::string::const_iterator end, |
| 401 int* output) { |
| 402 return IteratorRangeToNumber<IteratorRangeToIntTraits>::Invoke(begin, |
| 403 end, |
| 404 output); |
403 } | 405 } |
404 | 406 |
405 bool StringToInt64(const StringPiece& input, int64* output) { | 407 #if !defined(STD_STRING_ITERATOR_IS_CHAR_POINTER) |
406 return StringToIntImpl(input, output); | 408 bool StringToInt(const char* begin, const char* end, int* output) { |
| 409 return IteratorRangeToNumber<CharBufferToIntTraits>::Invoke(begin, |
| 410 end, |
| 411 output); |
| 412 } |
| 413 #endif |
| 414 |
| 415 bool StringToInt(const string16& input, int* output) { |
| 416 return IteratorRangeToNumber<WideIteratorRangeToIntTraits>::Invoke( |
| 417 input.begin(), input.end(), output); |
407 } | 418 } |
408 | 419 |
409 bool StringToInt64(const StringPiece16& input, int64* output) { | 420 bool StringToInt(string16::const_iterator begin, |
410 return String16ToIntImpl(input, output); | 421 string16::const_iterator end, |
| 422 int* output) { |
| 423 return IteratorRangeToNumber<WideIteratorRangeToIntTraits>::Invoke(begin, |
| 424 end, |
| 425 output); |
411 } | 426 } |
412 | 427 |
| 428 #if !defined(BASE_STRING16_ITERATOR_IS_CHAR16_POINTER) |
| 429 bool StringToInt(const char16* begin, const char16* end, int* output) { |
| 430 return IteratorRangeToNumber<WideCharBufferToIntTraits>::Invoke(begin, |
| 431 end, |
| 432 output); |
| 433 } |
| 434 #endif |
| 435 |
| 436 bool StringToInt64(const std::string& input, int64* output) { |
| 437 return IteratorRangeToNumber<IteratorRangeToInt64Traits>::Invoke( |
| 438 input.begin(), input.end(), output); |
| 439 } |
| 440 |
| 441 bool StringToInt64(std::string::const_iterator begin, |
| 442 std::string::const_iterator end, |
| 443 int64* output) { |
| 444 return IteratorRangeToNumber<IteratorRangeToInt64Traits>::Invoke(begin, |
| 445 end, |
| 446 output); |
| 447 } |
| 448 |
| 449 #if !defined(STD_STRING_ITERATOR_IS_CHAR_POINTER) |
| 450 bool StringToInt64(const char* begin, const char* end, int64* output) { |
| 451 return IteratorRangeToNumber<CharBufferToInt64Traits>::Invoke(begin, |
| 452 end, |
| 453 output); |
| 454 } |
| 455 #endif |
| 456 |
| 457 bool StringToInt64(const string16& input, int64* output) { |
| 458 return IteratorRangeToNumber<WideIteratorRangeToInt64Traits>::Invoke( |
| 459 input.begin(), input.end(), output); |
| 460 } |
| 461 |
| 462 bool StringToInt64(string16::const_iterator begin, |
| 463 string16::const_iterator end, |
| 464 int64* output) { |
| 465 return IteratorRangeToNumber<WideIteratorRangeToInt64Traits>::Invoke(begin, |
| 466 end, |
| 467 output); |
| 468 } |
| 469 |
| 470 #if !defined(BASE_STRING16_ITERATOR_IS_CHAR16_POINTER) |
| 471 bool StringToInt64(const char16* begin, const char16* end, int64* output) { |
| 472 return IteratorRangeToNumber<WideCharBufferToInt64Traits>::Invoke(begin, |
| 473 end, |
| 474 output); |
| 475 } |
| 476 #endif |
| 477 |
413 bool StringToDouble(const std::string& input, double* output) { | 478 bool StringToDouble(const std::string& input, double* output) { |
414 errno = 0; // Thread-safe? It is on at least Mac, Linux, and Windows. | 479 errno = 0; // Thread-safe? It is on at least Mac, Linux, and Windows. |
415 char* endptr = NULL; | 480 char* endptr = NULL; |
416 *output = dmg_fp::strtod(input.c_str(), &endptr); | 481 *output = dmg_fp::strtod(input.c_str(), &endptr); |
417 | 482 |
418 // Cases to return false: | 483 // Cases to return false: |
419 // - If errno is ERANGE, there was an overflow or underflow. | 484 // - If errno is ERANGE, there was an overflow or underflow. |
420 // - If the input string is empty, there was nothing to parse. | 485 // - If the input string is empty, there was nothing to parse. |
421 // - If endptr does not point to the end of the string, there are either | 486 // - If endptr does not point to the end of the string, there are either |
422 // characters remaining in the string after a parsed number, or the string | 487 // characters remaining in the string after a parsed number, or the string |
(...skipping 22 matching lines...) Expand all Loading... |
445 std::string ret(size * 2, '\0'); | 510 std::string ret(size * 2, '\0'); |
446 | 511 |
447 for (size_t i = 0; i < size; ++i) { | 512 for (size_t i = 0; i < size; ++i) { |
448 char b = reinterpret_cast<const char*>(bytes)[i]; | 513 char b = reinterpret_cast<const char*>(bytes)[i]; |
449 ret[(i * 2)] = kHexChars[(b >> 4) & 0xf]; | 514 ret[(i * 2)] = kHexChars[(b >> 4) & 0xf]; |
450 ret[(i * 2) + 1] = kHexChars[b & 0xf]; | 515 ret[(i * 2) + 1] = kHexChars[b & 0xf]; |
451 } | 516 } |
452 return ret; | 517 return ret; |
453 } | 518 } |
454 | 519 |
455 bool HexStringToInt(const StringPiece& input, int* output) { | 520 bool HexStringToInt(const std::string& input, int* output) { |
456 return IteratorRangeToNumber<HexIteratorRangeToIntTraits>::Invoke( | 521 return IteratorRangeToNumber<HexIteratorRangeToIntTraits>::Invoke( |
457 input.begin(), input.end(), output); | 522 input.begin(), input.end(), output); |
458 } | 523 } |
459 | 524 |
| 525 bool HexStringToInt(std::string::const_iterator begin, |
| 526 std::string::const_iterator end, |
| 527 int* output) { |
| 528 return IteratorRangeToNumber<HexIteratorRangeToIntTraits>::Invoke(begin, |
| 529 end, |
| 530 output); |
| 531 } |
| 532 |
| 533 #if !defined(STD_STRING_ITERATOR_IS_CHAR_POINTER) |
| 534 bool HexStringToInt(const char* begin, const char* end, int* output) { |
| 535 return IteratorRangeToNumber<HexCharBufferToIntTraits>::Invoke(begin, |
| 536 end, |
| 537 output); |
| 538 } |
| 539 #endif |
| 540 |
460 bool HexStringToBytes(const std::string& input, std::vector<uint8>* output) { | 541 bool HexStringToBytes(const std::string& input, std::vector<uint8>* output) { |
461 return HexStringToBytesT(input, output); | 542 return HexStringToBytesT(input, output); |
462 } | 543 } |
463 | 544 |
464 } // namespace base | 545 } // namespace base |
OLD | NEW |