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
19namespace boost {
20namespace urls {
21namespace detail {
22
23char
24decode_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
36std::size_t
37decode_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
59std::size_t
60decode_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

source code of boost/libs/url/src/detail/decode.cpp