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 1340 : 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 1340 : value_type t;
31 1340 : if(it == end)
32 : {
33 : // path-empty
34 125 : return t;
35 : }
36 1215 : if(end - it == 1)
37 : {
38 142 : if(*it == '/')
39 : {
40 : // path-absolute
41 78 : t.path = make_pct_string_view_unsafe(
42 : 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 63 : auto rv = grammar::parse(
52 : 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 1073 : if( it[0] == '/' &&
65 524 : 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 244 : }
76 1073 : if(it == end)
77 : {
78 : // path-empty
79 123 : return t;
80 : }
81 950 : auto const it0 = it;
82 950 : std::size_t dn = 0;
83 950 : if(*it != '/')
84 : {
85 : // segment_nc
86 552 : 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 3144 : while(it != end)
102 : {
103 2496 : if(*it == '/')
104 : {
105 1322 : ++dn;
106 1322 : ++it;
107 1322 : ++t.segment_count;
108 1322 : continue;
109 : }
110 1174 : auto rv = grammar::parse(
111 : it, end, segment_rule);
112 1174 : if(! rv)
113 0 : return rv.error();
114 1174 : if(rv->empty())
115 53 : break;
116 1121 : dn += rv->decoded_size();
117 : }
118 701 : t.path = make_pct_string_view_unsafe(
119 701 : it0, it - it0, dn);
120 701 : return t;
121 1340 : }
122 :
123 : } // detail
124 : } // urls
125 : } // boost
126 :
|