1  
//
1  
//
2  
// Copyright (c) 2016-2019 Vinnie Falco (vinnie dot falco at gmail dot com)
2  
// Copyright (c) 2016-2019 Vinnie Falco (vinnie dot falco at gmail dot com)
3  
// Copyright (c) 2023 Alan de Freitas (alandefreitas@gmail.com)
3  
// Copyright (c) 2023 Alan de Freitas (alandefreitas@gmail.com)
4  
//
4  
//
5  
// Distributed under the Boost Software License, Version 1.0. (See accompanying
5  
// Distributed under the Boost Software License, Version 1.0. (See accompanying
6  
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
6  
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
7  
//
7  
//
8  
// Official repository: https://github.com/boostorg/url
8  
// Official repository: https://github.com/boostorg/url
9  
//
9  
//
10  

10  

11  
#ifndef BOOST_URL_RFC_DETAIL_IMPL_RELATIVE_PART_RULE_HPP
11  
#ifndef BOOST_URL_RFC_DETAIL_IMPL_RELATIVE_PART_RULE_HPP
12  
#define BOOST_URL_RFC_DETAIL_IMPL_RELATIVE_PART_RULE_HPP
12  
#define BOOST_URL_RFC_DETAIL_IMPL_RELATIVE_PART_RULE_HPP
13  

13  

14  
#include <boost/url/detail/config.hpp>
14  
#include <boost/url/detail/config.hpp>
15  
#include <boost/url/rfc/detail/path_rules.hpp>
15  
#include <boost/url/rfc/detail/path_rules.hpp>
16  
#include <boost/url/rfc/pct_encoded_rule.hpp>
16  
#include <boost/url/rfc/pct_encoded_rule.hpp>
17  
#include <boost/url/rfc/pchars.hpp>
17  
#include <boost/url/rfc/pchars.hpp>
18  
#include <boost/url/grammar/error.hpp>
18  
#include <boost/url/grammar/error.hpp>
19  
#include <boost/url/grammar/parse.hpp>
19  
#include <boost/url/grammar/parse.hpp>
20  

20  

