GCC Code Coverage Report


Directory: libs/http_proto/
File: boost/http_proto/detail/header.hpp
Date: 2024-07-25 21:11:05
Exec Total Coverage
Lines: 10 10 100.0%
Functions: 3 3 100.0%
Branches: 0 0 -%

Line Branch Exec Source
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_proto
8 //
9
10 #ifndef BOOST_HTTP_PROTO_DETAIL_HEADER_HPP
11 #define BOOST_HTTP_PROTO_DETAIL_HEADER_HPP
12
13 #include <boost/http_proto/detail/align_up.hpp>
14 #include <boost/http_proto/detail/config.hpp>
15 #include <boost/http_proto/error.hpp>
16 #include <boost/http_proto/field.hpp>
17 #include <boost/http_proto/metadata.hpp>
18 #include <boost/http_proto/method.hpp>
19 #include <boost/http_proto/status.hpp>
20 #include <boost/http_proto/version.hpp>
21 #include <boost/core/detail/string_view.hpp>
22 #include <boost/assert.hpp>
23 #include <cstdint>
24 #include <type_traits>
25
26 namespace boost {
27 namespace http_proto {
28
29 class fields_base;
30 struct header_limits;
31
32 namespace detail {
33
34 enum kind : unsigned char
35 {
36 fields = 0,
37 request,
38 response,
39 };
40
41 struct empty
42 {
43 kind param;
44 };
45
46 struct header
47 {
48 // this field lookup table is
49 // stored at the end of the
50 // allocated buffer, in
51 // reverse order.
52 struct entry
53 {
54 offset_type np; // name pos
55 offset_type nn; // name size
56 offset_type vp; // value pos
57 offset_type vn; // value size
58 field id;
59
60 entry operator+(
61 std::size_t dv) const noexcept;
62 entry operator-(
63 std::size_t dv) const noexcept;
64 };
65
66 // HTTP-message = start-line CRLF *( field-line CRLF ) CRLF
67 // start-line = request-line / status-line
68 // status-line = HTTP-version SP status-code SP [ reason-phrase ]
69 // status-code = 3DIGIT
70 // HTTP-name = %x48.54.54.50 ; HTTP
71 // HTTP-version = HTTP-name "/" DIGIT "." DIGIT
72 //
73 // => "HTTP/1.1 111 \r\n" + trailing "\r\n"
74 static
75 constexpr
76 std::size_t const min_status_line = 17;
77
78 // "X:\r\n"
79 static
80 constexpr
81 std::size_t const min_field_line = 4;
82
83 static
84 constexpr
85 std::size_t const max_field_lines =
86 (max_offset - min_status_line) / min_field_line;
87
88 /** Returns the largest permissible capacity in bytes
89 */
90 static
91 constexpr
92 std::size_t
93 3428 max_capacity_in_bytes() noexcept
94 {
95 // the entire serialized contents of the header
96 // must fit entirely in max_offset
97 3428 return align_up(
98 (max_offset + (max_field_lines * sizeof(entry))),
99 3428 alignof(entry));
100 }
101
102 struct table
103 {
104 explicit
105 5802 table(
106 void* end) noexcept
107 5802 : p_(reinterpret_cast<
108 entry*>(end))
109 {
110 5802 }
111
112 entry&
113 5832 operator[](
114 std::size_t i) const noexcept
115 {
116 5832 return p_[-1 * (
117 5832 static_cast<
118 5832 long>(i) + 1)];
119 }
120
121 private:
122 entry* p_;
123 };
124
125 struct fld_t
126 {
127 };
128
129 struct req_t
130 {
131 offset_type method_len;
132 offset_type target_len;
133 http_proto::method method;
134 };
135
136 struct res_t
137 {
138 unsigned short status_int;
139 http_proto::status status;
140 };
141
142 //--------------------------------------------
143
144 detail::kind kind;
145 char const* cbuf = nullptr;
146 char* buf = nullptr;
147 std::size_t cap = 0;
148 std::size_t max_cap = max_capacity_in_bytes();
149
150 offset_type size = 0;
151 offset_type count = 0;
152 offset_type prefix = 0;
153
154 http_proto::version version =
155 http_proto::version::http_1_1;
156 metadata md;
157
158 union
159 {
160 fld_t fld;
161 req_t req;
162 res_t res;
163 };
164
165 private:
166 struct fields_tag {};
167 struct request_tag {};
168 struct response_tag {};
169
170 constexpr header(fields_tag) noexcept;
171 constexpr header(request_tag) noexcept;
172 constexpr header(response_tag) noexcept;
173
174 public:
175 // in fields_base.hpp
176 static header& get(fields_base& f) noexcept;
177
178 BOOST_HTTP_PROTO_DECL static header const*
179 get_default(detail::kind k) noexcept;
180
181 // called from parser
182 explicit header(empty) noexcept;
183
184 BOOST_HTTP_PROTO_DECL header(detail::kind) noexcept;
185 BOOST_HTTP_PROTO_DECL void swap(header&) noexcept;
186 BOOST_HTTP_PROTO_DECL bool keep_alive() const noexcept;
187
188 static std::size_t bytes_needed(
189 std::size_t size, std::size_t count) noexcept;
190 static std::size_t table_space(
191 std::size_t count) noexcept;
192 std::size_t table_space() const noexcept;
193
194 table tab() const noexcept;
195 entry* tab_() const noexcept;
196 bool is_default() const noexcept;
197 std::size_t find(field) const noexcept;
198 std::size_t find(core::string_view) const noexcept;
199 void copy_table(void*, std::size_t) const noexcept;
200 void copy_table(void*) const noexcept;
201 void assign_to(header&) const noexcept;
202
203 // metadata
204
205 std::size_t maybe_count(field) const noexcept;
206 bool is_special(field) const noexcept;
207 void on_start_line();
208 void on_insert(field, core::string_view);
209 void on_erase(field);
210 void on_insert_connection(core::string_view);
211 void on_insert_content_length(core::string_view);
212 void on_insert_expect(core::string_view);
213 void on_insert_transfer_encoding();
214 void on_insert_upgrade(core::string_view);
215 void on_erase_connection();
216 void on_erase_content_length();
217 void on_erase_expect();
218 void on_erase_transfer_encoding();
219 void on_erase_upgrade();
220 void on_erase_all(field);
221 void update_payload() noexcept;
222
223 // parsing
224
225 static std::size_t count_crlf(
226 core::string_view s) noexcept;
227 BOOST_HTTP_PROTO_DECL void parse(
228 std::size_t, header_limits const&,
229 system::error_code&) noexcept;
230 };
231
232 } // detail
233 } // http_proto
234 } // boost
235
236 #endif
237