Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for type checked term_at<T> and term_at<T>(i) #1397

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
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
44 changes: 44 additions & 0 deletions distr/flecs.h
Original file line number Diff line number Diff line change
Expand Up @@ -29730,6 +29730,8 @@ struct query_builder_i : term_builder_i<Base> {

/* Term notation for more complex query features */

/** Sets the current term to next one in term list.
*/
Base& term() {
if (this->term_) {
ecs_check(ecs_term_is_initialized(this->term_),
Expand All @@ -29748,6 +29750,30 @@ struct query_builder_i : term_builder_i<Base> {
return *this;
}

/** Sets the current term to the one with the provided type.
* This loops over all terms to find the one with the provided type.
* For performance-critical paths, use term_at(int32_t) instead.
*/
template <typename T>
Base& term_at() {
flecs::id_t term_id = _::type<T>::id(this->world_v());
for (int i = 0; i < term_index_; i ++) {
ecs_term_t cur_term = desc_->terms[i];
ecs_id_t cur_term_id = cur_term.id;
ecs_id_t cur_term_pair = ecs_pair(cur_term.first.id, cur_term.second.id);

if ((term_id == cur_term_id || (cur_term_id != 0 && term_id == ecs_get_typeid(this->world_v(), cur_term_id))) ||
(term_id == cur_term_pair || (cur_term_pair != 0 && term_id == ecs_get_typeid(this->world_v(), cur_term_pair)))) {
return term_at(i);
}
}

ecs_err("term not found");
return *this;
}

/** Sets the current term to the one at the provided index.
*/
Base& term_at(int32_t term_index) {
ecs_assert(term_index >= 0, ECS_INVALID_PARAMETER, NULL);
int32_t prev_index = term_index_;
Expand All @@ -29759,6 +29785,24 @@ struct query_builder_i : term_builder_i<Base> {
return *this;
}

/** Sets the current term to the one at the provided index and asserts that the type matches.
*/
template <typename T>
Base& term_at(int32_t term_index) {
this->term_at(term_index);
#if !defined(FLECS_NDEBUG) || defined(FLECS_KEEP_ASSERT)
flecs::id_t term_id = _::type<T>::id(this->world_v());
ecs_term_t cur_term = *this->term_;
ecs_id_t cur_term_id = cur_term.id;
ecs_id_t cur_term_pair = ecs_pair(cur_term.first.id, cur_term.second.id);

ecs_assert((term_id == cur_term_id || (cur_term_id != 0 && term_id == ecs_get_typeid(this->world_v(), cur_term_id))) ||
(term_id == cur_term_pair || (cur_term_pair != 0 && term_id == ecs_get_typeid(this->world_v(), cur_term_pair))),
ECS_INVALID_PARAMETER, "term type mismatch");
#endif
return *this;
}

/** Sort the output of a query.
* This enables sorting of entities across matched tables. As a result of this
* operation, the order of entities in the matched tables may be changed.
Expand Down
44 changes: 44 additions & 0 deletions include/flecs/addons/cpp/mixins/query/builder_i.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -217,6 +217,8 @@ struct query_builder_i : term_builder_i<Base> {

/* Term notation for more complex query features */

/** Sets the current term to next one in term list.
*/
Base& term() {
if (this->term_) {
ecs_check(ecs_term_is_initialized(this->term_),
Expand All @@ -235,6 +237,30 @@ struct query_builder_i : term_builder_i<Base> {
return *this;
}

/** Sets the current term to the one with the provided type.
* This loops over all terms to find the one with the provided type.
* For performance-critical paths, use term_at(int32_t) instead.
*/
template <typename T>
Base& term_at() {
flecs::id_t term_id = _::type<T>::id(this->world_v());
for (int i = 0; i < term_index_; i ++) {
ecs_term_t cur_term = desc_->terms[i];
ecs_id_t cur_term_id = cur_term.id;
ecs_id_t cur_term_pair = ecs_pair(cur_term.first.id, cur_term.second.id);

if ((term_id == cur_term_id || (cur_term_id != 0 && term_id == ecs_get_typeid(this->world_v(), cur_term_id))) ||
(term_id == cur_term_pair || (cur_term_pair != 0 && term_id == ecs_get_typeid(this->world_v(), cur_term_pair)))) {
return term_at(i);
}
}

ecs_err("term not found");
return *this;
}

/** Sets the current term to the one at the provided index.
*/
Base& term_at(int32_t term_index) {
ecs_assert(term_index >= 0, ECS_INVALID_PARAMETER, NULL);
int32_t prev_index = term_index_;
Expand All @@ -246,6 +272,24 @@ struct query_builder_i : term_builder_i<Base> {
return *this;
}

/** Sets the current term to the one at the provided index and asserts that the type matches.
*/
template <typename T>
Base& term_at(int32_t term_index) {
this->term_at(term_index);
#if !defined(FLECS_NDEBUG) || defined(FLECS_KEEP_ASSERT)
flecs::id_t term_id = _::type<T>::id(this->world_v());
ecs_term_t cur_term = *this->term_;
ecs_id_t cur_term_id = cur_term.id;
ecs_id_t cur_term_pair = ecs_pair(cur_term.first.id, cur_term.second.id);

ecs_assert((term_id == cur_term_id || (cur_term_id != 0 && term_id == ecs_get_typeid(this->world_v(), cur_term_id))) ||
(term_id == cur_term_pair || (cur_term_pair != 0 && term_id == ecs_get_typeid(this->world_v(), cur_term_pair))),
ECS_INVALID_PARAMETER, "term type mismatch");
#endif
return *this;
}

/** Sort the output of a query.
* This enables sorting of entities across matched tables. As a result of this
* operation, the order of entities in the matched tables may be changed.
Expand Down
2 changes: 2 additions & 0 deletions test/cpp/project.json
Original file line number Diff line number Diff line change
Expand Up @@ -747,6 +747,8 @@
"relation_w_predicate_wildcard",
"add_pair_w_rel_type",
"template_term",
"typed_term_at",
"typed_term_at_indexed",
"explicit_subject_w_id",
"explicit_subject_w_type",
"explicit_object_w_id",
Expand Down
48 changes: 48 additions & 0 deletions test/cpp/src/QueryBuilder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1592,6 +1592,54 @@ void QueryBuilder_template_term(void) {
test_int(count, 1);
}

void QueryBuilder_typed_term_at(void) {
flecs::world ecs;

struct Rel { int foo; };

int32_t count = 0;

auto s = ecs.system<Rel, const Velocity>()
.term_at<Velocity>().singleton()
.term_at<Rel>().second(flecs::Wildcard)
.run([&](flecs::iter it){
while (it.next()) {
count += it.count();
}
});

ecs.entity().add<Rel, Tag>();
ecs.set<Velocity>({});

s.run();

test_int(count, 1);
}

void QueryBuilder_typed_term_at_indexed(void) {
flecs::world ecs;

struct Rel { int foo; };

int32_t count = 0;

auto s = ecs.system<Rel, const Velocity>()
.term_at<Velocity>(1).singleton()
.term_at<Rel>(0).second(flecs::Wildcard)
.run([&](flecs::iter it){
while (it.next()) {
count += it.count();
}
});

ecs.entity().add<Rel, Tag>();
ecs.set<Velocity>({});

s.run();

test_int(count, 1);
}

void QueryBuilder_explicit_subject_w_id(void) {
flecs::world ecs;

Expand Down
12 changes: 11 additions & 1 deletion test/cpp/src/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -718,6 +718,8 @@ void QueryBuilder_relation_w_object_wildcard(void);
void QueryBuilder_relation_w_predicate_wildcard(void);
void QueryBuilder_add_pair_w_rel_type(void);
void QueryBuilder_template_term(void);
void QueryBuilder_typed_term_at(void);
void QueryBuilder_typed_term_at_indexed(void);
void QueryBuilder_explicit_subject_w_id(void);
void QueryBuilder_explicit_subject_w_type(void);
void QueryBuilder_explicit_object_w_id(void);
Expand Down Expand Up @@ -4160,6 +4162,14 @@ bake_test_case QueryBuilder_testcases[] = {
"template_term",
QueryBuilder_template_term
},
{
"typed_term_at",
QueryBuilder_typed_term_at
},
{
"typed_term_at_indexed",
QueryBuilder_typed_term_at_indexed
},
{
"explicit_subject_w_id",
QueryBuilder_explicit_subject_w_id
Expand Down Expand Up @@ -6805,7 +6815,7 @@ static bake_test_suite suites[] = {
"QueryBuilder",
QueryBuilder_setup,
NULL,
166,
168,
QueryBuilder_testcases,
1,
QueryBuilder_params
Expand Down
Loading