21  
namespace boost {
21  
namespace boost {
22  
namespace urls {
22  
namespace urls {
23  
namespace detail {
23  
namespace detail {
24  

24  

25  
BOOST_URL_CXX20_CONSTEXPR_OR_INLINE
25  
BOOST_URL_CXX20_CONSTEXPR_OR_INLINE
26  
auto
26  
auto
27  
relative_part_rule_t::
27  
relative_part_rule_t::
28  
parse(
28  
parse(
29  
    char const*& it,
29  
    char const*& it,
30  
    char const* const end
30  
    char const* const end
31  
        ) const noexcept ->
31  
        ) const noexcept ->
32  
    system::result<value_type>
32  
    system::result<value_type>
33  
{
33  
{
34  
    constexpr auto pchars_nc = pchars - ':';
34  
    constexpr auto pchars_nc = pchars - ':';
35  

35  

36  
    value_type t;
36  
    value_type t;
37  
    if(it == end)
37  
    if(it == end)
38  
    {
38  
    {
39  
        // path-empty
39  
        // path-empty
40  
        return t;
40  
        return t;
41  
    }
41  
    }
42  
    if(end - it == 1)
42  
    if(end - it == 1)
43  
    {
43  
    {
44  
        if(*it == '/')
44  
        if(*it == '/')
45  
        {
45  
        {
46  
            // path-absolute
46  
            // path-absolute
47  
            t.path = make_pct_string_view_unsafe(
47  
            t.path = make_pct_string_view_unsafe(
48  
                it, 1, 1);
48  
                it, 1, 1);
49  
            t.segment_count = 1;
49  
            t.segment_count = 1;
50  
            ++it;
50  
            ++it;
51  
            return t;
51  
            return t;
52  
        }
52  
        }
53  
        if(*it != ':')
53  
        if(*it != ':')
54  
        {
54  
        {
55  
            // path-noscheme or
55  
            // path-noscheme or
56  
            // path-empty
56  
            // path-empty
57  
            auto rv = grammar::parse(
57  
            auto rv = grammar::parse(
58  
                it, end, segment_rule);
58  
                it, end, segment_rule);
59  
            if(! rv)
59  
            if(! rv)
60  
                return rv.error();
60  
                return rv.error();
61  
            if(! rv->empty())
61  
            if(! rv->empty())
62  
            {
62  
            {
63  
                t.path = *rv;
63  
                t.path = *rv;
64  
                t.segment_count = 1;
64  
                t.segment_count = 1;
65  
            }
65  
            }
66  
        }
66  
        }
67  
        // path-empty
67  
        // path-empty
68  
        return t;
68  
        return t;
69  
    }
69  
    }
70  
    if( it[0] == '/' &&
70  
    if( it[0] == '/' &&
71  
        it[1] == '/')
71  
        it[1] == '/')
72  
    {
72  
    {
73  
        // "//" authority
73  
        // "//" authority
74  
        it += 2;
74  
        it += 2;
75  
        auto rv = grammar::parse(
75  
        auto rv = grammar::parse(
76  
            it, end, authority_rule);
76  
            it, end, authority_rule);
77  
        if(! rv)
77  
        if(! rv)
78  
            return rv.error();
78  
            return rv.error();
79  
        t.authority = *rv;
79  
        t.authority = *rv;
80  
        t.has_authority = true;
80  
        t.has_authority = true;
81  
    }
81  
    }
82  
    if(it == end)
82  
    if(it == end)
83  
    {
83  
    {
84  
        // path-empty
84  
        // path-empty
85  
        return t;
85  
        return t;
86  
    }
86  
    }
87  
    auto const it0 = it;
87  
    auto const it0 = it;
88  
    std::size_t dn = 0;
88  
    std::size_t dn = 0;
89  
    if(*it != '/')
89  
    if(*it != '/')
90  
    {
90  
    {
91  
        // segment_nc
91  
        // segment_nc
92  
        auto rv = grammar::parse(it, end,
92  
        auto rv = grammar::parse(it, end,
93  
            pct_encoded_rule(pchars_nc));
93  
            pct_encoded_rule(pchars_nc));
94  
        if(! rv)
94  
        if(! rv)
95  
            return rv.error();
95  
            return rv.error();
96  
        if(rv->empty())
96  
        if(rv->empty())
97  
            return t;
97  
            return t;
98  
        dn += rv->decoded_size();
98  
        dn += rv->decoded_size();
99  
        ++t.segment_count;
99  
        ++t.segment_count;
100  
        if( it != end &&
100  
        if( it != end &&
101  
            *it == ':')
101  
            *it == ':')
102  
        {
102  
        {
103  
            BOOST_URL_CONSTEXPR_RETURN_EC(
103  
            BOOST_URL_CONSTEXPR_RETURN_EC(
104  
                grammar::error::mismatch);
104  
                grammar::error::mismatch);
105  
        }
105  
        }
106  
    }
106  
    }
107  
    while(it != end)
107  
    while(it != end)
108  
    {
108  
    {
109  
        if(*it == '/')
109  
        if(*it == '/')
110  
        {
110  
        {
111  
            ++dn;
111  
            ++dn;
112  
            ++it;
112  
            ++it;
113  
            ++t.segment_count;
113  
            ++t.segment_count;
114  
            continue;
114  
            continue;
115  
        }
115  
        }
116  
        auto rv = grammar::parse(
116  
        auto rv = grammar::parse(
117  
            it, end, segment_rule);
117  
            it, end, segment_rule);
118  
        if(! rv)
118  
        if(! rv)
119  
            return rv.error();
119  
            return rv.error();
120  
        if(rv->empty())
120  
        if(rv->empty())
121  
            break;
121  
            break;
122  
        dn += rv->decoded_size();
122  
        dn += rv->decoded_size();
123  
    }
123  
    }
124  
    t.path = make_pct_string_view_unsafe(
124  
    t.path = make_pct_string_view_unsafe(
125  
        it0, it - it0, dn);
125  
        it0, it - it0, dn);
126  
    return t;
126  
    return t;
127  
}
127  
}
128  

128  

129  
} // detail
129  
} // detail
130  
} // urls
130  
} // urls
131  
} // boost
131  
} // boost
132  

132  

133  

133  

134  
#endif
134  
#endif