• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1//
2// Copyright (c) 2016-2019 Vinnie Falco (vinnie dot falco at gmail dot com)
3//
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)
6//
7// Official repository: https://github.com/boostorg/beast
8//
9
10#ifndef BOOST_BEAST_HTTP_IMPL_FIELDS_IPP
11#define BOOST_BEAST_HTTP_IMPL_FIELDS_IPP
12
13#include <boost/beast/http/fields.hpp>
14
15namespace boost {
16namespace beast {
17namespace http {
18namespace detail {
19
20// `basic_fields` assumes that `std::size_t` is larger than `uint16_t`, so we
21// verify it explicitly here, so that users that use split compilation don't
22// need to pay the (fairly small) price for this sanity check
23BOOST_STATIC_ASSERT((std::numeric_limits<std::size_t>::max)() >=
24    (std::numeric_limits<std::uint32_t>::max)());
25
26// Filter a token list
27//
28inline
29void
30filter_token_list(
31    beast::detail::temporary_buffer& s,
32    string_view value,
33    iequals_predicate const& pred)
34{
35    token_list te{value};
36    auto it = te.begin();
37    auto last = te.end();
38    if(it == last)
39        return;
40    while(pred(*it))
41        if(++it == last)
42            return;
43    s.append(*it);
44    while(++it != last)
45    {
46        if(! pred(*it))
47        {
48            s.append(", ", *it);
49        }
50    }
51}
52
53void
54filter_token_list_last(
55    beast::detail::temporary_buffer& s,
56    string_view value,
57    iequals_predicate const& pred)
58{
59    token_list te{value};
60    if(te.begin() != te.end())
61    {
62        auto it = te.begin();
63        auto next = std::next(it);
64        if(next == te.end())
65        {
66            if(! pred(*it))
67                s.append(*it);
68            return;
69        }
70        s.append(*it);
71        for(;;)
72        {
73            it = next;
74            next = std::next(it);
75            if(next == te.end())
76            {
77                if(! pred(*it))
78                {
79                    s.append(", ", *it);
80                }
81                return;
82            }
83            s.append(", ", *it);
84        }
85    }
86}
87
88void
89keep_alive_impl(
90    beast::detail::temporary_buffer& s, string_view value,
91    unsigned version, bool keep_alive)
92{
93    if(version < 11)
94    {
95        if(keep_alive)
96        {
97            // remove close
98            filter_token_list(s, value, iequals_predicate{"close", {}});
99            // add keep-alive
100            if(s.empty())
101                s.append("keep-alive");
102            else if(! token_list{value}.exists("keep-alive"))
103                s.append(", keep-alive");
104        }
105        else
106        {
107            // remove close and keep-alive
108            filter_token_list(s, value,
109                iequals_predicate{"close", "keep-alive"});
110        }
111    }
112    else
113    {
114        if(keep_alive)
115        {
116            // remove close and keep-alive
117            filter_token_list(s, value,
118                iequals_predicate{"close", "keep-alive"});
119        }
120        else
121        {
122            // remove keep-alive
123            filter_token_list(s, value, iequals_predicate{"keep-alive", {}});
124            // add close
125            if(s.empty())
126                s.append("close");
127            else if(! token_list{value}.exists("close"))
128                s.append(", close");
129        }
130    }
131}
132
133} // detail
134} // http
135} // beast
136} // boost
137
138#endif // BOOST_BEAST_HTTP_IMPL_FIELDS_IPP
139