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
38  
align_down(
38  
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  
{
43  
    auto addr = reinterpret_cast<std::uintptr_t>(ptr);
43  
    auto addr = reinterpret_cast<std::uintptr_t>(ptr);
44  
    auto aligned_end = (addr + size) & ~(alignment - 1);
44  
    auto aligned_end = (addr + size) & ~(alignment - 1);
45  

45  

46  
    if(aligned_end > addr)
46  
    if(aligned_end > addr)
47  
        return aligned_end - addr;
47  
        return aligned_end - addr;
48  

48  

49  
    return 0;
49  
    return 0;
50  
}
50  
}
51  

51  

52  
void
52  
void
53  
verify_field_name(
53  
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  
{
57  
    auto rv = grammar::parse(
57  
    auto rv = grammar::parse(
58  
        name, detail::field_name_rule);
58  
        name, detail::field_name_rule);
59  
    if(rv.has_error())
59  
    if(rv.has_error())
60  
    {
60  
    {
61  
        ec = BOOST_HTTP_ERR(
61  
        ec = BOOST_HTTP_ERR(
62  
            error::bad_field_name);
62  
            error::bad_field_name);
63  
    }
63  
    }
64  
}
64  
}
65  

65  

66  
system::result<detail::field_value_rule_t::value_type>
66  
system::result<detail::field_value_rule_t::value_type>
67  
verify_field_value(
67  
verify_field_value(
68  
    core::string_view value)
68  
    core::string_view value)
69  
{
69  
{
70  
    auto it = value.begin();
70  
    auto it = value.begin();
71  
    auto end = value.end();
71  
    auto end = value.end();
72  
    auto rv =
72  
    auto rv =
73  
        grammar::parse(it, end, detail::field_value_rule);
73  
        grammar::parse(it, end, detail::field_value_rule);
74  
    if( rv.has_error() )
74  
    if( rv.has_error() )
75  
    {
75  
    {
76  
        if( rv.error() == condition::need_more_input )
76  
        if( rv.error() == condition::need_more_input )
77  
            return error::bad_field_value;
77  
            return error::bad_field_value;
78  
        return rv.error();
78  
        return rv.error();
79  
    }
79  
    }
80  

80  

81  
    if( rv->has_crlf )
81  
    if( rv->has_crlf )
82  
        return error::bad_field_smuggle;
82  
        return error::bad_field_smuggle;
83  

83  

84  
    if( it != end )
84  
    if( it != end )
85  
        return error::bad_field_value;
85  
        return error::bad_field_value;
86  

86  

87  
    return rv;
87  
    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
104  
    op_t(
104  
    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
108  
        : self_(self)
108  
        : self_(self)
109  
        , s0_(s0)
109  
        , s0_(s0)
110  
        , s1_(s1)
110  
        , s1_(s1)
111  
    {
111  
    {
112  
    }
112  
    }
113  

113  

114  
    ~op_t()
114  
    ~op_t()
115  
    {
115  
    {
116  
        if(buf_)
116  
        if(buf_)
117  
            delete[] buf_;
117  
            delete[] buf_;
118  
    }
118  
    }
119  

119  

120  
    char const*
120  
    char const*
121  
    buf() const noexcept
121  
    buf() const noexcept
122  
    {
122  
    {
123  
        return buf_;
123  
        return buf_;
124  
    }
124  
    }
125  

125  

126  
    char const*
126  
    char const*
127  
    cbuf() const noexcept
127  
    cbuf() const noexcept
128  
    {
128  
    {
129  
        return cbuf_;
129  
        return cbuf_;
130  
    }
130  
    }
131  

131  

132  
    char*
132  
    char*
133  
    end() const noexcept
133  
    end() const noexcept
134  
    {
134  
    {
135  
        return buf_ + cap_;
135  
        return buf_ + cap_;
136  
    }
136  
    }
137  

137  

138  
    table
138  
    table
139  
    tab() const noexcept
139  
    tab() const noexcept
140  
    {
140  
    {
141  
        return table(end());
141  
        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
160  
fields_base::
160  
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
166  
    if(n > self_.max_cap_)
166  
    if(n > self_.max_cap_)
167  
    {
167  
    {
168  
        // max capacity exceeded
168  
        // max capacity exceeded
169  
        detail::throw_length_error();
169  
        detail::throw_length_error();
170  
    }
170  
    }
171  
    if(n <= self_.h_.cap)
171  
    if(n <= self_.h_.cap)
172  
        return false;
172  
        return false;
173  
    auto buf = new char[n];
173  
    auto buf = new char[n];
174  
    buf_ = self_.h_.buf;
174  
    buf_ = self_.h_.buf;
175  
    cbuf_ = self_.h_.cbuf;
175  
    cbuf_ = self_.h_.cbuf;
176  
    cap_ = self_.h_.cap;
176  
    cap_ = self_.h_.cap;
177  
    self_.h_.buf = buf;
177  
    self_.h_.buf = buf;
178  
    self_.h_.cbuf = buf;
178  
    self_.h_.cbuf = buf;
179  
    self_.h_.cap = n;
179  
    self_.h_.cap = n;
180  
    return true;
180  
    return true;
181  
}
181  
}
182  

182  

183  
bool
183  
bool
184  
fields_base::
184  
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  
{
190  
    if(extra_field > detail::header::max_offset - self_.h_.count)
190  
    if(extra_field > detail::header::max_offset - self_.h_.count)
191  
        detail::throw_length_error();
191  
        detail::throw_length_error();
192  

192  

193  
    if(extra_char > detail::header::max_offset - self_.h_.size)
193  
    if(extra_char > detail::header::max_offset - self_.h_.size)
194  
        detail::throw_length_error();
194  
        detail::throw_length_error();
195  

195  

196  
    return reserve(
196  
    return reserve(
197  
        detail::header::bytes_needed(
197  
        detail::header::bytes_needed(
198  
            self_.h_.size + extra_char,
198  
            self_.h_.size + extra_char,
199  
            self_.h_.count + extra_field));
199  
            self_.h_.count + extra_field));
200  
}
200  
}
201  

201  

202  
void
202  
void
203  
fields_base::
203  
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  
{
210  
    detail::move_chars(
210  
    detail::move_chars(
211  
        dest, src, n, s0_, s1_);
211  
        dest, src, n, s0_, s1_);
212  
}
212  
}
213  

213  

214  
//------------------------------------------------
214  
//------------------------------------------------
215  

215  

216  
fields_base::
216  
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,
222  
    core::string_view* s1)
222  
    core::string_view* s1)
223  
    : self_(self)
223  
    : self_(self)
224  
    , new_prefix_(static_cast<
224  
    , new_prefix_(static_cast<
225  
        offset_type>(new_prefix))
225  
        offset_type>(new_prefix))
226  
{
226  
{
227  
    if(self.h_.size - self.h_.prefix + new_prefix
227  
    if(self.h_.size - self.h_.prefix + new_prefix
228  
        > detail::header::max_offset)
228  
        > detail::header::max_offset)
229  
        detail::throw_length_error();
229  
        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.
233  
    if(new_prefix_ < self_.h_.prefix
233  
    if(new_prefix_ < self_.h_.prefix
234  
        && !self.h_.is_default())
234  
        && !self.h_.is_default())
235  
        return;
235  
        return;
236  

236  

237  
    auto new_size = static_cast<offset_type>(
237  
    auto new_size = static_cast<offset_type>(
238  
        self.h_.size - self.h_.prefix + new_prefix_);
238  
        self.h_.size - self.h_.prefix + new_prefix_);
239  

239  

240  
    auto bytes_needed =
240  
    auto bytes_needed =
241  
        detail::header::bytes_needed(
241  
        detail::header::bytes_needed(
242  
            new_size,
242  
            new_size,
243  
            self.h_.count);
243  
            self.h_.count);
244  

244  

245  
    if(bytes_needed > self.h_.cap)
245  
    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.
249  
        if(self.max_cap_ < bytes_needed)
249  
        if(self.max_cap_ < bytes_needed)
250  
            detail::throw_length_error();
250  
            detail::throw_length_error();
251  
        // TODO: consider using a growth factor
251  
        // TODO: consider using a growth factor
252  
        char* p = new char[bytes_needed];
252  
        char* p = new char[bytes_needed];
253  
        std::memcpy(
253  
        std::memcpy(
254  
            p + new_prefix_,
254  
            p + new_prefix_,
255  
            self.h_.cbuf + self.h_.prefix,
255  
            self.h_.cbuf + self.h_.prefix,
256  
            self.h_.size - self.h_.prefix);
256  
            self.h_.size - self.h_.prefix);
257  
        self.h_.copy_table(p + bytes_needed);
257  
        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.
262  
        buf_        = self.h_.buf;
262  
        buf_        = self.h_.buf;
263  
        self.h_.buf = p;
263  
        self.h_.buf = p;
264  
        self.h_.cap = bytes_needed;
264  
        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.
270  
        detail::move_chars(
270  
        detail::move_chars(
271  
            self.h_.buf + new_prefix_,
271  
            self.h_.buf + new_prefix_,
272  
            self.h_.cbuf + self.h_.prefix,
272  
            self.h_.cbuf + self.h_.prefix,
273  
            self.h_.size - self.h_.prefix,
273  
            self.h_.size - self.h_.prefix,
274  
            s0,
274  
            s0,
275  
            s1);
275  
            s1);
276  
    }
276  
    }
