Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(77)

Unified Diff: net/base/parse_number.cc

Issue 1828103002: Extend net/base/parse_number.h for parsing of negative numbers, and determining if there was overflo (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@proxy_num
Patch Set: remove http_response_headers changes (moving to other CL) Created 4 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: net/base/parse_number.cc
diff --git a/net/base/parse_number.cc b/net/base/parse_number.cc
index d315bec63a906dba00b5f27e56dd20161ace6266..478b5585294cf001a6e2c92d9522bb70509de174 100644
--- a/net/base/parse_number.cc
+++ b/net/base/parse_number.cc
@@ -4,20 +4,144 @@
#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 {
- int result;
- if (!base::StringToInt(input, &result))
- return false;
+// 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.
- *output = result;
- return true;
+bool StringToNumber(const base::StringPiece& input, int32_t* output) {
+ // This assumes ints are 32-bits.
+ return base::StringToInt(input, output);
+}
+
+bool StringToNumber(const base::StringPiece& input, uint32_t* output) {
+ // This assumes ints are 32-bits
+ 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);
+}
+
+template <typename T>
+ParseIntegerResult ParseIntegerHelper(const base::StringPiece& input,
+ ParseIntegerSignPolicy sign_policy,
+ T* output) {
+ if (input.empty())
+ return ParseIntegerResult::FAILED_PARSE;
+
+ bool starts_with_negative = input[0] == '-';
+ bool starts_with_digit = input[0] >= '0' && input[0] <= '9';
+
+ // Numbers must start with either a digit or a negative sign
+ //
+ // Reject everythin else to prevent the permissive behavior of
+ // StringToIntXXX() when it comes to accepting a leading '+'.
+ switch (sign_policy) {
+ case ParseIntegerSignPolicy::NON_NEGATIVE:
+ if (!starts_with_digit)
+ return ParseIntegerResult::FAILED_PARSE;
+ break;
+
+ case ParseIntegerSignPolicy::ANY:
+ if (!starts_with_digit && !starts_with_negative)
+ return ParseIntegerResult::FAILED_PARSE;
+ break;
+ }
+
+ // 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 ParseIntegerResult::OK;
+ }
+
+ // Set an error that distinguishes between parsing/underflow/overflow errors.
+ //
+ // Note that base::StringToXXX() functions have a magical API that modify the
+ // output on failure to indicate whether underflow/overflow happened.
+ //
+ // You would think these can be used here, but unfortunately they return those
+ // magic values in multiple cases making it impossible to distinguish
+ // underflow/overflow from failed parsing due to leading/trailing whitespace.
+ //
+ // So instead look at the number to see if it was valid.
+
+ // 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 starts_with_negative ? ParseIntegerResult::FAILED_UNDERFLOW
+ : ParseIntegerResult::FAILED_OVERFLOW;
+ }
+
+ // Otherwise it was a mundane parsing error.
+ return ParseIntegerResult::FAILED_PARSE;
+}
+
+template <typename T>
+bool ParseNonNegativeIntegerHelper(const base::StringPiece& input, T* output) {
+ auto result =
+ ParseIntegerHelper(input, ParseIntegerSignPolicy::NON_NEGATIVE, output);
+ return result == ParseIntegerResult::OK;
+}
+
+} // namespace
+
+ParseIntegerResult ParseInteger(const base::StringPiece& input,
+ ParseIntegerSignPolicy sign_policy,
+ int32_t* output) {
+ return ParseIntegerHelper(input, sign_policy, output);
+}
+
+ParseIntegerResult ParseInteger(const base::StringPiece& input,
+ ParseIntegerSignPolicy sign_policy,
+ uint32_t* output) {
+ return ParseIntegerHelper(input, sign_policy, output);
+}
+
+ParseIntegerResult ParseInteger(const base::StringPiece& input,
+ ParseIntegerSignPolicy sign_policy,
+ int64_t* output) {
+ return ParseIntegerHelper(input, sign_policy, output);
+}
+
+ParseIntegerResult ParseInteger(const base::StringPiece& input,
+ ParseIntegerSignPolicy sign_policy,
+ uint64_t* output) {
+ return ParseIntegerHelper(input, sign_policy, output);
+}
+
+bool ParseNonNegativeInteger(const base::StringPiece& input, int32_t* output) {
+ return ParseNonNegativeIntegerHelper(input, output);
+}
+
+bool ParseNonNegativeInteger(const base::StringPiece& input, uint32_t* output) {
+ return ParseNonNegativeIntegerHelper(input, output);
+}
+
+bool ParseNonNegativeInteger(const base::StringPiece& input, int64_t* output) {
+ return ParseNonNegativeIntegerHelper(input, output);
+}
+
+bool ParseNonNegativeInteger(const base::StringPiece& input, uint64_t* output) {
+ return ParseNonNegativeIntegerHelper(input, output);
}
} // namespace net

Powered by Google App Engine
This is Rietveld 408576698