97.44% Lines (685/703)
98.57% Functions (69/70)
| TLA | Baseline | Branch | ||||||
|---|---|---|---|---|---|---|---|---|
| Line | Hits | Code | Line | Hits | Code | |||
| 1 | // | 1 | // | |||||
| 2 | // Copyright (c) 2021 Vinnie Falco (vinnie.falco@gmail.com) | 2 | // Copyright (c) 2021 Vinnie Falco (vinnie.falco@gmail.com) | |||||
| 3 | // Copyright (c) 2025 Mohammad Nejati | 3 | // Copyright (c) 2025 Mohammad Nejati | |||||
| 4 | // | 4 | // | |||||
| 5 | // Distributed under the Boost Software License, Version 1.0. (See accompanying | 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) | 6 | // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) | |||||
| 7 | // | 7 | // | |||||
| 8 | // Official repository: https://github.com/cppalliance/http | 8 | // Official repository: https://github.com/cppalliance/http | |||||
| 9 | // | 9 | // | |||||
| 10 | 10 | |||||||
| 11 | #include <boost/http/detail/config.hpp> | 11 | #include <boost/http/detail/config.hpp> | |||||
| 12 | #include <boost/http/detail/except.hpp> | 12 | #include <boost/http/detail/except.hpp> | |||||
| 13 | #include <boost/http/detail/header.hpp> | 13 | #include <boost/http/detail/header.hpp> | |||||
| 14 | #include <boost/http/error.hpp> | 14 | #include <boost/http/error.hpp> | |||||
| 15 | #include <boost/http/field.hpp> | 15 | #include <boost/http/field.hpp> | |||||
| 16 | #include <boost/http/fields_base.hpp> | 16 | #include <boost/http/fields_base.hpp> | |||||
| 17 | #include <boost/http/header_limits.hpp> | 17 | #include <boost/http/header_limits.hpp> | |||||
| 18 | #include <boost/http/rfc/token_rule.hpp> | 18 | #include <boost/http/rfc/token_rule.hpp> | |||||
| 19 | 19 | |||||||
| 20 | #include "src/detail/move_chars.hpp" | 20 | #include "src/detail/move_chars.hpp" | |||||
| 21 | #include "src/rfc/detail/rules.hpp" | 21 | #include "src/rfc/detail/rules.hpp" | |||||
| 22 | 22 | |||||||
| 23 | #include <boost/assert.hpp> | 23 | #include <boost/assert.hpp> | |||||
| 24 | #include <boost/assert/source_location.hpp> | 24 | #include <boost/assert/source_location.hpp> | |||||
| 25 | #include <boost/core/detail/string_view.hpp> | 25 | #include <boost/core/detail/string_view.hpp> | |||||
| 26 | #include <boost/system/result.hpp> | 26 | #include <boost/system/result.hpp> | |||||
| 27 | #include <boost/url/grammar/ci_string.hpp> | 27 | #include <boost/url/grammar/ci_string.hpp> | |||||
| 28 | #include <boost/url/grammar/error.hpp> | 28 | #include <boost/url/grammar/error.hpp> | |||||
| 29 | #include <boost/url/grammar/parse.hpp> | 29 | #include <boost/url/grammar/parse.hpp> | |||||
| 30 | #include <boost/url/grammar/token_rule.hpp> | 30 | #include <boost/url/grammar/token_rule.hpp> | |||||
| 31 | 31 | |||||||
| 32 | namespace boost { | 32 | namespace boost { | |||||
| 33 | namespace http { | 33 | namespace http { | |||||
| 34 | 34 | |||||||
| 35 | namespace { | 35 | namespace { | |||||
| 36 | 36 | |||||||
| 37 | std::size_t | 37 | std::size_t | |||||
| HITCBC | 38 | 2070 | align_down( | 38 | 2079 | align_down( | ||
| 39 | void * ptr, | 39 | void * ptr, | |||||
| 40 | std::size_t size, | 40 | std::size_t size, | |||||
| 41 | std::size_t alignment) | 41 | std::size_t alignment) | |||||
| 42 | { | 42 | { | |||||
| HITCBC | 43 | 2070 | auto addr = reinterpret_cast<std::uintptr_t>(ptr); | 43 | 2079 | auto addr = reinterpret_cast<std::uintptr_t>(ptr); | ||
| HITCBC | 44 | 2070 | auto aligned_end = (addr + size) & ~(alignment - 1); | 44 | 2079 | auto aligned_end = (addr + size) & ~(alignment - 1); | ||
| 45 | 45 | |||||||
| HITCBC | 46 | 2070 | if(aligned_end > addr) | 46 | 2079 | if(aligned_end > addr) | ||
| HITCBC | 47 | 2070 | return aligned_end - addr; | 47 | 2079 | return aligned_end - addr; | ||
| 48 | 48 | |||||||
| MISUBC | 49 | ✗ | return 0; | 49 | ✗ | return 0; | ||
| 50 | } | 50 | } | |||||
| 51 | 51 | |||||||
| 52 | void | 52 | void | |||||
| HITCBC | 53 | 241 | verify_field_name( | 53 | 241 | verify_field_name( | ||
| 54 | core::string_view name, | 54 | core::string_view name, | |||||
| 55 | system::error_code& ec) | 55 | system::error_code& ec) | |||||
| 56 | { | 56 | { | |||||
| HITCBC | 57 | 241 | auto rv = grammar::parse( | 57 | 241 | auto rv = grammar::parse( | ||
| 58 | name, detail::field_name_rule); | 58 | name, detail::field_name_rule); | |||||
| HITCBC | 59 | 241 | if(rv.has_error()) | 59 | 241 | if(rv.has_error()) | ||
| 60 | { | 60 | { | |||||
| HITCBC | 61 | 18 | ec = BOOST_HTTP_ERR( | 61 | 18 | ec = BOOST_HTTP_ERR( | ||
| 62 | error::bad_field_name); | 62 | error::bad_field_name); | |||||
| 63 | } | 63 | } | |||||
| HITCBC | 64 | 241 | } | 64 | 241 | } | ||
| 65 | 65 | |||||||
| 66 | system::result<detail::field_value_rule_t::value_type> | 66 | system::result<detail::field_value_rule_t::value_type> | |||||
| HITCBC | 67 | 369 | verify_field_value( | 67 | 369 | verify_field_value( | ||
| 68 | core::string_view value) | 68 | core::string_view value) | |||||
| 69 | { | 69 | { | |||||
| HITCBC | 70 | 369 | auto it = value.begin(); | 70 | 369 | auto it = value.begin(); | ||
| HITCBC | 71 | 369 | auto end = value.end(); | 71 | 369 | auto end = value.end(); | ||
| 72 | auto rv = | 72 | auto rv = | |||||
| HITCBC | 73 | 369 | grammar::parse(it, end, detail::field_value_rule); | 73 | 369 | grammar::parse(it, end, detail::field_value_rule); | ||
| HITCBC | 74 | 369 | if( rv.has_error() ) | 74 | 369 | if( rv.has_error() ) | ||
| 75 | { | 75 | { | |||||
| HITCBC | 76 | 7 | if( rv.error() == condition::need_more_input ) | 76 | 7 | if( rv.error() == condition::need_more_input ) | ||
| HITCBC | 77 | 7 | return error::bad_field_value; | 77 | 7 | return error::bad_field_value; | ||
| MISUBC | 78 | ✗ | return rv.error(); | 78 | ✗ | return rv.error(); | ||
| 79 | } | 79 | } | |||||
| 80 | 80 | |||||||
| HITCBC | 81 | 362 | if( rv->has_crlf ) | 81 | 362 | if( rv->has_crlf ) | ||
| HITCBC | 82 | 16 | return error::bad_field_smuggle; | 82 | 16 | return error::bad_field_smuggle; | ||
| 83 | 83 | |||||||
| HITCBC | 84 | 346 | if( it != end ) | 84 | 346 | if( it != end ) | ||
| HITCBC | 85 | 7 | return error::bad_field_value; | 85 | 7 | return error::bad_field_value; | ||
| 86 | 86 | |||||||
| HITCBC | 87 | 339 | return rv; | 87 | 339 | return rv; | ||
| 88 | } | 88 | } | |||||
| 89 | 89 | |||||||
| 90 | } // namespace | 90 | } // namespace | |||||
| 91 | 91 | |||||||
| 92 | class fields_base:: | 92 | class fields_base:: | |||||
| 93 | op_t | 93 | op_t | |||||
| 94 | { | 94 | { | |||||
| 95 | fields_base& self_; | 95 | fields_base& self_; | |||||
| 96 | core::string_view* s0_; | 96 | core::string_view* s0_; | |||||
| 97 | core::string_view* s1_; | 97 | core::string_view* s1_; | |||||
| 98 | char* buf_ = nullptr; | 98 | char* buf_ = nullptr; | |||||
| 99 | char const* cbuf_ = nullptr; | 99 | char const* cbuf_ = nullptr; | |||||
| 100 | std::size_t cap_ = 0; | 100 | std::size_t cap_ = 0; | |||||
| 101 | 101 | |||||||
| 102 | public: | 102 | public: | |||||
| 103 | explicit | 103 | explicit | |||||
| HITCBC | 104 | 995 | op_t( | 104 | 995 | op_t( | ||
| 105 | fields_base& self, | 105 | fields_base& self, | |||||
| 106 | core::string_view* s0 = nullptr, | 106 | core::string_view* s0 = nullptr, | |||||
| 107 | core::string_view* s1 = nullptr) noexcept | 107 | core::string_view* s1 = nullptr) noexcept | |||||
| HITCBC | 108 | 995 | : self_(self) | 108 | 995 | : self_(self) | ||
| HITCBC | 109 | 995 | , s0_(s0) | 109 | 995 | , s0_(s0) | ||
| HITCBC | 110 | 995 | , s1_(s1) | 110 | 995 | , s1_(s1) | ||
| 111 | { | 111 | { | |||||
| HITCBC | 112 | 995 | } | 112 | 995 | } | ||
| 113 | 113 | |||||||
| HITCBC | 114 | 995 | ~op_t() | 114 | 995 | ~op_t() | ||
| 115 | { | 115 | { | |||||
| HITCBC | 116 | 995 | if(buf_) | 116 | 995 | if(buf_) | ||
| HITCBC | 117 | 151 | delete[] buf_; | 117 | 151 | delete[] buf_; | ||
| HITCBC | 118 | 995 | } | 118 | 995 | } | ||
| 119 | 119 | |||||||
| 120 | char const* | 120 | char const* | |||||
| HITCBC | 121 | 12 | buf() const noexcept | 121 | 12 | buf() const noexcept | ||
| 122 | { | 122 | { | |||||
| HITCBC | 123 | 12 | return buf_; | 123 | 12 | return buf_; | ||
| 124 | } | 124 | } | |||||
| 125 | 125 | |||||||
| 126 | char const* | 126 | char const* | |||||
| HITCBC | 127 | 460 | cbuf() const noexcept | 127 | 460 | cbuf() const noexcept | ||
| 128 | { | 128 | { | |||||
| HITCBC | 129 | 460 | return cbuf_; | 129 | 460 | return cbuf_; | ||
| 130 | } | 130 | } | |||||
| 131 | 131 | |||||||
| 132 | char* | 132 | char* | |||||
| HITCBC | 133 | 12 | end() const noexcept | 133 | 12 | end() const noexcept | ||
| 134 | { | 134 | { | |||||
| HITCBC | 135 | 12 | return buf_ + cap_; | 135 | 12 | return buf_ + cap_; | ||
| 136 | } | 136 | } | |||||
| 137 | 137 | |||||||
| 138 | table | 138 | table | |||||
| HITCBC | 139 | 6 | tab() const noexcept | 139 | 6 | tab() const noexcept | ||
| 140 | { | 140 | { | |||||
| HITCBC | 141 | 6 | return table(end()); | 141 | 6 | return table(end()); | ||
| 142 | } | 142 | } | |||||
| 143 | 143 | |||||||
| 144 | bool | 144 | bool | |||||
| 145 | reserve(std::size_t n); | 145 | reserve(std::size_t n); | |||||
| 146 | 146 | |||||||
| 147 | bool | 147 | bool | |||||
| 148 | grow( | 148 | grow( | |||||
| 149 | std::size_t extra_char, | 149 | std::size_t extra_char, | |||||
| 150 | std::size_t extra_field); | 150 | std::size_t extra_field); | |||||
| 151 | 151 | |||||||
| 152 | void | 152 | void | |||||
| 153 | move_chars( | 153 | move_chars( | |||||
| 154 | char* dest, | 154 | char* dest, | |||||
| 155 | char const* src, | 155 | char const* src, | |||||
| 156 | std::size_t n) const noexcept; | 156 | std::size_t n) const noexcept; | |||||
| 157 | }; | 157 | }; | |||||
| 158 | 158 | |||||||
| 159 | bool | 159 | bool | |||||
| HITCBC | 160 | 975 | fields_base:: | 160 | 975 | fields_base:: | ||
| 161 | op_t:: | 161 | op_t:: | |||||
| 162 | reserve( | 162 | reserve( | |||||
| 163 | std::size_t n) | 163 | std::size_t n) | |||||
| 164 | { | 164 | { | |||||
| 165 | // TODO: consider using a growth factor | 165 | // TODO: consider using a growth factor | |||||
| HITCBC | 166 | 975 | if(n > self_.max_cap_) | 166 | 975 | if(n > self_.max_cap_) | ||
| 167 | { | 167 | { | |||||
| 168 | // max capacity exceeded | 168 | // max capacity exceeded | |||||
| HITCBC | 169 | 18 | detail::throw_length_error(); | 169 | 18 | detail::throw_length_error(); | ||
| 170 | } | 170 | } | |||||
| HITCBC | 171 | 957 | if(n <= self_.h_.cap) | 171 | 957 | if(n <= self_.h_.cap) | ||
| HITCBC | 172 | 133 | return false; | 172 | 133 | return false; | ||
| HITCBC | 173 | 824 | auto buf = new char[n]; | 173 | 824 | auto buf = new char[n]; | ||
| HITCBC | 174 | 824 | buf_ = self_.h_.buf; | 174 | 824 | buf_ = self_.h_.buf; | ||
| HITCBC | 175 | 824 | cbuf_ = self_.h_.cbuf; | 175 | 824 | cbuf_ = self_.h_.cbuf; | ||
| HITCBC | 176 | 824 | cap_ = self_.h_.cap; | 176 | 824 | cap_ = self_.h_.cap; | ||
| HITCBC | 177 | 824 | self_.h_.buf = buf; | 177 | 824 | self_.h_.buf = buf; | ||
| HITCBC | 178 | 824 | self_.h_.cbuf = buf; | 178 | 824 | self_.h_.cbuf = buf; | ||
| HITCBC | 179 | 824 | self_.h_.cap = n; | 179 | 824 | self_.h_.cap = n; | ||
| HITCBC | 180 | 824 | return true; | 180 | 824 | return true; | ||
| 181 | } | 181 | } | |||||
| 182 | 182 | |||||||
| 183 | bool | 183 | bool | |||||
| HITCBC | 184 | 882 | fields_base:: | 184 | 882 | fields_base:: | ||
| 185 | op_t:: | 185 | op_t:: | |||||
| 186 | grow( | 186 | grow( | |||||
| 187 | std::size_t extra_char, | 187 | std::size_t extra_char, | |||||
| 188 | std::size_t extra_field) | 188 | std::size_t extra_field) | |||||
| 189 | { | 189 | { | |||||
| HITCBC | 190 | 882 | if(extra_field > detail::header::max_offset - self_.h_.count) | 190 | 882 | if(extra_field > detail::header::max_offset - self_.h_.count) | ||
| MISUBC | 191 | ✗ | detail::throw_length_error(); | 191 | ✗ | detail::throw_length_error(); | ||
| 192 | 192 | |||||||
| HITCBC | 193 | 882 | if(extra_char > detail::header::max_offset - self_.h_.size) | 193 | 882 | if(extra_char > detail::header::max_offset - self_.h_.size) | ||
| HITCBC | 194 | 2 | detail::throw_length_error(); | 194 | 2 | detail::throw_length_error(); | ||
| 195 | 195 | |||||||
| HITCBC | 196 | 880 | return reserve( | 196 | 880 | return reserve( | ||
| 197 | detail::header::bytes_needed( | 197 | detail::header::bytes_needed( | |||||
| HITCBC | 198 | 880 | self_.h_.size + extra_char, | 198 | 880 | self_.h_.size + extra_char, | ||
| HITCBC | 199 | 1755 | self_.h_.count + extra_field)); | 199 | 1755 | self_.h_.count + extra_field)); | ||
| 200 | } | 200 | } | |||||
| 201 | 201 | |||||||
| 202 | void | 202 | void | |||||
| HITCBC | 203 | 103 | fields_base:: | 203 | 103 | fields_base:: | ||
| 204 | op_t:: | 204 | op_t:: | |||||
| 205 | move_chars( | 205 | move_chars( | |||||
| 206 | char* dest, | 206 | char* dest, | |||||
| 207 | char const* src, | 207 | char const* src, | |||||
| 208 | std::size_t n) const noexcept | 208 | std::size_t n) const noexcept | |||||
| 209 | { | 209 | { | |||||
| HITCBC | 210 | 103 | detail::move_chars( | 210 | 103 | detail::move_chars( | ||
| HITCBC | 211 | 103 | dest, src, n, s0_, s1_); | 211 | 103 | dest, src, n, s0_, s1_); | ||
| HITCBC | 212 | 103 | } | 212 | 103 | } | ||
| 213 | 213 | |||||||
| 214 | //------------------------------------------------ | 214 | //------------------------------------------------ | |||||
| 215 | 215 | |||||||
| HITCBC | 216 | 71 | fields_base:: | 216 | 71 | fields_base:: | ||
| 217 | prefix_op_t:: | 217 | prefix_op_t:: | |||||
| 218 | prefix_op_t( | 218 | prefix_op_t( | |||||
| 219 | fields_base& self, | 219 | fields_base& self, | |||||
| 220 | std::size_t new_prefix, | 220 | std::size_t new_prefix, | |||||
| 221 | core::string_view* s0, | 221 | core::string_view* s0, | |||||
| HITCBC | 222 | 71 | core::string_view* s1) | 222 | 71 | core::string_view* s1) | ||
| HITCBC | 223 | 71 | : self_(self) | 223 | 71 | : self_(self) | ||
| HITCBC | 224 | 71 | , new_prefix_(static_cast< | 224 | 71 | , new_prefix_(static_cast< | ||
| HITCBC | 225 | 71 | offset_type>(new_prefix)) | 225 | 71 | offset_type>(new_prefix)) | ||
| 226 | { | 226 | { | |||||
| HITCBC | 227 | 71 | if(self.h_.size - self.h_.prefix + new_prefix | 227 | 71 | if(self.h_.size - self.h_.prefix + new_prefix | ||
| 228 | > detail::header::max_offset) | 228 | > detail::header::max_offset) | |||||
| HITCBC | 229 | 2 | detail::throw_length_error(); | 229 | 2 | detail::throw_length_error(); | ||
| 230 | 230 | |||||||
| 231 | // memmove happens in the destructor | 231 | // memmove happens in the destructor | |||||
| 232 | // to avoid overlaping with start line. | 232 | // to avoid overlaping with start line. | |||||
| HITCBC | 233 | 138 | if(new_prefix_ < self_.h_.prefix | 233 | 138 | if(new_prefix_ < self_.h_.prefix | ||
| HITCBC | 234 | 69 | && !self.h_.is_default()) | 234 | 69 | && !self.h_.is_default()) | ||
| HITCBC | 235 | 6 | return; | 235 | 6 | return; | ||
| 236 | 236 | |||||||
| HITCBC | 237 | 63 | auto new_size = static_cast<offset_type>( | 237 | 63 | auto new_size = static_cast<offset_type>( | ||
| HITCBC | 238 | 63 | self.h_.size - self.h_.prefix + new_prefix_); | 238 | 63 | self.h_.size - self.h_.prefix + new_prefix_); | ||
| 239 | 239 | |||||||
| 240 | auto bytes_needed = | 240 | auto bytes_needed = | |||||
| HITCBC | 241 | 63 | detail::header::bytes_needed( | 241 | 63 | detail::header::bytes_needed( | ||
| 242 | new_size, | 242 | new_size, | |||||
| HITCBC | 243 | 63 | self.h_.count); | 243 | 63 | self.h_.count); | ||
| 244 | 244 | |||||||
| HITCBC | 245 | 63 | if(bytes_needed > self.h_.cap) | 245 | 63 | if(bytes_needed > self.h_.cap) | ||
| 246 | { | 246 | { | |||||
| 247 | // static storage will always throw which is | 247 | // static storage will always throw which is | |||||
| 248 | // intended since they cannot reallocate. | 248 | // intended since they cannot reallocate. | |||||
| HITCBC | 249 | 56 | if(self.max_cap_ < bytes_needed) | 249 | 56 | if(self.max_cap_ < bytes_needed) | ||
| HITCBC | 250 | 1 | detail::throw_length_error(); | 250 | 1 | detail::throw_length_error(); | ||
| 251 | // TODO: consider using a growth factor | 251 | // TODO: consider using a growth factor | |||||
| HITCBC | 252 | 55 | char* p = new char[bytes_needed]; | 252 | 55 | char* p = new char[bytes_needed]; | ||
| HITCBC | 253 | 55 | std::memcpy( | 253 | 55 | std::memcpy( | ||
| HITCBC | 254 | 55 | p + new_prefix_, | 254 | 55 | p + new_prefix_, | ||
| HITCBC | 255 | 55 | self.h_.cbuf + self.h_.prefix, | 255 | 55 | self.h_.cbuf + self.h_.prefix, | ||
| HITCBC | 256 | 55 | self.h_.size - self.h_.prefix); | 256 | 55 | self.h_.size - self.h_.prefix); | ||
| HITCBC | 257 | 55 | self.h_.copy_table(p + bytes_needed); | 257 | 55 | self.h_.copy_table(p + bytes_needed); | ||
| 258 | 258 | |||||||
| 259 | // old buffer gets released in the destructor | 259 | // old buffer gets released in the destructor | |||||
| 260 | // to avoid invalidating any string_views | 260 | // to avoid invalidating any string_views | |||||
| 261 | // that may still reference it. | 261 | // that may still reference it. | |||||
| HITCBC | 262 | 55 | buf_ = self.h_.buf; | 262 | 55 | buf_ = self.h_.buf; | ||
| HITCBC | 263 | 55 | self.h_.buf = p; | 263 | 55 | self.h_.buf = p; | ||
| HITCBC | 264 | 55 | self.h_.cap = bytes_needed; | 264 | 55 | self.h_.cap = bytes_needed; | ||
| 265 | } | 265 | } | |||||
| 266 | else | 266 | else | |||||
| 267 | { | 267 | { | |||||
| 268 | // memmove to the right and update any | 268 | // memmove to the right and update any | |||||
| 269 | // string_views that reference that region. | 269 | // string_views that reference that region. | |||||
| HITCBC | 270 | 7 | detail::move_chars( | 270 | 7 | detail::move_chars( | ||
| HITCBC | 271 | 7 | self.h_.buf + new_prefix_, | 271 | 7 | self.h_.buf + new_prefix_, | ||
| HITCBC | 272 | 7 | self.h_.cbuf + self.h_.prefix, | 272 | 7 | self.h_.cbuf + self.h_.prefix, | ||
| HITCBC | 273 | 7 | self.h_.size - self.h_.prefix, | 273 | 7 | self.h_.size - self.h_.prefix, | ||
| 274 | s0, | 274 | s0, | |||||
| 275 | s1); | 275 | s1); | |||||
| 276 | } | 276 | } | |||||
| 277 | 277 | |||||||
| HITCBC | 278 | 62 | self.h_.cbuf = self.h_.buf; | 278 | 62 | self.h_.cbuf = self.h_.buf; | ||
| HITCBC | 279 | 62 | self.h_.size = new_size; | 279 | 62 | self.h_.size = new_size; | ||
| HITCBC | 280 | 62 | self.h_.prefix = new_prefix_; | 280 | 62 | self.h_.prefix = new_prefix_; | ||
| 281 | } | 281 | } | |||||
| 282 | 282 | |||||||
| HITCBC | 283 | 68 | fields_base:: | 283 | 68 | fields_base:: | ||
| 284 | prefix_op_t:: | 284 | prefix_op_t:: | |||||
| 285 | ~prefix_op_t() | 285 | ~prefix_op_t() | |||||
| 286 | { | 286 | { | |||||
| HITCBC | 287 | 68 | if(new_prefix_ < self_.h_.prefix) | 287 | 68 | if(new_prefix_ < self_.h_.prefix) | ||
| 288 | { | 288 | { | |||||
| HITCBC | 289 | 6 | std::memmove( | 289 | 6 | std::memmove( | ||
| HITCBC | 290 | 6 | self_.h_.buf + new_prefix_, | 290 | 6 | self_.h_.buf + new_prefix_, | ||
| HITCBC | 291 | 6 | self_.h_.cbuf + self_.h_.prefix, | 291 | 6 | self_.h_.cbuf + self_.h_.prefix, | ||
| HITCBC | 292 | 6 | self_.h_.size - self_.h_.prefix); | 292 | 6 | self_.h_.size - self_.h_.prefix); | ||
| 293 | 293 | |||||||
| HITCBC | 294 | 6 | self_.h_.size = | 294 | 6 | self_.h_.size = | ||
| HITCBC | 295 | 6 | self_.h_.size - self_.h_.prefix + new_prefix_; | 295 | 6 | self_.h_.size - self_.h_.prefix + new_prefix_; | ||
| HITCBC | 296 | 6 | self_.h_.prefix = new_prefix_; | 296 | 6 | self_.h_.prefix = new_prefix_; | ||
| 297 | } | 297 | } | |||||
| HITCBC | 298 | 62 | else if(buf_) | 298 | 62 | else if(buf_) | ||
| 299 | { | 299 | { | |||||
| HITCBC | 300 | 5 | delete[] buf_; | 300 | 5 | delete[] buf_; | ||
| 301 | } | 301 | } | |||||
| HITCBC | 302 | 68 | } | 302 | 68 | } | ||
| 303 | 303 | |||||||
| 304 | //------------------------------------------------ | 304 | //------------------------------------------------ | |||||
| 305 | 305 | |||||||
| HITCBC | 306 | 466 | fields_base:: | 306 | 466 | fields_base:: | ||
| 307 | fields_base( | 307 | fields_base( | |||||
| HITCBC | 308 | 466 | detail::kind k) noexcept | 308 | 466 | detail::kind k) noexcept | ||
| HITCBC | 309 | 466 | : h_(k) | 309 | 466 | : h_(k) | ||
| 310 | { | 310 | { | |||||
| HITCBC | 311 | 466 | } | 311 | 466 | } | ||
| 312 | 312 | |||||||
| HITCBC | 313 | 2070 | fields_base:: | 313 | 2079 | fields_base:: | ||
| 314 | fields_base( | 314 | fields_base( | |||||
| 315 | detail::kind k, | 315 | detail::kind k, | |||||
| 316 | void* storage, | 316 | void* storage, | |||||
| HITCBC | 317 | 2070 | std::size_t cap) noexcept | 317 | 2079 | std::size_t cap) noexcept | ||
| 318 | : fields_base( | 318 | : fields_base( | |||||
| HITCBC | 319 | 2070 | *detail::header::get_default(k), storage, cap) | 319 | 2079 | *detail::header::get_default(k), storage, cap) | ||
| 320 | { | 320 | { | |||||
| HITCBC | 321 | 2070 | } | 321 | 2079 | } | ||
| 322 | 322 | |||||||
| 323 | // copy s and parse it | 323 | // copy s and parse it | |||||
| HITCBC | 324 | 547 | fields_base:: | 324 | 547 | fields_base:: | ||
| 325 | fields_base( | 325 | fields_base( | |||||
| 326 | detail::kind k, | 326 | detail::kind k, | |||||
| HITCBC | 327 | 547 | core::string_view s) | 327 | 547 | core::string_view s) | ||
| HITCBC | 328 | 547 | : h_(detail::empty{k}) | 328 | 547 | : h_(detail::empty{k}) | ||
| 329 | { | 329 | { | |||||
| HITCBC | 330 | 547 | auto n = detail::header::count_crlf(s); | 330 | 547 | auto n = detail::header::count_crlf(s); | ||
| HITCBC | 331 | 547 | if(h_.kind == detail::kind::fields) | 331 | 547 | if(h_.kind == detail::kind::fields) | ||
| 332 | { | 332 | { | |||||
| HITCBC | 333 | 235 | if(n < 1) | 333 | 235 | if(n < 1) | ||
| HITCBC | 334 | 1 | detail::throw_invalid_argument(); | 334 | 1 | detail::throw_invalid_argument(); | ||
| HITCBC | 335 | 234 | n -= 1; | 335 | 234 | n -= 1; | ||
| 336 | } | 336 | } | |||||
| 337 | else | 337 | else | |||||
| 338 | { | 338 | { | |||||
| HITCBC | 339 | 312 | if(n < 2) | 339 | 312 | if(n < 2) | ||
| HITCBC | 340 | 2 | detail::throw_invalid_argument(); | 340 | 2 | detail::throw_invalid_argument(); | ||
| HITCBC | 341 | 310 | n -= 2; | 341 | 310 | n -= 2; | ||
| 342 | } | 342 | } | |||||
| HITCBC | 343 | 544 | op_t op(*this); | 343 | 544 | op_t op(*this); | ||
| HITCBC | 344 | 544 | op.grow(s.size(), n); | 344 | 544 | op.grow(s.size(), n); | ||
| HITCBC | 345 | 544 | s.copy(h_.buf, s.size()); | 345 | 544 | s.copy(h_.buf, s.size()); | ||
| HITCBC | 346 | 544 | system::error_code ec; | 346 | 544 | system::error_code ec; | ||
| 347 | // VFALCO This is using defaults? | 347 | // VFALCO This is using defaults? | |||||
| HITCBC | 348 | 544 | header_limits lim; | 348 | 544 | header_limits lim; | ||
| HITCBC | 349 | 544 | h_.parse(s.size(), lim, ec); | 349 | 544 | h_.parse(s.size(), lim, ec); | ||
| HITCBC | 350 | 544 | if(ec) | 350 | 544 | if(ec) | ||
| MISUBC | 351 | ✗ | detail::throw_system_error(ec); | 351 | ✗ | detail::throw_system_error(ec); | ||
| HITCBC | 352 | 544 | } | 352 | 544 | } | ||
| 353 | 353 | |||||||
| 354 | // construct a complete copy of h | 354 | // construct a complete copy of h | |||||
| HITCBC | 355 | 26 | fields_base:: | 355 | 26 | fields_base:: | ||
| 356 | fields_base( | 356 | fields_base( | |||||
| HITCBC | 357 | 26 | detail::header const& h) | 357 | 26 | detail::header const& h) | ||
| HITCBC | 358 | 26 | : h_(h.kind) | 358 | 26 | : h_(h.kind) | ||
| 359 | { | 359 | { | |||||
| HITCBC | 360 | 26 | if(h.is_default()) | 360 | 26 | if(h.is_default()) | ||
| HITCBC | 361 | 9 | return; | 361 | 9 | return; | ||
| 362 | 362 | |||||||
| 363 | // allocate and copy the buffer | 363 | // allocate and copy the buffer | |||||
| HITCBC | 364 | 17 | op_t op(*this); | 364 | 17 | op_t op(*this); | ||
| HITCBC | 365 | 17 | op.grow(h.size, h.count); | 365 | 17 | op.grow(h.size, h.count); | ||
| HITCBC | 366 | 17 | h.assign_to(h_); | 366 | 17 | h.assign_to(h_); | ||
| HITCBC | 367 | 17 | std::memcpy( | 367 | 17 | std::memcpy( | ||
| HITCBC | 368 | 17 | h_.buf, h.cbuf, h.size); | 368 | 17 | h_.buf, h.cbuf, h.size); | ||
| HITCBC | 369 | 17 | h.copy_table(h_.buf + h_.cap); | 369 | 17 | h.copy_table(h_.buf + h_.cap); | ||
| HITCBC | 370 | 17 | } | 370 | 17 | } | ||
| 371 | 371 | |||||||
| 372 | // construct a complete copy of h | 372 | // construct a complete copy of h | |||||
| HITCBC | 373 | 2070 | fields_base:: | 373 | 2079 | fields_base:: | ||
| 374 | fields_base( | 374 | fields_base( | |||||
| 375 | detail::header const& h, | 375 | detail::header const& h, | |||||
| 376 | void* storage, | 376 | void* storage, | |||||
| HITCBC | 377 | 2070 | std::size_t cap) | 377 | 2079 | std::size_t cap) | ||
| HITCBC | 378 | 2070 | : h_(h.kind) | 378 | 2079 | : h_(h.kind) | ||
| HITCBC | 379 | 2070 | , external_storage_(true) | 379 | 2079 | , external_storage_(true) | ||
| 380 | { | 380 | { | |||||
| HITCBC | 381 | 2070 | h_.cbuf = static_cast<char*>(storage); | 381 | 2079 | h_.cbuf = static_cast<char*>(storage); | ||
| HITCBC | 382 | 2070 | h_.buf = static_cast<char*>(storage); | 382 | 2079 | h_.buf = static_cast<char*>(storage); | ||
| HITCBC | 383 | 2070 | h_.cap = align_down( | 383 | 2079 | h_.cap = align_down( | ||
| 384 | storage, | 384 | storage, | |||||
| 385 | cap, | 385 | cap, | |||||
| 386 | alignof(detail::header::entry)); | 386 | alignof(detail::header::entry)); | |||||
| HITCBC | 387 | 2070 | max_cap_ = h_.cap; | 387 | 2079 | max_cap_ = h_.cap; | ||
| 388 | 388 | |||||||
| HITCBC | 389 | 4140 | if(detail::header::bytes_needed( | 389 | 4158 | if(detail::header::bytes_needed( | ||
| HITCBC | 390 | 2070 | h.size, h.count) | 390 | 2079 | h.size, h.count) | ||
| HITCBC | 391 | 2070 | >= h_.cap) | 391 | 2079 | >= h_.cap) | ||
| MISUBC | 392 | ✗ | detail::throw_length_error(); | 392 | ✗ | detail::throw_length_error(); | ||
| 393 | 393 | |||||||
| HITCBC | 394 | 2070 | h.assign_to(h_); | 394 | 2079 | h.assign_to(h_); | ||
| HITCBC | 395 | 2070 | std::memcpy( | 395 | 2079 | std::memcpy( | ||
| HITCBC | 396 | 2070 | h_.buf, h.cbuf, h.size); | 396 | 2079 | h_.buf, h.cbuf, h.size); | ||
| HITCBC | 397 | 2070 | h.copy_table(h_.buf + h_.cap); | 397 | 2079 | h.copy_table(h_.buf + h_.cap); | ||
| HITCBC | 398 | 2070 | } | 398 | 2079 | } | ||
| 399 | 399 | |||||||
| 400 | //------------------------------------------------ | 400 | //------------------------------------------------ | |||||
| 401 | 401 | |||||||
| HITCBC | 402 | 13 | fields_base:: | 402 | 13 | fields_base:: | ||
| HITCBC | 403 | 13 | fields_base(fields_base const& other) | 403 | 13 | fields_base(fields_base const& other) | ||
| HITCBC | 404 | 13 | : fields_base(other.h_) | 404 | 13 | : fields_base(other.h_) | ||
| 405 | { | 405 | { | |||||
| HITCBC | 406 | 13 | } | 406 | 13 | } | ||
| 407 | 407 | |||||||
| HITCBC | 408 | 3106 | fields_base:: | 408 | 3115 | fields_base:: | ||
| 409 | ~fields_base() | 409 | ~fields_base() | |||||
| 410 | { | 410 | { | |||||
| HITCBC | 411 | 3106 | if(h_.buf && !external_storage_) | 411 | 3115 | if(h_.buf && !external_storage_) | ||
| HITCBC | 412 | 723 | delete[] h_.buf; | 412 | 723 | delete[] h_.buf; | ||
| HITCBC | 413 | 3106 | } | 413 | 3115 | } | ||
| 414 | 414 | |||||||
| 415 | //------------------------------------------------ | 415 | //------------------------------------------------ | |||||
| 416 | // | 416 | // | |||||
| 417 | // Capacity | 417 | // Capacity | |||||
| 418 | // | 418 | // | |||||
| 419 | //------------------------------------------------ | 419 | //------------------------------------------------ | |||||
| 420 | 420 | |||||||
| 421 | void | 421 | void | |||||
| HITCBC | 422 | 10 | fields_base:: | 422 | 10 | fields_base:: | ||
| 423 | clear() noexcept | 423 | clear() noexcept | |||||
| 424 | { | 424 | { | |||||
| HITCBC | 425 | 10 | if(! h_.buf) | 425 | 10 | if(! h_.buf) | ||
| HITCBC | 426 | 5 | return; | 426 | 5 | return; | ||
| 427 | using H = | 427 | using H = | |||||
| 428 | detail::header; | 428 | detail::header; | |||||
| 429 | auto const& h = | 429 | auto const& h = | |||||
| HITCBC | 430 | 5 | *H::get_default( | 430 | 5 | *H::get_default( | ||
| HITCBC | 431 | 5 | h_.kind); | 431 | 5 | h_.kind); | ||
| HITCBC | 432 | 5 | h.assign_to(h_); | 432 | 5 | h.assign_to(h_); | ||
| HITCBC | 433 | 5 | std::memcpy( | 433 | 5 | std::memcpy( | ||
| HITCBC | 434 | 5 | h_.buf, | 434 | 5 | h_.buf, | ||
| HITCBC | 435 | 5 | h.cbuf, | 435 | 5 | h.cbuf, | ||
| HITCBC | 436 | 5 | h_.size); | 436 | 5 | h_.size); | ||
| 437 | } | 437 | } | |||||
| 438 | 438 | |||||||
| 439 | void | 439 | void | |||||
| HITCBC | 440 | 95 | fields_base:: | 440 | 95 | fields_base:: | ||
| 441 | reserve_bytes( | 441 | reserve_bytes( | |||||
| 442 | std::size_t n) | 442 | std::size_t n) | |||||
| 443 | { | 443 | { | |||||
| HITCBC | 444 | 95 | op_t op(*this); | 444 | 95 | op_t op(*this); | ||
| HITCBC | 445 | 95 | if(! op.reserve(n)) | 445 | 95 | if(! op.reserve(n)) | ||
| HITCBC | 446 | 48 | return; | 446 | 48 | return; | ||
| HITCBC | 447 | 68 | std::memcpy( | 447 | 68 | std::memcpy( | ||
| HITCBC | 448 | 34 | h_.buf, op.cbuf(), h_.size); | 448 | 34 | h_.buf, op.cbuf(), h_.size); | ||
| HITCBC | 449 | 34 | auto const nt = | 449 | 34 | auto const nt = | ||
| HITCBC | 450 | 34 | sizeof(entry) * h_.count; | 450 | 34 | sizeof(entry) * h_.count; | ||
| HITCBC | 451 | 34 | if(nt > 0) | 451 | 34 | if(nt > 0) | ||
| HITCBC | 452 | 6 | std::memcpy( | 452 | 6 | std::memcpy( | ||
| HITCBC | 453 | 6 | h_.buf + h_.cap - nt, | 453 | 6 | h_.buf + h_.cap - nt, | ||
| HITCBC | 454 | 6 | op.end() - nt, | 454 | 6 | op.end() - nt, | ||
| 455 | nt); | 455 | nt); | |||||
| HITCBC | 456 | 95 | } | 456 | 95 | } | ||
| 457 | 457 | |||||||
| 458 | void | 458 | void | |||||
| HITCBC | 459 | 7 | fields_base:: | 459 | 7 | fields_base:: | ||
| 460 | shrink_to_fit() | 460 | shrink_to_fit() | |||||
| 461 | { | 461 | { | |||||
| HITCBC | 462 | 14 | if(detail::header::bytes_needed( | 462 | 14 | if(detail::header::bytes_needed( | ||
| HITCBC | 463 | 7 | h_.size, h_.count) >= | 463 | 7 | h_.size, h_.count) >= | ||
| HITCBC | 464 | 7 | h_.cap) | 464 | 7 | h_.cap) | ||
| HITCBC | 465 | 3 | return; | 465 | 3 | return; | ||
| 466 | 466 | |||||||
| HITCBC | 467 | 4 | if(external_storage_) | 467 | 4 | if(external_storage_) | ||
| MISUBC | 468 | ✗ | return; | 468 | ✗ | return; | ||
| 469 | 469 | |||||||
| HITCBC | 470 | 4 | fields_base tmp(h_); | 470 | 4 | fields_base tmp(h_); | ||
| HITCBC | 471 | 4 | tmp.h_.swap(h_); | 471 | 4 | tmp.h_.swap(h_); | ||
| HITCBC | 472 | 4 | } | 472 | 4 | } | ||
| 473 | 473 | |||||||
| 474 | 474 | |||||||
| 475 | void | 475 | void | |||||
| HITCBC | 476 | 30 | fields_base:: | 476 | 30 | fields_base:: | ||
| 477 | set_max_capacity_in_bytes(std::size_t n) | 477 | set_max_capacity_in_bytes(std::size_t n) | |||||
| 478 | { | 478 | { | |||||
| HITCBC | 479 | 30 | if(n < h_.cap) | 479 | 30 | if(n < h_.cap) | ||
| HITCBC | 480 | 6 | detail::throw_invalid_argument(); | 480 | 6 | detail::throw_invalid_argument(); | ||
| HITCBC | 481 | 24 | max_cap_ = n; | 481 | 24 | max_cap_ = n; | ||
| HITCBC | 482 | 24 | } | 482 | 24 | } | ||
| 483 | 483 | |||||||
| 484 | //-------------------------------------------- | 484 | //-------------------------------------------- | |||||
| 485 | // | 485 | // | |||||
| 486 | // Observers | 486 | // Observers | |||||
| 487 | // | 487 | // | |||||
| 488 | //-------------------------------------------- | 488 | //-------------------------------------------- | |||||
| 489 | 489 | |||||||
| 490 | 490 | |||||||
| MISUBC | 491 | ✗ | fields_base:: | 491 | ✗ | fields_base:: | ||
| 492 | value_type:: | 492 | value_type:: | |||||
| 493 | value_type( | 493 | value_type( | |||||
| MISUBC | 494 | ✗ | reference const& other) | 494 | ✗ | reference const& other) | ||
| MISUBC | 495 | ✗ | : id(other.id) | 495 | ✗ | : id(other.id) | ||
| MISUBC | 496 | ✗ | , name(other.name) | 496 | ✗ | , name(other.name) | ||
| MISUBC | 497 | ✗ | , value(other.value) | 497 | ✗ | , value(other.value) | ||
| 498 | { | 498 | { | |||||
| MISUBC | 499 | ✗ | } | 499 | ✗ | } | ||
| 500 | 500 | |||||||
| 501 | //------------------------------------------------ | 501 | //------------------------------------------------ | |||||
| 502 | 502 | |||||||
| 503 | auto | 503 | auto | |||||
| HITCBC | 504 | 1890 | fields_base:: | 504 | 1890 | fields_base:: | ||
| 505 | iterator:: | 505 | iterator:: | |||||
| 506 | operator*() const noexcept -> | 506 | operator*() const noexcept -> | |||||
| 507 | reference | 507 | reference | |||||
| 508 | { | 508 | { | |||||
| HITCBC | 509 | 1890 | BOOST_ASSERT(i_ < ph_->count); | 509 | 1890 | BOOST_ASSERT(i_ < ph_->count); | ||
| 510 | auto tab = | 510 | auto tab = | |||||
| HITCBC | 511 | 1890 | ph_->tab(); | 511 | 1890 | ph_->tab(); | ||
| 512 | auto const& e = | 512 | auto const& e = | |||||
| HITCBC | 513 | 1890 | tab[i_]; | 513 | 1890 | tab[i_]; | ||
| HITCBC | 514 | 1890 | auto const* p = | 514 | 1890 | auto const* p = | ||
| HITCBC | 515 | 1890 | ph_->cbuf + ph_->prefix; | 515 | 1890 | ph_->cbuf + ph_->prefix; | ||
| 516 | return { | 516 | return { | |||||
| HITCBC | 517 | 1890 | (e.id == detail::header::unknown_field) | 517 | 1890 | (e.id == detail::header::unknown_field) | ||
| HITCBC | 518 | 1890 | ? optional<field>{} : e.id, | 518 | 1890 | ? optional<field>{} : e.id, | ||
| 519 | core::string_view( | 519 | core::string_view( | |||||
| HITCBC | 520 | 1890 | p + e.np, e.nn), | 520 | 1890 | p + e.np, e.nn), | ||
| 521 | core::string_view( | 521 | core::string_view( | |||||
| HITCBC | 522 | 1890 | p + e.vp, e.vn) }; | 522 | 1890 | p + e.vp, e.vn) }; | ||
| 523 | } | 523 | } | |||||
| 524 | 524 | |||||||
| 525 | //------------------------------------------------ | 525 | //------------------------------------------------ | |||||
| 526 | 526 | |||||||
| 527 | auto | 527 | auto | |||||
| HITCBC | 528 | 24 | fields_base:: | 528 | 24 | fields_base:: | ||
| 529 | reverse_iterator:: | 529 | reverse_iterator:: | |||||
| 530 | operator*() const noexcept -> | 530 | operator*() const noexcept -> | |||||
| 531 | reference | 531 | reference | |||||
| 532 | { | 532 | { | |||||
| HITCBC | 533 | 24 | BOOST_ASSERT(i_ > 0); | 533 | 24 | BOOST_ASSERT(i_ > 0); | ||
| 534 | auto tab = | 534 | auto tab = | |||||
| HITCBC | 535 | 24 | ph_->tab(); | 535 | 24 | ph_->tab(); | ||
| 536 | auto const& e = | 536 | auto const& e = | |||||
| HITCBC | 537 | 24 | tab[i_-1]; | 537 | 24 | tab[i_-1]; | ||
| HITCBC | 538 | 24 | auto const* p = | 538 | 24 | auto const* p = | ||
| HITCBC | 539 | 24 | ph_->cbuf + ph_->prefix; | 539 | 24 | ph_->cbuf + ph_->prefix; | ||
| 540 | return { | 540 | return { | |||||
| HITCBC | 541 | 24 | (e.id == detail::header::unknown_field) | 541 | 24 | (e.id == detail::header::unknown_field) | ||
| HITCBC | 542 | 24 | ? optional<field>{} : e.id, | 542 | 24 | ? optional<field>{} : e.id, | ||
| 543 | core::string_view( | 543 | core::string_view( | |||||
| HITCBC | 544 | 24 | p + e.np, e.nn), | 544 | 24 | p + e.np, e.nn), | ||
| 545 | core::string_view( | 545 | core::string_view( | |||||
| HITCBC | 546 | 24 | p + e.vp, e.vn) }; | 546 | 24 | p + e.vp, e.vn) }; | ||
| 547 | } | 547 | } | |||||
| 548 | 548 | |||||||
| 549 | //------------------------------------------------ | 549 | //------------------------------------------------ | |||||
| 550 | 550 | |||||||
| HITCBC | 551 | 21 | fields_base:: | 551 | 21 | fields_base:: | ||
| 552 | subrange:: | 552 | subrange:: | |||||
| 553 | iterator:: | 553 | iterator:: | |||||
| 554 | iterator( | 554 | iterator( | |||||
| 555 | detail::header const* ph, | 555 | detail::header const* ph, | |||||
| HITCBC | 556 | 21 | std::size_t i) noexcept | 556 | 21 | std::size_t i) noexcept | ||
| HITCBC | 557 | 21 | : ph_(ph) | 557 | 21 | : ph_(ph) | ||
| HITCBC | 558 | 21 | , i_(i) | 558 | 21 | , i_(i) | ||
| 559 | { | 559 | { | |||||
| HITCBC | 560 | 21 | BOOST_ASSERT(i <= ph_->count); | 560 | 21 | BOOST_ASSERT(i <= ph_->count); | ||
| HITCBC | 561 | 21 | } | 561 | 21 | } | ||
| 562 | 562 | |||||||
| HITCBC | 563 | 21 | fields_base:: | 563 | 21 | fields_base:: | ||
| 564 | subrange:: | 564 | subrange:: | |||||
| 565 | iterator:: | 565 | iterator:: | |||||
| 566 | iterator( | 566 | iterator( | |||||
| HITCBC | 567 | 21 | detail::header const* ph) noexcept | 567 | 21 | detail::header const* ph) noexcept | ||
| HITCBC | 568 | 21 | : ph_(ph) | 568 | 21 | : ph_(ph) | ||
| HITCBC | 569 | 21 | , i_(ph->count) | 569 | 21 | , i_(ph->count) | ||
| 570 | { | 570 | { | |||||
| HITCBC | 571 | 21 | } | 571 | 21 | } | ||
| 572 | 572 | |||||||
| 573 | auto | 573 | auto | |||||
| HITCBC | 574 | 11 | fields_base:: | 574 | 11 | fields_base:: | ||
| 575 | subrange:: | 575 | subrange:: | |||||
| 576 | iterator:: | 576 | iterator:: | |||||
| 577 | operator*() const noexcept -> | 577 | operator*() const noexcept -> | |||||
| 578 | reference const | 578 | reference const | |||||
| 579 | { | 579 | { | |||||
| 580 | auto tab = | 580 | auto tab = | |||||
| HITCBC | 581 | 11 | ph_->tab(); | 581 | 11 | ph_->tab(); | ||
| 582 | auto const& e = | 582 | auto const& e = | |||||
| HITCBC | 583 | 11 | tab[i_]; | 583 | 11 | tab[i_]; | ||
| HITCBC | 584 | 11 | auto const p = | 584 | 11 | auto const p = | ||
| HITCBC | 585 | 11 | ph_->cbuf + ph_->prefix; | 585 | 11 | ph_->cbuf + ph_->prefix; | ||
| HITCBC | 586 | 22 | return core::string_view( | 586 | 22 | return core::string_view( | ||
| HITCBC | 587 | 11 | p + e.vp, e.vn); | 587 | 11 | p + e.vp, e.vn); | ||
| 588 | } | 588 | } | |||||
| 589 | 589 | |||||||
| 590 | auto | 590 | auto | |||||
| HITCBC | 591 | 27 | fields_base:: | 591 | 27 | fields_base:: | ||
| 592 | subrange:: | 592 | subrange:: | |||||
| 593 | iterator:: | 593 | iterator:: | |||||
| 594 | operator++() noexcept -> | 594 | operator++() noexcept -> | |||||
| 595 | iterator& | 595 | iterator& | |||||
| 596 | { | 596 | { | |||||
| HITCBC | 597 | 27 | BOOST_ASSERT(i_ < ph_->count); | 597 | 27 | BOOST_ASSERT(i_ < ph_->count); | ||
| HITCBC | 598 | 27 | auto const* e = &ph_->tab()[i_]; | 598 | 27 | auto const* e = &ph_->tab()[i_]; | ||
| HITCBC | 599 | 27 | auto const id = e->id; | 599 | 27 | auto const id = e->id; | ||
| HITCBC | 600 | 27 | if(id != detail::header::unknown_field) | 600 | 27 | if(id != detail::header::unknown_field) | ||
| 601 | { | 601 | { | |||||
| HITCBC | 602 | 20 | ++i_; | 602 | 20 | ++i_; | ||
| HITCBC | 603 | 20 | --e; | 603 | 20 | --e; | ||
| HITCBC | 604 | 38 | while(i_ != ph_->count) | 604 | 38 | while(i_ != ph_->count) | ||
| 605 | { | 605 | { | |||||
| HITCBC | 606 | 26 | if(e->id == id) | 606 | 26 | if(e->id == id) | ||
| HITCBC | 607 | 8 | break; | 607 | 8 | break; | ||
| HITCBC | 608 | 18 | ++i_; | 608 | 18 | ++i_; | ||
| HITCBC | 609 | 18 | --e; | 609 | 18 | --e; | ||
| 610 | } | 610 | } | |||||
| HITCBC | 611 | 20 | return *this; | 611 | 20 | return *this; | ||
| 612 | } | 612 | } | |||||
| HITCBC | 613 | 7 | auto const p = | 613 | 7 | auto const p = | ||
| HITCBC | 614 | 7 | ph_->cbuf + ph_->prefix; | 614 | 7 | ph_->cbuf + ph_->prefix; | ||
| 615 | auto name = core::string_view( | 615 | auto name = core::string_view( | |||||
| HITCBC | 616 | 7 | p + e->np, e->nn); | 616 | 7 | p + e->np, e->nn); | ||
| HITCBC | 617 | 7 | ++i_; | 617 | 7 | ++i_; | ||
| HITCBC | 618 | 7 | --e; | 618 | 7 | --e; | ||
| HITCBC | 619 | 24 | while(i_ != ph_->count) | 619 | 24 | while(i_ != ph_->count) | ||
| 620 | { | 620 | { | |||||
| HITCBC | 621 | 20 | if(grammar::ci_is_equal( | 621 | 20 | if(grammar::ci_is_equal( | ||
| 622 | name, core::string_view( | 622 | name, core::string_view( | |||||
| HITCBC | 623 | 20 | p + e->np, e->nn))) | 623 | 20 | p + e->np, e->nn))) | ||
| HITCBC | 624 | 3 | break; | 624 | 3 | break; | ||
| HITCBC | 625 | 17 | ++i_; | 625 | 17 | ++i_; | ||
| HITCBC | 626 | 17 | --e; | 626 | 17 | --e; | ||
| 627 | } | 627 | } | |||||
| HITCBC | 628 | 7 | return *this; | 628 | 7 | return *this; | ||
| 629 | } | 629 | } | |||||
| 630 | 630 | |||||||
| 631 | //------------------------------------------------ | 631 | //------------------------------------------------ | |||||
| 632 | // | 632 | // | |||||
| 633 | // fields_base | 633 | // fields_base | |||||
| 634 | // | 634 | // | |||||
| 635 | //------------------------------------------------ | 635 | //------------------------------------------------ | |||||
| 636 | 636 | |||||||
| 637 | core::string_view | 637 | core::string_view | |||||
| HITCBC | 638 | 2 | fields_base:: | 638 | 2 | fields_base:: | ||
| 639 | at( | 639 | at( | |||||
| 640 | field id) const | 640 | field id) const | |||||
| 641 | { | 641 | { | |||||
| HITCBC | 642 | 2 | auto const it = find(id); | 642 | 2 | auto const it = find(id); | ||
| HITCBC | 643 | 2 | if(it == end()) | 643 | 2 | if(it == end()) | ||
| HITCBC | 644 | 2 | BOOST_THROW_EXCEPTION( | 644 | 2 | BOOST_THROW_EXCEPTION( | ||
| 645 | std::out_of_range{ "field not found" }); | 645 | std::out_of_range{ "field not found" }); | |||||
| HITCBC | 646 | 1 | return it->value; | 646 | 1 | return it->value; | ||
| 647 | } | 647 | } | |||||
| 648 | 648 | |||||||
| 649 | core::string_view | 649 | core::string_view | |||||
| HITCBC | 650 | 2 | fields_base:: | 650 | 2 | fields_base:: | ||
| 651 | at( | 651 | at( | |||||
| 652 | core::string_view name) const | 652 | core::string_view name) const | |||||
| 653 | { | 653 | { | |||||
| HITCBC | 654 | 2 | auto const it = find(name); | 654 | 2 | auto const it = find(name); | ||
| HITCBC | 655 | 2 | if(it == end()) | 655 | 2 | if(it == end()) | ||
| HITCBC | 656 | 2 | BOOST_THROW_EXCEPTION( | 656 | 2 | BOOST_THROW_EXCEPTION( | ||
| 657 | std::out_of_range{ "field not found" }); | 657 | std::out_of_range{ "field not found" }); | |||||
| HITCBC | 658 | 1 | return it->value; | 658 | 1 | return it->value; | ||
| 659 | } | 659 | } | |||||
| 660 | 660 | |||||||
| 661 | bool | 661 | bool | |||||
| HITCBC | 662 | 7 | fields_base:: | 662 | 7 | fields_base:: | ||
| 663 | exists( | 663 | exists( | |||||
| 664 | field id) const noexcept | 664 | field id) const noexcept | |||||
| 665 | { | 665 | { | |||||
| HITCBC | 666 | 7 | return find(id) != end(); | 666 | 7 | return find(id) != end(); | ||
| 667 | } | 667 | } | |||||
| 668 | 668 | |||||||
| 669 | bool | 669 | bool | |||||
| HITCBC | 670 | 7 | fields_base:: | 670 | 7 | fields_base:: | ||
| 671 | exists( | 671 | exists( | |||||
| 672 | core::string_view name) const noexcept | 672 | core::string_view name) const noexcept | |||||
| 673 | { | 673 | { | |||||
| HITCBC | 674 | 7 | return find(name) != end(); | 674 | 7 | return find(name) != end(); | ||
| 675 | } | 675 | } | |||||
| 676 | 676 | |||||||
| 677 | std::size_t | 677 | std::size_t | |||||
| HITCBC | 678 | 12 | fields_base:: | 678 | 12 | fields_base:: | ||
| 679 | count(field id) const noexcept | 679 | count(field id) const noexcept | |||||
| 680 | { | 680 | { | |||||
| HITCBC | 681 | 12 | std::size_t n = 0; | 681 | 12 | std::size_t n = 0; | ||
| HITCBC | 682 | 57 | for(auto v : *this) | 682 | 57 | for(auto v : *this) | ||
| HITCBC | 683 | 45 | if(v.id == id) | 683 | 45 | if(v.id == id) | ||
| HITCBC | 684 | 11 | ++n; | 684 | 11 | ++n; | ||
| HITCBC | 685 | 12 | return n; | 685 | 12 | return n; | ||
| 686 | } | 686 | } | |||||
| 687 | 687 | |||||||
| 688 | std::size_t | 688 | std::size_t | |||||
| HITCBC | 689 | 14 | fields_base:: | 689 | 14 | fields_base:: | ||
| 690 | count( | 690 | count( | |||||
| 691 | core::string_view name) const noexcept | 691 | core::string_view name) const noexcept | |||||
| 692 | { | 692 | { | |||||
| HITCBC | 693 | 14 | std::size_t n = 0; | 693 | 14 | std::size_t n = 0; | ||
| HITCBC | 694 | 76 | for(auto v : *this) | 694 | 76 | for(auto v : *this) | ||
| HITCBC | 695 | 62 | if(grammar::ci_is_equal( | 695 | 62 | if(grammar::ci_is_equal( | ||
| 696 | v.name, name)) | 696 | v.name, name)) | |||||
| HITCBC | 697 | 19 | ++n; | 697 | 19 | ++n; | ||
| HITCBC | 698 | 14 | return n; | 698 | 14 | return n; | ||
| 699 | } | 699 | } | |||||
| 700 | 700 | |||||||
| 701 | auto | 701 | auto | |||||
| HITCBC | 702 | 134 | fields_base:: | 702 | 134 | fields_base:: | ||
| 703 | find(field id) const noexcept -> | 703 | find(field id) const noexcept -> | |||||
| 704 | iterator | 704 | iterator | |||||
| 705 | { | 705 | { | |||||
| HITCBC | 706 | 134 | auto it = begin(); | 706 | 134 | auto it = begin(); | ||
| HITCBC | 707 | 134 | auto const last = end(); | 707 | 134 | auto const last = end(); | ||
| HITCBC | 708 | 266 | while(it != last) | 708 | 266 | while(it != last) | ||
| 709 | { | 709 | { | |||||
| HITCBC | 710 | 245 | if(it->id == id) | 710 | 245 | if(it->id == id) | ||
| HITCBC | 711 | 113 | break; | 711 | 113 | break; | ||
| HITCBC | 712 | 132 | ++it; | 712 | 132 | ++it; | ||
| 713 | } | 713 | } | |||||
| HITCBC | 714 | 134 | return it; | 714 | 134 | return it; | ||
| 715 | } | 715 | } | |||||
| 716 | 716 | |||||||
| 717 | auto | 717 | auto | |||||
| HITCBC | 718 | 93 | fields_base:: | 718 | 93 | fields_base:: | ||
| 719 | find( | 719 | find( | |||||
| 720 | core::string_view name) const noexcept -> | 720 | core::string_view name) const noexcept -> | |||||
| 721 | iterator | 721 | iterator | |||||
| 722 | { | 722 | { | |||||
| HITCBC | 723 | 93 | auto it = begin(); | 723 | 93 | auto it = begin(); | ||
| HITCBC | 724 | 93 | auto const last = end(); | 724 | 93 | auto const last = end(); | ||
| HITCBC | 725 | 206 | while(it != last) | 725 | 206 | while(it != last) | ||
| 726 | { | 726 | { | |||||
| HITCBC | 727 | 200 | if(grammar::ci_is_equal( | 727 | 200 | if(grammar::ci_is_equal( | ||
| HITCBC | 728 | 400 | it->name, name)) | 728 | 400 | it->name, name)) | ||
| HITCBC | 729 | 87 | break; | 729 | 87 | break; | ||
| HITCBC | 730 | 113 | ++it; | 730 | 113 | ++it; | ||
| 731 | } | 731 | } | |||||
| HITCBC | 732 | 93 | return it; | 732 | 93 | return it; | ||
| 733 | } | 733 | } | |||||
| 734 | 734 | |||||||
| 735 | auto | 735 | auto | |||||
| HITCBC | 736 | 2 | fields_base:: | 736 | 2 | fields_base:: | ||
| 737 | find( | 737 | find( | |||||
| 738 | iterator from, | 738 | iterator from, | |||||
| 739 | field id) const noexcept -> | 739 | field id) const noexcept -> | |||||
| 740 | iterator | 740 | iterator | |||||
| 741 | { | 741 | { | |||||
| HITCBC | 742 | 2 | auto const last = end(); | 742 | 2 | auto const last = end(); | ||
| HITCBC | 743 | 11 | while(from != last) | 743 | 11 | while(from != last) | ||
| 744 | { | 744 | { | |||||
| HITCBC | 745 | 10 | if(from->id == id) | 745 | 10 | if(from->id == id) | ||
| HITCBC | 746 | 1 | break; | 746 | 1 | break; | ||
| HITCBC | 747 | 9 | ++from; | 747 | 9 | ++from; | ||
| 748 | } | 748 | } | |||||
| HITCBC | 749 | 2 | return from; | 749 | 2 | return from; | ||
| 750 | } | 750 | } | |||||
| 751 | 751 | |||||||
| 752 | auto | 752 | auto | |||||
| HITCBC | 753 | 2 | fields_base:: | 753 | 2 | fields_base:: | ||
| 754 | find( | 754 | find( | |||||
| 755 | iterator from, | 755 | iterator from, | |||||
| 756 | core::string_view name) const noexcept -> | 756 | core::string_view name) const noexcept -> | |||||
| 757 | iterator | 757 | iterator | |||||
| 758 | { | 758 | { | |||||
| HITCBC | 759 | 2 | auto const last = end(); | 759 | 2 | auto const last = end(); | ||
| HITCBC | 760 | 12 | while(from != last) | 760 | 12 | while(from != last) | ||
| 761 | { | 761 | { | |||||
| HITCBC | 762 | 11 | if(grammar::ci_is_equal( | 762 | 11 | if(grammar::ci_is_equal( | ||
| HITCBC | 763 | 22 | name, from->name)) | 763 | 22 | name, from->name)) | ||
| HITCBC | 764 | 1 | break; | 764 | 1 | break; | ||
| HITCBC | 765 | 10 | ++from; | 765 | 10 | ++from; | ||
| 766 | } | 766 | } | |||||
| HITCBC | 767 | 2 | return from; | 767 | 2 | return from; | ||
| 768 | } | 768 | } | |||||
| 769 | 769 | |||||||
| 770 | auto | 770 | auto | |||||
| HITCBC | 771 | 3 | fields_base:: | 771 | 3 | fields_base:: | ||
| 772 | find_last( | 772 | find_last( | |||||
| 773 | iterator it, | 773 | iterator it, | |||||
| 774 | field id) const noexcept -> | 774 | field id) const noexcept -> | |||||
| 775 | iterator | 775 | iterator | |||||
| 776 | { | 776 | { | |||||
| HITCBC | 777 | 3 | auto const it0 = begin(); | 777 | 3 | auto const it0 = begin(); | ||
| 778 | for(;;) | 778 | for(;;) | |||||
| 779 | { | 779 | { | |||||
| HITCBC | 780 | 10 | if(it == it0) | 780 | 10 | if(it == it0) | ||
| HITCBC | 781 | 1 | return end(); | 781 | 1 | return end(); | ||
| HITCBC | 782 | 9 | --it; | 782 | 9 | --it; | ||
| HITCBC | 783 | 9 | if(it->id == id) | 783 | 9 | if(it->id == id) | ||
| HITCBC | 784 | 2 | return it; | 784 | 2 | return it; | ||
| 785 | } | 785 | } | |||||
| 786 | } | 786 | } | |||||
| 787 | 787 | |||||||
| 788 | auto | 788 | auto | |||||
| HITCBC | 789 | 3 | fields_base:: | 789 | 3 | fields_base:: | ||
| 790 | find_last( | 790 | find_last( | |||||
| 791 | iterator it, | 791 | iterator it, | |||||
| 792 | core::string_view name) const noexcept -> | 792 | core::string_view name) const noexcept -> | |||||
| 793 | iterator | 793 | iterator | |||||
| 794 | { | 794 | { | |||||
| HITCBC | 795 | 3 | auto const it0 = begin(); | 795 | 3 | auto const it0 = begin(); | ||
| 796 | for(;;) | 796 | for(;;) | |||||
| 797 | { | 797 | { | |||||
| HITCBC | 798 | 14 | if(it == it0) | 798 | 14 | if(it == it0) | ||
| HITCBC | 799 | 1 | return end(); | 799 | 1 | return end(); | ||
| HITCBC | 800 | 13 | --it; | 800 | 13 | --it; | ||
| HITCBC | 801 | 13 | if(grammar::ci_is_equal( | 801 | 13 | if(grammar::ci_is_equal( | ||
| HITCBC | 802 | 26 | it->name, name)) | 802 | 26 | it->name, name)) | ||
| HITCBC | 803 | 2 | return it; | 803 | 2 | return it; | ||
| 804 | } | 804 | } | |||||
| 805 | } | 805 | } | |||||
| 806 | 806 | |||||||
| 807 | core::string_view | 807 | core::string_view | |||||
| HITCBC | 808 | 39 | fields_base:: | 808 | 39 | fields_base:: | ||
| 809 | value_or( | 809 | value_or( | |||||
| 810 | field id, | 810 | field id, | |||||
| 811 | core::string_view s) const noexcept | 811 | core::string_view s) const noexcept | |||||
| 812 | { | 812 | { | |||||
| HITCBC | 813 | 39 | auto it = find(id); | 813 | 39 | auto it = find(id); | ||
| HITCBC | 814 | 39 | if(it != end()) | 814 | 39 | if(it != end()) | ||
| HITCBC | 815 | 29 | return it->value; | 815 | 29 | return it->value; | ||
| HITCBC | 816 | 10 | return s; | 816 | 10 | return s; | ||
| 817 | } | 817 | } | |||||
| 818 | 818 | |||||||
| 819 | core::string_view | 819 | core::string_view | |||||
| HITCBC | 820 | 2 | fields_base:: | 820 | 2 | fields_base:: | ||
| 821 | value_or( | 821 | value_or( | |||||
| 822 | core::string_view name, | 822 | core::string_view name, | |||||
| 823 | core::string_view s) const noexcept | 823 | core::string_view s) const noexcept | |||||
| 824 | { | 824 | { | |||||
| HITCBC | 825 | 2 | auto it = find(name); | 825 | 2 | auto it = find(name); | ||
| HITCBC | 826 | 2 | if(it != end()) | 826 | 2 | if(it != end()) | ||
| HITCBC | 827 | 1 | return it->value; | 827 | 1 | return it->value; | ||
| HITCBC | 828 | 1 | return s; | 828 | 1 | return s; | ||
| 829 | } | 829 | } | |||||
| 830 | 830 | |||||||
| 831 | //------------------------------------------------ | 831 | //------------------------------------------------ | |||||
| 832 | 832 | |||||||
| 833 | auto | 833 | auto | |||||
| HITCBC | 834 | 16 | fields_base:: | 834 | 16 | fields_base:: | ||
| 835 | find_all( | 835 | find_all( | |||||
| 836 | field id) const noexcept -> | 836 | field id) const noexcept -> | |||||
| 837 | subrange | 837 | subrange | |||||
| 838 | { | 838 | { | |||||
| HITCBC | 839 | 16 | return subrange( | 839 | 16 | return subrange( | ||
| HITCBC | 840 | 32 | &h_, find(id).i_); | 840 | 32 | &h_, find(id).i_); | ||
| 841 | } | 841 | } | |||||
| 842 | 842 | |||||||
| 843 | auto | 843 | auto | |||||
| HITCBC | 844 | 5 | fields_base:: | 844 | 5 | fields_base:: | ||
| 845 | find_all( | 845 | find_all( | |||||
| 846 | core::string_view name) const noexcept -> | 846 | core::string_view name) const noexcept -> | |||||
| 847 | subrange | 847 | subrange | |||||
| 848 | { | 848 | { | |||||
| HITCBC | 849 | 5 | return subrange( | 849 | 5 | return subrange( | ||
| HITCBC | 850 | 10 | &h_, find(name).i_); | 850 | 10 | &h_, find(name).i_); | ||
| 851 | } | 851 | } | |||||
| 852 | 852 | |||||||
| 853 | std::ostream& | 853 | std::ostream& | |||||
| HITCBC | 854 | 1 | operator<<( | 854 | 1 | operator<<( | ||
| 855 | std::ostream& os, | 855 | std::ostream& os, | |||||
| 856 | const fields_base& f) | 856 | const fields_base& f) | |||||
| 857 | { | 857 | { | |||||
| HITCBC | 858 | 1 | if(f.h_.prefix != 0) | 858 | 1 | if(f.h_.prefix != 0) | ||
| HITCBC | 859 | 1 | os << core::string_view(f.h_.cbuf, f.h_.prefix - 2) << '\n'; | 859 | 1 | os << core::string_view(f.h_.cbuf, f.h_.prefix - 2) << '\n'; | ||
| 860 | 860 | |||||||
| HITCBC | 861 | 3 | for(auto ref : f) | 861 | 3 | for(auto ref : f) | ||
| HITCBC | 862 | 2 | os << ref.name << ": " << ref.value << '\n'; | 862 | 2 | os << ref.name << ": " << ref.value << '\n'; | ||
| 863 | 863 | |||||||
| HITCBC | 864 | 1 | return os; | 864 | 1 | return os; | ||
| 865 | } | 865 | } | |||||
| 866 | 866 | |||||||
| 867 | //------------------------------------------------ | 867 | //------------------------------------------------ | |||||
| 868 | // | 868 | // | |||||
| 869 | // Modifiers | 869 | // Modifiers | |||||
| 870 | // | 870 | // | |||||
| 871 | //------------------------------------------------ | 871 | //------------------------------------------------ | |||||
| 872 | 872 | |||||||
| 873 | auto | 873 | auto | |||||
| HITCBC | 874 | 30 | fields_base:: | 874 | 30 | fields_base:: | ||
| 875 | erase( | 875 | erase( | |||||
| 876 | iterator it) noexcept -> iterator | 876 | iterator it) noexcept -> iterator | |||||
| 877 | { | 877 | { | |||||
| HITCBC | 878 | 30 | auto const id = it->id.value_or( | 878 | 30 | auto const id = it->id.value_or( | ||
| 879 | detail::header::unknown_field); | 879 | detail::header::unknown_field); | |||||
| HITCBC | 880 | 30 | raw_erase(it.i_); | 880 | 30 | raw_erase(it.i_); | ||
| HITCBC | 881 | 30 | h_.on_erase(id); | 881 | 30 | h_.on_erase(id); | ||
| HITCBC | 882 | 30 | return it; | 882 | 30 | return it; | ||
| 883 | } | 883 | } | |||||
| 884 | 884 | |||||||
| 885 | std::size_t | 885 | std::size_t | |||||
| HITCBC | 886 | 30 | fields_base:: | 886 | 30 | fields_base:: | ||
| 887 | erase( | 887 | erase( | |||||
| 888 | field id) noexcept | 888 | field id) noexcept | |||||
| 889 | { | 889 | { | |||||
| HITCBC | 890 | 30 | auto const i0 = h_.find(id); | 890 | 30 | auto const i0 = h_.find(id); | ||
| HITCBC | 891 | 30 | if(i0 == h_.count) | 891 | 30 | if(i0 == h_.count) | ||
| HITCBC | 892 | 3 | return 0; | 892 | 3 | return 0; | ||
| HITCBC | 893 | 27 | return erase_all(i0, id); | 893 | 27 | return erase_all(i0, id); | ||
| 894 | } | 894 | } | |||||
| 895 | 895 | |||||||
| 896 | std::size_t | 896 | std::size_t | |||||
| HITCBC | 897 | 18 | fields_base:: | 897 | 18 | fields_base:: | ||
| 898 | erase( | 898 | erase( | |||||
| 899 | core::string_view name) noexcept | 899 | core::string_view name) noexcept | |||||
| 900 | { | 900 | { | |||||
| HITCBC | 901 | 18 | auto const i0 = h_.find(name); | 901 | 18 | auto const i0 = h_.find(name); | ||
| HITCBC | 902 | 18 | if(i0 == h_.count) | 902 | 18 | if(i0 == h_.count) | ||
| HITCBC | 903 | 3 | return 0; | 903 | 3 | return 0; | ||
| HITCBC | 904 | 15 | auto const ft = h_.tab(); | 904 | 15 | auto const ft = h_.tab(); | ||
| HITCBC | 905 | 15 | auto const id = ft[i0].id; | 905 | 15 | auto const id = ft[i0].id; | ||
| HITCBC | 906 | 15 | if(id == detail::header::unknown_field) | 906 | 15 | if(id == detail::header::unknown_field) | ||
| HITCBC | 907 | 6 | return erase_all(i0, name); | 907 | 6 | return erase_all(i0, name); | ||
| HITCBC | 908 | 9 | return erase_all(i0, id); | 908 | 9 | return erase_all(i0, id); | ||
| 909 | } | 909 | } | |||||
| 910 | 910 | |||||||
| 911 | //------------------------------------------------ | 911 | //------------------------------------------------ | |||||
| 912 | 912 | |||||||
| 913 | void | 913 | void | |||||
| HITCBC | 914 | 28 | fields_base:: | 914 | 28 | fields_base:: | ||
| 915 | set( | 915 | set( | |||||
| 916 | iterator it, | 916 | iterator it, | |||||
| 917 | core::string_view value, | 917 | core::string_view value, | |||||
| 918 | system::error_code& ec) | 918 | system::error_code& ec) | |||||
| 919 | { | 919 | { | |||||
| HITCBC | 920 | 28 | auto rv = verify_field_value(value); | 920 | 28 | auto rv = verify_field_value(value); | ||
| HITCBC | 921 | 28 | if(rv.has_error()) | 921 | 28 | if(rv.has_error()) | ||
| 922 | { | 922 | { | |||||
| HITCBC | 923 | 4 | ec = rv.error(); | 923 | 4 | ec = rv.error(); | ||
| HITCBC | 924 | 4 | return; | 924 | 4 | return; | ||
| 925 | } | 925 | } | |||||
| 926 | 926 | |||||||
| HITCBC | 927 | 24 | value = rv->value; | 927 | 24 | value = rv->value; | ||
| HITCBC | 928 | 24 | bool has_obs_fold = rv->has_obs_fold; | 928 | 24 | bool has_obs_fold = rv->has_obs_fold; | ||
| 929 | 929 | |||||||
| HITCBC | 930 | 24 | auto const i = it.i_; | 930 | 24 | auto const i = it.i_; | ||
| HITCBC | 931 | 24 | auto tab = h_.tab(); | 931 | 24 | auto tab = h_.tab(); | ||
| HITCBC | 932 | 24 | auto const& e0 = tab[i]; | 932 | 24 | auto const& e0 = tab[i]; | ||
| HITCBC | 933 | 24 | auto const pos0 = offset(i); | 933 | 24 | auto const pos0 = offset(i); | ||
| HITCBC | 934 | 24 | auto const pos1 = offset(i + 1); | 934 | 24 | auto const pos1 = offset(i + 1); | ||
| 935 | std::ptrdiff_t dn = | 935 | std::ptrdiff_t dn = | |||||
| HITCBC | 936 | 24 | value.size() - | 936 | 24 | value.size() - | ||
| HITCBC | 937 | 24 | it->value.size(); | 937 | 24 | it->value.size(); | ||
| HITCBC | 938 | 24 | if( value.empty() && | 938 | 24 | if( value.empty() && | ||
| HITCBC | 939 | 24 | ! it->value.empty()) | 939 | 24 | ! it->value.empty()) | ||
| MISUBC | 940 | ✗ | --dn; // remove SP | 940 | ✗ | --dn; // remove SP | ||
| HITCBC | 941 | 24 | else if( | 941 | 24 | else if( | ||
| HITCBC | 942 | 24 | it->value.empty() && | 942 | 24 | it->value.empty() && | ||
| MISUBC | 943 | ✗ | ! value.empty()) | 943 | ✗ | ! value.empty()) | ||
| MISUBC | 944 | ✗ | ++dn; // add SP | 944 | ✗ | ++dn; // add SP | ||
| 945 | 945 | |||||||
| HITCBC | 946 | 24 | op_t op(*this, &value); | 946 | 24 | op_t op(*this, &value); | ||
| HITCBC | 947 | 30 | if( dn > 0 && | 947 | 30 | if( dn > 0 && | ||
| HITCBC | 948 | 12 | op.grow(value.size() - | 948 | 12 | op.grow(value.size() - | ||
| HITCBC | 949 | 30 | it->value.size(), 0)) | 949 | 30 | it->value.size(), 0)) | ||
| 950 | { | 950 | { | |||||
| 951 | // reallocated | 951 | // reallocated | |||||
| HITCBC | 952 | 6 | auto dest = h_.buf + | 952 | 6 | auto dest = h_.buf + | ||
| HITCBC | 953 | 6 | pos0 + e0.nn + 1; | 953 | 6 | pos0 + e0.nn + 1; | ||
| HITCBC | 954 | 12 | std::memcpy( | 954 | 12 | std::memcpy( | ||
| HITCBC | 955 | 6 | h_.buf, | 955 | 6 | h_.buf, | ||
| HITCBC | 956 | 6 | op.buf(), | 956 | 6 | op.buf(), | ||
| HITCBC | 957 | 6 | dest - h_.buf); | 957 | 6 | dest - h_.buf); | ||
| HITCBC | 958 | 6 | if(! value.empty()) | 958 | 6 | if(! value.empty()) | ||
| 959 | { | 959 | { | |||||
| HITCBC | 960 | 6 | *dest++ = ' '; | 960 | 6 | *dest++ = ' '; | ||
| HITCBC | 961 | 6 | value.copy( | 961 | 6 | value.copy( | ||
| 962 | dest, | 962 | dest, | |||||
| 963 | value.size()); | 963 | value.size()); | |||||
| HITCBC | 964 | 6 | if( has_obs_fold ) | 964 | 6 | if( has_obs_fold ) | ||
| HITCBC | 965 | 3 | detail::remove_obs_fold( | 965 | 3 | detail::remove_obs_fold( | ||
| HITCBC | 966 | 3 | dest, dest + value.size()); | 966 | 3 | dest, dest + value.size()); | ||
| HITCBC | 967 | 6 | dest += value.size(); | 967 | 6 | dest += value.size(); | ||
| 968 | } | 968 | } | |||||
| HITCBC | 969 | 6 | *dest++ = '\r'; | 969 | 6 | *dest++ = '\r'; | ||
| HITCBC | 970 | 6 | *dest++ = '\n'; | 970 | 6 | *dest++ = '\n'; | ||
| HITCBC | 971 | 12 | std::memcpy( | 971 | 12 | std::memcpy( | ||
| HITCBC | 972 | 6 | h_.buf + pos1 + dn, | 972 | 6 | h_.buf + pos1 + dn, | ||
| HITCBC | 973 | 12 | op.buf() + pos1, | 973 | 12 | op.buf() + pos1, | ||
| HITCBC | 974 | 6 | h_.size - pos1); | 974 | 6 | h_.size - pos1); | ||
| HITCBC | 975 | 12 | std::memcpy( | 975 | 12 | std::memcpy( | ||
| HITCBC | 976 | 6 | h_.buf + h_.cap - | 976 | 6 | h_.buf + h_.cap - | ||
| HITCBC | 977 | 6 | sizeof(entry) * h_.count, | 977 | 6 | sizeof(entry) * h_.count, | ||
| HITCBC | 978 | 6 | &op.tab()[h_.count - 1], | 978 | 6 | &op.tab()[h_.count - 1], | ||
| HITCBC | 979 | 6 | sizeof(entry) * h_.count); | 979 | 6 | sizeof(entry) * h_.count); | ||
| 980 | } | 980 | } | |||||
| 981 | else | 981 | else | |||||
| 982 | { | 982 | { | |||||
| 983 | // copy the value first | 983 | // copy the value first | |||||
| HITCBC | 984 | 36 | auto dest = h_.buf + pos0 + | 984 | 36 | auto dest = h_.buf + pos0 + | ||
| HITCBC | 985 | 18 | it->name.size() + 1; | 985 | 18 | it->name.size() + 1; | ||
| HITCBC | 986 | 18 | if(! value.empty()) | 986 | 18 | if(! value.empty()) | ||
| 987 | { | 987 | { | |||||
| HITCBC | 988 | 18 | *dest++ = ' '; | 988 | 18 | *dest++ = ' '; | ||
| HITCBC | 989 | 18 | value.copy( | 989 | 18 | value.copy( | ||
| 990 | dest, | 990 | dest, | |||||
| 991 | value.size()); | 991 | value.size()); | |||||
| HITCBC | 992 | 18 | if( has_obs_fold ) | 992 | 18 | if( has_obs_fold ) | ||
| MISUBC | 993 | ✗ | detail::remove_obs_fold( | 993 | ✗ | detail::remove_obs_fold( | ||
| MISUBC | 994 | ✗ | dest, dest + value.size()); | 994 | ✗ | dest, dest + value.size()); | ||
| HITCBC | 995 | 18 | dest += value.size(); | 995 | 18 | dest += value.size(); | ||
| 996 | } | 996 | } | |||||
| HITCBC | 997 | 18 | op.move_chars( | 997 | 18 | op.move_chars( | ||
| HITCBC | 998 | 18 | h_.buf + pos1 + dn, | 998 | 18 | h_.buf + pos1 + dn, | ||
| HITCBC | 999 | 18 | h_.buf + pos1, | 999 | 18 | h_.buf + pos1, | ||
| HITCBC | 1000 | 18 | h_.size - pos1); | 1000 | 18 | h_.size - pos1); | ||
| HITCBC | 1001 | 18 | *dest++ = '\r'; | 1001 | 18 | *dest++ = '\r'; | ||
| HITCBC | 1002 | 18 | *dest++ = '\n'; | 1002 | 18 | *dest++ = '\n'; | ||
| 1003 | } | 1003 | } | |||||
| 1004 | { | 1004 | { | |||||
| 1005 | // update tab | 1005 | // update tab | |||||
| HITCBC | 1006 | 24 | auto ft = h_.tab(); | 1006 | 24 | auto ft = h_.tab(); | ||
| HITCBC | 1007 | 24 | for(std::size_t j = h_.count - 1; | 1007 | 24 | for(std::size_t j = h_.count - 1; | ||
| HITCBC | 1008 | 31 | j > i; --j) | 1008 | 31 | j > i; --j) | ||
| HITCBC | 1009 | 7 | ft[j] = ft[j] + dn; | 1009 | 7 | ft[j] = ft[j] + dn; | ||
| HITCBC | 1010 | 24 | auto& e = ft[i]; | 1010 | 24 | auto& e = ft[i]; | ||
| HITCBC | 1011 | 48 | e.vp = e.np + e.nn + | 1011 | 48 | e.vp = e.np + e.nn + | ||
| HITCBC | 1012 | 24 | 1 + ! value.empty(); | 1012 | 24 | 1 + ! value.empty(); | ||
| HITCBC | 1013 | 24 | e.vn = static_cast< | 1013 | 24 | e.vn = static_cast< | ||
| HITCBC | 1014 | 24 | offset_type>(value.size()); | 1014 | 24 | offset_type>(value.size()); | ||
| HITCBC | 1015 | 24 | h_.size = static_cast< | 1015 | 24 | h_.size = static_cast< | ||
| HITCBC | 1016 | 24 | offset_type>(h_.size + dn); | 1016 | 24 | offset_type>(h_.size + dn); | ||
| 1017 | } | 1017 | } | |||||
| HITCBC | 1018 | 24 | auto const id = it->id.value_or( | 1018 | 24 | auto const id = it->id.value_or( | ||
| 1019 | detail::header::unknown_field); | 1019 | detail::header::unknown_field); | |||||
| HITCBC | 1020 | 24 | if(h_.is_special(id)) | 1020 | 24 | if(h_.is_special(id)) | ||
| 1021 | { | 1021 | { | |||||
| 1022 | // replace first char of name | 1022 | // replace first char of name | |||||
| 1023 | // with null to hide metadata | 1023 | // with null to hide metadata | |||||
| HITCBC | 1024 | 9 | char saved = h_.buf[pos0]; | 1024 | 9 | char saved = h_.buf[pos0]; | ||
| HITCBC | 1025 | 9 | auto& e = h_.tab()[i]; | 1025 | 9 | auto& e = h_.tab()[i]; | ||
| HITCBC | 1026 | 9 | e.id = detail::header::unknown_field; | 1026 | 9 | e.id = detail::header::unknown_field; | ||
| HITCBC | 1027 | 9 | h_.buf[pos0] = '\0'; | 1027 | 9 | h_.buf[pos0] = '\0'; | ||
| HITCBC | 1028 | 9 | h_.on_erase(id); | 1028 | 9 | h_.on_erase(id); | ||
| HITCBC | 1029 | 9 | h_.buf[pos0] = saved; // restore | 1029 | 9 | h_.buf[pos0] = saved; // restore | ||
| HITCBC | 1030 | 9 | e.id = id; | 1030 | 9 | e.id = id; | ||
| HITCBC | 1031 | 9 | h_.on_insert(id, it->value); | 1031 | 9 | h_.on_insert(id, it->value); | ||
| 1032 | } | 1032 | } | |||||
| HITCBC | 1033 | 24 | } | 1033 | 24 | } | ||
| 1034 | 1034 | |||||||
| 1035 | // erase existing fields with id | 1035 | // erase existing fields with id | |||||
| 1036 | // and then add the field with value | 1036 | // and then add the field with value | |||||
| 1037 | void | 1037 | void | |||||
| HITCBC | 1038 | 109 | fields_base:: | 1038 | 109 | fields_base:: | ||
| 1039 | set( | 1039 | set( | |||||
| 1040 | field id, | 1040 | field id, | |||||
| 1041 | core::string_view value, | 1041 | core::string_view value, | |||||
| 1042 | system::error_code& ec) | 1042 | system::error_code& ec) | |||||
| 1043 | { | 1043 | { | |||||
| HITCBC | 1044 | 109 | auto rv = verify_field_value(value); | 1044 | 109 | auto rv = verify_field_value(value); | ||
| HITCBC | 1045 | 109 | if(rv.has_error()) | 1045 | 109 | if(rv.has_error()) | ||
| 1046 | { | 1046 | { | |||||
| HITCBC | 1047 | 4 | ec = rv.error(); | 1047 | 4 | ec = rv.error(); | ||
| HITCBC | 1048 | 4 | return; | 1048 | 4 | return; | ||
| 1049 | } | 1049 | } | |||||
| 1050 | 1050 | |||||||
| HITCBC | 1051 | 105 | auto const i0 = h_.find(id); | 1051 | 105 | auto const i0 = h_.find(id); | ||
| HITCBC | 1052 | 105 | if(i0 != h_.count) | 1052 | 105 | if(i0 != h_.count) | ||
| 1053 | { | 1053 | { | |||||
| 1054 | // field exists | 1054 | // field exists | |||||
| HITCBC | 1055 | 21 | auto const ft = h_.tab(); | 1055 | 21 | auto const ft = h_.tab(); | ||
| 1056 | { | 1056 | { | |||||
| 1057 | // provide strong guarantee | 1057 | // provide strong guarantee | |||||
| 1058 | auto const n0 = | 1058 | auto const n0 = | |||||
| HITCBC | 1059 | 21 | h_.size - length(i0); | 1059 | 21 | h_.size - length(i0); | ||
| 1060 | auto const n = | 1060 | auto const n = | |||||
| HITCBC | 1061 | 21 | ft[i0].nn + 2 + | 1061 | 21 | ft[i0].nn + 2 + | ||
| HITCBC | 1062 | 21 | rv->value.size() + 2; | 1062 | 21 | rv->value.size() + 2; | ||
| 1063 | // VFALCO missing overflow check | 1063 | // VFALCO missing overflow check | |||||
| HITCBC | 1064 | 21 | reserve_bytes(n0 + n); | 1064 | 21 | reserve_bytes(n0 + n); | ||
| 1065 | } | 1065 | } | |||||
| HITCBC | 1066 | 21 | erase_all(i0, id); | 1066 | 21 | erase_all(i0, id); | ||
| 1067 | } | 1067 | } | |||||
| 1068 | 1068 | |||||||
| HITCBC | 1069 | 105 | insert_unchecked( | 1069 | 105 | insert_unchecked( | ||
| 1070 | id, | 1070 | id, | |||||
| 1071 | to_string(id), | 1071 | to_string(id), | |||||
| HITCBC | 1072 | 105 | rv->value, | 1072 | 105 | rv->value, | ||
| HITCBC | 1073 | 105 | h_.count, | 1073 | 105 | h_.count, | ||
| HITCBC | 1074 | 105 | rv->has_obs_fold); | 1074 | 105 | rv->has_obs_fold); | ||
| 1075 | } | 1075 | } | |||||
| 1076 | 1076 | |||||||
| 1077 | // erase existing fields with name | 1077 | // erase existing fields with name | |||||
| 1078 | // and then add the field with value | 1078 | // and then add the field with value | |||||
| 1079 | void | 1079 | void | |||||
| HITCBC | 1080 | 32 | fields_base:: | 1080 | 32 | fields_base:: | ||
| 1081 | set( | 1081 | set( | |||||
| 1082 | core::string_view name, | 1082 | core::string_view name, | |||||
| 1083 | core::string_view value, | 1083 | core::string_view value, | |||||
| 1084 | system::error_code& ec) | 1084 | system::error_code& ec) | |||||
| 1085 | { | 1085 | { | |||||
| HITCBC | 1086 | 32 | verify_field_name(name , ec); | 1086 | 32 | verify_field_name(name , ec); | ||
| HITCBC | 1087 | 32 | if(ec) | 1087 | 32 | if(ec) | ||
| HITCBC | 1088 | 8 | return; | 1088 | 8 | return; | ||
| 1089 | 1089 | |||||||
| HITCBC | 1090 | 28 | auto rv = verify_field_value(value); | 1090 | 28 | auto rv = verify_field_value(value); | ||
| HITCBC | 1091 | 28 | if(rv.has_error()) | 1091 | 28 | if(rv.has_error()) | ||
| 1092 | { | 1092 | { | |||||
| HITCBC | 1093 | 4 | ec = rv.error(); | 1093 | 4 | ec = rv.error(); | ||
| HITCBC | 1094 | 4 | return; | 1094 | 4 | return; | ||
| 1095 | } | 1095 | } | |||||
| 1096 | 1096 | |||||||
| HITCBC | 1097 | 24 | auto const i0 = h_.find(name); | 1097 | 24 | auto const i0 = h_.find(name); | ||
| HITCBC | 1098 | 24 | if(i0 != h_.count) | 1098 | 24 | if(i0 != h_.count) | ||
| 1099 | { | 1099 | { | |||||
| 1100 | // field exists | 1100 | // field exists | |||||
| HITCBC | 1101 | 18 | auto const ft = h_.tab(); | 1101 | 18 | auto const ft = h_.tab(); | ||
| HITCBC | 1102 | 18 | auto const id = ft[i0].id; | 1102 | 18 | auto const id = ft[i0].id; | ||
| 1103 | { | 1103 | { | |||||
| 1104 | // provide strong guarantee | 1104 | // provide strong guarantee | |||||
| 1105 | auto const n0 = | 1105 | auto const n0 = | |||||
| HITCBC | 1106 | 18 | h_.size - length(i0); | 1106 | 18 | h_.size - length(i0); | ||
| 1107 | auto const n = | 1107 | auto const n = | |||||
| HITCBC | 1108 | 18 | ft[i0].nn + 2 + | 1108 | 18 | ft[i0].nn + 2 + | ||
| HITCBC | 1109 | 18 | rv->value.size() + 2; | 1109 | 18 | rv->value.size() + 2; | ||
| 1110 | // VFALCO missing overflow check | 1110 | // VFALCO missing overflow check | |||||
| HITCBC | 1111 | 18 | reserve_bytes(n0 + n); | 1111 | 18 | reserve_bytes(n0 + n); | ||
| 1112 | } | 1112 | } | |||||
| 1113 | // VFALCO simple algorithm but | 1113 | // VFALCO simple algorithm but | |||||
| 1114 | // costs one extra memmove | 1114 | // costs one extra memmove | |||||
| HITCBC | 1115 | 18 | if(id != detail::header::unknown_field) | 1115 | 18 | if(id != detail::header::unknown_field) | ||
| HITCBC | 1116 | 15 | erase_all(i0, id); | 1116 | 15 | erase_all(i0, id); | ||
| 1117 | else | 1117 | else | |||||
| HITCBC | 1118 | 3 | erase_all(i0, name); | 1118 | 3 | erase_all(i0, name); | ||
| 1119 | } | 1119 | } | |||||
| HITCBC | 1120 | 24 | insert_unchecked( | 1120 | 24 | insert_unchecked( | ||
| HITCBC | 1121 | 24 | string_to_field(name), | 1121 | 24 | string_to_field(name), | ||
| 1122 | name, | 1122 | name, | |||||
| HITCBC | 1123 | 24 | rv->value, | 1123 | 24 | rv->value, | ||
| HITCBC | 1124 | 24 | h_.count, | 1124 | 24 | h_.count, | ||
| HITCBC | 1125 | 24 | rv->has_obs_fold); | 1125 | 24 | rv->has_obs_fold); | ||
| 1126 | } | 1126 | } | |||||
| 1127 | 1127 | |||||||
| 1128 | auto | 1128 | auto | |||||
| HITCBC | 1129 | 26 | fields_base:: | 1129 | 26 | fields_base:: | ||
| 1130 | insert( | 1130 | insert( | |||||
| 1131 | iterator before, | 1131 | iterator before, | |||||
| 1132 | field id, | 1132 | field id, | |||||
| 1133 | core::string_view value) | 1133 | core::string_view value) | |||||
| 1134 | -> iterator | 1134 | -> iterator | |||||
| 1135 | { | 1135 | { | |||||
| HITCBC | 1136 | 26 | system::error_code ec; | 1136 | 26 | system::error_code ec; | ||
| HITCBC | 1137 | 26 | auto const it = insert(before, id, value, ec); | 1137 | 26 | auto const it = insert(before, id, value, ec); | ||
| HITCBC | 1138 | 26 | if(ec) | 1138 | 26 | if(ec) | ||
| HITCBC | 1139 | 1 | detail::throw_system_error(ec); | 1139 | 1 | detail::throw_system_error(ec); | ||
| HITCBC | 1140 | 25 | return it; | 1140 | 25 | return it; | ||
| 1141 | } | 1141 | } | |||||
| 1142 | 1142 | |||||||
| 1143 | auto | 1143 | auto | |||||
| HITCBC | 1144 | 33 | fields_base:: | 1144 | 33 | fields_base:: | ||
| 1145 | insert( | 1145 | insert( | |||||
| 1146 | iterator before, | 1146 | iterator before, | |||||
| 1147 | field id, | 1147 | field id, | |||||
| 1148 | core::string_view value, | 1148 | core::string_view value, | |||||
| 1149 | system::error_code& ec) | 1149 | system::error_code& ec) | |||||
| 1150 | -> iterator | 1150 | -> iterator | |||||
| 1151 | { | 1151 | { | |||||
| HITCBC | 1152 | 33 | insert_impl( | 1152 | 33 | insert_impl( | ||
| 1153 | id, | 1153 | id, | |||||
| 1154 | to_string(id), | 1154 | to_string(id), | |||||
| 1155 | value, | 1155 | value, | |||||
| 1156 | before.i_, ec); | 1156 | before.i_, ec); | |||||
| HITCBC | 1157 | 33 | return before; | 1157 | 33 | return before; | ||
| 1158 | } | 1158 | } | |||||
| 1159 | 1159 | |||||||
| 1160 | auto | 1160 | auto | |||||
| HITCBC | 1161 | 13 | fields_base:: | 1161 | 13 | fields_base:: | ||
| 1162 | insert( | 1162 | insert( | |||||
| 1163 | iterator before, | 1163 | iterator before, | |||||
| 1164 | core::string_view name, | 1164 | core::string_view name, | |||||
| 1165 | core::string_view value) | 1165 | core::string_view value) | |||||
| 1166 | -> iterator | 1166 | -> iterator | |||||
| 1167 | { | 1167 | { | |||||
| HITCBC | 1168 | 13 | system::error_code ec; | 1168 | 13 | system::error_code ec; | ||
| HITCBC | 1169 | 13 | insert(before, name, value, ec); | 1169 | 13 | insert(before, name, value, ec); | ||
| HITCBC | 1170 | 13 | if(ec) | 1170 | 13 | if(ec) | ||
| HITCBC | 1171 | 1 | detail::throw_system_error(ec); | 1171 | 1 | detail::throw_system_error(ec); | ||
| HITCBC | 1172 | 12 | return before; | 1172 | 12 | return before; | ||
| 1173 | } | 1173 | } | |||||
| 1174 | 1174 | |||||||
| 1175 | auto | 1175 | auto | |||||
| HITCBC | 1176 | 16 | fields_base:: | 1176 | 16 | fields_base:: | ||
| 1177 | insert( | 1177 | insert( | |||||
| 1178 | iterator before, | 1178 | iterator before, | |||||
| 1179 | core::string_view name, | 1179 | core::string_view name, | |||||
| 1180 | core::string_view value, | 1180 | core::string_view value, | |||||
| 1181 | system::error_code& ec) | 1181 | system::error_code& ec) | |||||
| 1182 | -> iterator | 1182 | -> iterator | |||||
| 1183 | { | 1183 | { | |||||
| HITCBC | 1184 | 16 | insert_impl( | 1184 | 16 | insert_impl( | ||
| HITCBC | 1185 | 16 | string_to_field(name), | 1185 | 16 | string_to_field(name), | ||
| 1186 | name, | 1186 | name, | |||||
| 1187 | value, | 1187 | value, | |||||
| 1188 | before.i_, | 1188 | before.i_, | |||||
| 1189 | ec); | 1189 | ec); | |||||
| HITCBC | 1190 | 16 | return before; | 1190 | 16 | return before; | ||
| 1191 | } | 1191 | } | |||||
| 1192 | 1192 | |||||||
| 1193 | void | 1193 | void | |||||
| HITCBC | 1194 | 23 | fields_base:: | 1194 | 23 | fields_base:: | ||
| 1195 | set( | 1195 | set( | |||||
| 1196 | iterator it, | 1196 | iterator it, | |||||
| 1197 | core::string_view value) | 1197 | core::string_view value) | |||||
| 1198 | { | 1198 | { | |||||
| HITCBC | 1199 | 23 | system::error_code ec; | 1199 | 23 | system::error_code ec; | ||
| HITCBC | 1200 | 23 | set(it, value, ec); | 1200 | 23 | set(it, value, ec); | ||
| HITCBC | 1201 | 23 | if(ec) | 1201 | 23 | if(ec) | ||
| HITCBC | 1202 | 2 | detail::throw_system_error(ec); | 1202 | 2 | detail::throw_system_error(ec); | ||
| HITCBC | 1203 | 21 | } | 1203 | 21 | } | ||
| 1204 | 1204 | |||||||
| 1205 | //------------------------------------------------ | 1205 | //------------------------------------------------ | |||||
| 1206 | // | 1206 | // | |||||
| 1207 | // (implementation) | 1207 | // (implementation) | |||||
| 1208 | // | 1208 | // | |||||
| 1209 | //------------------------------------------------ | 1209 | //------------------------------------------------ | |||||
| 1210 | 1210 | |||||||
| 1211 | // copy start line and fields | 1211 | // copy start line and fields | |||||
| 1212 | void | 1212 | void | |||||
| HITCBC | 1213 | 17 | fields_base:: | 1213 | 17 | fields_base:: | ||
| 1214 | copy_impl( | 1214 | copy_impl( | |||||
| 1215 | detail::header const& h) | 1215 | detail::header const& h) | |||||
| 1216 | { | 1216 | { | |||||
| HITCBC | 1217 | 17 | BOOST_ASSERT( | 1217 | 17 | BOOST_ASSERT( | ||
| 1218 | h.kind == h_.kind); | 1218 | h.kind == h_.kind); | |||||
| 1219 | 1219 | |||||||
| 1220 | auto const n = | 1220 | auto const n = | |||||
| HITCBC | 1221 | 17 | detail::header::bytes_needed( | 1221 | 17 | detail::header::bytes_needed( | ||
| HITCBC | 1222 | 17 | h.size, h.count); | 1222 | 17 | h.size, h.count); | ||
| HITCBC | 1223 | 17 | if(n <= h_.cap && (!h.is_default() || external_storage_)) | 1223 | 17 | if(n <= h_.cap && (!h.is_default() || external_storage_)) | ||
| 1224 | { | 1224 | { | |||||
| 1225 | // no realloc | 1225 | // no realloc | |||||
| HITCBC | 1226 | 8 | h.assign_to(h_); | 1226 | 8 | h.assign_to(h_); | ||
| HITCBC | 1227 | 8 | h.copy_table( | 1227 | 8 | h.copy_table( | ||
| HITCBC | 1228 | 8 | h_.buf + h_.cap); | 1228 | 8 | h_.buf + h_.cap); | ||
| HITCBC | 1229 | 8 | std::memcpy( | 1229 | 8 | std::memcpy( | ||
| HITCBC | 1230 | 8 | h_.buf, | 1230 | 8 | h_.buf, | ||
| HITCBC | 1231 | 8 | h.cbuf, | 1231 | 8 | h.cbuf, | ||
| HITCBC | 1232 | 8 | h.size); | 1232 | 8 | h.size); | ||
| HITCBC | 1233 | 8 | return; | 1233 | 8 | return; | ||
| 1234 | } | 1234 | } | |||||
| 1235 | 1235 | |||||||
| 1236 | // static storages cannot reallocate | 1236 | // static storages cannot reallocate | |||||
| HITCBC | 1237 | 9 | if(external_storage_) | 1237 | 9 | if(external_storage_) | ||
| MISUBC | 1238 | ✗ | detail::throw_length_error(); | 1238 | ✗ | detail::throw_length_error(); | ||
| 1239 | 1239 | |||||||
| HITCBC | 1240 | 9 | fields_base tmp(h); | 1240 | 9 | fields_base tmp(h); | ||
| HITCBC | 1241 | 9 | tmp.h_.swap(h_); | 1241 | 9 | tmp.h_.swap(h_); | ||
| HITCBC | 1242 | 9 | } | 1242 | 9 | } | ||
| 1243 | 1243 | |||||||
| 1244 | void | 1244 | void | |||||
| HITCBC | 1245 | 209 | fields_base:: | 1245 | 209 | fields_base:: | ||
| 1246 | insert_impl( | 1246 | insert_impl( | |||||
| 1247 | optional<field> id, | 1247 | optional<field> id, | |||||
| 1248 | core::string_view name, | 1248 | core::string_view name, | |||||
| 1249 | core::string_view value, | 1249 | core::string_view value, | |||||
| 1250 | std::size_t before, | 1250 | std::size_t before, | |||||
| 1251 | system::error_code& ec) | 1251 | system::error_code& ec) | |||||
| 1252 | { | 1252 | { | |||||
| HITCBC | 1253 | 209 | verify_field_name(name, ec); | 1253 | 209 | verify_field_name(name, ec); | ||
| HITCBC | 1254 | 209 | if(ec) | 1254 | 209 | if(ec) | ||
| HITCBC | 1255 | 23 | return; | 1255 | 23 | return; | ||
| 1256 | 1256 | |||||||
| HITCBC | 1257 | 204 | auto rv = verify_field_value(value); | 1257 | 204 | auto rv = verify_field_value(value); | ||
| HITCBC | 1258 | 204 | if(rv.has_error()) | 1258 | 204 | if(rv.has_error()) | ||
| 1259 | { | 1259 | { | |||||
| HITCBC | 1260 | 18 | ec = rv.error(); | 1260 | 18 | ec = rv.error(); | ||
| HITCBC | 1261 | 18 | return; | 1261 | 18 | return; | ||
| 1262 | } | 1262 | } | |||||
| 1263 | 1263 | |||||||
| HITCBC | 1264 | 186 | insert_unchecked( | 1264 | 186 | insert_unchecked( | ||
| 1265 | id, | 1265 | id, | |||||
| 1266 | name, | 1266 | name, | |||||
| HITCBC | 1267 | 186 | rv->value, | 1267 | 186 | rv->value, | ||
| 1268 | before, | 1268 | before, | |||||
| HITCBC | 1269 | 186 | rv->has_obs_fold); | 1269 | 186 | rv->has_obs_fold); | ||
| 1270 | } | 1270 | } | |||||
| 1271 | 1271 | |||||||
| 1272 | void | 1272 | void | |||||
| HITCBC | 1273 | 315 | fields_base:: | 1273 | 315 | fields_base:: | ||
| 1274 | insert_unchecked( | 1274 | insert_unchecked( | |||||
| 1275 | optional<field> id, | 1275 | optional<field> id, | |||||
| 1276 | core::string_view name, | 1276 | core::string_view name, | |||||
| 1277 | core::string_view value, | 1277 | core::string_view value, | |||||
| 1278 | std::size_t before, | 1278 | std::size_t before, | |||||
| 1279 | bool has_obs_fold) | 1279 | bool has_obs_fold) | |||||
| 1280 | { | 1280 | { | |||||
| HITCBC | 1281 | 315 | auto const tab0 = h_.tab_(); | 1281 | 315 | auto const tab0 = h_.tab_(); | ||
| HITCBC | 1282 | 315 | auto const pos = offset(before); | 1282 | 315 | auto const pos = offset(before); | ||
| 1283 | auto const n = | 1283 | auto const n = | |||||
| HITCBC | 1284 | 315 | name.size() + // name | 1284 | 315 | name.size() + // name | ||
| HITCBC | 1285 | 315 | 1 + // ':' | 1285 | 315 | 1 + // ':' | ||
| HITCBC | 1286 | 315 | ! value.empty() + // [SP] | 1286 | 315 | ! value.empty() + // [SP] | ||
| HITCBC | 1287 | 315 | value.size() + // value | 1287 | 315 | value.size() + // value | ||
| HITCBC | 1288 | 315 | 2; // CRLF | 1288 | 315 | 2; // CRLF | ||
| 1289 | 1289 | |||||||
| HITCBC | 1290 | 315 | op_t op(*this, &name, &value); | 1290 | 315 | op_t op(*this, &name, &value); | ||
| HITCBC | 1291 | 315 | if(op.grow(n, 1)) | 1291 | 315 | if(op.grow(n, 1)) | ||
| 1292 | { | 1292 | { | |||||
| 1293 | // reallocated | 1293 | // reallocated | |||||
| HITCBC | 1294 | 223 | if(pos > 0) | 1294 | 223 | if(pos > 0) | ||
| HITCBC | 1295 | 203 | std::memcpy( | 1295 | 203 | std::memcpy( | ||
| HITCBC | 1296 | 203 | h_.buf, | 1296 | 203 | h_.buf, | ||
| HITCBC | 1297 | 203 | op.cbuf(), | 1297 | 203 | op.cbuf(), | ||
| 1298 | pos); | 1298 | pos); | |||||
| HITCBC | 1299 | 223 | if(before > 0) | 1299 | 223 | if(before > 0) | ||
| HITCBC | 1300 | 114 | std::memcpy( | 1300 | 114 | std::memcpy( | ||
| HITCBC | 1301 | 57 | h_.tab_() - before, | 1301 | 57 | h_.tab_() - before, | ||
| HITCBC | 1302 | 57 | tab0 - before, | 1302 | 57 | tab0 - before, | ||
| 1303 | before * sizeof(entry)); | 1303 | before * sizeof(entry)); | |||||
| HITCBC | 1304 | 446 | std::memcpy( | 1304 | 446 | std::memcpy( | ||
| HITCBC | 1305 | 223 | h_.buf + pos + n, | 1305 | 223 | h_.buf + pos + n, | ||
| HITCBC | 1306 | 223 | op.cbuf() + pos, | 1306 | 223 | op.cbuf() + pos, | ||
| HITCBC | 1307 | 223 | h_.size - pos); | 1307 | 223 | h_.size - pos); | ||
| 1308 | } | 1308 | } | |||||
| 1309 | else | 1309 | else | |||||
| 1310 | { | 1310 | { | |||||
| HITCBC | 1311 | 85 | op.move_chars( | 1311 | 85 | op.move_chars( | ||
| HITCBC | 1312 | 85 | h_.buf + pos + n, | 1312 | 85 | h_.buf + pos + n, | ||
| HITCBC | 1313 | 85 | h_.buf + pos, | 1313 | 85 | h_.buf + pos, | ||
| HITCBC | 1314 | 85 | h_.size - pos); | 1314 | 85 | h_.size - pos); | ||
| 1315 | } | 1315 | } | |||||
| 1316 | 1316 | |||||||
| 1317 | // serialize | 1317 | // serialize | |||||
| 1318 | { | 1318 | { | |||||
| HITCBC | 1319 | 308 | auto dest = h_.buf + pos; | 1319 | 308 | auto dest = h_.buf + pos; | ||
| HITCBC | 1320 | 308 | name.copy(dest, name.size()); | 1320 | 308 | name.copy(dest, name.size()); | ||
| HITCBC | 1321 | 308 | dest += name.size(); | 1321 | 308 | dest += name.size(); | ||
| HITCBC | 1322 | 308 | *dest++ = ':'; | 1322 | 308 | *dest++ = ':'; | ||
| HITCBC | 1323 | 308 | if(! value.empty()) | 1323 | 308 | if(! value.empty()) | ||
| 1324 | { | 1324 | { | |||||
| HITCBC | 1325 | 296 | *dest++ = ' '; | 1325 | 296 | *dest++ = ' '; | ||
| HITCBC | 1326 | 296 | value.copy( | 1326 | 296 | value.copy( | ||
| 1327 | dest, value.size()); | 1327 | dest, value.size()); | |||||
| HITCBC | 1328 | 296 | if( has_obs_fold ) | 1328 | 296 | if( has_obs_fold ) | ||
| HITCBC | 1329 | 18 | detail::remove_obs_fold( | 1329 | 18 | detail::remove_obs_fold( | ||
| HITCBC | 1330 | 18 | dest, dest + value.size()); | 1330 | 18 | dest, dest + value.size()); | ||
| HITCBC | 1331 | 296 | dest += value.size(); | 1331 | 296 | dest += value.size(); | ||
| 1332 | } | 1332 | } | |||||
| HITCBC | 1333 | 308 | *dest++ = '\r'; | 1333 | 308 | *dest++ = '\r'; | ||
| HITCBC | 1334 | 308 | *dest = '\n'; | 1334 | 308 | *dest = '\n'; | ||
| 1335 | } | 1335 | } | |||||
| 1336 | 1336 | |||||||
| 1337 | // update table | 1337 | // update table | |||||
| HITCBC | 1338 | 308 | auto const tab = h_.tab_(); | 1338 | 308 | auto const tab = h_.tab_(); | ||
| 1339 | { | 1339 | { | |||||
| HITCBC | 1340 | 308 | auto i = h_.count - before; | 1340 | 308 | auto i = h_.count - before; | ||
| HITCBC | 1341 | 308 | if(i > 0) | 1341 | 308 | if(i > 0) | ||
| 1342 | { | 1342 | { | |||||
| HITCBC | 1343 | 43 | auto p0 = tab0 - h_.count; | 1343 | 43 | auto p0 = tab0 - h_.count; | ||
| HITCBC | 1344 | 43 | auto p = tab - h_.count - 1; | 1344 | 43 | auto p = tab - h_.count - 1; | ||
| 1345 | do | 1345 | do | |||||
| 1346 | { | 1346 | { | |||||
| HITCBC | 1347 | 80 | *p++ = *p0++ + n; | 1347 | 80 | *p++ = *p0++ + n; | ||
| 1348 | } | 1348 | } | |||||
| HITCBC | 1349 | 80 | while(--i); | 1349 | 80 | while(--i); | ||
| 1350 | } | 1350 | } | |||||
| 1351 | } | 1351 | } | |||||
| HITCBC | 1352 | 308 | auto& e = tab[0 - static_cast<std::ptrdiff_t>(before) - 1]; | 1352 | 308 | auto& e = tab[0 - static_cast<std::ptrdiff_t>(before) - 1]; | ||
| HITCBC | 1353 | 308 | e.np = static_cast<offset_type>( | 1353 | 308 | e.np = static_cast<offset_type>( | ||
| HITCBC | 1354 | 308 | pos - h_.prefix); | 1354 | 308 | pos - h_.prefix); | ||
| HITCBC | 1355 | 308 | e.nn = static_cast< | 1355 | 308 | e.nn = static_cast< | ||
| HITCBC | 1356 | 308 | offset_type>(name.size()); | 1356 | 308 | offset_type>(name.size()); | ||
| HITCBC | 1357 | 308 | e.vp = static_cast<offset_type>( | 1357 | 308 | e.vp = static_cast<offset_type>( | ||
| HITCBC | 1358 | 616 | pos - h_.prefix + | 1358 | 616 | pos - h_.prefix + | ||
| HITCBC | 1359 | 308 | name.size() + 1 + | 1359 | 308 | name.size() + 1 + | ||
| HITCBC | 1360 | 308 | ! value.empty()); | 1360 | 308 | ! value.empty()); | ||
| HITCBC | 1361 | 308 | e.vn = static_cast< | 1361 | 308 | e.vn = static_cast< | ||
| HITCBC | 1362 | 308 | offset_type>(value.size()); | 1362 | 308 | offset_type>(value.size()); | ||
| HITCBC | 1363 | 308 | e.id = id.value_or( | 1363 | 308 | e.id = id.value_or( | ||
| 1364 | detail::header::unknown_field); | 1364 | detail::header::unknown_field); | |||||
| 1365 | 1365 | |||||||
| 1366 | // update container | 1366 | // update container | |||||
| HITCBC | 1367 | 308 | h_.count++; | 1367 | 308 | h_.count++; | ||
| HITCBC | 1368 | 308 | h_.size = static_cast< | 1368 | 308 | h_.size = static_cast< | ||
| HITCBC | 1369 | 308 | offset_type>(h_.size + n); | 1369 | 308 | offset_type>(h_.size + n); | ||
| HITCBC | 1370 | 308 | h_.on_insert(e.id, value); | 1370 | 308 | h_.on_insert(e.id, value); | ||
| HITCBC | 1371 | 315 | } | 1371 | 315 | } | ||
| 1372 | 1372 | |||||||
| 1373 | void | 1373 | void | |||||
| HITCBC | 1374 | 169 | fields_base:: | 1374 | 169 | fields_base:: | ||
| 1375 | raw_erase( | 1375 | raw_erase( | |||||
| 1376 | std::size_t i) noexcept | 1376 | std::size_t i) noexcept | |||||
| 1377 | { | 1377 | { | |||||
| HITCBC | 1378 | 169 | BOOST_ASSERT(i < h_.count); | 1378 | 169 | BOOST_ASSERT(i < h_.count); | ||
| HITCBC | 1379 | 169 | BOOST_ASSERT(h_.buf != nullptr); | 1379 | 169 | BOOST_ASSERT(h_.buf != nullptr); | ||
| HITCBC | 1380 | 169 | auto const p0 = offset(i); | 1380 | 169 | auto const p0 = offset(i); | ||
| HITCBC | 1381 | 169 | auto const p1 = offset(i + 1); | 1381 | 169 | auto const p1 = offset(i + 1); | ||
| HITCBC | 1382 | 169 | std::memmove( | 1382 | 169 | std::memmove( | ||
| HITCBC | 1383 | 169 | h_.buf + p0, | 1383 | 169 | h_.buf + p0, | ||
| HITCBC | 1384 | 169 | h_.buf + p1, | 1384 | 169 | h_.buf + p1, | ||
| HITCBC | 1385 | 169 | h_.size - p1); | 1385 | 169 | h_.size - p1); | ||
| HITCBC | 1386 | 169 | auto const n = p1 - p0; | 1386 | 169 | auto const n = p1 - p0; | ||
| HITCBC | 1387 | 169 | --h_.count; | 1387 | 169 | --h_.count; | ||
| HITCBC | 1388 | 169 | auto ft = h_.tab(); | 1388 | 169 | auto ft = h_.tab(); | ||
| HITCBC | 1389 | 270 | for(;i < h_.count; ++i) | 1389 | 270 | for(;i < h_.count; ++i) | ||
| HITCBC | 1390 | 101 | ft[i] = ft[i + 1] - n; | 1390 | 101 | ft[i] = ft[i + 1] - n; | ||
| HITCBC | 1391 | 169 | h_.size = static_cast< | 1391 | 169 | h_.size = static_cast< | ||
| HITCBC | 1392 | 169 | offset_type>(h_.size - n); | 1392 | 169 | offset_type>(h_.size - n); | ||
| HITCBC | 1393 | 169 | } | 1393 | 169 | } | ||
| 1394 | 1394 | |||||||
| 1395 | // erase n fields matching id | 1395 | // erase n fields matching id | |||||
| 1396 | // without updating metadata | 1396 | // without updating metadata | |||||
| 1397 | void | 1397 | void | |||||
| HITCBC | 1398 | 4 | fields_base:: | 1398 | 4 | fields_base:: | ||
| 1399 | raw_erase_n( | 1399 | raw_erase_n( | |||||
| 1400 | field id, | 1400 | field id, | |||||
| 1401 | std::size_t n) noexcept | 1401 | std::size_t n) noexcept | |||||
| 1402 | { | 1402 | { | |||||
| 1403 | // iterate in reverse | 1403 | // iterate in reverse | |||||
| HITCBC | 1404 | 4 | auto e = &h_.tab()[h_.count]; | 1404 | 4 | auto e = &h_.tab()[h_.count]; | ||
| HITCBC | 1405 | 4 | auto const e0 = &h_.tab()[0]; | 1405 | 4 | auto const e0 = &h_.tab()[0]; | ||
| HITCBC | 1406 | 10 | while(n > 0) | 1406 | 10 | while(n > 0) | ||
| 1407 | { | 1407 | { | |||||
| HITCBC | 1408 | 6 | BOOST_ASSERT(e != e0); | 1408 | 6 | BOOST_ASSERT(e != e0); | ||
| HITCBC | 1409 | 6 | ++e; // decrement | 1409 | 6 | ++e; // decrement | ||
| HITCBC | 1410 | 6 | if(e->id == id) | 1410 | 6 | if(e->id == id) | ||
| 1411 | { | 1411 | { | |||||
| HITCBC | 1412 | 5 | raw_erase(e0 - e); | 1412 | 5 | raw_erase(e0 - e); | ||
| HITCBC | 1413 | 5 | --n; | 1413 | 5 | --n; | ||
| 1414 | } | 1414 | } | |||||
| 1415 | } | 1415 | } | |||||
| HITCBC | 1416 | 4 | } | 1416 | 4 | } | ||
| 1417 | 1417 | |||||||
| 1418 | // erase all fields with id | 1418 | // erase all fields with id | |||||
| 1419 | // and update metadata | 1419 | // and update metadata | |||||
| 1420 | std::size_t | 1420 | std::size_t | |||||
| HITCBC | 1421 | 72 | fields_base:: | 1421 | 72 | fields_base:: | ||
| 1422 | erase_all( | 1422 | erase_all( | |||||
| 1423 | std::size_t i0, | 1423 | std::size_t i0, | |||||
| 1424 | field id) noexcept | 1424 | field id) noexcept | |||||
| 1425 | { | 1425 | { | |||||
| HITCBC | 1426 | 72 | BOOST_ASSERT( | 1426 | 72 | BOOST_ASSERT( | ||
| 1427 | id != detail::header::unknown_field); | 1427 | id != detail::header::unknown_field); | |||||
| HITCBC | 1428 | 72 | std::size_t n = 1; | 1428 | 72 | std::size_t n = 1; | ||
| HITCBC | 1429 | 72 | std::size_t i = h_.count - 1; | 1429 | 72 | std::size_t i = h_.count - 1; | ||
| HITCBC | 1430 | 72 | auto const ft = h_.tab(); | 1430 | 72 | auto const ft = h_.tab(); | ||
| HITCBC | 1431 | 149 | while(i > i0) | 1431 | 149 | while(i > i0) | ||
| 1432 | { | 1432 | { | |||||
| HITCBC | 1433 | 77 | if(ft[i].id == id) | 1433 | 77 | if(ft[i].id == id) | ||
| 1434 | { | 1434 | { | |||||
| HITCBC | 1435 | 44 | raw_erase(i); | 1435 | 44 | raw_erase(i); | ||
| HITCBC | 1436 | 44 | ++n; | 1436 | 44 | ++n; | ||
| 1437 | } | 1437 | } | |||||
| 1438 | // go backwards to | 1438 | // go backwards to | |||||
| 1439 | // reduce memmoves | 1439 | // reduce memmoves | |||||
| HITCBC | 1440 | 77 | --i; | 1440 | 77 | --i; | ||
| 1441 | } | 1441 | } | |||||
| HITCBC | 1442 | 72 | raw_erase(i0); | 1442 | 72 | raw_erase(i0); | ||
| HITCBC | 1443 | 72 | h_.on_erase_all(id); | 1443 | 72 | h_.on_erase_all(id); | ||
| HITCBC | 1444 | 72 | return n; | 1444 | 72 | return n; | ||
| 1445 | } | 1445 | } | |||||
| 1446 | 1446 | |||||||
| 1447 | // erase all fields with name | 1447 | // erase all fields with name | |||||
| 1448 | // when id == detail::header::unknown_field | 1448 | // when id == detail::header::unknown_field | |||||
| 1449 | std::size_t | 1449 | std::size_t | |||||
| HITCBC | 1450 | 9 | fields_base:: | 1450 | 9 | fields_base:: | ||
| 1451 | erase_all( | 1451 | erase_all( | |||||
| 1452 | std::size_t i0, | 1452 | std::size_t i0, | |||||
| 1453 | core::string_view name) noexcept | 1453 | core::string_view name) noexcept | |||||
| 1454 | { | 1454 | { | |||||
| HITCBC | 1455 | 9 | std::size_t n = 1; | 1455 | 9 | std::size_t n = 1; | ||
| HITCBC | 1456 | 9 | std::size_t i = h_.count - 1; | 1456 | 9 | std::size_t i = h_.count - 1; | ||
| HITCBC | 1457 | 9 | auto const ft = h_.tab(); | 1457 | 9 | auto const ft = h_.tab(); | ||
| HITCBC | 1458 | 9 | auto const* p = h_.cbuf + h_.prefix; | 1458 | 9 | auto const* p = h_.cbuf + h_.prefix; | ||
| HITCBC | 1459 | 36 | while(i > i0) | 1459 | 36 | while(i > i0) | ||
| 1460 | { | 1460 | { | |||||
| 1461 | core::string_view s( | 1461 | core::string_view s( | |||||
| HITCBC | 1462 | 27 | p + ft[i].np, ft[i].nn); | 1462 | 27 | p + ft[i].np, ft[i].nn); | ||
| HITCBC | 1463 | 27 | if(s == name) | 1463 | 27 | if(s == name) | ||
| 1464 | { | 1464 | { | |||||
| HITCBC | 1465 | 9 | raw_erase(i); | 1465 | 9 | raw_erase(i); | ||
| HITCBC | 1466 | 9 | ++n; | 1466 | 9 | ++n; | ||
| 1467 | } | 1467 | } | |||||
| 1468 | // go backwards to | 1468 | // go backwards to | |||||
| 1469 | // reduce memmoves | 1469 | // reduce memmoves | |||||
| HITCBC | 1470 | 27 | --i; | 1470 | 27 | --i; | ||
| 1471 | } | 1471 | } | |||||
| HITCBC | 1472 | 9 | raw_erase(i0); | 1472 | 9 | raw_erase(i0); | ||
| HITCBC | 1473 | 9 | return n; | 1473 | 9 | return n; | ||
| 1474 | } | 1474 | } | |||||
| 1475 | 1475 | |||||||
| 1476 | // return i-th field absolute offset | 1476 | // return i-th field absolute offset | |||||
| 1477 | std::size_t | 1477 | std::size_t | |||||
| HITCBC | 1478 | 779 | fields_base:: | 1478 | 779 | fields_base:: | ||
| 1479 | offset( | 1479 | offset( | |||||
| 1480 | std::size_t i) const noexcept | 1480 | std::size_t i) const noexcept | |||||
| 1481 | { | 1481 | { | |||||
| HITCBC | 1482 | 779 | if(i == 0) | 1482 | 779 | if(i == 0) | ||
| HITCBC | 1483 | 347 | return h_.prefix; | 1483 | 347 | return h_.prefix; | ||
| HITCBC | 1484 | 432 | if(i < h_.count) | 1484 | 432 | if(i < h_.count) | ||
| HITCBC | 1485 | 219 | return h_.prefix + h_.tab()[i].np; | 1485 | 219 | return h_.prefix + h_.tab()[i].np; | ||
| 1486 | // make final CRLF the last "field" | 1486 | // make final CRLF the last "field" | |||||
| HITCBC | 1487 | 213 | return h_.size - 2; | 1487 | 213 | return h_.size - 2; | ||
| 1488 | } | 1488 | } | |||||
| 1489 | 1489 | |||||||
| 1490 | // return i-th field absolute length | 1490 | // return i-th field absolute length | |||||
| 1491 | std::size_t | 1491 | std::size_t | |||||
| HITCBC | 1492 | 39 | fields_base:: | 1492 | 39 | fields_base:: | ||
| 1493 | length( | 1493 | length( | |||||
| 1494 | std::size_t i) const noexcept | 1494 | std::size_t i) const noexcept | |||||
| 1495 | { | 1495 | { | |||||
| 1496 | return | 1496 | return | |||||
| HITCBC | 1497 | 39 | offset(i + 1) - | 1497 | 39 | offset(i + 1) - | ||
| HITCBC | 1498 | 39 | offset(i); | 1498 | 39 | offset(i); | ||
| 1499 | } | 1499 | } | |||||
| 1500 | 1500 | |||||||
| 1501 | } // http | 1501 | } // http | |||||
| 1502 | } // boost | 1502 | } // boost | |||||