Line data Source code
1 : //
2 : // Copyright (c) 2021 Vinnie Falco (vinnie.falco@gmail.com)
3 : // Copyright (c) 2025 Mohammad Nejati
4 : //
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)
7 : //
8 : // Official repository: https://github.com/cppalliance/http_proto
9 : //
10 :
11 : #include <boost/http_proto/fields_view_base.hpp>
12 : #include <boost/http_proto/field.hpp>
13 : #include <boost/http_proto/detail/except.hpp>
14 : #include <boost/url/grammar/ci_string.hpp>
15 : #include <boost/url/grammar/parse.hpp>
16 : #include <boost/assert.hpp>
17 : #include <boost/assert/source_location.hpp>
18 :
19 : namespace boost {
20 : namespace http_proto {
21 :
22 0 : fields_view_base::
23 : value_type::
24 : value_type(
25 0 : reference const& other)
26 0 : : id(other.id)
27 0 : , name(other.name)
28 0 : , value(other.value)
29 : {
30 0 : }
31 :
32 : //------------------------------------------------
33 :
34 : auto
35 2164 : fields_view_base::
36 : iterator::
37 : operator*() const noexcept ->
38 : reference
39 : {
40 2164 : BOOST_ASSERT(i_ < ph_->count);
41 : auto tab =
42 2164 : ph_->tab();
43 : auto const& e =
44 2164 : tab[i_];
45 2164 : auto const* p =
46 2164 : ph_->cbuf + ph_->prefix;
47 : return {
48 2164 : (e.id == detail::header::unknown_field)
49 2164 : ? optional<field>{} : e.id,
50 : core::string_view(
51 2164 : p + e.np, e.nn),
52 : core::string_view(
53 2164 : p + e.vp, e.vn) };
54 : }
55 :
56 : //------------------------------------------------
57 :
58 : auto
59 24 : fields_view_base::
60 : reverse_iterator::
61 : operator*() const noexcept ->
62 : reference
63 : {
64 24 : BOOST_ASSERT(i_ > 0);
65 : auto tab =
66 24 : ph_->tab();
67 : auto const& e =
68 24 : tab[i_-1];
69 24 : auto const* p =
70 24 : ph_->cbuf + ph_->prefix;
71 : return {
72 24 : (e.id == detail::header::unknown_field)
73 24 : ? optional<field>{} : e.id,
74 : core::string_view(
75 24 : p + e.np, e.nn),
76 : core::string_view(
77 24 : p + e.vp, e.vn) };
78 : }
79 :
80 : //------------------------------------------------
81 :
82 21 : fields_view_base::
83 : subrange::
84 : iterator::
85 : iterator(
86 : detail::header const* ph,
87 21 : std::size_t i) noexcept
88 21 : : ph_(ph)
89 21 : , i_(i)
90 : {
91 21 : BOOST_ASSERT(i <= ph_->count);
92 21 : }
93 :
94 21 : fields_view_base::
95 : subrange::
96 : iterator::
97 : iterator(
98 21 : detail::header const* ph) noexcept
99 21 : : ph_(ph)
100 21 : , i_(ph->count)
101 : {
102 21 : }
103 :
104 : auto
105 11 : fields_view_base::
106 : subrange::
107 : iterator::
108 : operator*() const noexcept ->
109 : reference const
110 : {
111 : auto tab =
112 11 : ph_->tab();
113 : auto const& e =
114 11 : tab[i_];
115 11 : auto const p =
116 11 : ph_->cbuf + ph_->prefix;
117 22 : return core::string_view(
118 11 : p + e.vp, e.vn);
119 : }
120 :
121 : auto
122 27 : fields_view_base::
123 : subrange::
124 : iterator::
125 : operator++() noexcept ->
126 : iterator&
127 : {
128 27 : BOOST_ASSERT(i_ < ph_->count);
129 27 : auto const* e = &ph_->tab()[i_];
130 27 : auto const id = e->id;
131 27 : if(id != detail::header::unknown_field)
132 : {
133 20 : ++i_;
134 20 : --e;
135 38 : while(i_ != ph_->count)
136 : {
137 26 : if(e->id == id)
138 8 : break;
139 18 : ++i_;
140 18 : --e;
141 : }
142 20 : return *this;
143 : }
144 7 : auto const p =
145 7 : ph_->cbuf + ph_->prefix;
146 : auto name = core::string_view(
147 7 : p + e->np, e->nn);
148 7 : ++i_;
149 7 : --e;
150 24 : while(i_ != ph_->count)
151 : {
152 20 : if(grammar::ci_is_equal(
153 : name, core::string_view(
154 20 : p + e->np, e->nn)))
155 3 : break;
156 17 : ++i_;
157 17 : --e;
158 : }
159 7 : return *this;
160 : }
161 :
162 : //------------------------------------------------
163 : //
164 : // fields_view_base
165 : //
166 : //------------------------------------------------
167 :
168 : core::string_view
169 2 : fields_view_base::
170 : at(
171 : field id) const
172 : {
173 2 : auto const it = find(id);
174 2 : if(it == end())
175 2 : BOOST_THROW_EXCEPTION(
176 : std::out_of_range{ "field not found" });
177 1 : return it->value;
178 : }
179 :
180 : core::string_view
181 2 : fields_view_base::
182 : at(
183 : core::string_view name) const
184 : {
185 2 : auto const it = find(name);
186 2 : if(it == end())
187 2 : BOOST_THROW_EXCEPTION(
188 : std::out_of_range{ "field not found" });
189 1 : return it->value;
190 : }
191 :
192 : bool
193 4 : fields_view_base::
194 : exists(
195 : field id) const noexcept
196 : {
197 4 : return find(id) != end();
198 : }
199 :
200 : bool
201 7 : fields_view_base::
202 : exists(
203 : core::string_view name) const noexcept
204 : {
205 7 : return find(name) != end();
206 : }
207 :
208 : std::size_t
209 12 : fields_view_base::
210 : count(field id) const noexcept
211 : {
212 12 : std::size_t n = 0;
213 57 : for(auto v : *this)
214 45 : if(v.id == id)
215 11 : ++n;
216 12 : return n;
217 : }
218 :
219 : std::size_t
220 23 : fields_view_base::
221 : count(
222 : core::string_view name) const noexcept
223 : {
224 23 : std::size_t n = 0;
225 103 : for(auto v : *this)
226 80 : if(grammar::ci_is_equal(
227 : v.name, name))
228 31 : ++n;
229 23 : return n;
230 : }
231 :
232 : auto
233 99 : fields_view_base::
234 : find(field id) const noexcept ->
235 : iterator
236 : {
237 99 : auto it = begin();
238 99 : auto const last = end();
239 213 : while(it != last)
240 : {
241 204 : if(it->id == id)
242 90 : break;
243 114 : ++it;
244 : }
245 99 : return it;
246 : }
247 :
248 : auto
249 93 : fields_view_base::
250 : find(
251 : core::string_view name) const noexcept ->
252 : iterator
253 : {
254 93 : auto it = begin();
255 93 : auto const last = end();
256 206 : while(it != last)
257 : {
258 200 : if(grammar::ci_is_equal(
259 400 : it->name, name))
260 87 : break;
261 113 : ++it;
262 : }
263 93 : return it;
264 : }
265 :
266 : auto
267 2 : fields_view_base::
268 : find(
269 : iterator from,
270 : field id) const noexcept ->
271 : iterator
272 : {
273 2 : auto const last = end();
274 11 : while(from != last)
275 : {
276 10 : if(from->id == id)
277 1 : break;
278 9 : ++from;
279 : }
280 2 : return from;
281 : }
282 :
283 : auto
284 2 : fields_view_base::
285 : find(
286 : iterator from,
287 : core::string_view name) const noexcept ->
288 : iterator
289 : {
290 2 : auto const last = end();
291 12 : while(from != last)
292 : {
293 11 : if(grammar::ci_is_equal(
294 22 : name, from->name))
295 1 : break;
296 10 : ++from;
297 : }
298 2 : return from;
299 : }
300 :
301 : auto
302 3 : fields_view_base::
303 : find_last(
304 : iterator it,
305 : field id) const noexcept ->
306 : iterator
307 : {
308 3 : auto const it0 = begin();
309 : for(;;)
310 : {
311 10 : if(it == it0)
312 1 : return end();
313 9 : --it;
314 9 : if(it->id == id)
315 2 : return it;
316 : }
317 : }
318 :
319 : auto
320 3 : fields_view_base::
321 : find_last(
322 : iterator it,
323 : core::string_view name) const noexcept ->
324 : iterator
325 : {
326 3 : auto const it0 = begin();
327 : for(;;)
328 : {
329 14 : if(it == it0)
330 1 : return end();
331 13 : --it;
332 13 : if(grammar::ci_is_equal(
333 26 : it->name, name))
334 2 : return it;
335 : }
336 : }
337 :
338 : core::string_view
339 2 : fields_view_base::
340 : value_or(
341 : field id,
342 : core::string_view s) const noexcept
343 : {
344 2 : auto it = find(id);
345 2 : if(it != end())
346 1 : return it->value;
347 1 : return s;
348 : }
349 :
350 : core::string_view
351 2 : fields_view_base::
352 : value_or(
353 : core::string_view name,
354 : core::string_view s) const noexcept
355 : {
356 2 : auto it = find(name);
357 2 : if(it != end())
358 1 : return it->value;
359 1 : return s;
360 : }
361 :
362 : //------------------------------------------------
363 :
364 : auto
365 16 : fields_view_base::
366 : find_all(
367 : field id) const noexcept ->
368 : subrange
369 : {
370 32 : return subrange(
371 16 : ph_, find(id).i_);
372 : }
373 :
374 : auto
375 5 : fields_view_base::
376 : find_all(
377 : core::string_view name) const noexcept ->
378 : subrange
379 : {
380 10 : return subrange(
381 5 : ph_, find(name).i_);
382 : }
383 :
384 : //------------------------------------------------
385 :
386 : std::ostream&
387 0 : operator<<(
388 : std::ostream& os,
389 : const fields_view_base& f)
390 : {
391 0 : return os << f.buffer();
392 : }
393 :
394 : } // http_proto
395 : } // boost
|