ext-boost/boost/url/pct_string_view.hpp
2023-05-22 18:45:02 +10:00

463 lines
10 KiB
C++

//
// Copyright (c) 2022 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_PCT_STRING_VIEW_HPP
#define BOOST_URL_PCT_STRING_VIEW_HPP
#include <boost/url/detail/config.hpp>
#include <boost/url/encoding_opts.hpp>
#include <boost/url/error_types.hpp>
#include <boost/url/string_view.hpp>
#include <boost/url/grammar/string_token.hpp>
#include <boost/url/grammar/string_view_base.hpp>
#include <cstddef>
#include <iterator>
#include <string>
#include <type_traits>
#include <utility>
namespace boost {
namespace urls {
//------------------------------------------------
#ifndef BOOST_URL_DOCS
class decode_view;
class pct_string_view;
pct_string_view
make_pct_string_view_unsafe(
char const*, std::size_t,
std::size_t) noexcept;
namespace detail {
string_view&
ref(pct_string_view& s) noexcept;
} // detail
#endif
//------------------------------------------------
/** A reference to a valid percent-encoded string
Objects of this type behave like a
@ref string_view and have the same interface,
but offer an additional invariant: they can
only be constructed from strings containing
valid percent-escapes.
Attempting construction from a string
containing invalid or malformed percent
escapes results in an exception.
@par Operators
The following operators are supported between
@ref pct_string_view and any object that is
convertible to @ref string_view
@code
bool operator==( pct_string_view, pct_string_view ) noexcept;
bool operator!=( pct_string_view, pct_string_view ) noexcept;
bool operator<=( pct_string_view, pct_string_view ) noexcept;
bool operator< ( pct_string_view, pct_string_view ) noexcept;
bool operator> ( pct_string_view, pct_string_view ) noexcept;
bool operator>=( pct_string_view, pct_string_view ) noexcept;
@endcode
*/
class pct_string_view final
: public grammar::string_view_base
{
std::size_t dn_ = 0;
#ifndef BOOST_URL_DOCS
friend
pct_string_view
make_pct_string_view_unsafe(
char const*, std::size_t,
std::size_t) noexcept;
friend
string_view&
detail::ref(pct_string_view&) noexcept;
#endif
// unsafe
pct_string_view(
char const* data,
std::size_t size,
std::size_t dn) noexcept
: string_view_base(data, size)
, dn_(dn)
{
}
BOOST_URL_DECL
void
decode_impl(
string_token::arg& dest,
encoding_opts opt) const;
public:
/** Constructor
Default constructed string are empty.
@par Complexity
Constant.
@par Exception Safety
Throws nothing.
*/
constexpr pct_string_view() = default;
/** Constructor
The copy references the same
underlying character buffer.
Ownership is not transferred.
@par Postconditions
@code
this->data() == other.data()
@endcode
@par Complexity
Constant.
@par Exception Safety
Throws nothing.
@par other The string to copy.
*/
constexpr
pct_string_view(
pct_string_view const& other) = default;
/** Constructor
The newly constructed string references
the specified character buffer.
Ownership is not transferred.
@par Postconditions
@code
this->data() == string_view(s).data()
@endcode
@par Complexity
Linear in `string_view(s).size()`.
@par Exception Safety
Exceptions thrown on invalid input.
@throw system_error
The string contains an invalid percent encoding.
@tparam String A type convertible to @ref string_view
@param s The string to construct from.
*/
template<
class String
#ifndef BOOST_URL_DOCS
, class = typename std::enable_if<
std::is_convertible<
String,
string_view
>::value>::type
#endif
>
pct_string_view(
String const& s)
: pct_string_view(
detail::to_sv(s))
{
}
/** Constructor (deleted)
*/
pct_string_view(
std::nullptr_t) = delete;
/** Constructor
The newly constructed string references
the specified character buffer. Ownership
is not transferred.
@par Postconditions
@code
this->data() == s && this->size() == len
@endcode
@par Complexity
Linear in `len`.
@par Exception Safety
Exceptions thrown on invalid input.
@throw system_error
The string contains an invalid percent encoding.
@param s, len The string to construct from.
*/
pct_string_view(
char const* s,
std::size_t len)
: pct_string_view(
string_view(s, len))
{
}
/** Constructor
The newly constructed string references
the specified character buffer. Ownership
is not transferred.
@par Postconditions
@code
this->data() == s.data() && this->size() == s.size()
@endcode
@par Complexity
Linear in `s.size()`.
@par Exception Safety
Exceptions thrown on invalid input.
@throw system_error
The string contains an invalid percent encoding.
@param s The string to construct from.
*/
BOOST_URL_DECL
pct_string_view(
string_view s);
/** Assignment
The copy references the same
underlying character buffer.
Ownership is not transferred.
@par Postconditions
@code
this->data() == other.data()
@endcode
@par Complexity
Constant.
@par Exception Safety
Throws nothing.
@par other The string to copy.
*/
pct_string_view& operator=(
pct_string_view const& other) = default;
friend
BOOST_URL_DECL
result<pct_string_view>
make_pct_string_view(
string_view s) noexcept;
//--------------------------------------------
/** Return the decoded size
This function returns the number of
characters in the resulting string if
percent escapes were converted into
ordinary characters.
@par Complexity
Constant.
@par Exception Safety
Throws nothing.
*/
std::size_t
decoded_size() const noexcept
{
return dn_;
}
/** Return the string as a range of decoded characters
@par Complexity
Constant.
@par Exception Safety
Throws nothing.
@see
@ref decode_view.
*/
decode_view
operator*() const noexcept;
/** Return the string with percent-decoding
This function converts percent escapes
in the string into ordinary characters
and returns the result.
When called with no arguments, the
return type is `std::string`.
Otherwise, the return type and style
of output is determined by which string
token is passed.
@par Example
@code
assert( pct_string_view( "Program%20Files" ).decode() == "Program Files" );
@endcode
@par Complexity
Linear in `this->size()`.
@par Exception Safety
Calls to allocate may throw.
String tokens may throw exceptions.
@param opt The options for encoding. If
this parameter is omitted, the default
options are used.
@param token An optional string token.
If this parameter is omitted, then
a new `std::string` is returned.
Otherwise, the function return type
is the result type of the token.
@see
@ref encoding_opts,
@ref string_token::return_string.
*/
template<BOOST_URL_STRTOK_TPARAM>
BOOST_URL_STRTOK_RETURN
decode(
encoding_opts opt = {},
BOOST_URL_STRTOK_ARG(token)) const
{
/* If you get a compile error here, it
means that the token you passed does
not meet the requirements stated
in the documentation.
*/
static_assert(
string_token::is_token<
StringToken>::value,
"Type requirements not met");
decode_impl(token, opt);
return token.result();
}
#ifndef BOOST_URL_DOCS
// arrow support
pct_string_view const*
operator->() const noexcept
{
return this;
}
#endif
//--------------------------------------------
// VFALCO No idea why this fails in msvc
/** Swap
*/
/*BOOST_CXX14_CONSTEXPR*/ void swap(
pct_string_view& s ) noexcept
{
string_view_base::swap(s);
std::swap(dn_, s.dn_);
}
};
//------------------------------------------------
#ifndef BOOST_URL_DOCS
namespace detail {
// obtain modifiable reference to
// underlying string, to handle
// self-intersection on modifiers.
inline
string_view&
ref(pct_string_view& s) noexcept
{
return s.s_;
}
} // detail
#endif
//------------------------------------------------
/** Return a valid percent-encoded string
If `s` is a valid percent-encoded string,
the function returns the buffer as a valid
view which may be used to perform decoding
or measurements.
Otherwise the result contains an error code.
Upon success, the returned view references
the original character buffer;
Ownership is not transferred.
@par Complexity
Linear in `s.size()`.
@par Exception Safety
Throws nothing.
@param s The string to validate.
*/
BOOST_URL_DECL
result<pct_string_view>
make_pct_string_view(
string_view s) noexcept;
#ifndef BOOST_URL_DOCS
// VFALCO semi-private for now
inline
pct_string_view
make_pct_string_view_unsafe(
char const* data,
std::size_t size,
std::size_t decoded_size) noexcept
{
#if 0
BOOST_ASSERT(! make_pct_string_view(
string_view(data, size)).has_error());
#endif
return pct_string_view(
data, size, decoded_size);
}
#endif
#ifndef BOOST_URL_DOCS
namespace detail {
template <>
inline
string_view
to_sv(pct_string_view const& s) noexcept
{
return s.substr();
}
} // detail
#endif
} // urls
} // boost
#endif