mirror of
https://github.com/boostorg/parser.git
synced 2026-01-19 04:22:13 +00:00
122
include/boost/parser/detail/text/detail/all_t.hpp
Normal file
122
include/boost/parser/detail/text/detail/all_t.hpp
Normal file
@@ -0,0 +1,122 @@
|
||||
// Copyright (C) 2024 T. Zachary Laine
|
||||
//
|
||||
// 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)
|
||||
#ifndef BOOST_PARSER_DETAIL_TEXT_DETAIL_ALL_T_HPP
|
||||
#define BOOST_PARSER_DETAIL_TEXT_DETAIL_ALL_T_HPP
|
||||
|
||||
#include <boost/parser/detail/stl_interfaces/view_interface.hpp>
|
||||
#include <boost/parser/detail/text/detail/begin_end.hpp>
|
||||
#include <boost/parser/detail/detection.hpp>
|
||||
|
||||
#if BOOST_PARSER_DETAIL_TEXT_USE_CONCEPTS
|
||||
#include <ranges>
|
||||
#endif
|
||||
|
||||
|
||||
namespace boost::parser::detail::text::detail {
|
||||
|
||||
template<typename T>
|
||||
using iterator_ = decltype(text::detail::begin(std::declval<T &>()));
|
||||
template<typename Range>
|
||||
using sentinel_ = decltype(text::detail::end(std::declval<Range>()));
|
||||
|
||||
template<typename T>
|
||||
constexpr bool range_ =
|
||||
is_detected_v<iterator_, T> && is_detected_v<sentinel_, T>;
|
||||
|
||||
template<typename T>
|
||||
using has_insert_ = decltype(std::declval<T &>().insert(
|
||||
std::declval<T>().begin(), *std::declval<T>().begin()));
|
||||
|
||||
template<typename T>
|
||||
constexpr bool container_ = is_detected_v<has_insert_, T>;
|
||||
|
||||
template<typename R>
|
||||
constexpr bool view = range_<R> && !container_<R>;
|
||||
|
||||
template<
|
||||
typename R,
|
||||
typename Enable = std::enable_if_t<range_<R> && std::is_object_v<R>>>
|
||||
struct ref_view : stl_interfaces::view_interface<ref_view<R>>
|
||||
{
|
||||
template<
|
||||
typename T,
|
||||
typename Enable2 = std::enable_if_t<
|
||||
!std::
|
||||
is_same_v<remove_cv_ref_t<T>, remove_cv_ref_t<ref_view>> &&
|
||||
std::is_convertible_v<T, R &>>>
|
||||
constexpr ref_view(T && t) :
|
||||
r_(std::addressof(static_cast<R &>((T &&) t)))
|
||||
{}
|
||||
constexpr R & base() const { return *r_; }
|
||||
constexpr iterator_<R> begin() const
|
||||
{
|
||||
return text::detail::begin(*r_);
|
||||
}
|
||||
constexpr sentinel_<R> end() const { return text::detail::end(*r_); }
|
||||
|
||||
private:
|
||||
R * r_;
|
||||
};
|
||||
|
||||
template<typename R>
|
||||
ref_view(R &) -> ref_view<R>;
|
||||
|
||||
template<typename R>
|
||||
struct owning_view : stl_interfaces::view_interface<owning_view<R>>
|
||||
{
|
||||
owning_view() = default;
|
||||
constexpr owning_view(R && t) : r_(std::move(t)) {}
|
||||
|
||||
owning_view(owning_view &&) = default;
|
||||
owning_view & operator=(owning_view &&) = default;
|
||||
|
||||
constexpr R & base() & noexcept { return r_; }
|
||||
constexpr const R & base() const & noexcept { return r_; }
|
||||
constexpr R && base() && noexcept { return std::move(r_); }
|
||||
constexpr const R && base() const && noexcept { return std::move(r_); }
|
||||
|
||||
constexpr iterator_<R> begin() { return text::detail::begin(r_); }
|
||||
constexpr sentinel_<R> end() { return text::detail::end(r_); }
|
||||
|
||||
constexpr auto begin() const { return text::detail::begin(r_); }
|
||||
constexpr auto end() const { return text::detail::end(r_); }
|
||||
|
||||
private:
|
||||
R r_ = R();
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
using can_ref_view_expr = decltype(ref_view(std::declval<T>()));
|
||||
template<typename T>
|
||||
constexpr bool can_ref_view = is_detected_v<can_ref_view_expr, T>;
|
||||
|
||||
struct all_impl
|
||||
{
|
||||
template<typename R, typename Enable = std::enable_if_t<range_<R>>>
|
||||
[[nodiscard]] constexpr auto operator()(R && r) const
|
||||
{
|
||||
if constexpr (view<remove_cv_ref_t<R>>)
|
||||
return (R &&) r;
|
||||
else if constexpr (can_ref_view<R>)
|
||||
return ref_view((R &&) r);
|
||||
else
|
||||
return owning_view((R &&) r);
|
||||
}
|
||||
};
|
||||
|
||||
constexpr all_impl all;
|
||||
|
||||
#if BOOST_PARSER_DETAIL_TEXT_USE_CONCEPTS
|
||||
template<typename R>
|
||||
using all_t = std::views::all_t<R>;
|
||||
#else
|
||||
template<typename R>
|
||||
using all_t = decltype(all(std::declval<R>()));
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -8,6 +8,7 @@
|
||||
|
||||
#include <boost/parser/detail/text/transcode_algorithm.hpp>
|
||||
#include <boost/parser/detail/text/transcode_iterator.hpp>
|
||||
#include <boost/parser/detail/text/detail/all_t.hpp>
|
||||
|
||||
#include <boost/parser/detail/stl_interfaces/view_interface.hpp>
|
||||
#include <boost/parser/detail/stl_interfaces/view_adaptor.hpp>
|
||||
@@ -386,11 +387,11 @@ namespace boost::parser::detail { namespace text {
|
||||
|
||||
#if BOOST_PARSER_DETAIL_TEXT_USE_CONCEPTS
|
||||
template<class R>
|
||||
char8_view(R &&) -> char8_view<std::views::all_t<R>>;
|
||||
char8_view(R &&) -> char8_view<detail::all_t<R>>;
|
||||
template<class R>
|
||||
char16_view(R &&) -> char16_view<std::views::all_t<R>>;
|
||||
char16_view(R &&) -> char16_view<detail::all_t<R>>;
|
||||
template<class R>
|
||||
char32_view(R &&) -> char32_view<std::views::all_t<R>>;
|
||||
char32_view(R &&) -> char32_view<detail::all_t<R>>;
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -481,10 +482,8 @@ namespace boost::parser::detail { namespace text {
|
||||
constexpr auto end() const { return code_units().end(); }
|
||||
};
|
||||
|
||||
#if BOOST_PARSER_DETAIL_TEXT_USE_CONCEPTS
|
||||
template<class R>
|
||||
unpacking_view(R &&) -> unpacking_view<std::views::all_t<R>>;
|
||||
#endif
|
||||
unpacking_view(R &&) -> unpacking_view<detail::all_t<R>>;
|
||||
// clang-format on
|
||||
|
||||
#if BOOST_PARSER_DETAIL_TEXT_USE_CONCEPTS
|
||||
@@ -675,13 +674,13 @@ namespace boost::parser::detail { namespace text {
|
||||
{}
|
||||
};
|
||||
|
||||
#if BOOST_PARSER_DETAIL_TEXT_USE_CONCEPTS
|
||||
#if !BOOST_PARSER_DETAIL_TEXT_USE_ALIAS_CTAD
|
||||
template<class R>
|
||||
utf8_view(R &&) -> utf8_view<std::views::all_t<R>>;
|
||||
utf8_view(R &&) -> utf8_view<detail::all_t<R>>;
|
||||
template<class R>
|
||||
utf16_view(R &&) -> utf16_view<std::views::all_t<R>>;
|
||||
utf16_view(R &&) -> utf16_view<detail::all_t<R>>;
|
||||
template<class R>
|
||||
utf32_view(R &&) -> utf32_view<std::views::all_t<R>>;
|
||||
utf32_view(R &&) -> utf32_view<detail::all_t<R>>;
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
@@ -386,7 +386,6 @@ namespace boost::parser {
|
||||
};
|
||||
|
||||
// deduction guides
|
||||
#if BOOST_PARSER_USE_CONCEPTS
|
||||
template<
|
||||
typename V,
|
||||
typename ReplacementV,
|
||||
@@ -401,8 +400,8 @@ namespace boost::parser {
|
||||
ReplacementV &&,
|
||||
trace)
|
||||
-> replace_view<
|
||||
std::views::all_t<V>,
|
||||
std::views::all_t<ReplacementV>,
|
||||
detail::text::detail::all_t<V>,
|
||||
detail::text::detail::all_t<ReplacementV>,
|
||||
Parser,
|
||||
GlobalState,
|
||||
ErrorHandler,
|
||||
@@ -421,8 +420,8 @@ namespace boost::parser {
|
||||
parser_interface<SkipParser>,
|
||||
ReplacementV &&)
|
||||
-> replace_view<
|
||||
std::views::all_t<V>,
|
||||
std::views::all_t<ReplacementV>,
|
||||
detail::text::detail::all_t<V>,
|
||||
detail::text::detail::all_t<ReplacementV>,
|
||||
Parser,
|
||||
GlobalState,
|
||||
ErrorHandler,
|
||||
@@ -440,8 +439,8 @@ namespace boost::parser {
|
||||
ReplacementV &&,
|
||||
trace)
|
||||
-> replace_view<
|
||||
std::views::all_t<V>,
|
||||
std::views::all_t<ReplacementV>,
|
||||
detail::text::detail::all_t<V>,
|
||||
detail::text::detail::all_t<ReplacementV>,
|
||||
Parser,
|
||||
GlobalState,
|
||||
ErrorHandler,
|
||||
@@ -458,50 +457,12 @@ namespace boost::parser {
|
||||
parser_interface<Parser, GlobalState, ErrorHandler>,
|
||||
ReplacementV &&)
|
||||
-> replace_view<
|
||||
std::views::all_t<V>,
|
||||
std::views::all_t<ReplacementV>,
|
||||
detail::text::detail::all_t<V>,
|
||||
detail::text::detail::all_t<ReplacementV>,
|
||||
Parser,
|
||||
GlobalState,
|
||||
ErrorHandler,
|
||||
parser_interface<eps_parser<detail::phony>>>;
|
||||
#else
|
||||
template<
|
||||
typename V,
|
||||
typename ReplacementV,
|
||||
typename Parser,
|
||||
typename GlobalState,
|
||||
typename ErrorHandler>
|
||||
replace_view(
|
||||
V &&,
|
||||
parser_interface<Parser, GlobalState, ErrorHandler>,
|
||||
ReplacementV &&,
|
||||
trace)
|
||||
-> replace_view<
|
||||
V,
|
||||
ReplacementV,
|
||||
Parser,
|
||||
GlobalState,
|
||||
ErrorHandler,
|
||||
parser_interface<eps_parser<detail::phony>>>;
|
||||
|
||||
template<
|
||||
typename V,
|
||||
typename ReplacementV,
|
||||
typename Parser,
|
||||
typename GlobalState,
|
||||
typename ErrorHandler>
|
||||
replace_view(
|
||||
V &&,
|
||||
parser_interface<Parser, GlobalState, ErrorHandler>,
|
||||
ReplacementV &&)
|
||||
-> replace_view<
|
||||
V,
|
||||
ReplacementV,
|
||||
Parser,
|
||||
GlobalState,
|
||||
ErrorHandler,
|
||||
parser_interface<eps_parser<detail::phony>>>;
|
||||
#endif
|
||||
|
||||
namespace detail {
|
||||
template<
|
||||
|
||||
@@ -426,7 +426,6 @@ namespace boost::parser {
|
||||
};
|
||||
|
||||
// deduction guides
|
||||
#if BOOST_PARSER_USE_CONCEPTS
|
||||
template<
|
||||
typename V,
|
||||
typename Parser,
|
||||
@@ -439,7 +438,7 @@ namespace boost::parser {
|
||||
parser_interface<SkipParser>,
|
||||
trace)
|
||||
-> search_all_view<
|
||||
std::views::all_t<V>,
|
||||
detail::text::detail::all_t<V>,
|
||||
Parser,
|
||||
GlobalState,
|
||||
ErrorHandler,
|
||||
@@ -456,7 +455,7 @@ namespace boost::parser {
|
||||
parser_interface<Parser, GlobalState, ErrorHandler>,
|
||||
parser_interface<SkipParser>)
|
||||
-> search_all_view<
|
||||
std::views::all_t<V>,
|
||||
detail::text::detail::all_t<V>,
|
||||
Parser,
|
||||
GlobalState,
|
||||
ErrorHandler,
|
||||
@@ -470,7 +469,7 @@ namespace boost::parser {
|
||||
search_all_view(
|
||||
V &&, parser_interface<Parser, GlobalState, ErrorHandler>, trace)
|
||||
-> search_all_view<
|
||||
std::views::all_t<V>,
|
||||
detail::text::detail::all_t<V>,
|
||||
Parser,
|
||||
GlobalState,
|
||||
ErrorHandler,
|
||||
@@ -483,39 +482,11 @@ namespace boost::parser {
|
||||
typename ErrorHandler>
|
||||
search_all_view(V &&, parser_interface<Parser, GlobalState, ErrorHandler>)
|
||||
-> search_all_view<
|
||||
std::views::all_t<V>,
|
||||
detail::text::detail::all_t<V>,
|
||||
Parser,
|
||||
GlobalState,
|
||||
ErrorHandler,
|
||||
parser_interface<eps_parser<detail::phony>>>;
|
||||
#else
|
||||
template<
|
||||
typename V,
|
||||
typename Parser,
|
||||
typename GlobalState,
|
||||
typename ErrorHandler>
|
||||
search_all_view(
|
||||
V &&, parser_interface<Parser, GlobalState, ErrorHandler>, trace)
|
||||
-> search_all_view<
|
||||
V,
|
||||
Parser,
|
||||
GlobalState,
|
||||
ErrorHandler,
|
||||
parser_interface<eps_parser<detail::phony>>>;
|
||||
|
||||
template<
|
||||
typename V,
|
||||
typename Parser,
|
||||
typename GlobalState,
|
||||
typename ErrorHandler>
|
||||
search_all_view(V &&, parser_interface<Parser, GlobalState, ErrorHandler>)
|
||||
-> search_all_view<
|
||||
V,
|
||||
Parser,
|
||||
GlobalState,
|
||||
ErrorHandler,
|
||||
parser_interface<eps_parser<detail::phony>>>;
|
||||
#endif
|
||||
|
||||
namespace detail {
|
||||
template<
|
||||
|
||||
@@ -153,7 +153,6 @@ namespace boost::parser {
|
||||
};
|
||||
|
||||
// deduction guides
|
||||
#if BOOST_PARSER_USE_CONCEPTS
|
||||
template<
|
||||
typename V,
|
||||
typename Parser,
|
||||
@@ -166,7 +165,7 @@ namespace boost::parser {
|
||||
parser_interface<SkipParser>,
|
||||
trace)
|
||||
-> split_view<
|
||||
std::views::all_t<V>,
|
||||
detail::text::detail::all_t<V>,
|
||||
Parser,
|
||||
GlobalState,
|
||||
ErrorHandler,
|
||||
@@ -183,7 +182,7 @@ namespace boost::parser {
|
||||
parser_interface<Parser, GlobalState, ErrorHandler>,
|
||||
parser_interface<SkipParser>)
|
||||
-> split_view<
|
||||
std::views::all_t<V>,
|
||||
detail::text::detail::all_t<V>,
|
||||
Parser,
|
||||
GlobalState,
|
||||
ErrorHandler,
|
||||
@@ -197,7 +196,7 @@ namespace boost::parser {
|
||||
split_view(
|
||||
V &&, parser_interface<Parser, GlobalState, ErrorHandler>, trace)
|
||||
-> split_view<
|
||||
std::views::all_t<V>,
|
||||
detail::text::detail::all_t<V>,
|
||||
Parser,
|
||||
GlobalState,
|
||||
ErrorHandler,
|
||||
@@ -210,39 +209,11 @@ namespace boost::parser {
|
||||
typename ErrorHandler>
|
||||
split_view(V &&, parser_interface<Parser, GlobalState, ErrorHandler>)
|
||||
-> split_view<
|
||||
std::views::all_t<V>,
|
||||
detail::text::detail::all_t<V>,
|
||||
Parser,
|
||||
GlobalState,
|
||||
ErrorHandler,
|
||||
parser_interface<eps_parser<detail::phony>>>;
|
||||
#else
|
||||
template<
|
||||
typename V,
|
||||
typename Parser,
|
||||
typename GlobalState,
|
||||
typename ErrorHandler>
|
||||
split_view(
|
||||
V &&, parser_interface<Parser, GlobalState, ErrorHandler>, trace)
|
||||
-> split_view<
|
||||
V,
|
||||
Parser,
|
||||
GlobalState,
|
||||
ErrorHandler,
|
||||
parser_interface<eps_parser<detail::phony>>>;
|
||||
|
||||
template<
|
||||
typename V,
|
||||
typename Parser,
|
||||
typename GlobalState,
|
||||
typename ErrorHandler>
|
||||
split_view(V &&, parser_interface<Parser, GlobalState, ErrorHandler>)
|
||||
-> split_view<
|
||||
V,
|
||||
Parser,
|
||||
GlobalState,
|
||||
ErrorHandler,
|
||||
parser_interface<eps_parser<detail::phony>>>;
|
||||
#endif
|
||||
|
||||
namespace detail {
|
||||
template<
|
||||
|
||||
@@ -46,6 +46,7 @@ macro(add_test_executable name)
|
||||
add_test(NAME ${name} COMMAND ${name} --gtest_catch_exceptions=1)
|
||||
endmacro()
|
||||
|
||||
add_test_executable(all_t)
|
||||
add_test_executable(search)
|
||||
add_test_executable(split)
|
||||
add_test_executable(replace)
|
||||
|
||||
63
test/all_t.cpp
Normal file
63
test/all_t.cpp
Normal file
@@ -0,0 +1,63 @@
|
||||
/**
|
||||
* Copyright (C) 2024 T. Zachary Laine
|
||||
*
|
||||
* 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)
|
||||
*/
|
||||
|
||||
#include <boost/parser/config.hpp>
|
||||
#include <boost/parser/detail/text/detail/all_t.hpp>
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
|
||||
using namespace boost::parser::detail::text;
|
||||
|
||||
TEST(all_t, basic)
|
||||
{
|
||||
std::string str;
|
||||
std::string const const_str;
|
||||
|
||||
{
|
||||
auto && result = detail::all(
|
||||
BOOST_PARSER_SUBRANGE(const_str.begin(), const_str.end()));
|
||||
static_assert(std::is_same_v<
|
||||
decltype(result),
|
||||
BOOST_PARSER_SUBRANGE<decltype(const_str.begin())> &&>);
|
||||
}
|
||||
{
|
||||
auto && result = detail::all(str);
|
||||
static_assert(
|
||||
std::is_same_v<decltype(result), detail::ref_view<std::string> &&>);
|
||||
}
|
||||
{
|
||||
auto && result = detail::all(const_str);
|
||||
static_assert(std::is_same_v<
|
||||
decltype(result),
|
||||
detail::ref_view<std::string const> &&>);
|
||||
}
|
||||
{
|
||||
auto && result = detail::all(std::string{});
|
||||
static_assert(std::is_same_v<
|
||||
decltype(result),
|
||||
detail::owning_view<std::string> &&>);
|
||||
}
|
||||
|
||||
static_assert(
|
||||
std::is_same_v<
|
||||
detail::all_t<BOOST_PARSER_SUBRANGE<decltype(const_str.begin())>>,
|
||||
BOOST_PARSER_SUBRANGE<decltype(const_str.begin())>>);
|
||||
|
||||
static_assert(std::is_same_v<
|
||||
detail::all_t<std::string &>,
|
||||
detail::ref_view<std::string>>);
|
||||
|
||||
static_assert(std::is_same_v<
|
||||
detail::all_t<std::string const &>,
|
||||
detail::ref_view<std::string const>>);
|
||||
|
||||
static_assert(std::is_same_v<
|
||||
detail::all_t<std::string &&>,
|
||||
detail::owning_view<std::string>>);
|
||||
}
|
||||
Reference in New Issue
Block a user