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_HIER_PART_RULE_HPP
11  
#ifndef BOOST_URL_RFC_DETAIL_IMPL_HIER_PART_RULE_HPP
12  
#define BOOST_URL_RFC_DETAIL_IMPL_HIER_PART_RULE_HPP
12  
#define BOOST_URL_RFC_DETAIL_IMPL_HIER_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/grammar/parse.hpp>
16  
#include <boost/url/grammar/parse.hpp>
17  

17  

18  
namespace boost {
18  
namespace boost {
19  
namespace urls {
19  
namespace urls {
20  
namespace detail {
20  
namespace detail {
21  

21  

22  
BOOST_URL_CXX20_CONSTEXPR_OR_INLINE
22  
BOOST_URL_CXX20_CONSTEXPR_OR_INLINE
23  
auto
23  
auto
24  
hier_part_rule_t::
24  
hier_part_rule_t::
25  
parse(
25  
parse(
26  
    char const*& it,
26  
    char const*& it,
27  
    char const* const end
27  
    char const* const end
28  
        ) const noexcept ->
28  
        ) const noexcept ->
29  
    system::result<value_type>
29  
    system::result<value_type>
30  
{
30  
{
31  
    value_type t;
31  
    value_type t;
32  
    if(it == end)
32  
    if(it == end)
33  
    {
33  
    {
34  
        // path-empty
34  
        // path-empty
35  
        return t;
35  
        return t;
36  
    }
36  
    }
37  
    if(end - it == 1)
37  
    if(end - it == 1)
38  
    {
38  
    {
39  
        if(*it == '/')
39  
        if(*it == '/')
40  
        {
40  
        {
41  
            // path-absolute
41  
            // path-absolute
42  
            t.path = make_pct_string_view_unsafe(
42  
            t.path = make_pct_string_view_unsafe(
43  
                it, 1, 1);
43  
                it, 1, 1);
44  
            t.segment_count = 1;
44  
            t.segment_count = 1;
45  
            ++it;
45  
            ++it;
46  
            return t;
46  
            return t;
47  
        }
47  
        }
48  
        // path-rootless
48  
        // path-rootless
49  
        auto rv = grammar::parse(
49  
        auto rv = grammar::parse(
50  
            it, end, segment_rule);
50  
            it, end, segment_rule);
51  
        if(! rv)
51  
        if(! rv)
52  
            return rv.error();
52  
            return rv.error();
53  
        t.path = *rv;
53  
        t.path = *rv;
54  
        t.segment_count = !t.path.empty();
54  
        t.segment_count = !t.path.empty();
55  
        return t;
55  
        return t;
56  
    }
56  
    }
57  
    if( it[0] == '/' &&
57  
    if( it[0] == '/' &&
58  
        it[1] == '/')
58  
        it[1] == '/')
59  
    {
59  
    {
60  
        // "//" authority
60  
        // "//" authority
61  
        it += 2;
61  
        it += 2;
62  
        auto rv = grammar::parse(
62  
        auto rv = grammar::parse(
63  
            it, end, authority_rule);
63  
            it, end, authority_rule);
64  
        if(! rv)
64  
        if(! rv)
65  
            return rv.error();
65  
            return rv.error();
66  
        t.authority = *rv;
66  
        t.authority = *rv;
67  
        t.has_authority = true;
67  
        t.has_authority = true;
68  
    }
68  
    }
69  
    // the authority requires an absolute path
69  
    // the authority requires an absolute path
70  
    // or an empty path
70  
    // or an empty path
71  
    if(it == end || (
71  
    if(it == end || (
72  
        t.has_authority && (
72  
        t.has_authority && (
73  
            *it != '/' &&
73  
            *it != '/' &&
74  
            *it != '?' &&
74  
            *it != '?' &&
75  
            *it != '#')))
75  
            *it != '#')))
76  
    {
76  
    {
77  
        // path-empty
77  
        // path-empty
78  
        return t;
78  
        return t;
79  
    }
79  
    }
80  
    auto const it0 = it;
80  
    auto const it0 = it;
81  
    std::size_t dn = 0;
81  
    std::size_t dn = 0;
82  
    if(*it != '/')
82  
    if(*it != '/')
83  
    {
83  
    {
84  
        auto rv = grammar::parse(
84  
        auto rv = grammar::parse(
85  
            it, end, segment_rule);
85  
            it, end, segment_rule);
86  
        if(! rv)
86  
        if(! rv)
87  
            return rv.error();
87  
            return rv.error();
88  
        if(rv->empty())
88  
        if(rv->empty())
89  
            return t;
89  
            return t;
90  
        dn += rv->decoded_size();
90  
        dn += rv->decoded_size();
91  
        ++t.segment_count;
91  
        ++t.segment_count;
92  
    }
92  
    }
93  
    while(it != end)
93  
    while(it != end)
94  
    {
94  
    {
95  
        if(*it == '/')
95  
        if(*it == '/')
96  
        {
96  
        {
97  
            ++dn;
97  
            ++dn;
98  
            ++it;
98  
            ++it;
99  
            ++t.segment_count;
99  
            ++t.segment_count;
100  
            continue;
100  
            continue;
101  
        }
101  
        }
102  
        auto rv = grammar::parse(
102  
        auto rv = grammar::parse(
103  
            it, end, segment_rule);
103  
            it, end, segment_rule);
104  
        if(! rv)
104  
        if(! rv)
105  
            return rv.error();
105  
            return rv.error();
106  
        if(rv->empty())
106  
        if(rv->empty())
107  
            break;
107  
            break;
108  
        dn += rv->decoded_size();
108  
        dn += rv->decoded_size();
109  
    }
109  
    }
110  
    t.path = make_pct_string_view_unsafe(
110  
    t.path = make_pct_string_view_unsafe(
111  
        it0, it - it0, dn);
111  
        it0, it - it0, dn);
112  
    return t;
112  
    return t;
113  
}
113  
}
114  

114  

115  
} // detail
115  
} // detail
116  
} // urls
116  
} // urls
117  
} // boost
117  
} // boost
118  

118  

119  

119  

120  
#endif
120  
#endif