include/boost/url/grammar/impl/unsigned_rule.hpp

100.0% Lines (40/40) 100.0% Functions (2/3)
include/boost/url/grammar/impl/unsigned_rule.hpp
Line TLA Hits 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_CXX20_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
111