7 #include <boost/intrusive/set.hpp>
8 #include <boost/intrusive/list.hpp>
13 class field :
public boost::intrusive::list_base_hook<>,
14 public boost::intrusive::set_base_hook<>
17 using size_type = uint16_t;
23 static constexpr
auto delim = std::string_view{
": "};
27 : name_size(
name.size()), value_size(
value.size()),
29 auto pos = std::copy(
name.begin(),
name.end(), buffer);
30 pos = std::copy(delim.begin(), delim.end(), pos);
31 pos = std::copy(
value.begin(),
value.end(), pos);
39 std::string_view
name()
const {
40 return {buffer, name_size};
43 std::string_view
value()
const {
44 return {buffer + name_size + delim.size(), value_size};
53 const char*
c_str()
const {
return buffer; }
55 const char*
data()
const {
return buffer; }
57 size_type
size()
const {
return name_size + delim.size() + value_size; }
61 void operator()(
field* f) {
62 const size_t size =
sizeof(
field) + f->name_size + f->value_size;
63 using Alloc = std::allocator<char>;
64 using Traits = std::allocator_traits<Alloc>;
66 Traits::destroy(alloc, f);
67 Traits::deallocate(alloc,
reinterpret_cast<char*
>(f),
size);
70 using ptr = std::unique_ptr<field, deleter>;
73 static ptr create(std::string_view name, std::string_view value,
76 const size_t size =
sizeof(field) + name.size() + value.size();
77 using Alloc = std::allocator<char>;
78 using Traits = std::allocator_traits<Alloc>;
80 auto p = Traits::allocate(alloc, size);
82 return ptr{
new (p) field(name, value, never_index)};
83 }
catch (
const std::exception&) {
84 Traits::deallocate(alloc, p, size);
93 struct field_compare {
94 bool operator()(
char lhs,
char rhs)
const {
95 return std::tolower(lhs) < std::tolower(rhs);
97 bool operator()(std::string_view lhs, std::string_view rhs)
const {
98 return std::lexicographical_compare(lhs.begin(), lhs.end(),
99 rhs.begin(), rhs.end(), *
this);
101 bool operator()(
const field& lhs,
const field& rhs)
const {
102 return (*
this)(lhs.name(), rhs.name());
104 bool operator()(std::string_view lhs,
const field& rhs)
const {
105 return (*
this)(lhs, rhs.name());
107 bool operator()(
const field& lhs, std::string_view rhs)
const {
108 return (*
this)(lhs.name(), rhs);
113 using type = std::string_view;
114 type operator()(
const field& f) {
return f.name(); }
117 using field_multiset = boost::intrusive::multiset<field,
118 boost::intrusive::compare<field_compare>,
119 boost::intrusive::key_of_value<field_key>>;
121 using field_list = boost::intrusive::list<field,
122 boost::intrusive::constant_time_size<true>,
123 boost::intrusive::cache_last<true>,
124 boost::intrusive::size_type<uint16_t>>;
131 using list_type = detail::field_list;
134 using multiset_type = detail::field_multiset;
144 list = std::move(o.list);
145 set = std::move(o.set);
150 using size_type = list_type::size_type;
152 size_type
size()
const {
return list.size(); }
154 bool empty()
const {
return list.empty(); }
156 using value_type = field;
157 using iterator = list_type::iterator;
158 using const_iterator = list_type::const_iterator;
160 iterator begin() {
return list.begin(); }
161 const_iterator begin()
const {
return list.begin(); }
162 const_iterator cbegin()
const {
return list.cbegin(); }
164 iterator end() {
return list.end(); }
165 const_iterator end()
const {
return list.end(); }
166 const_iterator cend()
const {
return list.cend(); }
169 size_type
count(std::string_view name)
const {
170 return set.count(name);
174 iterator
find(std::string_view name) {
175 if (
auto i = set.find(name); i != set.end()) {
176 return list.iterator_to(*i);
182 const_iterator
find(std::string_view name)
const {
183 if (
auto i = set.find(name); i != set.end()) {
184 return list.iterator_to(*i);
192 -> std::pair<iterator, iterator>
194 auto lower = set.lower_bound(name);
195 if (lower == set.end()) {
196 return {list.end(), list.end()};
198 auto upper = set.upper_bound(name);
199 auto list_upper = std::next(list.iterator_to(*std::prev(upper)));
200 return {list.iterator_to(*lower), list_upper};
206 -> std::pair<const_iterator, const_iterator>
208 auto lower = set.lower_bound(name);
209 if (lower == set.end()) {
210 return {list.end(), list.end()};
212 auto upper = set.upper_bound(name);
213 auto list_upper = std::next(list.iterator_to(*std::prev(upper)));
214 return {list.iterator_to(*lower), list_upper};
219 iterator
insert(std::string_view name, std::string_view value,
220 bool never_index =
false)
222 auto ptr = field::create(name, value, never_index);
224 auto lower = set.lower_bound(name);
225 if (lower == set.end()) {
226 set.insert(set.end(), *ptr);
227 return list.insert(list.end(), *ptr.release());
229 auto upper = set.upper_bound(name);
230 auto list_upper = std::next(list.iterator_to(*std::prev(upper)));
231 set.insert(upper, *ptr);
232 return list.insert(list_upper, *ptr.release());
237 iterator
assign(std::string_view name, std::string_view value,
238 bool never_index =
false)
240 auto ptr = field::create(name, value, never_index);
242 auto lower = set.lower_bound(name);
243 if (lower == set.end()) {
244 set.insert(set.end(), *ptr);
245 return list.insert(list.end(), *ptr.release());
247 auto upper = set.upper_bound(name);
248 auto list_lower = list.iterator_to(*lower);
249 auto list_upper = std::next(list.iterator_to(*std::prev(upper)));
250 set.erase(lower, upper);
251 list.erase_and_dispose(list_lower, list_upper, field::deleter{});
253 set.insert(set.end(), *ptr);
254 return list.insert(list.end(), *ptr.release());
259 set.erase(set.iterator_to(*p));
260 return list.erase_and_dispose(p, field::deleter{});
264 iterator
erase(iterator begin, iterator end) {
265 set.erase(set.iterator_to(*begin),
266 std::next(set.iterator_to(*std::prev(end))));
267 return list.erase_and_dispose(begin, end, field::deleter{});
273 list.clear_and_dispose(field::deleter{});
an immutable key/value pair to represent a single header
Definition: fields.hpp:15
std::string_view name() const
return a view of the field name
Definition: fields.hpp:39
size_type size() const
return the string length of c_str()
Definition: fields.hpp:57
const char * c_str() const
return a null-terminated string of the form "<name>: <value>"
Definition: fields.hpp:53
const char * data() const
return a null-terminated string of the form "<name>: <value>"
Definition: fields.hpp:55
void never_index(bool value)
enable or disable the caching of this field for header compression
Definition: fields.hpp:48
bool never_index() const
return whether or not this field can be cached for header compression
Definition: fields.hpp:50
std::string_view value() const
return a view of the field value
Definition: fields.hpp:43
an ordered list of headers for an http request or response. all field name comparisons are case-insen...
Definition: fields.hpp:130
auto equal_range(std::string_view name) -> std::pair< iterator, iterator >
return an iterator pair corresponding to the range of fields that match the given name (the first mat...
Definition: fields.hpp:191
fields(fields &&o)=default
move-construct the fields, leaving o empty
void clear()
erase all fields
Definition: fields.hpp:271
fields & operator=(fields &&o)
move-assign the fields, leaving o empty
Definition: fields.hpp:142
iterator insert(std::string_view name, std::string_view value, bool never_index=false)
insert the given field after the last field that matches its name, or at the end of the list
Definition: fields.hpp:219
const_iterator find(std::string_view name) const
return an iterator to the first field that matches the given name
Definition: fields.hpp:182
iterator find(std::string_view name)
return an iterator to the first field that matches the given name
Definition: fields.hpp:174
fields()=default
construct an empty list of fields
iterator erase(iterator p)
erase the field at the given position
Definition: fields.hpp:258
auto equal_range(std::string_view name) const -> std::pair< const_iterator, const_iterator >
return an iterator pair corresponding to the range of fields that match the given name (the first mat...
Definition: fields.hpp:205
size_type count(std::string_view name) const
return the number of fields that match the given name
Definition: fields.hpp:169
size_type size() const
return the total number of fields in the list
Definition: fields.hpp:152
iterator assign(std::string_view name, std::string_view value, bool never_index=false)
insert the given field at the end of the list, erasing any existing fields with a matching name
Definition: fields.hpp:237
iterator erase(iterator begin, iterator end)
erase all fields in the range [begin,end)
Definition: fields.hpp:264
HTTP/3 library.
Definition: client.hpp:6