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
45 changes: 15 additions & 30 deletions include/rfl/Literal.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
#include "Result.hpp"
#include "Tuple.hpp"
#include "internal/StringLiteral.hpp"
#include "internal/find_index.hpp"
#include "internal/no_duplicate_field_names.hpp"

namespace rfl {
Expand Down Expand Up @@ -95,31 +96,24 @@ class Literal {

/// Determines whether the literal contains any of the strings in the other
/// literal at compile time.
template <class OtherLiteralType, int _i = 0>
template <class OtherLiteralType>
static constexpr bool contains_any() {
if constexpr (_i == num_fields_) {
return false;
} else {
constexpr auto name = find_name_within_own_fields<_i>();
return OtherLiteralType::template contains<name>() ||
contains_any<OtherLiteralType, _i + 1>();
}
return []<int... _is>(const std::integer_sequence<int, _is...>&) {
return (false || ... ||
OtherLiteralType::template contains<
find_name_within_own_fields<_is>()>());
}(std::make_integer_sequence<int, num_fields_>());
}

/// Determines whether the literal contains all of the strings in the other
/// literal at compile time.
template <class OtherLiteralType, int _i = 0, int _n_found = 0>
template <class OtherLiteralType>
static constexpr bool contains_all() {
if constexpr (_i == num_fields_) {
return _n_found == OtherLiteralType::num_fields_;
} else {
constexpr auto name = find_name_within_own_fields<_i>();
if constexpr (OtherLiteralType::template contains<name>()) {
return contains_all<OtherLiteralType, _i + 1, _n_found + 1>();
} else {
return contains_all<OtherLiteralType, _i + 1, _n_found>();
}
}
return []<int... _is>(const std::integer_sequence<int, _is...>&) {
return (true && ... &&
OtherLiteralType::template contains<
find_name_within_own_fields<_is>()>());
}(std::make_integer_sequence<int, num_fields_>());
}

/// Determines whether the literal has duplicate strings at compile time.
Expand Down Expand Up @@ -332,18 +326,9 @@ class Literal {
}

/// Finds the value of a string literal at compile time.
template <internal::StringLiteral _name, int _i = 0>
template <internal::StringLiteral _name>
static constexpr int find_value_of() {
if constexpr (_i == num_fields_) {
return -1;
} else {
using FieldType = tuple_element_t<_i, FieldsType>;
if constexpr (FieldType::name_ == _name) {
return _i;
} else {
return find_value_of<_name, _i + 1>();
}
}
return internal::find_index_or_minus_one<_name, FieldsType>();
}

/// Whether the literal contains this string.
Expand Down
16 changes: 16 additions & 0 deletions include/rfl/internal/find_index.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,22 @@ constexpr static int find_index() {
return ix;
}

/// Finds the index of the field signified by _field_name or -1.
template <StringLiteral _field_name, class Fields>
constexpr static int find_index_or_minus_one() {
if constexpr (rfl::tuple_size_v<Fields> == 0) {
return -1;
} else {
constexpr int ix = wrap_fields<_field_name, Fields>(
std::make_integer_sequence<int, rfl::tuple_size_v<Fields>>());
if constexpr (rfl::tuple_element_t<ix, Fields>::name_ == _field_name) {
return ix;
} else {
return -1;
}
}
}

} // namespace internal
} // namespace rfl

Expand Down
5 changes: 5 additions & 0 deletions tests/json/test_literal.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,11 @@ struct Person {
};

TEST(json, test_literal) {
static_assert(!FirstName::template contains_any<LastName>(),
"Must be false.");
static_assert(FirstName::template contains_any<FirstName>(), "Must be true.");
static_assert(FirstName::template contains_all<FirstName>(), "Must be true.");

const auto bart = Person{.first_name = FirstName::make<"Bart">()};

write_and_read(bart,
Expand Down
Loading