Line | Branch | Exec | Source |
---|---|---|---|
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 |
2/2✓ Branch 1 taken 826 times.
✓ Branch 2 taken 1151 times.
|
1977 | if(s.size() >= 3) |
42 | { | ||
43 | 826 | auto const safe_end = end - 2; | |
44 |
2/2✓ Branch 0 taken 6477 times.
✓ Branch 1 taken 826 times.
|
7303 | while(p < safe_end) |
45 | { | ||
46 |
2/2✓ Branch 0 taken 6218 times.
✓ Branch 1 taken 259 times.
|
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 | template <bool SpaceAsPlus> | ||
58 | std::size_t | ||
59 | decode_unsafe_is_plus_impl(char c); | ||
60 | |||
61 | template <> | ||
62 | std::size_t | ||
63 | 4247 | decode_unsafe_is_plus_impl<true>(char c) | |
64 | { | ||
65 | 4247 | return c == '+'; | |
66 | } | ||
67 | |||
68 | template <> | ||
69 | std::size_t | ||
70 | 10648 | decode_unsafe_is_plus_impl<false>(char) | |
71 | { | ||
72 | 10648 | return false; | |
73 | } | ||
74 | |||
75 | |||
76 | template <bool SpaceAsPlus> | ||
77 | std::size_t | ||
78 | 5422 | decode_unsafe_impl( | |
79 | char* const dest0, | ||
80 | char const* end, | ||
81 | core::string_view s) noexcept | ||
82 | { | ||
83 | 5422 | auto it = s.data(); | |
84 | 5422 | auto const last = it + s.size(); | |
85 | 5422 | auto dest = dest0; | |
86 | |||
87 |
2/2✓ Branch 0 taken 14895 times.
✓ Branch 1 taken 2711 times.
|
35212 | while(it != last) |
88 | { | ||
89 | // LCOV_EXCL_START | ||
90 | − | if(dest == end) | |
91 | { | ||
92 | /* | ||
93 | * dest too small: unreachable | ||
94 | * public functions always pass | ||
95 | * a buffer of sufficient size | ||
96 | */ | ||
97 | − | return dest - dest0; | |
98 | } | ||
99 | // LCOV_EXCL_STOP | ||
100 |
2/2✓ Branch 1 taken 5 times.
✓ Branch 2 taken 14890 times.
|
29790 | if(decode_unsafe_is_plus_impl<SpaceAsPlus>(*it)) |
101 | { | ||
102 | // plus to space | ||
103 | 10 | *dest++ = ' '; | |
104 | 10 | ++it; | |
105 | 10 | continue; | |
106 | } | ||
107 |
2/2✓ Branch 0 taken 686 times.
✓ Branch 1 taken 14204 times.
|
29780 | if(*it == '%') |
108 | { | ||
109 | // escaped | ||
110 | 1372 | ++it; | |
111 | // LCOV_EXCL_START | ||
112 | − | if(last - it < 2) | |
113 | { | ||
114 | // `%` not followed by two hex digits | ||
115 | // invalid input: unreachable | ||
116 | // public functions always pass | ||
117 | // a valid string_view. | ||
118 | // initialize output | ||
119 | − | std::memset(dest, | |
120 | − | 0, end - dest); | |
121 | − | return dest - dest0; | |
122 | } | ||
123 | // LCOV_EXCL_STOP | ||
124 | 1372 | *dest++ = decode_one(it); | |
125 | 1372 | it += 2; | |
126 | 1372 | continue; | |
127 | } | ||
128 | // unescaped | ||
129 | 28408 | *dest++ = *it++; | |
130 | } | ||
131 | 5422 | return dest - dest0; | |
132 | } | ||
133 | |||
134 | std::size_t | ||
135 | 2711 | decode_unsafe( | |
136 | char* const dest0, | ||
137 | char const* end, | ||
138 | core::string_view s, | ||
139 | encoding_opts opt) noexcept | ||
140 | { | ||
141 |
2/2✓ Branch 0 taken 709 times.
✓ Branch 1 taken 2002 times.
|
2711 | if(opt.space_as_plus) |
142 | { | ||
143 | 709 | return decode_unsafe_impl<true>( | |
144 | 709 | dest0, end, s); | |
145 | } | ||
146 | 2002 | return decode_unsafe_impl<false>( | |
147 | 2002 | dest0, end, s); | |
148 | } | ||
149 | |||
150 | } // detail | ||
151 | } // urls | ||
152 | } // boost | ||
153 | |||
154 |