Skip to content

Commit

Permalink
Add support for type checked term_at<T> and term_at<T>(i)
Browse files Browse the repository at this point in the history
First method is simple loop over terms to find term for T. Its slower
than using index directly, but sometimes type safety is more preferred
and when the cost is only on initialization.

Second method is same as term_at(i) but with type checked assert. For
middle ground to still keep the safety but also performance.

This is mostly to mirror the C# binding PR where this is slightly more
useful but maybe cpp would benefit too:

BeanCheeseBurrito/Flecs.NET#52

Signed-off-by: Tomas Slusny <[email protected]>
  • Loading branch information
deathbeam committed Oct 13, 2024
1 parent 5150a24 commit 5a80df7
Show file tree
Hide file tree
Showing 5 changed files with 111 additions and 1 deletion.
25 changes: 25 additions & 0 deletions distr/flecs.h
Original file line number Diff line number Diff line change
Expand Up @@ -29759,6 +29759,31 @@ struct query_builder_i : term_builder_i<Base> {
return *this;
}

template <typename T>
Base& term_at() {
flecs::id term_id = _::type<T>::id(this->world_v());

for (int i = 0; i < term_index_; i ++) {
if (desc_->terms[i].first.id == term_id) {
return *term_at(i);
}
}

ecs_assert(ecs_term_is_initialized(this->term_),
ECS_INVALID_PARAMETER, NULL);
ecs_assert(term_id == this->_term.first.id,
ECS_INVALID_PARAMETER, "term not found");
return *this;
}

template <typename T>
Base& term_at(int32_t term_index) {
this->term_at(term_index);
ecs_assert(this->_term.first.id == _::type<T>::id(this->world_v()),
ECS_INVALID_PARAMETER, "term type mismatch");
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
25 changes: 25 additions & 0 deletions include/flecs/addons/cpp/mixins/query/builder_i.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -246,6 +246,31 @@ struct query_builder_i : term_builder_i<Base> {
return *this;
}

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 ++) {
if (desc_->terms[i].first.id == term_id) {
return term_at(i);
}
}

ecs_assert(ecs_term_is_initialized(this->term_),
ECS_INVALID_PARAMETER, NULL);
ecs_assert(this->term_->first.id == term_id,
ECS_INVALID_PARAMETER, "term not found");
return *this;
}

template <typename T>
Base& term_at(int32_t term_index) {
this->term_at(term_index);
ecs_assert(this->term_->first.id == _::type<T>::id(this->world_v()),
ECS_INVALID_PARAMETER, "term type mismatch");
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",
"template_term_at",
"template_term_at_index",
"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_template_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_template_term_at_index(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_template_term_at(void);
void QueryBuilder_template_term_at_index(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
},
{
"template_term_at",
QueryBuilder_template_term_at
},
{
"template_term_at_index",
QueryBuilder_template_term_at_index
},
{
"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

0 comments on commit 5a80df7

Please sign in to comment.