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 "relative_part_rule.hpp" 13 : #include "boost/url/rfc/detail/path_rules.hpp" 14 : #include <boost/url/grammar/parse.hpp> 15 : 16 : namespace boost { 17 : namespace urls { 18 : namespace detail { 19 : 20 : constexpr auto pchars_nc = pchars - ':'; 21 : 22 : auto 23 1339 : relative_part_rule_t:: 24 : parse( 25 : char const*& it, 26 : char const* const end 27 : ) const noexcept -> 28 : system::result<value_type> 29 : { 30 2678 : value_type t; 31 1339 : if(it == end) 32 : { 33 : // path-empty 34 125 : return t; 35 : } 36 1214 : if(end - it == 1) 37 : { 38 142 : if(*it == '/') 39 : { 40 : // path-absolute 41 : t.path = make_pct_string_view_unsafe( 42 78 : it, 1, 1); 43 78 : t.segment_count = 1; 44 78 : ++it; 45 78 : return t; 46 : } 47 64 : if(*it != ':') 48 : { 49 : // path-noscheme or 50 : // path-empty 51 : auto rv = grammar::parse( 52 63 : it, end, segment_rule); 53 63 : if(! rv) 54 0 : return rv.error(); 55 63 : if(! rv->empty()) 56 : { 57 29 : t.path = *rv; 58 29 : t.segment_count = 1; 59 : } 60 : } 61 : // path-empty 62 64 : return t; 63 : } 64 1072 : if( it[0] == '/' && 65 523 : it[1] == '/') 66 : { 67 : // "//" authority 68 244 : it += 2; 69 : auto rv = grammar::parse( 70 244 : it, end, authority_rule); 71 244 : if(! rv) 72 0 : return rv.error(); 73 244 : t.authority = *rv; 74 244 : t.has_authority = true; 75 : } 76 1072 : if(it == end) 77 : { 78 : // path-empty 79 123 : return t; 80 : } 81 949 : auto const it0 = it; 82 949 : std::size_t dn = 0; 83 949 : if(*it != '/') 84 : { 85 : // segment_nc 86 : auto rv = grammar::parse(it, end, 87 552 : pct_encoded_rule(pchars_nc)); 88 552 : if(! rv) 89 1 : return rv.error(); 90 551 : if(rv->empty()) 91 207 : return t; 92 344 : dn += rv->decoded_size(); 93 344 : ++t.segment_count; 94 344 : if( it != end && 95 269 : *it == ':') 96 : { 97 41 : BOOST_URL_RETURN_EC( 98 : grammar::error::mismatch); 99 : } 100 : } 101 3137 : while(it != end) 102 : { 103 2490 : if(*it == '/') 104 : { 105 1319 : ++dn; 106 1319 : ++it; 107 1319 : ++t.segment_count; 108 1319 : continue; 109 : } 110 : auto rv = grammar::parse( 111 1171 : it, end, segment_rule); 112 1171 : if(! rv) 113 0 : return rv.error(); 114 1171 : if(rv->empty()) 115 53 : break; 116 1118 : dn += rv->decoded_size(); 117 : } 118 : t.path = make_pct_string_view_unsafe( 119 700 : it0, it - it0, dn); 120 700 : return t; 121 : } 122 : 123 : } // detail 124 : } // urls 125 : } // boost 126 :