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 1682 : fields_view_base::
39 : iterator::
40 : operator*() const noexcept ->
41 : reference
42 : {
43 1682 : BOOST_ASSERT(i_ < ph_->count);
44 : auto const& e =
45 1682 : ph_->tab()[i_];
46 1682 : auto const* p =
47 1682 : ph_->cbuf + ph_->prefix;
48 : return {
49 1682 : e.id,
50 : core::string_view(
51 1682 : p + e.np, e.nn),
52 : core::string_view(
53 1682 : 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 : core::string_view(
72 24 : p + e.np, e.nn),
73 : core::string_view(
74 24 : p + e.vp, e.vn) };
75 : }
76 :
77 : //------------------------------------------------
78 :
79 66 : fields_view_base::
80 : subrange::
81 : iterator::
82 : iterator(
83 : detail::header const* ph,
84 66 : std::size_t i) noexcept
85 : : ph_(ph)
86 66 : , i_(i)
87 : {
88 66 : BOOST_ASSERT(i <= ph_->count);
89 66 : }
90 :
91 66 : fields_view_base::
92 : subrange::
93 : iterator::
94 : iterator(
95 66 : detail::header const* ph) noexcept
96 : : ph_(ph)
97 66 : , i_(ph->count)
98 : {
99 66 : }
100 :
101 : auto
102 71 : fields_view_base::
103 : subrange::
104 : iterator::
105 : operator*() const noexcept ->
106 : reference const
107 : {
108 : auto const& e =
109 71 : ph_->tab()[i_];
110 71 : auto const p =
111 71 : ph_->cbuf + ph_->prefix;
112 142 : return core::string_view(
113 71 : p + e.vp, e.vn);
114 : }
115 :
116 : auto
117 79 : fields_view_base::
118 : subrange::
119 : iterator::
120 : operator++() noexcept ->
121 : iterator&
122 : {
123 79 : BOOST_ASSERT(i_ < ph_->count);
124 79 : auto const* e = &ph_->tab()[i_];
125 79 : auto const id = e->id;
126 79 : if(id != field::unknown)
127 : {
128 72 : ++i_;
129 72 : --e;
130 93 : while(i_ != ph_->count)
131 : {
132 44 : if(e->id == id)
133 23 : break;
134 21 : ++i_;
135 21 : --e;
136 : }
137 72 : return *this;
138 : }
139 7 : auto const p =
140 7 : ph_->cbuf + ph_->prefix;
141 : auto name = core::string_view(
142 7 : 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, core::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 : core::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(
193 : core::string_view name) const noexcept
194 : {
195 5 : std::size_t n = 0;
196 49 : for(auto v : *this)
197 44 : if(grammar::ci_is_equal(
198 : v.name, name))
199 7 : ++n;
200 5 : return n;
201 : }
202 :
203 : auto
204 58 : fields_view_base::
205 : find(field id) const noexcept ->
206 : iterator
207 : {
208 58 : auto it = begin();
209 58 : auto const last = end();
210 154 : while(it != last)
211 : {
212 146 : if(it->id == id)
213 50 : break;
214 96 : ++it;
215 : }
216 58 : return it;
217 : }
218 :
219 : auto
220 66 : fields_view_base::
221 : find(
222 : core::string_view name) const noexcept ->
223 : iterator
224 : {
225 66 : auto it = begin();
226 66 : auto const last = end();
227 168 : while(it != last)
228 : {
229 160 : if(grammar::ci_is_equal(
230 320 : it->name, name))
231 58 : break;
232 102 : ++it;
233 : }
234 66 : return it;
235 : }
236 :
237 : auto
238 2 : fields_view_base::
239 : find(
240 : iterator from,
241 : field id) const noexcept ->
242 : iterator
243 : {
244 2 : auto const last = end();
245 11 : while(from != last)
246 : {
247 10 : if(from->id == id)
248 1 : break;
249 9 : ++from;
250 : }
251 2 : return from;
252 : }
253 :
254 : auto
255 2 : fields_view_base::
256 : find(
257 : iterator from,
258 : core::string_view name) const noexcept ->
259 : iterator
260 : {
261 2 : auto const last = end();
262 12 : while(from != last)
263 : {
264 11 : if(grammar::ci_is_equal(
265 22 : name, from->name))
266 1 : break;
267 10 : ++from;
268 : }
269 2 : return from;
270 : }
271 :
272 : auto
273 27 : fields_view_base::
274 : find_last(
275 : iterator it,
276 : field id) const noexcept ->
277 : iterator
278 : {
279 27 : auto const it0 = begin();
280 : for(;;)
281 : {
282 40 : if(it == it0)
283 4 : return end();
284 36 : --it;
285 36 : if(it->id == id)
286 23 : return it;
287 : }
288 : }
289 :
290 : auto
291 3 : fields_view_base::
292 : find_last(
293 : iterator it,
294 : core::string_view name) const noexcept ->
295 : iterator
296 : {
297 3 : auto const it0 = begin();
298 : for(;;)
299 : {
300 14 : if(it == it0)
301 1 : return end();
302 13 : --it;
303 13 : if(grammar::ci_is_equal(
304 26 : it->name, name))
305 2 : return it;
306 : }
307 : }
308 :
309 : core::string_view
310 2 : fields_view_base::
311 : value_or(
312 : field id,
313 : core::string_view s) const noexcept
314 : {
315 2 : auto it = find(id);
316 2 : if(it != end())
317 1 : return it->value;
318 1 : return s;
319 : }
320 :
321 : core::string_view
322 2 : fields_view_base::
323 : value_or(
324 : core::string_view name,
325 : core::string_view s) const noexcept
326 : {
327 2 : auto it = find(name);
328 2 : if(it != end())
329 1 : return it->value;
330 1 : return s;
331 : }
332 :
333 : //------------------------------------------------
334 :
335 : auto
336 16 : fields_view_base::
337 : find_all(
338 : field id) const noexcept ->
339 : subrange
340 : {
341 32 : return subrange(
342 16 : ph_, find(id).i_);
343 : }
344 :
345 : auto
346 5 : fields_view_base::
347 : find_all(
348 : core::string_view name) const noexcept ->
349 : subrange
350 : {
351 10 : return subrange(
352 5 : ph_, find(name).i_);
353 : }
354 :
355 : //------------------------------------------------
356 :
357 : } // http_proto
358 : } // boost
359 :
360 : #endif
|