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_PORT_RULE_HPP
11  
#ifndef BOOST_URL_RFC_DETAIL_IMPL_PORT_RULE_HPP
12  
#define BOOST_URL_RFC_DETAIL_IMPL_PORT_RULE_HPP
12  
#define BOOST_URL_RFC_DETAIL_IMPL_PORT_RULE_HPP
13  

13  

14  
#include <boost/url/detail/config.hpp>
14  
#include <boost/url/detail/config.hpp>
15  
#include <boost/url/grammar/digit_chars.hpp>
15  
#include <boost/url/grammar/digit_chars.hpp>
16  
#include <boost/url/grammar/parse.hpp>
16  
#include <boost/url/grammar/parse.hpp>
17  
#include <boost/url/grammar/unsigned_rule.hpp>
17  
#include <boost/url/grammar/unsigned_rule.hpp>
18  

18  

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

22  

23  
BOOST_URL_CXX20_CONSTEXPR_OR_INLINE
23  
BOOST_URL_CXX20_CONSTEXPR_OR_INLINE
24  
auto
24  
auto
25  
port_rule::
25  
port_rule::
26  
parse(
26  
parse(
27  
    char const*& it,
27  
    char const*& it,
28  
    char const* end) const noexcept ->
28  
    char const* end) const noexcept ->
29  
        system::result<value_type>
29  
        system::result<value_type>
30  
{
30  
{
31  
    value_type t;
31  
    value_type t;
32  
    auto const start = it;
32  
    auto const start = it;
33  
    while(
33  
    while(
34  
        it != end &&
34  
        it != end &&
35  
        *it == '0')
35  
        *it == '0')
36  
    {
36  
    {
37  
        ++it;
37  
        ++it;
38  
    }
38  
    }
39  

39  

40  
    if (it != end)
40  
    if (it != end)
41  
    {
41  
    {
42  
        grammar::unsigned_rule<std::uint16_t> r;
42  
        grammar::unsigned_rule<std::uint16_t> r;
43  
        auto it0 = it;
43  
        auto it0 = it;
44  
        auto rv = r.parse(it, end);
44  
        auto rv = r.parse(it, end);
45  
        if (rv)
45  
        if (rv)
46  
        {
46  
        {
47  
            // number < max uint16_t
47  
            // number < max uint16_t
48  
            t.str = core::string_view(start, it);
48  
            t.str = core::string_view(start, it);
49  
            t.has_number = true;
49  
            t.has_number = true;
50  
            t.number = *rv;
50  
            t.number = *rv;
51  
            return t;
51  
            return t;
52  
        }
52  
        }
53  
        it = it0;
53  
        it = it0;
54  
        if (grammar::digit_chars(*it))
54  
        if (grammar::digit_chars(*it))
55  
        {
55  
        {
56  
            // number > max uint16_t
56  
            // number > max uint16_t
57  
            while (
57  
            while (
58  
                it != end &&
58  
                it != end &&
59  
                grammar::digit_chars(*it))
59  
                grammar::digit_chars(*it))
60  
            {
60  
            {
61  
                ++it;
61  
                ++it;
62  
            }
62  
            }
63  
            t.str = core::string_view(start, it);
63  
            t.str = core::string_view(start, it);
64  
            t.has_number = true;
64  
            t.has_number = true;
65  
            t.number = 0;
65  
            t.number = 0;
66  
            return t;
66  
            return t;
67  
        }
67  
        }
68  
    }
68  
    }
69  
    // no digits
69  
    // no digits
70  
    t.str = core::string_view(start, it);
70  
    t.str = core::string_view(start, it);
71  
    t.has_number = it != end;
71  
    t.has_number = it != end;
72  
    t.number = 0;
72  
    t.number = 0;
73  
    return t;
73  
    return t;
74  
}
74  
}
75  

75  

76  
BOOST_URL_CXX20_CONSTEXPR_OR_INLINE
76  
BOOST_URL_CXX20_CONSTEXPR_OR_INLINE
77  
auto
77  
auto
78  
port_part_rule_t::
78  
port_part_rule_t::
79  
parse(
79  
parse(
80  
    char const*& it,
80  
    char const*& it,
81  
    char const* end) const noexcept ->
81  
    char const* end) const noexcept ->
82  
        system::result<value_type>
82  
        system::result<value_type>
83  
{
83  
{
84  
    value_type t;
84  
    value_type t;
85  
    if( it == end ||
85  
    if( it == end ||
86  
        *it != ':')
86  
        *it != ':')
87  
    {
87  
    {
88  
        t.has_port = false;
88  
        t.has_port = false;
89  
        return t;
89  
        return t;
90  
    }
90  
    }
91  
    ++it;
91  
    ++it;
92  
    auto rv = grammar::parse(
92  
    auto rv = grammar::parse(
93  
        it, end, port_rule{});
93  
        it, end, port_rule{});
94  
    if(! rv)
94  
    if(! rv)
95  
        return rv.error();
95  
        return rv.error();
96  
    t.has_port = true;
96  
    t.has_port = true;
97  
    t.port = rv->str;
97  
    t.port = rv->str;
98  
    t.has_number = rv->has_number;
98  
    t.has_number = rv->has_number;
99  
    t.port_number = rv->number;
99  
    t.port_number = rv->number;
100  
    return t;
100  
    return t;
101  
}
101  
}
102  

102  

103  
} // detail
103  
} // detail
104  
} // urls
104  
} // urls
105  
} // boost
105  
} // boost
106  

106  

107  

107  

108  
#endif
108  
#endif