Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions include/iris/x4/attribute.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@
==============================================================================*/

#include <iris/config.hpp>
#include <iris/x4/attribute/as.hpp>
#include <iris/x4/attribute/as.hpp> // IWYU pragma: export
// #include <iris/x4/attribute/smart_ptr.hpp> // excluded
#include <iris/x4/attribute/value.hpp>
#include <iris/x4/attribute/value.hpp> // IWYU pragma: export

#endif
6 changes: 4 additions & 2 deletions include/iris/x4/attribute/as.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ struct as_type_parser_ctx_impl<true, Context, OuterAttr>
// to be `T`. When `T` is `unused_type`, this is equivalent to
// `omit_directive`.
template<X4Attribute T, class Subject>
struct as_type_parser : unary_parser<Subject, as_type_parser<T, Subject>>
struct as_type_parser : unary_parser<as_type_parser<T, Subject>, Subject>
{
static_assert(!std::is_const_v<T>); // Forbid const `unused_type`
static_assert(!std::same_as<T, unused_container_type>); // Unknown use case, not supported for now
Expand All @@ -65,6 +65,8 @@ struct as_type_parser : unary_parser<Subject, as_type_parser<T, Subject>>
// `parser_traits<as_type_parser<...>>::handles_container` must transparently
// handle this case.

using unary_parser<as_type_parser, Subject>::unary_parser;

private:
template<X4Attribute Attr>
using exposed_attr_for_child_t = std::conditional_t<
Expand Down Expand Up @@ -151,7 +153,7 @@ struct as_fn
operator()(Subject&& subject)
noexcept(is_parser_nothrow_constructible_v<as_type_parser<T, as_parser_plain_t<Subject>>, Subject>)
{
return {std::forward<Subject>(subject)};
return as_type_parser<T, as_parser_plain_t<Subject>>{std::forward<Subject>(subject)};
}
};

Expand Down
25 changes: 8 additions & 17 deletions include/iris/x4/attribute/smart_ptr.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -45,9 +45,9 @@ struct [[nodiscard]] smart_ptr_rollback_guard

