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
+123
View File
@@ -0,0 +1,123 @@
//
// 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_GRAMMAR_IMPL_ERROR_HPP
#define BOOST_URL_GRAMMAR_IMPL_ERROR_HPP
#include <type_traits>
namespace boost {
namespace system {
template<>
struct is_error_code_enum<
::boost::urls::grammar::error>
{
static bool const value = true;
};
template<>
struct is_error_condition_enum<
::boost::urls::grammar::condition>
{
static bool const value = true;
};
} // system
} // boost
namespace boost {
namespace urls {
namespace grammar {
namespace detail {
struct BOOST_SYMBOL_VISIBLE
error_cat_type
: system::error_category
{
BOOST_URL_DECL
const char* name(
) const noexcept override;
BOOST_URL_DECL
std::string message(
int) const override;
BOOST_URL_DECL
char const* message(
int, char*, std::size_t
) const noexcept override;
BOOST_URL_DECL
system::error_condition
default_error_condition(
int code) const noexcept override;
BOOST_SYSTEM_CONSTEXPR error_cat_type() noexcept
: error_category(0x0536e50a30f9e9f2)
{
}
};
struct BOOST_SYMBOL_VISIBLE
condition_cat_type
: system::error_category
{
BOOST_URL_DECL
const char* name(
) const noexcept override;
BOOST_URL_DECL
std::string message(
int) const override;
BOOST_URL_DECL
char const* message(
int, char*, std::size_t
) const noexcept override;
BOOST_SYSTEM_CONSTEXPR condition_cat_type()
: error_category(0x0536e50a30f9e9f2)
{
}
};
BOOST_URL_DECL extern
error_cat_type error_cat;
BOOST_URL_DECL extern
condition_cat_type condition_cat;
} // detail
inline
system::error_code
make_error_code(
error ev) noexcept
{
return system::error_code{
static_cast<std::underlying_type<
error>::type>(ev),
detail::error_cat};
}
inline
system::error_condition
make_error_condition(
condition c) noexcept
{
return system::error_condition{
static_cast<std::underlying_type<
condition>::type>(c),
detail::condition_cat};
}
} // grammar
} // urls
} // boost
#endif
+55
View File
@@ -0,0 +1,55 @@
//
// Copyright (c) 2016-2019 Vinnie Falco (vinnie dot falco at gmail dot 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_GRAMMAR_IMPL_NOT_EMPTY_RULE_HPP
#define BOOST_URL_GRAMMAR_IMPL_NOT_EMPTY_RULE_HPP
#include <boost/url/grammar/error.hpp>
#include <boost/url/grammar/parse.hpp>
namespace boost {
namespace urls {
namespace grammar {
template<class R>
auto
not_empty_rule_t<R>::
parse(
char const*& it,
char const* end) const ->
system::result<value_type>
{
if(it == end)
{
// empty
BOOST_URL_RETURN_EC(
error::mismatch);
}
auto const it0 = it;
auto rv = r_.parse(it, end);
if( !rv )
{
// error
return rv;
}
if(it == it0)
{
// empty
BOOST_URL_RETURN_EC(
error::mismatch);
}
// value
return rv;
}
} // grammar
} // urls
} // boost
#endif
+42
View File
@@ -0,0 +1,42 @@
//
// Copyright (c) 2016-2019 Vinnie Falco (vinnie dot falco at gmail dot 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_GRAMMAR_IMPL_OPTIONAL_RULE_HPP
#define BOOST_URL_GRAMMAR_IMPL_OPTIONAL_RULE_HPP
#include <boost/url/grammar/error.hpp>
namespace boost {
namespace urls {
namespace grammar {
template<class R>
auto
optional_rule_t<R>::
parse(
char const*& it,
char const* end) const ->
system::result<value_type>
{
if(it == end)
return boost::none;
auto const it0 = it;
auto rv =
this->get().parse(it, end);
if(rv)
return value_type(*rv);
it = it0;
return boost::none;
}
} // grammar
} // urls
} // boost
#endif
+67
View File
@@ -0,0 +1,67 @@
//
// Copyright (c) 2016-2019 Vinnie Falco (vinnie dot falco at gmail dot 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_GRAMMAR_IMPL_PARSE_HPP
#define BOOST_URL_GRAMMAR_IMPL_PARSE_HPP
#include <boost/url/grammar/error.hpp>
#include <boost/url/grammar/type_traits.hpp>
namespace boost {
namespace urls {
namespace grammar {
template<class R>
BOOST_URL_NO_INLINE
auto
parse(
char const*& it,
char const* end,
R const& r) ->
system::result<typename R::value_type>
{
// If this goes off, it means the rule
// passed in did not meet the requirements.
// Please check the documentation.
static_assert(
is_rule<R>::value,
"Rule requirements not met");
return r.parse(it, end);
}
template<class R>
BOOST_URL_NO_INLINE
auto
parse(
core::string_view s,
R const& r) ->
system::result<typename R::value_type>
{
// If this goes off, it means the rule
// passed in did not meet the requirements.
// Please check the documentation.
static_assert(
is_rule<R>::value,
"Rule requirements not met");
auto it = s.data();
auto const end = it + s.size();
auto rv = r.parse(it, end);
if( rv &&
it != end)
return error::leftover;
return rv;
}
} // grammar
} // urls
} // boost
#endif
+742
View File
@@ -0,0 +1,742 @@
//
// Copyright (c) 2016-2019 Vinnie Falco (vinnie dot falco at gmail dot 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_GRAMMAR_IMPL_RANGE_HPP
#define BOOST_URL_GRAMMAR_IMPL_RANGE_HPP
#include <boost/url/detail/except.hpp>
#include <boost/url/grammar/error.hpp>
#include <boost/url/grammar/recycled.hpp>
#include <boost/core/empty_value.hpp>
#include <boost/assert.hpp>
#include <boost/static_assert.hpp>
#include <exception>
#include <iterator>
#include <new>
#include <stddef.h> // ::max_align_t
namespace boost {
namespace urls {
namespace grammar {
// VFALCO This could be reused for
// other things that need to type-erase
//------------------------------------------------
//
// any_rule
//
//------------------------------------------------
// base class for the type-erased rule pair
template<class T>
struct range<T>::
any_rule
{
virtual
~any_rule() = default;
virtual
void
move(void* dest) noexcept
{
::new(dest) any_rule(
std::move(*this));
}
virtual
void
copy(void* dest) const noexcept
{
::new(dest) any_rule(*this);
}
virtual
system::result<T>
first(
char const*&,
char const*) const noexcept
{
return system::error_code{};
}
virtual
system::result<T>
next(
char const*&,
char const*) const noexcept
{
return system::error_code{};
}
};
//------------------------------------------------
// small
template<class T>
template<class R, bool Small>
struct range<T>::impl1
: any_rule
, private empty_value<R>
{
explicit
impl1(R const& next) noexcept
: empty_value<R>(
empty_init,
next)
{
}
private:
impl1(impl1&&) noexcept = default;
impl1(impl1 const&) noexcept = default;
void
move(void* dest
) noexcept override
{
::new(dest) impl1(
std::move(*this));
}
void
copy(void* dest
) const noexcept override
{
::new(dest) impl1(*this);
}
system::result<T>
first(
char const*& it,
char const* end)
const noexcept override
{
return grammar::parse(
it, end, this->get());
}
system::result<T>
next(
char const*& it,
char const* end)
const noexcept override
{
return grammar::parse(
it, end, this->get());
}
};
//------------------------------------------------
// big
template<class T>
template<class R>
struct range<T>::impl1<R, false>
: any_rule
{
explicit
impl1(R const& next) noexcept
{
::new(p_->addr()) impl{next};
}
private:
struct impl
{
R r;
};
recycled_ptr<
aligned_storage<impl>> p_;
impl1(impl1&&) noexcept = default;
impl1(impl1 const&) noexcept = default;
impl const&
get() const noexcept
{
return *reinterpret_cast<
impl const*>(p_->addr());
}
~impl1()
{
if(p_)
get().~impl();
}
void
move(void* dest
) noexcept override
{
::new(dest) impl1(
std::move(*this));
}
void
copy(void* dest
) const noexcept override
{
::new(dest) impl1(*this);
}
system::result<T>
first(
char const*& it,
char const* end)
const noexcept override
{
return grammar::parse(
it, end, this->get().r);
}
system::result<T>
next(
char const*& it,
char const* end)
const noexcept override
{
return grammar::parse(
it, end, this->get().r);
}
};
//------------------------------------------------
// small
template<class T>
template<
class R0, class R1, bool Small>
struct range<T>::impl2
: any_rule
, private empty_value<R0, 0>
, private empty_value<R1, 1>
{
impl2(
R0 const& first,
R1 const& next) noexcept
: empty_value<R0,0>(
empty_init, first)
, empty_value<R1,1>(
empty_init, next)
{
}
private:
impl2(impl2&&) noexcept = default;
impl2(impl2 const&) noexcept = default;
void
move(void* dest
) noexcept override
{
::new(dest) impl2(
std::move(*this));
}
void
copy(void* dest
) const noexcept override
{
::new(dest) impl2(*this);
}
system::result<T>
first(
char const*& it,
char const* end)
const noexcept override
{
return grammar::parse(it, end,
empty_value<
R0,0>::get());
}
system::result<T>
next(
char const*& it,
char const* end)
const noexcept override
{
return grammar::parse(it, end,
empty_value<
R1,1>::get());
}
};
//------------------------------------------------
// big
template<class T>
template<
class R0, class R1>
struct range<T>::impl2<R0, R1, false>
: any_rule
{
impl2(
R0 const& first,
R1 const& next) noexcept
{
::new(p_->addr()) impl{
first, next};
}
private:
struct impl
{
R0 first;
R1 next;
};
recycled_ptr<
aligned_storage<impl>> p_;
impl2(impl2&&) noexcept = default;
impl2(impl2 const&) noexcept = default;
impl const&
get() const noexcept
{
return *reinterpret_cast<
impl const*>(p_->addr());
}
~impl2()
{
if(p_)
get().~impl();
}
void
move(void* dest
) noexcept override
{
::new(dest) impl2(
std::move(*this));
}
void
copy(void* dest
) const noexcept override
{
::new(dest) impl2(*this);
}
system::result<T>
first(
char const*& it,
char const* end)
const noexcept override
{
return grammar::parse(
it, end, get().first);
}
system::result<T>
next(
char const*& it,
char const* end)
const noexcept override
{
return grammar::parse(
it, end, get().next);
}
};
//------------------------------------------------
//
// iterator
//
//------------------------------------------------
template<class T>
class range<T>::
iterator
{
public:
using value_type = T;
using reference = T const&;
using pointer = void const*;
using difference_type =
std::ptrdiff_t;
using iterator_category =
std::forward_iterator_tag;
iterator() = default;
iterator(
iterator const&) = default;
iterator& operator=(
iterator const&) = default;
reference
operator*() const noexcept
{
return *rv_;
}
bool
operator==(
iterator const& other) const noexcept
{
// can't compare iterators
// from different containers!
BOOST_ASSERT(r_ == other.r_);
return p_ == other.p_;
}
bool
operator!=(
iterator const& other) const noexcept
{
return !(*this == other);
}
iterator&
operator++() noexcept
{
BOOST_ASSERT(
p_ != nullptr);
auto const end =
r_->s_.data() +
r_->s_.size();
rv_ = r_->get().next(p_, end);
if( !rv_ )
p_ = nullptr;
return *this;
}
iterator
operator++(int) noexcept
{
auto tmp = *this;
++*this;
return tmp;
}
private:
friend class range<T>;
range<T> const* r_ = nullptr;
char const* p_ = nullptr;
system::result<T> rv_;
iterator(
range<T> const& r) noexcept
: r_(&r)
, p_(r.s_.data())
{
auto const end =
r_->s_.data() +
r_->s_.size();
rv_ = r_->get().first(p_, end);
if( !rv_ )
p_ = nullptr;
}
constexpr
iterator(
range<T> const& r,
int) noexcept
: r_(&r)
, p_(nullptr)
{
}
};
//------------------------------------------------
template<class T>
template<class R>
range<T>::
range(
core::string_view s,
std::size_t n,
R const& next)
: s_(s)
, n_(n)
{
BOOST_STATIC_ASSERT(
sizeof(impl1<R, false>) <=
BufferSize);
::new(&get()) impl1<R,
sizeof(impl1<R, true>) <=
BufferSize>(next);
}
//------------------------------------------------
template<class T>
template<
class R0, class R1>
range<T>::
range(
core::string_view s,
std::size_t n,
R0 const& first,
R1 const& next)
: s_(s)
, n_(n)
{
BOOST_STATIC_ASSERT(
sizeof(impl2<R0, R1, false>) <=
BufferSize);
::new(&get()) impl2<R0, R1,
sizeof(impl2<R0, R1, true>
) <= BufferSize>(
first, next);
}
//------------------------------------------------
template<class T>
range<T>::
~range()
{
get().~any_rule();
}
template<class T>
range<T>::
range() noexcept
{
::new(&get()) any_rule{};
char const* it = nullptr;
get().first(it, nullptr);
get().next(it, nullptr);
}
template<class T>
range<T>::
range(
range&& other) noexcept
: s_(other.s_)
, n_(other.n_)
{
other.s_ = {};
other.n_ = {};
other.get().move(&get());
other.get().~any_rule();
::new(&other.get()) any_rule{};
}
template<class T>
range<T>::
range(
range const& other) noexcept
: s_(other.s_)
, n_(other.n_)
{
other.get().copy(&get());
}
template<class T>
auto
range<T>::
operator=(
range&& other) noexcept ->
range&
{
s_ = other.s_;
n_ = other.n_;
other.s_ = {};
other.n_ = 0;
// VFALCO we rely on nothrow move
// construction here, but if necessary we
// could move to a local buffer first.
get().~any_rule();
other.get().move(&get());
other.get().~any_rule();
::new(&other.get()) any_rule{};
return *this;
}
template<class T>
auto
range<T>::
operator=(
range const& other) noexcept ->
range&
{
s_ = other.s_;
n_ = other.n_;
// VFALCO we rely on nothrow copy
// construction here, but if necessary we
// could construct to a local buffer first.
get().~any_rule();
other.get().copy(&get());
return *this;
}
template<class T>
auto
range<T>::
begin() const noexcept ->
iterator
{
return { *this };
}
template<class T>
auto
range<T>::
end() const noexcept ->
iterator
{
return { *this, 0 };
}
//------------------------------------------------
template<class R>
auto
range_rule_t<R>::
parse(
char const*& it,
char const* end) const ->
system::result<value_type>
{
using T = typename R::value_type;
std::size_t n = 0;
auto const it0 = it;
auto it1 = it;
auto rv = (grammar::parse)(
it, end, next_);
if( !rv )
{
if(rv.error() != error::end_of_range)
{
// rewind unless error::end_of_range
it = it1;
}
if(n < N_)
{
// too few
BOOST_URL_RETURN_EC(
error::mismatch);
}
// good
return range<T>(
core::string_view(it0, it - it0),
n, next_);
}
for(;;)
{
++n;
it1 = it;
rv = (grammar::parse)(
it, end, next_);
if( !rv )
{
if(rv.error() != error::end_of_range)
{
// rewind unless error::end_of_range
it = it1;
}
break;
}
if(n >= M_)
{
// too many
BOOST_URL_RETURN_EC(
error::mismatch);
}
}
if(n < N_)
{
// too few
BOOST_URL_RETURN_EC(
error::mismatch);
}
// good
return range<T>(
core::string_view(it0, it - it0),
n, next_);
}
//------------------------------------------------
template<class R0, class R1>
auto
range_rule_t<R0, R1>::
parse(
char const*& it,
char const* end) const ->
system::result<range<typename
R0::value_type>>
{
using T = typename R0::value_type;
std::size_t n = 0;
auto const it0 = it;
auto it1 = it;
auto rv = (grammar::parse)(
it, end, first_);
if( !rv )
{
if(rv.error() != error::end_of_range)
{
// rewind unless error::end_of_range
it = it1;
}
if(n < N_)
{
// too few
BOOST_URL_RETURN_EC(
error::mismatch);
}
// good
return range<T>(
core::string_view(it0, it - it0),
n, first_, next_);
}
for(;;)
{
++n;
it1 = it;
rv = (grammar::parse)(
it, end, next_);
if( !rv )
{
if(rv.error() != error::end_of_range)
{
// rewind unless error::end_of_range
it = it1;
}
break;
}
if(n >= M_)
{
// too many
BOOST_URL_RETURN_EC(
error::mismatch);
}
}
if(n < N_)
{
// too few
BOOST_URL_RETURN_EC(
error::mismatch);
}
// good
return range<T>(
core::string_view(it0, it - it0),
n, first_, next_);
}
} // grammar
} // urls
} // boost
#endif
+221
View File
@@ -0,0 +1,221 @@
//
// 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_GRAMMAR_IMPL_RECYCLED_PTR_HPP
#define BOOST_URL_GRAMMAR_IMPL_RECYCLED_PTR_HPP
#include <boost/assert.hpp>
namespace boost {
namespace urls {
namespace grammar {
//------------------------------------------------
template<class T>
recycled<T>::
~recycled()
{
std::size_t n = 0;
// VFALCO we should probably deallocate
// in reverse order of allocation but
// that requires a doubly-linked list.
auto it = head_;
while(it)
{
++n;
auto next = it->next;
BOOST_ASSERT(
it->refs == 0);
delete it;
it = next;
}
detail::recycled_remove(
sizeof(U) * n);
}
template<class T>
auto
recycled<T>::
acquire() ->
U*
{
U* p;
{
#if !defined(BOOST_URL_DISABLE_THREADS)
std::lock_guard<
std::mutex> lock(m_);
#endif
p = head_;
if(p)
{
// reuse
head_ = head_->next;
detail::recycled_remove(
sizeof(U));
++p->refs;
}
else
{
p = new U;
}
}
BOOST_ASSERT(p->refs == 1);
return p;
}
template<class T>
void
recycled<T>::
release(U* u) noexcept
{
if(--u->refs != 0)
return;
{
#if !defined(BOOST_URL_DISABLE_THREADS)
std::lock_guard<
std::mutex> lock(m_);
#endif
u->next = head_;
head_ = u;
}
detail::recycled_add(
sizeof(U));
}
//------------------------------------------------
template<class T>
recycled_ptr<T>::
~recycled_ptr()
{
if(p_)
bin_->release(p_);
}
template<class T>
recycled_ptr<T>::
recycled_ptr(
recycled<T>& bin)
: bin_(&bin)
, p_(bin.acquire())
{
}
template<class T>
recycled_ptr<T>::
recycled_ptr(
recycled<T>& bin,
std::nullptr_t) noexcept
: bin_(&bin)
{
}
template<class T>
recycled_ptr<T>::
recycled_ptr()
: recycled_ptr(nullptr)
{
p_ = bin_->acquire();
}
template<class T>
recycled_ptr<T>::
recycled_ptr(
std::nullptr_t) noexcept
: recycled_ptr([]() -> B&
{
// VFALCO need guaranteed constexpr-init
static B r;
return r;
}(), nullptr)
{
}
template<class T>
recycled_ptr<T>::
recycled_ptr(
recycled_ptr const& other) noexcept
: bin_(other.bin_)
, p_(other.p_)
{
if(p_)
++p_->refs;
}
template<class T>
recycled_ptr<T>::
recycled_ptr(
recycled_ptr&& other) noexcept
: bin_(other.bin_)
, p_(other.p_)
{
other.p_ = nullptr;
}
template<class T>
auto
recycled_ptr<T>::
operator=(
recycled_ptr&& other) noexcept ->
recycled_ptr&
{
BOOST_ASSERT(
bin_ == other.bin_);
if(p_)
bin_->release(p_);
p_ = other.p_;
other.p_ = nullptr;
return *this;
}
template<class T>
auto
recycled_ptr<T>::
operator=(
recycled_ptr const& other) noexcept ->
recycled_ptr&
{
BOOST_ASSERT(
bin_ == other.bin_);
if(p_)
bin_->release(p_);
p_ = other.p_;
if(p_)
++p_->refs;
return *this;
}
template<class T>
T&
recycled_ptr<T>::
acquire()
{
if(! p_)
p_ = bin_->acquire();
return p_->t;
}
template<class T>
void
recycled_ptr<T>::
release() noexcept
{
if(p_)
{
bin_->release(p_);
p_ = nullptr;
}
}
} // grammar
} // urls
} // boost
#endif
+45
View File
@@ -0,0 +1,45 @@
//
// Copyright (c) 2016-2019 Vinnie Falco (vinnie dot falco at gmail dot 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/http_proto
//
#ifndef BOOST_URL_IMPL_GRAMMAR_TOKEN_RULE_HPP
#define BOOST_URL_IMPL_GRAMMAR_TOKEN_RULE_HPP
#include <boost/url/grammar/error.hpp>
namespace boost {
namespace urls {
namespace grammar {
template<class CharSet>
auto
token_rule_t<CharSet>::
parse(
char const*& it,
char const* end
) const noexcept ->
system::result<value_type>
{
auto const it0 = it;
if(it == end)
{
BOOST_URL_RETURN_EC(
error::need_more);
}
it = (find_if_not)(it, end, cs_);
if(it != it0)
return core::string_view(it0, it - it0);
BOOST_URL_RETURN_EC(
error::mismatch);
}
} // grammar
} // urls
} // boost
#endif
+285
View File
@@ -0,0 +1,285 @@
//
// Copyright (c) 2022 Vinnie Falco (vinnie dot falco at gmail dot 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_GRAMMAR_IMPL_TUPLE_RULE_HPP
#define BOOST_URL_GRAMMAR_IMPL_TUPLE_RULE_HPP
#include <boost/url/grammar/parse.hpp>
#include <boost/mp11/integral.hpp>
#include <boost/mp11/list.hpp>
#include <boost/mp11/tuple.hpp>
#include <type_traits>
namespace boost {
namespace urls {
namespace grammar {
namespace detail {
// returns a tuple
template<
bool IsList,
class R0, class... Rn>
struct parse_sequence
{
using R = detail::tuple<R0, Rn...>;
using L = mp11::mp_list<
typename R0::value_type,
typename Rn::value_type...>;
using V = mp11::mp_remove<
std::tuple<
system::result<typename R0::value_type>,
system::result<typename Rn::value_type>...>,
system::result<void>>;
template<std::size_t I>
using is_void = std::is_same<
mp11::mp_at_c<L, I>, void>;
system::error_code ec;
R const& rn;
V vn;
explicit
parse_sequence(
R const& rn_) noexcept
: rn(rn_)
, vn(mp11::mp_fill<
V, system::error_code>{})
{
}
void
apply(
char const*&,
char const*,
...) const noexcept
{
}
// for system::result<void>
template<
std::size_t Ir,
std::size_t Iv>
void
apply(
char const*& it,
char const* end,
mp11::mp_size_t<Ir> const&,
mp11::mp_size_t<Iv> const&,
mp11::mp_true const&)
{
system::result<void> rv =
grammar::parse(
it, end, get<Ir>(rn));
if( !rv )
{
ec = rv.error();
return;
}
apply(it, end,
mp11::mp_size_t<Ir+1>{},
mp11::mp_size_t<Iv>{});
}
template<
std::size_t Ir,
std::size_t Iv>
void
apply(
char const*& it,
char const* end,
mp11::mp_size_t<Ir> const&,
mp11::mp_size_t<Iv> const&,
mp11::mp_false const&)
{
auto& rv = get<Iv>(vn);
rv = grammar::parse(
it, end, get<Ir>(rn));
if( !rv )
{
ec = rv.error();
return;
}
apply(it, end,
mp11::mp_size_t<Ir+1>{},
mp11::mp_size_t<Iv+1>{});
}
template<
std::size_t Ir = 0,
std::size_t Iv = 0>
typename std::enable_if<
Ir < 1 + sizeof...(Rn)>::type
apply(
char const*& it,
char const* end,
mp11::mp_size_t<Ir> const& ir = {},
mp11::mp_size_t<Iv> const& iv = {}
) noexcept
{
apply(it, end, ir, iv, is_void<Ir>{});
}
struct deref
{
template<class R>
auto
operator()(R const& r) const ->
decltype(*r)
{
return *r;
}
};
auto
make_result() noexcept ->
system::result<typename tuple_rule_t<
R0, Rn...>::value_type>
{
if(ec.failed())
return ec;
return mp11::tuple_transform(
deref{}, vn);
}
};
// returns a value_type
template<class R0, class... Rn>
struct parse_sequence<false, R0, Rn...>
{
using R = detail::tuple<R0, Rn...>;
using L = mp11::mp_list<
typename R0::value_type,
typename Rn::value_type...>;
using V = mp11::mp_first<
mp11::mp_remove<
mp11::mp_list<
system::result<typename R0::value_type>,
system::result<typename Rn::value_type>...>,
system::result<void>>>;
template<std::size_t I>
using is_void = std::is_same<
mp11::mp_at_c<L, I>, void>;
R const& rn;
V v;
explicit
parse_sequence(
R const& rn_) noexcept
: rn(rn_)
, v(system::error_code{})
{
}
void
apply(
char const*&,
char const*,
...) const noexcept
{
}
// for system::result<void>
template<
std::size_t Ir,
std::size_t Iv>
BOOST_URL_NO_INLINE
void
apply(
char const*& it,
char const* end,
mp11::mp_size_t<Ir> const&,
mp11::mp_size_t<Iv> const&,
mp11::mp_true const&)
{
system::result<void> rv =
grammar::parse(
it, end, get<Ir>(rn));
if( !rv )
{
v = rv.error();
return;
}
apply(it, end,
mp11::mp_size_t<Ir+1>{},
mp11::mp_size_t<Iv>{});
}
template<
std::size_t Ir,
std::size_t Iv>
void
apply(
char const*& it,
char const* end,
mp11::mp_size_t<Ir> const&,
mp11::mp_size_t<Iv> const&,
mp11::mp_false const&)
{
v = grammar::parse(
it, end, get<Ir>(rn));
if( !v )
return;
apply(it, end,
mp11::mp_size_t<Ir+1>{},
mp11::mp_size_t<Iv+1>{});
}
template<
std::size_t Ir = 0,
std::size_t Iv = 0>
typename std::enable_if<
Ir < 1 + sizeof...(Rn)>::type
apply(
char const*& it,
char const* end,
mp11::mp_size_t<Ir> const& ir = {},
mp11::mp_size_t<Iv> const& iv = {}
) noexcept
{
apply(it, end, ir, iv, is_void<Ir>{});
}
V
make_result() noexcept
{
return v;
}
};
} // detail
template<
class R0,
class... Rn>
auto
tuple_rule_t<R0, Rn...>::
parse(
char const*& it,
char const* end) const ->
system::result<value_type>
{
detail::parse_sequence<
IsList, R0, Rn...> t(this->get());
t.apply(it, end);
return t.make_result();
}
} // grammar
} // urls
} // boost
#endif
+109
View File
@@ -0,0 +1,109 @@
//
// Copyright (c) 2022 Alan de Freitas (alandefreitas at gmail dot 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_GRAMMAR_IMPL_UNSIGNED_RULE_HPP
#define BOOST_URL_GRAMMAR_IMPL_UNSIGNED_RULE_HPP
#include <boost/url/grammar/error.hpp>
#include <boost/url/grammar/digit_chars.hpp>
#include <algorithm> // VFALCO grr..
namespace boost {
namespace urls {
namespace grammar {
template<class U>
auto
unsigned_rule<U>::
parse(
char const*& it,
char const* end
) const noexcept ->
system::result<value_type>
{
if(it == end)
{
// end
BOOST_URL_RETURN_EC(
error::mismatch);
}
if(*it == '0')
{
++it;
if( it == end ||
! digit_chars(*it))
{
return U(0);
}
// bad leading zero
BOOST_URL_RETURN_EC(
error::invalid);
}
if(! digit_chars(*it))
{
// expected digit
BOOST_URL_RETURN_EC(
error::mismatch);
}
static constexpr U Digits10 =
std::numeric_limits<
U>::digits10;
static constexpr U ten = 10;
char const* safe_end;
if(static_cast<std::size_t>(
end - it) >= Digits10)
safe_end = it + Digits10;
else
safe_end = end;
U u = *it - '0';
++it;
while(it != safe_end &&
digit_chars(*it))
{
char const dig = *it - '0';
u = u * ten + dig;
++it;
}
if( it != end &&
digit_chars(*it))
{
static constexpr U Max = (
std::numeric_limits<
U>::max)();
static constexpr
auto div = (Max / ten);
static constexpr
char rem = (Max % ten);
char const dig = *it - '0';
if( u > div || (
u == div && dig > rem))
{
// integer overflow
BOOST_URL_RETURN_EC(
error::invalid);
}
u = u * ten + dig;
++it;
if( it < end &&
digit_chars(*it))
{
// integer overflow
BOOST_URL_RETURN_EC(
error::invalid);
}
}
return u;
}
} // grammar
} // urls
} // boost
#endif
+116
View File
@@ -0,0 +1,116 @@
//
// Copyright (c) 2016-2019 Vinnie Falco (vinnie dot falco at gmail dot 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_GRAMMAR_IMPL_VARIANT_RULE_HPP
#define BOOST_URL_GRAMMAR_IMPL_VARIANT_RULE_HPP
#include <boost/url/grammar/error.hpp>
#include <boost/url/grammar/parse.hpp>
#include <cstdint>
#include <type_traits>
namespace boost {
namespace urls {
namespace grammar {
namespace detail {
// must come first
template<
class R0,
class... Rn,
std::size_t I>
auto
parse_variant(
char const*&,
char const*,
detail::tuple<
R0, Rn...> const&,
std::integral_constant<
std::size_t, I> const&,
std::false_type const&) ->
system::result<variant<
typename R0::value_type,
typename Rn::value_type...>>
{
// no match
BOOST_URL_RETURN_EC(
error::mismatch);
}
template<
class R0,
class... Rn,
std::size_t I>
auto
parse_variant(
char const*& it,
char const* const end,
detail::tuple<
R0, Rn...> const& rn,
std::integral_constant<
std::size_t, I> const&,
std::true_type const&) ->
system::result<variant<
typename R0::value_type,
typename Rn::value_type...>>
{
auto const it0 = it;
auto rv = parse(
it, end, get<I>(rn));
if( rv )
return variant<
typename R0::value_type,
typename Rn::value_type...>{
variant2::in_place_index_t<I>{}, *rv};
it = it0;
return parse_variant(
it, end, rn,
std::integral_constant<
std::size_t, I+1>{},
std::integral_constant<bool,
((I + 1) < (1 +
sizeof...(Rn)))>{});
}
} // detail
template<class R0, class... Rn>
auto
variant_rule_t<R0, Rn...>::
parse(
char const*& it,
char const* end) const ->
system::result<value_type>
{
return detail::parse_variant(
it, end, rn_,
std::integral_constant<
std::size_t, 0>{},
std::true_type{});
}
//------------------------------------------------
template<class R0, class... Rn>
auto
constexpr
variant_rule(
R0 const& r0,
Rn const&... rn) noexcept ->
variant_rule_t<R0, Rn...>
{
return { r0, rn... };
}
} // grammar
} // urls
} // boost
#endif