277  

277  

278  
    self.h_.cbuf   = self.h_.buf;
278  
    self.h_.cbuf   = self.h_.buf;
279  
    self.h_.size   = new_size;
279  
    self.h_.size   = new_size;
280  
    self.h_.prefix = new_prefix_;
280  
    self.h_.prefix = new_prefix_;
281  
}
281  
}
282  

282  

283  
fields_base::
283  
fields_base::
284  
prefix_op_t::
284  
prefix_op_t::
285  
~prefix_op_t()
285  
~prefix_op_t()
286  
{
286  
{
287  
    if(new_prefix_ < self_.h_.prefix)
287  
    if(new_prefix_ < self_.h_.prefix)
288  
    {
288  
    {
289  
        std::memmove(
289  
        std::memmove(
290  
            self_.h_.buf + new_prefix_,
290  
            self_.h_.buf + new_prefix_,
291  
            self_.h_.cbuf + self_.h_.prefix,
291  
            self_.h_.cbuf + self_.h_.prefix,
292  
            self_.h_.size - self_.h_.prefix);
292  
            self_.h_.size - self_.h_.prefix);
293  

293  

294  
        self_.h_.size =
294  
        self_.h_.size =
295  
            self_.h_.size - self_.h_.prefix + new_prefix_;
295  
            self_.h_.size - self_.h_.prefix + new_prefix_;
296  
        self_.h_.prefix = new_prefix_;
296  
        self_.h_.prefix = new_prefix_;
297  
    }
297  
    }
298  
    else if(buf_)
298  
    else if(buf_)
299  
    {
299  
    {
300  
        delete[] buf_;
300  
        delete[] buf_;
301  
    }
301  
    }
302  
}
302  
}
303  

303  

304  
//------------------------------------------------
304  
//------------------------------------------------
305  

305  

306  
fields_base::
306  
fields_base::
307  
fields_base(
307  
fields_base(
308  
    detail::kind k) noexcept
308  
    detail::kind k) noexcept
309  
    : h_(k)
309  
    : h_(k)
310  
{
310  
{
311  
}
311  
}
312  

312  

313  
fields_base::
313  
fields_base::
314  
fields_base(
314  
fields_base(
315  
    detail::kind k,
315  
    detail::kind k,
316  
    void* storage,
316  
    void* storage,
317  
    std::size_t cap) noexcept
317  
    std::size_t cap) noexcept
318  
    : fields_base(
318  
    : fields_base(
319  
        *detail::header::get_default(k), storage, cap)
319  
        *detail::header::get_default(k), storage, cap)
320  
{
320  
{
321  
}
321  
}
322  

322  

323  
// copy s and parse it
323  
// copy s and parse it
324  
fields_base::
324  
fields_base::
325  
fields_base(
325  
fields_base(
326  
    detail::kind k,
326  
    detail::kind k,
327  
    core::string_view s)
327  
    core::string_view s)
328  
    : h_(detail::empty{k})
328  
    : h_(detail::empty{k})
329  
{
329  
{
330  
    auto n = detail::header::count_crlf(s);
330  
    auto n = detail::header::count_crlf(s);
331  
    if(h_.kind == detail::kind::fields)
331  
    if(h_.kind == detail::kind::fields)
332  
    {
332  
    {
333  
        if(n < 1)
333  
        if(n < 1)
334  
            detail::throw_invalid_argument();
334  
            detail::throw_invalid_argument();
335  
        n -= 1;
335  
        n -= 1;
336  
    }
336  
    }
337  
    else
337  
    else
338  
    {
338  
    {
339  
        if(n < 2)
339  
        if(n < 2)
340  
            detail::throw_invalid_argument();
340  
            detail::throw_invalid_argument();
341  
        n -= 2;
341  
        n -= 2;
342  
    }
342  
    }
343  
    op_t op(*this);
343  
    op_t op(*this);
344  
    op.grow(s.size(), n);
344  
    op.grow(s.size(), n);
345  
    s.copy(h_.buf, s.size());
345  
    s.copy(h_.buf, s.size());
346  
    system::error_code ec;
346  
    system::error_code ec;
347  
    // VFALCO This is using defaults?
347  
    // VFALCO This is using defaults?
348  
    header_limits lim;
348  
    header_limits lim;
349  
    h_.parse(s.size(), lim, ec);
349  
    h_.parse(s.size(), lim, ec);
350  
    if(ec)
350  
    if(ec)
351  
        detail::throw_system_error(ec);
351  
        detail::throw_system_error(ec);
352  
}
352  
}
353  

353  

354  
// construct a complete copy of h
354  
// construct a complete copy of h
355  
fields_base::
355  
fields_base::
356  
fields_base(
356  
fields_base(
357  
    detail::header const& h)
357  
    detail::header const& h)
358  
    : h_(h.kind)
358  
    : h_(h.kind)
359  
{
359  
{
360  
    if(h.is_default())
360  
    if(h.is_default())
361  
        return;
361  
        return;
362  

362  

363  
    // allocate and copy the buffer
363  
    // allocate and copy the buffer
364  
    op_t op(*this);
364  
    op_t op(*this);
365  
    op.grow(h.size, h.count);
365  
    op.grow(h.size, h.count);
366  
    h.assign_to(h_);
366  
    h.assign_to(h_);
367  
    std::memcpy(
367  
    std::memcpy(
368  
        h_.buf, h.cbuf, h.size);
368  
        h_.buf, h.cbuf, h.size);
369  
    h.copy_table(h_.buf + h_.cap);
369  
    h.copy_table(h_.buf + h_.cap);
370  
}
370  
}
371  

371  

372  
// construct a complete copy of h
372  
// construct a complete copy of h
373  
fields_base::
373  
fields_base::
374  
fields_base(
374  
fields_base(
375  
    detail::header const& h,
375  
    detail::header const& h,
376  
    void* storage,
376  
    void* storage,
377  
    std::size_t cap)
377  
    std::size_t cap)
378  
    : h_(h.kind)
378  
    : h_(h.kind)
379  
    , external_storage_(true)
379  
    , external_storage_(true)
380  
{
380  
{
381  
    h_.cbuf = static_cast<char*>(storage);
381  
    h_.cbuf = static_cast<char*>(storage);
382  
    h_.buf = static_cast<char*>(storage);
382  
    h_.buf = static_cast<char*>(storage);
383  
    h_.cap = align_down(
383  
    h_.cap = align_down(
384  
        storage,
384  
        storage,
385  
        cap,
385  
        cap,
386  
        alignof(detail::header::entry));
386  
        alignof(detail::header::entry));
387  
    max_cap_ = h_.cap;
387  
    max_cap_ = h_.cap;
388  

388  

389  
    if(detail::header::bytes_needed(
389  
    if(detail::header::bytes_needed(
390  
        h.size, h.count)
390  
        h.size, h.count)
391  
            >= h_.cap)
391  
            >= h_.cap)
392  
        detail::throw_length_error();
392  
        detail::throw_length_error();
393  

393  

394  
    h.assign_to(h_);
394  
    h.assign_to(h_);
395  
    std::memcpy(
395  
    std::memcpy(
396  
        h_.buf, h.cbuf, h.size);
396  
        h_.buf, h.cbuf, h.size);
397  
    h.copy_table(h_.buf + h_.cap);
397  
    h.copy_table(h_.buf + h_.cap);
398  
}
398  
}
399  

399  

400  
//------------------------------------------------
400  
//------------------------------------------------
401  

401  

402  
fields_base::
402  
fields_base::
403  
fields_base(fields_base const& other)
403  
fields_base(fields_base const& other)
404  
    : fields_base(other.h_)
404  
    : fields_base(other.h_)
405  
{
405  
{
406  
}
406  
}
407  

407  

