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