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 1674 : unsigned_rule<U>:: 24 : parse( 25 : char const*& it, 26 : char const* end 27 : ) const noexcept -> 28 : system::result<value_type> 29 : { 30 1674 : if(it == end) 31 : { 32 : // end 33 371 : BOOST_URL_RETURN_EC( 34 : error::mismatch); 35 : } 36 1303 : 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 1254 : 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 383 : if(static_cast<std::size_t>( 60 383 : end - it) >= Digits10) 61 177 : safe_end = it + Digits10; 62 : else 63 206 : safe_end = end; 64 383 : U u = *it - '0'; 65 383 : ++it; 66 1555 : while(it != safe_end && 67 668 : digit_chars(*it)) 68 : { 69 504 : char const dig = *it - '0'; 70 504 : u = u * ten + dig; 71 504 : ++it; 72 : } 73 626 : if( it != end && 74 243 : 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 354 : return u; 103 : } 104 : 105 : } // grammar 106 : } // urls 107 : } // boost 108 : 109 : #endif