408  
fields_base::
408  
fields_base::
409  
~fields_base()
409  
~fields_base()
410  
{
410  
{
411  
    if(h_.buf && !external_storage_)
411  
    if(h_.buf && !external_storage_)
412  
        delete[] h_.buf;
412  
        delete[] h_.buf;
413  
}
413  
}
414  

414  

415  
//------------------------------------------------
415  
//------------------------------------------------
416  
//
416  
//
417  
// Capacity
417  
// Capacity
418  
//
418  
//
419  
//------------------------------------------------
419  
//------------------------------------------------
420  

420  

421  
void
421  
void
422  
fields_base::
422  
fields_base::
423  
clear() noexcept
423  
clear() noexcept
424  
{
424  
{
425  
    if(! h_.buf)
425  
    if(! h_.buf)
426  
        return;
426  
        return;
427  
    using H =
427  
    using H =
428  
        detail::header;
428  
        detail::header;
429  
    auto const& h =
429  
    auto const& h =
430  
        *H::get_default(
430  
        *H::get_default(
431  
            h_.kind);
431  
            h_.kind);
432  
    h.assign_to(h_);
432  
    h.assign_to(h_);
433  
    std::memcpy(
433  
    std::memcpy(
434  
        h_.buf,
434  
        h_.buf,
435  
        h.cbuf,
435  
        h.cbuf,
436  
        h_.size);
436  
        h_.size);
437  
}
437  
}
438  

438  

439  
void
439  
void
440  
fields_base::
440  
fields_base::
441  
reserve_bytes(
441  
reserve_bytes(
442  
    std::size_t n)
442  
    std::size_t n)
443  
{
443  
{
444  
    op_t op(*this);
444  
    op_t op(*this);
445  
    if(! op.reserve(n))
445  
    if(! op.reserve(n))
446  
        return;
446  
        return;
447  
    std::memcpy(
447  
    std::memcpy(
448  
        h_.buf, op.cbuf(), h_.size);
448  
        h_.buf, op.cbuf(), h_.size);
449  
    auto const nt =
449  
    auto const nt =
450  
        sizeof(entry) * h_.count;
450  
        sizeof(entry) * h_.count;
451  
    if(nt > 0)
451  
    if(nt > 0)
452  
        std::memcpy(
452  
        std::memcpy(
453  
            h_.buf + h_.cap - nt,
453  
            h_.buf + h_.cap - nt,
454  
            op.end() - nt,
454  
            op.end() - nt,
455  
            nt);
455  
            nt);
456  
}
456  
}
457  

457  

458  
void
458  
void
459  
fields_base::
459  
fields_base::
460  
shrink_to_fit()
460  
shrink_to_fit()
461  
{
461  
{
462  
    if(detail::header::bytes_needed(
462  
    if(detail::header::bytes_needed(
463  
        h_.size, h_.count) >=
463  
        h_.size, h_.count) >=
464  
            h_.cap)
464  
            h_.cap)
465  
        return;
465  
        return;
466  

466  

467  
    if(external_storage_)
467  
    if(external_storage_)
468  
        return;
468  
        return;
469  

469  

470  
    fields_base tmp(h_);
470  
    fields_base tmp(h_);
471  
    tmp.h_.swap(h_);
471  
    tmp.h_.swap(h_);
472  
}
472  
}
473  

473  

474  

474  

475  
void
475  
void
476  
fields_base::
476  
fields_base::
477  
set_max_capacity_in_bytes(std::size_t n)
477  
set_max_capacity_in_bytes(std::size_t n)
478  
{
478  
{
479  
    if(n < h_.cap)
479  
    if(n < h_.cap)
480  
        detail::throw_invalid_argument();
480  
        detail::throw_invalid_argument();
481  
    max_cap_ = n;
481  
    max_cap_ = n;
482  
}
482  
}
483  

483  

484  
//--------------------------------------------
484  
//--------------------------------------------
485  
//
485  
//
486  
// Observers
486  
// Observers
487  
//
487  
//
488  
//--------------------------------------------
488  
//--------------------------------------------
489  

489  

490  

490  

491  
fields_base::
491  
fields_base::
492  
value_type::
492  
value_type::
493  
value_type(
493  
value_type(
494  
    reference const& other)
494  
    reference const& other)
495  
    : id(other.id)
495  
    : id(other.id)
496  
    , name(other.name)
496  
    , name(other.name)
497  
    , value(other.value)
497  
    , value(other.value)
498  
{
498  
{
499  
}
499  
}
500  

500  

501  
//------------------------------------------------
501  
//------------------------------------------------
502  

502  

503  
auto
503  
auto
504  
fields_base::
504  
fields_base::
505  
iterator::
505  
iterator::
506  
operator*() const noexcept ->
506  
operator*() const noexcept ->
507  
    reference
507  
    reference
508  
{
508  
{
509  
    BOOST_ASSERT(i_ < ph_->count);
509  
    BOOST_ASSERT(i_ < ph_->count);
510  
    auto tab =
510  
    auto tab =
511  
        ph_->tab();
511  
        ph_->tab();
512  
    auto const& e =
512  
    auto const& e =
513  
        tab[i_];
513  
        tab[i_];
514  
    auto const* p =
514  
    auto const* p =
515  
        ph_->cbuf + ph_->prefix;
515  
        ph_->cbuf + ph_->prefix;
516  
    return {
516  
    return {
517  
        (e.id == detail::header::unknown_field)
517  
        (e.id == detail::header::unknown_field)
518  
            ? optional<field>{} : e.id,
518  
            ? optional<field>{} : e.id,
519  
        core::string_view(
519  
        core::string_view(
520  
            p + e.np, e.nn),
520  
            p + e.np, e.nn),
521  
        core::string_view(
521  
        core::string_view(
522  
            p + e.vp, e.vn) };
522  
            p + e.vp, e.vn) };
523  
}
523  
}
524  

524  

525  
//------------------------------------------------
525  
//------------------------------------------------
526  

526  

527  
auto
527  
auto
528  
fields_base::
528  
fields_base::
529  
reverse_iterator::
529  
reverse_iterator::
530  
operator*() const noexcept ->
530  
operator*() const noexcept ->
531  
    reference
531  
    reference
532  
{
532  
{
533  
    BOOST_ASSERT(i_ > 0);
533  
    BOOST_ASSERT(i_ > 0);
534  
    auto tab =
534  
    auto tab =
535  
      ph_->tab();
535  
      ph_->tab();
536  
    auto const& e =
536  
    auto const& e =
537  
        tab[i_-1];
537  
        tab[i_-1];
538  
    auto const* p =
538  
    auto const* p =
539  
        ph_->cbuf + ph_->prefix;
539  
        ph_->cbuf + ph_->prefix;
540  
    return {
540  
    return {
541  
        (e.id == detail::header::unknown_field)
541  
        (e.id == detail::header::unknown_field)
542  
            ? optional<field>{} : e.id,
542  
            ? optional<field>{} : e.id,
543  
        core::string_view(
543  
        core::string_view(
544  
            p + e.np, e.nn),
544  
            p + e.np, e.nn),
545  
        core::string_view(
545  
        core::string_view(
546  
            p + e.vp, e.vn) };
546  
            p + e.vp, e.vn) };
547  
}
547  
}
548  

548  

549  
//------------------------------------------------
549  
//------------------------------------------------
550  

550  

551  
fields_base::
551  
fields_base::
552  
subrange::
552  
subrange::
553  
iterator::
553  
iterator::
554  
iterator(
554  
iterator(
555  
    detail::header const* ph,
555  
    detail::header const* ph,
556  
    std::size_t i) noexcept
556  
    std::size_t i) noexcept
557  
    : ph_(ph)
557  
    : ph_(ph)
558  
    , i_(i)
558  
    , i_(i)
559  
{
559  
{
560  
    BOOST_ASSERT(i <= ph_->count);
560  
    BOOST_ASSERT(i <= ph_->count);
561  
}
561  
}
562  

562  

563  
fields_base::
563  
fields_base::
564  
subrange::
564  
subrange::
565  
iterator::
565  
iterator::
566  
iterator(
566  
iterator(
567  
    detail::header const* ph) noexcept
567  
    detail::header const* ph) noexcept
568  
    : ph_(ph)
568  
    : ph_(ph)
569  
    , i_(ph->count)
569  
    , i_(ph->count)
570  
{
570  
{
571  
}
571  
}
572  

572  

573  
auto
573  
auto
574  
fields_base::
574  
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 =
581  
        ph_->tab();
581  
        ph_->tab();
582  
    auto const& e =
582  
    auto const& e =
583  
        tab[i_];
583  
        tab[i_];
584  
    auto const p =
584  
    auto const p =
585  
        ph_->cbuf + ph_->prefix;
