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 2224 unsigned_rule<U>::
25 parse(
26 char const*& it,
27 char const* end
28 ) const noexcept ->
29 system::result<value_type>
30 {
31 2224 if(it == end)
32 {
33 // end
34 425 BOOST_URL_CONSTEXPR_RETURN_EC(
35 error::mismatch);
36 }
37 1799 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 1747 if(! digit_chars(*it))
50 {
51 // expected digit
52 1045 BOOST_URL_CONSTEXPR_RETURN_EC(
53 error::mismatch);
54 }
55 702 constexpr U Digits10 =
56 std::numeric_limits<
57 U>::digits10;
58 702 constexpr U ten = 10;
59 702 char const* safe_end = nullptr;
60 702 if(static_cast<std::size_t>(
61 702 end - it) >= Digits10)
62 298 safe_end = it + Digits10;
63 else
64 404 safe_end = end;
65 702 U u = *it - '0';
66 702 ++it;
67 2932 while(it != safe_end &&
68 1218 digit_chars(*it))
69 {
70 1012 char const dig = *it - '0';
71 1012 u = u * ten + dig;
72 1012 ++it;
73 }
74 1072 if( it != end &&
75 370 digit_chars(*it))
76 {
77 45 constexpr U Max = (
78 std::numeric_limits<
79 U>::max)();
80 constexpr
81 45 auto div = (Max / ten);
82 constexpr
83 45 char rem = (Max % ten);
84 45 char const dig = *it - '0';
85 45 if( u > div || (
86 32 u == div && dig > rem))
87 {
88 // integer overflow
89 23 BOOST_URL_CONSTEXPR_RETURN_EC(
90 error::invalid);
91 }
92 22 u = u * ten + dig;
93 22 ++it;
94 30 if( it < end &&
95 8 digit_chars(*it))
96 {
97 // integer overflow
98 6 BOOST_URL_CONSTEXPR_RETURN_EC(
99 error::invalid);
100 }
101 }
102
103 673 return u;
104 }
105
106 } // grammar
107 } // urls
108 } // boost
109
110 #endif
111