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 : BOOST_URL_CXX14_CONSTEXPR
23 : auto
24 1951 : unsigned_rule<U>::
25 : parse(
26 : char const*& it,
27 : char const* end
28 : ) const noexcept ->
29 : system::result<value_type>
30 : {
31 1951 : if(it == end)
32 : {
33 : // end
34 417 : BOOST_URL_CONSTEXPR_RETURN_EC(
35 : error::mismatch);
36 : }
37 1534 : if(*it == '0')
38 : {
39 52 : ++it;
40 77 : if( it == end ||
41 25 : ! digit_chars(*it))
42 : {
43 46 : return U(0);
44 : }
45 : // bad leading zero
46 6 : BOOST_URL_CONSTEXPR_RETURN_EC(
47 : error::invalid);
48 : }
49 1482 : if(! digit_chars(*it))
50 : {
51 : // expected digit
52 1031 : BOOST_URL_CONSTEXPR_RETURN_EC(
53 : error::mismatch);
54 : }
55 451 : constexpr U Digits10 =
56 : std::numeric_limits<
57 : U>::digits10;
58 451 : constexpr U ten = 10;
59 451 : char const* safe_end = nullptr;
60 451 : if(static_cast<std::size_t>(
61 451 : end - it) >= Digits10)
62 207 : safe_end = it + Digits10;
63 : else
64 244 : safe_end = end;
65 451 : U u = *it - '0';
66 451 : ++it;
67 1819 : while(it != safe_end &&
68 783 : digit_chars(*it))
69 : {
70 585 : char const dig = *it - '0';
71 585 : u = u * ten + dig;
72 585 : ++it;
73 : }
74 730 : if( it != end &&
75 279 : digit_chars(*it))
76 : {
77 44 : constexpr U Max = (
78 : std::numeric_limits<
79 : U>::max)();
80 : constexpr
81 44 : auto div = (Max / ten);
82 : constexpr
83 44 : char rem = (Max % ten);
84 44 : char const dig = *it - '0';
85 44 : if( u > div || (
86 31 : u == div && dig > rem))
87 : {
88 : // integer overflow
89 23 : BOOST_URL_CONSTEXPR_RETURN_EC(
90 : error::invalid);
91 : }
92 21 : u = u * ten + dig;
93 21 : ++it;
94 28 : if( it < end &&
95 7 : digit_chars(*it))
96 : {
97 : // integer overflow
98 6 : BOOST_URL_CONSTEXPR_RETURN_EC(
99 : error::invalid);
100 : }
101 : }
102 :
103 422 : return u;
104 : }
105 :
106 : } // grammar
107 : } // urls
108 : } // boost
109 :
110 : #endif
|