parse_number.cc 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126
  1. // Copyright 2016 The Chromium Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style license that can be
  3. // found in the LICENSE file.
  4. #include "net/base/parse_number.h"
  5. #include "base/strings/string_number_conversions.h"
  6. #include "base/strings/string_util.h"
  7. namespace net {
  8. namespace {
  9. // The string to number conversion functions in //base include the type in the
  10. // name (like StringToInt64()). The following wrapper methods create a
  11. // consistent interface to StringToXXX() that calls the appropriate //base
  12. // version. This simplifies writing generic code with a template.
  13. bool StringToNumber(const base::StringPiece& input, int32_t* output) {
  14. // This assumes ints are 32-bits (will fail compile if that ever changes).
  15. return base::StringToInt(input, output);
  16. }
  17. bool StringToNumber(const base::StringPiece& input, uint32_t* output) {
  18. // This assumes ints are 32-bits (will fail compile if that ever changes).
  19. return base::StringToUint(input, output);
  20. }
  21. bool StringToNumber(const base::StringPiece& input, int64_t* output) {
  22. return base::StringToInt64(input, output);
  23. }
  24. bool StringToNumber(const base::StringPiece& input, uint64_t* output) {
  25. return base::StringToUint64(input, output);
  26. }
  27. bool SetError(ParseIntError error, ParseIntError* optional_error) {
  28. if (optional_error)
  29. *optional_error = error;
  30. return false;
  31. }
  32. template <typename T>
  33. bool ParseIntHelper(const base::StringPiece& input,
  34. ParseIntFormat format,
  35. T* output,
  36. ParseIntError* optional_error) {
  37. // Check that the input matches the format before calling StringToNumber().
  38. // Numbers must start with either a digit or a negative sign.
  39. if (input.empty())
  40. return SetError(ParseIntError::FAILED_PARSE, optional_error);
  41. bool starts_with_negative = input[0] == '-';
  42. bool starts_with_digit = base::IsAsciiDigit(input[0]);
  43. if (!starts_with_digit) {
  44. if (format == ParseIntFormat::NON_NEGATIVE || !starts_with_negative)
  45. return SetError(ParseIntError::FAILED_PARSE, optional_error);
  46. }
  47. // Dispatch to the appropriate flavor of base::StringToXXX() by calling one of
  48. // the type-specific overloads.
  49. T result;
  50. if (StringToNumber(input, &result)) {
  51. *output = result;
  52. return true;
  53. }
  54. // Optimization: If the error is not going to be inspected, don't bother
  55. // calculating it.
  56. if (!optional_error)
  57. return false;
  58. // Set an error that distinguishes between parsing/underflow/overflow errors.
  59. //
  60. // Note that the output set by base::StringToXXX() on failure cannot be used
  61. // as it has ambiguity with parse errors.
  62. // Strip any leading negative sign off the number.
  63. base::StringPiece numeric_portion =
  64. starts_with_negative ? input.substr(1) : input;
  65. // Test if |numeric_portion| is a valid non-negative integer.
  66. if (!numeric_portion.empty() &&
  67. numeric_portion.find_first_not_of("0123456789") == std::string::npos) {
  68. // If it was, the failure must have been due to underflow/overflow.
  69. return SetError(starts_with_negative ? ParseIntError::FAILED_UNDERFLOW
  70. : ParseIntError::FAILED_OVERFLOW,
  71. optional_error);
  72. }
  73. // Otherwise it was a mundane parsing error.
  74. return SetError(ParseIntError::FAILED_PARSE, optional_error);
  75. }
  76. } // namespace
  77. bool ParseInt32(const base::StringPiece& input,
  78. ParseIntFormat format,
  79. int32_t* output,
  80. ParseIntError* optional_error) {
  81. return ParseIntHelper(input, format, output, optional_error);
  82. }
  83. bool ParseInt64(const base::StringPiece& input,
  84. ParseIntFormat format,
  85. int64_t* output,
  86. ParseIntError* optional_error) {
  87. return ParseIntHelper(input, format, output, optional_error);
  88. }
  89. bool ParseUint32(const base::StringPiece& input,
  90. uint32_t* output,
  91. ParseIntError* optional_error) {
  92. return ParseIntHelper(input, ParseIntFormat::NON_NEGATIVE, output,
  93. optional_error);
  94. }
  95. bool ParseUint64(const base::StringPiece& input,
  96. uint64_t* output,
  97. ParseIntError* optional_error) {
  98. return ParseIntHelper(input, ParseIntFormat::NON_NEGATIVE, output,
  99. optional_error);
  100. }
  101. } // namespace net