Line data Source code
1 : //
2 : // Copyright (c) 2021 Vinnie Falco (vinnie.falco@gmail.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 : // Official repository: https://github.com/CPPAlliance/http_proto
8 : //
9 :
10 : #ifndef BOOST_HTTP_PROTO_IMPL_FIELDS_VIEW_BASE_IPP
11 : #define BOOST_HTTP_PROTO_IMPL_FIELDS_VIEW_BASE_IPP
12 :
13 : #include <boost/http_proto/fields_view.hpp>
14 : #include <boost/http_proto/field.hpp>
15 : #include <boost/http_proto/detail/except.hpp>
16 : #include <boost/url/grammar/ci_string.hpp>
17 : #include <boost/url/grammar/parse.hpp>
18 : #include <boost/assert.hpp>
19 : #include <boost/assert/source_location.hpp>
20 : #include <utility>
21 :
22 : namespace boost {
23 : namespace http_proto {
24 :
25 0 : fields_view_base::
26 : value_type::
27 : value_type(
28 0 : reference const& other)
29 0 : : id(other.id)
30 : , name(other.name)
31 0 : , value(other.value)
32 : {
33 0 : }
34 :
35 : //------------------------------------------------
36 :
37 : auto
38 1677 : fields_view_base::
39 : iterator::
40 : operator*() const noexcept ->
41 : reference
42 : {
43 1677 : BOOST_ASSERT(i_ < ph_->count);
44 : auto const& e =
45 1677 : ph_->tab()[i_];
46 1677 : auto const* p =
47 1677 : ph_->cbuf + ph_->prefix;
48 : return {
49 1677 : e.id,
50 : string_view(
51 1677 : p + e.np, e.nn),
52 : string_view(
53 1677 : p + e.vp, e.vn) };
54 : }
55 :
56 : //------------------------------------------------
57 :
58 : auto
59 24 : fields_view_base::
60 : reverse_iterator::
61 : operator*() const noexcept ->
62 : reference
63 : {
64 24 : BOOST_ASSERT(i_ > 0);
65 : auto const& e =
66 24 : ph_->tab()[i_-1];
67 24 : auto const* p =
68 24 : ph_->cbuf + ph_->prefix;
69 : return {
70 24 : e.id,
71 : string_view(
72 24 : p + e.np, e.nn),
73 : string_view(
74 24 : p + e.vp, e.vn) };
75 : }
76 :
77 : //------------------------------------------------
78 :
79 67 : fields_view_base::
80 : subrange::
81 : iterator::
82 : iterator(
83 : detail::header const* ph,
84 67 : std::size_t i) noexcept
85 : : ph_(ph)
86 67 : , i_(i)
87 : {
88 67 : BOOST_ASSERT(i <= ph_->count);
89 67 : }
90 :
91 67 : fields_view_base::
92 : subrange::
93 : iterator::
94 : iterator(
95 67 : detail::header const* ph) noexcept
96 : : ph_(ph)
97 67 : , i_(ph->count)
98 : {
99 67 : }
100 :
101 : auto
102 72 : fields_view_base::
103 : subrange::
104 : iterator::
105 : operator*() const noexcept ->
106 : reference const
107 : {
108 : auto const& e =
109 72 : ph_->tab()[i_];
110 72 : auto const p =
111 72 : ph_->cbuf + ph_->prefix;
112 144 : return string_view(
113 72 : p + e.vp, e.vn);
114 : }
115 :
116 : auto
117 80 : fields_view_base::
118 : subrange::
119 : iterator::
120 : operator++() noexcept ->
121 : iterator&
122 : {
123 80 : BOOST_ASSERT(i_ < ph_->count);
124 80 : auto const* e = &ph_->tab()[i_];
125 80 : auto const id = e->id;
126 80 : if(id != field::unknown)
127 : {
128 73 : ++i_;
129 73 : --e;
130 95 : while(i_ != ph_->count)
131 : {
132 45 : if(e->id == id)
133 23 : break;
134 22 : ++i_;
135 22 : --e;
136 : }
137 73 : return *this;
138 : }
139 7 : auto const p =
140 7 : ph_->cbuf + ph_->prefix;
141 : auto name =
142 7 : string_view(p + e->np, e->nn);
143 7 : ++i_;
144 7 : --e;
145 24 : while(i_ != ph_->count)
146 : {
147 20 : if(grammar::ci_is_equal(
148 : name, string_view(
149 20 : p + e->np, e->nn)))
150 3 : break;
151 17 : ++i_;
152 17 : --e;
153 : }
154 7 : return *this;
155 : }
156 :
157 : //------------------------------------------------
158 : //
159 : // fields_view_base
160 : //
161 : //------------------------------------------------
162 :
163 : bool
164 4 : fields_view_base::
165 : exists(
166 : field id) const noexcept
167 : {
168 4 : return find(id) != end();
169 : }
170 :
171 : bool
172 7 : fields_view_base::
173 : exists(
174 : string_view name) const noexcept
175 : {
176 7 : return find(name) != end();
177 : }
178 :
179 : std::size_t
180 12 : fields_view_base::
181 : count(field id) const noexcept
182 : {
183 12 : std::size_t n = 0;
184 55 : for(auto v : *this)
185 43 : if(v.id == id)
186 11 : ++n;
187 12 : return n;
188 : }
189 :
190 : std::size_t
191 5 : fields_view_base::
192 : count(string_view name) const noexcept
193 : {
194 5 : std::size_t n = 0;
195 49 : for(auto v : *this)
196 44 : if(grammar::ci_is_equal(
197 : v.name, name))
198 7 : ++n;
199 5 : return n;
200 : }
201 :
202 : auto
203 58 : fields_view_base::
204 : find(field id) const noexcept ->
205 : iterator
206 : {
207 58 : auto it = begin();
208 58 : auto const last = end();
209 151 : while(it != last)
210 : {
211 143 : if(it->id == id)
212 50 : break;
213 93 : ++it;
214 : }
215 58 : return it;
216 : }
217 :
218 : auto
219 66 : fields_view_base::
220 : find(string_view name) const noexcept ->
221 : iterator
222 : {
223 66 : auto it = begin();
224 66 : auto const last = end();
225 166 : while(it != last)
226 : {
227 158 : if(grammar::ci_is_equal(
228 316 : it->name, name))
229 58 : break;
230 100 : ++it;
231 : }
232 66 : return it;
233 : }
234 :
235 : auto
236 2 : fields_view_base::
237 : find(
238 : iterator from,
239 : field id) const noexcept ->
240 : iterator
241 : {
242 2 : auto const last = end();
243 11 : while(from != last)
244 : {
245 10 : if(from->id == id)
246 1 : break;
247 9 : ++from;
248 : }
249 2 : return from;
250 : }
251 :
252 : auto
253 2 : fields_view_base::
254 : find(
255 : iterator from,
256 : string_view name) const noexcept ->
257 : iterator
258 : {
259 2 : auto const last = end();
260 12 : while(from != last)
261 : {
262 11 : if(grammar::ci_is_equal(
263 22 : name, from->name))
264 1 : break;
265 10 : ++from;
266 : }
267 2 : return from;
268 : }
269 :
270 : auto
271 27 : fields_view_base::
272 : find_last(
273 : iterator it,
274 : field id) const noexcept ->
275 : iterator
276 : {
277 27 : auto const it0 = begin();
278 : for(;;)
279 : {
280 40 : if(it == it0)
281 4 : return end();
282 36 : --it;
283 36 : if(it->id == id)
284 23 : return it;
285 : }
286 : }
287 :
288 : auto
289 3 : fields_view_base::
290 : find_last(
291 : iterator it,
292 : string_view name) const noexcept ->
293 : iterator
294 : {
295 3 : auto const it0 = begin();
296 : for(;;)
297 : {
298 14 : if(it == it0)
299 1 : return end();
300 13 : --it;
301 13 : if(grammar::ci_is_equal(
302 26 : it->name, name))
303 2 : return it;
304 : }
305 : }
306 :
307 : string_view
308 2 : fields_view_base::
309 : value_or(
310 : field id,
311 : string_view s) const noexcept
312 : {
313 2 : auto it = find(id);
314 2 : if(it != end())
315 1 : return it->value;
316 1 : return s;
317 : }
318 :
319 : string_view
320 2 : fields_view_base::
321 : value_or(
322 : string_view name,
323 : string_view s) const noexcept
324 : {
325 2 : auto it = find(name);
326 2 : if(it != end())
327 1 : return it->value;
328 1 : return s;
329 : }
330 :
331 : //------------------------------------------------
332 :
333 : auto
334 16 : fields_view_base::
335 : find_all(
336 : field id) const noexcept ->
337 : subrange
338 : {
339 32 : return subrange(
340 16 : ph_, find(id).i_);
341 : }
342 :
343 : auto
344 5 : fields_view_base::
345 : find_all(
346 : string_view name) const noexcept ->
347 : subrange
348 : {
349 10 : return subrange(
350 5 : ph_, find(name).i_);
351 : }
352 :
353 : //------------------------------------------------
354 :
355 : } // http_proto
356 : } // boost
357 :
358 : #endif
|