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