LCOV - code coverage report
Current view: top level - boost/url/grammar/impl - unsigned_rule.hpp (source / functions) Hit Total Coverage
Test: coverage_filtered.info Lines: 34 34 100.0 %
Date: 2024-02-29 20:02:55 Functions: 4 4 100.0 %

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

Generated by: LCOV version 1.15