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

10  

11  
#include "src/rfc/detail/transfer_coding_rule.hpp"
11  
#include "src/rfc/detail/transfer_coding_rule.hpp"
12  

12  

13  
#include <boost/http/rfc/detail/ws.hpp>
13  
#include <boost/http/rfc/detail/ws.hpp>
14  
#include <boost/http/rfc/quoted_token_rule.hpp>
14  
#include <boost/http/rfc/quoted_token_rule.hpp>
15  
#include <boost/http/rfc/token_rule.hpp>
15  
#include <boost/http/rfc/token_rule.hpp>
16  
#include <boost/url/grammar/ci_string.hpp>
16  
#include <boost/url/grammar/ci_string.hpp>
17  
#include <boost/url/grammar/parse.hpp>
17  
#include <boost/url/grammar/parse.hpp>
18  

18  

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

22  

23  
auto
23  
auto
24  
transfer_parameter_rule_t::parse(
24  
transfer_parameter_rule_t::parse(
25  
    char const*& it,
25  
    char const*& it,
26  
    char const* end) const noexcept ->
26  
    char const* end) const noexcept ->
27  
        system::result<value_type>
27  
        system::result<value_type>
28  
{
28  
{
29  
    value_type t;
29  
    value_type t;
30  
    auto it0 = it;
30  
    auto it0 = it;
31  
    // OWS
31  
    // OWS
32  
    it = grammar::find_if_not(
32  
    it = grammar::find_if_not(
33  
        it, end, ws);
33  
        it, end, ws);
34  
    // ";"
34  
    // ";"
35  
    if(it == end)
35  
    if(it == end)
36  
    {
36  
    {
37  
        it = it0;
37  
        it = it0;
38  
        BOOST_HTTP_RETURN_EC(
38  
        BOOST_HTTP_RETURN_EC(
39  
            grammar::error::need_more);
39  
            grammar::error::need_more);
40  
    }
40  
    }
41  
    if(*it != ';')
41  
    if(*it != ';')
42  
    {
42  
    {
43  
        it = it0;
43  
        it = it0;
44  
        BOOST_HTTP_RETURN_EC(
44  
        BOOST_HTTP_RETURN_EC(
45  
            grammar::error::mismatch);
45  
            grammar::error::mismatch);
46  
    }
46  
    }
47  
    ++it;
47  
    ++it;
48  
    // OWS
48  
    // OWS
49  
    it = grammar::find_if_not(
49  
    it = grammar::find_if_not(
50  
        it, end, ws);
50  
        it, end, ws);
51  
    // token
51  
    // token
52  
    {
52  
    {
53  
        auto rv = grammar::parse(
53  
        auto rv = grammar::parse(
54  
            it, end, token_rule);
54  
            it, end, token_rule);
55  
        if(! rv)
55  
        if(! rv)
56  
            return rv.error();
56  
            return rv.error();
57  
        t.name = *rv;
57  
        t.name = *rv;
58  
    }
58  
    }
59  
    // BWS
59  
    // BWS
60  
    it = grammar::find_if_not(
60  
    it = grammar::find_if_not(
61  
        it, end, ws);
61  
        it, end, ws);
62  
    // "="
62  
    // "="
63  
    if(it == end)
63  
    if(it == end)
64  
    {
64  
    {
65  
        it = it0;
65  
        it = it0;
66  
        BOOST_HTTP_RETURN_EC(
66  
        BOOST_HTTP_RETURN_EC(
67  
            grammar::error::need_more);
67  
            grammar::error::need_more);
68  
    }
68  
    }
69  
    if(*it != '=')
69  
    if(*it != '=')
70  
    {
70  
    {
71  
        it = it0;
71  
        it = it0;
72  
        BOOST_HTTP_RETURN_EC(
72  
        BOOST_HTTP_RETURN_EC(
73  
            grammar::error::syntax);
73  
            grammar::error::syntax);
74  
    }
74  
    }
75  
    ++it;
75  
    ++it;
76  
    // BWS
76  
    // BWS
77  
    it = grammar::find_if_not(
77  
    it = grammar::find_if_not(
78  
        it, end, ws);
78  
        it, end, ws);
79  
    // quoted-token
79  
    // quoted-token
80  
    {
80  
    {
81  
        auto rv = grammar::parse(
81  
        auto rv = grammar::parse(
82  
            it, end, quoted_token_rule);
82  
            it, end, quoted_token_rule);
83  
        if(! rv)
83  
        if(! rv)
84  
            return rv.error();
84  
            return rv.error();
85  
        t.value = *rv;
85  
        t.value = *rv;
86  
    }
86  
    }
87  
    return t;
87  
    return t;
88  
}
88  
}
89  

