| Index: net/base/parse_number.cc
|
| diff --git a/net/base/parse_number.cc b/net/base/parse_number.cc
|
| index d315bec63a906dba00b5f27e56dd20161ace6266..365aa350b472c1f58e29903d91943f4fcc69c096 100644
|
| --- a/net/base/parse_number.cc
|
| +++ b/net/base/parse_number.cc
|
| @@ -4,20 +4,123 @@
|
|
|
| #include "net/base/parse_number.h"
|
|
|
| +#include "base/logging.h"
|
| #include "base/strings/string_number_conversions.h"
|
|
|
| namespace net {
|
|
|
| -bool ParseNonNegativeDecimalInt(const base::StringPiece& input, int* output) {
|
| - if (input.empty() || input[0] > '9' || input[0] < '0')
|
| - return false;
|
| +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 = input[0] >= '0' && input[0] <= '9';
|
|
|
| - int result;
|
| - if (!base::StringToInt(input, &result))
|
| + 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;
|
|
|
| - *output = result;
|
| - return true;
|
| + // 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
|
|
|