Line data Source code
1 : // 2 : // Copyright (c) 2019 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/boostorg/url 8 : // 9 : 10 : 11 : #include <boost/url/detail/config.hpp> 12 : #include "decode.hpp" 13 : #include <boost/url/grammar/charset.hpp> 14 : #include <boost/url/grammar/hexdig_chars.hpp> 15 : #include <memory> 16 : 17 : namespace boost { 18 : namespace urls { 19 : namespace detail { 20 : 21 : char 22 794 : decode_one( 23 : char const* const it) noexcept 24 : { 25 794 : auto d0 = grammar::hexdig_value(it[0]); 26 794 : auto d1 = grammar::hexdig_value(it[1]); 27 : return static_cast<char>( 28 794 : ((static_cast< 29 794 : unsigned char>(d0) << 4) + 30 794 : (static_cast< 31 794 : unsigned char>(d1)))); 32 : } 33 : 34 : std::size_t 35 1977 : decode_bytes_unsafe( 36 : core::string_view s) noexcept 37 : { 38 1977 : auto p = s.begin(); 39 1977 : auto const end = s.end(); 40 1977 : std::size_t dn = 0; 41 1977 : if(s.size() >= 3) 42 : { 43 826 : auto const safe_end = end - 2; 44 7303 : while(p < safe_end) 45 : { 46 6477 : if(*p != '%') 47 6218 : p += 1; 48 : else 49 259 : p += 3; 50 6477 : ++dn; 51 : } 52 : } 53 1977 : dn += end - p; 54 1977 : return dn; 55 : } 56 : 57 : std::size_t 58 2711 : decode_unsafe( 59 : char* const dest0, 60 : char const* end, 61 : core::string_view s, 62 : encoding_opts opt) noexcept 63 : { 64 2711 : auto it = s.data(); 65 2711 : auto const last = it + s.size(); 66 2711 : auto dest = dest0; 67 : 68 2711 : if(opt.space_as_plus) 69 : { 70 4956 : while(it != last) 71 : { 72 4247 : if(dest == end) 73 : { 74 : // dest too small 75 0 : return dest - dest0; 76 : } 77 4247 : if(*it == '+') 78 : { 79 : // plus to space 80 5 : *dest++ = ' '; 81 5 : ++it; 82 5 : continue; 83 : } 84 4242 : if(*it == '%') 85 : { 86 : // escaped 87 105 : ++it; 88 105 : if(last - it < 2) 89 : { 90 : // missing input, 91 : // initialize output 92 0 : std::memset(dest, 93 0 : 0, end - dest); 94 0 : return dest - dest0; 95 : } 96 105 : *dest++ = decode_one(it); 97 105 : it += 2; 98 105 : continue; 99 : } 100 : // unescaped 101 4137 : *dest++ = *it++; 102 : } 103 709 : return dest - dest0; 104 : } 105 : 106 12650 : while(it != last) 107 : { 108 10648 : if(dest == end) 109 : { 110 : // dest too small 111 0 : return dest - dest0; 112 : } 113 10648 : if(*it == '%') 114 : { 115 : // escaped 116 581 : ++it; 117 581 : if(last - it < 2) 118 : { 119 : // missing input, 120 : // initialize output 121 0 : std::memset(dest, 122 0 : 0, end - dest); 123 0 : return dest - dest0; 124 : } 125 581 : *dest++ = decode_one(it); 126 581 : it += 2; 127 581 : continue; 128 : } 129 : // unescaped 130 10067 : *dest++ = *it++; 131 : } 132 2002 : return dest - dest0; 133 : } 134 : 135 : } // detail 136 : } // urls 137 : } // boost 138 :