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