src/fields_base.cpp
99.3% Lines (454/457)
100.0% List of functions (51/51)
91.3% Branches (209/229)
Functions (51)
Function
Calls
Lines
Branches
Blocks
boost::burl::(anonymous namespace)::to_lower(char)
:34
33182x
100.0%
100.0%
100.0%
boost::burl::(anonymous namespace)::ci_equal_rev(char const*, char const*, unsigned long)
:42
16369x
100.0%
100.0%
100.0%
boost::burl::(anonymous namespace)::grow_size(unsigned long, unsigned long)
:75
757x
75.0%
50.0%
83.0%
boost::burl::fields_base::fields_base()
:86
389x
100.0%
–
100.0%
boost::burl::fields_base::alloc::alloc(unsigned long)
:98
903x
100.0%
–
100.0%
boost::burl::fields_base::alloc::~alloc()
:106
903x
75.0%
50.0%
67.0%
boost::burl::fields_base::alloc::size_for(unsigned long)
:114
912x
100.0%
–
100.0%
boost::burl::fields_base::release_()
:128
1675x
100.0%
100.0%
100.0%
boost::burl::fields_base::adopt_(boost::burl::fields_base::alloc&)
:136
903x
100.0%
–
100.0%
boost::burl::fields_base::init_static_(char*, unsigned long)
:146
30x
100.0%
100.0%
100.0%
boost::burl::fields_base::realloc_(unsigned long)
:162
60x
100.0%
100.0%
100.0%
boost::burl::fields_base::operator=(boost::burl::fields_base const&)
:175
99x
100.0%
100.0%
100.0%
boost::burl::fields_base::swap_(boost::burl::fields_base&)
:184
193x
100.0%
–
100.0%
boost::burl::fields_base::assign_(boost::burl::fields_base const&, unsigned short)
:194
113x
100.0%
86.7%
93.0%
boost::burl::fields_base::reserve_(unsigned long, unsigned long)
:223
59x
100.0%
90.0%
100.0%
boost::burl::fields_base::shrink_to_fit_()
:245
10x
100.0%
100.0%
100.0%
boost::burl::fields_base::fill_(char*, boost::burl::fields_base::piece const&, boost::burl::fields_base::piece const&)
:256
66899x
100.0%
–
100.0%
boost::burl::fields_base::fill_(char*, boost::burl::fields_base::piece const&, boost::burl::fields_base::piece const&)::{lambda(char*, std::basic_string_view<char, std::char_traits<char> >)#1}::operator()(char*, std::basic_string_view<char, std::char_traits<char> >) const
:262
133798x
100.0%
100.0%
100.0%
boost::burl::fields_base::fill_(char*, boost::burl::fields_base::piece const&, boost::burl::fields_base::piece const&)::{lambda(char const*, unsigned long, std::basic_string_view<char, std::char_traits<char> >)#1}::operator()(char const*, unsigned long, std::basic_string_view<char, std::char_traits<char> >) const
:268
66899x
100.0%
100.0%
100.0%
boost::burl::fields_base::splice_(unsigned int, unsigned int, unsigned long, unsigned short, boost::burl::fields_base::piece, boost::burl::fields_base::piece)
:289
66916x
96.9%
80.0%
90.0%
boost::burl::fields_base::splice_(unsigned int, unsigned int, unsigned long, unsigned short, boost::burl::fields_base::piece, boost::burl::fields_base::piece)::{lambda(boost::burl::fields_base::piece)#1}::operator()(boost::burl::fields_base::piece) const
:351
132184x
100.0%
100.0%
100.0%
boost::burl::fields_base::splice_fields_(unsigned int, unsigned int, unsigned long, unsigned short, boost::burl::fields_base::piece, boost::burl::fields_base::piece)
:373
66673x
100.0%
–
100.0%
boost::burl::fields_base::splice_prefix_(unsigned int, unsigned int, unsigned long, boost::burl::fields_base::piece, boost::burl::fields_base::piece)
:391
252x
100.0%
75.0%
89.0%
boost::burl::fields_base::notify_(unsigned short)
:410
66920x
100.0%
100.0%
100.0%
boost::burl::fields_base::resolve_(std::basic_string_view<char, std::char_traits<char> >)
:434
83750x
100.0%
100.0%
100.0%
boost::burl::fields_base::find_(unsigned short, boost::http::field) const
:444
901x
100.0%
100.0%
100.0%
boost::burl::fields_base::find_(unsigned short, std::basic_string_view<char, std::char_traits<char> >) const
:458
421x
100.0%
100.0%
100.0%
boost::burl::fields_base::find_last_(unsigned short, boost::http::field) const
:475
294x
100.0%
83.3%
90.0%
boost::burl::fields_base::find_last_(unsigned short, std::basic_string_view<char, std::char_traits<char> >) const
:493
5x
100.0%
80.0%
94.0%
boost::burl::fields_base::at(boost::http::field) const
:512
68x
100.0%
100.0%
100.0%
boost::burl::fields_base::at(std::basic_string_view<char, std::char_traits<char> >) const
:522
80x
100.0%
100.0%
100.0%
boost::burl::fields_base::count(boost::http::field) const
:532
13x
100.0%
100.0%
100.0%
boost::burl::fields_base::count(std::basic_string_view<char, std::char_traits<char> >) const
:547
8x
100.0%
100.0%
100.0%
boost::burl::fields_base::subrange::iterator::operator++()
:562
187x
100.0%
83.3%
91.0%
boost::burl::fields_base::append(std::initializer_list<boost::burl::fields_base::field_view>)
:601
37x
100.0%
100.0%
100.0%
boost::burl::fields_base::insert_(unsigned short, unsigned short, std::basic_string_view<char, std::char_traits<char> >, std::basic_string_view<char, std::char_traits<char> >)
:626
66644x
100.0%
85.7%
94.0%
boost::burl::fields_base::replace_value_(unsigned short, std::basic_string_view<char, std::char_traits<char> >)
:665
38x
100.0%
83.3%
95.0%
boost::burl::fields_base::erase_at_(unsigned short)
:694
109x
100.0%
75.0%
92.0%
unsigned short boost::burl::fields_base::erase_all_<boost::burl::fields_base::erase_all_(unsigned short, std::basic_string_view<char, std::char_traits<char> >)::{lambda(boost::burl::fields_base::entry const&)#1}>(unsigned short, unsigned short, boost::burl::fields_base::erase_all_(unsigned short, std::basic_string_view<char, std::char_traits<char> >)::{lambda(boost::burl::fields_base::entry const&)#1} const&)
:716
105x
100.0%
90.0%
96.0%
unsigned short boost::burl::fields_base::erase_all_<boost::burl::fields_base::erase_all_(unsigned short, unsigned short)::{lambda(boost::burl::fields_base::entry const&)#1}>(unsigned short, unsigned short, boost::burl::fields_base::erase_all_(unsigned short, unsigned short)::{lambda(boost::burl::fields_base::entry const&)#1} const&)
:716
47x
100.0%
90.0%
96.0%
boost::burl::fields_base::erase_all_(unsigned short, unsigned short)
:765
47x
100.0%
–
100.0%
boost::burl::fields_base::erase_all_(unsigned short, unsigned short)::{lambda(boost::burl::fields_base::entry const&)#1}::operator()(boost::burl::fields_base::entry const&) const
:771
81x
100.0%
–
100.0%
boost::burl::fields_base::erase_all_(unsigned short, std::basic_string_view<char, std::char_traits<char> >)
:778
105x
100.0%
–
100.0%
boost::burl::fields_base::erase_all_(unsigned short, std::basic_string_view<char, std::char_traits<char> >)::{lambda(boost::burl::fields_base::entry const&)#1}::operator()(boost::burl::fields_base::entry const&) const
:784
10112x
100.0%
100.0%
100.0%
boost::burl::fields_base::erase_dups_(unsigned short)
:792
31x
100.0%
100.0%
100.0%
boost::burl::fields_base::set(boost::http::field, std::basic_string_view<char, std::char_traits<char> >)
:812
301x
100.0%
100.0%
100.0%
boost::burl::fields_base::set(std::basic_string_view<char, std::char_traits<char> >, std::basic_string_view<char, std::char_traits<char> >)
:825
9x
100.0%
100.0%
100.0%
boost::burl::fields_base::erase(boost::http::field)
:838
167x
100.0%
100.0%
100.0%
boost::burl::fields_base::erase(std::basic_string_view<char, std::char_traits<char> >)
:848
105x
100.0%
100.0%
100.0%
boost::burl::fields_base::clear()
:858
6x
100.0%
100.0%
100.0%
boost::burl::operator<<(std::ostream&, boost::burl::fields_base const&)
:871
6x
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 | #include <boost/burl/fields_base.hpp> | |||
| 12 | ||||
| 13 | #include "detail/except.hpp" | |||
| 14 | ||||
| 15 | #include <boost/throw_exception.hpp> | |||
| 16 | ||||
| 17 | #include <algorithm> | |||
| 18 | #include <cstring> | |||
| 19 | #include <new> | |||
| 20 | #include <ostream> | |||
| 21 | #include <utility> | |||
| 22 | ||||
| 23 | namespace boost | |||
| 24 | { | |||
| 25 | namespace burl | |||
| 26 | { | |||
| 27 | ||||
| 28 | namespace | |||
| 29 | { | |||
| 30 | ||||
| 31 | char buf[] = "\r\n"; | |||
| 32 | ||||
| 33 | constexpr char | |||
| 34 | 33182x | to_lower(char c) noexcept | ||
| 35 | { | |||
| 36 |
4/4✓ Branch 0 taken 1062 times.
✓ Branch 1 taken 32120 times.
✓ Branch 2 taken 553 times.
✓ Branch 3 taken 509 times.
|
33182x | if(c >= 'A' && c <= 'Z') | |
| 37 | 553x | return static_cast<char>(c - 'A' + 'a'); | ||
| 38 | 32629x | return c; | ||
| 39 | } | |||
| 40 | ||||
| 41 | bool | |||
| 42 | 16369x | ci_equal_rev( | ||
| 43 | char const* p1, | |||
| 44 | char const* p2, | |||
| 45 | std::size_t n) noexcept | |||
| 46 | { | |||
| 47 | 16369x | p1 += n; | ||
| 48 | 16369x | p2 += n; | ||
| 49 | char a, b; | |||
| 50 | // fast loop | |||
| 51 |
2/2✓ Branch 0 taken 21300 times.
✓ Branch 1 taken 297 times.
|
21597x | while(n != 0) | |
| 52 | { | |||
| 53 | 21300x | --n; | ||
| 54 | 21300x | a = *--p1; | ||
| 55 | 21300x | b = *--p2; | ||
| 56 |
2/2✓ Branch 0 taken 16072 times.
✓ Branch 1 taken 5228 times.
|
21300x | if(a != b) | |
| 57 | 16072x | goto slow; | ||
| 58 | } | |||
| 59 | 297x | return true; | ||
| 60 | for(;;) | |||
| 61 | { | |||
| 62 | 519x | a = *--p1; | ||
| 63 | 519x | b = *--p2; | ||
| 64 | 16591x | slow: | ||
| 65 |
2/2✓ Branch 2 taken 15839 times.
✓ Branch 3 taken 752 times.
|
16591x | if(to_lower(a) != to_lower(b)) | |
| 66 | 15839x | return false; | ||
| 67 |
2/2✓ Branch 0 taken 233 times.
✓ Branch 1 taken 519 times.
|
752x | if(n == 0) | |
| 68 | 233x | break; | ||
| 69 | 519x | --n; | ||
| 70 | } | |||
| 71 | 233x | return true; | ||
| 72 | } | |||
| 73 | ||||
| 74 | std::size_t | |||
| 75 | 757x | grow_size( | ||
| 76 | std::size_t need, | |||
| 77 | std::size_t cap) noexcept | |||
| 78 | { | |||
| 79 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 757 times.
|
757x | if(cap > std::size_t(-1) - cap) | |
| 80 | ✗ | return need; | ||
| 81 | 757x | return (std::max)(need, 2 * cap); | ||
| 82 | } | |||
| 83 | ||||
| 84 | } // namespace | |||
| 85 | ||||
| 86 | 389x | fields_base:: | ||
| 87 | 389x | fields_base() noexcept | ||
| 88 | 389x | : fields_base(buf, 0, 2, 0) | ||
| 89 | { | |||
| 90 | 389x | } | ||
| 91 | ||||
| 92 | struct fields_base::alloc | |||
| 93 | { | |||
| 94 | std::size_t n; | |||
| 95 | char* p; | |||
| 96 | ||||
| 97 | explicit | |||
| 98 | 903x | alloc(std::size_t n_) | ||
| 99 | 903x | : n(size_for(n_)) | ||
| 100 | 903x | , p(static_cast<char*>(::operator new(n))) | ||
| 101 | { | |||
| 102 | 903x | } | ||
| 103 | ||||
| 104 | alloc(alloc const&) = delete; | |||
| 105 | ||||
| 106 | 903x | ~alloc() | ||
| 107 | { | |||
| 108 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 903 times.
|
903x | if(p) | |
| 109 | ✗ | ::operator delete(p); | ||
| 110 | 903x | } | ||
| 111 | ||||
| 112 | static | |||
| 113 | std::size_t | |||
| 114 | 912x | size_for(std::size_t n) noexcept | ||
| 115 | { | |||
| 116 | 912x | constexpr auto align = alignof(entry); | ||
| 117 | 912x | return (n + (align - 1)) & ~(align - 1); | ||
| 118 | } | |||
| 119 | }; | |||
| 120 | ||||
| 121 | //------------------------------------------------ | |||
| 122 | // | |||
| 123 | // Owning storage | |||
| 124 | // | |||
| 125 | //------------------------------------------------ | |||
| 126 | ||||
| 127 | void | |||
| 128 | 1675x | fields_base:: | ||
| 129 | release_() noexcept | |||
| 130 | { | |||
| 131 |
2/2✓ Branch 1 taken 903 times.
✓ Branch 2 taken 772 times.
|
1675x | if(owns_()) | |
| 132 | 903x | ::operator delete(base_()); | ||
| 133 | 1675x | } | ||
| 134 | ||||
| 135 | void | |||
| 136 | 903x | fields_base:: | ||
| 137 | adopt_(alloc& a) noexcept | |||
| 138 | { | |||
| 139 | 903x | release_(); | ||
| 140 | 903x | end_ = a.p + a.n; | ||
| 141 | 903x | buf_ = a.p + prefix_; | ||
| 142 | 903x | a.p = nullptr; | ||
| 143 | 903x | } | ||
| 144 | ||||
| 145 | void | |||
| 146 | 30x | fields_base:: | ||
| 147 | init_static_( | |||
| 148 | char* storage, | |||
| 149 | std::size_t n) | |||
| 150 | { | |||
| 151 | 30x | auto const a = reinterpret_cast<std::uintptr_t>(storage); | ||
| 152 | 30x | auto const e = (a + n) & ~std::uintptr_t(alignof(entry) - 1); | ||
| 153 | 30x | auto const need = std::size_t(prefix_) + size_; | ||
| 154 |
2/2✓ Branch 0 taken 3 times.
✓ Branch 1 taken 27 times.
|
30x | if(e < a + need) | |
| 155 | 3x | detail::throw_length_error("buffer too small"); | ||
| 156 | 27x | std::memcpy(storage, base_(), need); | ||
| 157 | 27x | buf_ = storage + prefix_; | ||
| 158 | 27x | end_ = storage + (e - a); | ||
| 159 | 27x | } | ||
| 160 | ||||
| 161 | void | |||
| 162 | 60x | fields_base:: | ||
| 163 | realloc_(std::size_t total) | |||
| 164 | { | |||
| 165 |
2/2✓ Branch 1 taken 1 time.
✓ Branch 2 taken 59 times.
|
60x | if(static_()) | |
| 166 | 1x | detail::throw_length_error("buffer limit exceeded"); | ||
| 167 | 59x | auto const tn = table_space_(count_); | ||
| 168 |
1/1✓ Branch 1 taken 59 times.
|
59x | alloc a(total); | |
| 169 | 59x | std::memcpy(a.p, base_(), std::size_t(prefix_) + size_); | ||
| 170 | 59x | std::memcpy(a.p + a.n - tn, end_ - tn, tn); | ||
| 171 | 59x | adopt_(a); | ||
| 172 | 59x | } | ||
| 173 | ||||
| 174 | fields_base& | |||
| 175 | 99x | fields_base:: | ||
| 176 | operator=(fields_base const& other) | |||
| 177 | { | |||
| 178 |
2/2✓ Branch 0 taken 95 times.
✓ Branch 1 taken 4 times.
|
99x | if(this != &other) | |
| 179 | 95x | assign_(other, other.prefix_); | ||
| 180 | 93x | return *this; | ||
| 181 | } | |||
| 182 | ||||
| 183 | void | |||
| 184 | 193x | fields_base::swap_(fields_base& other) noexcept | ||
| 185 | { | |||
| 186 | 193x | std::swap(buf_, other.buf_); | ||
| 187 | 193x | std::swap(end_, other.end_); | ||
| 188 | 193x | std::swap(size_, other.size_); | ||
| 189 | 193x | std::swap(count_, other.count_); | ||
| 190 | 193x | std::swap(prefix_, other.prefix_); | ||
| 191 | 193x | } | ||
| 192 | ||||
| 193 | void | |||
| 194 | 113x | fields_base:: | ||
| 195 | assign_( | |||
| 196 | fields_base const& other, | |||
| 197 | std::uint16_t prefix) | |||
| 198 | { | |||
| 199 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 113 times.
|
113x | BOOST_ASSERT(this != &other); | |
| 200 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 113 times.
|
113x | BOOST_ASSERT(prefix <= other.prefix_); | |
| 201 |
6/6✓ Branch 1 taken 89 times.
✓ Branch 2 taken 24 times.
✓ Branch 4 taken 3 times.
✓ Branch 5 taken 86 times.
✓ Branch 6 taken 3 times.
✓ Branch 7 taken 110 times.
|
113x | if(default_() && other.default_()) | |
| 202 | 3x | return; | ||
| 203 | 110x | auto const tn = table_space_(other.count_); | ||
| 204 | 110x | auto const need = std::size_t(prefix) + other.size_ + tn; | ||
| 205 |
2/2✓ Branch 1 taken 95 times.
✓ Branch 2 taken 15 times.
|
110x | if(need > capacity_in_bytes()) | |
| 206 | { | |||
| 207 |
2/2✓ Branch 1 taken 8 times.
✓ Branch 2 taken 87 times.
|
95x | if(static_()) | |
| 208 | 8x | detail::throw_length_error("buffer limit exceeded"); | ||
| 209 |
1/1✓ Branch 1 taken 87 times.
|
87x | alloc a(need); | |
| 210 | 87x | adopt_(a); | ||
| 211 | 87x | } | ||
| 212 | 102x | auto* const base = base_(); | ||
| 213 | 102x | buf_ = base + prefix; | ||
| 214 | 102x | size_ = other.size_; | ||
| 215 | 102x | count_ = other.count_; | ||
| 216 | 102x | prefix_ = prefix; | ||
| 217 | 102x | std::memcpy( | ||
| 218 | 102x | base, other.buf_ - prefix, std::size_t(prefix) + other.size_); | ||
| 219 | 102x | std::memcpy(end_ - tn, other.end_ - tn, tn); | ||
| 220 | } | |||
| 221 | ||||
| 222 | void | |||
| 223 | 59x | fields_base:: | ||
| 224 | reserve_( | |||
| 225 | std::size_t bytes, | |||
| 226 | std::size_t count) | |||
| 227 | { | |||
| 228 |
2/2✓ Branch 0 taken 2 times.
✓ Branch 1 taken 57 times.
|
59x | if(bytes > max_buffer_size) | |
| 229 | 2x | detail::throw_length_error("buffer limit exceeded"); | ||
| 230 |
2/2✓ Branch 0 taken 2 times.
✓ Branch 1 taken 55 times.
|
57x | if(count > max_field_count) | |
| 231 | 2x | detail::throw_length_error("field count too large"); | ||
| 232 | ||||
| 233 | 55x | bytes = (std::max)(bytes, std::size_t(size_)); | ||
| 234 | 55x | count = (std::max)(count, std::size_t(count_)); | ||
| 235 | ||||
| 236 |
3/4✓ Branch 0 taken 4 times.
✓ Branch 1 taken 51 times.
✓ Branch 2 taken 4 times.
✗ Branch 3 not taken.
|
55x | if(bytes <= size_ && count <= count_) | |
| 237 | 4x | return; | ||
| 238 | ||||
| 239 | 51x | auto const total = table_space_(count) + bytes + prefix_; | ||
| 240 |
2/2✓ Branch 1 taken 49 times.
✓ Branch 2 taken 2 times.
|
51x | if(total > capacity_in_bytes()) | |
| 241 | 49x | realloc_(total); | ||
| 242 | } | |||
| 243 | ||||
| 244 | void | |||
| 245 | 10x | fields_base:: | ||
| 246 | shrink_to_fit_() | |||
| 247 | { | |||
| 248 |
2/2✓ Branch 1 taken 1 time.
✓ Branch 2 taken 9 times.
|
10x | if(! owns_()) | |
| 249 | 1x | return; | ||
| 250 | 9x | auto const total = table_space_(count_) + size_ + prefix_; | ||
| 251 |
2/2✓ Branch 2 taken 7 times.
✓ Branch 3 taken 2 times.
|
9x | if(alloc::size_for(total) < capacity_in_bytes()) | |
| 252 | 7x | realloc_(total); | ||
| 253 | } | |||
| 254 | ||||
| 255 | void | |||
| 256 | 66899x | fields_base:: | ||
| 257 | fill_( | |||
| 258 | char* g, | |||
| 259 | piece const& p0, | |||
| 260 | piece const& p1) noexcept | |||
| 261 | { | |||
| 262 | 133798x | auto const put = [](char* d, std::string_view s) noexcept | ||
| 263 | { | |||
| 264 |
2/2✓ Branch 1 taken 68069 times.
✓ Branch 2 taken 65729 times.
|
133798x | if(!s.empty()) | |
| 265 | 68069x | std::memmove(d, s.data(), s.size()); | ||
| 266 | 133798x | }; | ||
| 267 | ||||
| 268 | 66899x | auto const overlaps = []( | ||
| 269 | char const* d, | |||
| 270 | std::size_t n, | |||
| 271 | std::string_view s) noexcept | |||
| 272 | { | |||
| 273 |
4/4✓ Branch 2 taken 449 times.
✓ Branch 3 taken 66450 times.
✓ Branch 5 taken 3 times.
✓ Branch 6 taken 446 times.
|
66899x | return d < s.data() + s.size() && s.data() < d + n; | |
| 274 | }; | |||
| 275 | ||||
| 276 |
2/2✓ Branch 2 taken 3 times.
✓ Branch 3 taken 66896 times.
|
66899x | if(overlaps(g + p0.at, p0.src.size(), p1.src)) | |
| 277 | { | |||
| 278 | 3x | put(g + p1.at, p1.src); | ||
| 279 | 3x | put(g + p0.at, p0.src); | ||
| 280 | } | |||
| 281 | else | |||
| 282 | { | |||
| 283 | 66896x | put(g + p0.at, p0.src); | ||
| 284 | 66896x | put(g + p1.at, p1.src); | ||
| 285 | } | |||
| 286 | 66899x | } | ||
| 287 | ||||
| 288 | char* | |||
| 289 | 66916x | fields_base:: | ||
| 290 | splice_( | |||
| 291 | std::uint32_t pos, | |||
| 292 | std::uint32_t old_n, | |||
| 293 | std::size_t new_n, | |||
| 294 | std::uint16_t added, | |||
| 295 | piece p0, | |||
| 296 | piece p1) | |||
| 297 | { | |||
| 298 | 66916x | auto* const base = base_(); | ||
| 299 | 66916x | auto const head = std::size_t(prefix_) + size_; | ||
| 300 | ||||
| 301 |
2/4✓ Branch 0 taken 66916 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 66916 times.
✗ Branch 3 not taken.
|
66916x | BOOST_ASSERT(pos <= head && old_n <= head - pos); | |
| 302 | ||||
| 303 | // checked before the sums below, so they cannot wrap | |||
| 304 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 66916 times.
|
66916x | if(new_n > max_buffer_size - (head - old_n)) | |
| 305 | ✗ | detail::throw_length_error("buffer limit exceeded"); | ||
| 306 | ||||
| 307 | auto const need = | |||
| 308 | 66916x | head - old_n + new_n + table_space_(count_ + added); | ||
| 309 | ||||
| 310 |
2/2✓ Branch 1 taken 774 times.
✓ Branch 2 taken 66142 times.
|
66916x | if(need > capacity_in_bytes()) | |
| 311 | { | |||
| 312 |
2/2✓ Branch 1 taken 17 times.
✓ Branch 2 taken 757 times.
|
774x | if(static_()) | |
| 313 | 17x | detail::throw_length_error("buffer limit exceeded"); | ||
| 314 | ||||
| 315 | 757x | auto const tn = table_space_(count_); | ||
| 316 |
1/1✓ Branch 3 taken 757 times.
|
757x | alloc a(grow_size(need, capacity_in_bytes())); | |
| 317 | ||||
| 318 | 757x | std::memcpy(a.p, base, pos); | ||
| 319 | 757x | std::memcpy( | ||
| 320 | 757x | a.p + pos + new_n, | ||
| 321 | 757x | base + pos + old_n, | ||
| 322 | 757x | head - pos - old_n); | ||
| 323 | 757x | std::memcpy(a.p + a.n - tn, end_ - tn, tn); | ||
| 324 | ||||
| 325 | 757x | auto* const g = a.p + pos; | ||
| 326 | 757x | fill_(g, p0, p1); | ||
| 327 | 757x | adopt_(a); | ||
| 328 | 757x | return g; | ||
| 329 | 757x | } | ||
| 330 | ||||
| 331 | 66142x | auto* const g = base + pos; | ||
| 332 | 66142x | auto const tail = head - pos - old_n; | ||
| 333 | ||||
| 334 |
2/2✓ Branch 0 taken 23 times.
✓ Branch 1 taken 66119 times.
|
66142x | if(new_n < old_n) | |
| 335 | { | |||
| 336 | // fill first: the sources may view the bytes the | |||
| 337 | // tail is about to slide over | |||
| 338 | ||||
| 339 | 23x | fill_(g, p0, p1); | ||
| 340 | 23x | std::memmove(g + new_n, g + old_n, tail); | ||
| 341 | } | |||
| 342 |
2/2✓ Branch 0 taken 66092 times.
✓ Branch 1 taken 27 times.
|
66119x | else if(new_n > old_n) | |
| 343 | { | |||
| 344 | 66092x | auto const delta = new_n - old_n; | ||
| 345 | 66092x | auto* const tail_end = g + old_n + tail; | ||
| 346 | ||||
| 347 | 66092x | std::memmove(g + new_n, g + old_n, tail); | ||
| 348 | ||||
| 349 | // a source which was in the tail moved with it | |||
| 350 | ||||
| 351 | 132184x | auto const slide = [&](piece p) noexcept | ||
| 352 | { | |||
| 353 | 132184x | if(!p.src.empty() && | ||
| 354 |
6/6✓ Branch 0 taken 66611 times.
✓ Branch 1 taken 65573 times.
✓ Branch 3 taken 541 times.
✓ Branch 4 taken 66070 times.
✓ Branch 5 taken 3 times.
✓ Branch 6 taken 132181 times.
|
132725x | p.src.data() >= g + old_n && | |
| 355 |
2/2✓ Branch 1 taken 3 times.
✓ Branch 2 taken 538 times.
|
541x | p.src.data() < tail_end) | |
| 356 | { | |||
| 357 | 3x | p.src = { p.src.data() + delta, p.src.size() }; | ||
| 358 | } | |||
| 359 | 132184x | return p; | ||
| 360 | 66092x | }; | ||
| 361 | ||||
| 362 | 66092x | fill_(g, slide(p0), slide(p1)); | ||
| 363 | } | |||
| 364 | else | |||
| 365 | { | |||
| 366 | 27x | fill_(g, p0, p1); | ||
| 367 | } | |||
| 368 | ||||
| 369 | 66142x | return g; | ||
| 370 | } | |||
| 371 | ||||
| 372 | char* | |||
| 373 | 66673x | fields_base:: | ||
| 374 | splice_fields_( | |||
| 375 | std::uint32_t pos, | |||
| 376 | std::uint32_t old_n, | |||
| 377 | std::size_t new_n, | |||
| 378 | std::uint16_t added, | |||
| 379 | piece p0, | |||
| 380 | piece p1) | |||
| 381 | { | |||
| 382 | 133332x | auto* const g = splice_( | ||
| 383 | 66673x | prefix_ + pos, old_n, new_n, added, p0, p1); | ||
| 384 | 66659x | buf_ = g - pos; | ||
| 385 | 66659x | size_ = static_cast<std::uint32_t>( | ||
| 386 | 66659x | size_ - old_n + new_n); | ||
| 387 | 66659x | return g; | ||
| 388 | } | |||
| 389 | ||||
| 390 | char* | |||
| 391 | 252x | fields_base:: | ||
| 392 | splice_prefix_( | |||
| 393 | std::uint32_t pos, | |||
| 394 | std::uint32_t old_n, | |||
| 395 | std::size_t new_n, | |||
| 396 | piece p0, | |||
| 397 | piece p1) | |||
| 398 | { | |||
| 399 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 252 times.
|
252x | BOOST_ASSERT(pos + old_n <= prefix_); | |
| 400 | 252x | auto const n = std::size_t(prefix_) - old_n + new_n; | ||
| 401 |
2/2✓ Branch 0 taken 9 times.
✓ Branch 1 taken 243 times.
|
252x | if(n > max_start_line_size) | |
| 402 | 9x | detail::throw_length_error("start line too large"); | ||
| 403 | 243x | auto* const g = splice_(pos, old_n, new_n, 0, p0, p1); | ||
| 404 | 240x | prefix_ = static_cast<std::uint16_t>(n); | ||
| 405 | 240x | buf_ = (g - pos) + prefix_; | ||
| 406 | 240x | return g; | ||
| 407 | } | |||
| 408 | ||||
| 409 | void | |||
| 410 | 66920x | fields_base::notify_(std::uint16_t id) noexcept | ||
| 411 | { | |||
| 412 | 66920x | auto const f = static_cast<http::field>(id); | ||
| 413 |
2/2✓ Branch 0 taken 296 times.
✓ Branch 1 taken 66624 times.
|
66920x | switch(f) | |
| 414 | { | |||
| 415 | 296x | case http::field::connection: | ||
| 416 | case http::field::content_length: | |||
| 417 | case http::field::expect: | |||
| 418 | case http::field::transfer_encoding: | |||
| 419 | case http::field::upgrade: | |||
| 420 | 296x | on_special_(f); | ||
| 421 | 296x | break; | ||
| 422 | 66624x | default: | ||
| 423 | 66624x | break; | ||
| 424 | } | |||
| 425 | 66920x | } | ||
| 426 | ||||
| 427 | //------------------------------------------------ | |||
| 428 | // | |||
| 429 | // Lookup | |||
| 430 | // | |||
| 431 | //------------------------------------------------ | |||
| 432 | ||||
| 433 | std::uint16_t | |||
| 434 | 83750x | fields_base:: | ||
| 435 | resolve_(std::string_view name) noexcept | |||
| 436 | { | |||
| 437 | 83750x | auto const f = http::string_to_field(name); | ||
| 438 |
2/2✓ Branch 1 taken 430 times.
✓ Branch 2 taken 83320 times.
|
83750x | if(f) | |
| 439 | 430x | return static_cast<std::uint16_t>(*f); | ||
| 440 | 83320x | return 0; | ||
| 441 | } | |||
| 442 | ||||
| 443 | std::uint16_t | |||
| 444 | 901x | fields_base:: | ||
| 445 | find_( | |||
| 446 | std::uint16_t from, | |||
| 447 | http::field id) const noexcept | |||
| 448 | { | |||
| 449 | 901x | auto const v = static_cast<std::uint16_t>(id); | ||
| 450 | 901x | auto* const et = tab_(); | ||
| 451 |
2/2✓ Branch 0 taken 751 times.
✓ Branch 1 taken 540 times.
|
1291x | for(auto i = from; i < count_; ++i) | |
| 452 |
2/2✓ Branch 1 taken 361 times.
✓ Branch 2 taken 390 times.
|
751x | if(ent_(et, i).id == v) | |
| 453 | 361x | return i; | ||
| 454 | 540x | return count_; | ||
| 455 | } | |||
| 456 | ||||
| 457 | std::uint16_t | |||
| 458 | 421x | fields_base:: | ||
| 459 | find_( | |||
| 460 | std::uint16_t from, | |||
| 461 | std::string_view name) const noexcept | |||
| 462 | { | |||
| 463 | 421x | auto const n = name.size(); | ||
| 464 | 421x | auto* const et = tab_(); | ||
| 465 |
2/2✓ Branch 0 taken 25380 times.
✓ Branch 1 taken 14 times.
|
25394x | for(auto i = from; i < count_; ++i) | |
| 466 | { | |||
| 467 | 25380x | auto const& e = ent_(et, i); | ||
| 468 |
6/6✓ Branch 0 taken 11691 times.
✓ Branch 1 taken 13689 times.
✓ Branch 4 taken 407 times.
✓ Branch 5 taken 11284 times.
✓ Branch 6 taken 407 times.
✓ Branch 7 taken 24973 times.
|
25380x | if(e.nn == n && ci_equal_rev(buf_ + e.of, name.data(), n)) | |
| 469 | 407x | return i; | ||
| 470 | } | |||
| 471 | 14x | return count_; | ||
| 472 | } | |||
| 473 | ||||
| 474 | std::uint16_t | |||
| 475 | 294x | fields_base:: | ||
| 476 | find_last_( | |||
| 477 | std::uint16_t before, | |||
| 478 | http::field id) const noexcept | |||
| 479 | { | |||
| 480 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 294 times.
|
294x | BOOST_ASSERT(before <= count_); | |
| 481 | 294x | auto const v = static_cast<std::uint16_t>(id); | ||
| 482 | 294x | auto i = before; | ||
| 483 |
2/2✓ Branch 0 taken 127 times.
✓ Branch 1 taken 205 times.
|
332x | while(i != 0) | |
| 484 | { | |||
| 485 | 127x | --i; | ||
| 486 |
2/2✓ Branch 1 taken 89 times.
✓ Branch 2 taken 38 times.
|
127x | if(ent_(i).id == v) | |
| 487 | 89x | return i; | ||
| 488 | } | |||
| 489 | 205x | return count_; | ||
| 490 | } | |||
| 491 | ||||
| 492 | std::uint16_t | |||
| 493 | 5x | fields_base:: | ||
| 494 | find_last_( | |||
| 495 | std::uint16_t before, | |||
| 496 | std::string_view name) const noexcept | |||
| 497 | { | |||
| 498 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
|
5x | BOOST_ASSERT(before <= count_); | |
| 499 | 5x | auto const n = name.size(); | ||
| 500 | 5x | auto i = before; | ||
| 501 |
2/2✓ Branch 0 taken 8 times.
✓ Branch 1 taken 3 times.
|
11x | while(i != 0) | |
| 502 | { | |||
| 503 | 8x | --i; | ||
| 504 | 8x | auto const& e = ent_(i); | ||
| 505 |
5/6✓ Branch 0 taken 2 times.
✓ Branch 1 taken 6 times.
✓ Branch 4 taken 2 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 2 times.
✓ Branch 7 taken 6 times.
|
8x | if(e.nn == n && ci_equal_rev(buf_ + e.of, name.data(), n)) | |
| 506 | 2x | return i; | ||
| 507 | } | |||
| 508 | 3x | return count_; | ||
| 509 | } | |||
| 510 | ||||
| 511 | std::string_view | |||
| 512 | 68x | fields_base:: | ||
| 513 | at(http::field id) const | |||
| 514 | { | |||
| 515 | 68x | auto const i = find_(0, id); | ||
| 516 |
2/2✓ Branch 0 taken 1 time.
✓ Branch 1 taken 67 times.
|
68x | if(i == count_) | |
| 517 | 1x | detail::throw_out_of_range("field not found"); | ||
| 518 | 67x | return ref_(i).value; | ||
| 519 | } | |||
| 520 | ||||
| 521 | std::string_view | |||
| 522 | 80x | fields_base:: | ||
| 523 | at(std::string_view name) const | |||
| 524 | { | |||
| 525 | 80x | auto const i = find_(0, name); | ||
| 526 |
2/2✓ Branch 0 taken 1 time.
✓ Branch 1 taken 79 times.
|
80x | if(i == count_) | |
| 527 | 1x | detail::throw_out_of_range("field not found"); | ||
| 528 | 79x | return ref_(i).value; | ||
| 529 | } | |||
| 530 | ||||
| 531 | std::size_t | |||
| 532 | 13x | fields_base:: | ||
| 533 | count(http::field id) const noexcept | |||
| 534 | { | |||
| 535 |
2/2✓ Branch 0 taken 1 time.
✓ Branch 1 taken 12 times.
|
13x | if(count_ == 0) | |
| 536 | 1x | return 0; | ||
| 537 | 12x | auto const v = static_cast<std::uint16_t>(id); | ||
| 538 | 12x | auto const* e = &ent_(0); | ||
| 539 | 12x | std::size_t n = 0; | ||
| 540 |
2/2✓ Branch 0 taken 31 times.
✓ Branch 1 taken 12 times.
|
43x | for(std::uint16_t i = 0; i != count_; ++i, --e) | |
| 541 |
2/2✓ Branch 0 taken 14 times.
✓ Branch 1 taken 17 times.
|
31x | if(e->id == v) | |
| 542 | 14x | ++n; | ||
| 543 | 12x | return n; | ||
| 544 | } | |||
| 545 | ||||
| 546 | std::size_t | |||
| 547 | 8x | fields_base:: | ||
| 548 | count(std::string_view name) const noexcept | |||
| 549 | { | |||
| 550 |
2/2✓ Branch 0 taken 1 time.
✓ Branch 1 taken 7 times.
|
8x | if(count_ == 0) | |
| 551 | 1x | return 0; | ||
| 552 | 7x | auto const nn = name.size(); | ||
| 553 | 7x | auto const* e = &ent_(0); | ||
| 554 | 7x | std::size_t n = 0; | ||
| 555 |
2/2✓ Branch 0 taken 29 times.
✓ Branch 1 taken 7 times.
|
36x | for(std::uint16_t i = 0; i != count_; ++i, --e) | |
| 556 |
6/6✓ Branch 0 taken 14 times.
✓ Branch 1 taken 15 times.
✓ Branch 4 taken 11 times.
✓ Branch 5 taken 3 times.
✓ Branch 6 taken 11 times.
✓ Branch 7 taken 18 times.
|
29x | if(e->nn == nn && ci_equal_rev(buf_ + e->of, name.data(), nn)) | |
| 557 | 11x | ++n; | ||
| 558 | 7x | return n; | ||
| 559 | } | |||
| 560 | ||||
| 561 | auto | |||
| 562 | 187x | fields_base:: | ||
| 563 | subrange::iterator::operator++() noexcept -> iterator& | |||
| 564 | { | |||
| 565 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 187 times.
|
187x | BOOST_ASSERT(f_ != nullptr); | |
| 566 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 187 times.
|
187x | BOOST_ASSERT(i_ < f_->count_); | |
| 567 | 187x | auto const& c = *f_; | ||
| 568 | 187x | auto const* e = &c.ent_(i_); | ||
| 569 | 187x | auto const id = e->id; | ||
| 570 |
2/2✓ Branch 0 taken 184 times.
✓ Branch 1 taken 3 times.
|
187x | if(id != 0) | |
| 571 | { | |||
| 572 | // known field; ids alone identify the name | |||
| 573 |
2/2✓ Branch 0 taken 29 times.
✓ Branch 1 taken 169 times.
|
198x | while(++i_ != c.count_) | |
| 574 | { | |||
| 575 | 29x | --e; | ||
| 576 |
2/2✓ Branch 0 taken 15 times.
✓ Branch 1 taken 14 times.
|
29x | if(e->id == id) | |
| 577 | 15x | break; | ||
| 578 | } | |||
| 579 | 184x | return *this; | ||
| 580 | } | |||
| 581 | 3x | auto const nn = e->nn; | ||
| 582 | 3x | auto const* p = c.buf_ + e->of; | ||
| 583 |
2/2✓ Branch 0 taken 5 times.
✓ Branch 1 taken 1 time.
|
6x | while(++i_ != c.count_) | |
| 584 | { | |||
| 585 | 5x | --e; | ||
| 586 |
3/4✓ Branch 0 taken 3 times.
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 3 times.
|
5x | if(e->id != 0 || e->nn != nn) | |
| 587 | 2x | continue; | ||
| 588 |
2/2✓ Branch 1 taken 2 times.
✓ Branch 2 taken 1 time.
|
3x | if(ci_equal_rev(c.buf_ + e->of, p, nn)) | |
| 589 | 2x | break; | ||
| 590 | } | |||
| 591 | 3x | return *this; | ||
| 592 | } | |||
| 593 | ||||
| 594 | //------------------------------------------------ | |||
| 595 | // | |||
| 596 | // Modifiers | |||
| 597 | // | |||
| 598 | //------------------------------------------------ | |||
| 599 | ||||
| 600 | void | |||
| 601 | 37x | fields_base:: | ||
| 602 | append(std::initializer_list<field_view> init) | |||
| 603 | { | |||
| 604 | // validate and total up front, so that | |||
| 605 | // nothing can throw once we start inserting | |||
| 606 | 37x | auto bytes = std::size_t(size_); | ||
| 607 |
2/2✓ Branch 2 taken 86 times.
✓ Branch 3 taken 34 times.
|
120x | for(auto const& e : init) | |
| 608 | { | |||
| 609 |
2/2✓ Branch 1 taken 1 time.
✓ Branch 2 taken 85 times.
|
86x | if(e.name.size() > max_name_size) | |
| 610 | 1x | detail::throw_length_error("field name too large"); | ||
| 611 |
2/2✓ Branch 1 taken 2 times.
✓ Branch 2 taken 83 times.
|
85x | if(e.value.size() > max_value_size) | |
| 612 | 2x | detail::throw_length_error("field value too large"); | ||
| 613 | 83x | bytes += e.name.size() + e.value.size() + 4; | ||
| 614 | } | |||
| 615 | 34x | reserve_(bytes, count_ + init.size()); | ||
| 616 |
2/2✓ Branch 2 taken 79 times.
✓ Branch 3 taken 33 times.
|
112x | for(auto const& e : init) | |
| 617 | { | |||
| 618 | 79x | auto const id = (e.id == unknown_field) | ||
| 619 |
2/2✓ Branch 0 taken 44 times.
✓ Branch 1 taken 35 times.
|
79x | ? resolve_(e.name) | |
| 620 | 79x | : static_cast<std::uint16_t>(e.id); | ||
| 621 | 79x | insert_(count_, id, e.name, e.value); | ||
| 622 | } | |||
| 623 | 33x | } | ||
| 624 | ||||
| 625 | std::uint16_t | |||
| 626 | 66644x | fields_base:: | ||
| 627 | insert_( | |||
| 628 | std::uint16_t i, | |||
| 629 | std::uint16_t id, | |||
| 630 | std::string_view name, | |||
| 631 | std::string_view value) | |||
| 632 | { | |||
| 633 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 66644 times.
|
66644x | BOOST_ASSERT(i <= count_); | |
| 634 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 66644 times.
|
66644x | BOOST_ASSERT(size_ >= 2); | |
| 635 |
2/2✓ Branch 0 taken 2 times.
✓ Branch 1 taken 66642 times.
|
66644x | if(count_ == max_field_count) | |
| 636 | 2x | detail::throw_length_error("field count limit exceeded"); | ||
| 637 |
2/2✓ Branch 1 taken 2 times.
✓ Branch 2 taken 66640 times.
|
66642x | if(name.size() > max_name_size) | |
| 638 | 2x | detail::throw_length_error("field name too large"); | ||
| 639 |
2/2✓ Branch 1 taken 3 times.
✓ Branch 2 taken 66637 times.
|
66640x | if(value.size() > max_value_size) | |
| 640 | 3x | detail::throw_length_error("field value too large"); | ||
| 641 | 66637x | auto const nn = static_cast<std::uint16_t>(name.size()); | ||
| 642 | 66637x | auto const vn = static_cast<std::uint16_t>(value.size()); | ||
| 643 | 66637x | auto const len = nn + vn + std::uint32_t(4); | ||
| 644 |
2/2✓ Branch 0 taken 66632 times.
✓ Branch 1 taken 5 times.
|
66637x | auto const pos = (i == count_) ? size_ - 2 : ent_(i).of; | |
| 645 | 133260x | char* p = splice_fields_( | ||
| 646 | 66637x | pos, 0, len, 1, { 0, name }, { std::size_t(nn) + 2, value }); | ||
| 647 | 66623x | p[nn] = ':'; | ||
| 648 | 66623x | p[nn + 1] = ' '; | ||
| 649 | 66623x | p[len - 2] = '\r'; | ||
| 650 | 66623x | p[len - 1] = '\n'; | ||
| 651 | 66623x | auto* et = tab_(); | ||
| 652 |
2/2✓ Branch 0 taken 12 times.
✓ Branch 1 taken 66623 times.
|
66635x | for(auto j = count_; j > i; --j) | |
| 653 | { | |||
| 654 | 12x | auto e = ent_(et, j - 1); | ||
| 655 | 12x | e.of += len; | ||
| 656 | 12x | ent_(et, j) = e; | ||
| 657 | } | |||
| 658 | 66623x | ent_(et, i) = { pos, id, nn, 2, vn }; | ||
| 659 | 66623x | ++count_; | ||
| 660 | 66623x | notify_(id); | ||
| 661 | 66623x | return i; | ||
| 662 | } | |||
| 663 | ||||
| 664 | void | |||
| 665 | 38x | fields_base:: | ||
| 666 | replace_value_( | |||
| 667 | std::uint16_t i, | |||
| 668 | std::string_view value) | |||
| 669 | { | |||
| 670 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 38 times.
|
38x | BOOST_ASSERT(i < count_); | |
| 671 |
2/2✓ Branch 1 taken 2 times.
✓ Branch 2 taken 36 times.
|
38x | if(value.size() > max_value_size) | |
| 672 | 2x | detail::throw_length_error("field value too large"); | ||
| 673 | 36x | auto const vn2 = static_cast<std::uint16_t>(value.size()); | ||
| 674 | 36x | auto const of = ent_(i).of; | ||
| 675 | 36x | auto const vp = of + ent_(i).nn + ent_(i).ws; | ||
| 676 | 36x | auto const old_n = line_len_(i) - (vp - of); | ||
| 677 | 36x | auto const new_n = std::size_t(vn2) + 2; | ||
| 678 | 36x | auto* const p = splice_fields_( | ||
| 679 | vp, old_n, new_n, 0, { 0, value }, {}); | |||
| 680 | 36x | p[vn2] = '\r'; | ||
| 681 | 36x | p[vn2 + 1] = '\n'; | ||
| 682 | 36x | auto const d = std::ptrdiff_t(new_n) - std::ptrdiff_t(old_n); | ||
| 683 | 36x | auto* et = tab_(); | ||
| 684 |
2/2✓ Branch 0 taken 32 times.
✓ Branch 1 taken 36 times.
|
68x | for(auto j = i + 1; j < count_; ++j) | |
| 685 | { | |||
| 686 | 32x | auto& e = ent_(et, j); | ||
| 687 | 32x | e.of = static_cast<std::uint32_t>(e.of + d); | ||
| 688 | } | |||
| 689 | 36x | ent_(i).vn = vn2; | ||
| 690 | 36x | notify_(ent_(i).id); | ||
| 691 | 36x | } | ||
| 692 | ||||
| 693 | void | |||
| 694 | 109x | fields_base:: | ||
| 695 | erase_at_(std::uint16_t i) noexcept | |||
| 696 | { | |||
| 697 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 109 times.
|
109x | BOOST_ASSERT(i < count_); | |
| 698 | 109x | auto const id = ent_(i).id; | ||
| 699 | 109x | auto const of = ent_(i).of; | ||
| 700 | 109x | auto const len = line_len_(i); | ||
| 701 | 109x | std::memmove(buf_ + of, buf_ + of + len, size_ - of - len); | ||
| 702 | 109x | auto* et = tab_(); | ||
| 703 |
2/2✓ Branch 0 taken 4961 times.
✓ Branch 1 taken 109 times.
|
5070x | for(auto j = i + 1; j < count_; ++j) | |
| 704 | { | |||
| 705 | 4961x | auto e = ent_(et, j); | ||
| 706 | 4961x | e.of -= len; | ||
| 707 | 4961x | ent_(et, j - 1) = e; | ||
| 708 | } | |||
| 709 | 109x | size_ -= len; | ||
| 710 | 109x | --count_; | ||
| 711 | 109x | notify_(id); | ||
| 712 | 109x | } | ||
| 713 | ||||
| 714 | template<class Match> | |||
| 715 | std::uint16_t | |||
| 716 | 152x | fields_base:: | ||
| 717 | erase_all_( | |||
| 718 | std::uint16_t i, | |||
| 719 | std::uint16_t id, | |||
| 720 | Match const& match) noexcept | |||
| 721 | { | |||
| 722 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 152 times.
|
152x | BOOST_ASSERT(i < count_); | |
| 723 | // single pass, relocating runs of surviving | |||
| 724 | // lines as whole blocks, so each character | |||
| 725 | // moves at most once | |||
| 726 | 152x | auto* et = tab_(); | ||
| 727 | 152x | auto cw = ent_(et, i).of; | ||
| 728 | 152x | auto ew = i; | ||
| 729 |
2/2✓ Branch 0 taken 280 times.
✓ Branch 1 taken 152 times.
|
432x | while(i != count_) | |
| 730 | { | |||
| 731 | 280x | auto e = ent_(et, i); | ||
| 732 |
2/2✓ Branch 1 taken 157 times.
✓ Branch 2 taken 123 times.
|
280x | if(match(e)) | |
| 733 | { | |||
| 734 | 157x | ++i; | ||
| 735 | 157x | continue; | ||
| 736 | } | |||
| 737 | 123x | std::uint32_t const rp = e.of; | ||
| 738 | 123x | std::uint32_t rn = 0; | ||
| 739 | 9910x | for(;;) | ||
| 740 | { | |||
| 741 | 10033x | auto const len = line_len_(i); | ||
| 742 | 10033x | e.of = cw + rn; | ||
| 743 | 10033x | ent_(et, ew) = e; | ||
| 744 | 10033x | rn += len; | ||
| 745 | 10033x | ++ew; | ||
| 746 |
2/2✓ Branch 0 taken 120 times.
✓ Branch 1 taken 9913 times.
|
10033x | if(++i == count_) | |
| 747 | 120x | break; | ||
| 748 | 9913x | e = ent_(et, i); | ||
| 749 |
2/2✓ Branch 1 taken 3 times.
✓ Branch 2 taken 9910 times.
|
9913x | if(match(e)) | |
| 750 | 3x | break; | ||
| 751 | } | |||
| 752 | 123x | std::memmove(buf_ + cw, buf_ + rp, rn); | ||
| 753 | 123x | cw += rn; | ||
| 754 | } | |||
| 755 | 152x | buf_[cw] = '\r'; | ||
| 756 | 152x | buf_[cw + 1] = '\n'; | ||
| 757 | 152x | auto const n = static_cast<std::uint16_t>(count_ - ew); | ||
| 758 | 152x | size_ = cw + 2; | ||
| 759 | 152x | count_ = ew; | ||
| 760 | 152x | notify_(id); | ||
| 761 | 152x | return n; | ||
| 762 | } | |||
| 763 | ||||
| 764 | std::uint16_t | |||
| 765 | 47x | fields_base:: | ||
| 766 | erase_all_( | |||
| 767 | std::uint16_t i, | |||
| 768 | std::uint16_t id) noexcept | |||
| 769 | { | |||
| 770 | 47x | return erase_all_(i, id, | ||
| 771 | 94x | [id](entry const& e) noexcept | ||
| 772 | { | |||
| 773 | 81x | return e.id == id; | ||
| 774 | 47x | }); | ||
| 775 | } | |||
| 776 | ||||
| 777 | std::uint16_t | |||
| 778 | 105x | fields_base:: | ||
| 779 | erase_all_( | |||
| 780 | std::uint16_t i, | |||
| 781 | std::string_view name) noexcept | |||
| 782 | { | |||
| 783 | 105x | return erase_all_(i, ent_(i).id, | ||
| 784 | 210x | [this, name](entry const& e) noexcept | ||
| 785 | { | |||
| 786 |
4/4✓ Branch 1 taken 4659 times.
✓ Branch 2 taken 5453 times.
✓ Branch 3 taken 108 times.
✓ Branch 4 taken 4551 times.
|
14771x | return e.nn == name.size() && | |
| 787 | 14771x | ci_equal_rev(buf_ + e.of, name.data(), name.size()); | ||
| 788 | 105x | }); | ||
| 789 | } | |||
| 790 | ||||
| 791 | void | |||
| 792 | 31x | fields_base:: | ||
| 793 | erase_dups_(std::uint16_t i) noexcept | |||
| 794 | { | |||
| 795 | 31x | auto const& e = ent_(i); | ||
| 796 |
2/2✓ Branch 0 taken 28 times.
✓ Branch 1 taken 3 times.
|
31x | if(e.id != 0) | |
| 797 | { | |||
| 798 | 28x | auto const j = find_(i + 1, static_cast<http::field>(e.id)); | ||
| 799 |
2/2✓ Branch 0 taken 2 times.
✓ Branch 1 taken 26 times.
|
28x | if(j != count_) | |
| 800 | 2x | erase_all_(j, e.id); | ||
| 801 | } | |||
| 802 | else | |||
| 803 | { | |||
| 804 | 3x | std::string_view const name(buf_ + e.of, e.nn); | ||
| 805 | 3x | auto const j = find_(i + 1, name); | ||
| 806 |
2/2✓ Branch 0 taken 1 time.
✓ Branch 1 taken 2 times.
|
3x | if(j != count_) | |
| 807 | 1x | erase_all_(j, name); | ||
| 808 | } | |||
| 809 | 31x | } | ||
| 810 | ||||
| 811 | void | |||
| 812 | 301x | fields_base:: | ||
| 813 | set( | |||
| 814 | http::field id, | |||
| 815 | std::string_view value) | |||
| 816 | { | |||
| 817 | 301x | auto const i = find_(0, id); | ||
| 818 |
2/2✓ Branch 0 taken 274 times.
✓ Branch 1 taken 27 times.
|
301x | if(i == count_) | |
| 819 | 274x | return append(id, value); | ||
| 820 | 27x | replace_value_(i, value); | ||
| 821 | 27x | erase_dups_(i); | ||
| 822 | } | |||
| 823 | ||||
| 824 | void | |||
| 825 | 9x | fields_base:: | ||
| 826 | set( | |||
| 827 | std::string_view name, | |||
| 828 | std::string_view value) | |||
| 829 | { | |||
| 830 | 9x | auto const i = find_(0, name); | ||
| 831 |
2/2✓ Branch 0 taken 4 times.
✓ Branch 1 taken 5 times.
|
9x | if(i == count_) | |
| 832 | 4x | return append(name, value); | ||
| 833 | 5x | replace_value_(i, value); | ||
| 834 | 4x | erase_dups_(i); | ||
| 835 | } | |||
| 836 | ||||
| 837 | std::size_t | |||
| 838 | 167x | fields_base:: | ||
| 839 | erase(http::field id) noexcept | |||
| 840 | { | |||
| 841 | 167x | auto const i = find_(0, id); | ||
| 842 |
2/2✓ Branch 0 taken 122 times.
✓ Branch 1 taken 45 times.
|
167x | if(i == count_) | |
| 843 | 122x | return 0; | ||
| 844 | 45x | return erase_all_(i, static_cast<std::uint16_t>(id)); | ||
| 845 | } | |||
| 846 | ||||
| 847 | std::size_t | |||
| 848 | 105x | fields_base:: | ||
| 849 | erase(std::string_view name) noexcept | |||
| 850 | { | |||
| 851 | 105x | auto const i = find_(0, name); | ||
| 852 |
2/2✓ Branch 0 taken 1 time.
✓ Branch 1 taken 104 times.
|
105x | if(i == count_) | |
| 853 | 1x | return 0; | ||
| 854 | 104x | return erase_all_(i, name); | ||
| 855 | } | |||
| 856 | ||||
| 857 | void | |||
| 858 | 6x | fields_base:: | ||
| 859 | clear() noexcept | |||
| 860 | { | |||
| 861 |
2/2✓ Branch 0 taken 1 time.
✓ Branch 1 taken 5 times.
|
6x | if(count_ == 0) | |
| 862 | 1x | return; | ||
| 863 | 5x | buf_[0] = '\r'; | ||
| 864 | 5x | buf_[1] = '\n'; | ||
| 865 | 5x | size_ = 2; | ||
| 866 | 5x | count_ = 0; | ||
| 867 | 5x | on_clear_(); | ||
| 868 | } | |||
| 869 | ||||
| 870 | std::ostream& | |||
| 871 | 6x | operator<<( | ||
| 872 | std::ostream& os, | |||
| 873 | fields_base const& f) | |||
| 874 | { | |||
| 875 |
2/2✓ Branch 5 taken 7 times.
✓ Branch 6 taken 6 times.
|
13x | for(auto fv : f) | |
| 876 |
4/4✓ Branch 1 taken 7 times.
✓ Branch 4 taken 7 times.
✓ Branch 7 taken 7 times.
✓ Branch 10 taken 7 times.
|
7x | os << fv.name << ": " << fv.value << '\n'; | |
| 877 | 6x | return os; | ||
| 878 | } | |||
| 879 | ||||
| 880 | } // namespace burl | |||
| 881 | } // namespace boost | |||
| 882 |