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