Line data Source code
1 : //
2 : // Copyright (c) 2019 Vinnie Falco (vinnie.falco@gmail.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/cppalliance/http
8 : //
9 :
10 : // we need a pragma once for the circular includes required
11 : // clangd's intellisense
12 : #pragma once
13 :
14 : #ifndef BOOST_HTTP_IMPL_PARSER_HPP
15 : #define BOOST_HTTP_IMPL_PARSER_HPP
16 :
17 : #include <boost/http/parser.hpp>
18 : #include <boost/http/sink.hpp>
19 : #include <boost/http/detail/type_traits.hpp>
20 :
21 : namespace boost {
22 : namespace http {
23 : namespace detail {
24 :
25 : // A wrapper that provides reference semantics for dynamic buffers
26 : // while satisfying the dynamic_buffer concept
27 : template<class DynamicBuffer>
28 : class dynamic_buffer_ref
29 : {
30 : DynamicBuffer* p_;
31 :
32 : public:
33 : using const_buffers_type = typename DynamicBuffer::const_buffers_type;
34 : using mutable_buffers_type = typename DynamicBuffer::mutable_buffers_type;
35 :
36 : explicit
37 372 : dynamic_buffer_ref(DynamicBuffer& b) noexcept
38 372 : : p_(&b)
39 : {
40 372 : }
41 :
42 : std::size_t
43 54726 : size() const noexcept
44 : {
45 54726 : return p_->size();
46 : }
47 :
48 : std::size_t
49 36569 : max_size() const noexcept
50 : {
51 36569 : return p_->max_size();
52 : }
53 :
54 : std::size_t
55 18157 : capacity() const noexcept
56 : {
57 18157 : return p_->capacity();
58 : }
59 :
60 : const_buffers_type
61 18411 : data() const noexcept
62 : {
63 18411 : return p_->data();
64 : }
65 :
66 : mutable_buffers_type
67 18411 : prepare(std::size_t n)
68 : {
69 18411 : return p_->prepare(n);
70 : }
71 :
72 : void
73 18411 : commit(std::size_t n)
74 : {
75 18411 : p_->commit(n);
76 18411 : }
77 :
78 : void
79 0 : consume(std::size_t n)
80 : {
81 0 : p_->consume(n);
82 0 : }
83 : };
84 :
85 : } // detail
86 :
87 : template<class ElasticBuffer>
88 : typename std::enable_if<
89 : ! detail::is_reference_wrapper<
90 : ElasticBuffer>::value &&
91 : ! is_sink<ElasticBuffer>::value>::type
92 11 : parser::
93 : set_body(
94 : ElasticBuffer&& eb)
95 : {
96 : // If this goes off it means you are trying
97 : // to pass by lvalue reference. Use std::ref
98 : // instead.
99 : static_assert(
100 : ! std::is_reference<ElasticBuffer>::value,
101 : "Use std::ref instead of pass-by-reference");
102 :
103 : // Check ElasticBuffer type requirements
104 : static_assert(
105 : capy::is_dynamic_buffer<ElasticBuffer>::value,
106 : "Type requirements not met.");
107 :
108 : // body must not already be set
109 11 : if(is_body_set())
110 0 : detail::throw_logic_error();
111 :
112 : // headers must be complete
113 11 : if(! got_header())
114 0 : detail::throw_logic_error();
115 :
116 11 : auto& dyn = ws().emplace<
117 : capy::any_dynamic_buffer_impl<typename
118 : std::decay<ElasticBuffer>::type,
119 11 : buffers_N>>(std::forward<ElasticBuffer>(eb));
120 :
121 11 : set_body_impl(dyn);
122 11 : }
123 :
124 : template<class ElasticBuffer>
125 : void
126 372 : parser::
127 : set_body(
128 : std::reference_wrapper<ElasticBuffer> eb)
129 : {
130 : // Check ElasticBuffer type requirements
131 : static_assert(
132 : capy::is_dynamic_buffer<ElasticBuffer>::value,
133 : "Type requirements not met.");
134 :
135 : // body must not already be set
136 372 : if(is_body_set())
137 0 : detail::throw_logic_error();
138 :
139 : // headers must be complete
140 372 : if(! got_header())
141 0 : detail::throw_logic_error();
142 :
143 : // Use dynamic_buffer_ref to provide reference semantics
144 372 : auto& dyn = ws().emplace<
145 : capy::any_dynamic_buffer_impl<
146 : detail::dynamic_buffer_ref<ElasticBuffer>,
147 372 : buffers_N>>(eb.get());
148 :
149 372 : set_body_impl(dyn);
150 372 : }
151 :
152 : template<
153 : class Sink,
154 : class... Args,
155 : class>
156 : Sink&
157 372 : parser::
158 : set_body(Args&&... args)
159 : {
160 : // body must not already be set
161 372 : if(is_body_set())
162 0 : detail::throw_logic_error();
163 :
164 : // headers must be complete
165 372 : if(! got_header())
166 0 : detail::throw_logic_error();
167 :
168 372 : auto& s = ws().emplace<Sink>(
169 : std::forward<Args>(args)...);
170 :
171 372 : set_body_impl(s);
172 372 : return s;
173 : }
174 :
175 : } // http
176 : } // boost
177 :
178 : #endif
|