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 : #ifndef BOOST_URL_RFC_DETAIL_IMPL_HIER_PART_RULE_IPP 11 : #define BOOST_URL_RFC_DETAIL_IMPL_HIER_PART_RULE_IPP 12 : 13 : #include <boost/url/detail/config.hpp> 14 : #include "hier_part_rule.hpp" 15 : #include "boost/url/rfc/detail/path_rules.hpp" 16 : #include <boost/url/grammar/parse.hpp> 17 : #include <boost/url/grammar/parse.hpp> 18 : 19 : namespace boost { 20 : namespace urls { 21 : namespace detail { 22 : 23 : auto 24 2249 : hier_part_rule_t:: 25 : parse( 26 : char const*& it, 27 : char const* const end 28 : ) const noexcept -> 29 : system::result<value_type> 30 : { 31 4498 : value_type t; 32 2249 : if(it == end) 33 : { 34 : // path-empty 35 44 : return t; 36 : } 37 2205 : if(end - it == 1) 38 : { 39 36 : if(*it == '/') 40 : { 41 : // path-absolute 42 : t.path = make_pct_string_view_unsafe( 43 26 : it, 1, 1); 44 26 : t.segment_count = 1; 45 26 : ++it; 46 26 : return t; 47 : } 48 : // path-rootless 49 : auto rv = grammar::parse( 50 10 : it, end, segment_rule); 51 10 : if(! rv) 52 0 : return rv.error(); 53 10 : t.path = *rv; 54 10 : t.segment_count = !t.path.empty(); 55 10 : return t; 56 : } 57 2169 : if( it[0] == '/' && 58 1568 : it[1] == '/') 59 : { 60 : // "//" authority 61 1472 : it += 2; 62 : auto rv = grammar::parse( 63 1472 : it, end, authority_rule); 64 1472 : if(! rv) 65 30 : return rv.error(); 66 1442 : t.authority = *rv; 67 1442 : t.has_authority = true; 68 : } 69 : // the authority requires an absolute path 70 : // or an empty path 71 2139 : if(it == end || ( 72 1733 : t.has_authority && ( 73 1036 : *it != '/' && 74 146 : *it != '?' && 75 103 : *it != '#'))) 76 : { 77 : // path-empty 78 495 : return t; 79 : } 80 1644 : auto const it0 = it; 81 1644 : std::size_t dn = 0; 82 1644 : if(*it != '/') 83 : { 84 : auto rv = grammar::parse( 85 658 : it, end, segment_rule); 86 658 : if(! rv) 87 2 : return rv.error(); 88 656 : if(rv->empty()) 89 75 : return t; 90 581 : dn += rv->decoded_size(); 91 581 : ++t.segment_count; 92 : } 93 4353 : while(it != end) 94 : { 95 2978 : if(*it == '/') 96 : { 97 1665 : ++dn; 98 1665 : ++it; 99 1665 : ++t.segment_count; 100 1665 : continue; 101 : } 102 : auto rv = grammar::parse( 103 1313 : it, end, segment_rule); 104 1313 : if(! rv) 105 4 : return rv.error(); 106 1309 : if(rv->empty()) 107 188 : break; 108 1121 : dn += rv->decoded_size(); 109 : } 110 : t.path = make_pct_string_view_unsafe( 111 1563 : it0, it - it0, dn); 112 1563 : return t; 113 : } 114 : 115 : } // detail 116 : } // urls 117 : } // boost 118 : 119 : #endif