Added thirdparty: boost library

This commit is contained in:
Viacheslav Demydiuk
2024-01-06 19:55:56 +02:00
parent bf49f439e1
commit bccd1e7051
15683 changed files with 3239840 additions and 0 deletions
+426
View File
@@ -0,0 +1,426 @@
//
// 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_ANY_PARAMS_ITER_HPP
#define BOOST_URL_DETAIL_ANY_PARAMS_ITER_HPP
#include <boost/url/param.hpp>
#include <boost/url/pct_string_view.hpp>
#include <boost/static_assert.hpp>
#include <cstddef>
#include <iterator>
#include <type_traits>
namespace boost {
namespace urls {
namespace detail {
//------------------------------------------------
//
// any_params_iter
//
//------------------------------------------------
/* An iterator to a type-erased,
possibly encoded sequence of
query params_ref.
*/
struct BOOST_SYMBOL_VISIBLE
any_params_iter
{
protected:
any_params_iter(
bool empty_,
core::string_view s0_ = {},
core::string_view s1_ = {}) noexcept
: s0(s0_)
, s1(s1_)
, empty(empty_)
{
}
public:
// these are adjusted
// when self-intersecting
core::string_view s0;
core::string_view s1;
// True if the sequence is empty
bool empty = false;
BOOST_URL_DECL
virtual
~any_params_iter() noexcept = 0;
// Rewind the iterator to the beginning
virtual
void
rewind() noexcept = 0;
// Measure and increment current element
// element.
// Returns false on end of range.
// n is increased by encoded size.
// Can throw on bad percent-escape
virtual
bool
measure(std::size_t& n) = 0;
// Copy and increment the current
// element. encoding is performed
// if needed.
virtual
void
copy(
char*& dest,
char const* end) noexcept = 0;
};
//------------------------------------------------
//
// query_iter
//
//------------------------------------------------
// A string of plain query params
struct BOOST_SYMBOL_VISIBLE
query_iter
: any_params_iter
{
// ne = never empty
BOOST_URL_DECL
explicit
query_iter(
core::string_view s,
bool ne = false) noexcept;
private:
core::string_view s_;
std::size_t n_;
char const* p_;
bool at_end_;
void rewind() noexcept override;
bool measure(std::size_t&) noexcept override;
void copy(char*&, char const*) noexcept override;
void increment() noexcept;
};
//------------------------------------------------
//
// param_iter
//
//------------------------------------------------
// A 1-param range allowing
// self-intersection
struct BOOST_SYMBOL_VISIBLE
param_iter
: any_params_iter
{
explicit
param_iter(
param_view const&) noexcept;
private:
bool has_value_;
bool at_end_ = false;
void rewind() noexcept override;
bool measure(std::size_t&) noexcept override;
void copy(char*&, char const*) noexcept override;
};
//------------------------------------------------
//
// params_iter_base
//
//------------------------------------------------
struct params_iter_base
{
protected:
// return encoded size
BOOST_URL_DECL
static
void
measure_impl(
std::size_t& n,
param_view const& p) noexcept;
// encode to dest
BOOST_URL_DECL
static
void
copy_impl(
char*& dest,
char const* end,
param_view const& v) noexcept;
};
//------------------------------------------------
// A range of plain query params_ref
template<class FwdIt>
struct params_iter
: any_params_iter
, private params_iter_base
{
BOOST_STATIC_ASSERT(
std::is_convertible<
typename std::iterator_traits<
FwdIt>::reference,
param_view>::value);
params_iter(
FwdIt first,
FwdIt last) noexcept
: any_params_iter(
first == last)
, it0_(first)
, it_(first)
, end_(last)
{
}
private:
FwdIt it0_;
FwdIt it_;
FwdIt end_;
void
rewind() noexcept override
{
it_ = it0_;
}
bool
measure(
std::size_t& n) noexcept override
{
if(it_ == end_)
return false;
measure_impl(n,
param_view(*it_++));
return true;
}
void
copy(
char*& dest,
char const* end) noexcept override
{
copy_impl(dest, end,
param_view(*it_++));
}
};
//------------------------------------------------
//
// param_encoded_iter
//
//------------------------------------------------
// A 1-param encoded range
// allowing self-intersection
struct BOOST_SYMBOL_VISIBLE
param_encoded_iter
: any_params_iter
{
explicit
param_encoded_iter(
param_pct_view const&) noexcept;
private:
bool has_value_;
bool at_end_ = false;
void rewind() noexcept override;
bool measure(std::size_t&) noexcept override;
void copy(char*&, char const*) noexcept override;
};
//------------------------------------------------
//
// params_encoded_iter
//
//------------------------------------------------
// Validating and copying from
// a string of encoded params
struct params_encoded_iter_base
{
protected:
BOOST_URL_DECL
static
void
measure_impl(
std::size_t& n,
param_view const& v) noexcept;
BOOST_URL_DECL
static
void
copy_impl(
char*& dest,
char const* end,
param_view const& v) noexcept;
};
//------------------------------------------------
// A range of encoded query params_ref
template<class FwdIt>
struct params_encoded_iter
: any_params_iter
, private params_encoded_iter_base
{
BOOST_STATIC_ASSERT(
std::is_convertible<
typename std::iterator_traits<
FwdIt>::reference,
param_view>::value);
params_encoded_iter(
FwdIt first,
FwdIt last) noexcept
: any_params_iter(
first == last)
, it0_(first)
, it_(first)
, end_(last)
{
}
private:
FwdIt it0_;
FwdIt it_;
FwdIt end_;
void
rewind() noexcept override
{
it_ = it0_;
}
bool
measure(
std::size_t& n) override
{
if(it_ == end_)
return false;
// throw on invalid input
measure_impl(n,
param_pct_view(
param_view(*it_++)));
return true;
}
void
copy(
char*& dest,
char const* end
) noexcept override
{
copy_impl(dest, end,
param_view(*it_++));
}
};
//------------------------------------------------
//
// param_value_iter
//
//------------------------------------------------
// An iterator which outputs
// one value on an existing key
struct param_value_iter
: any_params_iter
{
param_value_iter(
std::size_t nk,
core::string_view const& value,
bool has_value) noexcept
: any_params_iter(
false,
value)
, nk_(nk)
, has_value_(has_value)
{
}
private:
std::size_t nk_ = 0;
bool has_value_ = false;
bool at_end_ = false;
void rewind() noexcept override;
bool measure(std::size_t&) noexcept override;
void copy(char*&, char const*) noexcept override;
};
//------------------------------------------------
//
// param_encoded_value_iter
//
//------------------------------------------------
// An iterator which outputs one
// encoded value on an existing key
struct param_encoded_value_iter
: any_params_iter
{
param_encoded_value_iter(
std::size_t nk,
pct_string_view const& value,
bool has_value) noexcept
: any_params_iter(
false,
value)
, nk_(nk)
, has_value_(has_value)
{
}
private:
std::size_t nk_ = 0;
bool has_value_ = false;
bool at_end_ = false;
void rewind() noexcept override;
bool measure(std::size_t&) noexcept override;
void copy(char*&, char const*) noexcept override;
};
//------------------------------------------------
template<class FwdIt>
params_iter<FwdIt>
make_params_iter(
FwdIt first, FwdIt last)
{
return params_iter<
FwdIt>(first, last);
}
template<class FwdIt>
params_encoded_iter<FwdIt>
make_params_encoded_iter(
FwdIt first, FwdIt last)
{
return params_encoded_iter<
FwdIt>(first, last);
}
} // detail
} // urls
} // boost
#endif
+327
View File
@@ -0,0 +1,327 @@
//
// 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_ANY_SEGMENTS_ITER_HPP
#define BOOST_URL_DETAIL_ANY_SEGMENTS_ITER_HPP
#include <boost/url/pct_string_view.hpp>
#include <boost/static_assert.hpp>
#include <cstddef>
#include <iterator>
#include <type_traits>
namespace boost {
namespace urls {
namespace detail {
struct BOOST_SYMBOL_VISIBLE
any_segments_iter
{
protected:
explicit
any_segments_iter(
core::string_view s_ = {}) noexcept
: s(s_)
{
}
virtual ~any_segments_iter() = default;
public:
// this is adjusted
// when self-intersecting
core::string_view s;
// the first segment,
// to handle special cases
core::string_view front;
// quick number of segments
// 0 = zero
// 1 = one
// 2 = two, or more
int fast_nseg = 0;
// whether the segments should encode colons
// when we measure and copy. the calling
// function uses this for the first
// segment in some cases, such as:
// "x:y:z" -> remove_scheme -> "y%3Az"
// as "y:z" would no longer represent a path
bool encode_colons = false;
// Rewind the iterator to the beginning
virtual void rewind() noexcept = 0;
// Measure and increment the current
// element. n is increased by the
// encoded size. Returns false on
// end of range.
virtual bool measure(std::size_t& n) = 0;
// Copy and increment the current
// element, encoding as needed.
virtual void copy(char*& dest,
char const* end) noexcept = 0;
};
//------------------------------------------------
//
// segment_iter
//
//------------------------------------------------
// A 1-segment range
// allowing self-intersection
struct BOOST_SYMBOL_VISIBLE
segment_iter
: any_segments_iter
{
virtual ~segment_iter() = default;
explicit
segment_iter(
core::string_view s) noexcept;
private:
bool at_end_ = false;
void rewind() noexcept override;
bool measure(std::size_t&) noexcept override;
void copy(char*&, char const*) noexcept override;
};
//------------------------------------------------
//
// segments_iter
//
//------------------------------------------------
struct segments_iter_base
{
protected:
BOOST_URL_DECL static void
measure_impl(std::size_t&,
core::string_view, bool) noexcept;
BOOST_URL_DECL static void
copy_impl(char*&, char const*,
core::string_view, bool) noexcept;
};
// iterates segments in a
// plain segment range
template<class FwdIt>
struct segments_iter
: any_segments_iter
, segments_iter_base
{
BOOST_STATIC_ASSERT(
std::is_convertible<
typename std::iterator_traits<
FwdIt>::reference,
core::string_view>::value);
segments_iter(
FwdIt first,
FwdIt last) noexcept
: it_(first)
, it0_(first)
, end_(last)
{
if(first != last)
{
front = *first;
auto it = first;
if(++it == last)
fast_nseg = 1;
else
fast_nseg = 2;
}
else
{
fast_nseg = 0;
}
}
private:
FwdIt it_;
FwdIt it0_;
FwdIt end_;
void
rewind() noexcept override
{
it_ = it0_;
}
bool
measure(
std::size_t& n) noexcept override
{
if(it_ == end_)
return false;
measure_impl(n,
detail::to_sv(*it_),
encode_colons);
++it_;
return true;
}
void
copy(
char*& dest,
char const* end) noexcept override
{
copy_impl(dest, end,
detail::to_sv(*it_++),
encode_colons);
}
};
//------------------------------------------------
//
// segment_encoded_iter
//
//------------------------------------------------
// A 1-segment range
// allowing self-intersection
struct BOOST_SYMBOL_VISIBLE
segment_encoded_iter
: any_segments_iter
{
virtual ~segment_encoded_iter() = default;
explicit
segment_encoded_iter(
pct_string_view const& s) noexcept;
private:
bool at_end_ = false;
void rewind() noexcept override;
bool measure(std::size_t&) noexcept override;
void copy(char*&, char const*) noexcept override;
};
//------------------------------------------------
//
// segments_encoded_iter
//
//------------------------------------------------
// Validating and copying from
// a string of encoded segments
struct segments_encoded_iter_base
{
protected:
BOOST_URL_DECL static void
measure_impl(std::size_t&,
core::string_view, bool) noexcept;
BOOST_URL_DECL static void
copy_impl(char*&, char const*,
core::string_view, bool) noexcept;
};
// iterates segments in an
// encoded segment range
template<class FwdIt>
struct segments_encoded_iter
: public any_segments_iter
, public segments_encoded_iter_base
{
BOOST_STATIC_ASSERT(
std::is_convertible<
typename std::iterator_traits<
FwdIt>::reference,
core::string_view>::value);
segments_encoded_iter(
FwdIt first,
FwdIt last)
: it_(first)
, it0_(first)
, end_(last)
{
if(it_ != end_)
{
// throw on invalid input
front = pct_string_view(
detail::to_sv(*first));
auto it = first;
if(++it == last)
fast_nseg = 1;
else
fast_nseg = 2;
}
else
{
fast_nseg = 0;
}
}
private:
FwdIt it_;
FwdIt it0_;
FwdIt end_;
void
rewind() noexcept override
{
it_ = it0_;
}
bool
measure(
std::size_t& n) override
{
if(it_ == end_)
return false;
// throw on invalid input
measure_impl(n,
pct_string_view(
detail::to_sv(*it_++)),
encode_colons);
return true;
}
void
copy(
char*& dest,
char const* end) noexcept override
{
copy_impl(dest, end,
detail::to_sv(*it_++),
encode_colons);
}
};
//------------------------------------------------
template<class FwdIt>
segments_iter<FwdIt>
make_segments_iter(
FwdIt first, FwdIt last)
{
return segments_iter<
FwdIt>(first, last);
}
template<class FwdIt>
segments_encoded_iter<FwdIt>
make_segments_encoded_iter(
FwdIt first, FwdIt last)
{
return segments_encoded_iter<
FwdIt>(first, last);
}
} // detail
} // urls
} // boost
#endif
+144
View File
@@ -0,0 +1,144 @@
//
// Copyright (c) 2019 Vinnie Falco (vinnie.falco@gmail.com)
// Copyright (c) 2022 Alan de Freitas (alandefreitas@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_CONFIG_HPP
#define BOOST_URL_DETAIL_CONFIG_HPP
#include <boost/config.hpp>
#include <boost/config/workaround.hpp>
#include <limits.h>
#include <stdint.h>
#if CHAR_BIT != 8
# error unsupported platform
#endif
// Determine if compiling as a dynamic library
#if (defined(BOOST_URL_DYN_LINK) || defined(BOOST_ALL_DYN_LINK)) && !defined(BOOST_URL_STATIC_LINK)
# define BOOST_URL_BUILD_DLL
#endif
// Set visibility flags
#if !defined(BOOST_URL_BUILD_DLL)
# define BOOST_URL_DECL /* static library */
#elif defined(BOOST_URL_SOURCE)
# define BOOST_URL_DECL BOOST_SYMBOL_EXPORT /* source: dllexport/visibility */
#else
# define BOOST_URL_DECL BOOST_SYMBOL_IMPORT /* header: dllimport */
#endif
// Set up auto-linker
# if !defined(BOOST_URL_SOURCE) && !defined(BOOST_ALL_NO_LIB) && !defined(BOOST_URL_NO_LIB)
# define BOOST_LIB_NAME boost_url
# if defined(BOOST_ALL_DYN_LINK) || defined(BOOST_URL_DYN_LINK)
# define BOOST_DYN_LINK
# endif
# include <boost/config/auto_link.hpp>
# endif
// Set up SSE2
#if ! defined(BOOST_URL_NO_SSE2) && \
! defined(BOOST_URL_USE_SSE2)
# if (defined(_M_IX86) && _M_IX86_FP == 2) || \
defined(_M_X64) || defined(__SSE2__)
# define BOOST_URL_USE_SSE2
# endif
#endif
// constexpr
#if BOOST_WORKAROUND( BOOST_GCC_VERSION, <= 72000 ) || \
BOOST_WORKAROUND( BOOST_CLANG_VERSION, <= 35000 )
# define BOOST_URL_CONSTEXPR
#else
# define BOOST_URL_CONSTEXPR constexpr
#endif
// Add source location to error codes
#ifdef BOOST_URL_NO_SOURCE_LOCATION
# define BOOST_URL_ERR(ev) (::boost::system::error_code(ev))
# define BOOST_URL_RETURN_EC(ev) return (ev)
# define BOOST_URL_POS ::boost::source_location()
#else
# define BOOST_URL_ERR(ev) (::boost::system::error_code( (ev), [] { \
static constexpr auto loc((BOOST_CURRENT_LOCATION)); \
return &loc; }()))
# define BOOST_URL_RETURN_EC(ev) \
static constexpr auto loc ## __LINE__((BOOST_CURRENT_LOCATION)); \
return ::boost::system::error_code((ev), &loc ## __LINE__)
# define BOOST_URL_POS (BOOST_CURRENT_LOCATION)
#endif
// String token parameters
#ifndef BOOST_URL_STRTOK_TPARAM
#define BOOST_URL_STRTOK_TPARAM class StringToken = string_token::return_string
#endif
#ifndef BOOST_URL_STRTOK_RETURN
#define BOOST_URL_STRTOK_RETURN typename StringToken::result_type
#endif
#ifndef BOOST_URL_STRTOK_ARG
#define BOOST_URL_STRTOK_ARG(name) StringToken&& token = {}
#endif
// Move
#if BOOST_WORKAROUND( BOOST_GCC_VERSION, < 80000 ) || \
BOOST_WORKAROUND( BOOST_CLANG_VERSION, < 30900 )
#define BOOST_URL_RETURN(x) return std::move((x))
#else
#define BOOST_URL_RETURN(x) return (x)
#endif
// Limit tests
#ifndef BOOST_URL_MAX_SIZE
// we leave room for a null,
// and still fit in size_t
#define BOOST_URL_MAX_SIZE ((std::size_t(-1))-1)
#endif
// noinline attribute
#ifdef BOOST_GCC
#define BOOST_URL_NO_INLINE [[gnu::noinline]]
#else
#define BOOST_URL_NO_INLINE
#endif
// libstdcxx copy-on-write strings
#ifndef BOOST_URL_COW_STRINGS
#if defined(BOOST_LIBSTDCXX_VERSION) && (BOOST_LIBSTDCXX_VERSION < 60000 || (defined(_GLIBCXX_USE_CXX11_ABI) && _GLIBCXX_USE_CXX11_ABI == 0))
#define BOOST_URL_COW_STRINGS
#endif
#endif
// detect 32/64 bit
#if UINTPTR_MAX == UINT64_MAX
# define BOOST_URL_ARCH 64
#elif UINTPTR_MAX == UINT32_MAX
# define BOOST_URL_ARCH 32
#else
# error Unknown or unsupported architecture, please open an issue
#endif
// deprecated attribute
#if defined(BOOST_MSVC) || defined(BOOST_URL_DOCS)
#define BOOST_URL_DEPRECATED(msg)
#else
#define BOOST_URL_DEPRECATED(msg) BOOST_DEPRECATED(msg)
#endif
// avoid Boost.TypeTraits for these traits
namespace boost {
namespace urls {
template<class...> struct make_void { typedef void type; };
template<class... Ts> using void_t = typename make_void<Ts...>::type;
} // urls
} // boost
#endif
+44
View File
@@ -0,0 +1,44 @@
//
// Copyright (c) 2019 Vinnie Falco (vinnie.falco@gmail.com)
// Copyright (c) 2022 Alan de Freitas (alandefreitas@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_DECODE_HPP
#define BOOST_URL_DETAIL_DECODE_HPP
#include <boost/url/encoding_opts.hpp>
#include <boost/core/detail/string_view.hpp>
#include <cstdlib>
namespace boost {
namespace urls {
namespace detail {
BOOST_URL_DECL
char
decode_one(
char const* it) noexcept;
BOOST_URL_DECL
std::size_t
decode_bytes_unsafe(
core::string_view s) noexcept;
BOOST_URL_DECL
std::size_t
decode_unsafe(
char* dest,
char const* end,
core::string_view s,
encoding_opts opt = {}) noexcept;
} // detail
} // urls
} // boost
#endif
+205
View File
@@ -0,0 +1,205 @@
//
// Copyright (c) 2019 Vinnie Falco (vinnie.falco@gmail.com)
// Copyright (c) 2022 Alan de Freitas (alandefreitas@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_ENCODE_HPP
#define BOOST_URL_DETAIL_ENCODE_HPP
#include <boost/url/encoding_opts.hpp>
#include <boost/url/pct_string_view.hpp>
#include <boost/url/grammar/hexdig_chars.hpp>
#include <boost/core/ignore_unused.hpp>
#include <cstdlib>
namespace boost {
namespace urls {
namespace detail {
constexpr
char const* const hexdigs[] = {
"0123456789ABCDEF",
"0123456789abcdef" };
//------------------------------------------------
// re-encode is to percent-encode a
// string that can already contain
// escapes. Characters not in the
// unreserved set are escaped, and
// escapes are passed through unchanged.
//
template<class CharSet>
std::size_t
re_encoded_size_unsafe(
core::string_view s,
CharSet const& unreserved,
encoding_opts opt) noexcept
{
std::size_t n = 0;
auto const end = s.end();
auto it = s.begin();
if(opt.space_as_plus)
{
while(it != end)
{
if(*it != '%')
{
if( unreserved(*it)
|| *it == ' ')
n += 1;
else
n += 3;
++it;
}
else
{
BOOST_ASSERT(end - it >= 3);
BOOST_ASSERT(
grammar::hexdig_value(
it[1]) >= 0);
BOOST_ASSERT(
grammar::hexdig_value(
it[2]) >= 0);
n += 3;
it += 3;
}
}
}
else
{
while(it != end)
{
if(*it != '%')
{
if(unreserved(*it))
n += 1;
else
n += 3;
++it;
}
else
{
BOOST_ASSERT(end - it >= 3);
BOOST_ASSERT(
grammar::hexdig_value(
it[1]) >= 0);
BOOST_ASSERT(
grammar::hexdig_value(
it[2]) >= 0);
n += 3;
it += 3;
}
}
}
return n;
}
// unchecked
// returns decoded size
template<class CharSet>
std::size_t
re_encode_unsafe(
char*& dest_,
char const* const end,
core::string_view s,
CharSet const& unreserved,
encoding_opts opt) noexcept
{
char const* const hex =
detail::hexdigs[opt.lower_case];
auto const encode = [end, hex](
char*& dest,
unsigned char c) noexcept
{
ignore_unused(end);
*dest++ = '%';
BOOST_ASSERT(dest != end);
*dest++ = hex[c>>4];
BOOST_ASSERT(dest != end);
*dest++ = hex[c&0xf];
};
ignore_unused(end);
auto dest = dest_;
auto const dest0 = dest;
auto const last = s.end();
std::size_t dn = 0;
auto it = s.begin();
if(opt.space_as_plus)
{
while(it != last)
{
BOOST_ASSERT(dest != end);
if(*it != '%')
{
if(*it == ' ')
{
*dest++ = '+';
}
else if(unreserved(*it))
{
*dest++ = *it;
}
else
{
encode(dest, *it);
dn += 2;
}
++it;
}
else
{
*dest++ = *it++;
BOOST_ASSERT(dest != end);
*dest++ = *it++;
BOOST_ASSERT(dest != end);
*dest++ = *it++;
dn += 2;
}
}
}
else
{
while(it != last)
{
BOOST_ASSERT(dest != end);
if(*it != '%')
{
if(unreserved(*it))
{
*dest++ = *it;
}
else
{
encode(dest, *it);
dn += 2;
}
++it;
}
else
{
*dest++ = *it++;
BOOST_ASSERT(dest != end);
*dest++ = *it++;
BOOST_ASSERT(dest != end);
*dest++ = *it++;
dn += 2;
}
}
}
dest_ = dest;
return dest - dest0 - dn;
}
} // detail
} // urls
} // boost
#endif
+48
View File
@@ -0,0 +1,48 @@
//
// 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_EXCEPT_HPP
#define BOOST_URL_DETAIL_EXCEPT_HPP
#include <boost/url/error_types.hpp>
#include <boost/assert/source_location.hpp>
namespace boost {
namespace urls {
namespace detail {
BOOST_URL_DECL void BOOST_NORETURN
throw_system_error(
system::error_code const& ec,
source_location const& loc =
BOOST_URL_POS);
BOOST_URL_DECL void BOOST_NORETURN
throw_errc(
boost::system::errc::errc_t ev,
source_location const& loc =
BOOST_URL_POS);
//-----
BOOST_URL_DECL void BOOST_NORETURN
throw_invalid_argument(
source_location const& loc =
BOOST_URL_POS);
BOOST_URL_DECL void BOOST_NORETURN
throw_length_error(
source_location const& loc =
BOOST_URL_POS);
} // detail
} // urls
} // boost
#endif
+340
View File
@@ -0,0 +1,340 @@
//
// Copyright (c) 2022 Alan de Freitas (alandefreitas@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_FORMAT_ARGS_HPP
#define BOOST_URL_DETAIL_FORMAT_ARGS_HPP
#include <boost/url/detail/encode.hpp>
#include <boost/url/grammar/lut_chars.hpp>
#include <boost/core/ignore_unused.hpp>
#include <array>
// This file implements functions and classes to
// type-erase format arguments.
namespace boost {
namespace urls {
namespace detail {
// state of the format string. It basically keeps
// track of where we are in the format string.
class format_parse_context
{
char const* begin_;
char const* end_;
std::size_t arg_id_ = 0;
public:
constexpr
format_parse_context(
char const* first,
char const* last,
std::size_t arg_id = 0)
: begin_( first )
, end_( last )
, arg_id_( arg_id )
{}
constexpr
format_parse_context(
core::string_view fmt,
std::size_t arg_id = 0)
: format_parse_context(
fmt.data(),
fmt.data() + fmt.size(),
arg_id )
{}
constexpr
char const*
begin() const noexcept
{
return begin_;
}
constexpr
char const*
end() const noexcept
{
return end_;
}
BOOST_CXX14_CONSTEXPR
void
advance_to( char const* it )
{
begin_ = it;
}
std::size_t
next_arg_id()
{
return arg_id_++;
}
};
// State of the destination string
class format_context;
class measure_context;
struct ignore_format {};
template <class T>
struct named_arg
{
core::string_view name;
T const& value;
named_arg(core::string_view n, T const& v)
: name(n)
, value(v)
{}
};
// A type erased format argument
class format_arg
{
void const* arg_;
void (*measure_)(
format_parse_context&,
measure_context&,
grammar::lut_chars const&,
void const* );
void (*fmt_)(
format_parse_context&,
format_context&,
grammar::lut_chars const&,
void const* );
core::string_view name_;
std::size_t value_ = 0;
bool ignore_ = false;
template <class A>
static
void
measure_impl(
format_parse_context& pctx,
measure_context& mctx,
grammar::lut_chars const& cs,
void const* a );
template <class A>
static
void
format_impl(
format_parse_context& pctx,
format_context& fctx,
grammar::lut_chars const& cs,
void const* a );
public:
template<class A>
format_arg( A&& a );
template<class A>
format_arg( named_arg<A>&& a );
template<class A>
format_arg( core::string_view name, A&& a );
format_arg()
: format_arg(ignore_format{})
{}
explicit
operator bool() const noexcept
{
return !ignore_;
}
void
measure(
format_parse_context& pctx,
measure_context& mctx,
grammar::lut_chars const& cs)
{
measure_( pctx, mctx, cs, arg_ );
}
void
format(
format_parse_context& pctx,
format_context& fctx,
grammar::lut_chars const& cs )
{
fmt_( pctx, fctx, cs, arg_ );
}
core::string_view
name() const
{
return name_;
}
std::size_t
value() const
{
return value_;
}
};
// create temp stack storage for type erased args
template< class... Args >
std::array<format_arg, sizeof...(Args)>
make_format_args( Args&&... args )
{
return {{ std::forward<Args>(args)... }};
}
// reference to an array of format_args
class format_args
{
format_arg const* p_{nullptr};
std::size_t n_{0};
public:
format_args(
detail::format_arg const* first,
detail::format_arg const* last ) noexcept
: p_(first)
, n_(static_cast<std::size_t>(last - first))
{}
template < std::size_t N >
format_args( std::array<format_arg, N> const& store ) noexcept
: p_(store.data())
, n_(store.size())
{}
format_arg
get( std::size_t i ) const noexcept
{
if (i < n_)
return p_[i];
return {};
}
format_arg
get( core::string_view name ) const noexcept
{
for (std::size_t i = 0; i < n_; ++i)
{
if (p_[i].name() == name)
return p_[i];
}
return {};
}
};
// define the format_context after format_args
class format_context
{
format_args args_;
char* out_;
public:
format_context(
char* out,
format_args args )
: args_( args )
, out_( out )
{}
format_args
args() const noexcept
{
return args_;
}
format_arg
arg( std::size_t id ) const noexcept
{
return args_.get( id );
}
format_arg
arg( core::string_view name ) const noexcept
{
return args_.get( name );
}
char*
out()
{
return out_;
}
void
advance_to( char* it )
{
out_ = it;
}
};
// define the measure_context after format_args
class measure_context
{
format_args args_;
std::size_t out_;
public:
measure_context(
format_args args )
: measure_context(0, args)
{}
measure_context(
std::size_t out,
format_args args )
: args_( args )
, out_( out )
{}
format_args
args() const noexcept
{
return args_;
}
format_arg
arg( std::size_t id ) const noexcept
{
return args_.get( id );
}
format_arg
arg( core::string_view name ) const noexcept
{
return args_.get( name );
}
std::size_t
out()
{
return out_;
}
void
advance_to( std::size_t n )
{
out_ = n;
}
};
// fwd declare the formatter
template <class T, class = void>
struct formatter;
} // detail
} // url
} // boost
#include <boost/url/detail/impl/format_args.hpp>
#endif
+416
View File
@@ -0,0 +1,416 @@
//
// Copyright (c) 2022 Alan de Freitas (alandefreitas@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_FORMAT_ARGS_HPP
#define BOOST_URL_DETAIL_IMPL_FORMAT_ARGS_HPP
namespace boost {
namespace urls {
namespace detail {
template<
class A,
typename std::enable_if<
!std::is_integral<
typename std::decay<A>::type>::value,
int>::type = 0>
std::size_t
get_uvalue( A&& )
{
return 0;
}
template<
class A,
typename std::enable_if<
std::is_integral<
typename std::decay<A>::type>::value &&
std::is_signed<
typename std::decay<A>::type>::value,
int>::type = 0>
std::size_t
get_uvalue( A&& a )
{
if (a > 0)
return static_cast<std::size_t>(a);
return 0;
}
template<
class A,
typename std::enable_if<
std::is_integral<
typename std::decay<A>::type>::value &&
std::is_unsigned<
typename std::decay<A>::type>::value,
int>::type = 0>
std::size_t
get_uvalue( A&& a )
{
return static_cast<std::size_t>(a);
}
BOOST_URL_DECL
std::size_t
get_uvalue( core::string_view a );
BOOST_URL_DECL
std::size_t
get_uvalue( char a );
template<class A>
format_arg::
format_arg( A&& a )
: arg_( &a )
, measure_( &measure_impl<A> )
, fmt_( &format_impl<A> )
, value_( get_uvalue(std::forward<A>(a) ))
, ignore_( std::is_same<A, ignore_format>::value )
{}
template<class A>
format_arg::
format_arg( named_arg<A>&& a )
: arg_( &a.value )
, measure_( &measure_impl<A> )
, fmt_( &format_impl<A> )
, name_( a.name )
, value_( get_uvalue(a.value))
{}
template<class A>
format_arg::
format_arg( core::string_view name, A&& a )
: arg_( &a )
, measure_( &measure_impl<A> )
, fmt_( &format_impl<A> )
, name_( name )
, value_( get_uvalue(a) )
{}
// define the type-erased implementations that
// depends on everything: the context types,
// formatters, and type erased args
template <class A>
void
format_arg::
measure_impl(
format_parse_context& pctx,
measure_context& mctx,
grammar::lut_chars const& cs,
void const* a )
{
using ref_t = typename std::remove_reference<A>::type;
A const& ref = *static_cast<ref_t*>(
const_cast<void*>( a ) );
formatter<ref_t> f;
pctx.advance_to( f.parse(pctx) );
mctx.advance_to( f.measure( ref, mctx, cs ) );
}
template <class A>
void
format_arg::
format_impl(
format_parse_context& pctx,
format_context& fctx,
grammar::lut_chars const& cs,
void const* a )
{
using ref_t = typename std::remove_reference<A>::type;
A const& ref = *static_cast<ref_t*>(
const_cast<void*>( a ) );
formatter<ref_t> f;
pctx.advance_to( f.parse(pctx) );
fctx.advance_to( f.format( ref, fctx, cs ) );
}
// We point to formatter<ignore_format> where
// the format_arg variant would store monostate
template <>
struct formatter<ignore_format>
{
public:
char const*
parse(format_parse_context& ctx) const
{
return parse_empty_spec(
ctx.begin(), ctx.end());
}
std::size_t
measure(
ignore_format,
measure_context& ctx,
grammar::lut_chars const&) const
{
return ctx.out();
}
char*
format(
ignore_format,
format_context& ctx,
grammar::lut_chars const&) const
{
return ctx.out();
}
// We ignore the modifiers in all replacements
// for now
static
char const*
parse_empty_spec(
char const* it,
char const* end)
{
// [it, end] -> "} suffix"
BOOST_ASSERT(it != end);
ignore_unused(end);
// Should be always empty/valid as an
// implementation detail
BOOST_ASSERT(*it == '}');
/*
if (*it != '}')
urls::detail::throw_invalid_argument();
*/
return it;
}
};
inline
std::size_t
measure_one(
char c,
grammar::lut_chars const& unreserved)
{
// '%' must be reserved
BOOST_ASSERT(! unreserved('%'));
return 1 + !unreserved(c) * 2;
}
inline
void
encode_one(
char*& out,
char c,
grammar::lut_chars const& unreserved)
{
// '%' must be reserved
BOOST_ASSERT(! unreserved('%'));
if(unreserved(c))
{
*out++ = c;
return;
}
*out++ = '%';
*out++ = urls::detail::hexdigs[0][c>>4];
*out++ = urls::detail::hexdigs[0][c&0xf];
}
// get an unsigned value from format_args
BOOST_URL_DECL
void
get_width_from_args(
std::size_t arg_idx,
core::string_view arg_name,
format_args args,
std::size_t& w);
// formatter for string view
template <>
struct formatter<core::string_view>
{
private:
char fill = ' ';
char align = '\0';
std::size_t width = 0;
std::size_t width_idx = std::size_t(-1);
core::string_view width_name;
public:
BOOST_URL_DECL
char const*
parse(format_parse_context& ctx);
BOOST_URL_DECL
std::size_t
measure(
core::string_view str,
measure_context& ctx,
grammar::lut_chars const& cs) const;
BOOST_URL_DECL
char*
format(
core::string_view str,
format_context& ctx,
grammar::lut_chars const& cs) const;
};
// formatter for anything convertible to a
// string view
template <class T>
struct formatter<
T, typename std::enable_if<
std::is_convertible<
T, core::string_view>::value>::type>
{
formatter<core::string_view> impl_;
public:
char const*
parse(format_parse_context& ctx)
{
return impl_.parse(ctx);
}
std::size_t
measure(
core::string_view str,
measure_context& ctx,
grammar::lut_chars const& cs) const
{
return impl_.measure(str, ctx, cs);
}
char*
format(core::string_view str, format_context& ctx, grammar::lut_chars const& cs) const
{
return impl_.format(str, ctx, cs);
}
};
template <>
struct formatter<char>
{
formatter<core::string_view> impl_;
public:
char const*
parse(format_parse_context& ctx)
{
return impl_.parse(ctx);
}
std::size_t
measure(
char c,
measure_context& ctx,
grammar::lut_chars const& cs) const
{
return impl_.measure({&c, 1}, ctx, cs);
}
char*
format(
char c,
format_context& ctx,
grammar::lut_chars const& cs) const
{
return impl_.format({&c, 1}, ctx, cs);
}
};
// formatters for a single integer
class integer_formatter_impl
{
char fill = ' ';
char align = '\0';
char sign = '-';
bool zeros = false;
std::size_t width = 0;
std::size_t width_idx = std::size_t(-1);
core::string_view width_name;
public:
BOOST_URL_DECL
char const*
parse(format_parse_context& ctx);
BOOST_URL_DECL
std::size_t
measure(
unsigned long long int v,
measure_context& ctx,
grammar::lut_chars const& cs) const;
BOOST_URL_DECL
std::size_t
measure(
long long int v,
measure_context& ctx,
grammar::lut_chars const& cs) const;
BOOST_URL_DECL
char*
format(
unsigned long long int v,
format_context& ctx,
grammar::lut_chars const& cs) const;
BOOST_URL_DECL
char*
format(
long long int v,
format_context& ctx,
grammar::lut_chars const& cs) const;
};
template <class T>
struct formatter<
T, typename std::enable_if<
mp11::mp_contains<mp11::mp_list<
short int,
int,
long int,
long long int,
unsigned short int,
unsigned int,
unsigned long int,
unsigned long long int>, T>::value>::type>
{
private:
integer_formatter_impl impl_;
using base_value_type = typename std::conditional<
std::is_unsigned<T>::value,
unsigned long long int,
long long int
>::type;
public:
char const*
parse(format_parse_context& ctx)
{
return impl_.parse(ctx);
}
std::size_t
measure(
T v,
measure_context& ctx,
grammar::lut_chars const& cs) const
{
return impl_.measure(
static_cast<base_value_type>(v), ctx, cs);
}
char*
format(T v, format_context& ctx, grammar::lut_chars const& cs) const
{
return impl_.format(
static_cast<base_value_type>(v), ctx, cs);
}
};
} // detail
} // url
} // boost
#endif
+90
View File
@@ -0,0 +1,90 @@
//
// 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_MOVE_CHARS_HPP
#define BOOST_URL_DETAIL_MOVE_CHARS_HPP
#include <boost/core/detail/string_view.hpp>
#include <boost/assert.hpp>
#include <cstring>
#include <functional>
namespace boost {
namespace urls {
namespace detail {
// Moves characters, and adjusts any passed
// views if they point to any moved characters.
// true if s completely overlapped by buf
inline
bool
is_overlapping(
core::string_view buf,
core::string_view s) noexcept
{
auto const b0 = buf.data();
auto const e0 = b0 + buf.size();
auto const b1 = s.data();
auto const e1 = b1 + s.size();
auto const less_equal =
std::less_equal<char const*>();
if(less_equal(e0, b1))
return false;
if(less_equal(e1, b0))
return false;
// partial overlap is undefined
BOOST_ASSERT(less_equal(e1, e0));
BOOST_ASSERT(less_equal(b0, b1));
return true;
}
inline
void
move_chars_impl(
std::ptrdiff_t,
core::string_view const&) noexcept
{
}
template<class... Sn>
void
move_chars_impl(
std::ptrdiff_t d,
core::string_view const& buf,
core::string_view& s,
Sn&... sn) noexcept
{
if(is_overlapping(buf, s))
s = {s.data() + d, s.size()};
move_chars_impl(d, buf, sn...);
}
template<class... Args>
void
move_chars(
char* dest,
char const* src,
std::size_t n,
Args&... args) noexcept
{
core::string_view buf(src, n);
move_chars_impl(
dest - src,
core::string_view(src, n),
args...);
std::memmove(
dest, src, n);
}
} // detail
} // urls
} // boost
#endif
+179
View File
@@ -0,0 +1,179 @@
//
// Copyright (c) 2016-2019 Vinnie Falco (vinnie dot falco at gmail dot com)
// Copyright (c) 2022 Alan de Freitas (alandefreitas@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_NORMALIZED_HPP
#define BOOST_URL_DETAIL_NORMALIZED_HPP
#include <boost/core/detail/string_view.hpp>
#include <boost/url/segments_encoded_view.hpp>
#include <boost/url/detail/normalize.hpp>
namespace boost {
namespace urls {
namespace detail {
class fnv_1a
{
public:
using digest_type = std::size_t;
#if BOOST_URL_ARCH == 64
static constexpr std::size_t const prime =
static_cast<std::size_t>(0x100000001B3ULL);
static constexpr std::size_t init_hash =
static_cast<std::size_t>(0xcbf29ce484222325ULL);
#else
static constexpr std::size_t const prime =
static_cast<std::size_t>(0x01000193UL);
static constexpr std::size_t init_hash =
static_cast<std::size_t>(0x811C9DC5UL);
#endif
explicit
fnv_1a(std::size_t salt) noexcept
: h_(init_hash + salt)
{
}
void
put(char c) noexcept
{
h_ ^= c;
h_ *= prime;
}
void
put(core::string_view s) noexcept
{
for (char c: s)
{
put(c);
}
}
digest_type
digest() const noexcept
{
return h_;
}
private:
std::size_t h_;
};
void
pop_encoded_front(
core::string_view& s,
char& c,
std::size_t& n) noexcept;
// compare two core::string_views as if they are both
// percent-decoded
int
compare_encoded(
core::string_view lhs,
core::string_view rhs) noexcept;
// digest a core::string_view as if it were
// percent-decoded
void
digest_encoded(
core::string_view s,
fnv_1a& hasher) noexcept;
void
digest(
core::string_view s,
fnv_1a& hasher) noexcept;
// check if core::string_view lhs starts with core::string_view
// rhs as if they are both percent-decoded. If
// lhs starts with rhs, return number of chars
// matched in the encoded core::string_view
std::size_t
path_starts_with(
core::string_view lhs,
core::string_view rhs) noexcept;
// check if core::string_view lhs ends with core::string_view
// rhs as if they are both percent-decoded. If
// lhs ends with rhs, return number of chars
// matched in the encoded core::string_view
std::size_t
path_ends_with(
core::string_view lhs,
core::string_view rhs) noexcept;
// compare two core::string_views as if they are both
// percent-decoded and lowercase
int
ci_compare_encoded(
core::string_view lhs,
core::string_view rhs) noexcept;
// digest a core::string_view as if it were decoded
// and lowercase
void
ci_digest_encoded(
core::string_view s,
fnv_1a& hasher) noexcept;
// compare two ascii core::string_views
int
compare(
core::string_view lhs,
core::string_view rhs) noexcept;
// compare two core::string_views as if they are both
// lowercase
int
ci_compare(
core::string_view lhs,
core::string_view rhs) noexcept;
// digest a core::string_view as if it were lowercase
void
ci_digest(
core::string_view s,
fnv_1a& hasher) noexcept;
BOOST_URL_DECL
std::size_t
remove_dot_segments(
char* dest,
char const* end,
core::string_view s) noexcept;
void
pop_last_segment(
core::string_view& s,
core::string_view& c,
std::size_t& level,
bool r) noexcept;
char
path_pop_back( core::string_view& s );
void
normalized_path_digest(
core::string_view s,
bool remove_unmatched,
fnv_1a& hasher) noexcept;
int
segments_compare(
segments_encoded_view seg0,
segments_encoded_view seg1) noexcept;
} // detail
} // urls
} // boost
#endif
+99
View File
@@ -0,0 +1,99 @@
//
// Copyright (c) 2022 Alan de Freitas (alandefreitas@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_OPTIONAL_STRING_HPP
#define BOOST_URL_DETAIL_OPTIONAL_STRING_HPP
#include <boost/url/detail/string_view.hpp>
#include <boost/core/detail/string_view.hpp>
namespace boost {
namespace urls {
#ifndef BOOST_URL_DOCS
struct no_value_t;
#endif
namespace detail {
struct optional_string
{
core::string_view s;
bool b = false;
};
template <class String>
typename std::enable_if<
std::is_convertible<String, core::string_view>::value,
optional_string>::type
get_optional_string(
String const& s)
{
optional_string r;
r.s = s;
r.b = true;
return r;
}
template <class T, class = void>
struct is_dereferenceable : std::false_type
{};
template <class T>
struct is_dereferenceable<
T,
void_t<
decltype(*std::declval<T>())
>> : std::true_type
{};
template <class OptionalString>
typename std::enable_if<
!std::is_convertible<OptionalString, core::string_view>::value,
optional_string>::type
get_optional_string(
OptionalString const& opt)
{
// If this goes off, it means the rule
// passed in did not meet the requirements.
// Please check the documentation of functions
// that call get_optional_string.
static_assert(
is_dereferenceable<OptionalString>::value &&
std::is_constructible<bool, OptionalString>::value &&
!std::is_convertible<OptionalString, core::string_view>::value &&
std::is_convertible<typename std::decay<decltype(*std::declval<OptionalString>())>::type, core::string_view>::value,
"OptionalString requirements not met");
optional_string r;
r.s = opt ? detail::to_sv(*opt) : core::string_view{};
r.b = static_cast<bool>(opt);
return r;
}
inline
optional_string
get_optional_string(
std::nullptr_t)
{
return {};
}
inline
optional_string
get_optional_string(
no_value_t const&)
{
return {};
}
} // detail
} // urls
} // boost
#endif
+165
View File
@@ -0,0 +1,165 @@
//
// 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_OVER_ALLOCATOR_HPP
#define BOOST_URL_DETAIL_OVER_ALLOCATOR_HPP
#include <boost/config.hpp>
#include <boost/core/empty_value.hpp>
#include <boost/assert.hpp>
#include <boost/type_traits/is_final.hpp>
#include <boost/type_traits/type_with_alignment.hpp>
#ifdef BOOST_NO_CXX11_ALLOCATOR
# include <boost/core/allocator_traits.hpp>
#endif
#include <cstddef>
#include <memory>
#include <type_traits>
#include <utility>
namespace boost {
namespace urls {
namespace detail {
// This is a workaround for allocator_traits
// implementations which falsely claim C++11
// compatibility.
#ifdef BOOST_NO_CXX11_ALLOCATOR
template<class Alloc>
using allocator_traits =
boost::allocator_traits<Alloc>;
#else
template<class Alloc>
using allocator_traits = std::allocator_traits<Alloc>;
#endif
template<class T, class Allocator>
class over_allocator
: private empty_value<Allocator>
{
template<class U, class OtherAlloc>
friend class over_allocator;
std::size_t extra_;
public:
using is_always_equal = std::false_type;
using value_type = typename
allocator_traits<typename allocator_traits<
Allocator>::template rebind_alloc<T>>::value_type;
using pointer = typename
allocator_traits<typename allocator_traits<
Allocator>::template rebind_alloc<T>>::pointer;
using const_pointer = typename
allocator_traits<typename allocator_traits<
Allocator>::template rebind_alloc<T>>::const_pointer;
using size_type = typename
allocator_traits<typename allocator_traits<
Allocator>::template rebind_alloc<T>>::size_type;
using difference_type = typename
allocator_traits<typename allocator_traits<
Allocator>::template rebind_alloc<T>>::difference_type;
template<class U>
struct rebind
{
using other = over_allocator<U, Allocator>;
};
over_allocator(
std::size_t extra,
Allocator const& alloc)
: empty_value<Allocator>(
empty_init, alloc)
, extra_(extra)
{
}
template<class U>
over_allocator(over_allocator<U, Allocator> const& other) noexcept
: empty_value<Allocator>(
empty_init, other.get())
, extra_(other.extra_)
{
}
pointer
allocate(size_type n)
{
BOOST_ASSERT(n == 1);
using U = typename boost::type_with_alignment<
alignof(value_type)>::type;
auto constexpr S = sizeof(U);
using A = typename allocator_traits<
Allocator>::template rebind_alloc<U>;
A a(this->get());
return reinterpret_cast<pointer>(
std::allocator_traits<A>::allocate(a,
(n * sizeof(value_type) + extra_ + S - 1) / S));
}
void
deallocate(pointer p, size_type n)
{
BOOST_ASSERT(n == 1);
using U = typename boost::type_with_alignment<
alignof(value_type)>::type;
auto constexpr S = sizeof(U);
using A = typename allocator_traits<
Allocator>::template rebind_alloc<U>;
A a{this->get()};
std::allocator_traits<A>::deallocate(a,
reinterpret_cast<U*>(p),
(n * sizeof(value_type) + extra_ + S - 1) / S);
}
#if defined(BOOST_LIBSTDCXX_VERSION) && BOOST_LIBSTDCXX_VERSION < 60000
template<class U, class... Args>
void
construct(U* ptr, Args&&... args)
{
::new((void*)ptr) U(std::forward<Args>(args)...);
}
template<class U>
void
destroy(U* ptr)
{
ptr->~U();
}
#endif
template<class U>
friend
bool
operator==(
over_allocator const& lhs,
over_allocator<U, Allocator> const& rhs)
{
return
lhs.get() == rhs.get() &&
lhs.extra_ == rhs.extra_;
}
template<class U>
friend
bool
operator!=(
over_allocator const& lhs,
over_allocator<U, Allocator> const& rhs)
{
return ! (lhs == rhs);
}
};
} // detail
} // urls
} // boost
#endif
+84
View File
@@ -0,0 +1,84 @@
//
// 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_PARAMS_ITER_IMPL_HPP
#define BOOST_URL_DETAIL_PARAMS_ITER_IMPL_HPP
#include <boost/url/param.hpp>
#include <boost/url/detail/parts_base.hpp>
#include <boost/url/detail/url_impl.hpp>
#include <boost/assert.hpp>
namespace boost {
namespace urls {
namespace detail {
struct BOOST_URL_DECL params_iter_impl
: parts_base
{
query_ref ref;
std::size_t index = 0;
std::size_t pos;
std::size_t nk;
std::size_t nv;
std::size_t dk;
std::size_t dv;
params_iter_impl() = default;
params_iter_impl(
params_iter_impl const&) = default;
params_iter_impl& operator=(
params_iter_impl const&) = default;
// begin
params_iter_impl(
query_ref const&) noexcept;
// end
params_iter_impl(
query_ref const&,
int) noexcept;
// at index
params_iter_impl(
query_ref const&,
std::size_t,
std::size_t) noexcept;
void setup() noexcept;
void increment() noexcept;
void decrement() noexcept;
param_pct_view
dereference() const noexcept;
pct_string_view key() const noexcept;
auto
next() const noexcept ->
params_iter_impl
{
auto next = *this;
next.increment();
return next;
}
bool
equal(
params_iter_impl const&
other) const noexcept
{
// different containers
BOOST_ASSERT(ref.alias_of(other.ref));
return index == other.index;
}
};
} // detail
} // urls
} // boost
#endif
+53
View File
@@ -0,0 +1,53 @@
//
// 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_PARTS_BASE_HPP
#define BOOST_URL_DETAIL_PARTS_BASE_HPP
#include <boost/url/error.hpp>
namespace boost {
namespace urls {
namespace detail {
// mix-in to provide part
// constants and variables
struct parts_base
{
enum
{
id_scheme = -1, // trailing ':'
id_user, // leading "//"
id_pass, // leading ':', trailing '@'
id_host,
id_port, // leading ':'
id_path,
id_query, // leading '?'
id_frag, // leading '#'
id_end // one past the end
};
enum class from : char {
// this belongs to a string
string = 0,
// this belongs to url_base
// segments/params containers point to
// another url
url = 1,
// this belongs to authority_view
// id_user does not have the leading "//"
authority = 2,
};
};
} // detail
} // urls
} // boost
#endif
+140
View File
@@ -0,0 +1,140 @@
//
// 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_PATH_HPP
#define BOOST_URL_DETAIL_PATH_HPP
#include <boost/core/detail/string_view.hpp>
namespace boost {
namespace urls {
namespace detail {
// Return the number of characters at
// the front of the path that are reserved
inline
std::size_t
path_prefix(
char const* p,
std::size_t n) noexcept
{
switch(n)
{
case 0:
return 0;
case 1:
if(p[0] == '/')
return 1;
return 0;
case 2:
if(p[0] == '/')
return 1;
if( p[0] == '.' &&
p[1] == '/')
return 2;
return 0;
default:
if(p[0] == '/')
{
if( p[1] == '.' &&
p[2] == '/')
return 3;
return 1;
}
if( p[0] == '.' &&
p[1] == '/')
return 2;
break;
}
return 0;
}
// VFALCO DEPRECATED
inline
std::size_t
path_prefix(
core::string_view s) noexcept
{
return path_prefix(
s.data(), s.size());
}
// returns the number of adjusted
// segments based on the malleable prefix.
inline
std::size_t
path_segments(
core::string_view s,
std::size_t nseg) noexcept
{
switch(s.size())
{
case 0:
BOOST_ASSERT(nseg == 0);
return 0;
case 1:
BOOST_ASSERT(nseg == 1);
if(s[0] == '/')
return 0;
return 1;
case 2:
if(s[0] == '/')
return nseg;
if( s[0] == '.' &&
s[1] == '/')
{
BOOST_ASSERT(nseg > 1);
return nseg - 1;
}
return nseg;
default:
if(s[0] == '/')
{
if( s[1] == '.' &&
s[2] == '/')
{
BOOST_ASSERT(nseg > 1);
return nseg - 1;
}
return nseg;
}
if( s[0] == '.' &&
s[1] == '/')
{
BOOST_ASSERT(nseg > 1);
return nseg - 1;
}
break;
}
return nseg;
}
// Trim reserved characters from
// the front of the path.
inline
core::string_view
clean_path(
core::string_view s) noexcept
{
s.remove_prefix(
path_prefix(s));
return s;
}
} // detail
} // urls
} // boost
#endif
+60
View File
@@ -0,0 +1,60 @@
//
// Copyright (c) 2022 Alan de Freitas (alandefreitas@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_PATTERN_HPP
#define BOOST_URL_DETAIL_PATTERN_HPP
#include <boost/url/error_types.hpp>
#include <boost/url/url_base.hpp>
#include <boost/core/detail/string_view.hpp>
// This file includes functions and classes
// to parse uri templates or format strings
namespace boost {
namespace urls {
namespace detail {
class format_args;
struct pattern
{
core::string_view scheme;
core::string_view user;
core::string_view pass;
core::string_view host;
core::string_view port;
core::string_view path;
core::string_view query;
core::string_view frag;
bool has_authority = false;
bool has_user = false;
bool has_pass = false;
bool has_port = false;
bool has_query = false;
bool has_frag = false;
BOOST_URL_DECL
void
apply(
url_base& u,
format_args const& args) const;
};
BOOST_URL_DECL
system::result<pattern>
parse_pattern(
core::string_view s);
} // detail
} // url
} // boost
#endif
+42
View File
@@ -0,0 +1,42 @@
//
// Copyright (c) 2022 Alan de Freitas (alandefreitas@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_PCT_FORMAT_HPP
#define BOOST_URL_DETAIL_PCT_FORMAT_HPP
#include <boost/core/detail/string_view.hpp>
#include <boost/url/url.hpp>
#include <boost/url/grammar/lut_chars.hpp>
#include <boost/url/detail/format_args.hpp>
namespace boost {
namespace urls {
namespace detail {
// measure a single string
BOOST_URL_DECL
std::size_t
pct_vmeasure(
grammar::lut_chars const& cs,
format_parse_context& pctx,
measure_context& mctx);
// format a single string
BOOST_URL_DECL
char*
pct_vformat(
grammar::lut_chars const& cs,
format_parse_context& pctx,
format_context& fctx);
} // detail
} // url
} // boost
#endif
+79
View File
@@ -0,0 +1,79 @@
//
// 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_PRINT_HPP
#define BOOST_URL_DETAIL_PRINT_HPP
#include <cstdint>
#include <type_traits>
namespace boost {
namespace urls {
namespace detail {
// std::uint64_t
// 18446744073709551615
// 1 2
template<class T>
struct printed
: std::false_type
{
};
// 16-bit unsigned
template<>
class printed<std::uint16_t>
: std::false_type
{
char n_;
char buf_[5];
public:
printed(std::uint16_t n)
{
char* it =
buf_ + sizeof(buf_);
if(n == 0)
{
*--it = '0';
n_ = 1;
}
else
{
while(n > 0)
{
*--it = '0' + (n % 10);
n /= 10;
}
n_ = static_cast<char>(
sizeof(buf_) - (
it - buf_));
}
}
core::string_view
string() const noexcept
{
return core::string_view(buf_ +
sizeof(buf_) - n_, n_);
}
};
template<class T>
printed<T>
make_printed(T t)
{
return printed<T>(t);
}
} // detail
} // urls
} // boost
#endif
+76
View File
@@ -0,0 +1,76 @@
//
// Copyright (c) 2022 Alan de Freitas (alandefreitas@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_REPLACEMENT_FIELD_RULE_HPP
#define BOOST_URL_DETAIL_REPLACEMENT_FIELD_RULE_HPP
#include <boost/url/error.hpp>
#include <boost/core/detail/string_view.hpp>
#include <boost/url/grammar/variant_rule.hpp>
#include <boost/url/grammar/unsigned_rule.hpp>
namespace boost {
namespace urls {
namespace detail {
// replacement_field ::= "{" [arg_id] [":" format_spec "}"
struct replacement_field_rule_t
{
using value_type = core::string_view;
BOOST_URL_DECL
system::result<value_type>
parse(
char const*& it,
char const* end) const noexcept;
};
constexpr replacement_field_rule_t replacement_field_rule{};
// identifier ::= id_start id_continue*
// id_start ::= "a"..."z" | "A"..."Z" | "_"
// id_continue ::= id_start | digit
struct identifier_rule_t
{
using value_type = core::string_view;
BOOST_URL_DECL
system::result<value_type>
parse(
char const*& it,
char const* end) const noexcept;
};
constexpr identifier_rule_t identifier_rule{};
// arg_id ::= integer | identifier
// integer ::= digit+
// digit ::= "0"..."9"
static constexpr auto arg_id_rule =
grammar::variant_rule(
identifier_rule,
grammar::unsigned_rule<std::size_t>{});
struct format_spec_rule_t
{
using value_type = core::string_view;
system::result<value_type>
parse(
char const*& it,
char const* end) const noexcept;
};
constexpr format_spec_rule_t format_spec_rule{};
} // detail
} // urls
} // boost
#endif
+85
View File
@@ -0,0 +1,85 @@
//
// Copyright (c) 2019 Vinnie Falco (vinnie.falco@gmail.com)
// Copyright (c) 2022 Alan de Freitas (alandefreitas@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_SEGMENTS_ITER_IMPL_HPP
#define BOOST_URL_DETAIL_SEGMENTS_ITER_IMPL_HPP
#include <boost/url/detail/parts_base.hpp>
#include <boost/url/detail/url_impl.hpp>
#include <boost/core/detail/string_view.hpp>
#include <string>
namespace boost {
namespace urls {
namespace detail {
struct segments_iter_impl
: private parts_base
{
path_ref ref;
std::size_t pos = 0;
std::size_t next = 0;
std::size_t index = 0;
std::size_t dn = 0;
private:
pct_string_view s_;
public:
segments_iter_impl() = default;
segments_iter_impl(
segments_iter_impl const&) noexcept = default;
segments_iter_impl& operator=(
segments_iter_impl const&) noexcept = default;
// begin
segments_iter_impl(
detail::path_ref const&) noexcept;
// end
segments_iter_impl(
detail::path_ref const&,
int) noexcept;
// at index
segments_iter_impl(
url_impl const& u_,
std::size_t pos_,
std::size_t i_) noexcept;
void update() noexcept;
BOOST_URL_DECL
void
increment() noexcept;
BOOST_URL_DECL
void
decrement() noexcept;
pct_string_view
dereference() const noexcept
{
return s_;
}
bool
equal(
segments_iter_impl const& other) const noexcept
{
BOOST_ASSERT(ref.alias_of(other.ref));
return index == other.index;
}
};
} // detail
} // urls
} // boost
#endif
+34
View File
@@ -0,0 +1,34 @@
//
// Copyright (c) 2022 Alan de Freitas (alandefreitas@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_STRING_VIEW_HPP
#define BOOST_URL_DETAIL_STRING_VIEW_HPP
#include <boost/core/detail/string_view.hpp>
namespace boost {
namespace urls {
namespace detail {
// We use detail::to_sv(s) instead of core::string_view(s) whenever
// we should convert to core::string_view.
// This is a workaround for GCC >=8.0 <8.4
// See: https://github.com/boostorg/url/issues/672
template<class T>
core::string_view
to_sv(T const& t) noexcept
{
return core::string_view(t);
}
} // detail
} // urls
} // boost
#endif
+193
View File
@@ -0,0 +1,193 @@
//
// 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_DETAIL_URL_IMPL_HPP
#define BOOST_URL_DETAIL_URL_IMPL_HPP
#include <boost/url/host_type.hpp>
#include <boost/url/pct_string_view.hpp>
#include <boost/url/scheme.hpp>
#include <boost/core/detail/string_view.hpp>
#include <boost/url/detail/parts_base.hpp>
#include <boost/assert.hpp>
#include <cstdint>
namespace boost {
namespace urls {
class url_view;
class authority_view;
namespace detail {
constexpr char const* const empty_c_str_ = "";
// This is the private 'guts' of a
// url_view, exposed so different parts
// of the implementation can work on it.
struct BOOST_URL_DECL url_impl : parts_base
{
static
constexpr
std::size_t const zero_ = 0;
// never nullptr
char const* cs_ = empty_c_str_;
std::size_t offset_[id_end + 1] = {};
std::size_t decoded_[id_end] = {};
std::size_t nseg_ = 0;
std::size_t nparam_ = 0;
unsigned char ip_addr_[16] = {};
// VFALCO don't we need a bool?
std::uint16_t port_number_ = 0;
host_type host_type_ =
urls::host_type::none;
scheme scheme_ =
urls::scheme::none;
from from_ = from::string;
url_impl(
from b) noexcept
: from_(b)
{
}
// in url_view.ipp
url_view construct() const noexcept;
// in authority_view.ipp
authority_view
construct_authority() const noexcept;
std::size_t len(int, int) const noexcept;
std::size_t len(int) const noexcept;
std::size_t offset(int) const noexcept;
core::string_view get(int) const noexcept;
core::string_view get(int, int) const noexcept;
pct_string_view pct_get(int) const noexcept;
pct_string_view pct_get(int, int) const noexcept;
void set_size(int, std::size_t) noexcept;
void split(int, std::size_t) noexcept;
void adjust(int, int, std::size_t) noexcept;
void collapse(int, int, std::size_t) noexcept;
void apply_scheme(core::string_view) noexcept;
void apply_userinfo(pct_string_view const&,
pct_string_view const*) noexcept;
void apply_host(host_type, pct_string_view,
unsigned char const*) noexcept;
void apply_port(core::string_view, unsigned short) noexcept;
void apply_authority(authority_view const&) noexcept;
void apply_path(pct_string_view, std::size_t) noexcept;
void apply_query(pct_string_view, std::size_t) noexcept;
void apply_frag(pct_string_view) noexcept;
};
//------------------------------------------------
// this allows a path to come from a
// url_impl or a separate core::string_view
class path_ref
: private parts_base
{
url_impl const* impl_ = nullptr;
char const* data_ = nullptr;
std::size_t size_ = 0;
std::size_t nseg_ = 0;
std::size_t dn_ = 0;
public:
path_ref() = default;
path_ref(url_impl const& impl) noexcept;
path_ref(core::string_view,
std::size_t, std::size_t) noexcept;
pct_string_view buffer() const noexcept;
std::size_t size() const noexcept;
char const* data() const noexcept;
char const* end() const noexcept;
std::size_t nseg() const noexcept;
bool
alias_of(
url_impl const& impl) const noexcept
{
return impl_ == &impl;
}
bool
alias_of(
path_ref const& ref) const noexcept
{
if(impl_)
return impl_ == ref.impl_;
BOOST_ASSERT(data_ != ref.data_ || (
size_ == ref.size_ &&
nseg_ == ref.nseg_ &&
dn_ == ref.dn_));
return data_ == ref.data_;
}
};
//------------------------------------------------
// this allows a params to come from a
// url_impl or a separate core::string_view
class BOOST_URL_DECL query_ref
: private parts_base
{
url_impl const* impl_ = nullptr;
char const* data_ = nullptr;
std::size_t size_ = 0;
std::size_t nparam_ = 0;
std::size_t dn_ = 0;
bool question_mark_ = false;
public:
query_ref(
core::string_view s, // buffer, no '?'
std::size_t dn, // decoded size
std::size_t nparam
) noexcept;
query_ref() = default;
query_ref(url_impl const& impl) noexcept;
pct_string_view buffer() const noexcept;
std::size_t size() const noexcept; // with '?'
char const* begin() const noexcept; // no '?'
char const* end() const noexcept;
std::size_t nparam() const noexcept;
bool
alias_of(
url_impl const& impl) const noexcept
{
return impl_ == &impl;
}
bool
alias_of(
query_ref const& ref) const noexcept
{
if(impl_)
return impl_ == ref.impl_;
BOOST_ASSERT(data_ != ref.data_ || (
size_ == ref.size_ &&
nparam_ == ref.nparam_ &&
dn_ == ref.dn_));
return data_ == ref.data_;
}
};
} // detail
} // urls
} // boost
#endif
+48
View File
@@ -0,0 +1,48 @@
//
// Copyright (c) 2022 Alan de Freitas (alandefreitas@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_FORMAT_HPP
#define BOOST_URL_DETAIL_FORMAT_HPP
#include <boost/url/detail/format_args.hpp>
#include <boost/url/detail/pattern.hpp>
#include <boost/core/detail/string_view.hpp>
#include <boost/url/url.hpp>
namespace boost {
namespace urls {
namespace detail {
inline
void
vformat_to(
url_base& u,
core::string_view fmt,
detail::format_args args)
{
parse_pattern(fmt)
.value().apply(u, args);
}
inline
url
vformat(
core::string_view fmt,
detail::format_args args)
{
url u;
vformat_to(u, fmt, args);
return u;
}
} // detail
} // url
} // boost
#endif