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 : , dn_(n) 75 : , 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 :