Line data Source code
1 : //
2 : // Copyright (c) 2022 Alan de Freitas (alandefreitas at gmail dot com)
3 : //
4 : // Distributed under the Boost Software License, Version 1.0. (See accompanying
5 : // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
6 : //
7 : // Official repository: https://github.com/boostorg/url
8 : //
9 :
10 : #ifndef BOOST_URL_GRAMMAR_IMPL_UNSIGNED_RULE_HPP
11 : #define BOOST_URL_GRAMMAR_IMPL_UNSIGNED_RULE_HPP
12 :
13 : #include <boost/url/grammar/error.hpp>
14 : #include <boost/url/grammar/digit_chars.hpp>
15 : #include <algorithm> // VFALCO grr..
16 :
17 : namespace boost {
18 : namespace urls {
19 : namespace grammar {
20 :
21 : template<class U>
22 : auto
23 1693 : unsigned_rule<U>::
24 : parse(
25 : char const*& it,
26 : char const* end
27 : ) const noexcept ->
28 : system::result<value_type>
29 : {
30 1693 : if(it == end)
31 : {
32 : // end
33 371 : BOOST_URL_RETURN_EC(
34 : error::mismatch);
35 : }
36 1322 : if(*it == '0')
37 : {
38 49 : ++it;
39 73 : if( it == end ||
40 24 : ! digit_chars(*it))
41 : {
42 43 : return U(0);
43 : }
44 : // bad leading zero
45 6 : BOOST_URL_RETURN_EC(
46 : error::invalid);
47 : }
48 1273 : if(! digit_chars(*it))
49 : {
50 : // expected digit
51 871 : BOOST_URL_RETURN_EC(
52 : error::mismatch);
53 : }
54 : static constexpr U Digits10 =
55 : std::numeric_limits<
56 : U>::digits10;
57 : static constexpr U ten = 10;
58 : char const* safe_end;
59 402 : if(static_cast<std::size_t>(
60 402 : end - it) >= Digits10)
61 186 : safe_end = it + Digits10;
62 : else
63 216 : safe_end = end;
64 402 : U u = *it - '0';
65 402 : ++it;
66 1630 : while(it != safe_end &&
67 700 : digit_chars(*it))
68 : {
69 528 : char const dig = *it - '0';
70 528 : u = u * ten + dig;
71 528 : ++it;
72 : }
73 653 : if( it != end &&
74 251 : digit_chars(*it))
75 : {
76 : static constexpr U Max = (
77 : std::numeric_limits<
78 : U>::max)();
79 : static constexpr
80 : auto div = (Max / ten);
81 : static constexpr
82 : char rem = (Max % ten);
83 44 : char const dig = *it - '0';
84 44 : if( u > div || (
85 31 : u == div && dig > rem))
86 : {
87 : // integer overflow
88 23 : BOOST_URL_RETURN_EC(
89 : error::invalid);
90 : }
91 21 : u = u * ten + dig;
92 21 : ++it;
93 28 : if( it < end &&
94 7 : digit_chars(*it))
95 : {
96 : // integer overflow
97 6 : BOOST_URL_RETURN_EC(
98 : error::invalid);
99 : }
100 : }
101 :
102 373 : return u;
103 : }
104 :
105 : } // grammar
106 : } // urls
107 : } // boost
108 :
109 : #endif
|