2023-05-22 18:45:02 +10:00

140 lines
2.9 KiB
C++

//
// Copyright (c) 2019 Vinnie Falco (vinnie.falco@gmail.com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
// Official repository: https://github.com/boostorg/url
//
#ifndef BOOST_URL_DETAIL_IMPL_DECODE_IPP
#define BOOST_URL_DETAIL_IMPL_DECODE_IPP
#include <boost/url/detail/decode.hpp>
#include <boost/url/grammar/charset.hpp>
#include <memory>
namespace boost {
namespace urls {
namespace detail {
char
decode_one(
char const* const it) noexcept
{
auto d0 = grammar::hexdig_value(it[0]);
auto d1 = grammar::hexdig_value(it[1]);
return static_cast<char>(
((static_cast<
unsigned char>(d0) << 4) +
(static_cast<
unsigned char>(d1))));
}
std::size_t
decode_bytes_unsafe(
string_view s) noexcept
{
auto p = s.begin();
auto const end = s.end();
std::size_t dn = 0;
if(s.size() >= 3)
{
auto const safe_end = end - 2;
while(p < safe_end)
{
if(*p != '%')
p += 1;
else
p += 3;
++dn;
}
}
dn += end - p;
return dn;
}
std::size_t
decode_unsafe(
char* const dest0,
char const* end,
string_view s,
encoding_opts opt) noexcept
{
auto it = s.data();
auto const last = it + s.size();
auto dest = dest0;
if(opt.space_as_plus)
{
while(it != last)
{
if(dest == end)
{
// dest too small
return dest - dest0;
}
if(*it == '+')
{
// plus to space
*dest++ = ' ';
++it;
continue;
}
if(*it == '%')
{
// escaped
++it;
if(last - it < 2)
{
// missing input,
// initialize output
std::memset(dest,
0, end - dest);
return dest - dest0;
}
*dest++ = decode_one(it);
it += 2;
continue;
}
// unescaped
*dest++ = *it++;
}
return dest - dest0;
}
while(it != last)
{
if(dest == end)
{
// dest too small
return dest - dest0;
}
if(*it == '%')
{
// escaped
++it;
if(last - it < 2)
{
// missing input,
// initialize output
std::memset(dest,
0, end - dest);
return dest - dest0;
}
*dest++ = decode_one(it);
it += 2;
continue;
}
// unescaped
*dest++ = *it++;
}
return dest - dest0;
}
} // detail
} // urls
} // boost
#endif