Flecs: include/flecs/addons/cpp/iter.hpp Source File
Description: A fast entity component system (ECS) for C & C++

| Flecs v4.1 A fast entity component system (ECS) for C & C++

Loading...
Searching...
No Matches
iter.hpp
Go to the documentation of this file.
1
5
6#pragma once
7
15
16namespace flecs
17{
18
20
21namespace _ {
22
24
29template <typename T>
30 struct range_iterator
31{
32 explicit range_iterator(T value)
33 : value_(value){}
34
35 bool operator!=(range_iterator const& other) const
36 {
37 return value_ != other.value_;
38 }
39
40 T const& operator*() const
41 {
42 return value_;
43 }
44
45 range_iterator& operator++()
46 {
47 ++value_;
48 return *this;
49 }
50
51private:
52 T value_;
53};
54
55} // namespace _
56
57} // namespace flecs
58
59namespace flecs
60{
61
63
68 struct iter {
69private:
70 using row_iterator = _::range_iterator<size_t>;
71
72public:
78 iter(ecs_iter_t *it) : iter_(it) { }
79
81 row_iterator begin() const {
82 return row_iterator(0);
83 }
84
86 row_iterator end() const {
87 return row_iterator(static_cast<size_t>(iter_->count));
88 }
89
91 flecs::entity system() const;
92
94 flecs::entity event() const;
95
97 flecs::id event_id() const;
98
100 flecs::world world() const;
101
103 const flecs::iter_t* c_ptr() const {
104 return iter_;
105 }
106
111 size_t count() const {
112 ecs_check(iter_->flags & EcsIterIsValid, ECS_INVALID_PARAMETER,
113 "operation invalid before calling next()");
114 return static_cast<size_t>(iter_->count);
115 error:
116 return 0;
117 }
118
123 ecs_ftime_t delta_time() const {
124 return iter_->delta_time;
125 }
126
131 ecs_ftime_t delta_system_time() const {
132 return iter_->delta_system_time;
133 }
134
136 flecs::type type() const;
137
139 flecs::table table() const;
140
145 flecs::table other_table() const;
146
148 flecs::table_range range() const;
149
153 void* ctx() {
154 return iter_->ctx;
155 }
156
160 template <typename T>
161 T* ctx() {
162 return static_cast<T*>(iter_->ctx);
163 }
164
168 void* param() {
169 return iter_->param;
170 }
171
175 template <typename T>
176 T* param() {
177 /* TODO: type check */
178 return static_cast<T*>(iter_->param);
179 }
180
186 flecs::entity entity(size_t row) const;
187
193 bool is_self(int8_t index) const {
194 return ecs_field_is_self(iter_, index);
195 }
196
202 bool is_set(int8_t index) const {
203 return ecs_field_is_set(iter_, index);
204 }
205
211 bool is_readonly(int8_t index) const {
212 return ecs_field_is_readonly(iter_, index);
213 }
214
219 int32_t field_count() const {
220 return iter_->field_count;
221 }
222
228 size_t size(int8_t index) const {
229 return ecs_field_size(iter_, index);
230 }
231
237 flecs::entity src(int8_t index) const;
238
244 flecs::id id(int8_t index) const;
245
252 flecs::id pair(int8_t index) const;
253
259 int32_t column_index(int8_t index) const {
260 return ecs_field_column(iter_, index);
261 }
262
267 int8_t term_index() const {
268 return iter_->term_index;
269 }
270
275 flecs::string str() const {
276 char *s = ecs_iter_str(iter_);
277 return flecs::string(s);
278 }
279
292 template <typename T, typename A = actual_type_t<T>, if_t<is_const_v<T>> = 0>
293 flecs::field<A> field(int8_t index) const;
294
307 template <typename T, typename A = actual_type_t<T>, if_not_t<is_const_v<T>> = 0>
308 flecs::field<A> field(int8_t index) const;
309
320 flecs::untyped_field field(int8_t index) const {
321 ecs_assert(!(iter_->flags & EcsIterCppEach) ||
322 ecs_field_src(iter_, index) != 0, ECS_INVALID_OPERATION,
323 "cannot .field from .each, use .field_at(%d, row) instead", index);
324 return get_unchecked_field(index);
325 }
326
334 void* field_at(int8_t index, size_t row) const {
335 if (iter_->row_fields & (1llu << index)) {
336 return get_unchecked_field_at(index, row)[0];
337 } else {
338 return get_unchecked_field(index)[row];
339 }
340 }
341
350 template <typename T, typename A = actual_type_t<T>, if_t< is_const_v<T> > = 0>
351 const A& field_at(int8_t index, size_t row) const {
352 if (iter_->row_fields & (1llu << index)) {
353 return get_field_at<A>(index, row)[0];
354 } else {
355 return get_field<A>(index)[row];
356 }
357 }
358
367 template <typename T, typename A = actual_type_t<T>, if_not_t< is_const_v<T> > = 0>
368 A& field_at(int8_t index, size_t row) const {
369 ecs_assert(!ecs_field_is_readonly(iter_, index),
370 ECS_ACCESS_VIOLATION, nullptr);
371 if (iter_->row_fields & (1llu << index)) {
372 return get_field_at<A>(index, row)[0];
373 } else {
374 return get_field<A>(index)[row];
375 }
376 }
377
382 flecs::field<const flecs::entity_t> entities() const {
383 return flecs::field<const flecs::entity_t>(
384 iter_->entities, static_cast<size_t>(iter_->count), false);
385 }
386
392 bool changed() {
393 return ecs_iter_changed(iter_);
394 }
395
403 void skip() {
404 ecs_iter_skip(iter_);
405 }
406
411 uint64_t group_id() const {
412 return ecs_iter_get_group(iter_);
413 }
414
421 flecs::entity get_var(int var_id) const;
422
429 flecs::entity get_var(const char *name) const;
430
439 bool next() {
440 if (iter_->flags & EcsIterIsValid && iter_->table) {
441 ECS_TABLE_UNLOCK(iter_->world, iter_->table);
442 }
443 bool result = iter_->next(iter_);
444 iter_->flags |= EcsIterIsValid;
445 if (result && iter_->table) {
446 ECS_TABLE_LOCK(iter_->world, iter_->table);
447 }
448 return result;
449 }
450
455 void each() {
456 iter_->callback(iter_);
457 }
458
464 template <typename Func>
465 void targets(int8_t index, const Func& func);
466
476 void fini() {
477 if (iter_->flags & EcsIterIsValid && iter_->table) {
478 ECS_TABLE_UNLOCK(iter_->world, iter_->table);
479 }
480 ecs_iter_fini(iter_);
481 }
482
483private:
484 /* Get field, check if correct type is used. */
485 template <typename T, typename A = actual_type_t<T>>
486 flecs::field<T> get_field(int8_t index) const {
487
488#ifndef FLECS_NDEBUG
489 ecs_entity_t term_id = ecs_field_id(iter_, index);
490 ecs_assert(ECS_HAS_ID_FLAG(term_id, PAIR) ||
491 term_id == _::type<T>::id(iter_->world),
492 ECS_COLUMN_TYPE_MISMATCH, nullptr);
493#endif
494
495 size_t count;
496 bool is_shared = !ecs_field_is_self(iter_, index);
497
498 /* If a shared field is retrieved with field(), there will only be a
499 * single value. Ensure that the application does not accidentally read
500 * out of bounds. */
501 if (is_shared) {
502 count = 1;
503 } else {
504 /* If field is owned, there will be as many values as there are
505 * entities. */
506 count = static_cast<size_t>(iter_->count);
507 }
508
509 return flecs::field<A>(
510 static_cast<T*>(ecs_field_w_size(iter_, sizeof(A), index)),
511 count, is_shared);
512 }
513
514 /* Get field, check if correct type is used. */
515 template <typename T, typename A = actual_type_t<T>>
516 flecs::field<T> get_field_at(int8_t index, int32_t row) const {
517
518#ifndef FLECS_NDEBUG
519 ecs_entity_t term_id = ecs_field_id(iter_, index);
520 ecs_assert(ECS_HAS_ID_FLAG(term_id, PAIR) ||
521 term_id == _::type<T>::id(iter_->world),
522 ECS_COLUMN_TYPE_MISMATCH, nullptr);
523#endif
524
525 return flecs::field<A>(
526 static_cast<T*>(ecs_field_at_w_size(iter_, sizeof(A), index, row)),
527 1, false);
528 }
529
530 flecs::untyped_field get_unchecked_field(int8_t index) const {
531 size_t count;
532 size_t size = ecs_field_size(iter_, index);
533 bool is_shared = !ecs_field_is_self(iter_, index);
534
535 /* If a shared field is retrieved with field(), there will only be a
536 * single value. Ensure that the application does not accidentally read
537 * out of bounds. */
538 if (is_shared) {
539 count = 1;
540 } else {
541 /* If field is owned, there will be as many values as there are
542 * entities. */
543 count = static_cast<size_t>(iter_->count);
544 }
545
546 return flecs::untyped_field(
547 ecs_field_w_size(iter_, size, index), size, count, is_shared);
548 }
549
550 flecs::untyped_field get_unchecked_field_at(int8_t index, size_t row) const {
551 size_t size = ecs_field_size(iter_, index);
552 return flecs::untyped_field(
553 ecs_field_at_w_size(iter_, size, index, static_cast<int32_t>(row)),
554 size, 1, false);
555 }
556
557 flecs::iter_t *iter_;
558};
559
560} // namespace flecs
561
ecs_assert
#define ecs_assert(condition, error_code,...)
Assert.
Definition log.h:473
ECS_ACCESS_VIOLATION
#define ECS_ACCESS_VIOLATION
Access violation error code.
Definition log.h:719
ECS_INVALID_OPERATION
#define ECS_INVALID_OPERATION
Invalid operation error code.
Definition log.h:669
ECS_COLUMN_TYPE_MISMATCH
#define ECS_COLUMN_TYPE_MISMATCH
Column type mismatch error code.
Definition log.h:727
ECS_INVALID_PARAMETER
#define ECS_INVALID_PARAMETER
Invalid parameter error code.
Definition log.h:671
ecs_check
#define ecs_check(condition, error_code,...)
Check.
Definition log.h:527
ecs_entity_t
ecs_id_t ecs_entity_t
An entity identifier.
Definition flecs.h:385
flecs::iter_t
ecs_iter_t iter_t
Iterator type.
Definition c_types.hpp:28
ecs_field_src
ecs_entity_t ecs_field_src(const ecs_iter_t *it, int8_t index)
Return the field source.
ecs_iter_changed
bool ecs_iter_changed(ecs_iter_t *it)
Return whether the current iterator result has changed.
ecs_field_is_readonly
bool ecs_field_is_readonly(const ecs_iter_t *it, int8_t index)
Test whether the field is read-only.
ecs_iter_fini
void ecs_iter_fini(ecs_iter_t *it)
Clean up iterator resources.
ecs_iter_str
char * ecs_iter_str(const ecs_iter_t *it)
Convert an iterator to a string.
ecs_field_at_w_size
void * ecs_field_at_w_size(const ecs_iter_t *it, size_t size, int8_t index, int32_t row)
Get data for a field at a specified row.
ecs_field_id
ecs_id_t ecs_field_id(const ecs_iter_t *it, int8_t index)
Return the ID matched for a field.
ecs_field_is_set
bool ecs_field_is_set(const ecs_iter_t *it, int8_t index)
Test whether a field is set.
ecs_field_is_self
bool ecs_field_is_self(const ecs_iter_t *it, int8_t index)
Test whether the field is matched on self.
ecs_field_column
int32_t ecs_field_column(const ecs_iter_t *it, int8_t index)
Return the index of a matched table column.
ecs_iter_get_group
uint64_t ecs_iter_get_group(const ecs_iter_t *it)
Return the group ID for the currently iterated result.
ecs_field_w_size
void * ecs_field_w_size(const ecs_iter_t *it, size_t size, int8_t index)
Get data for a field.
ecs_field_size
size_t ecs_field_size(const ecs_iter_t *it, int8_t index)
Return the field type size.
ecs_ftime_t
#define ecs_ftime_t
Customizable precision for scalar time values.
Definition flecs.h:59
ecs_iter_skip
void ecs_iter_skip(ecs_iter_t *it)
Skip a table while iterating.
flecs::_
Int to enum.
Definition component.hpp:18
ecs_iter_t
Iterator.
Definition flecs.h:1170
ecs_iter_t::world
ecs_world_t * world
The world.
Definition flecs.h:1172
ecs_iter_t::count
int32_t count
Number of entities to iterate.
Definition flecs.h:1177
flecs::_::range_iterator
Iterate over an integer range (used to iterate over entity range).
Definition iter.hpp:31
flecs::_::type
Definition flecs.hpp:39
flecs::entity
Entity.
Definition entity.hpp:30
flecs::field
Wrapper class around a field.
Definition field.hpp:61
flecs::id
Class that wraps around a flecs::id_t.
Definition decl.hpp:27
flecs::iter::size
size_t size(int8_t index) const
Size of the field data type.
Definition iter.hpp:228
flecs::iter::field
flecs::field< A > field(int8_t index) const
Get read-only access to field data.
Definition iter.hpp:80
flecs::iter::event
flecs::entity event() const
Get the event entity associated with the iterator.
Definition iter.hpp:17
flecs::iter::field_at
const A & field_at(int8_t index, size_t row) const
Get const reference to field at row.
Definition iter.hpp:351
flecs::iter::table
flecs::table table() const
Get the table for the current iterator result.
Definition iter.hpp:63
flecs::iter::is_self
bool is_self(int8_t index) const
Return whether the field is matched on self.
Definition iter.hpp:193
flecs::iter::str
flecs::string str() const
Convert current iterator result to string.
Definition iter.hpp:275
flecs::iter::type
flecs::type type() const
Get the type of the iterated table.
Definition iter.hpp:58
flecs::iter::field_count
int32_t field_count() const
Number of fields in the iterator.
Definition iter.hpp:219
flecs::iter::delta_system_time
ecs_ftime_t delta_system_time() const
Get the time elapsed since the last system invocation.
Definition iter.hpp:131
flecs::iter::column_index
int32_t column_index(int8_t index) const
Obtain the column index for the field.
Definition iter.hpp:259
flecs::iter::param
void * param()
Access param.
Definition iter.hpp:168
flecs::iter::begin
row_iterator begin() const
Get an iterator to the beginning of the entity range.
Definition iter.hpp:81
flecs::iter::end
row_iterator end() const
Get an iterator to the end of the entity range.
Definition iter.hpp:86
flecs::iter::field_at
void * field_at(int8_t index, size_t row) const
Get pointer to field at row.
Definition iter.hpp:334
flecs::iter::delta_time
ecs_ftime_t delta_time() const
Get the time elapsed since the last frame.
Definition iter.hpp:123
flecs::iter::is_readonly
bool is_readonly(int8_t index) const
Return whether the field is readonly.
Definition iter.hpp:211
flecs::iter::other_table
flecs::table other_table() const
Get the other table for the current iterator result.
Definition iter.hpp:68
flecs::iter::c_ptr
const flecs::iter_t * c_ptr() const
Get a pointer to the underlying C iterator object.
Definition iter.hpp:103
flecs::iter::changed
bool changed()
Check if the current table has changed since the last iteration.
Definition iter.hpp:392
flecs::iter::term_index
int8_t term_index() const
Obtain the term that triggered an observer.
Definition iter.hpp:267
flecs::iter::ctx
T * ctx()
Access ctx.
Definition iter.hpp:161
flecs::iter::fini
void fini()
Free iterator resources.
Definition iter.hpp:476
flecs::iter::is_set
bool is_set(int8_t index) const
Return whether the field is set.
Definition iter.hpp:202
flecs::iter::field_at
A & field_at(int8_t index, size_t row) const
Get mutable reference to field at row.
Definition iter.hpp:368
flecs::iter::ctx
void * ctx()
Access ctx.
Definition iter.hpp:153
flecs::iter::entity
flecs::entity entity(size_t row) const
Obtain a mutable handle to the entity being iterated over.
Definition iter.hpp:32
flecs::iter::each
void each()
Forward to each().
Definition iter.hpp:455
flecs::iter::field
flecs::untyped_field field(int8_t index) const
Get unchecked access to field data.
Definition iter.hpp:320
flecs::iter::event_id
flecs::id event_id() const
Get the event ID associated with the iterator.
Definition iter.hpp:22
flecs::iter::get_var
flecs::entity get_var(int var_id) const
Get value of variable by ID.
Definition iter.hpp:101
flecs::iter::count
size_t count() const
Get the number of entities to iterate over.
Definition iter.hpp:111
flecs::iter::entities
flecs::field< const flecs::entity_t > entities() const
Get read-only access to entity IDs.
Definition iter.hpp:382
flecs::iter::group_id
uint64_t group_id() const
Return the group ID for the current table (grouped queries only).
Definition iter.hpp:411
flecs::iter::iter
iter(ecs_iter_t *it)
Construct iterator from C iterator object.
Definition iter.hpp:78
flecs::iter::param
T * param()
Access param.
Definition iter.hpp:176
flecs::iter::range
flecs::table_range range() const
Get the table range for the current iterator result.
Definition iter.hpp:73
flecs::iter::targets
void targets(int8_t index, const Func &func)
Iterate targets for pair field.
Definition iter.hpp:119
flecs::iter::src
flecs::entity src(int8_t index) const
Obtain the field source (0 if This).
Definition iter.hpp:39
flecs::iter::skip
void skip()
Skip current table.
Definition iter.hpp:403
flecs::iter::next
bool next()
Progress iterator.
Definition iter.hpp:439
flecs::iter::world
flecs::world world() const
Get the world associated with the iterator.
Definition iter.hpp:27
flecs::iter::system
flecs::entity system() const
Get the system entity associated with the iterator.
Definition iter.hpp:12
flecs::pair
Type that represents a pair.
Definition pair.hpp:36
flecs::string
Owned string wrapper.
Definition string.hpp:15
flecs::table_range
Table range.
Definition table.hpp:449
flecs::table
Table.
Definition table.hpp:23
flecs::type
Type class.
Definition type.hpp:21
flecs::untyped_field
Unsafe wrapper class around a field.
Definition field.hpp:26
flecs::world
The world.
Definition world.hpp:246