| // Copyright 2016 The Chromium Authors. All rights reserved. | 
 | // Use of this source code is governed by a BSD-style license that can be | 
 | // found in the LICENSE file. | 
 |  | 
 | #include "net/base/parse_number.h" | 
 |  | 
 | #include "base/logging.h" | 
 | #include "base/strings/string_number_conversions.h" | 
 | #include "base/strings/string_util.h" | 
 |  | 
 | namespace net { | 
 |  | 
 | namespace { | 
 |  | 
 | // The string to number conversion functions in //base include the type in the | 
 | // name (like StringToInt64()). The following wrapper methods create a | 
 | // consistent interface to StringToXXX() that calls the appropriate //base | 
 | // version. This simplifies writing generic code with a template. | 
 |  | 
 | bool StringToNumber(const base::StringPiece& input, int32_t* output) { | 
 |   // This assumes ints are 32-bits (will fail compile if that ever changes). | 
 |   return base::StringToInt(input, output); | 
 | } | 
 |  | 
 | bool StringToNumber(const base::StringPiece& input, uint32_t* output) { | 
 |   // This assumes ints are 32-bits (will fail compile if that ever changes). | 
 |   return base::StringToUint(input, output); | 
 | } | 
 |  | 
 | bool StringToNumber(const base::StringPiece& input, int64_t* output) { | 
 |   return base::StringToInt64(input, output); | 
 | } | 
 |  | 
 | bool StringToNumber(const base::StringPiece& input, uint64_t* output) { | 
 |   return base::StringToUint64(input, output); | 
 | } | 
 |  | 
 | bool SetError(ParseIntError error, ParseIntError* optional_error) { | 
 |   if (optional_error) | 
 |     *optional_error = error; | 
 |   return false; | 
 | } | 
 |  | 
 | template <typename T> | 
 | bool ParseIntHelper(const base::StringPiece& input, | 
 |                     ParseIntFormat format, | 
 |                     T* output, | 
 |                     ParseIntError* optional_error) { | 
 |   // Check that the input matches the format before calling StringToNumber(). | 
 |   // Numbers must start with either a digit or a negative sign. | 
 |   if (input.empty()) | 
 |     return SetError(ParseIntError::FAILED_PARSE, optional_error); | 
 |  | 
 |   bool starts_with_negative = input[0] == '-'; | 
 |   bool starts_with_digit = base::IsAsciiDigit(input[0]); | 
 |  | 
 |   if (!starts_with_digit) { | 
 |     if (format == ParseIntFormat::NON_NEGATIVE || !starts_with_negative) | 
 |       return SetError(ParseIntError::FAILED_PARSE, optional_error); | 
 |   } | 
 |  | 
 |   // Dispatch to the appropriate flavor of base::StringToXXX() by calling one of | 
 |   // the type-specific overloads. | 
 |   T result; | 
 |   if (StringToNumber(input, &result)) { | 
 |     *output = result; | 
 |     return true; | 
 |   } | 
 |  | 
 |   // Optimization: If the error is not going to be inspected, don't bother | 
 |   // calculating it. | 
 |   if (!optional_error) | 
 |     return false; | 
 |  | 
 |   // Set an error that distinguishes between parsing/underflow/overflow errors. | 
 |   // | 
 |   // Note that the output set by base::StringToXXX() on failure cannot be used | 
 |   // as it has ambiguity with parse errors. | 
 |  | 
 |   // Strip any leading negative sign off the number. | 
 |   base::StringPiece numeric_portion = | 
 |       starts_with_negative ? input.substr(1) : input; | 
 |  | 
 |   // Test if |numeric_portion| is a valid non-negative integer. | 
 |   if (!numeric_portion.empty() && | 
 |       numeric_portion.find_first_not_of("0123456789") == std::string::npos) { | 
 |     // If it was, the failure must have been due to underflow/overflow. | 
 |     return SetError(starts_with_negative ? ParseIntError::FAILED_UNDERFLOW | 
 |                                          : ParseIntError::FAILED_OVERFLOW, | 
 |                     optional_error); | 
 |   } | 
 |  | 
 |   // Otherwise it was a mundane parsing error. | 
 |   return SetError(ParseIntError::FAILED_PARSE, optional_error); | 
 | } | 
 |  | 
 | }  // namespace | 
 |  | 
 | bool ParseInt32(const base::StringPiece& input, | 
 |                 ParseIntFormat format, | 
 |                 int32_t* output, | 
 |                 ParseIntError* optional_error) { | 
 |   return ParseIntHelper(input, format, output, optional_error); | 
 | } | 
 |  | 
 | bool ParseInt64(const base::StringPiece& input, | 
 |                 ParseIntFormat format, | 
 |                 int64_t* output, | 
 |                 ParseIntError* optional_error) { | 
 |   return ParseIntHelper(input, format, output, optional_error); | 
 | } | 
 |  | 
 | bool ParseUint32(const base::StringPiece& input, | 
 |                  uint32_t* output, | 
 |                  ParseIntError* optional_error) { | 
 |   return ParseIntHelper(input, ParseIntFormat::NON_NEGATIVE, output, | 
 |                         optional_error); | 
 | } | 
 |  | 
 | bool ParseUint64(const base::StringPiece& input, | 
 |                  uint64_t* output, | 
 |                  ParseIntError* optional_error) { | 
 |   return ParseIntHelper(input, ParseIntFormat::NON_NEGATIVE, output, | 
 |                         optional_error); | 
 | } | 
 |  | 
 | }  // namespace net |