1 +
//
 
2 +
// Copyright (c) 2016-2019 Vinnie Falco (vinnie dot falco at gmail dot com)
 
3 +
// Copyright (c) 2023 Alan de Freitas (alandefreitas@gmail.com)
 
4 +
//
 
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)
 
7 +
//
 
8 +
// Official repository: https://github.com/boostorg/url
 
9 +
//
 
10 +

 
11 +
#ifndef BOOST_URL_RFC_DETAIL_QUERY_PART_RULE_HPP
 
12 +
#define BOOST_URL_RFC_DETAIL_QUERY_PART_RULE_HPP
 
13 +

 
14 +
#include "boost/url/detail/config.hpp"
 
15 +
#include "boost/url/error_types.hpp"
 
16 +
#include "boost/url/pct_string_view.hpp"
 
17 +
#include <boost/url/rfc/detail/charsets.hpp>
 
18 +
#include <boost/url/grammar/hexdig_chars.hpp>
 
19 +
#include <cstdlib>
 
20 +

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

 
25 +
/** Rule for query-part
 
26 +

 
27 +
    @par BNF
 
28 +
    @code
 
29 +
    query-part    = [ "?" query ]
 
30 +
    @endcode
 
31 +
*/
 
32 +
struct query_part_rule_t
 
33 +
{
 
34 +
    struct value_type
 
35 +
    {
 
36 +
        pct_string_view query;
 
37 +
        std::size_t count = 0;
 
38 +
        bool has_query = false;
 
39 +
    };
 
40 +

 
41 +
    BOOST_URL_CXX14_CONSTEXPR
 
42 +
    auto
 
43 +
    parse(
 
44 +
        char const*& it,
 
45 +
        char const* end
 
46 +
            ) const noexcept ->
 
47 +
        system::result<value_type>
 
48 +
    {
 
49 +
        if( it == end ||
 
50 +
            *it != '?')
 
51 +
            return {};
 
52 +
        ++it;
 
53 +
        auto const it0 = it;
 
54 +
        std::size_t dn = 0;
 
55 +
        std::size_t nparam = 1;
 
56 +
        while(it != end)
 
57 +
        {
 
58 +
            if(*it == '&')
 
59 +
            {
 
60 +
                ++nparam;
 
61 +
                ++it;
 
62 +
                continue;
 
63 +
            }
 
64 +
            if(detail::query_chars(*it))
 
65 +
            {
 
66 +
                ++it;
 
67 +
                continue;
 
68 +
            }
 
69 +
            if(*it == '%')
 
70 +
            {
 
71 +
                if(end - it < 3 ||
 
72 +
                    (!grammar::hexdig_chars(it[1]) ||
 
73 +
                     !grammar::hexdig_chars(it[2])))
 
74 +
                    break;
 
75 +
                it += 3;
 
76 +
                dn += 2;
 
77 +
                continue;
 
78 +
            }
 
79 +
            break;
 
80 +
        }
 
81 +
        std::size_t const n(it - it0);
 
82 +
        value_type t;
 
83 +
        t.query = make_pct_string_view_unsafe(
 
84 +
            it0, n, n - dn);
 
85 +
        t.count = nparam;
 
86 +
        t.has_query = true;
 
87 +
        return t;
 
88 +
    }
 
89 +
};
 
90 +

 
91 +
constexpr query_part_rule_t query_part_rule{};
 
92 +

 
93 +
} // detail
 
94 +
} // urls
 
95 +
} // boost
 
96 +

 
97 +
#endif