]>
Commit | Line | Data |
---|---|---|
1 | // | |
2 | // Copyright (c) 2013-2017 Vinnie Falco (vinnie dot falco at gmail dot com) | |
3 | // | |
4 | // Distributed under the Boost Software License, Version 1.0. (See accompanying | |
5 | // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) | |
6 | // | |
7 | ||
8 | #ifndef BEAST_HTTP_IMPL_BASIC_FIELDS_IPP | |
9 | #define BEAST_HTTP_IMPL_BASIC_FIELDS_IPP | |
10 | ||
11 | #include <beast/http/detail/rfc7230.hpp> | |
12 | #include <algorithm> | |
13 | ||
14 | namespace beast { | |
15 | namespace http { | |
16 | ||
17 | template<class Allocator> | |
18 | void | |
19 | basic_fields<Allocator>:: | |
20 | delete_all() | |
21 | { | |
22 | for(auto it = list_.begin(); it != list_.end();) | |
23 | { | |
24 | auto& e = *it++; | |
25 | alloc_traits::destroy(this->member(), &e); | |
26 | alloc_traits::deallocate( | |
27 | this->member(), &e, 1); | |
28 | } | |
29 | } | |
30 | ||
31 | template<class Allocator> | |
32 | inline | |
33 | void | |
34 | basic_fields<Allocator>:: | |
35 | move_assign(basic_fields& other, std::false_type) | |
36 | { | |
37 | if(this->member() != other.member()) | |
38 | { | |
39 | copy_from(other); | |
40 | other.clear(); | |
41 | } | |
42 | else | |
43 | { | |
44 | set_ = std::move(other.set_); | |
45 | list_ = std::move(other.list_); | |
46 | } | |
47 | } | |
48 | ||
49 | template<class Allocator> | |
50 | inline | |
51 | void | |
52 | basic_fields<Allocator>:: | |
53 | move_assign(basic_fields& other, std::true_type) | |
54 | { | |
55 | this->member() = std::move(other.member()); | |
56 | set_ = std::move(other.set_); | |
57 | list_ = std::move(other.list_); | |
58 | } | |
59 | ||
60 | template<class Allocator> | |
61 | inline | |
62 | void | |
63 | basic_fields<Allocator>:: | |
64 | copy_assign(basic_fields const& other, std::false_type) | |
65 | { | |
66 | copy_from(other); | |
67 | } | |
68 | ||
69 | template<class Allocator> | |
70 | inline | |
71 | void | |
72 | basic_fields<Allocator>:: | |
73 | copy_assign(basic_fields const& other, std::true_type) | |
74 | { | |
75 | this->member() = other.member(); | |
76 | copy_from(other); | |
77 | } | |
78 | ||
79 | //------------------------------------------------------------------------------ | |
80 | ||
81 | template<class Allocator> | |
82 | basic_fields<Allocator>:: | |
83 | ~basic_fields() | |
84 | { | |
85 | delete_all(); | |
86 | } | |
87 | ||
88 | template<class Allocator> | |
89 | basic_fields<Allocator>:: | |
90 | basic_fields(Allocator const& alloc) | |
91 | : beast::detail::empty_base_optimization< | |
92 | alloc_type>(alloc) | |
93 | { | |
94 | } | |
95 | ||
96 | template<class Allocator> | |
97 | basic_fields<Allocator>:: | |
98 | basic_fields(basic_fields&& other) | |
99 | : beast::detail::empty_base_optimization<alloc_type>( | |
100 | std::move(other.member())) | |
101 | , detail::basic_fields_base( | |
102 | std::move(other.set_), std::move(other.list_)) | |
103 | { | |
104 | } | |
105 | ||
106 | template<class Allocator> | |
107 | auto | |
108 | basic_fields<Allocator>:: | |
109 | operator=(basic_fields&& other) -> | |
110 | basic_fields& | |
111 | { | |
112 | if(this == &other) | |
113 | return *this; | |
114 | clear(); | |
115 | move_assign(other, std::integral_constant<bool, | |
116 | alloc_traits::propagate_on_container_move_assignment::value>{}); | |
117 | return *this; | |
118 | } | |
119 | ||
120 | template<class Allocator> | |
121 | basic_fields<Allocator>:: | |
122 | basic_fields(basic_fields const& other) | |
123 | : basic_fields(alloc_traits:: | |
124 | select_on_container_copy_construction(other.member())) | |
125 | { | |
126 | copy_from(other); | |
127 | } | |
128 | ||
129 | template<class Allocator> | |
130 | auto | |
131 | basic_fields<Allocator>:: | |
132 | operator=(basic_fields const& other) -> | |
133 | basic_fields& | |
134 | { | |
135 | clear(); | |
136 | copy_assign(other, std::integral_constant<bool, | |
137 | alloc_traits::propagate_on_container_copy_assignment::value>{}); | |
138 | return *this; | |
139 | } | |
140 | ||
141 | template<class Allocator> | |
142 | template<class OtherAlloc> | |
143 | basic_fields<Allocator>:: | |
144 | basic_fields(basic_fields<OtherAlloc> const& other) | |
145 | { | |
146 | copy_from(other); | |
147 | } | |
148 | ||
149 | template<class Allocator> | |
150 | template<class OtherAlloc> | |
151 | auto | |
152 | basic_fields<Allocator>:: | |
153 | operator=(basic_fields<OtherAlloc> const& other) -> | |
154 | basic_fields& | |
155 | { | |
156 | clear(); | |
157 | copy_from(other); | |
158 | return *this; | |
159 | } | |
160 | ||
161 | template<class Allocator> | |
162 | template<class FwdIt> | |
163 | basic_fields<Allocator>:: | |
164 | basic_fields(FwdIt first, FwdIt last) | |
165 | { | |
166 | for(;first != last; ++first) | |
167 | insert(first->name(), first->value()); | |
168 | } | |
169 | ||
170 | template<class Allocator> | |
171 | std::size_t | |
172 | basic_fields<Allocator>:: | |
173 | count(boost::string_ref const& name) const | |
174 | { | |
175 | auto const it = set_.find(name, less{}); | |
176 | if(it == set_.end()) | |
177 | return 0; | |
178 | auto const last = set_.upper_bound(name, less{}); | |
179 | return static_cast<std::size_t>(std::distance(it, last)); | |
180 | } | |
181 | ||
182 | template<class Allocator> | |
183 | auto | |
184 | basic_fields<Allocator>:: | |
185 | find(boost::string_ref const& name) const -> | |
186 | iterator | |
187 | { | |
188 | auto const it = set_.find(name, less{}); | |
189 | if(it == set_.end()) | |
190 | return list_.end(); | |
191 | return list_.iterator_to(*it); | |
192 | } | |
193 | ||
194 | template<class Allocator> | |
195 | boost::string_ref | |
196 | basic_fields<Allocator>:: | |
197 | operator[](boost::string_ref const& name) const | |
198 | { | |
199 | auto const it = find(name); | |
200 | if(it == end()) | |
201 | return {}; | |
202 | return it->second; | |
203 | } | |
204 | ||
205 | template<class Allocator> | |
206 | void | |
207 | basic_fields<Allocator>:: | |
208 | clear() noexcept | |
209 | { | |
210 | delete_all(); | |
211 | list_.clear(); | |
212 | set_.clear(); | |
213 | } | |
214 | ||
215 | template<class Allocator> | |
216 | std::size_t | |
217 | basic_fields<Allocator>:: | |
218 | erase(boost::string_ref const& name) | |
219 | { | |
220 | auto it = set_.find(name, less{}); | |
221 | if(it == set_.end()) | |
222 | return 0; | |
223 | auto const last = set_.upper_bound(name, less{}); | |
224 | std::size_t n = 1; | |
225 | for(;;) | |
226 | { | |
227 | auto& e = *it++; | |
228 | set_.erase(set_.iterator_to(e)); | |
229 | list_.erase(list_.iterator_to(e)); | |
230 | alloc_traits::destroy(this->member(), &e); | |
231 | alloc_traits::deallocate(this->member(), &e, 1); | |
232 | if(it == last) | |
233 | break; | |
234 | ++n; | |
235 | } | |
236 | return n; | |
237 | } | |
238 | ||
239 | template<class Allocator> | |
240 | void | |
241 | basic_fields<Allocator>:: | |
242 | insert(boost::string_ref const& name, | |
243 | boost::string_ref value) | |
244 | { | |
245 | value = detail::trim(value); | |
246 | auto const p = alloc_traits::allocate(this->member(), 1); | |
247 | alloc_traits::construct(this->member(), p, name, value); | |
248 | set_.insert_before(set_.upper_bound(name, less{}), *p); | |
249 | list_.push_back(*p); | |
250 | } | |
251 | ||
252 | template<class Allocator> | |
253 | void | |
254 | basic_fields<Allocator>:: | |
255 | replace(boost::string_ref const& name, | |
256 | boost::string_ref value) | |
257 | { | |
258 | value = detail::trim(value); | |
259 | erase(name); | |
260 | insert(name, value); | |
261 | } | |
262 | ||
263 | } // http | |
264 | } // beast | |
265 | ||
266 | #endif |