mirror of
https://github.com/vdemydiuk/mtapi.git
synced 2026-08-10 01:11:04 +00:00
Added thirdparty: boost library
This commit is contained in:
+123
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
|
||||
Reference in New Issue
Block a user