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