blob: f70619a7546ba0f8934624b60b85e137d980ee58 [file] [log] [blame]
Avi Drissman64595482022-09-14 20:52:291// Copyright 2016 The Chromium Authors
eroman94e42f52016-03-23 22:07:082// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#ifndef NET_BASE_PARSE_NUMBER_H_
6#define NET_BASE_PARSE_NUMBER_H_
7
Bruno Pitrus6bbf6b02023-04-11 19:32:138#include <cstdint>
David Benjamin506122dc2023-11-07 01:32:189#include <string_view>
Bruno Pitrus6bbf6b02023-04-11 19:32:1310
eroman94e42f52016-03-23 22:07:0811#include "net/base/net_export.h"
12
13// This file contains utility functions for parsing numbers, in the context of
14// network protocols.
15//
16// Q: Doesn't //base already provide these in string_number_conversions.h, with
17// functions like base::StringToInt()?
18//
eromanae40d9ba2016-04-11 18:40:2619// A: Yes, and those functions are used under the hood by these implementations.
eroman94e42f52016-03-23 22:07:0820//
eromanae40d9ba2016-04-11 18:40:2621// However using the base::StringTo*() has historically led to subtle bugs
22// in the context of parsing network protocols:
eroman94e42f52016-03-23 22:07:0823//
eromanae40d9ba2016-04-11 18:40:2624// * Permitting a leading '+'
25// * Incorrectly classifying overflow/underflow from a parsing failure
26// * Allowing negative numbers for non-negative fields
eroman94e42f52016-03-23 22:07:0827//
eromanae40d9ba2016-04-11 18:40:2628// This API tries to avoid these problems by picking sensible defaults for
29// //net code. For more details see crbug.com/596523.
eroman94e42f52016-03-23 22:07:0830
eroman94e42f52016-03-23 22:07:0831namespace net {
32
eromanae40d9ba2016-04-11 18:40:2633// Format to use when parsing integers.
34enum class ParseIntFormat {
35 // Accepts non-negative base 10 integers of the form:
36 //
37 // 1*DIGIT
38 //
39 // This construction is used in a variety of IETF standards, such as RFC 7230
40 // (HTTP).
41 //
42 // When attempting to parse a negative number using this format, the failure
43 // will be FAILED_PARSE since it violated the expected format (and not
44 // FAILED_UNDERFLOW).
45 //
46 // Also note that inputs need not be in minimal encoding: "0003" is valid and
47 // equivalent to "3".
48 NON_NEGATIVE,
49
50 // Accept optionally negative base 10 integers of the form:
51 //
52 // ["-"] 1*DIGIT
53 //
54 // In other words, this accepts the same things as NON_NEGATIVE, and
55 // additionally recognizes those numbers prefixed with a '-'.
56 //
Matt Menked80a12e2023-03-22 16:57:2657 // Note that by this definition "-0" IS a valid input.
58 OPTIONALLY_NEGATIVE,
59
60 // Like NON_NEGATIVE, but rejects anything not in minimal encoding - that is,
61 // it rejects anything with leading 0's, except "0".
62 STRICT_NON_NEGATIVE,
63
64 // Like OPTIONALLY_NEGATIVE, but rejects anything not in minimal encoding -
65 // that is, it rejects "-0" and anything with leading 0's, except "0".
66 STRICT_OPTIONALLY_NEGATIVE,
eromanae40d9ba2016-04-11 18:40:2667};
68
69// The specific reason why a ParseInt*() function failed.
70enum class ParseIntError {
71 // The parsed number couldn't fit into the provided output type because it was
72 // too high.
73 FAILED_OVERFLOW,
74
75 // The parsed number couldn't fit into the provided output type because it was
76 // too low.
77 FAILED_UNDERFLOW,
78
79 // The number failed to be parsed because it wasn't a valid decimal number (as
80 // determined by the policy).
81 FAILED_PARSE,
82};
83
84// The ParseInt*() functions parse a string representing a number.
eroman94e42f52016-03-23 22:07:0885//
eromanae40d9ba2016-04-11 18:40:2686// The format of the strings that are accepted is controlled by the |format|
87// parameter. This allows rejecting negative numbers.
eroman94e42f52016-03-23 22:07:0888//
eromanae40d9ba2016-04-11 18:40:2689// These functions return true on success, and fill |*output| with the result.
eroman94e42f52016-03-23 22:07:0890//
eromanae40d9ba2016-04-11 18:40:2691// On failure, it is guaranteed that |*output| was not modified. If
92// |optional_error| was non-null, then it is filled with the reason for the
93// failure.
Daniel Cheng76bb1e002022-01-14 01:34:4294[[nodiscard]] NET_EXPORT bool ParseInt32(
David Benjamin506122dc2023-11-07 01:32:1895 std::string_view input,
Daniel Cheng76bb1e002022-01-14 01:34:4296 ParseIntFormat format,
97 int32_t* output,
98 ParseIntError* optional_error = nullptr);
eromanae40d9ba2016-04-11 18:40:2699
Daniel Cheng76bb1e002022-01-14 01:34:42100[[nodiscard]] NET_EXPORT bool ParseInt64(
David Benjamin506122dc2023-11-07 01:32:18101 std::string_view input,
Daniel Cheng76bb1e002022-01-14 01:34:42102 ParseIntFormat format,
103 int64_t* output,
104 ParseIntError* optional_error = nullptr);
eromanae40d9ba2016-04-11 18:40:26105
106// The ParseUint*() functions parse a string representing a number.
eroman94e42f52016-03-23 22:07:08107//
Matt Menked80a12e2023-03-22 16:57:26108// These are equivalent to calling ParseInt*(), except with unsigned output
Qingxin Wu430b87e02023-04-10 18:04:59109// types. ParseIntFormat may only be one of {NON_NEGATIVE, STRICT_NON_NEGATIVE}.
Daniel Cheng76bb1e002022-01-14 01:34:42110[[nodiscard]] NET_EXPORT bool ParseUint32(
David Benjamin506122dc2023-11-07 01:32:18111 std::string_view input,
Matt Menked80a12e2023-03-22 16:57:26112 ParseIntFormat format,
Daniel Cheng76bb1e002022-01-14 01:34:42113 uint32_t* output,
114 ParseIntError* optional_error = nullptr);
eromanae40d9ba2016-04-11 18:40:26115
Daniel Cheng76bb1e002022-01-14 01:34:42116[[nodiscard]] NET_EXPORT bool ParseUint64(
David Benjamin506122dc2023-11-07 01:32:18117 std::string_view input,
Matt Menked80a12e2023-03-22 16:57:26118 ParseIntFormat format,
Daniel Cheng76bb1e002022-01-14 01:34:42119 uint64_t* output,
120 ParseIntError* optional_error = nullptr);
eroman94e42f52016-03-23 22:07:08121
122} // namespace net
123
124#endif // NET_BASE_PARSE_NUMBER_H_