585  
        ph_->cbuf + ph_->prefix;
586  
    return core::string_view(
586  
    return core::string_view(
587  
        p + e.vp, e.vn);
587  
        p + e.vp, e.vn);
588  
}
588  
}
589  

589  

590  
auto
590  
auto
591  
fields_base::
591  
fields_base::
592  
subrange::
592  
subrange::
593  
iterator::
593  
iterator::
594  
operator++() noexcept ->
594  
operator++() noexcept ->
595  
    iterator&
595  
    iterator&
596  
{
596  
{
597  
    BOOST_ASSERT(i_ < ph_->count);
597  
    BOOST_ASSERT(i_ < ph_->count);
598  
    auto const* e = &ph_->tab()[i_];
598  
    auto const* e = &ph_->tab()[i_];
599  
    auto const id = e->id;
599  
    auto const id = e->id;
600  
    if(id != detail::header::unknown_field)
600  
    if(id != detail::header::unknown_field)
601  
    {
601  
    {
602  
        ++i_;
602  
        ++i_;
603  
        --e;
603  
        --e;
604  
        while(i_ != ph_->count)
604  
        while(i_ != ph_->count)
605  
        {
605  
        {
606  
            if(e->id == id)
606  
            if(e->id == id)
607  
                break;
607  
                break;
608  
            ++i_;
608  
            ++i_;
609  
            --e;
609  
            --e;
610  
        }
610  
        }
611  
        return *this;
611  
        return *this;
612  
    }
612  
    }
613  
    auto const p =
613  
    auto const p =
614  
        ph_->cbuf + ph_->prefix;
614  
        ph_->cbuf + ph_->prefix;
615  
    auto name = core::string_view(
615  
    auto name = core::string_view(
616  
        p + e->np, e->nn);
616  
        p + e->np, e->nn);
617  
    ++i_;
617  
    ++i_;
618  
    --e;
618  
    --e;
619  
    while(i_ != ph_->count)
619  
    while(i_ != ph_->count)
620  
    {
620  
    {
621  
        if(grammar::ci_is_equal(
621  
        if(grammar::ci_is_equal(
622  
            name, core::string_view(
622  
            name, core::string_view(
623  
                p + e->np, e->nn)))
623  
                p + e->np, e->nn)))
624  
            break;
624  
            break;
625  
        ++i_;
625  
        ++i_;
626  
        --e;
626  
        --e;
627  
    }
627  
    }
628  
    return *this;
628  
    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
638  
fields_base::
638  
fields_base::
639  
at(
639  
at(
640  
    field id) const
640  
    field id) const
641  
{
641  
{
642  
    auto const it = find(id);
642  
    auto const it = find(id);
643  
    if(it == end())
643  
    if(it == end())
644  
        BOOST_THROW_EXCEPTION(
644  
        BOOST_THROW_EXCEPTION(
645  
            std::out_of_range{ "field not found" });
645  
            std::out_of_range{ "field not found" });
646  
    return it->value;
646  
    return it->value;
647  
}
647  
}
648  

648  

649  
core::string_view
649  
core::string_view
650  
fields_base::
650  
fields_base::
651  
at(
651  
at(
652  
    core::string_view name) const
652  
    core::string_view name) const
653  
{
653  
{
654  
    auto const it = find(name);
654  
    auto const it = find(name);
655  
    if(it == end())
655  
    if(it == end())
656  
        BOOST_THROW_EXCEPTION(
656  
        BOOST_THROW_EXCEPTION(
657  
            std::out_of_range{ "field not found" });
657  
            std::out_of_range{ "field not found" });
658  
    return it->value;
658  
    return it->value;
659  
}
659  
}
660  

660  

661  
bool
661  
bool
662  
fields_base::
662  
fields_base::
663  
exists(
663  
exists(
664  
    field id) const noexcept
664  
    field id) const noexcept
665  
{
665  
{
666  
    return find(id) != end();
666  
    return find(id) != end();
667  
}
667  
}
668  

668  

669  
bool
669  
bool
670  
fields_base::
670  
fields_base::
671  
exists(
671  
exists(
672  
    core::string_view name) const noexcept
672  
    core::string_view name) const noexcept
673  
{
673  
{
674  
    return find(name) != end();
674  
    return find(name) != end();
675  
}
675  
}
676  

676  

677  
std::size_t
677  
std::size_t
678  
fields_base::
678  
fields_base::
679  
count(field id) const noexcept
679  
count(field id) const noexcept
680  
{
680  
{
681  
    std::size_t n = 0;
681  
    std::size_t n = 0;
682  
    for(auto v : *this)
682  
    for(auto v : *this)
683  
        if(v.id == id)
683  
        if(v.id == id)
684  
            ++n;
684  
            ++n;
685  
    return n;
685  
    return n;
686  
}
686  
}
687  

687  

688  
std::size_t
688  
std::size_t
689  
fields_base::
689  
fields_base::
690  
count(
690  
count(
691  
    core::string_view name) const noexcept
691  
    core::string_view name) const noexcept
692  
{
692  
{
693  
    std::size_t n = 0;
693  
    std::size_t n = 0;
694  
    for(auto v : *this)
694  
    for(auto v : *this)
695  
        if(grammar::ci_is_equal(
695  
        if(grammar::ci_is_equal(
696  
                v.name, name))
696  
                v.name, name))
697  
            ++n;
697  
            ++n;
698  
    return n;
698  
    return n;
699  
}
699  
}
700  

700  

701  
auto
701  
auto
702  
fields_base::
702  
fields_base::
703  
find(field id) const noexcept ->
703  
find(field id) const noexcept ->
704  
    iterator
704  
    iterator
705  
{
705  
{
706  
    auto it = begin();
706  
    auto it = begin();
707  
    auto const last = end();
707  
    auto const last = end();
708  
    while(it != last)
708  
    while(it != last)
709  
    {
709  
    {
710  
        if(it->id == id)
710  
        if(it->id == id)
711  
            break;
711  
            break;
712  
        ++it;
712  
        ++it;
713  
    }
713  
    }
714  
    return it;
714  
    return it;
715  
}
715  
}
716  

716  

717  
auto
717  
auto
718  
fields_base::
718  
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  
{
723  
    auto it = begin();
723  
    auto it = begin();
724  
    auto const last = end();
724  
    auto const last = end();
725  
    while(it != last)
725  
    while(it != last)
726  
    {
726  
    {
727  
        if(grammar::ci_is_equal(
727  
        if(grammar::ci_is_equal(
728  
                it->name, name))
728  
                it->name, name))
729  
            break;
729  
            break;
730  
        ++it;
730  
        ++it;
731  
    }
731  
    }
732  
    return it;
732  
    return it;
733  
}
733  
}
734  

734  

735  
auto
735  
auto
736  
fields_base::
736  
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  
{
742  
    auto const last = end();
742  
    auto const last = end();
743  
    while(from != last)
743  
    while(from != last)
744  
    {
744  
    {
745  
        if(from->id == id)
745  
        if(from->id == id)
746  
            break;
746  
            break;
747  
        ++from;
747  
        ++from;
748  
    }
748  
    }
749  
    return from;
749  
    return from;
750  
}
750  
}
751  

751  

752  
auto
752  
auto
753  
fields_base::
753  
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  
{
759  
    auto const last = end();
759  
    auto const last = end();
760  
    while(from != last)
760  
    while(from != last)
761  
    {
761  
    {
762  
        if(grammar::ci_is_equal(
762  
        if(grammar::ci_is_equal(
763  
                name, from->name))
763  
                name, from->name))
764  
            break;
764  
            break;
765  
        ++from;
765  
        ++from;
766  
    }
766  
    }
767  
    return from;
767  
    return from;
768  
}
768  
}
769  

769  

770  
auto
770  
auto
771  
fields_base::
771  
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  
{
777  
    auto const it0 = begin();
777  
    auto const it0 = begin();
778  
    for(;;)
778  
    for(;;)
779  
    {
779  
    {
780  
        if(it == it0)
780  
        if(it == it0)
781  
            return end();
781  
            return end();
782  
        --it;
782  
        --it;
783  
        if(it->id == id)
783  
        if(it->id == id)
784  
            return it;
784  
            return it;
785  
    }
785  
    }
786  
}
786  
}
787  

787  

788  
auto
788  
auto
789  
fields_base::
789  
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  
{
795  
    auto const it0 = begin();
795  
    auto const it0 = begin();
796  
    for(;;)
796  
    for(;;)
797  
    {
797  
    {
798  
        if(it == it0)
798  
        if(it == it0)
799  
            return end();
799  
            return end();
800  
        --it;
800  
        --it;
801  
        if(grammar::ci_is_equal(
801  
        if(grammar::ci_is_equal(
802  
                it->name, name))
802  
                it->name, name))
803  
            return it;
803  
            return it;
804  
    }
804  
    }
805  
}
805  
}
806  

