GCC Code Coverage Report


Directory: libs/http_proto/
File: src/fields_view_base.cpp
Date: 2025-09-21 18:08:15
Exec Total Coverage
Lines: 152 160 95.0%
Functions: 22 24 91.7%
Branches: 60 68 88.2%

Line Branch Exec Source
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 fields_view_base::
23 value_type::
24 value_type(
25 reference const& other)
26 : id(other.id)
27 , name(other.name)
28 , value(other.value)
29 {
30 }
31
32 //------------------------------------------------
33
34 auto
35 2164 fields_view_base::
36 iterator::
37 operator*() const noexcept ->
38 reference
39 {
40
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2164 times.
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
2/2
✓ Branch 0 taken 789 times.
✓ Branch 1 taken 1375 times.
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
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 24 times.
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
2/2
✓ Branch 0 taken 15 times.
✓ Branch 1 taken 9 times.
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
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 21 times.
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
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 27 times.
27 BOOST_ASSERT(i_ < ph_->count);
129 27 auto const* e = &ph_->tab()[i_];
130 27 auto const id = e->id;
131
2/2
✓ Branch 0 taken 20 times.
✓ Branch 1 taken 7 times.
27 if(id != detail::header::unknown_field)
132 {
133 20 ++i_;
134 20 --e;
135
2/2
✓ Branch 0 taken 26 times.
✓ Branch 1 taken 12 times.
38 while(i_ != ph_->count)
136 {
137
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 18 times.
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
2/2
✓ Branch 0 taken 20 times.
✓ Branch 1 taken 4 times.
24 while(i_ != ph_->count)
151 {
152
2/2
✓ Branch 1 taken 3 times.
✓ Branch 2 taken 17 times.
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/2
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 1 times.
2 if(it == end())
175
1/2
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
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/2
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 1 times.
2 if(it == end())
187
1/2
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
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
2/2
✓ Branch 5 taken 45 times.
✓ Branch 6 taken 12 times.
57 for(auto v : *this)
214
2/2
✓ Branch 1 taken 11 times.
✓ Branch 2 taken 34 times.
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
2/2
✓ Branch 5 taken 80 times.
✓ Branch 6 taken 23 times.
103 for(auto v : *this)
226
2/2
✓ Branch 1 taken 31 times.
✓ Branch 2 taken 49 times.
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
2/2
✓ Branch 1 taken 204 times.
✓ Branch 2 taken 9 times.
213 while(it != last)
240 {
241
2/2
✓ Branch 3 taken 90 times.
✓ Branch 4 taken 114 times.
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
2/2
✓ Branch 1 taken 200 times.
✓ Branch 2 taken 6 times.
206 while(it != last)
257 {
258 200 if(grammar::ci_is_equal(
259
2/2
✓ Branch 2 taken 87 times.
✓ Branch 3 taken 113 times.
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
2/2
✓ Branch 1 taken 10 times.
✓ Branch 2 taken 1 times.
11 while(from != last)
275 {
276
2/2
✓ Branch 3 taken 1 times.
✓ Branch 4 taken 9 times.
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
2/2
✓ Branch 1 taken 11 times.
✓ Branch 2 taken 1 times.
12 while(from != last)
292 {
293 11 if(grammar::ci_is_equal(
294
2/2
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 10 times.
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
2/2
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 9 times.
10 if(it == it0)
312 1 return end();
313 9 --it;
314
2/2
✓ Branch 3 taken 2 times.
✓ Branch 4 taken 7 times.
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
2/2
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 13 times.
14 if(it == it0)
330 1 return end();
331 13 --it;
332 13 if(grammar::ci_is_equal(
333
2/2
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 11 times.
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/2
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 1 times.
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/2
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 1 times.
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 operator<<(
388 std::ostream& os,
389 const fields_view_base& f)
390 {
391 return os << f.buffer();
392 }
393
394 } // http_proto
395 } // boost
396