89  

90  
//------------------------------------------------
90  
//------------------------------------------------
91  

91  

92  
auto
92  
auto
93  
transfer_coding_rule_t::
93  
transfer_coding_rule_t::
94  
parse(
94  
parse(
95  
    char const*& it,
95  
    char const*& it,
96  
    char const* end) const noexcept ->
96  
    char const* end) const noexcept ->
97  
        system::result<value_type>
97  
        system::result<value_type>
98  
{
98  
{
99  
    value_type t;
99  
    value_type t;
100  
    {
100  
    {
101  
        // token
101  
        // token
102  
        auto rv = grammar::parse(
102  
        auto rv = grammar::parse(
103  
            it, end, token_rule);
103  
            it, end, token_rule);
104  
        if(! rv)
104  
        if(! rv)
105  
            return rv.error();
105  
            return rv.error();
106  

106  

107  
        // These can't have transfer-parameter
107  
        // These can't have transfer-parameter
108  
        if(grammar::ci_is_equal(
108  
        if(grammar::ci_is_equal(
109  
            *rv, "chunked"))
109  
            *rv, "chunked"))
110  
        {
110  
        {
111  
            t.id = coding::chunked;
111  
            t.id = coding::chunked;
112  
            return t;
112  
            return t;
113  
        }
113  
        }
114  
        if(grammar::ci_is_equal(
114  
        if(grammar::ci_is_equal(
115  
            *rv, "compress"))
115  
            *rv, "compress"))
116  
        {
116  
        {
117  
            t.id = coding::compress;
117  
            t.id = coding::compress;
118  
            return t;
118  
            return t;
119  
        }
119  
        }
120  
        if(grammar::ci_is_equal(
120  
        if(grammar::ci_is_equal(
121  
            *rv, "deflate"))
121  
            *rv, "deflate"))
122  
        {
122  
        {
123  
            t.id = coding::deflate;
123  
            t.id = coding::deflate;
124  
            return t;
124  
            return t;
125  
        }
125  
        }
126  
        if(grammar::ci_is_equal(
126  
        if(grammar::ci_is_equal(
127  
            *rv, "gzip"))
127  
            *rv, "gzip"))
128  
        {
128  
        {
129  
            t.id = coding::gzip;
129  
            t.id = coding::gzip;
130  
            return t;
130  
            return t;
131  
        }
131  
        }
132  

132  

133  
        t.extension.token = *rv;
133  
        t.extension.token = *rv;
134  
    }
134  
    }
135  
    // transfer-extension = token *( OWS ";" OWS transfer-parameter )
135  
    // transfer-extension = token *( OWS ";" OWS transfer-parameter )
136  
    {
136  
    {
137  
        auto rv = grammar::parse(it, end,
137  
        auto rv = grammar::parse(it, end,
138  
            grammar::range_rule(
138  
            grammar::range_rule(
139  
                detail::transfer_parameter_rule));
139  
                detail::transfer_parameter_rule));
140  
        if(! rv)
140  
        if(! rv)
141  
            return rv.error();
141  
            return rv.error();
142  
        t.extension.params = std::move(*rv);
142  
        t.extension.params = std::move(*rv);
143  
    }
143  
    }
144  
    return t;
144  
    return t;
145  
}
145  
}
146  

146  

147  
} // detail
147  
} // detail
148  
} // http
148  
} // http
149  
} // boost
149  
} // boost