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  
//
3  
//
4  
// Distributed under the Boost Software License, Version 1.0. (See accompanying
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)
5  
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
6  
//
6  
//
7  
// Official repository: https://github.com/boostorg/url
7  
// Official repository: https://github.com/boostorg/url
8  
//
8  
//
9  

9  

10  

10  

11  
#include <boost/url/detail/config.hpp>
11  
#include <boost/url/detail/config.hpp>
12  
#include "hier_part_rule.hpp"
12  
#include "hier_part_rule.hpp"
13  
#include "boost/url/rfc/detail/path_rules.hpp"
13  
#include "boost/url/rfc/detail/path_rules.hpp"
14  
#include <boost/url/grammar/parse.hpp>
14  
#include <boost/url/grammar/parse.hpp>
15  
#include <boost/url/grammar/parse.hpp>
15  
#include <boost/url/grammar/parse.hpp>
16  

16  

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

20  

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

112  

113  
} // detail
113  
} // detail
114  
} // urls
114  
} // urls
115  
} // boost
115  
} // boost
116  

116