Line data Source code
1 : //
2 : // Copyright (c) 2022 Alan de Freitas (alandefreitas@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/boostorg/url
8 : //
9 :
10 :
11 : #include <boost/url/detail/config.hpp>
12 : #include <boost/url/decode_view.hpp>
13 : #include <boost/url/grammar/hexdig_chars.hpp>
14 : #include <ostream>
15 :
16 : namespace boost {
17 : namespace urls {
18 :
19 : namespace detail {
20 :
21 : template <class T>
22 : int
23 3246 : decoded_strcmp(decode_view s0, T s1)
24 : {
25 3246 : auto const n0 = s0.size();
26 3246 : auto const n1 = s1.size();
27 3246 : auto n = (std::min)(n0, n1);
28 3246 : auto it0 = s0.begin();
29 3246 : auto it1 = s1.begin();
30 5157 : while (n--)
31 : {
32 4226 : const char c0 = *it0++;
33 4226 : const char c1 = *it1++;
34 4226 : if (c0 == c1)
35 1911 : continue;
36 2315 : return 1 - 2 * (static_cast<unsigned char>(c0)
37 4630 : < static_cast<unsigned char>(c1));
38 : }
39 931 : return 1 - (n0 == n1) - 2 * (n0 < n1);
40 : }
41 :
42 : } // detail
43 :
44 : //------------------------------------------------
45 :
46 : auto
47 6299 : decode_view::
48 : iterator::
49 : operator*() const noexcept ->
50 : reference
51 : {
52 6299 : if (space_as_plus_ &&
53 53 : *pos_ == '+')
54 6 : return ' ';
55 6293 : if (*pos_ != '%')
56 5917 : return *pos_;
57 376 : auto d0 = grammar::hexdig_value(pos_[1]);
58 376 : auto d1 = grammar::hexdig_value(pos_[2]);
59 : return static_cast<char>(
60 376 : ((static_cast<
61 376 : unsigned char>(d0) << 4) +
62 376 : (static_cast<
63 376 : unsigned char>(d1))));
64 : }
65 :
66 : // unchecked constructor
67 3773 : decode_view::
68 : decode_view(
69 : core::string_view s,
70 : std::size_t n,
71 3773 : encoding_opts opt) noexcept
72 3773 : : p_(s.data())
73 3773 : , n_(s.size())
74 3773 : , dn_(n)
75 3773 : , space_as_plus_(
76 3773 : opt.space_as_plus)
77 : {
78 3773 : }
79 :
80 : int
81 2930 : decode_view::
82 : compare(core::string_view other) const noexcept
83 : {
84 2930 : return detail::decoded_strcmp(*this, other);
85 : }
86 :
87 : int
88 316 : decode_view::
89 : compare(decode_view other) const noexcept
90 : {
91 316 : return detail::decoded_strcmp(*this, other);
92 : }
93 :
94 : void
95 2 : decode_view::
96 : write(std::ostream& os) const
97 : {
98 2 : auto it = begin();
99 2 : auto const end_ = end();
100 23 : while(it != end_)
101 21 : os.put(*it++);
102 2 : }
103 :
104 : void
105 1 : decode_view::
106 : remove_prefix( size_type n )
107 : {
108 1 : auto it = begin();
109 1 : auto n0 = n;
110 3 : while (n)
111 : {
112 2 : ++it;
113 2 : --n;
114 : }
115 1 : n_ -= (it.base() - begin().base());
116 1 : dn_ -= n0;
117 1 : p_ = it.base();
118 1 : }
119 :
120 : void
121 1 : decode_view::
122 : remove_suffix( size_type n )
123 : {
124 1 : auto it = end();
125 1 : auto n0 = n;
126 6 : while (n)
127 : {
128 5 : --it;
129 5 : --n;
130 : }
131 1 : n_ -= (end().base() - it.base());
132 1 : dn_ -= n0;
133 1 : }
134 :
135 : bool
136 3 : decode_view::
137 : starts_with( core::string_view s ) const noexcept
138 : {
139 3 : if (s.size() > size())
140 1 : return false;
141 2 : auto it0 = begin();
142 2 : auto it1 = s.begin();
143 2 : std::size_t n = s.size();
144 11 : while (n)
145 : {
146 10 : if (*it0 != *it1)
147 1 : return false;
148 9 : ++it0;
149 9 : ++it1;
150 9 : --n;
151 : }
152 1 : return true;
153 : }
154 :
155 : bool
156 3 : decode_view::
157 : ends_with( core::string_view s ) const noexcept
158 : {
159 3 : if (s.size() > size())
160 1 : return false;
161 2 : auto it0 = end();
162 2 : auto it1 = s.end();
163 2 : std::size_t n = s.size();
164 2 : --it0;
165 2 : --it1;
166 14 : while (n - 1)
167 : {
168 13 : if (*it0 != *it1)
169 1 : return false;
170 12 : --it0;
171 12 : --it1;
172 12 : --n;
173 : }
174 1 : return *it0 == *it1;
175 : }
176 :
177 : bool
178 1 : decode_view::
179 : starts_with( char ch ) const noexcept
180 : {
181 : return
182 2 : !empty() &&
183 2 : front() == ch;
184 : }
185 :
186 : bool
187 1 : decode_view::
188 : ends_with( char ch ) const noexcept
189 : {
190 : return
191 2 : !empty() &&
192 2 : back() == ch;
193 : }
194 :
195 : decode_view::const_iterator
196 2 : decode_view::
197 : find( char ch ) const noexcept
198 : {
199 2 : auto it = begin();
200 2 : auto end = this->end();
201 8 : while (it != end)
202 : {
203 7 : if (*it == ch)
204 1 : return it;
205 6 : ++it;
206 : }
207 1 : return it;
208 : }
209 :
210 : decode_view::const_iterator
211 5 : decode_view::
212 : rfind( char ch ) const noexcept
213 : {
214 5 : if (empty())
215 1 : return end();
216 4 : auto it = end();
217 4 : auto begin = this->begin();
218 4 : --it;
219 27 : while (it != begin)
220 : {
221 25 : if (*it == ch)
222 2 : return it;
223 23 : --it;
224 : }
225 2 : if (*it == ch)
226 1 : return it;
227 1 : return end();
228 : }
229 :
230 : } // urls
231 : } // boost
232 :
|