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 <boost/url/rfc/ipv4_address_rule.hpp>
12  
#include <boost/url/rfc/ipv4_address_rule.hpp>
13  
#include "host_rule.hpp"
13  
#include "host_rule.hpp"
14  
#include "ip_literal_rule.hpp"
14  
#include "ip_literal_rule.hpp"
15  
#include "reg_name_rule.hpp"
15  
#include "reg_name_rule.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  
auto
22  
auto
23  
host_rule_t::
23  
host_rule_t::
24  
parse(
24  
parse(
25  
    char const*& it,
25  
    char const*& it,
26  
    char const* const end
26  
    char const* const end
27  
        ) const noexcept ->
27  
        ) const noexcept ->
28  
    system::result<value_type>
28  
    system::result<value_type>
29  
{
29  
{
30  
    value_type t;
30  
    value_type t;
31  

31  

32  
    if(it == end)
32  
    if(it == end)
33  
    {
33  
    {
34  
        // empty host
34  
        // empty host
35  
        t.host_type =
35  
        t.host_type =
36  
            urls::host_type::name;
36  
            urls::host_type::name;
37  
        return t;
37  
        return t;
38  
    }
38  
    }
39  

39  

40  
    auto const it0 = it;
40  
    auto const it0 = it;
41  
    if(*it == '[')
41  
    if(*it == '[')
42  
    {
42  
    {
43  
        // IP-literal
43  
        // IP-literal
44  
        auto rv = grammar::parse(
44  
        auto rv = grammar::parse(
45  
            it, end,
45  
            it, end,
46  
            detail::ip_literal_rule);
46  
            detail::ip_literal_rule);
47  
        if(! rv)
47  
        if(! rv)
48  
            return rv.error();
48  
            return rv.error();
49  
        auto v = *rv;
49  
        auto v = *rv;
50  
        if(v.is_ipv6)
50  
        if(v.is_ipv6)
51  
        {
51  
        {
52  
            // IPv6address
52  
            // IPv6address
53  
            auto const b =
53  
            auto const b =
54  
                v.ipv6.to_bytes();
54  
                v.ipv6.to_bytes();
55  
            std::memcpy(
55  
            std::memcpy(
56  
                t.addr,
56  
                t.addr,
57  
                b.data(),
57  
                b.data(),
58  
                b.size());
58  
                b.size());
59  
            t.host_type =
59  
            t.host_type =
60  
                urls::host_type::ipv6;
60  
                urls::host_type::ipv6;
61  
            t.match = core::string_view(
61  
            t.match = core::string_view(
62  
                it0, it - it0);
62  
                it0, it - it0);
63  
            return t;
63  
            return t;
64  
        }
64  
        }
65  

65  

66  
        // IPvFuture
66  
        // IPvFuture
67  
        t.host_type =
67  
        t.host_type =
68  
            urls::host_type::ipvfuture;
68  
            urls::host_type::ipvfuture;
69  
        t.match = core::string_view(
69  
        t.match = core::string_view(
70  
            it0, it - it0);
70  
            it0, it - it0);
71  
        return t;
71  
        return t;
72  
    }
72  
    }
73  

73  

74  
    // IPv4address
74  
    // IPv4address
75  
    {
75  
    {
76  
        auto rv = grammar::parse(
76  
        auto rv = grammar::parse(
77  
            it, end, ipv4_address_rule);
77  
            it, end, ipv4_address_rule);
78  
        if( rv )
78  
        if( rv )
79  
        {
79  
        {
80  
            auto it02 = it;
80  
            auto it02 = it;
81  
            auto rv2 = grammar::parse(
81  
            auto rv2 = grammar::parse(
82  
                it, end,
82  
                it, end,
83  
                detail::reg_name_rule);
83  
                detail::reg_name_rule);
84  
            if (rv2.has_value() &&
84  
            if (rv2.has_value() &&
85  
                !rv2->empty())
85  
                !rv2->empty())
86  
            {
86  
            {
87  
                t.name = core::string_view(
87  
                t.name = core::string_view(
88  
                    it0, it - it0);
88  
                    it0, it - it0);
89  
                t.host_type =
89  
                t.host_type =
90  
                    urls::host_type::name;
90  
                    urls::host_type::name;
91  
                t.match = core::string_view(
91  
                t.match = core::string_view(
92  
                    it0, it - it0);
92  
                    it0, it - it0);
93  
                return t;
93  
                return t;
94  
            }
94  
            }
95  
            it = it02;
95  
            it = it02;
96  
            auto const b =
96  
            auto const b =
97  
                rv->to_bytes();
97  
                rv->to_bytes();
98  
            std::memcpy(
98  
            std::memcpy(
99  
                t.addr,
99  
                t.addr,
100  
                b.data(),
100  
                b.data(),
101  
                b.size());
101  
                b.size());
102  
            t.host_type =
102  
            t.host_type =
103  
                urls::host_type::ipv4;
103  
                urls::host_type::ipv4;
104  
            t.match = core::string_view(
104  
            t.match = core::string_view(
105  
                it0, it - it0);
105  
                it0, it - it0);
106  
            return t;
106  
            return t;
107  
        }
107  
        }
108  

108  

109  
        it = it0; // rewind
109  
        it = it0; // rewind
110  
    }
110  
    }
111  

111  

112  
    // reg-name
112  
    // reg-name
113  
    {
113  
    {
114  
        auto rv = grammar::parse(
114  
        auto rv = grammar::parse(
115  
            it, end,
115  
            it, end,
116  
            detail::reg_name_rule);
116  
            detail::reg_name_rule);
117  
        if(! rv)
117  
        if(! rv)
118  
            return rv.error();
118  
            return rv.error();
119  
        t.name = *rv;
119  
        t.name = *rv;
120  
        t.host_type =
120  
        t.host_type =
121  
            urls::host_type::name;
121  
            urls::host_type::name;
122  
        t.match = core::string_view(
122  
        t.match = core::string_view(
123  
            it0, it - it0);
123  
            it0, it - it0);
124  
        return t;
124  
        return t;
125  
    }
125  
    }
126  
}
126  
}
127  

127  

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

131