1  
//
1  
//
2  
// Copyright (c) 2021 Vinnie Falco (vinnie.falco@gmail.com)
2  
// Copyright (c) 2021 Vinnie Falco (vinnie.falco@gmail.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/cppalliance/http
7  
// Official repository: https://github.com/cppalliance/http
8  
//
8  
//
9  

9  

10  
#include <boost/http/rfc/quoted_token_rule.hpp>
10  
#include <boost/http/rfc/quoted_token_rule.hpp>
11  
#include <boost/http/rfc/token_rule.hpp>
11  
#include <boost/http/rfc/token_rule.hpp>
12  
#include <boost/url/grammar/charset.hpp>
12  
#include <boost/url/grammar/charset.hpp>
13  
#include <boost/url/grammar/error.hpp>
13  
#include <boost/url/grammar/error.hpp>
14  
#include <boost/url/grammar/lut_chars.hpp>
14  
#include <boost/url/grammar/lut_chars.hpp>
15  
#include <boost/url/grammar/parse.hpp>
15  
#include <boost/url/grammar/parse.hpp>
16  
#include <boost/url/grammar/vchars.hpp>
16  
#include <boost/url/grammar/vchars.hpp>
17  

17  

18  
namespace boost {
18  
namespace boost {
19  
namespace http {
19  
namespace http {
20  

20  

21  
namespace {
21  
namespace {
22  

22  

23  
struct obs_text
23  
struct obs_text
24  
{
24  
{
25  
    constexpr
25  
    constexpr
26  
    bool
26  
    bool
27  
    operator()(char ch) const noexcept
27  
    operator()(char ch) const noexcept
28  
    {
28  
    {
29  
        return static_cast<
29  
        return static_cast<
30  
            unsigned char>(ch) >= 0x80;
30  
            unsigned char>(ch) >= 0x80;
31  
    }
31  
    }
32  
};
32  
};
33  

33  

34  
struct qdtext
34  
struct qdtext
35  
{
35  
{
36  
    constexpr
36  
    constexpr
37  
    bool
37  
    bool
38  
    operator()(char ch) const noexcept
38  
    operator()(char ch) const noexcept
39  
    {
39  
    {
40  
        return
40  
        return
41  
            ch == '\t' ||
41  
            ch == '\t' ||
42  
            ch == ' ' ||
42  
            ch == ' ' ||
43  
            ch == 0x21 ||
43  
            ch == 0x21 ||
44  
            (ch >= 0x23 && ch <= 0x5b) ||
44  
            (ch >= 0x23 && ch <= 0x5b) ||
45  
            (ch >= 0x5d && ch <= 0x7e) ||
45  
            (ch >= 0x5d && ch <= 0x7e) ||
46  
            static_cast<unsigned char>(ch) >= 0x80;
46  
            static_cast<unsigned char>(ch) >= 0x80;
47  
    }
47  
    }
48  
};
48  
};
49  

49  

50  
// qdtext  = HTAB / SP /%x21 / %x23-5B / %x5D-7E / obs-text
50  
// qdtext  = HTAB / SP /%x21 / %x23-5B / %x5D-7E / obs-text
51  
constexpr grammar::lut_chars qdtext_chars(qdtext{});
51  
constexpr grammar::lut_chars qdtext_chars(qdtext{});
52  

52  

53  
// qpchars = ( HTAB / SP / VCHAR / obs-text )
53  
// qpchars = ( HTAB / SP / VCHAR / obs-text )
54  
constexpr auto qpchars =
54  
constexpr auto qpchars =
55  
    grammar::lut_chars(grammar::vchars) +
55  
    grammar::lut_chars(grammar::vchars) +
56  
    grammar::lut_chars(obs_text{}) + '\t' + ' ';
56  
    grammar::lut_chars(obs_text{}) + '\t' + ' ';
57  

57  

58  
} // namespace
58  
} // namespace
59  

59  

60  

60  

61  
namespace implementation_defined {
61  
namespace implementation_defined {
62  
auto
62  
auto
63  
quoted_token_rule_t::
63  
quoted_token_rule_t::
64  
parse(
64  
parse(
65  
    char const*& it,
65  
    char const*& it,
66  
    char const* end) const noexcept ->
66  
    char const* end) const noexcept ->
67  
        system::result<value_type>
67  
        system::result<value_type>
68  
{
68  
{
69  
    if(it == end)
69  
    if(it == end)
70  
    {
70  
    {
71  
        BOOST_HTTP_RETURN_EC(
71  
        BOOST_HTTP_RETURN_EC(
72  
            grammar::error::need_more);
72  
            grammar::error::need_more);
73  
    }
73  
    }
74  
    if(*it != '\"')
74  
    if(*it != '\"')
75  
    {
75  
    {
76  
        // token
76  
        // token
77  
        auto rv = grammar::parse(
77  
        auto rv = grammar::parse(
78  
            it, end, token_rule);
78  
            it, end, token_rule);
79  
        if(rv.has_value())
79  
        if(rv.has_value())
80  
            return quoted_token_view(*rv);
80  
            return quoted_token_view(*rv);
81  
        return rv.error();
81  
        return rv.error();
82  
    }
82  
    }
83  
    // quoted-string
83  
    // quoted-string
84  
    auto const it0 = it++;
84  
    auto const it0 = it++;
85  
    std::size_t n = 0;
85  
    std::size_t n = 0;
86  
    for(;;)
86  
    for(;;)
87  
    {
87  
    {
88  
        auto it1 = it;
88  
        auto it1 = it;
89  
        it = grammar::find_if_not(
89  
        it = grammar::find_if_not(
90  
            it, end, qdtext_chars);
90  
            it, end, qdtext_chars);
91  
        if(it == end)
91  
        if(it == end)
92  
        {
92  
        {
93  
            BOOST_HTTP_RETURN_EC(
93  
            BOOST_HTTP_RETURN_EC(
94  
                grammar::error::need_more);
94  
                grammar::error::need_more);
95  
        }
95  
        }
96  
        n += static_cast<std::size_t>(it - it1);
96  
        n += static_cast<std::size_t>(it - it1);
97  
        if(*it == '\"')
97  
        if(*it == '\"')
98  
            break;
98  
            break;
99  
        if(*it != '\\')
99  
        if(*it != '\\')
100  
        {
100  
        {
101  
            BOOST_HTTP_RETURN_EC(
101  
            BOOST_HTTP_RETURN_EC(
102  
                grammar::error::syntax);
102  
                grammar::error::syntax);
103  
        }
103  
        }
104  
        ++it;
104  
        ++it;
105  
        if(it == end)
105  
        if(it == end)
106  
        {
106  
        {
107  
            BOOST_HTTP_RETURN_EC(
107  
            BOOST_HTTP_RETURN_EC(
108  
                grammar::error::need_more);
108  
                grammar::error::need_more);
109  
        }
109  
        }
110  
        if(! qpchars(*it))
110  
        if(! qpchars(*it))
111  
        {
111  
        {
112  
            BOOST_HTTP_RETURN_EC(
112  
            BOOST_HTTP_RETURN_EC(
113  
                grammar::error::syntax);
113  
                grammar::error::syntax);
114  
        }
114  
        }
115  
        ++it;
115  
        ++it;
116  
        ++n;
116  
        ++n;
117  
    }
117  
    }
118  
    return value_type(core::string_view(
118  
    return value_type(core::string_view(
119  
        it0, ++it - it0), n);
119  
        it0, ++it - it0), n);
120  
}
120  
}
121  

121  

122  
} // implementation_defined
122  
} // implementation_defined
123  
} // http
123  
} // http
124  
} // boost
124  
} // boost