template<class Derived, class Subject, class T, class DeleterT>
struct unique_ptr_parser_base
: proxy_parser<Subject, Derived>
: proxy_parser<Derived, Subject>
{
using base_type = proxy_parser<Subject, Derived>;
using base_type = proxy_parser<Derived, Subject>;

// https://eel.is/c++draft/unique.ptr.single.ctor

Expand Down Expand Up @@ -115,18 +115,9 @@ struct unique_ptr_parser_base

template<class Derived, class Subject, class T>
struct unique_ptr_parser_base<Derived, Subject, T, std::default_delete<T>>
: proxy_parser<Subject, Derived>
: proxy_parser<Derived, Subject>
{
using base_type = proxy_parser<Subject, Derived>;

template<class SubjectT>
requires
(!std::same_as<std::remove_cvref_t<SubjectT>, Derived>) &&
std::is_constructible_v<base_type, SubjectT>
constexpr explicit unique_ptr_parser_base(SubjectT&& subject)
noexcept(std::is_nothrow_constructible_v<base_type, SubjectT>)
: base_type(std::forward<SubjectT>(subject))
{}
using proxy_parser<Derived, Subject>::proxy_parser;

template<std::forward_iterator It, std::sentinel_for<It> Se, class Context, X4Attribute Attr>
[[nodiscard]] constexpr bool
Expand Down Expand Up @@ -219,9 +210,9 @@ namespace detail {

template<class Derived, class Subject, class T, class DeleterT>
struct shared_ptr_parser_base
: proxy_parser<Subject, Derived>
: proxy_parser<Derived, Subject>
{
using base_type = proxy_parser<Subject, Derived>;
using base_type = proxy_parser<Derived, Subject>;

// https://eel.is/c++draft/util.smartptr.shared.const

Expand Down Expand Up @@ -287,9 +278,9 @@ struct shared_ptr_parser_base

template<class Derived, class Subject, class T>
struct shared_ptr_parser_base<Derived, Subject, T, std::default_delete<T>>
: proxy_parser<Subject, Derived>
: proxy_parser<Derived, Subject>
{
using base_type = proxy_parser<Subject, Derived>;
using base_type = proxy_parser<Derived, Subject>;

template<class SubjectT>
requires
Expand Down
48 changes: 29 additions & 19 deletions include/iris/x4/attribute/value.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
#include <iterator>
#include <type_traits>
#include <utility>
#include <initializer_list>

namespace iris::x4 {

Expand All @@ -32,42 +33,51 @@ struct fixed_value_parser : parser<fixed_value_parser<T, HeldValueT>>
{
static_assert(X4Attribute<T>);
static_assert(!X4UnusedAttribute<T>, "fixed_value_parser with `unused_type` is meaningless");
static_assert(X4Movable<HeldValueT const&, T>);

// `HeldValueT` is almost always equal to `T`.
//
// The most notable situation where they differ is when `fixed_value_parser` is initialized
// by `char const (&)[N]`. In such case, `fixed_value_parser` must hold the value by
// `std::string_view`, instead of `std::string`, to be constexpr.

static_assert(X4Movable<HeldValueT const&, T>);

using attribute_type = T;
using held_value_type = HeldValueT;

template<class U>
constexpr fixed_value_parser() = default;

template<class U, class... Rest>
requires
(!std::is_same_v<std::remove_cvref_t<U>, fixed_value_parser>) &&
std::is_constructible_v<HeldValueT, U>
constexpr explicit fixed_value_parser(U&& value)
noexcept(std::is_nothrow_constructible_v<HeldValueT, U>)
: held_value_(std::forward<U>(value))
// This exclusion is mandatory because `HeldValueT` can be a weakly constrained
// type such as `std::any`
(!std::is_base_of_v<fixed_value_parser, std::remove_cvref_t<U>>) &&
std::is_constructible_v<HeldValueT, U, Rest...>
constexpr explicit fixed_value_parser(U&& arg, Rest&&... rest)
noexcept(std::is_nothrow_constructible_v<HeldValueT, U, Rest...>)
: held_value_(std::forward<U>(arg), std::forward<Rest>(rest)...)
{}

template<class U, class... Args>
requires std::is_constructible_v<HeldValueT, std::initializer_list<U>&, Args...>
constexpr explicit fixed_value_parser(std::initializer_list<U> il, Args&&... args)
noexcept(std::is_nothrow_constructible_v<HeldValueT, std::initializer_list<U>&, Args...>)
: held_value_(il, std::forward<Args>(args)...)
{}

template<std::forward_iterator It, std::sentinel_for<It> Se, class Context, X4Attribute Attr>
[[nodiscard]] constexpr bool
parse(It&, Se const&, Context const&, Attr& attr_) const
noexcept(noexcept(x4::move_to(std::as_const(held_value_), attr_)))
parse(It&, Se const&, Context const&, Attr& exposed_attr) const
noexcept(noexcept(x4::move_to(std::declval<HeldValueT const&>(), exposed_attr)))
{
// Always copy (need reuse in repetitive invocations)
x4::move_to(std::as_const(held_value_), attr_);
x4::move_to(this->held_value_, exposed_attr);
return true;
}

private:
HeldValueT held_value_;
IRIS_NO_UNIQUE_ADDRESS HeldValueT held_value_{};
};

// `reset_value<T>`
// aka `reset_value<T>`
template<class T>
struct fixed_value_parser<T, void> : parser<fixed_value_parser<T, void>>
{
Expand All @@ -86,19 +96,19 @@ struct fixed_value_parser<T, void> : parser<fixed_value_parser<T, void>>
template<std::forward_iterator It, std::sentinel_for<It> Se, class Context, X4NonUnusedAttribute ContainerAttr>
requires traits::CategorizedAttr<ContainerAttr, traits::container_attr>
[[nodiscard]] static constexpr bool
parse(It&, Se const&, Context const&, ContainerAttr& container_attr) noexcept
parse(It&, Se const&, Context const&, ContainerAttr& exposed_attr) noexcept
{
traits::clear(container_attr);
traits::clear(exposed_attr);
return true;
}

template<std::forward_iterator It, std::sentinel_for<It> Se, class Context, X4NonUnusedAttribute Attr>
requires (!traits::CategorizedAttr<Attr, traits::container_attr>)
[[nodiscard]] static constexpr bool
parse(It&, Se const&, Context const&, Attr& attr_)
noexcept(noexcept(attr_ = Attr{}))
parse(It&, Se const&, Context const&, Attr& exposed_attr)
noexcept(noexcept(exposed_attr = Attr{}))
{
attr_ = Attr{};
exposed_attr = Attr{};
return true;
}
};
Expand Down
16 changes: 9 additions & 7 deletions include/iris/x4/char.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,15 +10,17 @@
file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
==============================================================================*/

#include <iris/config.hpp>
#include <iris/x4/char/char_parser.hpp>
#include <iris/x4/char/negated_char.hpp>
#include <iris/x4/char/char.hpp>
#include <iris/x4/char/char_class.hpp>
#include <iris/x4/char/char_set.hpp>
#include <iris/config.hpp> // IWYU pragma: keep

#include <iris/x4/char_string_literal.hpp> // IWYU pragma: export

#include <iris/x4/char/char.hpp> // IWYU pragma: export
#include <iris/x4/char/char_parser.hpp> // IWYU pragma: export
#include <iris/x4/char/char_class.hpp> // IWYU pragma: export
#include <iris/x4/char/char_set.hpp> // IWYU pragma: export

#ifdef IRIS_X4_UNICODE
# include <iris/x4/char/unicode_char_class.hpp>
# include <iris/x4/char/unicode_char_class.hpp> // IWYU pragma: export
#endif

#endif
31 changes: 9 additions & 22 deletions include/iris/x4/char/any_char.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,19 +10,18 @@
file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
==============================================================================*/

#include <iris/x4/core/char_traits.hpp>
#include <iris/x4/char/literal_char.hpp>
#include <iris/x4/char/char_set.hpp>

namespace iris::x4 {

template<class Encoding>
struct any_char : char_parser<Encoding, any_char<Encoding>>
struct any_char : char_parser<any_char<Encoding>, Encoding>
{
using encoding_type = Encoding;
using attribute_type = typename Encoding::char_type;
using char_type = typename Encoding::char_type;
using classify_type = typename Encoding::classify_type;
using attribute_type = Encoding::char_type;
using char_type = Encoding::char_type;
using classify_type = Encoding::classify_type;

static constexpr bool has_attribute = true;

Expand All @@ -33,47 +32,35 @@ struct any_char : char_parser<Encoding, any_char<Encoding>>
return encoding_type::ischar(classify_ch);
}

static constexpr void
test(auto, auto const& /* ctx */) = delete; // Mixing incompatible char types is not allowed

template<std::same_as<char_type> CharT>
[[nodiscard]] static constexpr literal_char<Encoding>
operator()(CharT ch) noexcept
{
return {ch};
}

template<CharIncompatibleWith<char_type> CharT>
static constexpr void operator()(CharT) = delete; // Mixing incompatible char types is not allowed

template<std::same_as<char_type> CharT>
[[nodiscard]] static constexpr literal_char<Encoding>
operator()(char_type const (&ch)[2]) noexcept
operator()(CharT const (&ch)[2]) noexcept
{
return {ch[0]};
}

template<std::size_t N>
template<std::same_as<char_type> CharT, std::size_t N>
[[nodiscard]] static constexpr char_set<Encoding>
operator()(char_type const (&ch)[N])
operator()(CharT const (&ch)[N])
{
static_assert(N >= 3);
return char_set<Encoding>{ch};
}

template<CharIncompatibleWith<char_type> CharT, std::size_t N>
static constexpr void
operator()(CharT const (&)[N]) = delete; // Mixing incompatible char types is not allowed

template<std::same_as<char_type> CharT>
[[nodiscard]] static constexpr char_range<Encoding>
operator()(CharT from, CharT to) noexcept
{
return {from, to};
}

template<class From, class To>
requires CharIncompatibleWith<From, char_type> || CharIncompatibleWith<To, char_type>
static constexpr void operator()(From, To) = delete; // Mixing incompatible char types is not allowed

template<class From, std::size_t FromN, class To, std::size_t ToN>
static constexpr void
operator()(From const (&)[FromN], To const (&)[ToN]) = delete; // Use single character literal to define character range
Expand Down
Loading
Loading