Line data Source code
1 : //
2 : // Copyright (c) 2025 Mohammad Nejati
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_STATIC_FIELDS_HPP
11 : #define BOOST_HTTP_PROTO_STATIC_FIELDS_HPP
12 :
13 : #include <boost/http_proto/detail/config.hpp>
14 : #include <boost/http_proto/fields_base.hpp>
15 : #include <boost/http_proto/fields_view.hpp>
16 : #include <boost/core/detail/string_view.hpp>
17 :
18 : namespace boost {
19 : namespace http_proto {
20 :
21 : /** A modifiable static container of HTTP fields.
22 :
23 : This container owns a collection of HTTP fields,
24 : represented by an inline buffer with fixed capacity.
25 : The contents may be inspected and modified,
26 : and the implementation maintains a useful
27 : invariant: changes to the fields always
28 : leave it in a valid state.
29 :
30 : @par Example
31 : @code
32 : static_fields<1024> fs;
33 :
34 : fs.set(field::host, "example.com");
35 : fs.set(field::accept_encoding, "gzip, deflate, br");
36 : fs.set(field::cache_control, "no-cache");
37 :
38 : assert(fs.buffer() ==
39 : "Host: example.com\r\n"
40 : "Accept-Encoding: gzip, deflate, br\r\n"
41 : "Cache-Control: no-cache\r\n"
42 : "\r\n");
43 : @endcode
44 :
45 : @par Invariants
46 : @code
47 : this->capacity_in_bytes() == Capacity && this->max_capacity_in_bytes() == Capacity
48 : @endcode
49 :
50 : @tparam Capacity The maximum capacity in bytes.
51 :
52 : @see
53 : @ref fields,
54 : @ref fields_view.
55 : */
56 : template<std::size_t Capacity>
57 : class static_fields final
58 : : public fields_base
59 : {
60 : alignas(entry)
61 : char buf_[Capacity];
62 :
63 : public:
64 :
65 : //--------------------------------------------
66 : //
67 : // Special Members
68 : //
69 : //--------------------------------------------
70 :
71 : /** Constructor.
72 :
73 : A default-constructed fields container
74 : contains no name-value pairs.
75 :
76 : @par Example
77 : @code
78 : static_fields<1024> fs;
79 : @endcode
80 :
81 : @par Postconditions
82 : @code
83 : this->buffer() == "\r\n"
84 : @endcode
85 :
86 : @par Complexity
87 : Constant.
88 : */
89 9 : static_fields() noexcept
90 : : fields_view_base(
91 9 : &this->fields_base::h_)
92 : , fields_base(
93 : detail::kind::fields,
94 9 : buf_,
95 9 : Capacity)
96 : {
97 9 : }
98 :
99 :
100 : /** Constructor.
101 :
102 : Constructs a fields container from the
103 : string `s`, which must contain valid
104 : HTTP fields or else an exception is thrown.
105 : The new fields container retains ownership
106 : by making a copy of the passed string.
107 :
108 : @par Example
109 : @code
110 : static_fields<1024> fs(
111 : "Server: Boost.HttpProto\r\n"
112 : "Content-Type: text/plain\r\n"
113 : "\r\n");
114 : @endcode
115 :
116 : @par Postconditions
117 : @code
118 : this->buffer.data() != s.data()
119 : @endcode
120 :
121 : @par Complexity
122 : Linear in `s.size()`.
123 :
124 : @par Exception Safety
125 : Exception thrown on invalid input.
126 : Exception thrown if max capacity exceeded.
127 :
128 : @throw system_error
129 : The input does not contain a valid HTTP fields.
130 :
131 : @throw std::length_error
132 : Max capacity would be exceeded.
133 :
134 : @param s The string to parse.
135 : */
136 12 : explicit static_fields(
137 : core::string_view s)
138 : : fields_view_base(
139 12 : &this->fields_base::h_)
140 : , fields_base(
141 : detail::kind::fields,
142 12 : buf_,
143 : Capacity,
144 12 : s)
145 : {
146 12 : }
147 :
148 : /** Constructor.
149 :
150 : The newly constructed object contains
151 : a copy of `f`.
152 :
153 : @par Postconditions
154 : @code
155 : this->buffer() == f.buffer() && this->buffer.data() != f.buffer().data()
156 : @endcode
157 :
158 : @par Complexity
159 : Linear in `f.size()`.
160 :
161 : @param f The fields container to copy.
162 : */
163 1 : static_fields(
164 : static_fields const& f) noexcept
165 : : fields_view_base(
166 1 : &this->fields_base::h_)
167 : , fields_base(
168 1 : *f.ph_,
169 1 : buf_,
170 1 : Capacity)
171 : {
172 1 : }
173 :
174 : /** Constructor.
175 :
176 : The newly constructed object contains
177 : a copy of `f`.
178 :
179 : @par Postconditions
180 : @code
181 : this->buffer() == f.buffer() && this->buffer.data() != f.buffer().data()
182 : @endcode
183 :
184 : @par Complexity
185 : Linear in `f.size()`.
186 :
187 : @par Exception Safety
188 : Exception thrown if max capacity exceeded.
189 :
190 : @throw std::length_error
191 : Max capacity would be exceeded.
192 :
193 : @param f The fields container to copy.
194 : */
195 : /** Constructor
196 : */
197 1 : static_fields(
198 : fields_view const& f)
199 : : fields_view_base(
200 1 : &this->fields_base::h_)
201 : , fields_base(
202 1 : *f.ph_,
203 1 : buf_,
204 1 : Capacity)
205 : {
206 1 : }
207 :
208 : /** Assignment.
209 :
210 : The contents of `f` are copied and
211 : the previous contents of `this` are
212 : discarded.
213 :
214 : @par Postconditions
215 : @code
216 : this->buffer() == f.buffer() && this->buffer().data() != f.buffer().data()
217 : @endcode
218 :
219 : @par Complexity
220 : Linear in `f.size()`.
221 :
222 : @param f The fields container to copy.
223 :
224 : @return A reference to this object.
225 : */
226 : static_fields&
227 3 : operator=(static_fields const& f) noexcept
228 : {
229 3 : copy_impl(*f.ph_);
230 3 : return *this;
231 : }
232 :
233 : /** Assignment.
234 :
235 : The contents of `f` are copied and
236 : the previous contents of `this` are
237 : discarded.
238 :
239 : @par Postconditions
240 : @code
241 : this->buffer() == f.buffer() && this->buffer().data() != f.buffer().data()
242 : @endcode
243 :
244 : @par Complexity
245 : Linear in `f.size()`.
246 :
247 : @par Exception Safety
248 : Strong guarantee.
249 : Exception thrown if max capacity exceeded.
250 :
251 : @throw std::length_error
252 : Max capacity would be exceeded.
253 :
254 : @param f The fields container to copy.
255 :
256 : @return A reference to this object.
257 : */
258 : static_fields&
259 4 : operator=(fields_view const& f)
260 : {
261 4 : copy_impl(*f.ph_);
262 4 : return *this;
263 : }
264 :
265 : /** Conversion.
266 :
267 : @see
268 : @ref fields_view.
269 :
270 : @return A view of the fields.
271 : */
272 4 : operator fields_view() const noexcept
273 : {
274 4 : return fields_view(ph_);
275 : }
276 : };
277 :
278 : } // http_proto
279 : } // boost
280 :
281 : #endif
|