806  

807  
core::string_view
807  
core::string_view
808  
fields_base::
808  
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  
{
813  
    auto it = find(id);
813  
    auto it = find(id);
814  
    if(it != end())
814  
    if(it != end())
815  
        return it->value;
815  
        return it->value;
816  
    return s;
816  
    return s;
817  
}
817  
}
818  

818  

819  
core::string_view
819  
core::string_view
820  
fields_base::
820  
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  
{
825  
    auto it = find(name);
825  
    auto it = find(name);
826  
    if(it != end())
826  
    if(it != end())
827  
        return it->value;
827  
        return it->value;
828  
    return s;
828  
    return s;
829  
}
829  
}
830  

830  

831  
//------------------------------------------------
831  
//------------------------------------------------
832  

832  

833  
auto
833  
auto
834  
fields_base::
834  
fields_base::
835  
find_all(
835  
find_all(
836  
    field id) const noexcept ->
836  
    field id) const noexcept ->
837  
        subrange
837  
        subrange
838  
{
838  
{
839  
    return subrange(
839  
    return subrange(
840  
        &h_, find(id).i_);
840  
        &h_, find(id).i_);
841  
}
841  
}
842  

842  

843  
auto
843  
auto
844  
fields_base::
844  
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  
{
849  
    return subrange(
849  
    return subrange(
850  
        &h_, find(name).i_);
850  
        &h_, find(name).i_);
851  
}
851  
}
852  

852  

853  
std::ostream&
853  
std::ostream&
854  
operator<<(
854  
operator<<(
855  
    std::ostream& os,
855  
    std::ostream& os,
856  
    const fields_base& f)
856  
    const fields_base& f)
857  
{
857  
{
858  
    if(f.h_.prefix != 0)
858  
    if(f.h_.prefix != 0)
859  
        os << core::string_view(f.h_.cbuf, f.h_.prefix - 2) << '\n';
859  
        os << core::string_view(f.h_.cbuf, f.h_.prefix - 2) << '\n';
860  

860  

861  
    for(auto ref : f)
861  
    for(auto ref : f)
862  
        os << ref.name << ": " << ref.value << '\n';
862  
        os << ref.name << ": " << ref.value << '\n';
863  

863  

864  
    return os;
864  
    return os;
865  
}
865  
}
866  

866  

867  
//------------------------------------------------
867  
//------------------------------------------------
868  
//
868  
//
869  
// Modifiers
869  
// Modifiers
870  
//
870  
//
871  
//------------------------------------------------
871  
//------------------------------------------------
872  

872  

873  
auto
873  
auto
874  
fields_base::
874  
fields_base::
875  
erase(
875  
erase(
876  
    iterator it) noexcept -> iterator
876  
    iterator it) noexcept -> iterator
877  
{
877  
{
878  
    auto const id = it->id.value_or(
878  
    auto const id = it->id.value_or(
879  
        detail::header::unknown_field);
879  
        detail::header::unknown_field);
880  
    raw_erase(it.i_);
880  
    raw_erase(it.i_);
881  
    h_.on_erase(id);
881  
    h_.on_erase(id);
882  
    return it;
882  
    return it;
883  
}
883  
}
884  

884  

885  
std::size_t
885  
std::size_t
886  
fields_base::
886  
fields_base::
887  
erase(
887  
erase(
888  
    field id) noexcept
888  
    field id) noexcept
889  
{
889  
{
890  
    auto const i0 = h_.find(id);
890  
    auto const i0 = h_.find(id);
891  
    if(i0 == h_.count)
891  
    if(i0 == h_.count)
892  
        return 0;
892  
        return 0;
893  
    return erase_all(i0, id);
893  
    return erase_all(i0, id);
894  
}
894  
}
895  

895  

896  
std::size_t
896  
std::size_t
897  
fields_base::
897  
fields_base::
898  
erase(
898  
erase(
899  
    core::string_view name) noexcept
899  
    core::string_view name) noexcept
900  
{
900  
{
901  
    auto const i0 = h_.find(name);
901  
    auto const i0 = h_.find(name);
902  
    if(i0 == h_.count)
902  
    if(i0 == h_.count)
903  
        return 0;
903  
        return 0;
904  
    auto const ft = h_.tab();
904  
    auto const ft = h_.tab();
905  
    auto const id = ft[i0].id;
905  
    auto const id = ft[i0].id;
906  
    if(id == detail::header::unknown_field)
906  
    if(id == detail::header::unknown_field)
907  
        return erase_all(i0, name);
907  
        return erase_all(i0, name);
908  
    return erase_all(i0, id);
908  
    return erase_all(i0, id);
909  
}
909  
}
910  

910  

911  
//------------------------------------------------
911  
//------------------------------------------------
912  

912  

