include/boost/burl/fields_base.hpp

100.0% Lines (209/209) 100.0% List of functions (68/69) 71.4% Branches (45/63)
fields_base.hpp
f(x) Functions (69)
Function Calls Lines Branches Blocks
boost::burl::fields_base::field_view::field_view(std::basic_string_view<char, std::char_traits<char> >, std::basic_string_view<char, std::char_traits<char> >) :134 50x 100.0% 100.0% boost::burl::fields_base::field_view::field_view(boost::http::field, std::basic_string_view<char, std::char_traits<char> >) :149 34x 100.0% 50.0% 80.0% boost::burl::fields_base::field_view::field_view(std::basic_string_view<char, std::char_traits<char> >, std::basic_string_view<char, std::char_traits<char> >, boost::http::field) :162 3012x 100.0% 100.0% <unknown function 184> :184 boost::burl::fields_base::iterator::iterator(boost::burl::fields_base const*, unsigned short) :189 4100x 100.0% 100.0% boost::burl::fields_base::iterator::arrow::operator->() const :211 242x 100.0% 100.0% boost::burl::fields_base::iterator::operator*() const :220 106x 100.0% 100.0% boost::burl::fields_base::iterator::operator->() const :226 242x 100.0% 100.0% boost::burl::fields_base::iterator::operator[](long) const :232 2306x 100.0% 100.0% boost::burl::fields_base::iterator::operator++() :239 16x 100.0% 100.0% boost::burl::fields_base::iterator::operator++(int) :246 1x 100.0% 100.0% boost::burl::fields_base::iterator::operator--() :254 11x 100.0% 100.0% boost::burl::fields_base::iterator::operator--(int) :261 1x 100.0% 100.0% boost::burl::fields_base::iterator::operator+=(long) :269 3x 100.0% 100.0% boost::burl::fields_base::iterator::operator-=(long) :276 4x 100.0% 100.0% boost::burl::operator+(boost::burl::fields_base::iterator, long) :283 2x 100.0% 100.0% boost::burl::operator+(long, boost::burl::fields_base::iterator) :292 1x 100.0% 100.0% boost::burl::operator-(boost::burl::fields_base::iterator, long) :301 3x 100.0% 100.0% boost::burl::operator-(boost::burl::fields_base::iterator const&, boost::burl::fields_base::iterator const&) :310 2x 100.0% 100.0% boost::burl::fields_base::iterator::operator==(boost::burl::fields_base::iterator const&) const :319 639x 100.0% 75.0% 83.0% boost::burl::fields_base::iterator::operator<=>(boost::burl::fields_base::iterator const&) const :322 4x 100.0% 83.3% 89.0% boost::burl::fields_base::subrange::subrange(boost::burl::fields_base const*, unsigned short) :361 207x 100.0% 100.0% boost::burl::fields_base::subrange::iterator::iterator(boost::burl::fields_base const*, unsigned short) :378 407x 100.0% 100.0% boost::burl::fields_base::subrange::iterator::operator*() const :397 203x 100.0% 100.0% boost::burl::fields_base::subrange::iterator::operator==(boost::burl::fields_base::subrange::iterator const&) const :415 389x 100.0% 75.0% 83.0% boost::burl::fields_base::subrange::begin() const :432 204x 100.0% 100.0% boost::burl::fields_base::subrange::end() const :439 203x 100.0% 100.0% 100.0% boost::burl::fields_base::subrange::empty() const :446 5x 100.0% 75.0% 83.0% boost::burl::fields_base::capacity_in_bytes() const :487 263791x 100.0% 100.0% boost::burl::fields_base::buffer() const :518 100x 100.0% 100.0% boost::burl::fields_base::size() const :560 45063x 100.0% 100.0% boost::burl::fields_base::empty() const :571 125x 100.0% 100.0% boost::burl::fields_base::begin() const :579 2500x 100.0% 100.0% boost::burl::fields_base::end() const :587 922x 100.0% 100.0% boost::burl::fields_base::rbegin() const :595 4x 100.0% 100.0% boost::burl::fields_base::rend() const :603 6x 100.0% 100.0% boost::burl::fields_base::find(boost::http::field) const :629 53x 100.0% 100.0% boost::burl::fields_base::find(std::basic_string_view<char, std::char_traits<char> >) const :654 207x 100.0% 100.0% boost::burl::fields_base::find(boost::burl::fields_base::iterator, boost::http::field) const :676 2x 100.0% 50.0% 86.0% boost::burl::fields_base::find(boost::burl::fields_base::iterator, std::basic_string_view<char, std::char_traits<char> >) const :706 2x 100.0% 50.0% 86.0% boost::burl::fields_base::find_last(boost::burl::fields_base::iterator, boost::http::field) const :731 294x 100.0% 50.0% 86.0% boost::burl::fields_base::find_last(boost::burl::fields_base::iterator, std::basic_string_view<char, std::char_traits<char> >) const :761 5x 100.0% 50.0% 86.0% boost::burl::fields_base::find_all(boost::http::field) const :778 202x 100.0% 100.0% boost::burl::fields_base::find_all(std::basic_string_view<char, std::char_traits<char> >) const :796 5x 100.0% 100.0% boost::burl::fields_base::value_or(boost::http::field, std::basic_string_view<char, std::char_traits<char> >) const :816 34x 100.0% 100.0% 100.0% boost::burl::fields_base::value_or(std::basic_string_view<char, std::char_traits<char> >, std::basic_string_view<char, std::char_traits<char> >) const :845 5x 100.0% 100.0% 100.0% boost::burl::fields_base::contains(boost::http::field) const :935 46x 100.0% 100.0% boost::burl::fields_base::contains(std::basic_string_view<char, std::char_traits<char> >) const :952 5x 100.0% 100.0% boost::burl::fields_base::append(boost::http::field, std::basic_string_view<char, std::char_traits<char> >) :999 451x 100.0% 75.0% 86.0% boost::burl::fields_base::append(std::basic_string_view<char, std::char_traits<char> >, std::basic_string_view<char, std::char_traits<char> >) :1052 66106x 100.0% 100.0% boost::burl::fields_base::insert(boost::burl::fields_base::iterator, boost::http::field, std::basic_string_view<char, std::char_traits<char> >) :1140 2x 100.0% 66.7% 75.0% boost::burl::fields_base::insert(boost::burl::fields_base::iterator, std::basic_string_view<char, std::char_traits<char> >, std::basic_string_view<char, std::char_traits<char> >) :1202 6x 100.0% 66.7% 89.0% boost::burl::fields_base::set(boost::burl::fields_base::iterator, std::basic_string_view<char, std::char_traits<char> >) :1243 6x 100.0% 50.0% 67.0% boost::burl::fields_base::erase(boost::burl::fields_base::iterator) :1408 109x 100.0% 50.0% 78.0% boost::burl::fields_base::fields_base(char*, unsigned long, unsigned int, unsigned short, unsigned short) :1455 42022x 100.0% 100.0% boost::burl::fields_base::fields_base(boost::burl::fields_base const&) :1469 637x 100.0% 100.0% boost::burl::fields_base::static_() const :1483 26x 100.0% 100.0% boost::burl::fields_base::on_clear_() :1490 2x 100.0% 100.0% boost::burl::fields_base::on_special_(boost::http::field) :1496 7x 100.0% 100.0% boost::burl::fields_base::base_() const :1501 774126x 100.0% 100.0% boost::burl::fields_base::detach_() :1507 10x 100.0% 100.0% 100.0% boost::burl::fields_base::ent_(unsigned short) const :1549 41669x 100.0% 100.0% boost::burl::fields_base::table_space_(unsigned long) :1561 263757x 100.0% 100.0% boost::burl::fields_base::default_() const :1591 1897x 100.0% 100.0% boost::burl::fields_base::owns_() const :1597 1685x 100.0% 75.0% 100.0% boost::burl::fields_base::tab_() const :1603 109911x 100.0% 100.0% boost::burl::fields_base::ent_(boost::burl::fields_base::entry*, unsigned short) :1609 164779x 100.0% 100.0% boost::burl::fields_base::ref_(unsigned short) const :1617 3012x 100.0% 100.0% boost::burl::fields_base::line_len_(unsigned short) const :1629 10178x 100.0% 100.0% 100.0%
Line Branch TLA Hits Source Code
1 //
2 // Copyright (c) 2021 Vinnie Falco ([email protected])
3 // Copyright (c) 2026 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/burl
9 //
10
11 #ifndef BOOST_BURL_FIELDS_BASE_HPP
12 #define BOOST_BURL_FIELDS_BASE_HPP
13
14 #include <boost/burl/detail/config.hpp>
15
16 #include <boost/assert.hpp>
17 #include <boost/http/field.hpp>
18
19 #include <compare>
20 #include <cstddef>
21 #include <cstdint>
22 #include <initializer_list>
23 #include <iosfwd>
24 #include <iterator>
25 #include <string_view>
26
27 namespace boost
28 {
29 namespace burl
30 {
31
32 /** Mixin for HTTP fields.
33
34 This type provides the observers, lookup
35 functions, and modifiers shared by every
36 container of HTTP fields. The fields are held in
37 storage supplied by the derived container, where
38 each field is a `name: value` line terminated by
39 CRLF and the sequence ends with the final empty
40 line. This wire form is available from
41 @ref buffer.
42
43 Fields are kept in insertion order, and more than
44 one field may have the same name. When a name
45 matches a known field, the corresponding constant
46 is stored with it regardless of how the field was
47 added; lookups by id compare constants and never
48 examine the stored names, while lookups by string
49 compare names case-insensitively.
50
51 Names and values are stored verbatim: no
52 normalization, folding, or validation is
53 performed. Modifiers throw `std::length_error`
54 when the storage cannot grow, or when a size
55 limit would be exceeded; see @ref max_name_size,
56 @ref max_value_size, @ref max_field_count, and
57 @ref max_buffer_size.
58
59 Iterators refer to positions, while views refer
60 to characters in the storage. Each modifier
61 documents which iterators and views it
62 invalidates.
63
64 Users cannot construct, copy, or destroy objects
65 of this type: they are obtained by reference from
66 a derived container. This makes the type useful
67 for writing algorithms which operate on any
68 container of fields:
69
70 @code
71 void print_host( fields_base const& f )
72 {
73 std::cout << f.value_or(
74 http::field::host, "(none)" );
75 }
76 @endcode
77
78 @see
79 @ref fields,
80 @ref static_fields,
81 @ref message_head_base.
82 */
83 class fields_base
84 {
85 public:
86 //--------------------------------------------
87 //
88 // Types
89 //
90 //--------------------------------------------
91
92 /** A view to an HTTP field.
93
94 Objects of this type are returned when
95 dereferencing an iterator. The views are
96 invalidated when the underlying container
97 is modified.
98
99 They are also formed implicitly from the
100 elements of an initializer list when
101 constructing a @ref fields container; the
102 field name may be given as a string or as
103 a field constant:
104
105 @code
106 fields f = {
107 { http::field::host, "example.com" },
108 { "X-Request-Id", "42" },
109 };
110 @endcode
111
112 The caller is responsible for ensuring
113 that the lifetime of the viewed characters
114 extends until the view is no longer
115 referenced.
116 */
117 struct field_view
118 {
119 /// A view to the field name, as stored
120 std::string_view name;
121
122 /// A view to the field value
123 std::string_view value;
124
125 /// The field name constant
126 http::field id;
127
128 /** Constructor.
129
130 @param name_ The field name.
131
132 @param value_ The field value.
133 */
134 50x field_view(
135 std::string_view name_,
136 std::string_view value_) noexcept
137 50x : name(name_)
138 50x , value(value_)
139 50x , id(unknown_field)
140 {
141 50x }
142
143 /** Constructor.
144
145 @param id_ The field name constant.
146
147 @param value_ The field value.
148 */
149 34x field_view(
150 http::field id_,
151 std::string_view value_) noexcept
152 34x : name(http::to_string(id_))
153 34x , value(value_)
154 34x , id(id_)
155 {
156
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 34 times.
34x BOOST_ASSERT(id_ != unknown_field);
157 34x }
158
159 private:
160 friend class fields_base;
161
162 3012x field_view(
163 std::string_view name_,
164 std::string_view value_,
165 http::field id_) noexcept
166 3012x : name(name_)
167 3012x , value(value_)
168 3012x , id(id_)
169 {
170 3012x }
171 };
172
173 /** A random-access iterator to HTTP fields.
174
175 Dereferencing returns a @ref field_view by
176 value; the views it holds point into the
177 container.
178
179 The iterator is invalidated when the
180 underlying container is modified.
181 */
182 class iterator
183 {
184 639x fields_base const* f_ = nullptr;
185 639x std::uint16_t i_ = 0;
186
187 friend class fields_base;
188
189 4100x iterator(
190 fields_base const* f,
191 std::uint16_t i) noexcept
192 4100x : f_(f)
193 4100x , i_(i)
194 {
195 4100x }
196
197 public:
198 using value_type = fields_base::field_view;
199 using reference = fields_base::field_view;
200 using difference_type = std::ptrdiff_t;
201 using pointer = void;
202 using iterator_category = std::input_iterator_tag;
203 using iterator_concept = std::random_access_iterator_tag;
204
205 /// Proxy returned by `operator->`
206 struct arrow
207 {
208 fields_base::field_view ref;
209
210 fields_base::field_view const*
211 242x operator->() const noexcept
212 {
213 242x return &ref;
214 }
215 };
216
217 iterator() = default;
218
219 reference
220 106x operator*() const noexcept
221 {
222 106x return f_->ref_(i_);
223 }
224
225 arrow
226 242x operator->() const noexcept
227 {
228 242x return arrow{ f_->ref_(i_) };
229 }
230
231 reference
232 2306x operator[](difference_type n) const noexcept
233 {
234 2306x return f_->ref_(
235 2306x static_cast<std::uint16_t>(i_ + n));
236 }
237
238 iterator&
239 16x operator++() noexcept
240 {
241 16x ++i_;
242 16x return *this;
243 }
244
245 iterator
246 1x operator++(int) noexcept
247 {
248 1x auto it = *this;
249 1x ++i_;
250 1x return it;
251 }
252
253 iterator&
254 11x operator--() noexcept
255 {
256 11x --i_;
257 11x return *this;
258 }
259
260 iterator
261 1x operator--(int) noexcept
262 {
263 1x auto it = *this;
264 1x --i_;
265 1x return it;
266 }
267
268 iterator&
269 3x operator+=(difference_type n) noexcept
270 {
271 3x i_ = static_cast<std::uint16_t>(i_ + n);
272 3x return *this;
273 }
274
275 iterator&
276 4x operator-=(difference_type n) noexcept
277 {
278 4x i_ = static_cast<std::uint16_t>(i_ - n);
279 4x return *this;
280 }
281
282 friend iterator
283 2x operator+(
284 iterator it,
285 difference_type n) noexcept
286 {
287 2x it += n;
288 2x return it;
289 }
290
291 friend iterator
292 1x operator+(
293 difference_type n,
294 iterator it) noexcept
295 {
296 1x it += n;
297 1x return it;
298 }
299
300 friend iterator
301 3x operator-(
302 iterator it,
303 difference_type n) noexcept
304 {
305 3x it -= n;
306 3x return it;
307 }
308
309 friend difference_type
310 2x operator-(
311 iterator const& a,
312 iterator const& b) noexcept
313 {
314 2x return static_cast<difference_type>(a.i_) -
315 2x static_cast<difference_type>(b.i_);
316 }
317
318 bool
319
3/4
✗ Branch 0 not taken.
✓ Branch 1 taken 639 times.
✓ Branch 2 taken 330 times.
✓ Branch 3 taken 309 times.
639x operator==(iterator const& other) const noexcept = default;
320
321 std::strong_ordering
322 4x operator<=>(iterator const& other) const noexcept
323 {
324
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4x BOOST_ASSERT(f_ == other.f_);
325
4/4
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 1 time.
✓ Branch 3 taken 1 time.
4x return i_ <=> other.i_;
326 }
327 };
328
329 /// @copydoc iterator
330 using const_iterator = iterator;
331
332 /** A reverse random-access iterator to HTTP fields.
333 */
334 using reverse_iterator = std::reverse_iterator<iterator>;
335
336 /// @copydoc reverse_iterator
337 using const_reverse_iterator = reverse_iterator;
338
339 /** A forward range of values for all matching fields.
340
341 Objects of this type are returned by
342 @ref find_all. Dereferencing an iterator
343 returns the field value as a
344 `std::string_view`.
345
346 Advancing skips fields whose name differs;
347 when the fields are known, only field ids
348 are compared and the field names are never
349 touched.
350
351 The range is invalidated when the
352 underlying container is modified.
353 */
354 class subrange
355 {
356 fields_base const* f_ = nullptr;
357 std::uint16_t i_ = 0;
358
359 friend class fields_base;
360
361 207x subrange(
362 fields_base const* f,
363 std::uint16_t i) noexcept
364 207x : f_(f)
365 207x , i_(i)
366 {
367 207x }
368
369 public:
370 /// A forward iterator over the values
371 class iterator
372 {
373 389x fields_base const* f_ = nullptr;
374 389x std::uint16_t i_ = 0;
375
376 friend class subrange;
377
378 407x iterator(
379 fields_base const* f,
380 std::uint16_t i) noexcept
381 407x : f_(f)
382 407x , i_(i)
383 {
384 407x }
385
386 public:
387 using value_type = std::string_view;
388 using reference = std::string_view;
389 using difference_type = std::ptrdiff_t;
390 using pointer = void;
391 using iterator_category = std::input_iterator_tag;
392 using iterator_concept = std::forward_iterator_tag;
393
394 iterator() = default;
395
396 std::string_view
397 203x operator*() const noexcept
398 {
399 203x return f_->ref_(i_).value;
400 }
401
402 BOOST_BURL_DECL
403 iterator&
404 operator++() noexcept;
405
406 iterator
407 operator++(int) noexcept
408 {
409 auto it = *this;
410 ++*this;
411 return it;
412 }
413
414 bool
415
3/4
✗ Branch 0 not taken.
✓ Branch 1 taken 389 times.
✓ Branch 2 taken 201 times.
✓ Branch 3 taken 188 times.
389x operator==(iterator const& other) const noexcept = default;
416 };
417
418 /// @copydoc iterator
419 using const_iterator = iterator;
420
421 /// The type of each element
422 using value_type = std::string_view;
423
424 /** Constructor.
425
426 Default-constructed subranges are empty.
427 */
428 subrange() = default;
429
430 /// Return an iterator to the beginning
431 iterator
432 204x begin() const noexcept
433 {
434 204x return iterator(f_, i_);
435 }
436
437 /// Return an iterator to the end
438 iterator
439 203x end() const noexcept
440 {
441
2/2
✓ Branch 0 taken 202 times.
✓ Branch 1 taken 1 time.
203x return iterator(f_, f_ ? f_->count_ : 0);
442 }
443
444 /// Return true if the range is empty
445 bool
446 5x empty() const noexcept
447 {
448
3/4
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 1 time.
✓ Branch 2 taken 4 times.
✗ Branch 3 not taken.
5x return f_ == nullptr || i_ == f_->count_;
449 }
450 };
451
452 /** The type of each element.
453
454 This is an alias for @ref field_view:
455 elements are views, and copying one does
456 not copy the underlying characters.
457 */
458 using value_type = field_view;
459
460 /// The type used to represent sizes
461 using size_type = std::size_t;
462
463 /// The type used to represent iterator distances
464 using difference_type = std::ptrdiff_t;
465
466 /// Maximum allowed name size
467 static constexpr std::size_t max_name_size = 65535;
468
469 /// Maximum allowed value size
470 static constexpr std::size_t max_value_size = 65535;
471
472 /// Maximum allowed number of fields
473 static constexpr std::size_t max_field_count = 65535;
474
475 /// Maximum allowed size of the header
476 static constexpr std::size_t max_buffer_size = 0x7FFFFFFF;
477
478 /// Maximum allowed size of the start line
479 static constexpr std::size_t max_start_line_size = 65535;
480
481 /** Return the size of the storage space, in bytes.
482
483 @par Complexity
484 Constant.
485 */
486 std::size_t
487 263791x capacity_in_bytes() const noexcept
488 {
489 263791x return std::size_t(end_ - base_());
490 }
491
492 //--------------------------------------------
493 //
494 // Observers
495 //
496 //--------------------------------------------
497
498 /** Return a string view representing the field section.
499
500 The returned view references every field
501 line followed by the final empty line:
502
503 @code
504 "Host: example.com\r\nAccept: text/html\r\n\r\n"
505 @endcode
506
507 Header containers provide their own
508 @ref message_head_base::buffer which additionally
509 includes the start line.
510
511 The view is invalidated when the container
512 is modified.
513
514 @par Complexity
515 Constant.
516 */
517 std::string_view
518 100x buffer() const noexcept
519 {
520 100x return { buf_, size_ };
521 }
522
523 /** Format the fields to an output stream.
524
525 Each field is written as `name: value`
526 followed by a newline:
527
528 @code
529 "Host: example.com\nAccept: text/html\n"
530 @endcode
531
532 This form is for diagnostics; the wire
533 form is available from @ref buffer.
534
535 @par Complexity
536 Linear in `f.buffer().size()`.
537
538 @par Exception Safety
539 Basic guarantee.
540
541 @return A reference to the output stream.
542
543 @param os The output stream to write to.
544
545 @param f The container to write.
546 */
547 friend
548 BOOST_BURL_DECL
549 std::ostream&
550 operator<<(
551 std::ostream& os,
552 fields_base const& f);
553
554 /** Return the number of fields in the container.
555
556 @par Complexity
557 Constant.
558 */
559 std::size_t
560 45063x size() const noexcept
561 {
562 45063x return count_;
563 }
564
565 /** Return true if the container has no fields.
566
567 @par Complexity
568 Constant.
569 */
570 bool
571 125x empty() const noexcept
572 {
573 125x return count_ == 0;
574 }
575
576 /** Return an iterator to the beginning.
577 */
578 iterator
579 2500x begin() const noexcept
580 {
581 2500x return iterator(this, 0);
582 }
583
584 /** Return an iterator to the end.
585 */
586 iterator
587 922x end() const noexcept
588 {
589 922x return iterator(this, count_);
590 }
591
592 /** Return a reverse iterator to the beginning.
593 */
594 reverse_iterator
595 4x rbegin() const noexcept
596 {
597 4x return reverse_iterator(end());
598 }
599
600 /** Return a reverse iterator to the end.
601 */
602 reverse_iterator
603 6x rend() const noexcept
604 {
605 6x return reverse_iterator(begin());
606 }
607
608 //--------------------------------------------
609 //
610 // Lookup
611 //
612 //--------------------------------------------
613
614 /** Return an iterator to the matching element if it exists.
615
616 If more than one field with the specified
617 name exists, the first field defined by
618 insertion order is returned.
619
620 @par Complexity
621 Linear in `this->size()`.
622
623 @return An iterator to the field, or
624 @ref end if no field matches.
625
626 @param id The field name constant.
627 */
628 iterator
629 53x find(http::field id) const noexcept
630 {
631 53x return iterator(this, find_(0, id));
632 }
633
634 /** Return an iterator to the matching element if it exists.
635
636 If more than one field with the specified
637 name exists, the first field defined by
638 insertion order is returned. The comparison
639 is case-insensitive.
640
641 If `name` refers to a known field, it is
642 faster to call @ref find with a field id
643 instead of a string.
644
645 @par Complexity
646 Linear in `this->size()`.
647
648 @return An iterator to the field, or
649 @ref end if no field matches.
650
651 @param name The field name.
652 */
653 iterator
654 207x find(std::string_view name) const noexcept
655 {
656 207x return iterator(this, find_(0, name));
657 }
658
659 /** Return an iterator to the matching element if it exists.
660
661 The search starts at `from` and runs
662 forwards.
663
664 @par Complexity
665 Linear in `this->size()`.
666
667 @return An iterator to the field, or
668 @ref end if no field matches.
669
670 @param from The position to begin the
671 search from. This can be `end()`.
672
673 @param id The field name constant.
674 */
675 iterator
676 2x find(
677 iterator from,
678 http::field id) const noexcept
679 {
680
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2x BOOST_ASSERT(from.f_ == this);
681 2x return iterator(this, find_(from.i_, id));
682 }
683
684 /** Return an iterator to the matching element if it exists.
685
686 The search starts at `from` and runs
687 forwards. The comparison is
688 case-insensitive.
689
690 If `name` refers to a known field, it is
691 faster to call @ref find with a field id
692 instead of a string.
693
694 @par Complexity
695 Linear in `this->size()`.
696
697 @return An iterator to the field, or
698 @ref end if no field matches.
699
700 @param from The position to begin the
701 search from. This can be `end()`.
702
703 @param name The field name.
704 */
705 iterator
706 2x find(
707 iterator from,
708 std::string_view name) const noexcept
709 {
710
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2x BOOST_ASSERT(from.f_ == this);
711 2x return iterator(this, find_(from.i_, name));
712 }
713
714 /** Return an iterator to the last matching element if it exists.
715
716 The search runs backwards, beginning with
717 the field immediately preceding `before`.
718
719 @par Complexity
720 Linear in `this->size()`.
721
722 @return An iterator to the field, or
723 @ref end if no field matches.
724
725 @param before One past the position to
726 begin the search from. This can be `end()`.
727
728 @param id The field name constant.
729 */
730 iterator
731 294x find_last(
732 iterator before,
733 http::field id) const noexcept
734 {
735
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 294 times.
294x BOOST_ASSERT(before.f_ == this);
736 294x return iterator(this, find_last_(before.i_, id));
737 }
738
739 /** Return an iterator to the last matching element if it exists.
740
741 The search runs backwards, beginning with
742 the field immediately preceding `before`.
743 The comparison is case-insensitive.
744
745 If `name` refers to a known field, it is
746 faster to call @ref find_last with a field
747 id instead of a string.
748
749 @par Complexity
750 Linear in `this->size()`.
751
752 @return An iterator to the field, or
753 @ref end if no field matches.
754
755 @param before One past the position to
756 begin the search from. This can be `end()`.
757
758 @param name The field name.
759 */
760 iterator
761 5x find_last(
762 iterator before,
763 std::string_view name) const noexcept
764 {
765
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5x BOOST_ASSERT(before.f_ == this);
766 5x return iterator(this, find_last_(before.i_, name));
767 }
768
769 /** Return a forward range containing values for all matching fields.
770
771 @par Complexity
772 Constant; advancing the iterators of the
773 returned range is linear in `this->size()`.
774
775 @param id The field name constant.
776 */
777 subrange
778 202x find_all(http::field id) const noexcept
779 {
780 202x return subrange(this, find_(0, id));
781 }
782
783 /** Return a forward range containing values for all matching fields.
784
785 If `name` refers to a known field, it is
786 faster to call @ref find_all with a field
787 id instead of a string.
788
789 @par Complexity
790 Constant; advancing the iterators of the
791 returned range is linear in `this->size()`.
792
793 @param name The field name.
794 */
795 subrange
796 5x find_all(std::string_view name) const noexcept
797 {
798 5x return subrange(this, find_(0, name));
799 }
800
801 /** Return the value of a field or a default if missing.
802
803 If more than one field with the specified
804 name exists, the value of the first field
805 defined by insertion order is returned.
806
807 @par Complexity
808 Linear in `this->size()`.
809
810 @param id The field name constant.
811
812 @param s The value to be returned if the
813 field does not exist.
814 */
815 std::string_view
816 34x value_or(
817 http::field id,
818 std::string_view s) const noexcept
819 {
820 34x auto const i = find_(0, id);
821
2/2
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 29 times.
34x if(i != count_)
822 5x return ref_(i).value;
823 29x return s;
824 }
825
826 /** Return the value of a field or a default if missing.
827
828 If more than one field with the specified
829 name exists, the value of the first field
830 defined by insertion order is returned.
831
832 If `name` refers to a known field, it is
833 faster to call @ref value_or with a field
834 id instead of a string.
835
836 @par Complexity
837 Linear in `this->size()`.
838
839 @param name The field name.
840
841 @param s The value to be returned if the
842 field does not exist.
843 */
844 std::string_view
845 5x value_or(
846 std::string_view name,
847 std::string_view s) const noexcept
848 {
849 5x auto const i = find_(0, name);
850
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 1 time.
5x if(i != count_)
851 4x return ref_(i).value;
852 1x return s;
853 }
854
855 /** Return the value of a field, or throw an exception.
856
857 If more than one field with the specified
858 name exists, the value of the first field
859 defined by insertion order is returned.
860
861 @par Complexity
862 Linear in `this->size()`.
863
864 @par Exception Safety
865 Strong guarantee.
866
867 @throw std::out_of_range
868 Field is not found.
869
870 @param id The field name constant.
871 */
872 BOOST_BURL_DECL
873 std::string_view
874 at(http::field id) const;
875
876 /** Return the value of a field, or throw an exception.
877
878 If more than one field with the specified
879 name exists, the value of the first field
880 defined by insertion order is returned.
881
882 If `name` refers to a known field, it is
883 faster to call @ref at with a field id
884 instead of a string.
885
886 @par Complexity
887 Linear in `this->size()`.
888
889 @par Exception Safety
890 Strong guarantee.
891
892 @throw std::out_of_range
893 Field is not found.
894
895 @param name The field name.
896 */
897 BOOST_BURL_DECL
898 std::string_view
899 at(std::string_view name) const;
900
901 /** Return the number of matching fields.
902
903 @par Complexity
904 Linear in `this->size()`.
905
906 @param id The field name constant.
907 */
908 BOOST_BURL_DECL
909 std::size_t
910 count(http::field id) const noexcept;
911
912 /** Return the number of matching fields.
913
914 If `name` refers to a known field, it is
915 faster to call @ref count with a field id
916 instead of a string.
917
918 @par Complexity
919 Linear in `this->size()`.
920
921 @param name The field name.
922 */
923 BOOST_BURL_DECL
924 std::size_t
925 count(std::string_view name) const noexcept;
926
927 /** Return true if a field exists.
928
929 @par Complexity
930 Linear in `this->size()`.
931
932 @param id The field name constant.
933 */
934 bool
935 46x contains(http::field id) const noexcept
936 {
937 46x return find_(0, id) != count_;
938 }
939
940 /** Return true if a field exists.
941
942 If `name` refers to a known field, it is
943 faster to call @ref contains with a field
944 id instead of a string.
945
946 @par Complexity
947 Linear in `this->size()`.
948
949 @param name The field name.
950 */
951 bool
952 5x contains(std::string_view name) const noexcept
953 {
954 5x return find_(0, name) != count_;
955 }
956
957 //--------------------------------------------
958 //
959 // Modifiers
960 //
961 //--------------------------------------------
962
963 /** Append a field.
964
965 This function appends a new field using
966 the canonical name of `id`. Existing
967 fields with the same name are not changed.
968
969 The value is stored verbatim.
970
971 All references and views are invalidated.
972 No iterators are invalidated.
973
974 @par Example
975 @code
976 f.append( http::field::user_agent, "Boost" );
977 @endcode
978
979 @par Complexity
980 Linear in `to_string( id ).size() + value.size()`,
981 amortized.
982
983 @par Exception Safety
984 Strong guarantee.
985 Exception thrown if the storage cannot
986 grow, or if a size limit would be
987 exceeded.
988
989 @throw std::length_error
990 The storage cannot accommodate the field;
991 see @ref max_name_size, @ref max_value_size,
992 @ref max_field_count, and @ref max_buffer_size.
993
994 @param id The field name constant.
995
996 @param value The field value.
997 */
998 void
999 451x append(
1000 http::field id,
1001 std::string_view value)
1002 {
1003
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 451 times.
451x BOOST_ASSERT(id != unknown_field);
1004 451x insert_(
1005
1/1
✓ Branch 1 taken 449 times.
451x count_,
1006 static_cast<std::uint16_t>(id),
1007
1/1
✓ Branch 1 taken 451 times.
451x http::to_string(id),
1008 value);
1009 449x }
1010
1011 /** Append a field.
1012
1013 This function appends a new field.
1014 Existing fields with the same name are not
1015 changed.
1016
1017 The name and value are stored verbatim.
1018 When `name` equals a known field name, the
1019 corresponding field constant is stored
1020 with it, and subsequent lookups by id
1021 succeed regardless of how the field was
1022 added.
1023
1024 All references and views are invalidated.
1025 No iterators are invalidated.
1026
1027 @par Example
1028 @code
1029 f.append( "User-Agent", "Boost" );
1030 @endcode
1031
1032 @par Complexity
1033 Linear in `name.size() + value.size()`,
1034 amortized.
1035
1036 @par Exception Safety
1037 Strong guarantee.
1038 Exception thrown if the storage cannot
1039 grow, or if a size limit would be
1040 exceeded.
1041
1042 @throw std::length_error
1043 The storage cannot accommodate the field;
1044 see @ref max_name_size, @ref max_value_size,
1045 @ref max_field_count, and @ref max_buffer_size.
1046
1047 @param name The field name.
1048
1049 @param value The field value.
1050 */
1051 void
1052 66106x append(
1053 std::string_view name,
1054 std::string_view value)
1055 {
1056 66106x insert_(count_, resolve_(name), name, value);
1057 66089x }
1058
1059 /** Append fields.
1060
1061 This function appends the fields in `init`
1062 in order, as if by calling @ref append for
1063 each element. Existing fields with the same
1064 names are not changed.
1065
1066 The names and values are stored verbatim.
1067
1068 All references and views are invalidated.
1069 No iterators are invalidated.
1070
1071 @par Example
1072 @code
1073 f.append({
1074 { http::field::host, "example.com" },
1075 { "User-Agent", "Boost" } });
1076 @endcode
1077
1078 @par Complexity
1079 Linear in the total size of the names and
1080 values in `init`.
1081
1082 @par Exception Safety
1083 Strong guarantee.
1084 Exception thrown if the storage cannot
1085 grow, or if a size limit would be
1086 exceeded.
1087
1088 @throw std::length_error
1089 The storage cannot accommodate the fields;
1090 see @ref max_name_size, @ref max_value_size,
1091 @ref max_field_count, and @ref max_buffer_size.
1092
1093 @param init The fields to append.
1094 */
1095 BOOST_BURL_DECL
1096 void
1097 append(std::initializer_list<field_view> init);
1098
1099 /** Insert a field.
1100
1101 If a matching field with the same name
1102 exists, it is not replaced. Instead, an
1103 additional field is inserted using the
1104 canonical name of `id`.
1105
1106 The value is stored verbatim.
1107
1108 All references and views are invalidated, as
1109 are iterators at or after `before`.
1110
1111 @par Example
1112 @code
1113 f.insert( f.begin(), http::field::user_agent, "Boost" );
1114 @endcode
1115
1116 @par Complexity
1117 Linear in `to_string( id ).size() + value.size()`
1118 plus the size of the fields after `before`.
1119
1120 @par Exception Safety
1121 Strong guarantee.
1122 Exception thrown if the storage cannot
1123 grow, or if a size limit would be
1124 exceeded.
1125
1126 @throw std::length_error
1127 The storage cannot accommodate the field;
1128 see @ref max_name_size, @ref max_value_size,
1129 @ref max_field_count, and @ref max_buffer_size.
1130
1131 @return An iterator to the newly inserted field.
1132
1133 @param before Position to insert before.
1134
1135 @param id The field name constant.
1136
1137 @param value The field value.
1138 */
1139 iterator
1140 2x insert(
1141 iterator before,
1142 http::field id,
1143 std::string_view value)
1144 {
1145
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2x BOOST_ASSERT(before.f_ == this);
1146
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2x BOOST_ASSERT(id != unknown_field);
1147 4x return iterator(
1148 this,
1149 4x insert_(
1150
1/1
✓ Branch 1 taken 2 times.
2x before.i_,
1151 static_cast<std::uint16_t>(id),
1152
1/1
✓ Branch 1 taken 2 times.
2x http::to_string(id),
1153 2x value));
1154 }
1155
1156 /** Insert a field.
1157
1158 If a matching field with the same name
1159 exists, it is not replaced. Instead, an
1160 additional field with the same name is
1161 inserted.
1162
1163 The name and value are stored verbatim.
1164 When `name` equals a known field name, the
1165 corresponding field constant is stored
1166 with it, and subsequent lookups by id
1167 succeed regardless of how the field was
1168 added.
1169
1170 All references and views are invalidated, as
1171 are iterators at or after `before`.
1172
1173 @par Example
1174 @code
1175 f.insert( f.begin(), "User-Agent", "Boost" );
1176 @endcode
1177
1178 @par Complexity
1179 Linear in `name.size() + value.size()`
1180 plus the size of the fields after `before`.
1181
1182 @par Exception Safety
1183 Strong guarantee.
1184 Exception thrown if the storage cannot
1185 grow, or if a size limit would be
1186 exceeded.
1187
1188 @throw std::length_error
1189 The storage cannot accommodate the field;
1190 see @ref max_name_size, @ref max_value_size,
1191 @ref max_field_count, and @ref max_buffer_size.
1192
1193 @return An iterator to the newly inserted field.
1194
1195 @param before Position to insert before.
1196
1197 @param name The field name.
1198
1199 @param value The field value.
1200 */
1201 iterator
1202 6x insert(
1203 iterator before,
1204 std::string_view name,
1205 std::string_view value)
1206 {
1207
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6x BOOST_ASSERT(before.f_ == this);
1208
1/1
✓ Branch 2 taken 4 times.
6x return iterator(this, insert_(before.i_, resolve_(name), name, value));
1209 }
1210
1211 /** Set a field value.
1212
1213 Uses the given value to overwrite the
1214 current one in the field pointed to by
1215 the iterator. No other fields are
1216 affected.
1217
1218 The value is stored verbatim.
1219
1220 All references and views are invalidated.
1221 No iterators are invalidated.
1222
1223 @par Complexity
1224 Linear in `this->buffer().size()`.
1225
1226 @par Exception Safety
1227 Strong guarantee.
1228 Exception thrown if the storage cannot
1229 grow, or if a size limit would be
1230 exceeded.
1231
1232 @throw std::length_error
1233 The storage cannot accommodate the value;
1234 see @ref max_value_size and
1235 @ref max_buffer_size.
1236
1237 @param it The iterator to the field. Must
1238 be dereferenceable.
1239
1240 @param value The field value.
1241 */
1242 void
1243 6x set(
1244 iterator it,
1245 std::string_view value)
1246 {
1247
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6x BOOST_ASSERT(it.f_ == this);
1248
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6x BOOST_ASSERT(it.i_ < count_);
1249 6x replace_value_(it.i_, value);
1250 5x }
1251
1252 /** Set a field value, removing duplicates.
1253
1254 The container is modified to contain
1255 exactly one field with the specified id
1256 set to the given value: if a matching
1257 field exists, its value is replaced in
1258 place and the remaining duplicates are
1259 removed; otherwise the field is appended.
1260
1261 The value is stored verbatim.
1262
1263 All references and views are invalidated.
1264 Iterators at or after the first removed
1265 duplicate are invalidated; if there are no
1266 duplicates, no iterators are invalidated.
1267
1268 @par Postconditions
1269 @code
1270 this->count( id ) == 1 && this->at( id ) == value
1271 @endcode
1272
1273 @par Complexity
1274 Linear in `this->buffer().size()`.
1275
1276 @par Exception Safety
1277 Strong guarantee.
1278 Exception thrown if the storage cannot
1279 grow, or if a size limit would be
1280 exceeded.
1281
1282 @throw std::length_error
1283 The storage cannot accommodate the value;
1284 see @ref max_value_size and
1285 @ref max_buffer_size.
1286
1287 @param id The field name constant.
1288
1289 @param value The field value.
1290 */
1291 BOOST_BURL_DECL
1292 void
1293 set(
1294 http::field id,
1295 std::string_view value);
1296
1297 /** Set a field value, removing duplicates.
1298
1299 The container is modified to contain
1300 exactly one field with the specified name
1301 set to the given value: if a matching
1302 field exists, its value is replaced in
1303 place and the remaining duplicates are
1304 removed; otherwise the field is appended.
1305 The comparison is case-insensitive.
1306
1307 The name and value are stored verbatim.
1308
1309 All references and views are invalidated.
1310 Iterators at or after the first removed
1311 duplicate are invalidated; if there are no
1312 duplicates, no iterators are invalidated.
1313
1314 @par Postconditions
1315 @code
1316 this->count( name ) == 1 && this->at( name ) == value
1317 @endcode
1318
1319 @par Complexity
1320 Linear in `this->buffer().size()`.
1321
1322 @par Exception Safety
1323 Strong guarantee.
1324 Exception thrown if the storage cannot
1325 grow, or if a size limit would be
1326 exceeded.
1327
1328 @throw std::length_error
1329 The storage cannot accommodate the field;
1330 see @ref max_name_size, @ref max_value_size,
1331 @ref max_field_count, and @ref max_buffer_size.
1332
1333 @param name The field name.
1334
1335 @param value The field value.
1336 */
1337 BOOST_BURL_DECL
1338 void
1339 set(
1340 std::string_view name,
1341 std::string_view value);
1342
1343 /** Erase all matching fields.
1344
1345 This removes all fields whose name
1346 constant is equal to `id`.
1347
1348 If any fields are erased, all references and
1349 views are invalidated, as are iterators at or
1350 after the first erased field. Otherwise,
1351 nothing is invalidated.
1352
1353 @par Complexity
1354 Linear in `this->buffer().size()`.
1355
1356 @return The number of fields erased.
1357
1358 @param id The field name constant.
1359 */
1360 BOOST_BURL_DECL
1361 std::size_t
1362 erase(http::field id) noexcept;
1363
1364 /** Erase all matching fields.
1365
1366 This removes all fields with a matching
1367 name, using a case-insensitive comparison.
1368
1369 If any fields are erased, all references and
1370 views are invalidated, as are iterators at or
1371 after the first erased field. Otherwise,
1372 nothing is invalidated.
1373
1374 If `name` refers to a known field, it is
1375 faster to call @ref erase with a field id
1376 instead of a string.
1377
1378 @par Complexity
1379 Linear in `this->buffer().size()`.
1380
1381 @return The number of fields erased.
1382
1383 @param name The field name.
1384 */
1385 BOOST_BURL_DECL
1386 std::size_t
1387 erase(std::string_view name) noexcept;
1388
1389 /** Erase a field.
1390
1391 This removes the field pointed to by
1392 `pos`.
1393
1394 All references and views are invalidated, as
1395 are iterators at or after `pos`.
1396
1397 @par Complexity
1398 Linear in the size of the fields after
1399 `pos`.
1400
1401 @return An iterator to one past the
1402 removed element.
1403
1404 @param pos The iterator to the element to
1405 erase. Must be dereferenceable.
1406 */
1407 iterator
1408 109x erase(iterator pos) noexcept
1409 {
1410
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 109 times.
109x BOOST_ASSERT(pos.f_ == this);
1411
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 109 times.
109x BOOST_ASSERT(pos.i_ < count_);
1412 109x erase_at_(pos.i_);
1413 109x return iterator(this, pos.i_);
1414 }
1415
1416 /** Erase all fields.
1417
1418 The start line of header containers is
1419 preserved. The capacity is unchanged.
1420
1421 All iterators, references, and views are
1422 invalidated.
1423
1424 @par Postconditions
1425 @code
1426 this->size() == 0
1427 @endcode
1428
1429 @par Complexity
1430 Constant.
1431 */
1432 BOOST_BURL_DECL
1433 void
1434 clear() noexcept;
1435
1436 protected:
1437 struct entry
1438 {
1439 std::uint32_t of;
1440 std::uint16_t id;
1441 std::uint16_t nn;
1442 std::uint16_t ws;
1443 std::uint16_t vn;
1444 };
1445
1446 struct piece
1447 {
1448 std::size_t at;
1449 std::string_view src;
1450 };
1451
1452 BOOST_BURL_DECL
1453 fields_base() noexcept;
1454
1455 42022x fields_base(
1456 char* base,
1457 std::size_t cap,
1458 std::uint32_t size,
1459 std::uint16_t count,
1460 std::uint16_t prefix = 0) noexcept
1461 42022x : buf_(base + prefix)
1462 42022x , end_(base + cap)
1463 42022x , size_(size)
1464 42022x , count_(count)
1465 42022x , prefix_(prefix)
1466 {
1467 42022x }
1468
1469 637x fields_base(fields_base const&) = default;
1470
1471 BOOST_BURL_DECL
1472 fields_base&
1473 operator=(fields_base const& other);
1474
1475 ~fields_base() = default;
1476
1477 BOOST_BURL_DECL
1478 void
1479 swap_(fields_base& other) noexcept;
1480
1481 virtual
1482 bool
1483 26x static_() const noexcept
1484 {
1485 26x return true;
1486 }
1487
1488 virtual
1489 void
1490 2x on_clear_() noexcept
1491 {
1492 2x }
1493
1494 virtual
1495 void
1496 7x on_special_(http::field) noexcept
1497 {
1498 7x }
1499
1500 char*
1501 774126x base_() const noexcept
1502 {
1503 774126x return buf_ - prefix_;
1504 }
1505
1506 void
1507 10x detach_()
1508 {
1509
2/2
✓ Branch 1 taken 4 times.
✓ Branch 2 taken 6 times.
10x if(default_())
1510 4x realloc_(table_space_(count_) + size_ + prefix_);
1511 10x }
1512
1513 BOOST_BURL_DECL
1514 void
1515 release_() noexcept;
1516
1517 BOOST_BURL_DECL
1518 void
1519 init_static_(
1520 char* storage,
1521 std::size_t n);
1522
1523 BOOST_BURL_DECL
1524 char*
1525 splice_prefix_(
1526 std::uint32_t pos,
1527 std::uint32_t old_n,
1528 std::size_t new_n,
1529 piece p0 = {},
1530 piece p1 = {});
1531
1532 BOOST_BURL_DECL
1533 void
1534 assign_(
1535 fields_base const& other,
1536 std::uint16_t prefix);
1537
1538 BOOST_BURL_DECL
1539 void
1540 reserve_(
1541 std::size_t bytes,
1542 std::size_t count);
1543
1544 BOOST_BURL_DECL
1545 void
1546 shrink_to_fit_();
1547
1548 entry&
1549 41669x ent_(std::uint16_t i) const noexcept
1550 {
1551 41669x return ent_(tab_(), i);
1552 }
1553
1554 BOOST_BURL_DECL
1555 static std::uint16_t
1556 resolve_(std::string_view name) noexcept;
1557
1558 static
1559 constexpr
1560 std::size_t
1561 263757x table_space_(std::size_t count) noexcept
1562 {
1563 263757x return sizeof(entry) * count;
1564 }
1565
1566 /*
1567 +------------+--------+------+-----------------------------+
1568 | start line | fields | free | entry[count-1] ... entry[0] |
1569 +------------+--------+------+-----------------------------+
1570 ^ ^ ^ ^
1571 | buf buf + size end
1572 buf - prefix
1573 */
1574
1575 char* buf_;
1576 char* end_;
1577 std::uint32_t size_;
1578 std::uint16_t count_;
1579 std::uint16_t prefix_;
1580
1581 private:
1582 struct alloc;
1583
1584 void
1585 adopt_(alloc& a) noexcept;
1586
1587 constexpr static http::field unknown_field =
1588 static_cast<http::field>(0);
1589
1590 bool
1591 1897x default_() const noexcept
1592 {
1593 1897x return end_ == base_();
1594 }
1595
1596 bool
1597 1685x owns_() const noexcept
1598 {
1599
3/4
✓ Branch 1 taken 912 times.
✓ Branch 2 taken 773 times.
✓ Branch 4 taken 912 times.
✗ Branch 5 not taken.
1685x return ! default_() && ! static_();
1600 }
1601
1602 entry*
1603 109911x tab_() const noexcept
1604 {
1605 109911x return reinterpret_cast<entry*>(end_);
1606 }
1607
1608 static entry&
1609 164779x ent_(
1610 entry* t,
1611 std::uint16_t i) noexcept
1612 {
1613 164779x return *(t - 1 - static_cast<std::ptrdiff_t>(i));
1614 }
1615
1616 field_view
1617 3012x ref_(std::uint16_t i) const noexcept
1618 {
1619 3012x auto const& e = ent_(i);
1620 return
1621 {
1622 3012x { buf_ + e.of, e.nn },
1623 3012x { buf_ + e.of + e.nn + e.ws, e.vn },
1624 3012x static_cast<http::field>(e.id)
1625 3012x };
1626 }
1627
1628 std::uint32_t
1629 10178x line_len_(std::uint16_t i) const noexcept
1630 {
1631 10178x auto const of = ent_(i).of;
1632
2/2
✓ Branch 0 taken 139 times.
✓ Branch 1 taken 10039 times.
10178x if(i + 1 == count_)
1633 139x return size_ - 2 - of;
1634 10039x return ent_(i + 1).of - of;
1635 }
1636
1637 char*
1638 splice_fields_(
1639 std::uint32_t pos,
1640 std::uint32_t old_n,
1641 std::size_t new_n,
1642 std::uint16_t added,
1643 piece p0,
1644 piece p1);
1645
1646 char*
1647 splice_(
1648 std::uint32_t pos,
1649 std::uint32_t old_n,
1650 std::size_t new_n,
1651 std::uint16_t added,
1652 piece p0,
1653 piece p1);
1654
1655 BOOST_BURL_DECL
1656 void
1657 realloc_(std::size_t total);
1658
1659 static void
1660 fill_(
1661 char* g,
1662 piece const& p0,
1663 piece const& p1) noexcept;
1664
1665 BOOST_BURL_DECL
1666 std::uint16_t
1667 find_(
1668 std::uint16_t from,
1669 http::field id) const noexcept;
1670
1671 BOOST_BURL_DECL
1672 std::uint16_t
1673 find_(
1674 std::uint16_t from,
1675 std::string_view name) const noexcept;
1676
1677 BOOST_BURL_DECL
1678 std::uint16_t
1679 find_last_(
1680 std::uint16_t before,
1681 http::field id) const noexcept;
1682
1683 BOOST_BURL_DECL
1684 std::uint16_t
1685 find_last_(
1686 std::uint16_t before,
1687 std::string_view name) const noexcept;
1688
1689 void
1690 notify_(std::uint16_t id) noexcept;
1691
1692 BOOST_BURL_DECL
1693 std::uint16_t
1694 insert_(
1695 std::uint16_t i,
1696 std::uint16_t id,
1697 std::string_view name,
1698 std::string_view value);
1699
1700 BOOST_BURL_DECL
1701 void
1702 replace_value_(
1703 std::uint16_t i,
1704 std::string_view value);
1705
1706 BOOST_BURL_DECL
1707 void
1708 erase_at_(std::uint16_t i) noexcept;
1709
1710 template<class Match>
1711 std::uint16_t
1712 erase_all_(
1713 std::uint16_t i,
1714 std::uint16_t id,
1715 Match const& match) noexcept;
1716
1717 std::uint16_t
1718 erase_all_(
1719 std::uint16_t i,
1720 std::uint16_t id) noexcept;
1721
1722 std::uint16_t
1723 erase_all_(
1724 std::uint16_t i,
1725 std::string_view name) noexcept;
1726
1727 void
1728 erase_dups_(std::uint16_t i) noexcept;
1729 };
1730
1731 } // namespace burl
1732 } // namespace boost
1733
1734 #endif
1735