Line data Source code
1 : // 2 : // Copyright (c) 2016-2019 Vinnie Falco (vinnie dot falco 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 : 11 : #include <boost/url/detail/config.hpp> 12 : #include "hier_part_rule.hpp" 13 : #include "boost/url/rfc/detail/path_rules.hpp" 14 : #include <boost/url/grammar/parse.hpp> 15 : #include <boost/url/grammar/parse.hpp> 16 : 17 : namespace boost { 18 : namespace urls { 19 : namespace detail { 20 : 21 : auto 22 2265 : hier_part_rule_t:: 23 : parse( 24 : char const*& it, 25 : char const* const end 26 : ) const noexcept -> 27 : system::result<value_type> 28 : { 29 4530 : value_type t; 30 2265 : if(it == end) 31 : { 32 : // path-empty 33 44 : return t; 34 : } 35 2221 : if(end - it == 1) 36 : { 37 36 : if(*it == '/') 38 : { 39 : // path-absolute 40 : t.path = make_pct_string_view_unsafe( 41 26 : it, 1, 1); 42 26 : t.segment_count = 1; 43 26 : ++it; 44 26 : return t; 45 : } 46 : // path-rootless 47 : auto rv = grammar::parse( 48 10 : it, end, segment_rule); 49 10 : if(! rv) 50 0 : return rv.error(); 51 10 : t.path = *rv; 52 10 : t.segment_count = !t.path.empty(); 53 10 : return t; 54 : } 55 2185 : if( it[0] == '/' && 56 1584 : it[1] == '/') 57 : { 58 : // "//" authority 59 1488 : it += 2; 60 : auto rv = grammar::parse( 61 1488 : it, end, authority_rule); 62 1488 : if(! rv) 63 30 : return rv.error(); 64 1458 : t.authority = *rv; 65 1458 : t.has_authority = true; 66 : } 67 : // the authority requires an absolute path 68 : // or an empty path 69 2155 : if(it == end || ( 70 1735 : t.has_authority && ( 71 1038 : *it != '/' && 72 146 : *it != '?' && 73 103 : *it != '#'))) 74 : { 75 : // path-empty 76 509 : return t; 77 : } 78 1646 : auto const it0 = it; 79 1646 : std::size_t dn = 0; 80 1646 : if(*it != '/') 81 : { 82 : auto rv = grammar::parse( 83 658 : it, end, segment_rule); 84 658 : if(! rv) 85 2 : return rv.error(); 86 656 : if(rv->empty()) 87 75 : return t; 88 581 : dn += rv->decoded_size(); 89 581 : ++t.segment_count; 90 : } 91 4359 : while(it != end) 92 : { 93 2982 : if(*it == '/') 94 : { 95 1667 : ++dn; 96 1667 : ++it; 97 1667 : ++t.segment_count; 98 1667 : continue; 99 : } 100 : auto rv = grammar::parse( 101 1315 : it, end, segment_rule); 102 1315 : if(! rv) 103 4 : return rv.error(); 104 1311 : if(rv->empty()) 105 188 : break; 106 1123 : dn += rv->decoded_size(); 107 : } 108 : t.path = make_pct_string_view_unsafe( 109 1565 : it0, it - it0, dn); 110 1565 : return t; 111 : } 112 : 113 : } // detail 114 : } // urls 115 : } // boost 116 :