913  
void
913  
void
914  
fields_base::
914  
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  
{
920  
    auto rv = verify_field_value(value);
920  
    auto rv = verify_field_value(value);
921  
    if(rv.has_error())
921  
    if(rv.has_error())
922  
    {
922  
    {
923  
        ec = rv.error();
923  
        ec = rv.error();
924  
        return;
924  
        return;
925  
    }
925  
    }
926  

926  

927  
    value = rv->value;
927  
    value = rv->value;
928  
    bool has_obs_fold = rv->has_obs_fold;
928  
    bool has_obs_fold = rv->has_obs_fold;
929  

929  

930  
    auto const i = it.i_;
930  
    auto const i = it.i_;
931  
    auto tab = h_.tab();
931  
    auto tab = h_.tab();
932  
    auto const& e0 = tab[i];
932  
    auto const& e0 = tab[i];
933  
    auto const pos0 = offset(i);
933  
    auto const pos0 = offset(i);
934  
    auto const pos1 = offset(i + 1);
934  
    auto const pos1 = offset(i + 1);
935  
    std::ptrdiff_t dn =
935  
    std::ptrdiff_t dn =
936  
        value.size() -
936  
        value.size() -
937  
        it->value.size();
937  
        it->value.size();
938  
    if( value.empty() &&
938  
    if( value.empty() &&
939  
        ! it->value.empty())
939  
        ! it->value.empty())
940  
        --dn; // remove SP
940  
        --dn; // remove SP
941  
    else if(
941  
    else if(
942  
        it->value.empty() &&
942  
        it->value.empty() &&
943  
        ! value.empty())
943  
        ! value.empty())
944  
        ++dn; // add SP
944  
        ++dn; // add SP
945  

945  

946  
    op_t op(*this, &value);
946  
    op_t op(*this, &value);
947  
    if( dn > 0 &&
947  
    if( dn > 0 &&
948  
        op.grow(value.size() -
948  
        op.grow(value.size() -
949  
            it->value.size(), 0))
949  
            it->value.size(), 0))
950  
    {
950  
    {
951  
        // reallocated
951  
        // reallocated
952  
        auto dest = h_.buf +
952  
        auto dest = h_.buf +
953  
            pos0 + e0.nn + 1;
953  
            pos0 + e0.nn + 1;
954  
        std::memcpy(
954  
        std::memcpy(
955  
            h_.buf,
955  
            h_.buf,
956  
            op.buf(),
956  
            op.buf(),
957  
            dest - h_.buf);
957  
            dest - h_.buf);
958  
        if(! value.empty())
958  
        if(! value.empty())
959  
        {
959  
        {
960  
            *dest++ = ' ';
960  
            *dest++ = ' ';
961  
            value.copy(
961  
            value.copy(
962  
                dest,
962  
                dest,
963  
                value.size());
963  
                value.size());
964  
            if( has_obs_fold )
964  
            if( has_obs_fold )
965  
                detail::remove_obs_fold(
965  
                detail::remove_obs_fold(
966  
                    dest, dest + value.size());
966  
                    dest, dest + value.size());
967  
            dest += value.size();
967  
            dest += value.size();
968  
        }
968  
        }
969  
        *dest++ = '\r';
969  
        *dest++ = '\r';
970  
        *dest++ = '\n';
970  
        *dest++ = '\n';
971  
        std::memcpy(
971  
        std::memcpy(
972  
            h_.buf + pos1 + dn,
972  
            h_.buf + pos1 + dn,
973  
            op.buf() + pos1,
973  
            op.buf() + pos1,
974  
            h_.size - pos1);
974  
            h_.size - pos1);
975  
        std::memcpy(
975  
        std::memcpy(
976  
            h_.buf + h_.cap -
976  
            h_.buf + h_.cap -
977  
                sizeof(entry) * h_.count,
977  
                sizeof(entry) * h_.count,
978  
            &op.tab()[h_.count - 1],
978  
            &op.tab()[h_.count - 1],
979  
            sizeof(entry) * h_.count);
979  
            sizeof(entry) * h_.count);
980  
    }
980  
    }
981  
    else
981  
    else
982  
    {
982  
    {
983  
        // copy the value first
983  
        // copy the value first
984  
        auto dest = h_.buf + pos0 +
984  
        auto dest = h_.buf + pos0 +
985  
            it->name.size() + 1;
985  
            it->name.size() + 1;
986  
        if(! value.empty())
986  
        if(! value.empty())
987  
        {
987  
        {
988  
            *dest++ = ' ';
988  
            *dest++ = ' ';
989  
            value.copy(
989  
            value.copy(
990  
                dest,
990  
                dest,
991  
                value.size());
991  
                value.size());
992  
            if( has_obs_fold )
992  
            if( has_obs_fold )
993  
                detail::remove_obs_fold(
993  
                detail::remove_obs_fold(
994  
                    dest, dest + value.size());
994  
                    dest, dest + value.size());
995  
            dest += value.size();
995  
            dest += value.size();
996  
        }
996  
        }
997  
        op.move_chars(
997  
        op.move_chars(
998  
            h_.buf + pos1 + dn,
998  
            h_.buf + pos1 + dn,
999  
            h_.buf + pos1,
999  
            h_.buf + pos1,
1000  
            h_.size - pos1);
1000  
            h_.size - pos1);
1001  
        *dest++ = '\r';
1001  
        *dest++ = '\r';
1002  
        *dest++ = '\n';
1002  
        *dest++ = '\n';
1003  
    }
1003  
    }
1004  
    {
1004  
    {
1005  
        // update tab
1005  
        // update tab
1006  
        auto ft = h_.tab();
1006  
        auto ft = h_.tab();
1007  
        for(std::size_t j = h_.count - 1;
1007  
        for(std::size_t j = h_.count - 1;
1008  
                j > i; --j)
1008  
                j > i; --j)
1009  
            ft[j] = ft[j] + dn;
1009  
            ft[j] = ft[j] + dn;
1010  
        auto& e = ft[i];
1010  
        auto& e = ft[i];
1011  
        e.vp = e.np + e.nn +
1011  
        e.vp = e.np + e.nn +
1012  
            1 + ! value.empty();
1012  
            1 + ! value.empty();
1013  
        e.vn = static_cast<
1013  
        e.vn = static_cast<
1014  
            offset_type>(value.size());
1014  
            offset_type>(value.size());
1015  
        h_.size = static_cast<
1015  
        h_.size = static_cast<
1016  
            offset_type>(h_.size + dn);
1016  
            offset_type>(h_.size + dn);
1017  
    }
1017  
    }
1018  
    auto const id = it->id.value_or(
1018  
    auto const id = it->id.value_or(
1019  
        detail::header::unknown_field);
1019  
        detail::header::unknown_field);
1020  
    if(h_.is_special(id))
1020  
    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
1024  
        char saved = h_.buf[pos0];
1024  
        char saved = h_.buf[pos0];
1025  
        auto& e = h_.tab()[i];
1025  
        auto& e = h_.tab()[i];
1026  
        e.id = detail::header::unknown_field;
1026  
        e.id = detail::header::unknown_field;
1027  
        h_.buf[pos0] = '\0';
1027  
        h_.buf[pos0] = '\0';
1028  
        h_.on_erase(id);
1028  
        h_.on_erase(id);
1029  
        h_.buf[pos0] = saved; // restore
1029  
        h_.buf[pos0] = saved; // restore
1030  
        e.id = id;
1030  
        e.id = id;
1031  
        h_.on_insert(id, it->value);
1031  
        h_.on_insert(id, it->value);
1032  
    }
1032  
    }
1033  
}
1033  
}
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
1038  
fields_base::
1038  
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  
{
1044  
    auto rv = verify_field_value(value);
1044  
    auto rv = verify_field_value(value);
1045  
    if(rv.has_error())
1045  
    if(rv.has_error())
1046  
    {
1046  
    {
1047  
        ec = rv.error();
1047  
        ec = rv.error();
1048  
        return;
1048  
        return;
1049  
    }
1049  
    }
1050  

1050  

1051  
    auto const i0 = h_.find(id);
1051  
    auto const i0 = h_.find(id);
1052  
    if(i0 != h_.count)
1052  
    if(i0 != h_.count)
1053  
    {
1053  
    {
1054  
        // field exists
1054  
        // field exists
1055  
        auto const ft = h_.tab();
1055  
        auto const ft = h_.tab();
1056  
        {
1056  
        {
1057  
            // provide strong guarantee
1057  
            // provide strong guarantee
1058  
            auto const n0 =
1058  
            auto const n0 =
1059  
                h_.size - length(i0);
1059  
                h_.size - length(i0);
1060  
            auto const n =
1060  
            auto const n =
1061  
                ft[i0].nn + 2 +
1061  
                ft[i0].nn + 2 +
1062  
                    rv->value.size() + 2;
1062  
                    rv->value.size() + 2;
1063  
            // VFALCO missing overflow check
1063  
            // VFALCO missing overflow check
1064  
            reserve_bytes(n0 + n);
1064  
            reserve_bytes(n0 + n);
1065  
        }
1065  
        }
1066  
        erase_all(i0, id);
1066  
        erase_all(i0, id);
1067  
    }
1067  
    }
1068  

1068  

1069  
    insert_unchecked(
1069  
    insert_unchecked(
1070  
        id,
1070  
        id,
1071  
        to_string(id),
1071  
        to_string(id),
1072  
        rv->value,
1072  
        rv->value,
1073  
        h_.count,
1073  
        h_.count,
1074  
        rv->has_obs_fold);
1074  
        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
1080  
fields_base::
1080  
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  
{
1086  
    verify_field_name(name , ec);
1086  
    verify_field_name(name , ec);
1087  
    if(ec)
1087  
    if(ec)
1088  
        return;
1088  
        return;
1089  

1089  

1090  
    auto rv = verify_field_value(value);
1090  
    auto rv = verify_field_value(value);
1091  
    if(rv.has_error())
1091  
    if(rv.has_error())
1092  
    {
1092  
    {
1093  
        ec = rv.error();
1093  
        ec = rv.error();
1094  
        return;
1094  
        return;
1095  
    }
1095  
    }
1096  

1096  

1097  
    auto const i0 = h_.find(name);
1097  
    auto const i0 = h_.find(name);
1098  
    if(i0 != h_.count)
1098  
    if(i0 != h_.count)
1099  
    {
1099  
    {
1100  
        // field exists
1100  
        // field exists
1101  
        auto const ft = h_.tab();
1101  
        auto const ft = h_.tab();
1102  
        auto const id = ft[i0].id;
1102  
        auto const id = ft[i0].id;
1103  
        {
1103  
        {
1104  
            // provide strong guarantee
1104  
            // provide strong guarantee
1105  
            auto const n0 =
1105  
            auto const n0 =
1106  
                h_.size - length(i0);
1106  
                h_.size - length(i0);
1107  
            auto const n =
1107  
            auto const n =
1108  
                ft[i0].nn + 2 +
1108  
                ft[i0].nn + 2 +
1109  
                    rv->value.size() + 2;
1109  
                    rv->value.size() + 2;
1110  
            // VFALCO missing overflow check
1110  
            // VFALCO missing overflow check
1111  
            reserve_bytes(n0 + n);
1111  
            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
1115  
        if(id != detail::header::unknown_field)
1115  
        if(id != detail::header::unknown_field)
1116  
            erase_all(i0, id);
1116  
            erase_all(i0, id);
1117  
        else
1117  
        else
1118  
            erase_all(i0, name);
1118  
            erase_all(i0, name);
1119  
    }
1119  
    }
1120  
    insert_unchecked(
1120  
    insert_unchecked(
1121  
        string_to_field(name),
1121  
        string_to_field(name),
1122  
        name,
1122  
        name,
1123  
        rv->value,
1123  
        rv->value,
1124  
        h_.count,
1124  
        h_.count,
1125  
        rv->has_obs_fold);
1125  
        rv->has_obs_fold);
1126  
}
1126  
}
1127  

1127  

1128  
auto
1128  
auto
1129  
fields_base::
1129  
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  
{
1136  
    system::error_code ec;
1136  
    system::error_code ec;
1137  
    auto const it = insert(before, id, value, ec);
1137  
    auto const it = insert(before, id, value, ec);
1138  
    if(ec)
1138  
    if(ec)
1139  
        detail::throw_system_error(ec);
1139  
        detail::throw_system_error(ec);
1140  
    return it;
1140  
    return it;
1141  
}
1141  
}
1142  

1142  

1143  
auto
1143  
auto
1144  
fields_base::
1144  
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  
{
1152  
    insert_impl(
1152  
    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);
1157  
    return before;
1157  
    return before;
1158  
}
1158  
}
1159  

1159  

1160  
auto
1160  
auto
1161  
fields_base::
1161  
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  
{
1168  
    system::error_code ec;
1168  
    system::error_code ec;
1169  
    insert(before, name, value, ec);
1169  
    insert(before, name, value, ec);
1170  
    if(ec)
1170  
    if(ec)
1171  
        detail::throw_system_error(ec);
1171  
        detail::throw_system_error(ec);
1172  
    return before;
1172  
    return before;
1173  
}
1173  
}
1174  

1174  

1175  
auto
1175  
auto
1176  
fields_base::
1176  
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  
{
1184  
    insert_impl(
1184  
    insert_impl(
1185  
        string_to_field(name),
1185  
        string_to_field(name),
1186  
        name,
1186  
        name,
1187  
        value,
1187  
        value,
1188  
        before.i_,
1188  
        before.i_,
1189  
        ec);
1189  
        ec);
1190  
    return before;
1190  
    return before;
1191  
}
1191  
}
1192  

1192  

1193  
void
1193  
void
1194  
fields_base::
1194  
fields_base::
1195  
set(
1195  
set(
1196  
    iterator it,
1196  
    iterator it,
1197  
    core::string_view value)
1197  
    core::string_view value)
1198  
{
1198  
{
1199  
    system::error_code ec;
1199  
    system::error_code ec;
1200  
    set(it, value, ec);
1200  
    set(it, value, ec);
1201  
    if(ec)
1201  
    if(ec)
1202  
        detail::throw_system_error(ec);
1202  
        detail::throw_system_error(ec);
1203  
}
1203  
}
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
1213  
fields_base::
1213  
fields_base::
1214  
copy_impl(
1214  
copy_impl(
1215  
    detail::header const& h)
1215  
    detail::header const& h)
1216  
{
1216  
{
1217  
    BOOST_ASSERT(
1217  
    BOOST_ASSERT(
1218  
        h.kind == h_.kind);
1218  
        h.kind == h_.kind);
1219  

1219  

1220  
    auto const n =
1220  
    auto const n =
1221  
        detail::header::bytes_needed(
1221  
        detail::header::bytes_needed(
1222  
            h.size, h.count);
1222  
            h.size, h.count);
1223  
    if(n <= h_.cap && (!h.is_default() || external_storage_))
1223  
    if(n <= h_.cap && (!h.is_default() || external_storage_))
1224  
    {
1224  
    {
1225  
        // no realloc
1225  
        // no realloc
1226  
        h.assign_to(h_);
1226  
        h.assign_to(h_);
1227  
        h.copy_table(
1227  
        h.copy_table(
1228  
            h_.buf + h_.cap);
1228  
            h_.buf + h_.cap);
1229  
        std::memcpy(
1229  
        std::memcpy(
1230  
            h_.buf,
1230  
            h_.buf,
1231  
            h.cbuf,
1231  
            h.cbuf,
1232  
            h.size);
1232  
            h.size);
1233  
        return;
1233  
        return;
1234  
    }
1234  
    }
1235  

1235  

1236  
    // static storages cannot reallocate
1236  
    // static storages cannot reallocate
1237  
    if(external_storage_)
1237  
    if(external_storage_)
1238  
        detail::throw_length_error();
1238  
        detail::throw_length_error();
1239  

1239  

1240  
    fields_base tmp(h);
1240  
    fields_base tmp(h);
1241  
    tmp.h_.swap(h_);
1241  
    tmp.h_.swap(h_);
1242  
}
1242  
}
1243  

1243  

1244  
void
1244  
void
1245  
fields_base::
1245  
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  
{
1253  
    verify_field_name(name, ec);
1253  
    verify_field_name(name, ec);
1254  
    if(ec)
1254  
    if(ec)
1255  
        return;
1255  
        return;
1256  

1256  

1257  
    auto rv = verify_field_value(value);
1257  
    auto rv = verify_field_value(value);
1258  
    if(rv.has_error())
1258  
    if(rv.has_error())
1259  
    {
1259  
    {
1260  
        ec = rv.error();
1260  
        ec = rv.error();
1261  
        return;
1261  
        return;
1262  
    }
1262  
    }
1263  

1263  

1264  
    insert_unchecked(
1264  
    insert_unchecked(
1265  
        id,
1265  
        id,
1266  
        name,
1266  
        name,
1267  
        rv->value,
1267  
        rv->value,
1268  
        before,
1268  
        before,
1269  
        rv->has_obs_fold);
1269  
        rv->has_obs_fold);
1270  
}
1270  
}
1271  

1271  

1272  
void
1272  
void
1273  
fields_base::
1273  
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  
{
1281  
    auto const tab0 = h_.tab_();
1281  
    auto const tab0 = h_.tab_();
1282  
    auto const pos = offset(before);
1282  
    auto const pos = offset(before);
1283  
    auto const n =
1283  
    auto const n =
1284  
        name.size() +       // name
1284  
        name.size() +       // name
1285  
        1 +                 // ':'
1285  
        1 +                 // ':'
1286  
        ! value.empty() +   // [SP]
1286  
        ! value.empty() +   // [SP]
1287  
        value.size() +      // value
1287  
        value.size() +      // value
1288  
        2;                  // CRLF
1288  
        2;                  // CRLF
1289  

1289  

1290  
    op_t op(*this, &name, &value);
1290  
    op_t op(*this, &name, &value);
1291  
    if(op.grow(n, 1))
1291  
    if(op.grow(n, 1))
1292  
    {
1292  
    {
1293  
        // reallocated
1293  
        // reallocated
1294  
        if(pos > 0)
1294  
        if(pos > 0)
1295  
            std::memcpy(
1295  
            std::memcpy(
1296  
                h_.buf,
1296  
                h_.buf,
1297  
                op.cbuf(),
1297  
                op.cbuf(),
1298  
                pos);
1298  
                pos);
1299  
        if(before > 0)
1299  
        if(before > 0)
1300  
            std::memcpy(
1300  
            std::memcpy(
1301  
                h_.tab_() - before,
1301  
                h_.tab_() - before,
1302  
                tab0 - before,
1302  
                tab0 - before,
1303  
                before * sizeof(entry));
1303  
                before * sizeof(entry));
1304  
        std::memcpy(
1304  
        std::memcpy(
1305  
            h_.buf + pos + n,
1305  
            h_.buf + pos + n,
1306  
            op.cbuf() + pos,
1306  
            op.cbuf() + pos,
1307  
            h_.size - pos);
1307  
            h_.size - pos);
1308  
    }
1308  
    }
1309  
    else
1309  
    else
1310  
    {
1310  
    {
1311  
        op.move_chars(
1311  
        op.move_chars(
1312  
            h_.buf + pos + n,
1312  
            h_.buf + pos + n,
1313  
            h_.buf + pos,
1313  
            h_.buf + pos,
1314  
            h_.size - pos);
1314  
            h_.size - pos);
1315  
    }
1315  
    }
1316  

1316  

1317  
    // serialize
1317  
    // serialize
1318  
    {
1318  
    {
1319  
        auto dest = h_.buf + pos;
1319  
        auto dest = h_.buf + pos;
1320  
        name.copy(dest, name.size());
1320  
        name.copy(dest, name.size());
1321  
        dest += name.size();
1321  
        dest += name.size();
1322  
        *dest++ = ':';
1322  
        *dest++ = ':';
1323  
        if(! value.empty())
1323  
        if(! value.empty())
1324  
        {
1324  
        {
1325  
            *dest++ = ' ';
1325  
            *dest++ = ' ';
1326  
            value.copy(
1326  
            value.copy(
1327  
                dest, value.size());
1327  
                dest, value.size());
1328  
            if( has_obs_fold )
1328  
            if( has_obs_fold )
1329  
                detail::remove_obs_fold(
1329  
                detail::remove_obs_fold(
1330  
                    dest, dest + value.size());
1330  
                    dest, dest + value.size());
1331  
            dest += value.size();
1331  
            dest += value.size();
1332  
        }
1332  
        }
1333  
        *dest++ = '\r';
1333  
        *dest++ = '\r';
1334  
        *dest = '\n';
1334  
        *dest = '\n';
1335  
    }
1335  
    }
1336  

1336  

1337  
    // update table
1337  
    // update table
1338  
    auto const tab = h_.tab_();
1338  
    auto const tab = h_.tab_();
1339  
    {
1339  
    {
1340  
        auto i = h_.count - before;
1340  
        auto i = h_.count - before;
1341  
        if(i > 0)
1341  
        if(i > 0)
1342  
        {
1342  
        {
1343  
            auto p0 = tab0 - h_.count;
1343  
            auto p0 = tab0 - h_.count;
1344  
            auto p = tab - h_.count - 1;
1344  
            auto p = tab - h_.count - 1;
1345  
            do
1345  
            do
1346  
            {
1346  
            {
1347  
                *p++ = *p0++ + n;
1347  
                *p++ = *p0++ + n;
1348  
            }
1348  
            }
1349  
            while(--i);
1349  
            while(--i);
1350  
        }
1350  
        }
1351  
    }
1351  
    }
1352  
    auto& e = tab[0 - static_cast<std::ptrdiff_t>(before) - 1];
1352  
    auto& e = tab[0 - static_cast<std::ptrdiff_t>(before) - 1];
1353  
    e.np = static_cast<offset_type>(
1353  
    e.np = static_cast<offset_type>(
1354  
        pos - h_.prefix);
1354  
        pos - h_.prefix);
1355  
    e.nn = static_cast<
1355  
    e.nn = static_cast<
1356  
        offset_type>(name.size());
1356  
        offset_type>(name.size());
1357  
    e.vp = static_cast<offset_type>(
1357  
    e.vp = static_cast<offset_type>(
1358  
        pos - h_.prefix +
1358  
        pos - h_.prefix +
1359  
            name.size() + 1 +
1359  
            name.size() + 1 +
1360  
            ! value.empty());
1360  
            ! value.empty());
1361  
    e.vn = static_cast<
1361  
    e.vn = static_cast<
1362  
        offset_type>(value.size());
1362  
        offset_type>(value.size());
1363  
    e.id = id.value_or(
1363  
    e.id = id.value_or(
1364  
        detail::header::unknown_field);
1364  
        detail::header::unknown_field);
1365  

1365  

1366  
    // update container
1366  
    // update container
1367  
    h_.count++;
1367  
    h_.count++;
1368  
    h_.size = static_cast<
1368  
    h_.size = static_cast<
1369  
        offset_type>(h_.size + n);
1369  
        offset_type>(h_.size + n);
1370  
    h_.on_insert(e.id, value);
1370  
    h_.on_insert(e.id, value);
1371  
}
1371  
}
1372  

1372  

1373  
void
1373  
void
1374  
fields_base::
1374  
fields_base::
1375  
raw_erase(
1375  
raw_erase(
1376  
    std::size_t i) noexcept
1376  
    std::size_t i) noexcept
1377  
{
1377  
{
1378  
    BOOST_ASSERT(i < h_.count);
1378  
    BOOST_ASSERT(i < h_.count);
1379  
    BOOST_ASSERT(h_.buf != nullptr);
1379  
    BOOST_ASSERT(h_.buf != nullptr);
1380  
    auto const p0 = offset(i);
1380  
    auto const p0 = offset(i);
1381  
    auto const p1 = offset(i + 1);
1381  
    auto const p1 = offset(i + 1);
1382  
    std::memmove(
1382  
    std::memmove(
1383  
        h_.buf + p0,
1383  
        h_.buf + p0,
1384  
        h_.buf + p1,
1384  
        h_.buf + p1,
1385  
        h_.size - p1);
1385  
        h_.size - p1);
1386  
    auto const n = p1 - p0;
1386  
    auto const n = p1 - p0;
1387  
    --h_.count;
1387  
    --h_.count;
1388  
    auto ft = h_.tab();
1388  
    auto ft = h_.tab();
1389  
    for(;i < h_.count; ++i)
1389  
    for(;i < h_.count; ++i)
1390  
        ft[i] = ft[i + 1] - n;
1390  
        ft[i] = ft[i + 1] - n;
1391  
    h_.size = static_cast<
1391  
    h_.size = static_cast<
1392  
        offset_type>(h_.size - n);
1392  
        offset_type>(h_.size - n);
1393  
}
1393  
}
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
1398  
fields_base::
1398  
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
1404  
    auto e = &h_.tab()[h_.count];
1404  
    auto e = &h_.tab()[h_.count];
1405  
    auto const e0 = &h_.tab()[0];
1405  
    auto const e0 = &h_.tab()[0];
1406  
    while(n > 0)
1406  
    while(n > 0)
1407  
    {
1407  
    {
1408  
        BOOST_ASSERT(e != e0);
1408  
        BOOST_ASSERT(e != e0);
1409  
        ++e; // decrement
1409  
        ++e; // decrement
1410  
        if(e->id == id)
1410  
        if(e->id == id)
1411  
        {
1411  
        {
1412  
            raw_erase(e0 - e);
1412  
            raw_erase(e0 - e);
1413  
            --n;
1413  
            --n;
1414  
        }
1414  
        }
1415  
    }
1415  
    }
1416  
}
1416  
}
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
1421  
fields_base::
1421  
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  
{
1426  
    BOOST_ASSERT(
1426  
    BOOST_ASSERT(
1427  
        id != detail::header::unknown_field);
1427  
        id != detail::header::unknown_field);
1428  
    std::size_t n = 1;
1428  
    std::size_t n = 1;
1429  
    std::size_t i = h_.count - 1;
1429  
    std::size_t i = h_.count - 1;
1430  
    auto const ft = h_.tab();
1430  
    auto const ft = h_.tab();
1431  
    while(i > i0)
1431  
    while(i > i0)
1432  
    {
1432  
    {
1433  
        if(ft[i].id == id)
1433  
        if(ft[i].id == id)
1434  
        {
1434  
        {
1435  
            raw_erase(i);
1435  
            raw_erase(i);
1436  
            ++n;
1436  
            ++n;
1437  
        }
1437  
        }
1438  
        // go backwards to
1438  
        // go backwards to
1439  
        // reduce memmoves
1439  
        // reduce memmoves
1440  
        --i;
1440  
        --i;
1441  
    }
1441  
    }
1442  
    raw_erase(i0);
1442  
    raw_erase(i0);
1443  
    h_.on_erase_all(id);
1443  
    h_.on_erase_all(id);
1444  
    return n;
1444  
    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
1450  
fields_base::
1450  
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  
{
1455  
    std::size_t n = 1;
1455  
    std::size_t n = 1;
1456  
    std::size_t i = h_.count - 1;
1456  
    std::size_t i = h_.count - 1;
1457  
    auto const ft = h_.tab();
1457  
    auto const ft = h_.tab();
1458  
    auto const* p = h_.cbuf + h_.prefix;
1458  
    auto const* p = h_.cbuf + h_.prefix;
1459  
    while(i > i0)
1459  
    while(i > i0)
1460  
    {
1460  
    {
1461  
        core::string_view s(
1461  
        core::string_view s(
1462  
            p + ft[i].np, ft[i].nn);
1462  
            p + ft[i].np, ft[i].nn);
1463  
        if(s == name)
1463  
        if(s == name)
1464  
        {
1464  
        {
1465  
            raw_erase(i);
1465  
            raw_erase(i);
1466  
            ++n;
1466  
            ++n;
1467  
        }
1467  
        }
1468  
        // go backwards to
1468  
        // go backwards to
1469  
        // reduce memmoves
1469  
        // reduce memmoves
1470  
        --i;
1470  
        --i;
1471  
    }
1471  
    }
1472  
    raw_erase(i0);
1472  
    raw_erase(i0);
1473  
    return n;
1473  
    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
1478  
fields_base::
1478  
fields_base::
1479  
offset(
1479  
offset(
1480  
    std::size_t i) const noexcept
1480  
    std::size_t i) const noexcept
1481  
{
1481  
{
1482  
    if(i == 0)
1482  
    if(i == 0)
1483  
        return h_.prefix;
1483  
        return h_.prefix;
1484  
    if(i < h_.count)
1484  
    if(i < h_.count)
1485  
        return h_.prefix + h_.tab()[i].np;
1485  
        return h_.prefix + h_.tab()[i].np;
1486  
    // make final CRLF the last "field"
1486  
    // make final CRLF the last "field"
1487  
    return h_.size - 2;
1487  
    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
1492  
fields_base::
1492  
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
1497  
        offset(i + 1) -
1497  
        offset(i + 1) -
1498  
        offset(i);
1498  
        offset(i);
1499  
}
1499  
}
1500  

1500  

1501  
} // http
1501  
} // http
1502  
} // boost
1502  
} // boost