text: #define flecs_STATIC
  /**
   * @file flecs.h
   * @brief Flecs public API.
   *
   * This file contains the public API for Flecs.
   */
  
  #ifndef FLECS_H
  #define FLECS_H
  
  /* FLECS_LEGACY should be defined when building for C89 */
  // #define FLECS_LEGACY
  
  /* FLECS_NO_CPP should be defined when building for C++ without the C++ API */
  // #define FLECS_NO_CPP
  
  /* FLECS_CUSTOM_BUILD should be defined when manually selecting features */
  // #define FLECS_CUSTOM_BUILD
  
  /* If this is a regular, non-custom build, build all modules and addons. */
  #ifndef FLECS_CUSTOM_BUILD
  /* Modules */
  #define FLECS_SYSTEM
  #define FLECS_PIPELINE
  #define FLECS_TIMER
  
  /* Addons */
  #define FLECS_BULK
  #define FLECS_DBG
  #define FLECS_MODULE
  #define FLECS_QUEUE
  #define FLECS_READER_WRITER
  #define FLECS_SNAPSHOT
  #define FLECS_DIRECT_ACCESS
  #define FLECS_STATS
  #endif
  
  /* Set to double or int to increase accuracy of time keeping. Note that when
   * using an integer type, an application has to provide the delta_time values
   * to the progress() function, as the code that measures time requires a
   * floating point type. */
  #ifndef FLECS_FLOAT
  #define FLECS_FLOAT float
  #endif
  
  /**
   * @file api_defines.h
   * @brief Supporting defines for the public API.
   *
   * This file contains constants / macro's that are typically not used by an
   * application but support the public API, and therefore must be exposed. This
   * header should not be included by itself.
   */
  
  #ifndef FLECS_API_DEFINES_H
  #define FLECS_API_DEFINES_H
  
  /* Standard library dependencies */
  #include <time.h>
  #include <stdlib.h>
  #include <assert.h>
  #include <stdarg.h>
  #include <string.h>
  #include <stdio.h>
  #include <limits.h>
  #include <string.h>
  
  /* Non-standard but required. If not provided by platform, add manually. */
  #include <stdint.h>
  
  /* Contains macro's for importing / exporting symbols */
  /*
                                     )
                                    (.)
                                    .|.
                                    | |
                                _.--| |--._
                             .-';  ;`-'& ; `&.
                            \   &  ;    &   &_/
                             |"""---...---"""|
                             \ | | | | | | | /
                              `---.|.|.|.---'
  
   * This file is generated by bake.lang.c for your convenience. Headers of
   * dependencies will automatically show up in this file. Include bake_config.h
   * in your main project file. Do not edit! */
  
  #ifndef FLECS_BAKE_CONFIG_H
  #define FLECS_BAKE_CONFIG_H
  
  /* Headers of public dependencies */
  /* No dependencies */
  
  /* Convenience macro for exporting symbols */
  #ifndef flecs_STATIC
  #if flecs_EXPORTS && (defined(_MSC_VER) || defined(__MINGW32__))
    #define FLECS_API __declspec(dllexport)
  #elif flecs_EXPORTS
    #define FLECS_API __attribute__((__visibility__("default")))
  #elif defined _MSC_VER
    #define FLECS_API __declspec(dllimport)
  #else
    #define FLECS_API
  #endif
  #else
    #define FLECS_API
  #endif
  
  #endif
  
  
  #ifdef __cplusplus
  extern "C" {
  #endif
  
  #ifdef __BAKE_LEGACY__
  #define FLECS_LEGACY
  #endif
  
  
  ////////////////////////////////////////////////////////////////////////////////
  //// Language support defines
  ////////////////////////////////////////////////////////////////////////////////
  
  #ifndef FLECS_LEGACY
  #include <stdbool.h>
  #endif
  
  /* The API uses the native bool type in C++, or a custom one in C */
  #if !defined(__cplusplus) && !defined(__bool_true_false_are_defined)
  #undef bool
  #undef true
  #undef false
  typedef char bool;
  #define false 0
  #define true !false
  #endif
  
  typedef uint32_t ecs_flags32_t;
  typedef uint64_t ecs_flags64_t;
  
  /* Keep unsigned integers out of the codebase as they do more harm than good */
  typedef int32_t ecs_size_t;
  #define ECS_SIZEOF(T) (ecs_size_t)sizeof(T)
  
  /* Use alignof in C++, or a trick in C. */
  #ifdef __cplusplus
  #define ECS_ALIGNOF(T) (int64_t)alignof(T)
  #elif defined(_MSC_VER)
  #define ECS_ALIGNOF(T) (int64_t)__alignof(T)
  #elif defined(__GNUC__)
  #define ECS_ALIGNOF(T) (int64_t)__alignof__(T)
  #else
  #define ECS_ALIGNOF(T) ((int64_t)&((struct { char c; T d; } *)0)->d)
  #endif
  
  #if defined(__GNUC__)
  #define ECS_UNUSED __attribute__((unused))
  #else
  #define ECS_UNUSED
  #endif
  
  #define ECS_ALIGN(size, alignment) (ecs_size_t)((((((size_t)size) - 1) / ((size_t)alignment)) + 1) * ((size_t)alignment))
  
  /* Simple utility for determining the max of two values */
  #define ECS_MAX(a, b) ((a > b) ? a : b)
  
  
  ////////////////////////////////////////////////////////////////////////////////
  //// Reserved component ids
  ////////////////////////////////////////////////////////////////////////////////
  
  /** Builtin component ids */
  #define FLECS__EEcsComponent (1)
  #define FLECS__EEcsComponentLifecycle (2)
  #define FLECS__EEcsType (3)
  #define FLECS__EEcsName (6)
  
  /** System module component ids */
  #define FLECS__EEcsTrigger (4)
  #define FLECS__EEcsSystem (5)
  #define FLECS__EEcsTickSource (7)
  #define FLECS__EEcsSignatureExpr (8)
  #define FLECS__EEcsSignature (9)
  #define FLECS__EEcsQuery (10)
  #define FLECS__EEcsIterAction (11)
  #define FLECS__EEcsContext (12)
  
  /** Pipeline module component ids */
  #define FLECS__EEcsPipelineQuery (13)
  
  /** Timer module component ids */
  #define FLECS__EEcsTimer (14)
  #define FLECS__EEcsRateFilter (15)
  
  
  ////////////////////////////////////////////////////////////////////////////////
  //// Entity id macro's
  ////////////////////////////////////////////////////////////////////////////////
  
  #define ECS_ROLE_MASK         ((ecs_entity_t)0xFF << 56)
  #define ECS_ENTITY_MASK       ((uint64_t)0xFFFFFFFF)
  #define ECS_GENERATION_MASK   ((uint64_t)0xFFFF << 32)
  #define ECS_GENERATION(e)     ((e & ECS_GENERATION_MASK) >> 32)
  #define ECS_GENERATION_INC(e) ((e & ~ECS_GENERATION_MASK) | ((ECS_GENERATION(e) + 1) << 32))
  #define ECS_COMPONENT_MASK    ((ecs_entity_t)~ECS_ROLE_MASK)
  #define ECS_TYPE_ROLE_START   ECS_CHILDOF
  #define ECS_HAS_ROLE(e, role) ((e & ECS_ROLE_MASK) == ECS_##role)
  
  
  ////////////////////////////////////////////////////////////////////////////////
  //// Convert between C typenames and variables
  ////////////////////////////////////////////////////////////////////////////////
  
  /** Translate C type to ecs_type_t variable. */
  #define ecs_type(T) FLECS__T##T
  
  /** Translate C type to entity id. */
  #define ecs_typeid(T) FLECS__E##T
  
  /* DEPRECATED: old way to get entity id from type */
  #define ecs_entity(T) ecs_typeid(T)
  
  /** Translate C type to module struct. */
  #define ecs_module(T) FLECS__M##T
  
  /** Translate C type to module struct. */
  #define ecs_module_ptr(T) FLECS__M##T##_ptr
  
  /** Translate C type to module struct. */
  #define ecs_iter_action(T) FLECS__F##T
  
  #ifndef FLECS_LEGACY
  
  
  ////////////////////////////////////////////////////////////////////////////////
  //// Utilities for working with trait identifiers
  ////////////////////////////////////////////////////////////////////////////////
  
  #define ecs_entity_t_lo(value) ((uint32_t)(value))
  #define ecs_entity_t_hi(value) ((uint32_t)((value) >> 32))
  #define ecs_entity_t_comb(v1, v2) (((uint64_t)(v2) << 32) + (uint32_t)(v1))
  #define ecs_trait(comp, trait) ECS_TRAIT | ecs_entity_t_comb(comp, trait)
  
  
  ////////////////////////////////////////////////////////////////////////////////
  //// Convenience macro's for ctor, dtor, move and copy
  ////////////////////////////////////////////////////////////////////////////////
  
  /* Constructor / destructor convenience macro */
  #define ECS_XTOR_IMPL(type, postfix, var, ...)\
      void type##_##postfix(\
          ecs_world_t *world,\
          ecs_entity_t component,\
          const ecs_entity_t *entity_ptr,\
          void *_ptr,\
          size_t _size,\
          int32_t _count,\
          void *ctx)\
      {\
          (void)world;\
          (void)component;\
          (void)entity_ptr;\
          (void)_ptr;\
          (void)_size;\
          (void)_count;\
          (void)ctx;\
          for (int32_t i = 0; i < _count; i ++) {\
              ecs_entity_t entity = entity_ptr[i];\
              type *var = &((type*)_ptr)[i];\
              (void)entity;\
              (void)var;\
              __VA_ARGS__\
          }\
      }
  
  /* Copy convenience macro */
  #define ECS_COPY_IMPL(type, dst_var, src_var, ...)\
      void type##_##copy(\
          ecs_world_t *world,\
          ecs_entity_t component,\
          const ecs_entity_t *dst_entities,\
          const ecs_entity_t *src_entities,\
          void *_dst_ptr,\
          const void *_src_ptr,\
          size_t _size,\
          int32_t _count,\
          void *ctx)\
      {\
          (void)world;\
          (void)component;\
          (void)dst_entities;\
          (void)src_entities;\
          (void)_dst_ptr;\
          (void)_src_ptr;\
          (void)_size;\
          (void)_count;\
          (void)ctx;\
          for (int32_t i = 0; i < _count; i ++) {\
              ecs_entity_t dst_entity = dst_entities[i];\
              ecs_entity_t src_entity = src_entities[i];\
              type *dst_var = &((type*)_dst_ptr)[i];\
              type *src_var = &((type*)_src_ptr)[i];\
              (void)dst_entity;\
              (void)src_entity;\
              (void)dst_var;\
              (void)src_var;\
              __VA_ARGS__\
          }\
      }
  
  /* Move convenience macro */
  #define ECS_MOVE_IMPL(type, dst_var, src_var, ...)\
      void type##_##move(\
          ecs_world_t *world,\
          ecs_entity_t component,\
          const ecs_entity_t *dst_entities,\
          const ecs_entity_t *src_entities,\
          void *_dst_ptr,\
          void *_src_ptr,\
          size_t _size,\
          int32_t _count,\
          void *ctx)\
      {\
          (void)world;\
          (void)component;\
          (void)dst_entities;\
          (void)src_entities;\
          (void)_dst_ptr;\
          (void)_src_ptr;\
          (void)_size;\
          (void)_count;\
          (void)ctx;\
          for (int32_t i = 0; i < _count; i ++) {\
              ecs_entity_t dst_entity = dst_entities[i];\
              ecs_entity_t src_entity = src_entities[i];\
              type *dst_var = &((type*)_dst_ptr)[i];\
              type *src_var = &((type*)_src_ptr)[i];\
              (void)dst_entity;\
              (void)src_entity;\
              (void)dst_var;\
              (void)src_var;\
              __VA_ARGS__\
          }\
      }
  #endif
  #ifdef __cplusplus
  }
  #endif
  
  #endif
  
  /**
   * @file vector.h
   * @brief Vector datastructure.
   *
   * This is an implementation of a simple vector type. The vector is allocated in
   * a single block of memory, with the element count, and allocated number of
   * elements encoded in the block. As this vector is used for user-types it has
   * been designed to support alignments higher than 8 bytes. This makes the size
   * of the vector header variable in size. To reduce the overhead associated with
   * retrieving or computing this size, the functions are wrapped in macro calls
   * that compute the header size at compile time.
   *
   * The API provides a number of _t macro's, which accept a size and alignment.
   * These macro's are used when no compile-time type is available.
   *
   * The vector guarantees contiguous access to its elements. When an element is
   * removed from the vector, the last element is copied to the removed element.
   *
   * The API requires passing in the type of the vector. This type is used to test
   * whether the size of the provided type equals the size of the type with which
   * the vector was created. In release mode this check is not performed.
   *
   * When elements are added to the vector, it will automatically resize to the
   * next power of two. This can change the pointer of the vector, which is why
   * operations that can increase the vector size, accept a double pointer to the
   * vector.
   */
  
  #ifndef FLECS_VECTOR_H
  #define FLECS_VECTOR_H
  
  
  #ifdef __cplusplus
  extern "C" {
  #endif
  
  /* Public, so we can do compile-time header size calculation */
  struct ecs_vector_t {
      int32_t count;
      int32_t size;
      
  #ifndef NDEBUG
      int64_t elem_size;
  #endif
  };
  
  /* Compute the header size of the vector from size & alignment */
  #define ECS_VECTOR_U(size, alignment) size, ECS_MAX(ECS_SIZEOF(ecs_vector_t), alignment)
  
  /* Compute the header size of the vector from a provided compile-time type */
  #define ECS_VECTOR_T(T) ECS_VECTOR_U(ECS_SIZEOF(T), ECS_ALIGNOF(T))
  
  /* Utility macro's for creating vector on stack */
  #ifndef NDEBUG
  #define ECS_VECTOR_VALUE(T, elem_count)\
  {\
      .elem_size = (int32_t)(ECS_SIZEOF(T)),\
      .count = elem_count,\
      .size = elem_count\
  }
  #else
  #define ECS_VECTOR_VALUE(T, elem_count)\
  {\
      .count = elem_count,\
      .size = elem_count\
  }
  #endif
  
  #define ECS_VECTOR_DECL(name, T, elem_count)\
  struct {\
      union {\
          ecs_vector_t vector;\
          uint64_t align;\
      } header;\
      T array[elem_count];\
  } __##name##_value = {\
      .header.vector = ECS_VECTOR_VALUE(T, elem_count)\
  };\
  const ecs_vector_t *name = (ecs_vector_t*)&__##name##_value
  
  #define ECS_VECTOR_IMPL(name, T, elems, elem_count)\
  ecs_os_memcpy(__##name##_value.array, elems, sizeof(T) * elem_count)
  
  #define ECS_VECTOR_STACK(name, T, elems, elem_count)\
  ECS_VECTOR_DECL(name, T, elem_count);\
  ECS_VECTOR_IMPL(name, T, elems, elem_count)
  
  typedef struct ecs_vector_t ecs_vector_t;
  
  typedef int (*ecs_comparator_t)(
      const void* p1,
      const void *p2);
  
  /** Create new vector. */
  FLECS_API
  ecs_vector_t* _ecs_vector_new(
      ecs_size_t elem_size,
      int16_t offset,
      int32_t elem_count);
  
  #define ecs_vector_new(T, elem_count) \
      _ecs_vector_new(ECS_VECTOR_T(T), elem_count)
  
  #define ecs_vector_new_t(size, alignment, elem_count) \
      _ecs_vector_new(ECS_VECTOR_U(size, alignment), elem_count)    
  
  /* Create new vector, initialize it with provided array */
  FLECS_API
  ecs_vector_t* _ecs_vector_from_array(
      ecs_size_t elem_size,
      int16_t offset,
      int32_t elem_count,
      void *array);
  
  #define ecs_vector_from_array(T, elem_count, array)\
      _ecs_vector_from_array(ECS_VECTOR_T(T), elem_count, array)
  
  /* Initialize vector with zero's */
  FLECS_API
  void _ecs_vector_zero(
      ecs_vector_t *vector,
      ecs_size_t elem_size,
      int16_t offset);
  
  #define ecs_vector_zero(vector, T) \
      _ecs_vector_zero(vector, ECS_VECTOR_T(T))
  
  /** Free vector */
  FLECS_API
  void ecs_vector_free(
      ecs_vector_t *vector);
  
  /** Clear values in vector */
  FLECS_API
  void ecs_vector_clear(
      ecs_vector_t *vector);
  
  /** Assert when the provided size does not match the vector type. */
  FLECS_API
  void ecs_vector_assert_size(
      ecs_vector_t* vector_inout,
      ecs_size_t elem_size);
  
  /** Assert when the provided alignment does not match the vector type. */
  FLECS_API
  void ecs_vector_assert_alignment(
      ecs_vector_t* vector,
      ecs_size_t elem_alignment);    
  
  /** Add element to vector. */
  FLECS_API
  void* _ecs_vector_add(
      ecs_vector_t **array_inout,
      ecs_size_t elem_size,
      int16_t offset);
  
  #define ecs_vector_add(vector, T) \
      ((T*)_ecs_vector_add(vector, ECS_VECTOR_T(T)))
  
  #define ecs_vector_add_t(vector, size, alignment) \
      _ecs_vector_add(vector, ECS_VECTOR_U(size, alignment))
  
  /** Add n elements to the vector. */
  FLECS_API
  void* _ecs_vector_addn(
      ecs_vector_t **array_inout,
      ecs_size_t elem_size,
      int16_t offset,
      int32_t elem_count);
  
  #define ecs_vector_addn(vector, T, elem_count) \
      ((T*)_ecs_vector_addn(vector, ECS_VECTOR_T(T), elem_count))
  
  #define ecs_vector_addn_t(vector, size, alignment, elem_count) \
      _ecs_vector_addn(vector, ECS_VECTOR_U(size, alignment), elem_count)
  
  /** Get element from vector. */
  FLECS_API
  void* _ecs_vector_get(
      const ecs_vector_t *vector,
      ecs_size_t elem_size,
      int16_t offset,
      int32_t index);
  
  #define ecs_vector_get(vector, T, index) \
      ((T*)_ecs_vector_get(vector, ECS_VECTOR_T(T), index))
  
  #define ecs_vector_get_t(vector, size, alignment, index) \
      _ecs_vector_get(vector, ECS_VECTOR_U(size, alignment), index)
  
  /** Get last element from vector. */
  FLECS_API
  void* _ecs_vector_last(
      const ecs_vector_t *vector,
      ecs_size_t elem_size,
      int16_t offset);
  
  #define ecs_vector_last(vector, T) \
      (T*)_ecs_vector_last(vector, ECS_VECTOR_T(T))
  
  /** Set minimum size for vector. If the current size of the vector is larger, 
   * the function will have no side effects. */
  FLECS_API
  int32_t _ecs_vector_set_min_size(
      ecs_vector_t **array_inout,
      ecs_size_t elem_size,
      int16_t offset,
      int32_t elem_count);
  
  #define ecs_vector_set_min_size(vector, T, size) \
      _ecs_vector_set_min_size(vector, ECS_VECTOR_T(T), size)
  
  /** Set minimum count for vector. If the current count of the vector is larger, 
   * the function will have no side effects. */
  FLECS_API
  int32_t _ecs_vector_set_min_count(
      ecs_vector_t **vector_inout,
      ecs_size_t elem_size,
      int16_t offset,
      int32_t elem_count);
  
  #define ecs_vector_set_min_count(vector, T, size) \
      _ecs_vector_set_min_count(vector, ECS_VECTOR_T(T), size)
  
  /** Remove last element. This operation requires no swapping of values. */
  FLECS_API
  void ecs_vector_remove_last(
      ecs_vector_t *vector);
  
  /** Remove last value, store last element in provided value. */
  FLECS_API
  bool _ecs_vector_pop(
      ecs_vector_t *vector,
      ecs_size_t elem_size,
      int16_t offset,
      void *value);
  
  #define ecs_vector_pop(vector, T, value) \
      _ecs_vector_pop(vector, ECS_VECTOR_T(T), value)
  
  /** Append element at specified index to another vector. */
  FLECS_API
  int32_t _ecs_vector_move_index(
      ecs_vector_t **dst,
      ecs_vector_t *src,
      ecs_size_t elem_size,
      int16_t offset,
      int32_t index);
  
  #define ecs_vector_move_index(dst, src, T, index) \
      _ecs_vector_move_index(dst, src, ECS_VECTOR_T(T), index)
  
  /** Remove element at specified index. Moves the last value to the index. */
  FLECS_API
  int32_t _ecs_vector_remove_index(
      ecs_vector_t *vector,
      ecs_size_t elem_size,
      int16_t offset,
      int32_t index);
  
  #define ecs_vector_remove_index(vector, T, index) \
      _ecs_vector_remove_index(vector, ECS_VECTOR_T(T), index)
  
  #define ecs_vector_remove_index_t(vector, size, alignment, index) \
      _ecs_vector_remove_index(vector, ECS_VECTOR_U(size, alignment), index)
  
  /** Shrink vector to make the size match the count. */
  FLECS_API
  void _ecs_vector_reclaim(
      ecs_vector_t **vector,
      ecs_size_t elem_size,
      int16_t offset);
  
  #define ecs_vector_reclaim(vector, T)\
      _ecs_vector_reclaim(vector, ECS_VECTOR_T(T))
  
  /** Grow size of vector with provided number of elements. */
  FLECS_API
  int32_t _ecs_vector_grow(
      ecs_vector_t **vector,
      ecs_size_t elem_size,
      int16_t offset,
      int32_t elem_count);
  
  #define ecs_vector_grow(vector, T, size) \
      _ecs_vector_grow(vector, ECS_VECTOR_T(T), size)
  
  /** Set allocation size of vector. */
  FLECS_API
  int32_t _ecs_vector_set_size(
      ecs_vector_t **vector,
      ecs_size_t elem_size,
      int16_t offset,
      int32_t elem_count);
  
  #define ecs_vector_set_size(vector, T, elem_count) \
      _ecs_vector_set_size(vector, ECS_VECTOR_T(T), elem_count)
  
  #define ecs_vector_set_size_t(vector, size, alignment, elem_count) \
      _ecs_vector_set_size(vector, ECS_VECTOR_U(size, alignment), elem_count)
  
  /** Set count of vector. If the size of the vector is smaller than the provided
   * count, the vector is resized. */
  FLECS_API
  int32_t _ecs_vector_set_count(
      ecs_vector_t **vector,
      ecs_size_t elem_size,
      int16_t offset,
      int32_t elem_count);
  
  #define ecs_vector_set_count(vector, T, elem_count) \
      _ecs_vector_set_count(vector, ECS_VECTOR_T(T), elem_count)
  
  #define ecs_vector_set_count_t(vector, size, alignment, elem_count) \
      _ecs_vector_set_count(vector, ECS_VECTOR_U(size, alignment), elem_count)
  
  /** Return number of elements in vector. */
  FLECS_API
  int32_t ecs_vector_count(
      const ecs_vector_t *vector);
  
  /** Return size of vector. */
  FLECS_API
  int32_t ecs_vector_size(
      const ecs_vector_t *vector);
  
  /** Return first element of vector. */
  FLECS_API
  void* _ecs_vector_first(
      const ecs_vector_t *vector,
      ecs_size_t elem_size,
      int16_t offset);
  
  #define ecs_vector_first(vector, T) \
      ((T*)_ecs_vector_first(vector, ECS_VECTOR_T(T)))
  
  #define ecs_vector_first_t(vector, size, alignment) \
      _ecs_vector_first(vector, ECS_VECTOR_U(size, alignment))
  
  /** Sort elements in vector. */
  FLECS_API
  void _ecs_vector_sort(
      ecs_vector_t *vector,
      ecs_size_t elem_size,
      int16_t offset,
      ecs_comparator_t compare_action);
  
  #define ecs_vector_sort(vector, T, compare_action) \
      _ecs_vector_sort(vector, ECS_VECTOR_T(T), compare_action)
  
  /** Return memory occupied by vector. */
  FLECS_API
  void _ecs_vector_memory(
      const ecs_vector_t *vector,
      ecs_size_t elem_size,
      int16_t offset,
      int32_t *allocd,
      int32_t *used);
  
  #define ecs_vector_memory(vector, T, allocd, used) \
      _ecs_vector_memory(vector, ECS_VECTOR_T(T), allocd, used)
  
  #define ecs_vector_memory_t(vector, size, alignment, allocd, used) \
      _ecs_vector_memory(vector, ECS_VECTOR_U(size, alignment), allocd, used)
  
  /** Copy vectors */
  FLECS_API
  ecs_vector_t* _ecs_vector_copy(
      const ecs_vector_t *src,
      ecs_size_t elem_size,
      int16_t offset);
  
  #define ecs_vector_copy(src, T) \
      _ecs_vector_copy(src, ECS_VECTOR_T(T))
  
  #define ecs_vector_copy_t(src, size, alignment) \
      _ecs_vector_copy(src, ECS_VECTOR_U(size, alignment))
  
  #ifndef FLECS_LEGACY
  #define ecs_vector_each(vector, T, var, ...)\
      {\
          int var##_i, var##_count = ecs_vector_count(vector);\
          T* var##_array = ecs_vector_first(vector, T);\
          for (var##_i = 0; var##_i < var##_count; var##_i ++) {\
              T* var = &var##_array[var##_i];\
              __VA_ARGS__\
          }\
      }
  #endif
  #ifdef __cplusplus
  }
  #endif
  
  
  /** C++ wrapper for vector class. */
  #ifdef __cplusplus
  #ifndef FLECS_NO_CPP
  
  #include <initializer_list>
  
  namespace flecs {
  
  template <typename T>
  class vector_iterator
  {
  public:
      explicit vector_iterator(T* value, int index) {
          m_value = value;
          m_index = index;
      }
  
      bool operator!=(vector_iterator const& other) const
      {
          return m_index != other.m_index;
      }
  
      T const& operator*() const
      {
          return m_value[m_index];
      }
  
      vector_iterator& operator++()
      {
          ++m_index;
          return *this;
      }
  
  private:
      T* m_value;
      int m_index;
  };
  
  template <typename T>
  class vector {
  public:
      explicit vector(ecs_vector_t *v) : m_vector( v ) { }
  
      vector(int32_t count = 0) : m_vector( nullptr ) { 
          if (count) {
              init(count);
          }
      }
  
      vector(std::initializer_list<T> elems) : m_vector( nullptr) {
          init(elems.size());
          *this = elems;
      }
  
      void operator=(std::initializer_list<T> elems) {
          for (auto elem : elems) {
              this->add(elem);
          }
      }
  
      T& operator[](size_t index) {
          return ecs_vector_get(m_vector, T, index)[0];
      }
  
      vector_iterator<T> begin() {
          return vector_iterator<T>(
              ecs_vector_first(m_vector, T), 0);
      }
  
      vector_iterator<T> end() {
          return vector_iterator<T>(
              ecs_vector_last(m_vector, T),
              ecs_vector_count(m_vector));
      }    
  
      void clear() {
          ecs_vector_clear(m_vector);
      }
  
      void add(T& value) {
          T* elem = ecs_vector_add(&m_vector, T);
          *elem = value;
      }
  
      void add(T&& value) {
          T* elem = ecs_vector_add(&m_vector, T);
          *elem = value;
      }    
  
      T& get(int32_t index) {
          return ecs_vector_get(m_vector, T, index);
      }
  
      T& first() {
          return ecs_vector_first(m_vector, T);
      }
  
      T& last() {
          return ecs_vector_last(m_vector, T);
      }
  
      int32_t count() {
          return ecs_vector_count(m_vector);
      }
  
      int32_t size() {
          return ecs_vector_size(m_vector);
      }
  
      ecs_vector_t *ptr() {
          return m_vector;
      }
  
      void ptr(ecs_vector_t *ptr) {
          m_vector = ptr;
      }
  
  private:
      void init(int32_t count) {
          m_vector = ecs_vector_new(T, count);
      }
  
      ecs_vector_t *m_vector;
  };
  
  }
  
  #endif
  #endif
  
  #endif
  /**
   * @file sparse.h
   * @brief Sparse set datastructure.
   *
   * This is an implementation of a paged sparse set that stores the payload in
   * the sparse array.
   *
   * A sparse set has a dense and a sparse array. The sparse array is directly
   * indexed by a 64 bit identifier. The sparse element is linked with a dense
   * element, which allows for liveliness checking. The liveliness check itself
   * can be performed by doing (psuedo code):
   *  dense[sparse[sparse_id].dense] == sparse_id
   *
   * To ensure that the sparse array doesn't have to grow to a large size when
   * using large sparse_id's, the sparse set uses paging. This cuts up the array
   * into several pages of 4096 elements. When an element is set, the sparse set
   * ensures that the corresponding page is created. The page associated with an
   * id is determined by shifting a bit 12 bits to the right.
   *
   * The sparse set keeps track of a generation count per id, which is increased
   * each time an id is deleted. The generation is encoded in the returned id.
   *
   * This sparse set implementation stores payload in the sparse array, which is
   * not typical. The reason for this is to guarantee that (in combination with
   * paging) the returned payload pointers are stable. This allows for various
   * optimizations in the parts of the framework that uses the sparse set.
   *
   * The sparse set has been designed so that new ids can be generated in bulk, in
   * an O(1) operation. The way this works is that once a dense-sparse pair is
   * created, it is never unpaired. Instead it is moved to the end of the dense
   * array, and the sparse set stores an additional count to keep track of the
   * last alive id in the sparse set. To generate new ids in bulk, the sparse set
   * only needs to increase this count by the number of requested ids.
   */
  
  #ifndef FLECS_SPARSE_H
  #define FLECS_SPARSE_H
  
  
  #ifdef __cplusplus
  extern "C" {
  #endif
  
  typedef struct ecs_sparse_t ecs_sparse_t;
  
  /** Create new sparse set */
  FLECS_API ecs_sparse_t* _ecs_sparse_new(
      ecs_size_t elem_size);
  
  #define ecs_sparse_new(type)\
      _ecs_sparse_new(sizeof(type))
  
  /** Set id source. This allows the sparse set to use an external variable for
   * issuing and increasing new ids. */
  FLECS_API void ecs_sparse_set_id_source(
      ecs_sparse_t *sparse,
      uint64_t *id_source);
  
  /** Free sparse set */
  FLECS_API void ecs_sparse_free(
      ecs_sparse_t *sparse);
  
  /** Remove all elements from sparse set */
  FLECS_API void ecs_sparse_clear(
      ecs_sparse_t *sparse);
  
  /** Add element to sparse set, this generates or recycles an id */
  FLECS_API void* _ecs_sparse_add(
      ecs_sparse_t *sparse,
      ecs_size_t elem_size);
  
  #define ecs_sparse_add(sparse, type)\
      ((type*)_ecs_sparse_add(sparse, sizeof(type)))
  
  /** Get last issued id. */
  FLECS_API uint64_t ecs_sparse_last_id(
      ecs_sparse_t *sparse);
  
  /** Generate or recycle a new id. */
  FLECS_API uint64_t ecs_sparse_new_id(
      ecs_sparse_t *sparse);
  
  /** Generate or recycle new ids in bulk. The returned pointer points directly to
   * the internal dense array vector with sparse ids. Operations on the sparse set
   * can (and likely will) modify the contents of the buffer. */
  FLECS_API const uint64_t* ecs_sparse_new_ids(
      ecs_sparse_t *sparse,
      int32_t count);
  
  /** Remove an element */
  FLECS_API void ecs_sparse_remove(
      ecs_sparse_t *sparse,
      uint64_t index);
  
  /** Remove an element, return pointer to the value in the sparse array */
  FLECS_API void* _ecs_sparse_remove_get(
      ecs_sparse_t *sparse,
      ecs_size_t elem_size,
      uint64_t index);    
  
  #define ecs_sparse_remove_get(sparse, type, index)\
      ((type*)_ecs_sparse_remove_get(sparse, sizeof(type), index))
  
  /** Override the generation count for a specific id */
  FLECS_API void ecs_sparse_set_generation(
      ecs_sparse_t *sparse,
      uint64_t index);    
  
  /** Check whether an id has ever been issued. */
  FLECS_API bool ecs_sparse_exists(
      ecs_sparse_t *sparse,
      uint64_t index);
  
  /** Test if id is alive, which requires the generation count tp match. */
  FLECS_API bool ecs_sparse_is_alive(
      const ecs_sparse_t *sparse,
      uint64_t index);
  
  /** Get value from sparse set by dense id. This function is useful in 
   * combination with ecs_sparse_count for iterating all values in the set. */
  FLECS_API void* _ecs_sparse_get(
      const ecs_sparse_t *sparse,
      ecs_size_t elem_size,
      int32_t index);
  
  #define ecs_sparse_get(sparse, type, index)\
      ((type*)_ecs_sparse_get(sparse, sizeof(type), index))
  
  /** Get the number of alive elements in the sparse set. */
  FLECS_API int32_t ecs_sparse_count(
      const ecs_sparse_t *sparse);
  
  /** Return total number of allocated elements in the dense array */
  FLECS_API int32_t ecs_sparse_size(
      const ecs_sparse_t *sparse);
  
  /** Get element by (sparse) id. The returned pointer is stable for the duration
   * of the sparse set, as it is stored in the sparse array. */
  FLECS_API void* _ecs_sparse_get_sparse(
      const ecs_sparse_t *sparse,
      ecs_size_t elem_size,
      uint64_t index);
  
  #define ecs_sparse_get_sparse(sparse, type, index)\
      ((type*)_ecs_sparse_get_sparse(sparse, sizeof(type), index))
  
  /** Like get_sparse, but don't care whether element is alive or not. */
  FLECS_API void* _ecs_sparse_get_sparse_any(
      ecs_sparse_t *sparse,
      ecs_size_t elem_size,
      uint64_t index);
  
  #define ecs_sparse_get_sparse_any(sparse, type, index)\
      ((type*)_ecs_sparse_get_sparse_any(sparse, sizeof(type), index))
  
  /** Get or create element by (sparse) id. */
  FLECS_API void* _ecs_sparse_get_or_create(
      ecs_sparse_t *sparse,
      ecs_size_t elem_size,
      uint64_t index);
  
  #define ecs_sparse_get_or_create(sparse, type, index)\
      ((type*)_ecs_sparse_get_or_create(sparse, sizeof(type), index))
  
  /** Set value. */
  FLECS_API void* _ecs_sparse_set(
      ecs_sparse_t *sparse,
      ecs_size_t elem_size,
      uint64_t index,
      void *value);
  
  #define ecs_sparse_set(sparse, type, index, value)\
      ((type*)_ecs_sparse_set(sparse, sizeof(type), index, value))
  
  /** Get pointer to ids (alive and not alive). Use with count() or size(). */
  FLECS_API const uint64_t* ecs_sparse_ids(
      const ecs_sparse_t *sparse);
  
  /** Set size of the dense array. */
  FLECS_API void ecs_sparse_set_size(
      ecs_sparse_t *sparse,
      int32_t elem_count);
  
  /** Copy sparse set into a new sparse set. */
  FLECS_API ecs_sparse_t* ecs_sparse_copy(
      const ecs_sparse_t *src);    
  
  /** Restore sparse set into destination sparse set. */
  FLECS_API void ecs_sparse_restore(
      ecs_sparse_t *dst,
      const ecs_sparse_t *src);
  
  /** Get memory usage of sparse set. */
  FLECS_API void ecs_sparse_memory(
      ecs_sparse_t *sparse,
      int32_t *allocd,
      int32_t *used);
  
  #ifndef FLECS_LEGACY
  #define ecs_sparse_each(sparse, T, var, ...)\
      {\
          int var##_i, var##_count = ecs_sparse_count(sparse);\
          for (var##_i = 0; var##_i < var##_count; var##_i ++) {\
              T* var = ecs_sparse_get(sparse, T, var##_i);\
              __VA_ARGS__\
          }\
      }
  #endif
  
  #ifdef __cplusplus
  }
  #endif
  
  #endif
  /**
   * @file bitset.h
   * @brief Bitset datastructure.
   *
   * Simple bitset implementation. The bitset allows for storage of arbitrary
   * numbers of bits.
   */
  
  #ifndef FLECS_BITSET_H
  #define FLECS_BITSET_H
  
  
  #ifdef __cplusplus
  extern "C" {
  #endif
  
  typedef struct ecs_bitset_t {
      uint64_t *data;
      int32_t count;
      ecs_size_t size;
  } ecs_bitset_t;
  
  /** Initialize bitset. */
  void ecs_bitset_init(
      ecs_bitset_t *bs);
  
  /** Deinialize bitset. */
  void ecs_bitset_deinit(
      ecs_bitset_t *bs);
  
  /** Add n elements to bitset. */
  void ecs_bitset_addn(
      ecs_bitset_t *bs,
      int32_t count);
  
  /** Ensure element exists. */
  void ecs_bitset_ensure(
      ecs_bitset_t *bs,
      int32_t count);
  
  /** Set element. */
  void ecs_bitset_set(
      ecs_bitset_t *bs,
      int32_t elem,
      bool value);
  
  /** Get element. */
  bool ecs_bitset_get(
      const ecs_bitset_t *bs,
      int32_t elem);
  
  /** Return number of elements. */
  int32_t ecs_bitset_count(
      const ecs_bitset_t *bs);
  
  /** Remove from bitset. */
  void ecs_bitset_remove(
      ecs_bitset_t *bs,
      int32_t elem);
  
  /** Swap values in bitset. */
  void ecs_bitset_swap(
      ecs_bitset_t *bs,
      int32_t elem_a,
      int32_t elem_b);
  
  #ifdef __cplusplus
  }
  #endif
  
  #endif
  /**
   * @file map.h
   * @brief Map datastructure.
   *
   * Key-value datastructure. The map allows for fast retrieval of a payload for
   * a 64-bit key. While it is not as fast as the sparse set, it is better at
   * handling randomly distributed values.
   *
   * Payload is stored in bucket arrays. A bucket is computed from an id by
   * using the (bucket_count - 1) as an AND-mask. The number of buckets is always
   * a power of 2. Multiple keys will be stored in the same bucket. As a result
   * the worst case retrieval performance of the map is O(n), though this is rare.
   * On average lookup performance should equal O(1).
   *
   * The datastructure will automatically grow the number of buckets when the
   * ratio between elements and buckets exceeds a certain threshold (LOAD_FACTOR).
   *
   * Note that while the implementation is a hashmap, it can only compute hashes
   * for the provided 64 bit keys. This means that the provided keys must always
   * be unique. If the provided keys are hashes themselves, it is the
   * responsibility of the user to ensure that collisions are handled.
   *
   * In debug mode the map verifies that the type provided to the map functions
   * matches the one used at creation time.
   */
  
  #ifndef FLECS_MAP_H
  #define FLECS_MAP_H
  
  
  #ifdef __cplusplus
  extern "C" {
  #endif
  
  typedef struct ecs_map_t ecs_map_t;
  typedef struct ecs_bucket_t ecs_bucket_t;
  typedef uint64_t ecs_map_key_t;
  
  typedef struct ecs_map_iter_t {
      const ecs_map_t *map;
      ecs_bucket_t *bucket;
      int32_t bucket_index;
      int32_t element_index;
      void *payload;
  } ecs_map_iter_t;
  
  /** Create new map. */
  FLECS_API
  ecs_map_t * _ecs_map_new(
      ecs_size_t elem_size,
      ecs_size_t alignment,
      int32_t elem_count);
  
  #define ecs_map_new(T, elem_count)\
      _ecs_map_new(sizeof(T), ECS_ALIGNOF(T), elem_count)
  
  /** Get element for key, returns NULL if they key doesn't exist. */
  FLECS_API
  void * _ecs_map_get(
      const ecs_map_t *map,
      ecs_size_t elem_size,
      ecs_map_key_t key);
  
  #define ecs_map_get(map, T, key)\
      (T*)_ecs_map_get(map, sizeof(T), (ecs_map_key_t)key)
  
  /** Get pointer element. This dereferences the map element as a pointer. This
   * operation returns NULL when either the element does not exist or whether the
   * pointer is NULL, and should therefore only be used when the application knows
   * for sure that a pointer should never be NULL. */
  FLECS_API
  void * _ecs_map_get_ptr(
      const ecs_map_t *map,
      ecs_map_key_t key);
  
  #define ecs_map_get_ptr(map, T, key)\
      (T)_ecs_map_get_ptr(map, key)
  
  /** Get or create element for key. */
  FLECS_API
  void * _ecs_map_ensure(
      ecs_map_t *map,
      ecs_size_t elem_size,
      ecs_map_key_t key);
  
  #define ecs_map_ensure(map, T, key)\
      (T*)_ecs_map_ensure(map, sizeof(T), (ecs_map_key_t)key)
  
  /** Set element. */
  FLECS_API
  void* _ecs_map_set(
      ecs_map_t *map,
      ecs_size_t elem_size,
      ecs_map_key_t key,
      const void *payload);
  
  #define ecs_map_set(map, key, payload)\
      _ecs_map_set(map, sizeof(*payload), (ecs_map_key_t)key, payload);
  
  /** Free map. */
  FLECS_API
  void ecs_map_free(
      ecs_map_t *map);
  
  /** Remove key from map. */
  FLECS_API
  void ecs_map_remove(
      ecs_map_t *map,
      ecs_map_key_t key);
  
  /** Remove all elements from map. */
  FLECS_API
  void ecs_map_clear(
      ecs_map_t *map);
  
  /** Return number of elements in map. */
  FLECS_API
  int32_t ecs_map_count(
      const ecs_map_t *map);
  
  /** Return number of buckets in map. */
  FLECS_API
  int32_t ecs_map_bucket_count(
      const ecs_map_t *map);
  
  /** Return iterator to map contents. */
  FLECS_API
  ecs_map_iter_t ecs_map_iter(
      const ecs_map_t *map);
  
  /** Obtain next element in map from iterator. */
  FLECS_API
  void* _ecs_map_next(
      ecs_map_iter_t* iter,
      ecs_size_t elem_size,
      ecs_map_key_t *key);
  
  #define ecs_map_next(iter, T, key) \
      (T*)_ecs_map_next(iter, sizeof(T), key)
  
  /** Obtain next pointer element from iterator. See ecs_map_get_ptr. */
  FLECS_API
  void* _ecs_map_next_ptr(
      ecs_map_iter_t* iter,
      ecs_map_key_t *key);
  
  #define ecs_map_next_ptr(iter, T, key) \
      (T)_ecs_map_next_ptr(iter, key)
  
  /** Grow number of buckets in the map for specified number of elements. */
  FLECS_API
  void ecs_map_grow(
      ecs_map_t *map,
      int32_t elem_count);
  
  /** Set number of buckets in the map for specified number of elements. */
  FLECS_API
  void ecs_map_set_size(
      ecs_map_t *map,
      int32_t elem_count);
  
  /** Return memory occupied by map. */
  FLECS_API
  void ecs_map_memory(
      ecs_map_t *map,
      int32_t *allocd,
      int32_t *used);
  
  #ifndef FLECS_LEGACY
  #define ecs_map_each(map, T, key, var, ...)\
      {\
          ecs_map_iter_t it = ecs_map_iter(map);\
          ecs_map_key_t key;\
          T* var;\
          (void)key;\
          (void)var;\
          while ((var = ecs_map_next(&it, T, &key))) {\
              __VA_ARGS__\
          }\
      }
  #endif
  #ifdef __cplusplus
  }
  #endif
  
  /** C++ wrapper for map. */
  #ifdef __cplusplus
  #ifndef FLECS_NO_CPP
  
  #include <initializer_list>
  #include <utility>
  
  namespace flecs {
  
  template <typename K, typename T>
  class map {
  public:
      map(int32_t count = 0) {
          init(count);
      }
  
      map(std::initializer_list<std::pair<K, T>> elems) {
          init(elems.size());
          *this = elems;
      }
  
      void operator=(std::initializer_list<std::pair<K, T>> elems) {
          for (auto elem : elems) {
              this->set(elem.first, elem.second);
          }
      }
  
      void clear() {
          ecs_map_clear(m_map);
      }
  
      int32_t count() {
          return ecs_map_count(m_map);
      }
  
      void set(K& key, T& value) {
          ecs_map_set(m_map, reinterpret_cast<ecs_map_key_t>(key), &value);
      }
  
      T& get(K& key) {
          *(T*)ecs_map_get(m_map, T, reinterpret_cast<ecs_map_key_t>(key));
      }
  
  private:
      void init(int32_t count) {
          m_map = ecs_map_new(T, count);
      }
  
      ecs_map_t *m_map;
  };
  
  }
  
  #endif
  #endif
  
  #endif
  /**
   * @file switch_list.h
   * @brief Interleaved linked list for storing mutually exclusive values.
   *
   * Datastructure that stores N interleaved linked lists in an array. 
   * This allows for efficient storage of elements with mutually exclusive values.
   * Each linked list has a header element which points to the index in the array
   * that stores the first node of the list. Each list node points to the next
   * array element.
   *
   * The datastructure needs to be created with min and max values, so that it can
   * allocate an array of headers that can be directly indexed by the value. The
   * values are stored in a contiguous array, which allows for the values to be
   * iterated without having to follow the linked list nodes.
   *
   * The datastructure allows for efficient storage and retrieval for values with
   * mutually exclusive values, such as enumeration values. The linked list allows
   * an application to obtain all elements for a given (enumeration) value without
   * having to search.
   *
   * While the list accepts 64 bit values, it only uses the lower 32bits of the
   * value for selecting the correct linked list.
   */
  
  #ifndef FLECS_SWITCH_LIST_H
  #define FLECS_SWITCH_LIST_H
  
  
  typedef struct ecs_switch_header_t {
      int32_t element;        /* First element for value */
      int32_t count;          /* Number of elements for value */
  } ecs_switch_header_t;
  
  typedef struct ecs_switch_node_t {
      int32_t next;           /* Next node in list */
      int32_t prev;           /* Prev node in list */
  } ecs_switch_node_t;
  
  typedef struct ecs_switch_t {
      uint64_t min;           /* Minimum value the switch can store */
      uint64_t max;           /* Maximum value the switch can store */
      ecs_switch_header_t *headers;   /* Array with headers, indexed by value */
      ecs_vector_t *nodes;    /* Vector with nodes, of type ecs_switch_node_t */
      ecs_vector_t *values;   /* Vector with values, of type uint64_t */
  } ecs_switch_t;
  
  /** Create new switch. */
  ecs_switch_t* ecs_switch_new(
      uint64_t min, 
      uint64_t max,
      int32_t elements);
  
  /** Free switch. */
  void ecs_switch_free(
      ecs_switch_t *sw);
  
  /** Add element to switch, initialize value to 0 */
  void ecs_switch_add(
      ecs_switch_t *sw);
  
  /** Set number of elements in switch list */
  void ecs_switch_set_count(
      ecs_switch_t *sw,
      int32_t count);
  
  /** Ensure that element exists. */
  void ecs_switch_ensure(
      ecs_switch_t *sw,
      int32_t count);
  
  /** Add n elements. */
  void ecs_switch_addn(
      ecs_switch_t *sw,
      int32_t count);    
  
  /** Set value of element. */
  void ecs_switch_set(
      ecs_switch_t *sw,
      int32_t element,
      uint64_t value);
  
  /** Remove element. */
  void ecs_switch_remove(
      ecs_switch_t *sw,
      int32_t element);
  
  /** Get value for element. */
  uint64_t ecs_switch_get(
      const ecs_switch_t *sw,
      int32_t element);
  
  /** Swap element. */
  void ecs_switch_swap(
      ecs_switch_t *sw,
      int32_t elem_1,
      int32_t elem_2);
  
  /** Get vector with all values. Use together with count(). */
  ecs_vector_t* ecs_switch_values(
      const ecs_switch_t *sw);    
  
  /** Return number of different values. */
  int32_t ecs_switch_case_count(
      const ecs_switch_t *sw,
      uint64_t value);
  
  /** Return first element for value. */
  int32_t ecs_switch_first(
      const ecs_switch_t *sw,
      uint64_t value);
  
  /** Return next element for value. Use with first(). */
  int32_t ecs_switch_next(
      const ecs_switch_t *sw,
      int32_t elem);
  
  #ifdef __cplusplus
  extern "C" {
  #endif
  
  #ifdef __cplusplus
  }
  #endif
  
  #endif
  /**
   * @file strbuf.h
   * @brief Utility for constructing strings.
   *
   * A buffer builds up a list of elements which individually can be up to N bytes
   * large. While appending, data is added to these elements. More elements are
   * added on the fly when needed. When an application calls ecs_strbuf_get, all
   * elements are combined in one string and the element administration is freed.
   *
   * This approach prevents reallocs of large blocks of memory, and therefore
   * copying large blocks of memory when appending to a large buffer. A buffer
   * preallocates some memory for the element overhead so that for small strings
   * there is hardly any overhead, while for large strings the overhead is offset
   * by the reduced time spent on copying memory.
   */
  
  #ifndef FLECS_STRBUF_H_
  #define FLECS_STRBUF_H_
  
  
  #ifdef __cplusplus
  extern "C" {
  #endif
  
  #define ECS_STRBUF_INIT (ecs_strbuf_t){0}
  #define ECS_STRBUF_ELEMENT_SIZE (511)
  #define ECS_STRBUF_MAX_LIST_DEPTH (32)
  
  typedef struct ecs_strbuf_element {
      bool buffer_embedded;
      int32_t pos;
      char *buf;
      struct ecs_strbuf_element *next;
  } ecs_strbuf_element;
  
  typedef struct ecs_strbuf_element_embedded {
      ecs_strbuf_element super;
      char buf[ECS_STRBUF_ELEMENT_SIZE + 1];
  } ecs_strbuf_element_embedded;
  
  typedef struct ecs_strbuf_element_str {
      ecs_strbuf_element super;
      char *alloc_str;
  } ecs_strbuf_element_str;
  
  typedef struct ecs_strbuf_list_elem {
      int32_t count;
      const char *separator;
  } ecs_strbuf_list_elem;
  
  typedef struct ecs_strbuf_t {
      /* When set by an application, append will write to this buffer */
      char *buf;
  
      /* The maximum number of characters that may be printed */
      int32_t max;
  
      /* Size of elements minus current element */
      int32_t size;
  
      /* The number of elements in use */
      int32_t elementCount;
  
      /* Always allocate at least one element */
      ecs_strbuf_element_embedded firstElement;
  
      /* The current element being appended to */
      ecs_strbuf_element *current;
  
      /* Stack that keeps track of number of list elements, used for conditionally
       * inserting a separator */
      ecs_strbuf_list_elem list_stack[ECS_STRBUF_MAX_LIST_DEPTH];
      int32_t list_sp;
  } ecs_strbuf_t;
  
  /* Append format string to a buffer.
   * Returns false when max is reached, true when there is still space */
  FLECS_API
  bool ecs_strbuf_append(
      ecs_strbuf_t *buffer,
      const char *fmt,
      ...);
  
  /* Append format string with argument list to a buffer.
   * Returns false when max is reached, true when there is still space */
  FLECS_API
  bool ecs_strbuf_vappend(
      ecs_strbuf_t *buffer,
      const char *fmt,
      va_list args);
  
  /* Append string to buffer.
   * Returns false when max is reached, true when there is still space */
  FLECS_API
  bool ecs_strbuf_appendstr(
      ecs_strbuf_t *buffer,
      const char *str);
  
  /* Append source buffer to destination buffer.
   * Returns false when max is reached, true when there is still space */
  FLECS_API
  bool ecs_strbuf_mergebuff(
      ecs_strbuf_t *dst_buffer,
      ecs_strbuf_t *src_buffer);
  
  /* Append string to buffer, transfer ownership to buffer.
   * Returns false when max is reached, true when there is still space */
  FLECS_API
  bool ecs_strbuf_appendstr_zerocpy(
      ecs_strbuf_t *buffer,
      char *str);
  
  /* Append string to buffer, do not free/modify string.
   * Returns false when max is reached, true when there is still space */
  FLECS_API
  bool ecs_strbuf_appendstr_zerocpy_const(
      ecs_strbuf_t *buffer,
      const char *str);
  
  /* Append n characters to buffer.
   * Returns false when max is reached, true when there is still space */
  FLECS_API
  bool ecs_strbuf_appendstrn(
      ecs_strbuf_t *buffer,
      const char *str,
      int32_t n);
  
  /* Return result string (also resets buffer) */
  FLECS_API
  char *ecs_strbuf_get(
      ecs_strbuf_t *buffer);
  
  /* Reset buffer without returning a string */
  FLECS_API
  void ecs_strbuf_reset(
      ecs_strbuf_t *buffer);
  
  /* Push a list */
  FLECS_API
  void ecs_strbuf_list_push(
      ecs_strbuf_t *buffer,
      const char *list_open,
      const char *separator);
  
  /* Pop a new list */
  FLECS_API
  void ecs_strbuf_list_pop(
      ecs_strbuf_t *buffer,
      const char *list_close);
  
  /* Insert a new element in list */
  FLECS_API
  void ecs_strbuf_list_next(
      ecs_strbuf_t *buffer);
  
  /* Append formatted string as a new element in list */
  FLECS_API
  bool ecs_strbuf_list_append(
      ecs_strbuf_t *buffer,
      const char *fmt,
      ...);
  
  /* Append string as a new element in list */
  FLECS_API
  bool ecs_strbuf_list_appendstr(
      ecs_strbuf_t *buffer,
      const char *str);
  
  #ifdef __cplusplus
  }
  #endif
  
  #endif
  /**
   * @file os_api.h
   * @brief Operationg system abstractions.
   *
   * This file contains the operating system abstraction API. The flecs core 
   * library avoids OS/runtime specific API calls as much as possible. Instead it
   * provides an interface that can be implemented by applications.
   *
   * Examples for how to implement this interface can be found in the 
   * examples/os_api folder.
   */
  
  #ifndef FLECS_OS_API_H
  #define FLECS_OS_API_H
  
  #include <stdarg.h>
  
  #if defined(_MSC_VER) || defined(__MINGW32__)
  #include <malloc.h>
  #elif defined(__FreeBSD__)
  #include <stdlib.h>
  #else
  #include <alloca.h>
  #endif
  
  #if defined(_WIN32)
  #define ECS_OS_WINDOWS
  #elif defined(__linux__)
  #define ECS_OS_LINUX
  #elif defined(__APPLE__) && defined(__MACH__)
  #define ECS_OS_DARWIN
  #else
  /* Unknown OS */
  #endif
  
  #ifdef __cplusplus
  extern "C" {
  #endif
  
  typedef struct ecs_time_t {
      uint32_t sec;
      uint32_t nanosec;
  } ecs_time_t;
  
  /* Allocation counters (not thread safe) */
  extern int64_t ecs_os_api_malloc_count;
  extern int64_t ecs_os_api_realloc_count;
  extern int64_t ecs_os_api_calloc_count;
  extern int64_t ecs_os_api_free_count;
  
  /* Use handle types that _at least_ can store pointers */
  typedef uintptr_t ecs_os_thread_t;
  typedef uintptr_t ecs_os_cond_t;
  typedef uintptr_t ecs_os_mutex_t;
  typedef uintptr_t ecs_os_dl_t;
  
  /* Generic function pointer type */
  typedef void (*ecs_os_proc_t)(void);
  
  /* OS API init */
  typedef 
  void (*ecs_os_api_init_t)(void);
  
  /* OS API deinit */
  typedef 
  void (*ecs_os_api_fini_t)(void);
  
  /* Memory management */
  typedef 
  void* (*ecs_os_api_malloc_t)(
      ecs_size_t size);
  
  typedef 
  void (*ecs_os_api_free_t)(
      void *ptr);
  
  typedef
  void* (*ecs_os_api_realloc_t)(
      void *ptr, 
      ecs_size_t size);
  
  typedef
  void* (*ecs_os_api_calloc_t)(
      ecs_size_t size);
  
  typedef
  char* (*ecs_os_api_strdup_t)(
      const char *str);
  
  /* Threads */
  typedef
  void* (*ecs_os_thread_callback_t)(
      void*);
  
  typedef
  ecs_os_thread_t (*ecs_os_api_thread_new_t)(
      ecs_os_thread_callback_t callback,
      void *param);
  
  typedef
  void* (*ecs_os_api_thread_join_t)(
      ecs_os_thread_t thread);
  
  
  /* Atomic increment / decrement */
  typedef
  int (*ecs_os_api_ainc_t)(
      int32_t *value);
  
  
  /* Mutex */
  typedef
  ecs_os_mutex_t (*ecs_os_api_mutex_new_t)(
      void);
  
  typedef
  void (*ecs_os_api_mutex_lock_t)(
      ecs_os_mutex_t mutex);
  
  typedef
  void (*ecs_os_api_mutex_unlock_t)(
      ecs_os_mutex_t mutex);
  
  typedef
  void (*ecs_os_api_mutex_free_t)(
      ecs_os_mutex_t mutex);
  
  /* Condition variable */
  typedef
  ecs_os_cond_t (*ecs_os_api_cond_new_t)(
      void);
  
  typedef
  void (*ecs_os_api_cond_free_t)(
      ecs_os_cond_t cond);
  
  typedef
  void (*ecs_os_api_cond_signal_t)(
      ecs_os_cond_t cond);
  
  typedef
  void (*ecs_os_api_cond_broadcast_t)(
      ecs_os_cond_t cond);
  
  typedef
  void (*ecs_os_api_cond_wait_t)(
      ecs_os_cond_t cond,
      ecs_os_mutex_t mutex);
  
  typedef 
  void (*ecs_os_api_sleep_t)(
      int32_t sec,
      int32_t nanosec);
  
  typedef
  void (*ecs_os_api_get_time_t)(
      ecs_time_t *time_out);
  
  /* Logging */
  typedef
  void (*ecs_os_api_log_t)(
      const char *fmt,
      va_list args);
  
  /* Application termination */
  typedef
  void (*ecs_os_api_abort_t)(
      void);
  
  /* Dynamic libraries */
  typedef
  ecs_os_dl_t (*ecs_os_api_dlopen_t)(
      const char *libname);
  
  typedef
  ecs_os_proc_t (*ecs_os_api_dlproc_t)(
      ecs_os_dl_t lib,
      const char *procname);
  
  typedef
  void (*ecs_os_api_dlclose_t)(
      ecs_os_dl_t lib);
  
  typedef
  char* (*ecs_os_api_module_to_path_t)(
      const char *module_id);
  
  /* Prefix members of struct with 'ecs_' as some system headers may define 
   * macro's for functions like "strdup", "log" or "_free" */
  
  typedef struct ecs_os_api_t {
      /* API init / deinit */
      ecs_os_api_init_t init_;
      ecs_os_api_fini_t fini_;
  
      /* Memory management */
      ecs_os_api_malloc_t malloc_;
      ecs_os_api_realloc_t realloc_;
      ecs_os_api_calloc_t calloc_;
      ecs_os_api_free_t free_;
  
      /* Strings */
      ecs_os_api_strdup_t strdup_;
  
      /* Threads */
      ecs_os_api_thread_new_t thread_new_;
      ecs_os_api_thread_join_t thread_join_;
  
      /* Atomic incremenet / decrement */
      ecs_os_api_ainc_t ainc_;
      ecs_os_api_ainc_t adec_;
  
      /* Mutex */
      ecs_os_api_mutex_new_t mutex_new_;
      ecs_os_api_mutex_free_t mutex_free_;
      ecs_os_api_mutex_lock_t mutex_lock_;
      ecs_os_api_mutex_lock_t mutex_unlock_;
  
      /* Condition variable */
      ecs_os_api_cond_new_t cond_new_;
      ecs_os_api_cond_free_t cond_free_;
      ecs_os_api_cond_signal_t cond_signal_;
      ecs_os_api_cond_broadcast_t cond_broadcast_;
      ecs_os_api_cond_wait_t cond_wait_;
  
      /* Time */
      ecs_os_api_sleep_t sleep_;
      ecs_os_api_get_time_t get_time_;
  
      /* Logging */
      ecs_os_api_log_t log_;
      ecs_os_api_log_t log_error_;
      ecs_os_api_log_t log_debug_;
      ecs_os_api_log_t log_warning_;
  
      /* Application termination */
      ecs_os_api_abort_t abort_;
  
      /* Dynamic library loading */
      ecs_os_api_dlopen_t dlopen_;
      ecs_os_api_dlproc_t dlproc_;
      ecs_os_api_dlclose_t dlclose_;
  
      /* Overridable function that translates from a logical module id to a
       * shared library filename */
      ecs_os_api_module_to_path_t module_to_dl_;
  
      /* Overridable function that translates from a logical module id to a
       * path that contains module-specif resources or assets */
      ecs_os_api_module_to_path_t module_to_etc_;    
  } ecs_os_api_t;
  
  FLECS_API
  extern ecs_os_api_t ecs_os_api;
  
  FLECS_API
  void ecs_os_init(void);
  
  FLECS_API
  void ecs_os_fini(void);
  
  FLECS_API
  void ecs_os_set_api(
      ecs_os_api_t *os_api);
  
  FLECS_API
  void ecs_os_set_api_defaults(void);
  
  /* Memory management */
  #ifndef ecs_os_malloc
  #define ecs_os_malloc(size) ecs_os_api.malloc_(size)
  #endif
  #ifndef ecs_os_free
  #define ecs_os_free(ptr) ecs_os_api.free_(ptr)
  #endif
  #ifndef ecs_os_realloc
  #define ecs_os_realloc(ptr, size) ecs_os_api.realloc_(ptr, size)
  #endif
  #ifndef ecs_os_calloc
  #define ecs_os_calloc(size) ecs_os_api.calloc_(size)
  #endif
  #if defined(_MSC_VER) || defined(__MINGW32__)
  #define ecs_os_alloca(size) _alloca((size_t)(size))
  #else
  #define ecs_os_alloca(size) alloca((size_t)(size))
  #endif
  
  /* Strings */
  #ifndef ecs_os_strdup
  #define ecs_os_strdup(str) ecs_os_api.strdup_(str)
  #endif
  #define ecs_os_strlen(str) (ecs_size_t)strlen(str)
  #define ecs_os_strcmp(str1, str2) strcmp(str1, str2)
  #define ecs_os_strncmp(str1, str2, num) strncmp(str1, str2, (size_t)(num))
  #define ecs_os_memcmp(ptr1, ptr2, num) memcmp(ptr1, ptr2, (size_t)(num))
  #define ecs_os_memcpy(ptr1, ptr2, num) memcpy(ptr1, ptr2, (size_t)(num))
  #define ecs_os_memset(ptr, value, num) memset(ptr, value, (size_t)(num))
  #define ecs_os_memmove(ptr, value, num) memmove(ptr, value, (size_t)(num))
  
  #if defined(_MSC_VER)
  #define ecs_os_strcat(str1, str2) strcat_s(str1, INT_MAX, str2)
  #define ecs_os_sprintf(ptr, ...) sprintf_s(ptr, INT_MAX, __VA_ARGS__)
  #define ecs_os_vsprintf(ptr, fmt, args) vsprintf_s(ptr, INT_MAX, fmt, args)
  #define ecs_os_strcpy(str1, str2) strcpy_s(str1, INT_MAX, str2)
  #define ecs_os_strncpy(str1, str2, num) strncpy_s(str1, INT_MAX, str2, (size_t)(num))
  #else
  #define ecs_os_strcat(str1, str2) strcat(str1, str2)
  #define ecs_os_sprintf(ptr, ...) sprintf(ptr, __VA_ARGS__)
  #define ecs_os_vsprintf(ptr, fmt, args) vsprintf(ptr, fmt, args)
  #define ecs_os_strcpy(str1, str2) strcpy(str1, str2)
  #define ecs_os_strncpy(str1, str2, num) strncpy(str1, str2, (size_t)(num))
  #endif
  
  
  /* Threads */
  #define ecs_os_thread_new(callback, param) ecs_os_api.thread_new_(callback, param)
  #define ecs_os_thread_join(thread) ecs_os_api.thread_join_(thread)
  
  /* Atomic increment / decrement */
  #define ecs_os_ainc(value) ecs_os_api.ainc_(value)
  #define ecs_os_adec(value) ecs_os_api.adec_(value)
  
  /* Mutex */
  #define ecs_os_mutex_new() ecs_os_api.mutex_new_()
  #define ecs_os_mutex_free(mutex) ecs_os_api.mutex_free_(mutex)
  #define ecs_os_mutex_lock(mutex) ecs_os_api.mutex_lock_(mutex)
  #define ecs_os_mutex_unlock(mutex) ecs_os_api.mutex_unlock_(mutex)
  
  /* Condition variable */
  #define ecs_os_cond_new() ecs_os_api.cond_new_()
  #define ecs_os_cond_free(cond) ecs_os_api.cond_free_(cond)
  #define ecs_os_cond_signal(cond) ecs_os_api.cond_signal_(cond)
  #define ecs_os_cond_broadcast(cond) ecs_os_api.cond_broadcast_(cond)
  #define ecs_os_cond_wait(cond, mutex) ecs_os_api.cond_wait_(cond, mutex)
  
  /* Time */
  #define ecs_os_sleep(sec, nanosec) ecs_os_api.sleep_(sec, nanosec)
  #define ecs_os_get_time(time_out) ecs_os_api.get_time_(time_out)
  
  /* Logging (use functions to avoid using variadic macro arguments) */
  FLECS_API
  void ecs_os_log(const char *fmt, ...);
  
  FLECS_API
  void ecs_os_warn(const char *fmt, ...);
  
  FLECS_API
  void ecs_os_err(const char *fmt, ...);
  
  FLECS_API
  void ecs_os_dbg(const char *fmt, ...);
  
  /* Application termination */
  #define ecs_os_abort() ecs_os_api.abort_()
  
  /* Dynamic libraries */
  #define ecs_os_dlopen(libname) ecs_os_api.dlopen_(libname)
  #define ecs_os_dlproc(lib, procname) ecs_os_api.dlproc_(lib, procname)
  #define ecs_os_dlclose(lib) ecs_os_api.dlclose_(lib)
  
  /* Module id translation */
  #define ecs_os_module_to_dl(lib) ecs_os_api.module_to_dl_(lib)
  #define ecs_os_module_to_etc(lib) ecs_os_api.module_to_etc_(lib)
  
  /* Sleep with floating point time */
  FLECS_API
  void ecs_sleepf(
      double t);
  
  /* Measure time since provided timestamp */
  FLECS_API
  double ecs_time_measure(
      ecs_time_t *start);
  
  /* Calculate difference between two timestamps */
  FLECS_API
  ecs_time_t ecs_time_sub(
      ecs_time_t t1,
      ecs_time_t t2);
  
  /* Convert time value to a double */
  FLECS_API
  double ecs_time_to_double(
      ecs_time_t t);
  
  FLECS_API
  void* ecs_os_memdup(
      const void *src, 
      ecs_size_t size);
  
  /** Are heap functions available? */
  FLECS_API
  bool ecs_os_has_heap(void);
  
  /** Are threading functions available? */
  FLECS_API
  bool ecs_os_has_threading(void);
  
  /** Are time functions available? */
  FLECS_API
  bool ecs_os_has_time(void);
  
  /** Are logging functions available? */
  FLECS_API
  bool ecs_os_has_logging(void);
  
  /** Are dynamic library functions available? */
  FLECS_API
  bool ecs_os_has_dl(void);
  
  /** Are module path functions available? */
  FLECS_API
  bool ecs_os_has_modules(void);
  
  #ifdef __cplusplus
  }
  #endif
  
  #endif
  
  #ifdef __cplusplus
  extern "C" {
  #endif
  
  
  /**
   * @defgroup api_types Basic API types
   * @{
   */
  
  /** An entity identifier. */
  typedef uint64_t ecs_entity_t;
  
  /** A vector containing component identifiers used to describe a type. */
  typedef const ecs_vector_t* ecs_type_t;
  
  /** An ECS world is the container for all ECS data and supporting features. */
  typedef struct ecs_world_t ecs_world_t;
  
  /** A snapshot stores the state of a world in a particular point in time. */
  typedef struct ecs_snapshot_t ecs_snapshot_t;
  
  /** Queries are the primary mechanism for iterating (prematched) entities. */
  typedef struct ecs_query_t ecs_query_t;
  
  /* An iterator lets an application iterate entities across tables. */
  typedef struct ecs_iter_t ecs_iter_t;
  
  /** Refs cache data that lets them access components faster than ecs_get. */
  typedef struct ecs_ref_t ecs_ref_t;
  
  /** Describes how a filter should match components with a table. */
  typedef enum ecs_match_kind_t {
      EcsMatchDefault = 0,
      EcsMatchAll,            /**< Match all components in a type */
      EcsMatchAny,            /**< Match one of the components in a type */
      EcsMatchExact           /**< Match the type exactly */
  } ecs_match_kind_t;
  
  /** Filters alllow for ad-hoc quick filtering of entity tables. */
  typedef struct ecs_filter_t {
      ecs_type_t include;             /**< Components that should match */
      ecs_type_t exclude;             /**< Components that should not match */
      ecs_match_kind_t include_kind;  /**< Match kind for include components */
      ecs_match_kind_t exclude_kind;  /**< Match kind for exclude components */
  } ecs_filter_t;
  
  /** Type that contains information about the world. */
  typedef struct ecs_world_info_t {
      ecs_entity_t last_component_id;   /**< Last issued component entity id */
      ecs_entity_t last_id;             /**< Last issued entity id */
      ecs_entity_t min_id;              /**< First allowed entity id */
      ecs_entity_t max_id;              /**< Last allowed entity id */
  
      FLECS_FLOAT delta_time_raw;      /**< Raw delta time (no time scaling) */
      FLECS_FLOAT delta_time;          /**< Time passed to or computed by ecs_progress */
      FLECS_FLOAT time_scale;          /**< Time scale applied to delta_time */
      FLECS_FLOAT target_fps;          /**< Target fps */
      FLECS_FLOAT frame_time_total;    /**< Total time spent processing a frame */
      FLECS_FLOAT system_time_total;   /**< Total time spent in systems */
      FLECS_FLOAT merge_time_total;    /**< Total time spent in merges */
      FLECS_FLOAT world_time_total;    /**< Time elapsed in simulation */
      FLECS_FLOAT world_time_total_raw; /**< Time elapsed in simulation (no scaling) */
      FLECS_FLOAT sleep_err;           /**< Measured sleep error */
      
      int32_t frame_count_total;  /**< Total number of frames */
      int32_t merge_count_total;  /**< Total number of merges */
      int32_t pipeline_build_count_total; /**< Total number of pipeline builds */
      int32_t systems_ran_frame;  /**< Total number of systems ran in last frame */
  } ecs_world_info_t;
  
  /** @} */
  
  /**
   * @defgroup function_types Function Types
   * @{
   */
  
  /** Action callback for systems and triggers */
  typedef void (*ecs_iter_action_t)(
      ecs_iter_t *it);
  
  typedef bool (*ecs_iter_next_action_t)(
      ecs_iter_t *it);
  
  /** Compare callback used for sorting */
  typedef int (*ecs_compare_action_t)(
      ecs_entity_t e1,
      const void *ptr1,
      ecs_entity_t e2,
      const void *ptr2);    
  
  /** Compare callback used for sorting */
  typedef int32_t (*ecs_rank_type_action_t)(
      ecs_world_t *world,
      ecs_entity_t rank_component,
      ecs_type_t type);
  
  /** Initialization action for modules */
  typedef void (*ecs_module_action_t)(
      ecs_world_t *world);    
  
  /** Action callback on world exit */
  typedef void (*ecs_fini_action_t)(
      ecs_world_t *world,
      void *ctx);
  
  /**
   * @file api_types.h
   * @brief Supporting types for the public API.
   *
   * This file contains types that are typically not used by an application but 
   * support the public API, and therefore must be exposed. This header should not
   * be included by itself.
   */
  
  #ifndef FLECS_API_TYPES_H
  #define FLECS_API_TYPES_H
  
  
  #ifdef __cplusplus
  extern "C" {
  #endif
  
  
  ////////////////////////////////////////////////////////////////////////////////
  //// Opaque types
  ////////////////////////////////////////////////////////////////////////////////
  
  /** A stage enables modification while iterating and from multiple threads */
  typedef struct ecs_stage_t ecs_stage_t;
  
  /** A table is where entities and components are stored */
  typedef struct ecs_table_t ecs_table_t;
  
  /** A record stores data to map an entity id to a location in a table */
  typedef struct ecs_record_t ecs_record_t;
  
  /** Table column */
  typedef struct ecs_column_t ecs_column_t;
  
  /** Table data */
  typedef struct ecs_data_t ecs_data_t;
  
  
  ////////////////////////////////////////////////////////////////////////////////
  //// Non-opaque types
  ////////////////////////////////////////////////////////////////////////////////
  
  struct ecs_record_t {
      ecs_table_t *table;  /* Identifies a type (and table) in world */
      int32_t row;         /* Table row of the entity */
  };
  
  /** Cached reference. */
  struct ecs_ref_t {
      ecs_entity_t entity;    /**< Entity of the reference */
      ecs_entity_t component; /**< Component of the reference */
      void *table;            /**< Last known table */
      int32_t row;            /**< Last known location in table */
      int32_t alloc_count;    /**< Last known alloc count of table */
      ecs_record_t *record;   /**< Pointer to record, if in main stage */
      const void *ptr;        /**< Cached ptr */
  };
  
  /** Array of entity ids that, other than a type, can live on the stack */
  typedef struct ecs_entities_t {
      ecs_entity_t *array;    /**< An array with entity ids */
      int32_t count;          /**< The number of entities in the array */
  } ecs_entities_t;
  
  typedef struct ecs_page_cursor_t {
      int32_t first;
      int32_t count;
  } ecs_page_cursor_t;
  
  typedef struct ecs_page_iter_t {
      int32_t offset;
      int32_t limit;
      int32_t remaining;
  } ecs_page_iter_t;
  
  /** Table specific data for iterators */
  typedef struct ecs_iter_table_t {
      int32_t *columns;        /**< Mapping from query columns to table columns */
      ecs_table_t *table;       /**< The current table. */
      ecs_data_t *data;         /**< Table component data */
      ecs_entity_t *components; /**< Components in current table */
      ecs_type_t *types;        /**< Components in current table */
      ecs_ref_t *references;    /**< References to entities (from query) */
  } ecs_iter_table_t;
  
  /** Scope-iterator specific data */
  typedef struct ecs_scope_iter_t {
      ecs_filter_t filter;
      ecs_vector_t *tables;
      int32_t index;
      ecs_iter_table_t table;
  } ecs_scope_iter_t;
  
  /** Filter-iterator specific data */
  typedef struct ecs_filter_iter_t {
      ecs_filter_t filter;
      ecs_sparse_t *tables;
      int32_t index;
      ecs_iter_table_t table;
  } ecs_filter_iter_t;
  
  /** Iterator flags used to quickly select the optimal iterator algorithm */
  typedef enum ecs_query_iter_kind_t {
      EcsQuerySimpleIter,     /**< No paging, sorting or sparse columns */
      EcsQueryPagedIter,      /**< Regular iterator with paging */
      EcsQuerySortedIter,     /**< Sorted iterator */
      EcsQuerySwitchIter      /**< Switch type iterator */
  } ecs_query_iter_kind_t;
  
  /** Query-iterator specific data */
  typedef struct ecs_query_iter_t {
      ecs_page_iter_t page_iter;
      int32_t index;
      int32_t sparse_smallest;
      int32_t sparse_first;
      int32_t bitset_first;
  } ecs_query_iter_t;  
  
  /** Query-iterator specific data */
  typedef struct ecs_snapshot_iter_t {
      ecs_filter_t filter;
      ecs_vector_t *tables; /* ecs_table_leaf_t */
      int32_t index;
      ecs_iter_table_t table;
  } ecs_snapshot_iter_t;  
  
  /** The ecs_iter_t struct allows applications to iterate tables.
   * Queries and filters, among others, allow an application to iterate entities
   * that match a certain set of components. Because of how data is stored 
   * internally, entities with a given set of components may be stored in multiple
   * consecutive arrays, stored across multiple tables. The ecs_iter_t type 
   * enables iteration across tables. */
  struct ecs_iter_t {
      ecs_world_t *world;           /**< The world */
      ecs_world_t *real_world;      /**< Actual world. This differs from world when using threads.  */
      ecs_entity_t system;          /**< The current system (if applicable) */
      ecs_query_iter_kind_t kind;
  
      ecs_iter_table_t *table;      /**< Table related data */
      ecs_query_t *query;           /**< Current query being evaluated */
      int32_t table_count;          /**< Active table count for query */
      int32_t inactive_table_count; /**< Inactive table count for query */
      int32_t column_count;         /**< Number of columns for system */
      
      void *table_columns;          /**< Table component data */
      ecs_entity_t *entities;       /**< Entity identifiers */
  
      void *param;                  /**< User data (EcsContext or param argument) */
      FLECS_FLOAT delta_time;       /**< Time elapsed since last frame */
      FLECS_FLOAT delta_system_time;/**< Time elapsed since last system invocation */
      FLECS_FLOAT world_time;       /**< Time elapsed since start of simulation */
  
      int32_t frame_offset;         /**< Offset relative to frame */
      int32_t offset;               /**< Offset relative to current table */
      int32_t count;                /**< Number of entities to process by system */
      int32_t total_count;          /**< Total number of entities in table */
  
      ecs_entities_t *triggered_by; /**< Component(s) that triggered the system */
      ecs_entity_t interrupted_by;  /**< When set, system execution is interrupted */
  
      union {
          ecs_scope_iter_t parent;
          ecs_filter_iter_t filter;
          ecs_query_iter_t query;
          ecs_snapshot_iter_t snapshot;
      } iter;                       /**< Iterator specific data */
  };
  
  typedef enum EcsMatchFailureReason {
      EcsMatchOk,
      EcsMatchNotASystem,
      EcsMatchSystemIsATask,
      EcsMatchEntityIsDisabled,
      EcsMatchEntityIsPrefab,
      EcsMatchFromSelf,
      EcsMatchFromOwned,
      EcsMatchFromShared,
      EcsMatchFromContainer,
      EcsMatchFromEntity,
      EcsMatchOrFromSelf,
      EcsMatchOrFromOwned,
      EcsMatchOrFromShared,
      EcsMatchOrFromContainer,
      EcsMatchNotFromSelf,
      EcsMatchNotFromOwned,
      EcsMatchNotFromShared,
      EcsMatchNotFromContainer,
  } EcsMatchFailureReason;
  
  typedef struct ecs_match_failure_t {
      EcsMatchFailureReason reason;
      int32_t column;
  } ecs_match_failure_t;
  
  ////////////////////////////////////////////////////////////////////////////////
  //// Function types
  ////////////////////////////////////////////////////////////////////////////////
  
  /** Constructor/destructor. Used for initializing / deinitializing components. */
  typedef void (*ecs_xtor_t)(
      ecs_world_t *world,
      ecs_entity_t component,
      const ecs_entity_t *entity_ptr,
      void *ptr,
      size_t size,
      int32_t count,
      void *ctx);
  
  /** Copy is invoked when a component is copied into another component. */
  typedef void (*ecs_copy_t)(
      ecs_world_t *world,
      ecs_entity_t component,    
      const ecs_entity_t *dst_entity,
      const ecs_entity_t *src_entity,
      void *dst_ptr,
      const void *src_ptr,
      size_t size,
      int32_t count,
      void *ctx);
  
  /** Move is invoked when a component is moved to another component. */
  typedef void (*ecs_move_t)(
      ecs_world_t *world,
      ecs_entity_t component,
      const ecs_entity_t *dst_entity,
      const ecs_entity_t *src_entity,
      void *dst_ptr,
      void *src_ptr,
      size_t size,
      int32_t count,
      void *ctx);
  
  
  #ifdef __cplusplus
  }
  #endif
  
  #endif
  /**
   * @file api_support.h
   * @brief Support functions and constants.
   *
   * Supporting types and functions that need to be exposed either in support of 
   * the public API or for unit tests, but that may change between minor / patch 
   * releases. 
   */
  
  #ifndef FLECS_API_SUPPORT_H
  #define FLECS_API_SUPPORT_H
  
  
  #ifdef __cplusplus
  extern "C" {
  #endif
  
  /** This reserves entity ids for components. Regular entity ids will start after
   * this constant. This affects performance of table traversal, as edges with ids 
   * lower than this constant are looked up in an array, whereas constants higher
   * than this id are looked up in a map. Increasing this value can improve
   * performance at the cost of (significantly) higher memory usage. */
  #define ECS_HI_COMPONENT_ID (256) /* Maximum number of components */
  
  
  ////////////////////////////////////////////////////////////////////////////////
  //// Global type handles
  ////////////////////////////////////////////////////////////////////////////////
  
  /** Type handles to builtin components */
  FLECS_API
  extern ecs_type_t 
      ecs_type(EcsComponent),
      ecs_type(EcsComponentLifecycle),
      ecs_type(EcsType),
      ecs_type(EcsName);
  
  /** This allows passing 0 as type to functions that accept types */
  #define FLECS__TNULL 0
  #define FLECS__T0 0
  
  
  ////////////////////////////////////////////////////////////////////////////////
  //// Functions used in declarative (macro) API
  ////////////////////////////////////////////////////////////////////////////////
  
  FLECS_API
  ecs_entity_t ecs_new_entity(
      ecs_world_t *world,
      ecs_entity_t e,
      const char *id,
      const char *components);
  
  FLECS_API
  ecs_entity_t ecs_new_component(
      ecs_world_t *world,
      ecs_entity_t e,
      const char *id,
      size_t size,
      size_t alignment);
  
  FLECS_API
  ecs_entity_t ecs_new_module(
      ecs_world_t *world,
      ecs_entity_t e,
      const char *name,
      size_t size,
      size_t alignment);
  
  FLECS_API
  ecs_entity_t ecs_new_type(
      ecs_world_t *world,
      ecs_entity_t e,
      const char *id,
      const char *components);
  
  FLECS_API
  ecs_entity_t ecs_new_prefab(
      ecs_world_t *world,
      ecs_entity_t e,
      const char *id,
      const char *sig);
  
  FLECS_API
  ecs_entity_t ecs_new_system(
      ecs_world_t *world,
      ecs_entity_t e,
      const char *name,
      ecs_entity_t phase,
      const char *signature,
      ecs_iter_action_t action);
  
  FLECS_API
  ecs_entity_t ecs_new_trigger(
      ecs_world_t *world,
      ecs_entity_t e,
      const char *name,
      ecs_entity_t kind,
      const char *component,
      ecs_iter_action_t action);
  
  FLECS_API
  ecs_entity_t ecs_new_pipeline(
      ecs_world_t *world,
      ecs_entity_t e,
      const char *name,
      const char *expr);
  
  FLECS_API
  char* ecs_module_path_from_c(
      const char *c_name);
  
  FLECS_API
  bool ecs_component_has_actions(
      ecs_world_t *world,
      ecs_entity_t component);
  
  ////////////////////////////////////////////////////////////////////////////////
  //// Signature API
  ////////////////////////////////////////////////////////////////////////////////
  
  typedef enum ecs_sig_inout_kind_t {
      EcsInOut,
      EcsIn,
      EcsOut
  } ecs_sig_inout_kind_t;
  
  /** Type that is used by systems to indicate where to fetch a component from */
  typedef enum ecs_sig_from_kind_t {
      EcsFromAny,            /* Get component from self (default) */
      EcsFromOwned,           /* Get owned component from self */
      EcsFromShared,          /* Get shared component from self */
      EcsFromParent,          /* Get component from container */
      EcsFromSystem,          /* Get component from system */
      EcsFromEmpty,           /* Get entity handle by id */
      EcsFromEntity,          /* Get component from other entity */
      EcsCascade              /* Walk component in cascading (hierarchy) order */
  } ecs_sig_from_kind_t;
  
  /** Type describing an operator used in an signature of a system signature */
  typedef enum ecs_sig_oper_kind_t {
      EcsOperAnd = 0,
      EcsOperOr = 1,
      EcsOperNot = 2,
      EcsOperOptional = 3,
      EcsOperAll = 4,
      EcsOperLast = 5
  } ecs_sig_oper_kind_t;
  
  /** Type that describes a single column in the system signature */
  typedef struct ecs_sig_column_t {
      ecs_sig_from_kind_t from_kind;        /* Element kind (Entity, Component) */
      ecs_sig_oper_kind_t oper_kind;   /* Operator kind (AND, OR, NOT) */
      ecs_sig_inout_kind_t inout_kind; /* Is component read or written */
      union {
          ecs_vector_t *type;          /* Used for OR operator */
          ecs_entity_t component;      /* Used for AND operator */
      } is;
      ecs_entity_t source;             /* Source entity (used with FromEntity) */
      char *name;                /* Name of column */
  } ecs_sig_column_t;
  
  /** Type that stores a parsed signature */
  typedef struct ecs_sig_t {
      const char *name;           /* Optional name used for debugging */
      char *expr;                 /* Original expression string */
      ecs_vector_t *columns;      /* Columns that contain parsed data */
  } ecs_sig_t;
  
  /** Parse signature. */
  FLECS_API
  void ecs_sig_init(
      ecs_world_t *world,
      const char *name,
      const char *expr,
      ecs_sig_t *sig);
  
  /** Release signature resources */
  FLECS_API
  void ecs_sig_deinit(
      ecs_sig_t *sig);
  
  /** Add column to signature. */
  FLECS_API
  int ecs_sig_add(
      ecs_world_t *world,
      ecs_sig_t *sig,
      ecs_sig_from_kind_t from_kind,
      ecs_sig_oper_kind_t oper_kind,
      ecs_sig_inout_kind_t access_kind,
      ecs_entity_t component,
      ecs_entity_t source,
      const char *arg_name);
  
  /** Create query based on signature object. */
  FLECS_API
  ecs_query_t* ecs_query_new_w_sig(
      ecs_world_t *world,
      ecs_entity_t system,
      ecs_sig_t *sig);
  
  /** Get signature object from query */
  FLECS_API
  ecs_sig_t* ecs_query_get_sig(
      ecs_query_t *query);
  
  
  #define ECS_INVALID_ENTITY (1)
  #define ECS_INVALID_PARAMETER (2)
  #define ECS_INVALID_COMPONENT_ID (3)
  #define ECS_INVALID_EXPRESSION (4)
  #define ECS_INVALID_TYPE_EXPRESSION (5)
  #define ECS_INVALID_SIGNATURE (6)
  #define ECS_UNKNOWN_COMPONENT_ID (7)
  #define ECS_UNKNOWN_TYPE_ID (8)
  #define ECS_TYPE_NOT_AN_ENTITY (9)
  #define ECS_MISSING_SYSTEM_CONTEXT (10)
  #define ECS_NOT_A_COMPONENT (11)
  #define ECS_INTERNAL_ERROR (12)
  #define ECS_MORE_THAN_ONE_PREFAB (13)
  #define ECS_ALREADY_DEFINED (14)
  #define ECS_INVALID_COMPONENT_SIZE (15)
  #define ECS_INVALID_COMPONENT_ALIGNMENT (16)
  #define ECS_OUT_OF_MEMORY (17)
  #define ECS_MODULE_UNDEFINED (18)
  #define ECS_COLUMN_INDEX_OUT_OF_RANGE (19)
  #define ECS_COLUMN_IS_NOT_SHARED (20)
  #define ECS_COLUMN_IS_SHARED (21)
  #define ECS_COLUMN_HAS_NO_DATA (22)
  #define ECS_COLUMN_TYPE_MISMATCH (23)
  #define ECS_INVALID_WHILE_MERGING (24)
  #define ECS_INVALID_WHILE_ITERATING (25)
  #define ECS_INVALID_FROM_WORKER (26)
  #define ECS_UNRESOLVED_IDENTIFIER (27)
  #define ECS_OUT_OF_RANGE (28)
  #define ECS_COLUMN_IS_NOT_SET (29)
  #define ECS_UNRESOLVED_REFERENCE (30)
  #define ECS_THREAD_ERROR (31)
  #define ECS_MISSING_OS_API (32)
  #define ECS_TYPE_TOO_LARGE (33)
  #define ECS_INVALID_PREFAB_CHILD_TYPE (34)
  #define ECS_UNSUPPORTED (35)
  #define ECS_NO_OUT_COLUMNS (36)
  #define ECS_COLUMN_ACCESS_VIOLATION (37)
  #define ECS_DESERIALIZE_COMPONENT_ID_CONFLICT (38)
  #define ECS_DESERIALIZE_COMPONENT_SIZE_CONFLICT (39)
  #define ECS_DESERIALIZE_FORMAT_ERROR (40)
  #define ECS_INVALID_REACTIVE_SIGNATURE (41)
  #define ECS_INCONSISTENT_COMPONENT_NAME (42)
  #define ECS_TYPE_CONSTRAINT_VIOLATION (43)
  #define ECS_COMPONENT_NOT_REGISTERED (44)
  #define ECS_INCONSISTENT_COMPONENT_ID (45)
  #define ECS_INVALID_CASE (46)
  #define ECS_COMPONENT_NAME_IN_USE (47)
  #define ECS_INCONSISTENT_NAME (48)
  #define ECS_INCONSISTENT_COMPONENT_ACTION (49)
  #define ECS_INVALID_OPERATION (50)
  
  /** Calculate offset from address */
  #define ECS_OFFSET(o, offset) (void*)(((uintptr_t)(o)) + ((uintptr_t)(offset)))
  
  #ifdef __cplusplus
  }
  #endif
  
  #endif
  /**
   * @file log.h
   * @brief Internal logging API.
   *
   * Internal utility functions for tracing, warnings and errors. 
   */
  
  #ifndef FLECS_LOG_H
  #define FLECS_LOG_H
  
  
  #ifdef __cplusplus
  extern "C" {
  #endif
  
  
  ////////////////////////////////////////////////////////////////////////////////
  //// Color macro's
  ////////////////////////////////////////////////////////////////////////////////
  
  #define ECS_BLACK   "\033[1;30m"
  #define ECS_RED     "\033[0;31m"
  #define ECS_GREEN   "\033[0;32m"
  #define ECS_YELLOW  "\033[0;33m"
  #define ECS_BLUE    "\033[0;34m"
  #define ECS_MAGENTA "\033[0;35m"
  #define ECS_CYAN    "\033[0;36m"
  #define ECS_WHITE   "\033[1;37m"
  #define ECS_GREY    "\033[0;37m"
  #define ECS_NORMAL  "\033[0;49m"
  #define ECS_BOLD    "\033[1;49m"
  
  
  ////////////////////////////////////////////////////////////////////////////////
  //// Tracing
  ////////////////////////////////////////////////////////////////////////////////
  
  FLECS_API
  void _ecs_trace(
      int level,
      const char *file,
      int32_t line,
      const char *fmt,
      ...);
  
  FLECS_API
  void _ecs_warn(
      const char *file,
      int32_t line,
      const char *fmt,
      ...);
  
  FLECS_API
  void _ecs_err(
      const char *file,
      int32_t line,
      const char *fmt,
      ...);
  FLECS_API
  void ecs_log_push(void);
  
  FLECS_API
  void ecs_log_pop(void);
  
  #ifndef FLECS_LEGACY
  
  #define ecs_trace(lvl, ...)\
      _ecs_trace(lvl, __FILE__, __LINE__, __VA_ARGS__)
  
  #define ecs_warn(...)\
      _ecs_warn(__FILE__, __LINE__, __VA_ARGS__)
  
  #define ecs_err(...)\
      _ecs_err(__FILE__, __LINE__, __VA_ARGS__)
  
  
  /* If in debug mode and no tracing verbosity is defined, compile all tracing */
  #if !defined(NDEBUG) && !(defined(ECS_TRACE_0) || defined(ECS_TRACE_1) || defined(ECS_TRACE_2) || defined(ECS_TRACE_3))
  #define ECS_TRACE_3
  #endif
  
  #ifndef NDEBUG
  #if defined(ECS_TRACE_3)
  #define ecs_trace_1(...) ecs_trace(1, __VA_ARGS__);
  #define ecs_trace_2(...) ecs_trace(2, __VA_ARGS__);
  #define ecs_trace_3(...) ecs_trace(3, __VA_ARGS__);
  
  #elif defined(ECS_TRACE_2)
  #define ecs_trace_1(...) ecs_trace(1, __VA_ARGS__);
  #define ecs_trace_2(...) ecs_trace(2, __VA_ARGS__);
  #define ecs_trace_3(...)
  
  #elif defined(ECS_TRACE_1)
  #define ecs_trace_1(...) ecs_trace(1, __VA_ARGS__);
  #define ecs_trace_2(...)
  #define ecs_trace_3(...)
  #endif
  #else
  #define ecs_trace_1(...)
  #define ecs_trace_2(...)
  #define ecs_trace_3(...)
  #endif
  #endif
  
  ////////////////////////////////////////////////////////////////////////////////
  //// Exceptions
  ////////////////////////////////////////////////////////////////////////////////
  
  /** Get description for error code */
  FLECS_API
  const char* ecs_strerror(
      int32_t error_code);
  
  /** Abort */
  FLECS_API
  void _ecs_abort(
      int32_t error_code,
      const char *param,
      const char *file,
      int32_t line);
  
  #define ecs_abort(error_code, param)\
      _ecs_abort(error_code, param, __FILE__, __LINE__); abort()
  
  /** Assert */
  FLECS_API
  void _ecs_assert(
      bool condition,
      int32_t error_code,
      const char *param,
      const char *condition_str,
      const char *file,
      int32_t line);
  
  #ifdef NDEBUG
  #define ecs_assert(condition, error_code, param)
  #else
  #define ecs_assert(condition, error_code, param)\
      _ecs_assert(condition, error_code, param, #condition, __FILE__, __LINE__);\
      assert(condition)
  #endif
  
  FLECS_API
  void _ecs_parser_error(
      const char *name,
      const char *expr, 
      int64_t column,
      const char *fmt,
      ...);
  
  #ifndef FLECS_LEGACY
  
  #define ecs_parser_error(name, expr, column, ...)\
      _ecs_parser_error(name, expr, column, __VA_ARGS__);\
      abort()
  
  #endif
  
  #ifdef __cplusplus
  }
  #endif
  
  #endif
  /**
   * @file type.h
   * @brief Type API.
   *
   * This API contains utilities for working with types. Types are vectors of
   * component ids, and are used most prominently in the API to construct filters.
   */
  
  #ifndef FLECS_TYPE_H
  #define FLECS_TYPE_H
  
  #ifdef __cplusplus
  extern "C" {
  #endif
  
  FLECS_API
  ecs_type_t ecs_type_from_entity(
      ecs_world_t *world,
      ecs_entity_t entity);
  
  FLECS_API
  ecs_entity_t ecs_type_to_entity(
      ecs_world_t *world,
      ecs_type_t type);
  
  FLECS_API
  char* ecs_type_str(
      ecs_world_t *world,
      ecs_type_t type);  
  
  FLECS_API
  ecs_type_t ecs_type_from_str(
      ecs_world_t *world,
      const char *expr);    
  
  FLECS_API
  ecs_type_t ecs_type_find(
      ecs_world_t *world,
      ecs_entity_t *array,
      int32_t count);
  
  FLECS_API
  ecs_type_t ecs_type_merge(
      ecs_world_t *world,
      ecs_type_t type,
      ecs_type_t type_add,
      ecs_type_t type_remove);
  
  FLECS_API
  ecs_type_t ecs_type_add(
      ecs_world_t *world,
      ecs_type_t type,
      ecs_entity_t entity);
  
  FLECS_API
  ecs_type_t ecs_type_remove(
      ecs_world_t *world,
      ecs_type_t type,
      ecs_entity_t entity);
  
  FLECS_API
  bool ecs_type_has_entity(
      ecs_world_t *world,
      ecs_type_t type,
      ecs_entity_t entity);
  
  FLECS_API
  bool ecs_type_has_type(
      ecs_world_t *world,
      ecs_type_t type,
      ecs_type_t has);
  
  FLECS_API
  bool ecs_type_owns_entity(
      ecs_world_t *world,
      ecs_type_t type,
      ecs_entity_t entity,
      bool owned);
  
  FLECS_API
  bool ecs_type_owns_type(
      ecs_world_t *world,
      ecs_type_t type,
      ecs_type_t has,
      bool owned);
  
  FLECS_API
  ecs_entity_t ecs_type_get_entity_for_xor(
      ecs_world_t *world,
      ecs_type_t type,
      ecs_entity_t xor_tag);
  
  FLECS_API
  int32_t ecs_type_index_of(
      ecs_type_t type,
      ecs_entity_t component);
  
  FLECS_API
  int32_t ecs_type_trait_index_of(
      ecs_type_t type, 
      int32_t start_index, 
      ecs_entity_t trait);
  
  #ifdef __cplusplus
  }
  #endif
  
  #endif
  
  /** @} */
  
  
  /**
   * @defgroup builtin_types Builtin Types
   * @{
   */
  
  /** Entity name. */
  typedef struct EcsName {
      const char *value;     /**< Entity name */
      char *symbol;          /**< Optional symbol name, if it differs from name */
      char *alloc_value;     /**< If set, value will be freed on destruction */
  } EcsName;
  
  /** Component information. */
  typedef struct EcsComponent {
      ecs_size_t size;           /**< Component size */
      ecs_size_t alignment;      /**< Component alignment */
  } EcsComponent;
  
  /** Component that stores an ecs_type_t. 
   * This component allows for the creation of entities that represent a type, and
   * therefore the creation of named types. This component is typically 
   * instantiated by ECS_TYPE. */
  typedef struct EcsType {
      ecs_type_t type;        /**< Preserved nested types */
      ecs_type_t normalized;  /**< Union of type and nested AND types */
  } EcsType;
  
  /** Component that contains lifecycle callbacks for a component. */
  typedef struct EcsComponentLifecycle {
      ecs_xtor_t ctor;        /**< Component constructor */
      ecs_xtor_t dtor;        /**< Component destructor */
      ecs_copy_t copy;        /**< Component copy */
      ecs_move_t move;        /**< Component move */
      void *ctx;              /**< User defined context */
  } EcsComponentLifecycle;
  
  /** Component used for registering component triggers */
  typedef struct EcsTrigger {
      ecs_entity_t kind;
      ecs_iter_action_t action;
      ecs_entity_t component;
      ecs_entity_t self;
      void *ctx;
  } EcsTrigger;
  
  /** @} */
  
  
  /**
   * @defgroup type_roles Type Roles
   * @{
   */
  
  /* Type roles are used to indicate the role of an entity in a type. If no flag
   * is specified, the entity is interpreted as a regular component or tag. Flags
   * are added to an entity by using a bitwise OR (|). An example:
   *
   * ecs_entity_t parent = ecs_new(world, 0);
   * ecs_entity_t child = ecs_add_entity(world, e, ECS_CHILDOF | parent);
   *
   * Type flags can also be used in type expressions, without the ECS prefix:
   *
   * ECS_ENTITY(world, Base, Position);
   * ECS_TYPE(world, InstanceOfBase, INSTANCEOF | Base);
   */
  
  /** Role bit added to roles to differentiate between roles and generations */
  #define ECS_ROLE ((uint64_t)1 << 63)
  
  /** The INSTANCEOF role indicates that the components from the entity should be
   * shared with the entity that instantiates the type. */
  #define ECS_INSTANCEOF (ECS_ROLE | ((ecs_entity_t)0x7E << 56))
  
  /** The CHILDOF role indicates that the entity should be treated as a parent of
   * the entity that instantiates the type. */
  #define ECS_CHILDOF (ECS_ROLE | ((ecs_entity_t)0x7D << 56))
  
  /** Cases are used to switch between mutually exclusive components */
  #define ECS_CASE (ECS_ROLE | ((ecs_entity_t)0x7C << 56))
  
  /** Switches allow for fast switching between mutually exclusive components */
  #define ECS_SWITCH (ECS_ROLE | ((ecs_entity_t)0x7B << 56))
  
  /** The TRAIT role indicates that the entity is a trait identifier. */
  #define ECS_TRAIT (ECS_ROLE | ((ecs_entity_t)0x7A << 56))
  
  /** Enforce that all entities of a type are present in the type.
   * This flag can only be used in combination with an entity that has EcsType. */
  #define ECS_AND (ECS_ROLE | ((ecs_entity_t)0x79 << 56))
  
  /** Enforce that at least one entity of a type must be present in the type.
   * This flag can only be used in combination with an entity that has EcsType. */
  #define ECS_OR (ECS_ROLE | ((ecs_entity_t)0x78 << 56))
  
  /** Enforce that exactly one entity of a type must be present in the type.
   * This flag can only be used in combination with an entity that has EcsType. 
   * When another entity of the XOR'd type is added to an entity of this type, the
   * previous entity is removed from the entity. This makes XOR useful for
   * implementing state machines, as it allows for traversing states while 
   * ensuring that only one state is ever active at the same time. */
  #define ECS_XOR (ECS_ROLE | ((ecs_entity_t)0x77 << 56))
  
  /** None of the entities in a type may be added to the type.
   * This flag can only be used in combination with an entity that has EcsType. */
  #define ECS_NOT (ECS_ROLE | ((ecs_entity_t)0x76 << 56))
  
  /** Enforce ownership of a component */
  #define ECS_OWNED (ECS_ROLE | ((ecs_entity_t)0x75 << 56))
  
  /** Track whether component is enabled or not */
  #define ECS_DISABLED (ECS_ROLE | ((ecs_entity_t)0x74 << 56))
  
  /** @} */
  
  /**
   * @defgroup builtin_tags Builtin Tags
   * @{
   */
  
  /* Builtin tag ids */
  #define EcsModule (ECS_HI_COMPONENT_ID + 0)
  #define EcsPrefab (ECS_HI_COMPONENT_ID + 1)
  #define EcsHidden (ECS_HI_COMPONENT_ID + 2)
  #define EcsDisabled (ECS_HI_COMPONENT_ID + 3)
  #define EcsDisabledIntern (ECS_HI_COMPONENT_ID + 4)
  #define EcsInactive (ECS_HI_COMPONENT_ID + 5)
  #define EcsOnDemand (ECS_HI_COMPONENT_ID + 6)
  #define EcsMonitor (ECS_HI_COMPONENT_ID + 7)
  #define EcsPipeline (ECS_HI_COMPONENT_ID + 8)
  
  /* Trigger tags */
  #define EcsOnAdd (ECS_HI_COMPONENT_ID + 9)
  #define EcsOnRemove (ECS_HI_COMPONENT_ID + 10)
  
  /* Set system tags */
  #define EcsOnSet (ECS_HI_COMPONENT_ID + 11)
  #define EcsUnSet (ECS_HI_COMPONENT_ID + 12)
  
  /* Builtin pipeline tags */
  #define EcsPreFrame (ECS_HI_COMPONENT_ID + 13)
  #define EcsOnLoad (ECS_HI_COMPONENT_ID + 14)
  #define EcsPostLoad (ECS_HI_COMPONENT_ID + 15)
  #define EcsPreUpdate (ECS_HI_COMPONENT_ID + 16)
  #define EcsOnUpdate (ECS_HI_COMPONENT_ID + 17)
  #define EcsOnValidate (ECS_HI_COMPONENT_ID + 18)
  #define EcsPostUpdate (ECS_HI_COMPONENT_ID + 19)
  #define EcsPreStore (ECS_HI_COMPONENT_ID + 20)
  #define EcsOnStore (ECS_HI_COMPONENT_ID + 21)
  #define EcsPostFrame (ECS_HI_COMPONENT_ID + 22)
  
  /** Builtin entity ids */
  #define EcsFlecs (ECS_HI_COMPONENT_ID + 23)
  #define EcsFlecsCore (ECS_HI_COMPONENT_ID + 24)
  #define EcsWorld (ECS_HI_COMPONENT_ID + 25)
  #define EcsSingleton (ECS_HI_COMPONENT_ID + 26)
  #define EcsWildcard (ECS_HI_COMPONENT_ID + 27)
  
  /* Value used to quickly check if component is builtin. This is used to quickly
   * filter out tables with builtin components (for example for ecs_delete) */
  #define EcsLastInternalComponentId (ecs_typeid(EcsSystem))
  
  /* The first user-defined component starts from this id. Ids up to this number
   * are reserved for builtin components */
  #define EcsFirstUserComponentId (32)
  
  /* The first user-defined entity starts from this id. Ids up to this number
   * are reserved for builtin components */
  #define EcsFirstUserEntityId (ECS_HI_COMPONENT_ID + 32)
  
  /** @} */
  
  /**
   * @defgroup convenience_macros Convenience Macro's
   * @{
   */
  
  /* Macro's rely on variadic arguments which are C99 and above */
  #ifndef FLECS_LEGACY
  
  /** Declare an extern component variable.
   * Use this macro in a header when defining a component identifier globally.
   * Must be used together with ECS_ENTITY_DECLARE.
   *
   * Example:
   *   ECS_COMPONENT_EXTERN(Position);
   */
  #define ECS_ENTITY_EXTERN(id)\
      extern ecs_entity_t id
  
  /** Declare an entity variable outside the scope of a function.
   * Use this macro in a header when defining a tag identifier globally.
   * Must be used together with ECS_ENTITY_DEFINE.
   *
   * Example:
   *   ECS_ENTITY_DECLARE(Position);
   */
  #define ECS_ENTITY_DECLARE(id)\
      ecs_entity_t id
  
  /** Define a component, store in variable outside of the current scope.
   * Use this macro in a header when defining a component identifier globally.
   * Must be used together with ECS_ENTITY_DECLARE.
   *
   * Example:
   *   ECS_ENTITY_DEFINE(world, Position);
   */
  #define ECS_ENTITY_DEFINE(world, id, ...)\
      id = ecs_new_entity(world, id, #id, #__VA_ARGS__)
  
  /** Declare a named entity with a type expression. 
   * Example:
   *   ECS_ENTITY(world, MyEntity, Position, Velocity);
   */ 
  #define ECS_ENTITY(world, id, ...)\
      ecs_entity_t id = ecs_new_entity(world, 0, #id, #__VA_ARGS__);\
      (void)id
  
  /** Declare a prefab with a type expression. 
   * Example:
   *   ECS_PREFAB(world, MyEntity, Position, Velocity);
   */
  #define ECS_PREFAB(world, id, ...) \
      ecs_entity_t id = ecs_new_prefab(world, 0, #id, #__VA_ARGS__);\
      (void)id
  
  /** Declare a component.
   * Example:
   *   ECS_COMPONENT(world, Position);
   */
  #define ECS_COMPONENT(world, id) \
      ECS_ENTITY_VAR(id) = ecs_new_component(world, 0, #id, sizeof(id), ECS_ALIGNOF(id));\
      ECS_VECTOR_STACK(FLECS__T##id, ecs_entity_t, &FLECS__E##id, 1);\
      (void)ecs_typeid(id);\
      (void)ecs_type(id)
  
  /** Declare an extern component variable.
   * Use this macro in a header when defining a component identifier globally.
   * Must be used together with ECS_COMPONENT_DECLARE.
   *
   * Example:
   *   ECS_COMPONENT_EXTERN(Position);
   */
  #define ECS_COMPONENT_EXTERN(id)\
      extern ECS_ENTITY_VAR(id);\
      extern ecs_type_t ecs_type(id)
  
  /** Declare a component variable outside the scope of a function.
   * Use this macro in a header when defining a component identifier globally.
   * Must be used together with ECS_COMPONENT_DEFINE.
   *
   * Example:
   *   ECS_COMPONENT_IMPL(Position);
   */
  #define ECS_COMPONENT_DECLARE(id)\
      ECS_ENTITY_VAR(id);\
      ecs_type_t ecs_type(id)
  
  /** Define a component, store in variable outside of the current scope.
   * Use this macro in a header when defining a component identifier globally.
   * Must be used together with ECS_COMPONENT_DECLARE.
   *
   * Example:
   *   ECS_COMPONENT_DEFINE(world, Position);
   */
  #define ECS_COMPONENT_DEFINE(world, id)\
      ecs_typeid(id) = ecs_new_component(world, ecs_typeid(id), #id, sizeof(id), ECS_ALIGNOF(id));\
      ecs_type(id) = ecs_type_from_entity(world, ecs_typeid(id))
  
  /** Declare a tag.
   * Example:
   *   ECS_TAG(world, MyTag);
   */
  #define ECS_TAG(world, id)\
      ECS_ENTITY(world, id, 0);\
      ECS_VECTOR_STACK(FLECS__T##id, ecs_entity_t, &id, 1);\
      (void)ecs_type(id)
  
  /** Declare an extern tag variable.
   * Use this macro in a header when defining a tag identifier globally.
   * Must be used together with ECS_TAG_DECLARE.
   *
   * Example:
   *   ECS_TAG_EXTERN(Enemy);
   */
  #define ECS_TAG_EXTERN(id)\
      extern ecs_entity_t id;\
      extern ecs_type_t ecs_type(id)
  
  /** Declare a tag variable outside the scope of a function.
   * Use this macro in a header when defining a tag identifier globally.
   * Must be used together with ECS_TAG_DEFINE.
   *
   * Example:
   *   ECS_TAG_DECLARE(Enemy);
   */
  #define ECS_TAG_DECLARE(id)\
      ecs_entity_t id;\
      ecs_type_t ecs_type(id)
  
  /** Define a tag, store in variable outside of the current scope.
   * Use this macro in a header when defining a tag identifier globally.
   * Must be used together with ECS_TAG_DECLARE.
   *
   * Example:
   *   ECS_TAG_DEFINE(world, Enemy);
   */
  #define ECS_TAG_DEFINE(world, id)\
      id = ecs_new_entity(world, id, #id, 0);\
      ecs_type(id) = ecs_type_from_entity(world, id)
  
  /** Declare a type.
   * Example:
   *   ECS_TYPE(world, MyType, Position, Velocity);
   */
  #define ECS_TYPE(world, id, ...) \
      ecs_entity_t id = ecs_new_type(world, 0, #id, #__VA_ARGS__);\
      ECS_TYPE_VAR(id) = ecs_type_from_entity(world, id);\
      (void)id;\
      (void)ecs_type(id)
  
  /** Declare an extern type variable.
   * Use this macro in a header when defining a type globally.
   * Must be used together with ECS_TYPE_DECLARE.
   *
   * Example:
   *   ECS_TYPE_EXTERN(Movable);
   */
  #define ECS_TYPE_EXTERN(id)\
      extern ecs_entity_t id;\
      extern ecs_type_t ecs_type(id)
  
  /** Declare a type variable outside the scope of a function.
   * Use this macro in a header when defining a type globally.
   * Must be used together with ECS_TYPE_DEFINE.
   *
   * Example:
   *   ECS_TYPE_DECLARE(Movable);
   */
  #define ECS_TYPE_DECLARE(id)\
      ecs_entity_t id;\
      ecs_type_t ecs_type(id)
  
  /** Define a type, store in variable outside of the current scope.
   * Use this macro in a header when defining a type globally.
   * Must be used together with ECS_TYPE_DECLARE.
   *
   * Example:
   *   ECS_TYPE_DEFINE(world, Movable, Position, Velocity);
   */
  #define ECS_TYPE_DEFINE(world, id, ...)\
      id = ecs_new_type(world, 0, #id, #__VA_ARGS__);\
      ecs_type(id) = ecs_type_from_entity(world, id);\
  
  /** Declare a constructor.
   * Example:
   *   ECS_CTOR(MyType, ptr, { ptr->value = NULL; });
   */
  #define ECS_CTOR(type, var, ...)\
      ECS_XTOR_IMPL(type, ctor, var, __VA_ARGS__)
  
  /** Declare a destructor.
   * Example:
   *   ECS_DTOR(MyType, ptr, { free(ptr->value); });
   */
  #define ECS_DTOR(type, var, ...)\
      ECS_XTOR_IMPL(type, dtor, var, __VA_ARGS__)
  
  /** Declare a copy action.
   * Example:
   *   ECS_COPY(MyType, dst, src, { dst->value = strdup(src->value); });
   */
  #define ECS_COPY(type, dst_var, src_var, ...)\
      ECS_COPY_IMPL(type, dst_var, src_var, __VA_ARGS__)
  
  /** Declare a move action.
   * Example:
   *   ECS_MOVE(MyType, dst, src, { dst->value = src->value; src->value = 0; });
   */
  #define ECS_MOVE(type, dst_var, src_var, ...)\
      ECS_MOVE_IMPL(type, dst_var, src_var, __VA_ARGS__)
  
  /* Map from typename to function name of component lifecycle action */
  #define ecs_ctor(type) type##_ctor
  #define ecs_dtor(type) type##_dtor
  #define ecs_copy(type) type##_copy
  #define ecs_move(type) type##_move
  
  #endif /* FLECS_LEGACY */
  
  /** @} */
  
  /**
   * @defgroup world_api World API
   * @{
   */
  
  /** Create a new world.
   * A world manages all the ECS data and supporting infrastructure. Applications 
   * must have at least one world. Entities, component and system handles are 
   * local to a world and should not be shared between worlds.
   * 
   * This operation creates a world with all builtin modules loaded. 
   *
   * @return A new world object
   */
  FLECS_API
  ecs_world_t* ecs_init(void);
  
  /** Same as ecs_init, but with minimal set of modules loaded.
   *
   * @return A new world object
   */
  FLECS_API
  ecs_world_t* ecs_mini(void);
  
  /** Create a new world with arguments.
   * Same as ecs_init, but allows passing in command line arguments. These can be
   * used to dynamically enable flecs features to an application. Currently these
   * arguments are not used.
   *
   * @return A new world object
   */
  FLECS_API
  ecs_world_t* ecs_init_w_args(
      int argc,
      char *argv[]);
  
  /** Delete a world.
   * This operation deletes the world, and everything it contains.
   *
   * @param world The world to delete.
   * @return Zero if successful, non-zero if failed.
   */
  FLECS_API
  int ecs_fini(
      ecs_world_t *world);
  
  /** Register action to be executed when world is destroyed.
   * Fini actions are typically used when a module needs to clean up before a
   * world shuts down.
   * 
   * @param world The world.
   * @param action The function to execute.
   * @param ctx Userdata to pass to the function */
  FLECS_API
  void ecs_atfini(
      ecs_world_t *world,
      ecs_fini_action_t action,
      void *ctx);
  
  /** Register action to be executed once after frame.
   * Post frame actions are typically used for calling operations that cannot be
   * invoked during iteration, such as changing the number of threads.
   * 
   * @param world The world.
   * @param action The function to execute.
   * @param ctx Userdata to pass to the function */
  FLECS_API
  void ecs_run_post_frame(
      ecs_world_t *world,
      ecs_fini_action_t action,
      void *ctx);    
  
  /** Register ctor, dtor, copy & move actions for component.
   *
   * @param world The world.
   * @param component The component id for which to register the actions
   * @param actions Type that contains the component actions.
   */
  FLECS_API
  void ecs_set_component_actions_w_entity(
      ecs_world_t *world,
      ecs_entity_t component,
      EcsComponentLifecycle *actions);
  
  #ifndef FLECS_LEGACY
  #define ecs_set_component_actions(world, component, ...)\
      ecs_set_component_actions_w_entity(world, ecs_typeid(component), &(EcsComponentLifecycle)__VA_ARGS__)
  
  #endif
  /** Set a world context.
   * This operation allows an application to register custom data with a world
   * that can be accessed anywhere where the application has the world object.
   *
   * @param world The world.
   * @param ctx A pointer to a user defined structure.
   */
  FLECS_API
  void ecs_set_context(
      ecs_world_t *world,
      void *ctx);
  
  /** Get the world context.
   * This operation retrieves a previously set world context.
   *
   * @param world The world.
   * @return The context set with ecs_set_context. If no context was set, the
   *         function returns NULL.
   */
  FLECS_API
  void* ecs_get_context(
      ecs_world_t *world);
  
  /** Get world info.
   *
   * @param world The world.
   * @return Pointer to the world info. This pointer will remain valid for as long
   *         as the world is valid.
   */
  FLECS_API
  const ecs_world_info_t* ecs_get_world_info(
      ecs_world_t *world);
  
  /** Dimension the world for a specified number of entities.
   * This operation will preallocate memory in the world for the specified number
   * of entities. Specifying a number lower than the current number of entities in
   * the world will have no effect. Note that this function does not allocate
   * memory for components (use ecs_dim_type for that).
   *
   * @param world The world.
   * @param entity_count The number of entities to preallocate.
   */
  FLECS_API
  void ecs_dim(
      ecs_world_t *world,
      int32_t entity_count);
  
  /** Dimension a type for a specified number of entities.
   * This operation will preallocate memory for a type (table) for the
   * specified number of entities. Specifying a number lower than the current
   * number of entities in the table will have no effect.
   *
   * @param world The world.
   * @param type Handle to the type, as obtained by ecs_type_get.
   * @param entity_count The number of entities to preallocate.
   */
  FLECS_API
  void ecs_dim_type(
      ecs_world_t *world,
      ecs_type_t type,
      int32_t entity_count);
  
  /** Set a range for issueing new entity ids.
   * This function constrains the entity identifiers returned by ecs_new to the 
   * specified range. This operation can be used to ensure that multiple processes
   * can run in the same simulation without requiring a central service that
   * coordinates issueing identifiers.
   * 
   * If id_end is set to 0, the range is infinite. If id_end is set to a non-zero
   * value, it has to be larger than id_start. If id_end is set and ecs_new is
   * invoked after an id is issued that is equal to id_end, the application will
   * abort.
   * 
   * @param world The world.
   * @param id_start The start of the range.
   * @param id_end The end of the range.
   */
  FLECS_API
  void ecs_set_entity_range(
      ecs_world_t *world,
      ecs_entity_t id_start,
      ecs_entity_t id_end);
  
  /** Enable/disable range limits.
   * When an application is both a receiver of range-limited entities and a
   * producer of range-limited entities, range checking needs to be temporarily
   * disabled when inserting received entities. Range checking is disabled on a 
   * stage, so setting this value is thread safe.
   *
   * @param world The world.
   * @param enable True if range checking should be enabled, false to disable.
   * @return The previous value.
   */
  FLECS_API
  bool ecs_enable_range_check(
      ecs_world_t *world,
      bool enable);
  
  /** Enable world locking while in progress.
   * When locking is enabled, Flecs will lock the world while in progress. This
   * allows applications to interact with the world from other threads without
   * running into race conditions.
   *
   * This is a better alternative to applications putting a lock around calls to
   * ecs_progress, since ecs_progress can sleep when FPS control is enabled,
   * which is time during which other threads could perform work.
   *
   * Locking must be enabled before applications can use the ecs_lock and
   * ecs_unlock functions. Locking is turned off by default.
   *
   * @param world The world.
   * @param enable True if locking is to be enabled.
   * @result The previous value of the setting.
   */
  FLECS_API
  bool ecs_enable_locking(
      ecs_world_t *world,
      bool enable);
  
  /** Locks the world.
   * See ecs_enable_locking for details.
   *
   * @param world The world.
   */
  FLECS_API
  void ecs_lock(
      ecs_world_t *world);
  
  /** Unlocks the world.
   * See ecs_enable_locking for details.
   * 
   * @param world The world.
   */
  FLECS_API
  void ecs_unlock(
      ecs_world_t *world);
  
  /** Wait until world becomes available.
   * When a non-flecs thread needs to interact with the world, it should invoke
   * this function to wait until the world becomes available (as in, it is not
   * progressing the frame). Invoking this function guarantees that the thread
   * will not starve. (as opposed to simply taking the world lock).
   *
   * An application will have to invoke ecs_end_wait after this function returns.
   * 
   * @param world The world.
   */
  FLECS_API 
  void ecs_begin_wait(
      ecs_world_t *world);
  
  /** Release world after calling ecs_begin_wait.
   * This operation should be invoked after invoking ecs_begin_wait, and will
   * release the world back to the thread running the main loop.
   *
   * @param world The world.
   */
  FLECS_API 
  void ecs_end_wait(
      ecs_world_t *world);
  
  /** Enable or disable tracing.
   * This will enable builtin tracing. For tracing to work, it will have to be
   * compiled in which requires defining one of the following macro's:
   *
   * ECS_TRACE_0 - All tracing is disabled
   * ECS_TRACE_1 - Enable tracing level 1
   * ECS_TRACE_2 - Enable tracing level 2 and below
   * ECS_TRACE_3 - Enable tracing level 3 and below
   *
   * If no tracing level is defined and this is a debug build, ECS_TRACE_3 will
   * have been automatically defined.
   *
   * The provided level corresponds with the tracing level. If -1 is provided as
   * value, warnings are disabled. If -2 is provided, errors are disabled as well.
   *
   * @param level Desired tracing level.
   */
  FLECS_API
  void ecs_tracing_enable(
      int level);
  
  /** Measure frame time. 
   * Frame time measurements measure the total time passed in a single frame, and 
   * how much of that time was spent on systems and on merging.
   *
   * Frame time measurements add a small constant-time overhead to an application.
   * When an application sets a target FPS, frame time measurements are enabled by
   * default.
   *
   * @param world The world.
   * @param enable Whether to enable or disable frame time measuring.
   */
  FLECS_API void ecs_measure_frame_time(
      ecs_world_t *world,
      bool enable);
  
  /** Measure system time. 
   * System time measurements measure the time spent in each system.
   *
   * System time measurements add overhead to every system invocation and 
   * therefore have a small but measurable impact on application performance.
   * System time measurements must be enabled before obtaining system statistics.
   *
   * @param world The world.
   * @param enable Whether to enable or disable system time measuring.
   */
  FLECS_API void ecs_measure_system_time(
      ecs_world_t *world,
      bool enable);   
  
  /** Set target frames per second (FPS) for application.
   * Setting the target FPS ensures that ecs_progress is not invoked faster than
   * the specified FPS. When enabled, ecs_progress tracks the time passed since
   * the last invocation, and sleeps the remaining time of the frame (if any).
   *
   * This feature ensures systems are ran at a consistent interval, as well as
   * conserving CPU time by not running systems more often than required.
   *
   * Note that ecs_progress only sleeps if there is time left in the frame. Both
   * time spent in flecs as time spent outside of flecs are taken into
   * account.
   *
   * @param world The world.
   * @param fps The target FPS.
   */
  FLECS_API
  void ecs_set_target_fps(
      ecs_world_t *world,
      FLECS_FLOAT fps);     
  
  /** Get current number of threads. */
  FLECS_API
  int32_t ecs_get_threads(
      ecs_world_t *world);
  
  /** Get current thread index */
  FLECS_API
  int32_t ecs_get_thread_index(
      ecs_world_t *world);
  
  
  /** @} */
  
  /**
   * @defgroup creating_entities Creating Entities
   * @{
   */
  
  /** Create new entity id.
   * This operation returns an unused entity id.
   *
   * @param world The world.
   * @return The new entity id.
   */
  FLECS_API
  ecs_entity_t ecs_new_id(
      ecs_world_t *world);
  
  /** Create new component id.
   * This operation returns a new component id. Component ids are the same as
   * entity ids, but can make use of the [1 .. ECS_HI_COMPONENT_ID] range.
   * 
   * This operation does not recycle ids.
   *
   * @param world The world.
   * @return The new component id.
   */
  FLECS_API
  ecs_entity_t ecs_new_component_id(
      ecs_world_t *world);
  
  /** Create new entity.
   * This operation creates a new entity with a single entity in its type. The
   * entity may contain type roles. This operation recycles ids.
   *
   * @param world The world.
   * @param entity The entity to initialize the new entity with.
   * @return The new entity.
   */
  FLECS_API
  ecs_entity_t ecs_new_w_entity(
      ecs_world_t *world,
      ecs_entity_t entity);
  
  /** Create new entity.
   * This operation creates a new entity initialized with a type. This operation 
   * recycles ids.
   *
   * @param world The world.
   * @param type The type to initialize the new entity with.
   * @return The new entity.
   */
  FLECS_API
  ecs_entity_t ecs_new_w_type(
      ecs_world_t *world,
      ecs_type_t type);
  
  /** Create a new entity.
   * This operation creates a new entity with a single component in its type. This
   * operation accepts variables created with ECS_COMPONENT, ECS_TYPE and ECS_TAG.
   * This operation recycles ids.
   * 
   * @param world The world.
   * @param type The component type.
   * @return The new entity.
   */
  #define ecs_new(world, type)\
      ecs_new_w_type(world, ecs_type(type))
  
  /** Create N new entities.
   * This operation is the same as ecs_new_w_entity, but creates N entities
   * instead of one and does not recycle ids.
   * 
   * @param world The world.
   * @param entity The entity.
   * @param count The number of entities to create.
   * @return The first entity id of the newly created entities.
   */
  FLECS_API
  const ecs_entity_t* ecs_bulk_new_w_entity(
      ecs_world_t *world,
      ecs_entity_t entity,
      int32_t count);
  
  /** Create N new entities.
   * This operation is the same as ecs_new_w_type, but creates N entities
   * instead of one and does not recycle ids.
   * 
   * @param world The world.
   * @param type The type.
   * @param count The number of entities to create.
   * @return The first entity id of the newly created entities.
   */
  FLECS_API
  const ecs_entity_t* ecs_bulk_new_w_type(
      ecs_world_t *world,
      ecs_type_t type,
      int32_t count);
  
  /** Create N new entities and initialize components.
   * This operation is the same as ecs_bulk_new_w_type, but initializes components
   * with the provided component array. Instead of a type the operation accepts an
   * array of component identifiers (entities). The component arrays need to be
   * provided in the same order as the component identifiers.
   * 
   * @param world The world.
   * @param components Array with component identifiers.
   * @param count The number of entities to create.
   * @param data The data arrays to initialize the components with.
   * @return The first entity id of the newly created entities.
   */
  FLECS_API
  const ecs_entity_t* ecs_bulk_new_w_data(
      ecs_world_t *world,
      int32_t count,
      ecs_entities_t *component_ids,
      void *data);
  
  /** Create N new entities.
   * This operation is the same as ecs_new, but creates N entities
   * instead of one and does not recycle ids.
   * 
   * @param world The world.
   * @param component The component type.
   * @param count The number of entities to create.
   * @return The first entity id of the newly created entities.
   */
  #define ecs_bulk_new(world, component, count)\
      ecs_bulk_new_w_type(world, ecs_type(component), count)
  
  /** Clone an entity
   * This operation clones the components of one entity into another entity. If
   * no destination entity is provided, a new entity will be created. Component
   * values are not copied unless copy_value is true.
   *
   * @param world The world.
   * @param dst The entity to copy the components to.
   * @param src The entity to copy the components from.
   * @param copy_value If true, the value of components will be copied to dst.
   * @return The destination entity.
   */
  FLECS_API
  ecs_entity_t ecs_clone(
      ecs_world_t *world,
      ecs_entity_t dst,
      ecs_entity_t src,
      bool copy_value);
  
  /** @} */
  
  /**
   * @defgroup adding_removing Adding & Removing
   * @{
   */
  
  /** Add an entity to an entity.
   * This operation adds a single entity to the type of an entity. Type roles may
   * be used in combination with the added entity. If the entity already has the
   * entity, this operation will have no side effects.
   *
   * @param world The world.
   * @param entity The entity.
   * @param entity_add The entity to add.
   */
  FLECS_API
  void ecs_add_entity(
      ecs_world_t *world,
      ecs_entity_t entity,
      ecs_entity_t entity_add);
  
  /** Add a type to an entity.
   * This operation adds a type to an entity. The resulting type of the entity
   * will be the union of the previous type and the provided type. If the added
   * type did not have new components, this operation will have no side effects.
   *
   * @param world The world.
   * @param entity The entity.
   * @param type The type to add.
   */
  FLECS_API
  void ecs_add_type(
      ecs_world_t *world,
      ecs_entity_t entity,
      ecs_type_t type);
  
  /** Add a component, type or tag to an entity.
   * This operation adds a type to an entity. The resulting type of the entity
   * will be the union of the previous type and the provided type. If the added
   * type did not have new components, this operation will have no side effects.
   *
   * This operation accepts variables declared by ECS_COMPONENT, ECS_TYPE and
   * ECS_TAG.
   *
   * @param world The world.
   * @param entity The entity.
   * @param component The component, type or tag to add.
   */
  #define ecs_add(world, entity, component)\
      ecs_add_type(world, entity, ecs_type(component))
  
  
  /** Remove an entity from an entity.
   * This operation removes a single entity from the type of an entity. Type roles
   * may be used in combination with the added entity. If the entity does not have
   * the entity, this operation will have no side effects.
   *
   * @param world The world.
   * @param entity The entity.
   * @param entity_remove The entity to remove.
   */
  FLECS_API
  void ecs_remove_entity(
      ecs_world_t *world,
      ecs_entity_t entity,
      ecs_entity_t entity_remove);
  
  /** Remove a type from an entity.
   * This operation removes a type to an entity. The resulting type of the entity
   * will be the difference of the previous type and the provided type. If the 
   * type did not overlap with the entity type, this operation has no side effects.
   *
   * @param world The world.
   * @param entity The entity.
   * @param type The type to remove.
   */
  FLECS_API
  void ecs_remove_type(
      ecs_world_t *world,
      ecs_entity_t entity,
      ecs_type_t type);
  
  /** Remove a component, type or tag from an entity.
   * This operation removes a type to an entity. The resulting type of the entity
   * will be the difference of the previous type and the provided type. If the 
   * type did not overlap with the entity type, this operation has no side effects.
   *
   * This operation accepts variables declared by ECS_COMPONENT, ECS_TYPE and
   * ECS_TAG.
   *
   * @param world The world.
   * @param entity The entity.
   * @param component The component, type or tag to remove.
   */
  #define ecs_remove(world, entity, type)\
      ecs_remove_type(world, entity, ecs_type(type))
  
  
  /** Add / remove entity from entities matching a filter.
   * Combination of ecs_add_entity and ecs_remove_entity.
   *
   * @param world The world.
   * @param entity The entity.
   * @param to_add The entity to add.
   * @param to_remove The entity to remove.
   */
  FLECS_API
  void ecs_add_remove_entity(
      ecs_world_t *world,
      ecs_entity_t entity,
      ecs_entity_t to_add,
      ecs_entity_t to_remove);
  
  /** Add / remove type from entities matching a filter.
   * Combination of ecs_add_type and ecs_remove_type.
   *
   * @param world The world.
   * @param entity The entity.
   * @param to_add The type to add.
   * @param to_remove The type to remove.
   */
  FLECS_API
  void ecs_add_remove_type(
      ecs_world_t *world,
      ecs_entity_t entity,
      ecs_type_t to_add,
      ecs_type_t to_remove);
  
  /** Add / remove component, type or tag from entity.
   * Combination of ecs_add and ecs_remove.
   *
   * @param world The world.
   * @param entity The entity.
   * @param to_add The component, type or tag to add.
   * @param to_remove The component, type or tag to remove.
   */
  #define ecs_add_remove(world, entity, to_add, to_remove)\
      ecs_add_remove_type(world, entity, ecs_type(to_add), ecs_type(to_remove))
  
  /** @} */
  
  
  /**
   * @defgroup enabling_disabling Enabling & Disabling components.
   * @{
   */
  
  /** Enable or disable component.
   * Enabling or disabling a component does not add or remove a component from an
   * entity, but prevents it from being matched with queries. This operation can
   * be useful when a component must be temporarily disabled without destroying
   * its value. It is also a more performant operation for when an application
   * needs to add/remove components at high frequency, as enabling/disabling is
   * cheaper than a regular add or remove.
   *
   * @param world The world.
   * @param entity The entity.
   * @param component The component.
   * @param enable True to enable the component, false to disable.
   */
  FLECS_API void ecs_enable_component_w_entity(
      ecs_world_t *world,
      ecs_entity_t entity,
      ecs_entity_t component,
      bool enable);
  
  #define ecs_enable_component(world, entity, T, enable)\
      ecs_enable_component_w_entity(world, entity, ecs_typeid(T), enable)
  
  /** Test if component is enabled.
   * Test whether a component is currently enabled or disabled. This operation
   * will return true when the entity has the component and if it has not been
   * disabled by ecs_enable_component.
   *
   * @param world The world.
   * @param entity The entity.
   * @param component The component.
   * @return True if the component is enabled, otherwise false.
   */
  FLECS_API bool ecs_is_component_enabled_w_entity(
      ecs_world_t *world,
      ecs_entity_t entity,
      ecs_entity_t component);
  
  #define ecs_is_component_enabled(world, entity, T)\
      ecs_is_component_enabled_w_entity(world, entity, ecs_typeid(T))
  
  /** @} */
  
  
  /**
   * @defgroup traits Traits
   * @{
   */
  
  /** Add a trait
   * This operation adds a trait from an entity.
   *
   * @param world The world.
   * @param entity The entity.
   * @param component The entity for which to remove the trait.
   * @param trait The trait to remove.
   */
  #define ecs_add_trait(world, entity, component, trait)\
      ecs_add_entity(world, entity, ecs_trait(component, trait))
  
  /** Remove a trait
   * This operation removes a trait from an entity.
   *
   * @param world The world.
   * @param entity The entity.
   * @param component The entity for which to remove the trait.
   * @param trait The trait to remove.
   */
  #define ecs_remove_trait(world, entity, component, trait)\
      ecs_remove_entity(world, entity, ecs_trait(component, trait))
  
  /** Test if an entity has a trait.
   * This operation returns true if the entity has the provided trait for the
   * specified component in its type.
   *
   * @param world The world.
   * @param entity The entity.
   * @param component The entity.
   * @param trait The entity.
   * @return True if the entity has the trait, false if not.
   */
  #define ecs_has_trait(world, entity, component, trait)\
      ecs_has_entity(world, entity, ecs_trait(component, trait))
  
  
  #ifndef FLECS_LEGACY
  /** Set trait for component. 
   * This operation adds a trait for an entity and component. Traits can be added
   * multiple times to the same entity, as long as it is for different components.
   *
   * Traits can be matched with systems by providing the TRAIT role to the 
   * trait component in the system signature. A system will match multiple times
   * with the same entity if the trait is added for multiple components.
   *
   * * This operation can only be used with traits that are components.
   *
   * @param world The world.
   * @param e The entity.
   * @param component The component for which to add the trait.
   * @param trait The trait to add.
   */
  #define ecs_set_trait(world, entity, component, trait, ...)\
      ecs_set_ptr_w_entity(world, entity, ecs_trait(ecs_typeid(component), ecs_typeid(trait)), sizeof(trait), &(trait)__VA_ARGS__)
  
  
  /** Set tag trait for component. 
   * This operation is similar to ecs_set_trait, but is used for trait tags. When
   * a trait tag is set on an entity, the trait type is not used (tags have no
   * type) and instead the component type is used.
   *
   * This operation can only be used with traits that are not components.
   *
   * @param world The world.
   * @param e The entity.
   * @param component The component for which to add the trait.
   * @param trait The trait to add.
   */
  #define ecs_set_trait_tag(world, entity, trait, component, ...)\
      ecs_set_ptr_w_entity(world, entity, ecs_trait(ecs_typeid(component), trait), sizeof(component), &(component)__VA_ARGS__)
  
  #endif
  
  /** Get trait for component. 
   * This operation obtains the value of a trait for a componetn that has been 
   * added by ecs_set_trait.
   *
   * @param world The world.
   * @param e The entity.
   * @param component The component to which the trait was added.
   * @param trait The trait that was added.
   */
  #define ecs_get_trait(world, entity, component, trait)\
      ((trait*)ecs_get_w_entity(world, entity, ecs_trait(ecs_typeid(component), ecs_typeid(trait))))
  
  /** Get trait tag for component. 
   * This operation obtains the value of a trait for a componetn that has been 
   * added by ecs_set_trait.
   *
   * @param world The world.
   * @param e The entity.
   * @param trait The trait that was added.
   * @param component The component to which the trait was added.
   */
  #define ecs_get_trait_tag(world, entity, trait, component)\
      ((component*)ecs_get_w_entity(world, entity, ecs_trait(ecs_typeid(component), trait)))
  
  /** Get case for switch.
   * This operation gets the current case for the specified switch. If the current
   * switch is not set for the entity, the operation will return 0.
   *
   * @param world The world.
   * @param e The entity.
   * @param sw The switch for which to obtain the case.
   * @return The current case for the specified switch. 
   */
  FLECS_API
  ecs_entity_t ecs_get_case(
      ecs_world_t *world,
      ecs_entity_t e,
      ecs_entity_t sw);
  
  /** @} */
  
  /**
   * @defgroup deleting Deleting Entities and components
   * @{
   */
  
  /** Clear all components.
   * This operation will clear all components from an entity but will not delete
   * the entity itself. This effectively prevents the entity id from being 
   * recycled.
   *
   * @param world The world.
   * @param entity The entity.
   */
  FLECS_API
  void ecs_clear(
      ecs_world_t *world,
      ecs_entity_t entity);
  
  /** Delete an entity.
   * This operation will delete an entity and all of its components. The entity id
   * will be recycled. Repeatedly calling ecs_delete without ecs_new, 
   * ecs_new_w_entity or ecs_new_w_type will cause a memory leak as it will cause
   * the list with ids that can be recycled to grow unbounded.
   *
   * @param world The world.
   * @param entity The entity.
   */
  FLECS_API
  void ecs_delete(
      ecs_world_t *world,
      ecs_entity_t entity);
  
  
  /** Delete children of an entity.
   * This operation deletes all children of a parent entity. If a parent has no
   * children this operation has no effect.
   *
   * @param world The world.
   * @param parent The parent entity.
   */
  FLECS_API
  void ecs_delete_children(
      ecs_world_t *world,
      ecs_entity_t parent);
  
  /** @} */
  
  /**
   * @defgroup getting Getting Components
   * @{
   */
  
  /** Get an immutable pointer to a component.
   * This operation obtains a const pointer to the requested component. The
   * operation accepts the component entity id.
   *
   * @param world The world.
   * @param entity The entity.
   * @param component The entity id of the component to obtain.
   * @return The component pointer, NULL if the entity does not have the component.
   */
  FLECS_API
  const void* ecs_get_w_entity(
      ecs_world_t *world,
      ecs_entity_t entity,
      ecs_entity_t component);
  
  /** Get an immutable pointer to a component.
   * Same as ecs_get_w_entity, but accepts the typename of a component.
   *
   * @param world The world.
   * @param entity The entity.
   * @param component The component to obtain.
   * @return The component pointer, NULL if the entity does not have the component.
   */
  #define ecs_get(world, entity, component)\
      ((const component*)ecs_get_w_entity(world, entity, ecs_typeid(component)))
  
  /* -- Get cached pointer -- */
  
  /** Get an immutable reference to a component.
   * This operation is similar to ecs_get_w_entity but it stores temporary
   * information in a `ecs_ref_t` value which allows subsequent lookups to be
   * faster.
   *
   * @param world The world.
   * @param ref Pointer to a ecs_ref_t value. Must be initialized.
   * @param entity The entity.
   * @param component The entity id of the component to obtain.
   * @return The component pointer, NULL if the entity does not have the component.
   */
  FLECS_API
  const void* ecs_get_ref_w_entity(
      ecs_world_t *world,
      ecs_ref_t *ref,
      ecs_entity_t entity,
      ecs_entity_t component);
  
  /** Get an immutable reference to a component.
   * Same as ecs_get_ref_w_entity, but accepts the typename of a component.
   *
   * @param world The world.
   * @param ref Pointer to a ecs_ref_t value. Must be initialized.
   * @param entity The entity.
   * @param component The component to obtain.
   * @return The component pointer, NULL if the entity does not have the component.
   */
  #define ecs_get_ref(world, ref, entity, component)\
      ((const component*)ecs_get_ref_w_entity(world, ref, entity, ecs_typeid(component)))
  
  /** Get a mutable pointer to a component.
   * This operation is similar to ecs_get_w_entity but it returns a mutable 
   * pointer. If this operation is invoked from inside a system, the entity will
   * be staged and a pointer to the staged component will be returned.
   *
   * If the entity did not yet have the component, the component will be added by
   * this operation. In this case the is_added out parameter will be set to true.
   *
   * @param world The world.
   * @param entity The entity.
   * @param component The entity id of the component to obtain.
   * @param is_added Out parameter that returns true if the component was added.
   * @return The component pointer.
   */
  FLECS_API
  void* ecs_get_mut_w_entity(
      ecs_world_t *world,
      ecs_entity_t entity,
      ecs_entity_t component,
      bool *is_added);
  
  /** Get a mutable pointer to a component.
   * Same as ecs_get_mut_w_entity but accepts a component typename.
   *
   * @param world The world.
   * @param entity The entity.
   * @param component The component to obtain.
   * @param is_added Out parameter that returns true if the component was added.
   * @return The component pointer.
   */
  #define ecs_get_mut(world, entity, component, is_added)\
      ((component*)ecs_get_mut_w_entity(world, entity, ecs_typeid(component), is_added))
  
  /** Signal that a component has been modified.
   * This operation allows an application to signal to Flecs that a component has
   * been modified. As a result, OnSet systems will be invoked.
   *
   * This operation is commonly used together with ecs_get_mut.
   *
   * @param world The world.
   * @param entity The entity.
   * @param component The entity id of the component that was modified.
   */
  FLECS_API 
  void ecs_modified_w_entity(
      ecs_world_t *world,
      ecs_entity_t entity,
      ecs_entity_t component);
  
  /** Signal that a component has been modified.
   * Same as ecs_modified_w_entity but accepts a component typename.
   *
   * @param world The world.
   * @param entity The entity.
   * @param component The component that was modified.
   */
  #define ecs_modified(world, entity, component)\
      ecs_modified_w_entity(world, entity, ecs_typeid(component))
  
  
  /** @} */
  
  /**
   * @defgroup setting Setting Components
   * @{
   */
  
  /** Set the value of a component.
   * This operation allows an application to set the value of a component. The
   * operation is equivalent to calling ecs_get_mut and ecs_modified.
   *
   * If the provided entity is 0, a new entity will be created.
   *
   * @param world The world.
   * @param entity The entity.
   * @param component The entity id of the component to set.
   * @param size The size of the pointer to the value.
   * @param ptr The pointer to the value.
   * @return The entity. A new entity if no entity was provided.
   */
  FLECS_API
  ecs_entity_t ecs_set_ptr_w_entity(
      ecs_world_t *world,
      ecs_entity_t entity,
      ecs_entity_t component,
      size_t size,
      const void *ptr);
  
  /** Set the value of a component.
   * Same as ecs_set_ptr_w_entity, but accepts a component typename and 
   * automatically determines the type size.
   *
   * @param world The world.
   * @param entity The entity.
   * @param component The component to set.
   * @param size The size of the pointer to the value.
   * @return The entity. A new entity if no entity was provided.
   */
  #define ecs_set_ptr(world, entity, component, ptr)\
      ecs_set_ptr_w_entity(world, entity, ecs_typeid(component), sizeof(component), ptr)
  
  /* Conditionally skip macro's as compound literals and variadic arguments are 
   * not supported in C89 */
  #ifndef FLECS_LEGACY
  
  /** Set the value of a component.
   * Same as ecs_set_ptr, but accepts a value instead of a pointer to a value.
   *
   * @param world The world.
   * @param entity The entity.
   * @param component The component to set.
   * @param size The size of the pointer to the value.
   * @return The entity. A new entity if no entity was provided.
   */
  #define ecs_set(world, entity, component, ...)\
      ecs_set_ptr_w_entity(world, entity, ecs_typeid(component), sizeof(component), &(component)__VA_ARGS__)
  
  #endif
  
  /** @} */
  
  /**
   * @defgroup singleton Singleton components
   * @{
   */
  
  #define ecs_singleton_get(world, comp)\
      ecs_get(world, ecs_typeid(comp), comp)
  
  #ifndef FLECS_LEGACY
  #define ecs_singleton_set(world, comp, ...)\
      ecs_set(world, ecs_typeid(comp), comp, __VA_ARGS__)
  #endif
  
  #define ecs_singleton_get_mut(world, comp)\
      ecs_get_mut(world, ecs_typeid(comp), comp, NULL)
  
  #define ecs_singleton_modified(world, comp)\
      ecs_modified(world, ecs_typeid(comp), comp)
  
  /**
   * @defgroup testing Testing Components
   * @{
   */
  
  /** Test if an entity has an entity.
   * This operation returns true if the entity has the provided entity in its 
   * type.
   *
   * @param world The world.
   * @param entity The entity.
   * @param to_check The entity to test for.
   * @return True if the entity has the entity, false if not.
   */
  FLECS_API
  bool ecs_has_entity(
      ecs_world_t *world,
      ecs_entity_t entity,
      ecs_entity_t to_check);
  
  /** Test if an entity has a type.
   * This operation returns true if the entity has the provided type in its 
   * type.
   *
   * @param world The world.
   * @param entity The entity.
   * @param type The type to test for.
   * @return True if the entity has the type, false if not.
   */
  FLECS_API
  bool ecs_has_type(
      ecs_world_t *world,
      ecs_entity_t entity,
      ecs_type_t type);
  
  /** Test if an entity has a component, type or tag.
   * This operation returns true if the entity has the provided component, type or
   * tag in its type.
   *
   * @param world The world.
   * @param entity The entity.
   * @param type The component, type or tag to test for.
   * @return True if the entity has the type, false if not.
   */
  #define ecs_has(world, entity, type)\
      ecs_has_type(world, entity, ecs_type(type))
  
  /** Test if an entity owns component, type or tag.
   * This operation is similar to ecs_has, but will return false if the entity
   * does not own the component, which is the case if the component is defined on
   * a base entity with an INSTANCEOF role.
   *
   * @param world The world.
   * @param entity The entity.
   * @param type The component, type or tag to test for.
   * @return True if the entity owns the component, type or tag, false if not.
   */
  #define ecs_owns(world, entity, type, owned)\
      ecs_type_owns_type(world, ecs_get_type(world, entity), ecs_type(type), owned)
  
  /** Test if an entity owns an entity.
   * This operation is similar to ecs_has, but will return false if the entity
   * does not own the entity, which is the case if the entity is defined on
   * a base entity with an INSTANCEOF role.
   *
   * @param world The world.
   * @param entity The entity.
   * @param type The entity to test for.
   * @return True if the entity owns the entity, false if not.
   */
  #define ecs_owns_entity(world, entity, has, owned)\
      ecs_type_owns_entity(world, ecs_get_type(world, entity), has, owned)
  
  
  /** @} */
  
  /**
   * @defgroup metadata Entity Metadata
   * @{
   */
  
  /** Test whether an entity is alive.
   *
   * @param world The world.
   * @param e The entity.
   * @return True if the entity is alive, false if the entity is not alive.
   */
  FLECS_API
  bool ecs_is_alive(
      ecs_world_t *world,
      ecs_entity_t e);
  
  /** Test whether an entity exists.
   * Similar as ecs_is_alive, but ignores entity generation count.
   *
   * @param world The world.
   * @param e The entity.
   * @return True if the entity exists, false if the entity does not exist.
   */
  FLECS_API
  bool ecs_exists(
      ecs_world_t *world,
      ecs_entity_t e);
  
  /** Get the type of an entity.
   *
   * @param world The world.
   * @param entity The entity.
   * @return The type of the entity, NULL if the entity has no components.
   */
  FLECS_API
  ecs_type_t ecs_get_type(
      ecs_world_t *world,
      ecs_entity_t entity);
  
  /** Get the typeid of an entity.
   *
   * @param world The world.
   * @param entity The entity.
   * @return The typeid of the entity.
   */
  FLECS_API
  ecs_entity_t ecs_get_typeid(
      ecs_world_t *world,
      ecs_entity_t e);
  
  /** Get the name of an entity.
   * This will return the name as specified in the EcsName component.
   *
   * @param world The world.
   * @param entity The entity.
   * @return The type of the entity, NULL if the entity has no name.
   */
  FLECS_API
  const char* ecs_get_name(
      ecs_world_t *world,
      ecs_entity_t entity);
  
  /** Convert type role to string.
   * This operation converts a type role to a string.
   * 
   * @param world The world.
   * @param entity The entity containing the type role.
   * @return The type role string, or NULL if no type role is provided.
   */
  FLECS_API
  const char* ecs_role_str(
      ecs_entity_t entity);
  
  /** Convert entity identifier to string.
   * This operation interprets type roles and translates them to a string.
   *
   * @param world The world.
   * @param entity The entity to convert to a string.
   * @param buffer The buffer in which to store the string.
   * @param buffer_len The length of the provided buffer.
   * @return The number of characters required to write the string.
   */
  FLECS_API
  size_t ecs_entity_str(
      ecs_world_t *world,
      ecs_entity_t entity,
      char *buffer,
      size_t buffer_len);
  
  /** Get the parent of an entity.
   * This will return a parent of the entity that has the specified component. If
   * the component is 0, the operation will return the first parent that it finds
   * in the entity type (an entity with a CHILDOF role).
   *
   * @param world The world.
   * @param entity The entity.
   * @param component The entity id of a component that the parent must have.
   * @return The parent of the entity, 0 if no parent was found.
   */
  FLECS_API
  ecs_entity_t ecs_get_parent_w_entity(
      ecs_world_t *world,
      ecs_entity_t entity,
      ecs_entity_t component);
  
  /** Get the parent of an entity.
   * Same as ecs_get_parent_w_entity but accepts a component typename.
   *
   * @param world The world.
   * @param entity The entity.
   * @param component A component that the parent must have.
   * @return The parent of the entity, 0 if no parent was found.
   */
  #define ecs_get_parent(world, entity, component)\
      ecs_get_parent_w_entity(world, entity, ecs_typeid(component))
  
  
  /** Enable or disable an entity.
   * This operation enables or disables an entity by adding or removing the
   * EcsDisabled tag. A disabled entity will not be matched with any systems,
   * unless the system explicitly specifies the EcsDisabled tag.
   *
   * @param world The world.
   * @param entity The entity to enable or disable.
   * @param enabled true to enable the entity, false to disable.
   */
  FLECS_API
  void ecs_enable(
      ecs_world_t *world,
      ecs_entity_t entity,
      bool enabled);
  
  /** Count entities that have an entity.
   * Returns the number of entities that have the specified entity.
   *
   * @param world The world.
   * @param entity The entity.
   * @return The number of entities that have the entity.
   */
  FLECS_API
  int32_t ecs_count_entity(
      ecs_world_t *world,
      ecs_entity_t entity);
  
  /** Count entities that have a type.
   * Returns the number of entities that have the specified type.
   *
   * @param world The world.
   * @param type The type.
   * @return The number of entities that have the type.
   */
  FLECS_API
  int32_t ecs_count_type(
      ecs_world_t *world,
      ecs_type_t type);
  
  /** Count entities that have a component, type or tag.
   * Returns the number of entities that have the specified component, type or tag.
   *
   * @param world The world.
   * @param type The component, type or tag.
   * @return The number of entities that have the component, type or tag.
   */
  #define ecs_count(world, type)\
      ecs_count_type(world, ecs_type(type))
  
  /** Count entities that match a filter.
   * Returns the number of entities that match the specified filter.
   *
   * @param world The world.
   * @param type The type.
   * @return The number of entities that match the specified filter.
   */
  FLECS_API
  int32_t ecs_count_w_filter(
      ecs_world_t *world,
      const ecs_filter_t *filter);
  
  
  /** @} */
  
  /**
   * @defgroup lookup Lookups
   * @{
   */
  
  /** Lookup an entity by name.
   * Returns an entity that matches the specified name. Only looks for entities in
   * the current scope (root if no scope is provided).
   *
   * @param world The world.
   * @param name The entity name.
   * @return The entity with the specified name, or 0 if no entity was found.
   */
  FLECS_API
  ecs_entity_t ecs_lookup(
      ecs_world_t *world,
      const char *name);
  
  /** Lookup a child entity by name.
   * Returns an entity that matches the specified name. Only looks for entities in
   * the provided parent. If no parent is provided, look in the current scope (
   * root if no scope is provided).
   *
   * @param world The world.
   * @param name The entity name.
   * @return The entity with the specified name, or 0 if no entity was found.
   */
  FLECS_API
  ecs_entity_t ecs_lookup_child(
      ecs_world_t *world,
      ecs_entity_t parent,
      const char *name);
  
  /** Lookup an entity from a path.
   * Lookup an entity from a provided path, relative to the provided parent. The
   * operation will use the provided separator to tokenize the path expression. If
   * the provided path contains the prefix, the search will start from the root.
   *
   * If the entity is not found in the provided parent, the operation will 
   * continue to search in the parent of the parent, until the root is reached. If
   * the entity is still not found, the lookup will search in the flecs.core
   * scope. If the entity is not found there either, the function returns 0.
   *
   * @param world The world.
   * @param parent The entity from which to resolve the path.
   * @param path The path to resolve.
   * @param sep The path separator.
   * @param prefix The path prefix.
   * @return The entity if found, else 0.
   */
  FLECS_API
  ecs_entity_t ecs_lookup_path_w_sep(
      ecs_world_t *world,
      ecs_entity_t parent,
      const char *path,
      const char *sep,
      const char *prefix);
  
  /** Lookup an entity from a path.
   * Same as ecs_lookup_path_w_sep, but with defaults for the separator and
   * prefix. These defaults are used when looking up identifiers in a type or
   * signature expression.
   *
   * @param world The world.
   * @param parent The entity from which to resolve the path.
   * @param path The path to resolve.
   * @return The entity if found, else 0. 
   */
  #define ecs_lookup_path(world, parent, path)\
      ecs_lookup_path_w_sep(world, parent, path, ".", NULL)
  
  /** Lookup an entity from a full path.
   * Same as ecs_lookup_pat, but  searches from the current scope, or root scope
   * if no scope is set.
   *
   * @param world The world.
   * @param path The path to resolve.
   * @return The entity if found, else 0. 
   */
  #define ecs_lookup_fullpath(world, path)\
      ecs_lookup_path_w_sep(world, 0, path, ".", NULL)
  
  /** Lookup an entity by its symbol name.
   * This looks up an entity by the symbol name that was provided in EcsName. The
   * operation does not take into account scoping, which means it will search all
   * entities that have an EcsName.
   *
   * This operation can be useful to resolve, for example, a type by its C 
   * identifier, which does not include the Flecs namespacing.
   */
  FLECS_API
  ecs_entity_t ecs_lookup_symbol(
      ecs_world_t *world,
      const char *name);
  
  /* Add alias for entity to global scope */
  FLECS_API
  void ecs_use(
      ecs_world_t *world,
      ecs_entity_t entity,
      const char *name);
  
  /** @} */
  
  /**
   * @defgroup paths Paths
   * @{
   */
  
  /** Get a path identifier for an entity.
   * This operation creates a path that contains the names of the entities from
   * the specified parent to the provided entity, separated by the provided 
   * separator. If no parent is provided the path will be relative to the root. If
   * a prefix is provided, the path will be prefixed by the prefix.
   *
   * If the parent is equal to the provided child, the operation will return an
   * empty string. If a nonzero component is provided, the path will be created by 
   * looking for parents with that component.
   *
   * The returned path should be freed by the application.
   *
   * @param world The world.
   * @param parent The entity from which to create the path.
   * @param child The entity to which to create the path.
   * @param component The component of the parent.
   * @return The relative entity path.
   */
  FLECS_API
  char* ecs_get_path_w_sep(
      ecs_world_t *world,
      ecs_entity_t parent,
      ecs_entity_t child,
      ecs_entity_t component,
      const char *sep,
      const char *prefix);
  
  /** Get a path identifier for an entity.
   * Same as ecs_get_path_w_sep, but with default values for the separator and
   * prefix. These defaults are used throughout Flecs whenever identifiers are
   * used in type or signature expressions.
   *
   * @param world The world.
   * @param parent The entity from which to create the path.
   * @param child The entity to which to create the path.
   * @return The relative entity path.
   */
  #define ecs_get_path(world, parent, child)\
      ecs_get_path_w_sep(world, parent, child, 0, ".", NULL)
  
  /** Get a full path for an entity.
   * Same as ecs_get_path, but with default values for the separator and
   * prefix, and the path is created from the current scope, or root if no scope
   * is provided.
   *
   * @param world The world.
   * @param child The entity to which to create the path.
   * @return The entity path.
   */
  #define ecs_get_fullpath(world, child)\
      ecs_get_path_w_sep(world, 0, child, 0, ".", NULL)
  
  /** Find or create entity from path.
   * This operation will find or create an entity from a path, and will create any
   * intermediate entities if required. If the entity already exists, no entities
   * will be created.
   *
   * If the path starts with the prefix, then the entity will be created from the
   * root scope.
   *
   * @param world The world.
   * @param parent The entity relative to which the entity should be created.
   * @param path The path to create the entity for.
   * @param sep The separator used in the path.
   * @param prefix The prefix used in the path.
   * @return The entity.
   */
  FLECS_API
  ecs_entity_t ecs_new_from_path_w_sep(
      ecs_world_t *world,
      ecs_entity_t parent,
      const char *path,
      const char *sep,
      const char *prefix);
  
  /** Find or create entity from path.
   * Same as ecs_new_from_path_w_sep, but with defaults for sep and prefix.
   *
   * @param world The world.
   * @param parent The entity relative to which the entity should be created.
   * @param path The path to create the entity for.
   * @return The entity.
   */
  #define ecs_new_from_path(world, parent, path)\
      ecs_new_from_path_w_sep(world, parent, path, ".", NULL)
  
  /** Find or create entity from full path.
   * Same as ecs_new_from_path, but entity will be created from the current scope,
   * or root scope if no scope is set.
   *
   * @param world The world.
   * @param path The path to create the entity for.
   * @return The entity.
   */
  #define ecs_new_from_fullpath(world, path)\
      ecs_new_from_path_w_sep(world, 0, path, ".", NULL)
  
  /** Add specified path to entity.
   * This operation is similar to ecs_new_from_path, but will instead add the path
   * to an existing entity.
   *
   * If an entity already exists for the path, it will be returned instead.
   *
   * @param world The world.
   * @param entity The entity to which to add the path.
   * @param parent The entity relative to which the entity should be created.
   * @param path The path to create the entity for.
   * @param sep The separator used in the path.
   * @param prefix The prefix used in the path.
   * @return The entity.
   */ 
  FLECS_API
  ecs_entity_t ecs_add_path_w_sep(
      ecs_world_t *world,
      ecs_entity_t entity,
      ecs_entity_t parent,
      const char *path,
      const char *sep,
      const char *prefix);
  
  /** Add specified path to entity.
   * Same as ecs_add_from_path_w_sep, but with defaults for sep and prefix.
   *
   * @param world The world.
   * @param entity The entity to which to add the path. 
   * @param parent The entity relative to which the entity should be created.
   * @param path The path to create the entity for.
   * @return The entity.
   */
  #define ecs_add_path(world, entity, parent, path)\
      ecs_add_path_w_sep(world, entity, parent, path, ".", NULL)
  
  /** Add specified path to entity.
   * Same as ecs_add_from_path, but entity will be created from the current scope,
   * or root scope if no scope is set.
   *
   * @param world The world.
   * @param entity The entity to which to add the path.
   * @param path The path to create the entity for.
   * @return The entity.
   */
  #define ecs_add_fullpath(world, entity, path)\
      ecs_add_path_w_sep(world, entity, 0, path, ".", NULL)
  
  
  /** @} */
  
  /**
   * @defgroup scopes Scopes
   * @{
   */
  
  /** Does entity have children.
   *
   * @param world The world
   * @param entity The entity
   * @return True if the entity has children, false if not.
   */
  FLECS_API
  int32_t ecs_get_child_count(
      ecs_world_t *world,
      ecs_entity_t entity);
  
  /** Return a scope iterator.
   * A scope iterator iterates over all the child entities of the specified 
   * parent.
   *
   * @param world The world.
   * @param parent The parent entity for which to iterate the children.
   * @return The iterator.
   */
  FLECS_API
  ecs_iter_t ecs_scope_iter(
      ecs_world_t *world,
      ecs_entity_t parent);
  
  /** Return a filtered scope iterator.
   * Same as ecs_scope_iter, but results will be filtered.
   *
   * @param world The world.
   * @param parent The parent entity for which to iterate the children.
   * @return The iterator.
   */
  FLECS_API
  ecs_iter_t ecs_scope_iter_w_filter(
      ecs_world_t *world,
      ecs_entity_t parent,
      ecs_filter_t *filter);
  
  /** Progress the scope iterator.
   * This operation progresses the scope iterator to the next table. The iterator
   * must have been initialized with `ecs_scope_iter`. This operation must be
   * invoked at least once before interpreting the contents of the iterator.
   *
   * @param it The iterator
   * @return True if more data is available, false if not.
   */
  FLECS_API
  bool ecs_scope_next(
      ecs_iter_t *it);
  
  /** Set the current scope.
   * This operation sets the scope of the current stage to the provided entity.
   * As a result new entities will be created in this scope, and lookups will be
   * relative to the provided scope.
   *
   * It is considered good practice to restore the scope to the old value.
   *
   * @param world The world.
   * @param scope The entity to use as scope.
   * @return The previous scope.
   */
  FLECS_API
  ecs_entity_t ecs_set_scope(
      ecs_world_t *world,
      ecs_entity_t scope);
  
  /** Get the current scope.
   * Get the scope set by ecs_set_scope. If no scope is set, this operation will
   * return 0.
   *
   * @param world The world.
   * @return The current scope.
   */
  FLECS_API
  ecs_entity_t ecs_get_scope(
      ecs_world_t *world);
  
  /** Set a name prefix for newly created entities.
   * This is a utility that lets C modules use prefixed names for C types and
   * C functions, while using names for the entity names that do not have the 
   * prefix. The name prefix is currently only used by ECS_COMPONENT.
   *
   * @param world The world.
   * @param prefix The name prefix to use.
   * @return The previous prefix.
   */
  FLECS_API
  const char* ecs_set_name_prefix(
      ecs_world_t *world,
      const char *prefix);    
  
  /** @} */
  
  /**
   * @defgroup filters Filters
   * @{
   */
  
  /** Return a filter iterator.
   * A filter iterator lets an application iterate over entities that match the
   * specified filter. If NULL is provided for the filter, the iterator will
   * iterate all tables in the world.
   * 
   * @param world The world.
   * @param filter The filter.
   * @return An iterator that can be used with ecs_filter_next.
   */
  FLECS_API
  ecs_iter_t ecs_filter_iter(
      ecs_world_t *world,
      const ecs_filter_t *filter);  
  
  /** Iterate tables matched by filter.
   * This operation progresses the filter iterator to the next table. The 
   * iterator must have been initialized with `ecs_filter_iter`. This operation 
   * must be invoked at least once before interpreting the contents of the 
   * iterator.
   *
   * @param it The iterator
   * @return True if more data is available, false if not.
   */
  FLECS_API
  bool ecs_filter_next(
      ecs_iter_t *iter);
  
  
  /** @} */
  
  /**
   * @defgroup queries Queries
   * @{
   */
  
  /** Create a query.
   * This operation creates a query. Queries are used to iterate over entities
   * that match a signature expression and are the fastest way to find and iterate
   * over entities and their components.
   * 
   * Queries should be created once, and reused multiple times. While iterating a
   * query is a cheap operation, creating and deleting a query is expensive. The
   * reason for this is that queries are "prematched", which means that a query
   * stores state about which entities (or rather, tables) match with the query.
   * Building up this state happens during query creation.
   *
   * Once a query is created, matching only happens when new tables are created.
   * In most applications this is an infrequent process, since it only occurs when
   * a new combination of components is introduced. While matching is expensive,
   * it is importent to note that matching does not happen on a per-entity basis,
   * but on a per-table basis. This means that the average time spent on matching
   * per frame should rapidly approach zero over the lifetime of an application.
   *
   * A query provides direct access to the component arrays. When an application
   * creates/deletes entities or adds/removes components, these arrays can shift
   * component values around, or may grow in size. This can cause unexpected or
   * undefined behavior to occur if these operations are performed while 
   * iterating. To prevent this from happening an application should either not
   * perform these operations while iterating, or use deferred operations (see
   * ecs_defer_begin and ecs_defer_end).
   *
   * Queries can be created and deleted dynamically. If a query was not deleted
   * (using ecs_query_free) before the world is deleted, it will be deleted 
   * automatically.
   *
   * @param world The world.
   * @param sig The query signature expression.
   * @return The new query.
   */
  FLECS_API
  ecs_query_t* ecs_query_new(
      ecs_world_t *world,
      const char *sig);
  
  /** Create a subquery.
   * A subquery is just like a regular query, except that it is matched against 
   * the matched tables of a parent query. Reducing the number of global (normal)
   * queries can improve performance, as new archetypes have to be matched against
   * fewer queries.
   *
   * Subqueries are cheaper to create than regular queries, because the initial
   * set of tables they have to match against is smaller. This makes subqueries
   * more suitable for creating while the simulation.
   *
   * Subqueries are not registered with tables directly, and instead receive new
   * table notifications from their parent query. This means that there is less
   * administrative overhead associated with subqueries.
   *
   * Subqueries can be nested, which allows for the creation of increasingly more
   * specific query hierarchies that are considerably more efficient than when all
   * queries would be created as global queries.
   *
   * @param world The world.
   * @param parent The parent query.
   * @param sig The query signature expression.
   * @return The new subquery.
   */
  FLECS_API
  ecs_query_t* ecs_subquery_new(
      ecs_world_t *world,
      ecs_query_t *parent,
      const char *sig);    
  
  /** Cleanup a query.
   * This operation frees a query.
   *
   * @param query The query.
   */
  FLECS_API
  void ecs_query_free(
      ecs_query_t *query);
  
  /** Return a query iterator.
   * A query iterator lets an application iterate over entities that match the
   * specified query. If a sorting function is specified, the query will check
   * whether a resort is required upon creating the iterator.
   *
   * Creating a query iterator is a cheap operation that does not allocate any
   * resources. An application does not need to deinitialize or free a query 
   * iterator before it goes out of scope.
   *
   * To iterate the iterator, an application should use ecs_query_next to progress
   * the iterator and test if it has data.
   *
   * Query iteration requires an outer and an inner loop. The outer loop uses
   * ecs_query_next to test if new tables are available. The inner loop iterates
   * the entities in the table, and is usually a for loop that uses iter.count to
   * loop through the entities and component arrays.
   *
   * The two loops are necessary because of how data is stored internally. 
   * Entities are grouped by the components they have, in tables. A single query 
   * can (and often does) match with multiple tables. Because each table has its
   * own set of arrays, an application has to reobtain pointers to those arrays
   * for each matching table.
   *
   * @param query The query to iterate.
   * @return The query iterator.
   */
  FLECS_API
  ecs_iter_t ecs_query_iter(
      ecs_query_t *query);  
  
  /** Iterate over a query.
   * This operation is similar to ecs_query_iter, but starts iterating from a
   * specified offset, and will not iterate more than limit entities.
   *
   * @param query The query to iterate.
   * @param offset The number of entities to skip.
   * @param limit The maximum number of entities to iterate.
   * @return The query iterator.
   */
  FLECS_API
  ecs_iter_t ecs_query_iter_page(
      ecs_query_t *query,
      int32_t offset,
      int32_t limit);  
  
  /** Progress the query iterator.
   * This operation progresses the query iterator to the next table. The 
   * iterator must have been initialized with `ecs_query_iter`. This operation 
   * must be invoked at least once before interpreting the contents of the 
   * iterator.
   *
   * @param iter The iterator.
   * @returns True if more data is available, false if not.
   */
  FLECS_API
  bool ecs_query_next(
      ecs_iter_t *iter);      
  
  /** Progress the query iterator with filter.
   * This operation is the same as ecs_query_next, but accepts a filter as an
   * argument. Entities not matching the filter will be skipped by the iterator.
   *
   * @param iter The iterator.
   * @param filter The filter to apply to the iterator.
   * @returns True if more data is available, false if not.
   */
  FLECS_API
  bool ecs_query_next_w_filter(
      ecs_iter_t *iter,
      const ecs_filter_t *filter); 
  
  /** Progress the query iterator for a worker thread.
   * This operation is similar to ecs_query_next, but provides the ability to 
   * divide entities up across multiple worker threads. The operation accepts a
   * current thread id and a total thread id, which is used to determine which
   * subset of entities should be assigned to the current thread.
   *
   * Current should be less than total, and there should be as many as total
   * threads. If there are less entities in a table than there are threads, only
   * as many threads as there are entities will iterate that table.
   *
   * @param it The iterator.
   * @param current Thread id of current thread.
   * @param total Total number of threads.
   * @returns True if more data is available, false if not.
   */
  bool ecs_query_next_worker(
      ecs_iter_t *it,
      int32_t current,
      int32_t total);
  
  /** 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. 
   * Resorting happens when a query iterator is obtained, and only if the table
   * data has changed.
   *
   * If multiple queries that match the same (sub)set of tables specify different 
   * sorting functions, resorting is likely to happen every time an iterator is
   * obtained, which can significantly slow down iterations.
   *
   * The sorting function will be applied to the specified component. Resorting
   * only happens if that component has changed, or when the entity order in the
   * table has changed. If no component is provided, resorting only happens when
   * the entity order changes.
   *
   * @param world The world.
   * @param query The query.
   * @param component The component used to sort.
   * @param compare The compare function used to sort the components.
   */
  FLECS_API
  void ecs_query_order_by(
      ecs_world_t *world,
      ecs_query_t *query,
      ecs_entity_t component,
      ecs_compare_action_t compare);
  
  /** Group and sort matched tables.
   * Similar yo ecs_query_order_by, but instead of sorting individual entities, this
   * operation only sorts matched tables. This can be useful of a query needs to
   * enforce a certain iteration order upon the tables it is iterating, for 
   * example by giving a certain component or tag a higher priority.
   *
   * The sorting function assigns a "rank" to each type, which is then used to
   * sort the tables. Tables with higher ranks will appear later in the iteration.
   * 
   * Resorting happens when a query iterator is obtained, and only if the set of
   * matched tables for a query has changed. If table sorting is enabled together
   * with entity sorting, table sorting takes precedence, and entities will be
   * sorted within each set of tables that are assigned the same rank.
   *
   * @param world The world.
   * @param query The query.
   * @param component The component used to determine the group rank.
   * @param rank_action The rank action.
   */
  FLECS_API
  void ecs_query_group_by(
      ecs_world_t *world,
      ecs_query_t *query,
      ecs_entity_t component,
      ecs_rank_type_action_t rank_action);
  
  /** Returns whether the query data changed since the last iteration.
   * This operation must be invoked before obtaining the iterator, as this will
   * reset the changed state. The operation will return true after:
   * - new entities have been matched with
   * - matched entities were deleted
   * - matched components were changed
   * 
   * @param query The query.
   * @return true if entities changed, otherwise false.
   */
  FLECS_API
  bool ecs_query_changed(
      ecs_query_t *query);
  
  /** Returns whether query is orphaned.
   * When the parent query of a subquery is deleted, it is left in an orphaned
   * state. The only valid operation on an orphaned query is deleting it. Only
   * subqueries can be orphaned.
   *
   * @param query The query.
   * @return true if query is orphaned, otherwise false.
   */
  FLECS_API
  bool ecs_query_orphaned(
      ecs_query_t *query);
  
  /** @} */
  
  /**
   * @defgroup iterator Iterators
   * @{
   */
  
  /** Obtain column data. 
   * This operation is to be used to obtain a component array for a specific 
   * column in the system or query signature. The column is identified by the 
   * provided index. For example, if this is the provided signature:
   * 
   * Position, Velocity
   * 
   * Position is at index 1, and Velocity is at index 2.
   *
   * This operation may return NULL if the column is optional, and the current
   * table does not have the data. Additionally, if the column points to a shared
   * component or a reference, the returned value should be interpreted as a 
   * pointer instead of an array.
   *
   * The provided size must match the size of the component, otherwise the 
   * function may fail.
   * 
   * @param it The iterator.
   * @param size The size of the component.
   * @param column The index identifying the column in a signature.
   * @return A pointer to the column data.
   */
  FLECS_API
  void* ecs_column_w_size(
      const ecs_iter_t *it,
      size_t size,
      int32_t column);
  
  /** Obtain column data. 
   * This operation is similar to ecs_column_w_size, except that it accepts the
   * component typename.
   * 
   * @param it The iterator.
   * @param type The typename of the component for which to obtain the data.
   * @param column The index identifying the column in a signature.
   * @return A pointer to the column data.
   */
  #define ecs_column(it, type, column)\
      ((type*)ecs_column_w_size(it, sizeof(type), column))
  
  /** Get column index by name.
   * This function obtains a column index by name. This function can only be used
   * if a query signature contains names.
   *
   * @param it The iterator.
   * @param name The column name.
   * @return Index of the column (to be used with ecs_column_* functions).
   */
  FLECS_API
  int32_t ecs_column_index_from_name(
      const ecs_iter_t *it,
      const char *name);
  
  /** Test if column is owned or not.
   * The following signature shows an example of one owned components and two
   * components that are not owned by the current entity:
   * 
   * Position, PARENT:Velocity, MyEntity:Mass
   * 
   * Position is an owned component. Velocity and Mass both belong to a different
   * entity. This operation will return false for Position, and true for Velocity
   * and Mass. If a component is matched from a prefab, this operation will also
   * return false.
   * 
   * @param it The it parameter passed into the system.
   * @param index The index identifying the column in a system signature.
   * @return True if column is owned, false if column is not.
   */
  FLECS_API
  bool ecs_is_owned(
      const ecs_iter_t *it,
      int32_t column);
  
  /** Obtain a single element. 
   * This operation is similar to ecs_column, but instead of an array it obtains
   * a single element from a component array. The advantage of using ecs_element
   * is that a system can be agnostic towards whether a component is owned or not,
   * at the cost of some additional performance overhead.
   *
   * @param it The iterator.
   * @param size The component size.
   * @param column The index identifying the column in a signature.
   * @param row The current row in the table.
   * @return A pointer to the current element.
   */
  FLECS_API
  void *ecs_element_w_size(
      const ecs_iter_t *it,
      size_t size,
      int32_t column,
      int32_t row);
  
  /** Obtain a single element. 
   * Same as ecs_element_w_size, but allows specifying a typename instead of a
   * size.
   *
   * @param it The iterator.
   * @param type The column type.
   * @param column The index identifying the column in a signature.
   * @param row The current row in the table.
   * @return A pointer to the current element.
   */
  #define ecs_element(it, type, column, row)\
      ((type*)ecs_element_w_size(it, sizeof(type), column, row))
  
  /** Obtain the source of a signature column.
   * This operation returns the source of a signature column. By default this will
   * return 0 for regular columns, but for columns where the components are
   * provided by entities other than the entity being iterated over, this will
   * return the source of the component.
   * 
   * @param it Pointer to the it object passed into the system callback.
   * @param column The index identifying the column in a signature.
   * @return The source entity for the column. 
   */
  FLECS_API
  ecs_entity_t ecs_column_source(
      const ecs_iter_t *it,
      int32_t column);
  
  /** Obtain the entity id of the signature column.
   * This operation returns the entity id of the component or tag used in the
   * system signature. For example, when provided this signature:
   *
   * Position, Velocity
   *
   * ecs_column_entity(world, 1) will return the component handle for Position and
   * ecs_column_entity(world, 2) will return the componnet handle for Velocity.
   * 
   * @param it The iterator.
   * @param column The index identifying the column in a signature.
   * @return The entity id of the signature column.
   */
  FLECS_API
  ecs_entity_t ecs_column_entity(
      const ecs_iter_t *it,
      int32_t column);
  
  /** Obtain the type of a column from inside a system. 
   * This operation is equivalent to ecs_column_entity, except that it returns
   * a type, instead of an entity handle. Invoking this function is the same as
   * doing:
   * 
   * ecs_type_from_entity( ecs_column_entity(it, index));
   * 
   * @param it The iterator.
   * @param column The index identifying the column in a signature.
   * @return The type for the specified column, or NULL if failed.
   */ 
  FLECS_API
  ecs_type_t ecs_column_type(
      const ecs_iter_t *it,
      int32_t column);
  
  /** Get the size of the component of the specified column.
   *
   * @param it The iterator.
   * @param column The column for which to obtain the size.
   */
  FLECS_API
  size_t ecs_column_size(
      const ecs_iter_t *it,
      int32_t column);
  
  /** Is the column readonly.
   * This operation returns if the column is a readonly column. Readonly columns
   * are marked in the system signature with the [in] modifier. 
   * 
   * @param it Pointer to the it object passed into the system callback.
   * @param column An index identifying the column.
   * @return True if the column is readonly, false otherwise. */
  FLECS_API
  bool ecs_is_readonly(
      const ecs_iter_t *it,
      int32_t column);
  
  /** Get type of table that system is currently iterating over. 
   * This will return the type for all entities that are currently being iterated
   * over, until ecs_iter_next is invoked.
   *
   * @param it The iterator.
   * @return The type of the current table.
   */
  FLECS_API
  ecs_type_t ecs_iter_type(
      const ecs_iter_t *it);
  
  /** Get component array from table.
   * In some cases an application may require access to the table component arrays
   * directly instead of going through the signature to table mapping. A typical
   * scenario where this would be used is when using a filter iterator, where
   * there is no signature, and thus ecs_column cannot be used.
   *
   * @param it The iterator.
   * @param column The index identifying the column in a table.
   * @return The component array corresponding to the column index.
   */
  FLECS_API
  void* ecs_table_column(
      const ecs_iter_t *it,
      int32_t column);
  
  /** Get the size of a table column.
   *
   * @param it The iterator.
   * @param column The column for which to obtain the size.
   */
  FLECS_API
  size_t ecs_table_column_size(
      const ecs_iter_t *it,
      int32_t column);
  
  /** Get the index of the table column for a component.
   * 
   * @param it The iterator.
   * @param component The component for which to obtain the index.
   */
  FLECS_API
  int32_t ecs_table_component_index(
      const ecs_iter_t *it,
      ecs_entity_t component);
  
  /** Get a strongly typed pointer to a column (owned or shared). */
  #define ECS_COLUMN(it, type, id, column)\
      ECS_ENTITY_VAR(type) = ecs_column_entity(it, column);\
      ECS_TYPE_VAR(type) = ecs_column_type(it, column);\
      type *id = ecs_column(it, type, column);\
      (void)ecs_typeid(type);\
      (void)ecs_type(type);\
      (void)id
  
  /** Get a strongly typed pointer to a column (owned or shared). */
  #define ECS_CONST_COLUMN(it, type, id, column)\
      const type *id = ecs_const_column(it, type, column)
  
  /** Obtain a handle to the component of a column */
  #define ECS_COLUMN_COMPONENT(it, id, column)\
      ECS_ENTITY_VAR(id) = ecs_column_entity(it, column);\
      ECS_TYPE_VAR(id) = ecs_column_type(it, column);\
      (void)ecs_typeid(id);\
      (void)ecs_type(id)
  
  /** Obtain a handle to the entity of a column */
  #define ECS_COLUMN_ENTITY(it, id, column)\
      ecs_entity_t id = ecs_column_entity(it, column);\
      ECS_TYPE_VAR(id) = ecs_column_type(it, column);\
      (void)id;\
      (void)ecs_type(id)
  
  /** Utility macro for importing all handles for a module from a system column */
  #define ECS_IMPORT_COLUMN(it, module, column) \
      module *ecs_module_ptr(module) = ecs_column(it, module, column);\
      ecs_assert(ecs_module_ptr(module) != NULL, ECS_MODULE_UNDEFINED, #module);\
      ecs_assert(!ecs_is_owned(it, column), ECS_COLUMN_IS_NOT_SHARED, NULL);\
      module ecs_module(module) = *ecs_module_ptr(module);\
      module##ImportHandles(ecs_module(module))
  
  
  /** @} */
  
  /**
   * @defgroup staging Staging
   * @{
   */
  
  /** Begin frame. */
  FLECS_API
  FLECS_FLOAT ecs_frame_begin(
      ecs_world_t *world,
      FLECS_FLOAT delta_time);
  
  /** End frame. */
  FLECS_API
  void ecs_frame_end(
      ecs_world_t *world);
  
  /** Begin staging.
   * When staging is enabled, modifications to entities are stored to a stage.
   * This ensures that arrays are not modified while iterating. Modifications are
   * merged back to the "main stage" when ecs_staging_end is invoked.
   *
   * @param world The world
   * @return Whether world is currently staged.
   */
  FLECS_API
  bool ecs_staging_begin(
      ecs_world_t *world);
  
  /** End staging.
   * If any data was staged, this operation will merge that data back to the main
   * stage.
   *
   * @param world The world
   */
  FLECS_API
  void ecs_staging_end(
      ecs_world_t *world);
  
  /** Manually merge.
   * When automerging is set to false, an application can invoke this operation to
   * force merging all stages.
   *
   * @param world The world.
   */
  FLECS_API
  void ecs_merge(
      ecs_world_t *world);
  
  /** Defer operations until end of frame. 
   * When this operation is invoked while iterating, operations inbetween the
   * defer_begin and defer_end operations are executed at the end of the frame.
   *
   * This operation is thread safe.
   * 
   * @param world The world.
   * @return true if world changed from non-deferred mode to deferred mode.
   */
  FLECS_API
  bool ecs_defer_begin(
      ecs_world_t *world);
  
  /** End block of operations to defer. 
   * See defer_begin.
   *
   * This operation is thread safe.
   *
   * @param world The world.
   * @return true if world changed from deferred mode to non-deferred mode.
   */
  FLECS_API
  bool ecs_defer_end(
      ecs_world_t *world);
  
  /** Enable / disable automerging.
   * When automerging is enabled, running a pipeline will automatically merge when
   * necessary. With automerging disabled, merging will not happen unless the
   * application manually invokes ecs_merge.
   *
   * @param world The world.
   */
  FLECS_API
  void ecs_set_automerge(
      ecs_world_t *world,
      bool auto_merge);
  
  /** @} */
  
  
  /**
   * @defgroup table_functions Public table operations
   * @{
   */
  
  /** Find or create table with specified component string. 
   * The provided string must be a comma-separated list of fully qualified 
   * component identifiers. The returned table will have the specified components.
   * Two lists that are the same but specify components in a different order will
   * return the same table.
   *
   * @param world The world.
   * @param type The components.
   * @return The new or existing table, or NULL if the string contains an error.
   */
  FLECS_API
  ecs_table_t* ecs_table_from_str(
      ecs_world_t *world,
      const char *type);
  
  /** Find or create table from type.
   * Same as ecs_table_from_str, but provides the type directly.
   *
   * @param world The world.
   * @param type The type.
   * @return The new or existing table.
   */
  FLECS_API
  ecs_table_t* ecs_table_from_type(
      ecs_world_t *world,
      ecs_type_t type);
  
  /** Get type for table.
   *
   * @param table The table.
   * @return The type of the table.
   */
  FLECS_API
  ecs_type_t ecs_table_get_type(
      ecs_table_t *table);
  
  /** Insert record into table.
   * This will create a new record for the table, which inserts a value for each
   * component. An optional entity and record can be provided.
   *
   * If a non-zero entity id is provided, a record must also be provided and vice
   * versa. The record must be created by the entity index. If the provided record 
   * is not created for the specified entity, the behavior will be undefined.
   *
   * If the provided record is not managed by the entity index, the behavior will
   * be undefined.
   *
   * The returned record contains a reference to the table and the table row. The
   * data pointed to by the record is guaranteed not to move unless one or more
   * rows are removed from this table. A row can be removed as result of a delete,
   * or by adding/removing components from an entity stored in the table.
   *
   * @param world The world.
   * @param table The table.
   * @param entity The entity.
   * @param record The entity-index record for the specified entity.
   * @return A record containing the table and table row.
   */
  FLECS_API
  ecs_record_t ecs_table_insert(
      ecs_world_t *world,
      ecs_table_t *table,
      ecs_entity_t entity,
      ecs_record_t *record);
  
  /** Returns the number of records in the table. 
   * This operation returns the number of records that have been populated through
   * the regular (entity) API as well as the number of records that have been
   * inserted using the direct access API.
   *
   * @param world The world.
   * @param table The table.
   * @return The number of records in a table.
   */
  FLECS_API
  int32_t ecs_table_count(
      ecs_table_t *table);
  
  /** @} */
  
  /* Optional modules */
  #ifdef FLECS_SYSTEM
  /**
   * @file system.h
   * @brief System module.
   *
   * The system module allows for creating and running systems. A system is a
   * query in combination with a callback function. In addition systems have
   * support for time management and can be monitored by the stats addon.
   */
  
  #ifdef FLECS_SYSTEM
  
  #ifndef FLECS_MODULE
  #define FLECS_MODULE
  #endif
  
  /**
   * @file module.h
   * @brief Module addon.
   *
   * The module addon allows for creating and importing modules. Flecs modules 
   * enable applications to organize components and systems into reusable units of
   * code that can easily be across projects.
   */
  
  #ifdef FLECS_MODULE
  
  #ifndef FLECS_MODULE_H
  #define FLECS_MODULE_H
  
  #ifdef __cplusplus
  extern "C" {
  #endif
  
  /** Import a module.
   * This operation will load a modules and store the public module handles in the
   * handles_out out parameter. The module name will be used to verify if the
   * module was already loaded, in which case it won't be reimported. The name
   * will be translated from PascalCase to an entity path (pascal.case) before the
   * lookup occurs.
   *
   * Module contents will be stored as children of the module entity. This 
   * prevents modules from accidentally defining conflicting identifiers. This is
   * enforced by setting the scope before and after loading the module to the 
   * module entity id.
   *
   * A more convenient way to import a module is by using the ECS_IMPORT macro.
   *
   * @param world The world.
   * @param module The module to load.
   * @param module_name The name of the module to load.
   * @param flags An integer that will be passed into the module import action.
   * @param handles_out A struct with handles to the module components/systems.
   * @param handles_size Size of the handles_out parameter.
   * @return The module entity.
   */
  FLECS_API
  ecs_entity_t ecs_import(
      ecs_world_t *world,
      ecs_module_action_t module,
      const char *module_name,
      void *handles_out,
      size_t handles_size);
  
  /* Import a module from a library.
   * Similar to ecs_import, except that this operation will attempt to load the 
   * module from a dynamic library.
   *
   * A library may contain multiple modules, which is why both a library name and
   * a module name need to be provided. If only a library name is provided, the
   * library name will be reused for the module name.
   *
   * The library will be looked up using a canonical name, which is in the same
   * form as a module, like `flecs.components.transform`. To transform this
   * identifier to a platform specific library name, the operation relies on the
   * module_to_dl callback of the os_api which the application has to override if
   * the default does not yield the correct library name.
   *
   * @param world The world.
   * @param library_name The name of the library to load.
   * @param module_name The name of the module to load.
   * @param flags The flags to pass to the module.
   */
  FLECS_API
  ecs_entity_t ecs_import_from_library(
      ecs_world_t *world,
      const char *library_name,
      const char *module_name);
  
  /** Define module
   */
  #define ECS_MODULE(world, id)\
      ECS_ENTITY_VAR(id) = ecs_new_module(world, 0, #id, sizeof(id), ECS_ALIGNOF(id));\
      ECS_VECTOR_STACK(FLECS__T##id, ecs_entity_t, &FLECS__E##id, 1);\
      id *handles = (id*)ecs_get_mut(world, ecs_typeid(id), id, NULL);\
      (void)ecs_typeid(id);\
      (void)ecs_type(id);\
      (void)handles;
  
  /** Wrapper around ecs_import.
   * This macro provides a convenient way to load a module with the world. It can
   * be used like this:
   *
   * ECS_IMPORT(world, FlecsSystemsPhysics, 0);
   * 
   * This macro will define entity and type handles for the component associated
   * with the module. An application can retrieve the module component like this:
   * 
   * FlecsSystemsPhysics m = ecs_get(world, EcsSingleton, FlecsSystemsPhysics);
   * 
   * The contents of a module component are module specific, although they
   * typically contain handles to the content of the module.
   */
  #define ECS_IMPORT(world, id) \
      id ecs_module(id);\
      char *id##__name = ecs_module_path_from_c(#id);\
      ECS_ENTITY_VAR(id) = ecs_import(\
          world, id##Import, id##__name, &ecs_module(id), sizeof(id));\
      ecs_os_free(id##__name);\
      ECS_VECTOR_STACK(FLECS__T##id, ecs_entity_t, &FLECS__E##id, 1);\
      id##ImportHandles(ecs_module(id));\
      (void)ecs_typeid(id);\
      (void)ecs_type(id);\
  
  /** Declare type variable */
  #define ECS_TYPE_VAR(id)\
      ecs_type_t ecs_type(id)
  
  /** Declare entity variable */
  #define ECS_ENTITY_VAR(id)\
      ecs_entity_t ecs_typeid(id)
  
  /** Utility macro for declaring a component inside a handles type */
  #define ECS_DECLARE_COMPONENT(id)\
      ECS_ENTITY_VAR(id);\
      ECS_TYPE_VAR(id)
  
  /** Utility macro for declaring an entity inside a handles type */
  #define ECS_DECLARE_ENTITY(id)\
      ecs_entity_t id;\
      ECS_TYPE_VAR(id)
  
  /** Utility macro for declaring a type inside a handles type */
  #define ECS_DECLARE_TYPE(id)\
      ECS_DECLARE_ENTITY(id)
  
  /** Utility macro for setting a component in a module function */
  #define ECS_SET_COMPONENT(id)\
      if (handles) handles->ecs_typeid(id) = ecs_typeid(id);\
      if (handles) handles->ecs_type(id) = ecs_type(id)
  
  /** Utility macro for setting an entity in a module function */
  #define ECS_SET_ENTITY(id)\
      if (handles) handles->id = id;
  
  /** Utility macro for setting a type in a module function */
  #define ECS_SET_TYPE(id)\
      if (handles) handles->id = id;\
      if (handles) handles->ecs_type(id) = ecs_type(id);
  
  #define ECS_EXPORT_COMPONENT(id)\
      ECS_SET_COMPONENT(id)
  
  #define ECS_EXPORT_ENTITY(id)\
      ECS_SET_ENTITY(id)
  
  #define ECS_EXPORT_TYPE(id)\
      ECS_SET_TYPE(id)
  
  /** Utility macro for importing a component */
  #define ECS_IMPORT_COMPONENT(handles, id)\
      ECS_ENTITY_VAR(id) = (handles).ecs_typeid(id); (void)ecs_typeid(id);\
      ECS_VECTOR_STACK(FLECS__T##id, ecs_entity_t, &FLECS__E##id, 1);\
      (void)ecs_typeid(id);\
      (void)ecs_type(id)
  
  /** Utility macro for importing an entity */
  #define ECS_IMPORT_ENTITY(handles, id)\
      ecs_entity_t id = (handles).id;\
      ECS_VECTOR_STACK(FLECS__T##id, ecs_entity_t, &id, 1);\
      (void)id;\
      (void)ecs_type(id)
  
  /** Utility macro for importing a type */
  #define ECS_IMPORT_TYPE(handles, id)\
      ecs_entity_t id = (handles).id;\
      ecs_type_t ecs_type(id) = (handles).ecs_type(id);\
      (void)id;\
      (void)ecs_type(id)
  
  #ifdef __cplusplus
  }
  #endif
  
  #endif
  
  #endif
  
  #ifndef FLECS_SYSTEMS_H
  #define FLECS_SYSTEMS_H
  
  #ifdef __cplusplus
  extern "C" {
  #endif
  
  
  ////////////////////////////////////////////////////////////////////////////////
  //// Components
  ////////////////////////////////////////////////////////////////////////////////
  
  FLECS_API
  extern ecs_type_t
      ecs_type(EcsTrigger),
      ecs_type(EcsSystem),
      ecs_type(EcsTickSource),
      ecs_type(EcsSignatureExpr),
      ecs_type(EcsSignature),
      ecs_type(EcsQuery),
      ecs_type(EcsIterAction),
      ecs_type(EcsContext);
  
  /* Component used to provide a tick source to systems */
  typedef struct EcsTickSource {
      bool tick;           /* True if providing tick */
      FLECS_FLOAT time_elapsed;  /* Time elapsed since last tick */
  } EcsTickSource;
  
  /* Signature expression */
  typedef struct EcsSignatureExpr {
      const char *expr;
  } EcsSignatureExpr;
  
  /* Parsed signature */
  typedef struct EcsSignature {
      ecs_sig_t signature;
  } EcsSignature;
  
  /* Query component */
  typedef struct EcsQuery {
      ecs_query_t *query;
  } EcsQuery;
  
  /* System action */
  typedef struct EcsIterAction {
      ecs_iter_action_t action;
  } EcsIterAction;
  
  /* System context */
  typedef struct EcsContext {
      const void *ctx;
  } EcsContext;
  
  
  ////////////////////////////////////////////////////////////////////////////////
  //// Systems API
  ////////////////////////////////////////////////////////////////////////////////
  
  /** Declare a systen.
   * This macro declares a system with the specified function, kind and signature. 
   * Systems are matched with entities that match the system signature. The system
   * signature is specified as a comma-separated list of column expressions, where
   * a column expression can be any of the following: 
   *
   * - A simple component identifier ('Position')
   * - An OR expression ('Position | Velocity')
   * - An optional expression ('?Position')
   * - A NOT expression ('!Position')
   * - An OWNED expression ('OWNED:Position')
   * - A SHARED expression ('SHARED:Position')
   * - A PARENT expression ('PARENT:Position')
   * - A CASCADE expression ('CASCADE:Position')
   * - An entity expression ('MyEntity:Position')
   * - An empty expression (':Position')
   * 
   * The systen kind specifies the phase in which the system is ran.
   *
   * Examples:
   * ECS_SYSTEM(world, Move, EcsOnUpdate, Position, Velocity, !AngularVelocity);
   * ECS_SYSTEM(world, Transform, EcsPostUpdate, PARENT:Transform, Transform);
   *
   * In these examples, 'Move' and 'Transform' must be valid identifiers to a C
   * function of the following signature:
   *
   * void Move(ecs_iter_t *it) { ... }
   *
   * Inside this function the system can access the data from the signature with
   * the ECS_COLUMN macro:
   *
   * ECS_COLUMN(it, Position, p, 1);
   * ECS_COLUMN(it, Velocity, v, 2);
   *
   * For more details on system signatures and phases see the Flecs manual.
   */
  
  #ifndef FLECS_LEGACY
  #define ECS_SYSTEM(world, name, kind, ...) \
      ecs_iter_action_t ecs_iter_action(name) = name;\
      ecs_entity_t name = ecs_new_system(world, 0, #name, kind, #__VA_ARGS__, ecs_iter_action(name));\
      (void)ecs_iter_action(name);\
      (void)name;
  #endif
  
  #define ECS_TRIGGER(world, name, kind, component) \
      ecs_entity_t __F##name = ecs_new_trigger(world, 0, #name, kind, #component, name);\
      ecs_entity_t name = __F##name;\
      (void)__F##name;\
      (void)name;
  
  /** Run a specific system manually.
   * This operation runs a single system manually. It is an efficient way to
   * invoke logic on a set of entities, as manual systems are only matched to
   * tables at creation time or after creation time, when a new table is created.
   *
   * Manual systems are useful to evaluate lists of prematched entities at
   * application defined times. Because none of the matching logic is evaluated
   * before the system is invoked, manual systems are much more efficient than
   * manually obtaining a list of entities and retrieving their components.
   *
   * An application may pass custom data to a system through the param parameter.
   * This data can be accessed by the system through the param member in the
   * ecs_iter_t value that is passed to the system callback.
   *
   * Any system may interrupt execution by setting the interrupted_by member in
   * the ecs_iter_t value. This is particularly useful for manual systems, where
   * the value of interrupted_by is returned by this operation. This, in
   * cominbation with the param argument lets applications use manual systems
   * to lookup entities: once the entity has been found its handle is passed to
   * interrupted_by, which is then subsequently returned.
   *
   * @param world The world.
   * @param system The system to run.
   * @param delta_time: The time passed since the last system invocation.
   * @param param A user-defined parameter to pass to the system.
   * @return handle to last evaluated entity if system was interrupted.
   */
  FLECS_API
  ecs_entity_t ecs_run(
      ecs_world_t *world,
      ecs_entity_t system,
      FLECS_FLOAT delta_time,
      void *param);
  
  /** Run system with offset/limit and type filter.
   * This operation is the same as ecs_run, but filters the entities that will be
   * iterated by the system.
   * 
   * Entities can be filtered in two ways. Offset and limit control the range of
   * entities that is iterated over. The range is applied to all entities matched
   * with the system, thus may cover multiple archetypes.
   * 
   * The type filter controls which entity types the system will evaluate. Only
   * types that contain all components in the type filter will be iterated over. A
   * type filter is only evaluated once per table, which makes filtering cheap if
   * the number of entities is large and the number of tables is small, but not as
   * cheap as filtering in the system signature.
   * 
   * @param world The world.
   * @param system The system to invoke.
   * @param delta_time: The time passed since the last system invocation.
   * @param filter A component or type to filter matched entities.
   * @param param A user-defined parameter to pass to the system.
   * @return handle to last evaluated entity if system was interrupted.
   */
  FLECS_API
  ecs_entity_t ecs_run_w_filter(
      ecs_world_t *world,
      ecs_entity_t system,
      FLECS_FLOAT delta_time,
      int32_t offset,
      int32_t limit,
      const ecs_filter_t *filter,
      void *param);
  
  /** System status change callback */
  typedef enum ecs_system_status_t {
      EcsSystemStatusNone = 0,
      EcsSystemEnabled,
      EcsSystemDisabled,
      EcsSystemActivated,
      EcsSystemDeactivated
  } ecs_system_status_t;
  
  typedef void (*ecs_system_status_action_t)(
      ecs_world_t *world,
      ecs_entity_t system,
      ecs_system_status_t status,
      void *ctx);
  
  /** Set system status action.
   * The status action is invoked whenever a system is enabled or disabled. Note
   * that a system may be enabled but may not actually match any entities. In this
   * case the system is enabled but not _active_.
   *
   * In addition to communicating the enabled / disabled status, the action also
   * communicates changes in the activation status of the system. A system becomes
   * active when it has one or more matching entities, and becomes inactive when
   * it no longer matches any entities.
   * 
   * A system switches between enabled and disabled when an application invokes the
   * ecs_enable operation with a state different from the state of the system, for
   * example the system is disabled, and ecs_enable is invoked with enabled: true.
   *
   * Additionally a system may switch between enabled and disabled when it is an
   * EcsOnDemand system, and interest is generated or lost for one of its [out]
   * columns.
   *
   * @param world The world.
   * @param system The system for which to set the action.
   * @param action The action.
   * @param ctx Context that will be passed to the action when invoked.
   */
  FLECS_API
  void ecs_set_system_status_action(
      ecs_world_t *world,
      ecs_entity_t system,
      ecs_system_status_action_t action,
      const void *ctx);
  
  /** Get the query object for a system.
   * Systems use queries under the hood. This enables an application to get access
   * to the underlying query object of a system. This can be useful when, for 
   * example, an application needs to enable sorting for a system.
   *
   * @param world The world.
   * @param system The system from which to obtain the query.
   * @return The query.
   */
  FLECS_API
  ecs_query_t* ecs_get_query(
      ecs_world_t *world,
      ecs_entity_t system);
  
  ////////////////////////////////////////////////////////////////////////////////
  //// System debug API
  ////////////////////////////////////////////////////////////////////////////////
  
  typedef struct ecs_dbg_system_t {
      ecs_entity_t system;   
      int32_t entities_matched_count;
      int32_t active_table_count;
      int32_t inactive_table_count;
      bool enabled;
      void *system_data;
  } ecs_dbg_system_t;
  
  FLECS_API
  int ecs_dbg_system(
      ecs_world_t *world,
      ecs_entity_t system,
      ecs_dbg_system_t *dbg_out);
  
  FLECS_API
  ecs_table_t* ecs_dbg_get_active_table(
      ecs_world_t *world,
      ecs_dbg_system_t *dbg,
      int32_t index);
  
  FLECS_API
  ecs_table_t* ecs_dbg_get_inactive_table(
      ecs_world_t *world,
      ecs_dbg_system_t *dbg,
      int32_t index);
  
  FLECS_API
  ecs_type_t ecs_dbg_get_column_type(
      ecs_world_t *world,
      ecs_entity_t system,
      int32_t column_index);
  
  FLECS_API
  bool ecs_dbg_match_entity(
      ecs_world_t *world,
      ecs_entity_t entity,
      ecs_entity_t system,
      ecs_match_failure_t *failure_info_out);
  
  
  ////////////////////////////////////////////////////////////////////////////////
  //// Module
  ////////////////////////////////////////////////////////////////////////////////
  
  /* Pipeline component is empty: components and tags in module are static */
  typedef struct FlecsSystem {
      int32_t dummy; 
  } FlecsSystem;
  
  FLECS_API
  void FlecsSystemImport(
      ecs_world_t *world);
  
  #define FlecsSystemImportHandles(handles)
  
  #ifdef __cplusplus
  }
  #endif
  
  #endif
  
  #endif
  #endif
  #ifdef FLECS_PIPELINE
  /**
   * @file pipeline.h
   * @brief Pipeline module.
   *
   * The pipeline module provides support for running systems automatically and
   * on multiple threads. A pipeline is a collection of tags that can be added to
   * systems. When ran, a pipeline will query for all systems that have the tags
   * that belong to a pipeline, and run them.
   *
   * The module defines a number of builtin tags (EcsPreUpdate, EcsOnUpdate, 
   * EcsPostUpdate etc.) that are registered with the builtin pipeline. The 
   * builtin pipeline is ran by default when calling ecs_progress(). An 
   * application can set a custom pipeline with the ecs_set_pipeline function.
   */
  
  #ifdef FLECS_PIPELINE
  
  #ifndef FLECS_SYSTEM
  #define FLECS_SYSTEM
  #endif
  
  
  #ifndef FLECS_PIPELINE_H
  #define FLECS_PIPELINE_H
  
  #ifdef __cplusplus
  extern "C" {
  #endif
  
  #ifndef FLECS_LEGACY
  #define ECS_PIPELINE(world, name, ...) \
      ecs_entity_t name = ecs_new_pipeline(world, 0, #name, #__VA_ARGS__);
  #endif
  
  /** Set a custom pipeline.
   * This operation sets the pipeline to run when ecs_progress is invoked.
   *
   * @param world The world.
   * @param pipeline The pipeline to set.
   */
  FLECS_API
  void ecs_set_pipeline(
      ecs_world_t *world,
      ecs_entity_t pipeline);       
  
  /** Get the current pipeline.
   * This operation gets the current pipeline.
   *
   * @param world The world.
   * @param pipeline The pipeline to set.
   */
  FLECS_API
  ecs_entity_t ecs_get_pipeline(
      ecs_world_t *world);  
  
  /** Progress a world.
   * This operation progresses the world by running all systems that are both
   * enabled and periodic on their matching entities.
   *
   * An application can pass a delta_time into the function, which is the time
   * passed since the last frame. This value is passed to systems so they can
   * update entity values proportional to the elapsed time since their last
   * invocation.
   *
   * When an application passes 0 to delta_time, ecs_progress will automatically
   * measure the time passed since the last frame. If an application does not uses
   * time management, it should pass a non-zero value for delta_time (1.0 is
   * recommended). That way, no time will be wasted measuring the time.
   *
   * @param world The world to progress.
   * @param delta_time The time passed since the last frame.
   * @return false if ecs_quit has been called, true otherwise.
   */
  FLECS_API
  bool ecs_progress(
      ecs_world_t *world,
      FLECS_FLOAT delta_time);   
  
  /** Set time scale.
   * Increase or decrease simulation speed by the provided multiplier.
   *
   * @param world The world.
   * @param scale The scale to apply (default = 1).
   */
  FLECS_API 
  void ecs_set_time_scale(
      ecs_world_t *world,
      FLECS_FLOAT scale);
  
  /** Reset world clock.
   * Reset the clock that keeps track of the total time passed in the simulation.
   *
   * @param world The world.
   */
  FLECS_API
  void ecs_reset_clock(
      ecs_world_t *world);
  
  /** Signal exit
   * This operation signals that the application should quit. It will cause
   * ecs_progress to return false.
   *
   * @param world The world to quit.
   */
  FLECS_API
  void ecs_quit(
      ecs_world_t *world);
  
  /** Deactivate systems that are not matched with tables.
   * By default Flecs deactivates systems that are not matched with any tables.
   * However, once a system has been matched with a table it remains activated, to
   * prevent systems from continuously becoming active and inactive.
   *
   * To re-deactivate systems, an application can invoke this function, which will
   * deactivate all systems that are not matched with any tables.
   *
   * @param world The world.
   */
  FLECS_API
  void ecs_deactivate_systems(
      ecs_world_t *world);
  
  
  ////////////////////////////////////////////////////////////////////////////////
  //// Threading
  ////////////////////////////////////////////////////////////////////////////////
  
  /** Set number of worker threads.
   * Setting this value to a value higher than 1 will start as many threads and
   * will cause systems to evenly distribute matched entities across threads. The
   * operation may be called multiple times to reconfigure the number of threads
   * used, but never while running a system / pipeline. */
  FLECS_API
  void ecs_set_threads(
      ecs_world_t *world,
      int32_t threads);
  
  ////////////////////////////////////////////////////////////////////////////////
  //// Module
  ////////////////////////////////////////////////////////////////////////////////
  
  /* Pipeline component is empty: components and tags in module are static */
  typedef struct FlecsPipeline {
      int32_t dummy; 
  } FlecsPipeline;
  
  FLECS_API
  void FlecsPipelineImport(
      ecs_world_t *world);
  
  #define FlecsPipelineImportHandles(handles)
  
  #ifdef __cplusplus
  }
  #endif
  
  #endif
  
  #endif
  #endif
  #ifdef FLECS_TIMER
  /**
   * @file timer.h
   * @brief Timer module.
   *
   * Timers can be used to trigger actions at periodic or one-shot intervals. They
   * are typically used together with systems and pipelines.
   */
  
  #ifdef FLECS_TIMER
  
  #ifndef FLECS_MODULE
  #define FLECS_MODULE
  #endif
  
  #ifndef FLECS_PIPELINE
  #define FLECS_PIPELINE
  #endif
  
  #ifndef FLECS_TIMER_H
  #define FLECS_TIMER_H
  
  
  #ifdef __cplusplus
  extern "C" {
  #endif
  
  
  ////////////////////////////////////////////////////////////////////////////////
  //// Components
  ////////////////////////////////////////////////////////////////////////////////
  
  FLECS_API
  extern ecs_type_t 
      ecs_type(EcsTimer),
      ecs_type(EcsRateFilter);
  
  /** Component used for timer functionality */
  typedef struct EcsTimer {
      FLECS_FLOAT timeout;         /* Timer timeout period */
      FLECS_FLOAT time;            /* Incrementing time value */
      int32_t fired_count;   /* Number of times ticked */
      bool active;           /* Is the timer active or not */
      bool single_shot;      /* Is this a single shot timer */
  } EcsTimer;
  
  /* Apply a rate filter to a tick source */
  typedef struct EcsRateFilter {
      ecs_entity_t src;
      int32_t rate;
      int32_t tick_count;
      FLECS_FLOAT time_elapsed;   /* Time elapsed since last tick */
  } EcsRateFilter;
  
  
  ////////////////////////////////////////////////////////////////////////////////
  //// Timer API
  ////////////////////////////////////////////////////////////////////////////////
  
  /** Set timer timeout.
   * This operation executes any systems associated with the timer after the
   * specified timeout value. If the entity contains an existing timer, the 
   * timeout value will be reset.
   *
   * Any entity can be used as a timer (including systems). If a timeout value is
   * set on a system entity, it will be automatically applied to that system.
   *
   * The timer is synchronous, and is incremented each frame by delta_time.
   *
   * @param world The world.
   * @param timer The timer for which to set the timeout (0 to create one).
   * @param timeout The timeout value.
   * @return The timer entity.
   */
  FLECS_API
  ecs_entity_t ecs_set_timeout(
      ecs_world_t *world,
      ecs_entity_t timer,
      FLECS_FLOAT timeout);
  
  /** Get current timeout value for the specified timer.
   * This operation returns the value set by ecs_set_timeout. If no timer is
   * active for this entity, the operation returns 0.
   *
   * After the timeout expires the timer component is removed from the entity.
   * This means that if ecs_get_timeout is invoked after the timer is expired, the
   * operation will return 0.
   *
   * @param world The world.
   * @param timer The timer.
   * @return The current timeout value, or 0 if no timer is active.
   */
  FLECS_API
  FLECS_FLOAT ecs_get_timeout(
      ecs_world_t *world,
      ecs_entity_t timer);
  
  /** Set timer interval.
   * This operation will continously invoke systems associated with the timer 
   * after the interval period expires. If the entity contains an existing timer,
   * the interval value will be reset.
   *
   * Any entity can be used as a timer (including systems). If an interval value
   * is set on a system entity, it will be automatically applied to that system.
   *
   * The timer is synchronous, and is incremented each frame by delta_time.
   *
   * @param world The world.
   * @param timer The timer for which to set the interval (0 to create one).
   * @param interval The interval value.
   * @return The timer entity.
   */
  FLECS_API
  ecs_entity_t ecs_set_interval(
      ecs_world_t *world,
      ecs_entity_t timer,
      FLECS_FLOAT interval);   
  
  /** Get current interval value for the specified timer.
   * This operation returns the value set by ecs_set_interval. If no timer is
   * active for this entity, the operation returns 0.
   *
   * @param world The world.
   * @param timer The timer for which to set the interval. If 0, an entity will be created.
   * @return The current interval value, or 0 if no timer is active.
   */
  FLECS_API
  FLECS_FLOAT ecs_get_interval(
      ecs_world_t *world,
      ecs_entity_t timer);
  
  /** Start timer.
   * This operation resets the timer and starts it with the specified timeout. The
   * entity must have the EcsTimer component (added by ecs_set_timeout and 
   * ecs_set_interval). If the entity does not have the EcsTimer component this
   * operation will assert.
   *
   * @param world The world.
   * @param timer The timer to start.
   */
  FLECS_API
  void ecs_start_timer(
      ecs_world_t *world,
      ecs_entity_t timer);
  
  /** Stop timer
   * This operation stops a timer from triggering. The entity must have the 
   * EcsTimer component or this operation will assert.
   *
   * @param world The world.
   * @param timer The timer to stop.
   */
  FLECS_API
  void ecs_stop_timer(
      ecs_world_t *world,
      ecs_entity_t timer);
  
  /** Set rate filter.
   * This operation sets the source and rate for a rate filter. A rate filter
   * samples another tick source (or frames, if none provided) and ticks when the
   * number of sampled ticks equals the rate.
   *
   * @param world The world.
   * @param filter The filter entity (0 to create one).
   * @param rate The rate to apply.
   * @param source The tick source (0 to use frames)
   * @return The filter entity.
   */
  FLECS_API
  ecs_entity_t ecs_set_rate_filter(
      ecs_world_t *world,
      ecs_entity_t filter,
      int32_t rate,
      ecs_entity_t source);
  
  /** Assign tick source to system.
   * This operation associates a system with a tick source. If the system is both 
   * active and enabled at the moment the tick source fires, it will be executed.
   * If no tick source is associated with a system, it will be invoked every 
   * frame.
   *
   * To disassociate a tick source from a system, use 0 for the tick_source 
   * parameter.
   *
   * Timer and rate filter entities are valid tick sources. An application can
   * also create its own tick source by setting the EcsTickSource component on an
   * entity.
   *
   * If an entity without the EcsTickSource component is provided as tick source,
   * the system will not be executed.
   *
   * @param world The world.
   * @param system The system to associate with the timer.
   * @param timer The timer to associate with the system.
   */ 
  FLECS_API
  void ecs_set_tick_source(
      ecs_world_t *world,
      ecs_entity_t system,
      ecs_entity_t tick_source);
  
  
  ////////////////////////////////////////////////////////////////////////////////
  //// Module
  ////////////////////////////////////////////////////////////////////////////////
  
  /* Timers module component */
  typedef struct FlecsTimer {
      int32_t dummy;
  } FlecsTimer;
  
  FLECS_API
  void FlecsTimerImport(
      ecs_world_t *world);
  
  #define FlecsTimerImportHandles(handles)
  
  #ifdef __cplusplus
  }
  #endif
  
  #endif
  
  #endif
  #endif
  
  /* Optional addons */
  #ifdef FLECS_BULK
  /**
   * @file bulk.h
   * @brief Bulk operations operate on all entities that match a provided filter.
   */
  
  #ifdef FLECS_BULK
  
  #ifndef FLECS_BULK_H
  #define FLECS_BULK_H
  
  #ifdef __cplusplus
  extern "C" {
  #endif
  
  /** Add an entity to entities matching a filter.
   * This operation is the same as ecs_add_entity, but is applied to all entities
   * that match the provided filter.
   *
   * @param world The world.
   * @param entity_add The entity to add.
   * @param filter The filter.
   */
  FLECS_API
  void ecs_bulk_add_entity(
      ecs_world_t *world,
      ecs_entity_t entity_add,
      const ecs_filter_t *filter);
  
  /** Add a type to entities matching a filter.
   * This operation is the same as ecs_add_type but is applied to all entities
   * that match the provided filter.
   *
   * @param world The world.
   * @param type The type to add.
   * @param filter The filter.
   */
  FLECS_API
  void ecs_bulk_add_type(
      ecs_world_t *world,
      ecs_type_t type,
      const ecs_filter_t *filter);
  
  /** Add a component / type / tag to entities matching a filter.
   * This operation is the same as ecs_add but is applied to all entities
   * that match the provided filter.
   *
   * @param world The world.
   * @param type The component, type or tag to add.
   * @param filter The filter.
   */
  #define ecs_bulk_add(world, type, filter)\
      ecs_bulk_add_type(world, ecs_type(type), filter)
  
  /** Removes an entity from entities matching a filter.
   * This operation is the same as ecs_remove_entity, but is applied to all 
   * entities that match the provided filter.
   *
   * @param world The world.
   * @param entity_remove The entity to remove.
   * @param filter The filter.
   */
  FLECS_API
  void ecs_bulk_remove_entity(
      ecs_world_t *world,
      ecs_entity_t entity_remove,
      const ecs_filter_t *filter);
  
  /** Remove a type from entities matching a filter.
   * This operation is the same as ecs_remove_type but is applied to all entities
   * that match the provided filter.
   *
   * @param world The world.
   * @param type The type to remove.
   * @param filter The filter.
   */
  FLECS_API
  void ecs_bulk_remove_type(
      ecs_world_t *world,
      ecs_type_t type,
      const ecs_filter_t *filter);
  
  /** Add a component / type / tag to entities matching a filter.
   * This operation is the same as ecs_remove but is applied to all entities
   * that match the provided filter.
   *
   * @param world The world.
   * @param type The component, type or tag to remove.
   * @param filter The filter.
   */
  #define ecs_bulk_remove(world, type, filter)\
      ecs_bulk_remove_type(world, ecs_type(type), filter)
  
  /** Add / remove type from entities matching a filter.
   * Combination of ecs_bulk_add_type and ecs_bulk_remove_type.
   *
   * @param world The world.
   * @param to_add The type to add.
   * @param to_remove The type to remove.
   * @param filter The filter.
   */
  FLECS_API
  void ecs_bulk_add_remove_type(
      ecs_world_t *world,
      ecs_type_t to_add,
      ecs_type_t to_remove,
      const ecs_filter_t *filter);
  
  /** Add / remove component, type or tag from entities matching a filter.
   * Combination of ecs_bulk_add and ecs_bulk_remove.
   *
   * @param world The world.
   * @param to_add The component, type or tag to add.
   * @param to_remove The component, type or tag to remove.
   * @param filter The filter.
   */
  #define ecs_bulk_add_remove(world, to_add, to_remove, filter)\
      ecs_bulk_add_remove_type(world, ecs_type(to_add), ecs_type(to_remove), filter)
  
  /** Delete entities matching a filter.
   * This operation is the same as ecs_delete, but applies to all entities that
   * match a filter.
   *
   * @param world The world.
   * @param filter The filter.
   */
  FLECS_API
  void ecs_bulk_delete(
      ecs_world_t *world,
      const ecs_filter_t *filter);
  
  #ifdef __cplusplus
  }
  #endif
  
  #endif
  
  #endif
  #endif
  #ifdef FLECS_DBG
  /**
   * @file dbg.h
   * @brief The debug addon enables requesting internals from entities and tables.
   */
  
  #ifdef FLECS_DBG
  
  #ifndef FLECS_DBG_H
  #define FLECS_DBG_H
  
  #ifdef __cplusplus
  extern "C" {
  #endif
  
  /* Unstable API */
  
  typedef struct ecs_dbg_entity_t {
      ecs_entity_t entity;
      ecs_table_t *table;
      ecs_type_t type;
      int32_t row;
      bool is_watched;
  } ecs_dbg_entity_t;
  
  typedef struct ecs_dbg_table_t {
      ecs_table_t *table;
      ecs_type_t type;
      ecs_type_t shared;
      ecs_type_t container;
      ecs_type_t parent_entities;
      ecs_type_t base_entities;     
      ecs_vector_t *systems_matched;
      ecs_entity_t *entities;
      int32_t entities_count;
  } ecs_dbg_table_t;
  
  FLECS_API
  void ecs_dbg_entity(
      ecs_world_t *world, 
      ecs_entity_t entity, 
      ecs_dbg_entity_t *dbg_out);
  
  FLECS_API
  ecs_table_t *ecs_dbg_find_table(
      ecs_world_t *world,
      ecs_type_t type);
  
  FLECS_API
  ecs_table_t *ecs_dbg_get_table(
      ecs_world_t *world,
      int32_t index);
  
  FLECS_API
  bool ecs_dbg_filter_table(
      ecs_world_t *world,
      ecs_table_t *table,
      ecs_filter_t *filter);
  
  FLECS_API
  void ecs_dbg_table(
      ecs_world_t *world, 
      ecs_table_t *table, 
      ecs_dbg_table_t *dbg_out);
  
  #ifdef __cplusplus
  }
  #endif
  
  #endif
  
  #endif
  #endif
  #ifdef FLECS_MODULE
  #endif
  #ifdef FLECS_QUEUE
  /**
   * @file queue.h
   * @brief Queue datastructure.
   *
   * The queue data structure implements a fixed-size ringbuffer. It is not used
   * by the flecs core, but is used by flecs-hub modules.
   */
  
  #ifdef FLECS_QUEUE
  
  #ifndef FLECS_QUEUE_H_
  #define FLECS_QUEUE_H_
  
  #ifdef __cplusplus
  extern "C" {
  #endif
  
  typedef struct ecs_queue_t ecs_queue_t;
  
  FLECS_API
  ecs_queue_t* _ecs_queue_new(
      ecs_size_t elem_size,
      int16_t offset,
      int32_t elem_count);
  
  #define ecs_queue_new(T, elem_count)\
      _ecs_queue_new(ECS_VECTOR_T(T), elem_count)
  
  FLECS_API
  ecs_queue_t* _ecs_queue_from_array(
      ecs_size_t elem_size,
      int16_t offset,
      int32_t elem_count,
      void *array);
  
  #define ecs_queue_from_array(T, elem_count, array)\
      _ecs_queue_from_array(ECS_VECTOR_T(T), elem_count, array)
  
  FLECS_API
  void* _ecs_queue_push(
      ecs_queue_t *queue,
      ecs_size_t elem_size,
      int16_t offset);
  
  #define ecs_queue_push(queue, T)\
      (T*)_ecs_queue_push(queue, ECS_VECTOR_T(T))
  
  FLECS_API
  void* _ecs_queue_get(
      ecs_queue_t *queue,
      ecs_size_t elem_size,
      int16_t offset,
      int32_t index);
  
  #define ecs_queue_get(queue, T, index)\
      (T*)_ecs_queue_get(queue, ECS_VECTOR_T(T), index)
  
  #define ecs_queue_get_t(vector, size, alignment, index) \
      _ecs_queue_get(vector, ECS_VECTOR_U(size, alignment), index)
  
  FLECS_API
  void* _ecs_queue_last(
      ecs_queue_t *queue,
      ecs_size_t elem_size,
      int16_t offset);
  
  #define ecs_queue_last(queue, T)\
      (T*)_ecs_queue_last(queue, ECS_VECTOR_T(T))
  
  FLECS_API
  int32_t ecs_queue_index(
      ecs_queue_t *queue);
  
  FLECS_API
  int32_t ecs_queue_count(
      ecs_queue_t *queue);
  
  FLECS_API
  void ecs_queue_free(
      ecs_queue_t *queue);
  
  #ifdef __cplusplus
  }
  #endif
  
  #endif
  
  #endif
  #endif
  #ifdef FLECS_READER_WRITER
  /**
   * @file reader_writer.h
   * @brief Blob serializer addon.
   *
   * The blos serializer addon allows an application to serialize the state of a 
   * world to a blob (a flat byte buffer). The addon contains a reader and writer
   * API. The reader reads from a world and serializes it to N fixed-size buffers.
   * The writer reads from N fixed-size buffers and writes to the world.
   *
   * The current limitations of the serializer are:
   * - only POD types
   * - no support for switch types and component enabling/disabling
   */
  
  #ifdef FLECS_READER_WRITER
  
  #ifndef FLECS_READER_WRITER_H
  #define FLECS_READER_WRITER_H
  
  #ifdef __cplusplus
  extern "C" {
  #endif 
  
  typedef enum ecs_blob_header_kind_t {
      EcsStreamHeader,
  
      /* Stream states */
      EcsTableSegment,
      EcsFooterSegment,
  
      /* Table segment */
      EcsTableHeader,
      EcsTableTypeSize,
      EcsTableType,
      EcsTableSize,
      EcsTableColumn,
      EcsTableColumnHeader,
      EcsTableColumnSize,
      EcsTableColumnData,
  
      /* Name column (EcsName) */
      EcsTableColumnNameHeader,
      EcsTableColumnNameLength,
      EcsTableColumnName,
  
      EcsStreamFooter  
  } ecs_blob_header_kind_t;
  
  typedef struct ecs_table_reader_t {
      ecs_blob_header_kind_t state;
  
      int32_t table_index;
      ecs_table_t *table;
      ecs_data_t *data;
  
      /* Current index in type */
      ecs_size_t type_written;
      ecs_type_t type;
  
      /* Current column */
      ecs_vector_t *column_vector;
      int32_t column_index;
      int32_t total_columns;
  
      /* Keep track of how much of the component column has been written */
      void *column_data;
      int16_t column_size;
      int16_t column_alignment;
      ecs_size_t column_written;
  
      /* Keep track of row when writing non-blittable data */
      int32_t row_index;
      int32_t row_count;
  
      /* Keep track of how much of an entity name has been written */
      const char *name;
      ecs_size_t name_len;
      ecs_size_t name_written;
  
      bool has_next_table;
  } ecs_table_reader_t;
  
  typedef struct ecs_reader_t {
      ecs_world_t *world;
      ecs_blob_header_kind_t state;
      ecs_iter_t data_iter;
      ecs_iter_next_action_t data_next;
      ecs_iter_t component_iter;
      ecs_iter_next_action_t component_next;
      ecs_table_reader_t table;
  } ecs_reader_t;
  
  typedef struct ecs_name_writer_t {
      char *name;
      int32_t written;
      int32_t len;
      int32_t max_len;
  } ecs_name_writer_t;
  
  typedef struct ecs_table_writer_t {
      ecs_blob_header_kind_t state;
  
      ecs_table_t *table;
      ecs_vector_t *column_vector;
  
      /* Keep state for parsing type */
      int32_t type_count;
      int32_t type_max_count;
      ecs_size_t type_written;
      ecs_entity_t *type_array;
      
      int32_t column_index;
      int16_t column_size;
      int16_t column_alignment;
      ecs_size_t column_written;
      void *column_data;
  
      int32_t row_count;
      int32_t row_index;
      ecs_name_writer_t name; 
  } ecs_table_writer_t;
  
  typedef struct ecs_writer_t {
      ecs_world_t *world;
      ecs_blob_header_kind_t state;
      ecs_table_writer_t table;
      int error;
  } ecs_writer_t;
  
  /** Initialize a reader.
   * A reader serializes data in a world to a sequence of bytes that can be stored
   * in a file or sent across a network. 
   *
   * @param world The world to serialize.
   * @return The reader.
   */
  FLECS_API
  ecs_reader_t ecs_reader_init(
      ecs_world_t *world);
  
  /** Initialize a snapshot reader.
   * A snapshot reader serializes data in a snapshot to a sequence of bytes that 
   * can be stored in a file or sent across a network. A snapshot reader has as
   * advantage that serialization can take place asynchronously while the world
   * is progressing.
   *
   * @param world The world in which the snapshot is taken.
   * @param iter Iterator to the data to be serialized.
   * @return The reader.
   */
  FLECS_API
  ecs_reader_t ecs_reader_init_w_iter(
      ecs_iter_t *iter,
      ecs_iter_next_action_t next);
  
  /** Read from a reader.
   * This operation reads a specified number of bytes from a reader and stores it
   * in the specified buffer. When there are no more bytes to read from the reader
   * the operation will return 0, otherwise it will return the number of bytes
   * read.
   *
   * The specified buffer must be at least as big as the specified size, and the
   * specified size must be a multiple of 4.
   *
   * @param buffer The buffer in which to store the read bytes.
   * @param size The maximum number of bytes to read.
   * @param reader The reader from which to read the bytes.
   * @return The number of bytes read.
   */ 
  FLECS_API
  int32_t ecs_reader_read(
      char *buffer,
      int32_t size,
      ecs_reader_t *reader);
  
  /** Initialize a writer.
   * A writer deserializes data from a sequence of bytes into a world. This 
   * enables applications to restore data from disk or the network.
   *
   * The provided world must be either empty or compatible with the data to
   * deserialize, where compatible means that the serialized component ids and 
   * sizes must match exactly with those in the world. Errors can occur if a world
   * is provided in which components have been declared in a different order, or
   * when components have different type definitions.
   *
   * @param world The world in which to deserialize the data.
   * @return The writer. 
   */
  FLECS_API
  ecs_writer_t ecs_writer_init(
      ecs_world_t *world);
  
  /** Write to a writer.
   * This operation writes a specified number of bytes from a specified buffer
   * into the writer. The writer will restore the deserialized data into the 
   * original serialized entities. The write operation may be invoked multiple
   * times with partial buffers, which allows applications to use static buffers
   * when reading from, for example, a file or the network.
   *
   * The data contained in the buffers must have been serialized with the
   * ecs_reader_read operation. If the data does not match the expected format, or
   * the data contains conflicts with the world, the operation will fail. The
   * data must be provided in the same order as produced by ecs_reader_read,
   * but the used buffer size does not have to be the same as the one used by
   * ecs_reader_read. The buffer size must be a multiple of 4.
   * 
   * @param buffer The buffer to deserialize.
   * @param size The maximum number of bytes.
   * @param writer The writer to write to.
   * @return Zero if success, non-zero if failed to deserialize.
   */
  FLECS_API
  int32_t ecs_writer_write(
      const char *buffer,
      int32_t size,
      ecs_writer_t *writer);
  
  #ifdef __cplusplus
  }
  #endif     
  
  #endif
  
  #endif
  #endif
  #ifdef FLECS_SNAPSHOT
  /**
   * @file snapshot.h
   * @brief Snapshot addon.
   *
   * A snapshot records the state of a world in a way so that it can be restored
   * later. Snapshots work with POD components and non-POD components, provided
   * that the appropriate lifecycle actions are registered for non-POD components.
   *
   * A snapshot is tightly coupled to a world. It is not possible to restore a
   * snapshot from world A into world B.
   */
  
  #ifdef FLECS_SNAPSHOT
  
  #ifndef FLECS_SNAPSHOT_H
  #define FLECS_SNAPSHOT_H
  
  #ifdef __cplusplus
  extern "C" {
  #endif
  
  /** Create a snapshot.
   * This operation makes a copy of all component in the world that matches the 
   * specified filter.
   *
   * @param world The world to snapshot.
   * @param return The snapshot.
   */
  FLECS_API
  ecs_snapshot_t* ecs_snapshot_take(
      ecs_world_t *world);
  
  /** Create a filtered snapshot.
   * This operation is the same as ecs_snapshot_take, but accepts an iterator so
   * an application can control what is stored by the snapshot. 
   *
   * @param iter An iterator to the data to be stored by the snapshot.
   * @param next A function pointer to the next operation for the iterator.
   * @param return The snapshot.
   */
  FLECS_API
  ecs_snapshot_t* ecs_snapshot_take_w_iter(
      ecs_iter_t *iter,
      ecs_iter_next_action_t action);
  
  /** Restore a snapshot.
   * This operation restores the world to the state it was in when the specified
   * snapshot was taken. A snapshot can only be used once for restoring, as its
   * data replaces the data that is currently in the world.
   * This operation also resets the last issued entity handle, so any calls to
   * ecs_new may return entity ids that have been issued before restoring the 
   * snapshot.
   *
   * The world in which the snapshot is restored must be the same as the world in
   * which the snapshot is taken.
   *
   * @param world The world to restore the snapshot to.
   * @param snapshot The snapshot to restore. 
   */
  FLECS_API
  void ecs_snapshot_restore(
      ecs_world_t *world,
      ecs_snapshot_t *snapshot);
  
  /** Obtain iterator to snapshot data.
   *
   * @param snapshot The snapshot to iterate over.
   * @return Iterator to snapshot data. */
  FLECS_API
  ecs_iter_t ecs_snapshot_iter(
      ecs_snapshot_t *snapshot,
      const ecs_filter_t *filter);
  
  /** Progress snapshot iterator.
   * 
   * @param iter The snapshot iterator.
   * @return True if more data is available, otherwise false.
   */
  FLECS_API
  bool ecs_snapshot_next(
      ecs_iter_t *iter);
  
  
  /** Free snapshot resources.
   * This frees resources associated with a snapshot without restoring it.
   *
   * @param world The world.
   * @param snapshot The snapshot to free. 
   */
  FLECS_API
  void ecs_snapshot_free(
      ecs_snapshot_t *snapshot);
      
  #ifdef __cplusplus
  }
  #endif
  
  #endif
  
  #endif
  #endif
  /**
   * @file direct_access.h
   * @brief Low-level access to underlying data structures for best performance.
   *
   * This API allows for low-level direct access to tables and their columns. The
   * APIs primary intent is to provide fast primitives for new operations. It is
   * not recommended to use the API directly in application code, as invoking the
   * API in an incorrect way can lead to a corrupted datastore.
   */
  
  #ifndef FLECS_DIRECT_ACCESS_H_
  #define FLECS_DIRECT_ACCESS_H_
  
  #ifdef __cplusplus
  extern "C" {
  #endif
  
  #ifdef FLECS_DIRECT_ACCESS
  
  /** Find the index of a column in a table.
   * Table columns are stored in the order of their respective component ids. As
   * this is not trivial for an application to deduce, this operation returns the
   * index of a column in a table for a given component. This index can be used
   * in other table operations to identify a column.
   *
   * The returned index is determined separately for each table. Indices obtained
   * for one table should not be used for another table.
   *
   * @param table The table.
   * @param component The component for which to retrieve the column index.
   * @return The column index, or -1 if the table does not have the component.
   */
  FLECS_API
  int32_t ecs_table_find_column(
      ecs_table_t *table,
      ecs_entity_t component);
  
  /** Get table column.
   * This operation returns the pointer to a column array. A column contains all
   * the data for a component for the provided table in a contiguous array.
   *
   * The returned pointer is not stable, and may change when a table needs to
   * resize its arrays, for example in order to accomodate for more records.
   *
   * @param table The table.
   * @param column The column index.
   * @return Vector that contains the column array.
   */
  FLECS_API
  ecs_vector_t* ecs_table_get_column(
      ecs_table_t *table,
      int32_t column);
  
  /** Set table column.
   * This operation enables an application to set a component column for a table.
   * After the operation the column is owned by the table. Any operations that
   * change the column after this operation can cause undefined behavior.
   *
   * Care must be taken that all columns in a table have the same number of
   * elements. If one column has less elements than another, the behavior is
   * undefined. The operation will not check if the assigned column is of the same
   * size as other columns, as this would prevent an application from assigning
   * a set of different columns to a table of a different size.
   *
   * Setting a column will not delete the previous column. It is the 
   * responsibility of the application to ensure that the old column is deleted
   * properly (using ecs_table_delete_column).
   *
   * The provided vector must have the same element size and alignment as the
   * target column. If the size and/or alignment do not match, the behavior will
   * be undefined. In debug mode the operation may assert.
   *
   * If the provided vector is NULL, the table will ensure that a vector is
   * created for the provided column. If a vector exists that is not of the
   * same size as the entities vector, it will be resized to match.
   *
   * @param world The world.
   * @param table The table.
   * @param column The column index.
   * @param vector The column data to assing.
   */
  FLECS_API
  ecs_vector_t* ecs_table_set_column(
      ecs_world_t *world,
      ecs_table_t *table,
      int32_t column,
      ecs_vector_t *vector);
  
  /** Get the vector containing entity ids for the table.
   * This operation obtains the vector with entity ids for the current table. Each
   * entity id is associated with one record, and ids are stored in the same order
   * as the table records. The element type of the vector is ecs_entity_t.
   *
   * @param table The table.
   * @return The vector containing the table's entities.
   */
  FLECS_API
  ecs_vector_t* ecs_table_get_entities(
      ecs_table_t *table);
  
  /** Get the vector containing pointers to entity records.
   * A table stores cached pointers to entity records for fast access. This 
   * operation provides direct access to the vector. The element type of the
   * vector is ecs_record_t*.
   *
   * @param table The table.
   * @return The vector containing the entity records.
   */ 
  FLECS_API
  ecs_vector_t* ecs_table_get_records(
      ecs_table_t *table);
  
  /** Clear records.
   * This operation clears records for a world so that they no longer point to a
   * table. This is useful to ensure that a world is left in a consistent state
   * after moving data to destination world. 
   *
   * @param records The vector with record pointers
   */
  FLECS_API
  void ecs_records_clear(
      ecs_vector_t *records);
  
  /** Initialize records.
   * This operation ensures entity records are updated to the provided table. 
   *
   * @param world The world.
   * @param entities The vector with entity identifiers.
   * @param records The vector with record pointers.
   * @param table The table in which the entities are stored.
   */
  FLECS_API
  void ecs_records_update(
      ecs_world_t *world,
      ecs_vector_t *entities,
      ecs_vector_t *records,
      ecs_table_t *table);
  
  /** Set the vector containing entity ids for the table.
   * This operation sets the vector with entity ids for a table. In addition the
   * operation also requires setting a vector with pointers to records. The
   * record pointers in the vector need to be managed by the entity index. If they
   * are not, this can cause undefined behavior.
   *
   * The provided vectors must have the same number of elements as the number of
   * records in the table. If the element count is not the same, this causes
   * undefined behavior.
   *
   * A table must have an entity and record vector, even if the table does not
   * contain entities. For each record that is not an entity, the entity vector
   * should contain 0, and the record vector should contain NULL.
   *
   * @param table The table.
   * @param entities The entity vector.
   * @param records The record vector.
   */
  FLECS_API
  void ecs_table_set_entities(
      ecs_table_t *table,
      ecs_vector_t *entities,
      ecs_vector_t *records);
  
  /** Delete a column.
   * This operation frees the memory of a table column and will invoke the
   * component destructor if registered.
   *
   * The provided vector does not need to be the same as the vector in the table.
   * The reason the table must be provided is so that the operation can retrieve
   * the correct destructor for the component. If the component does not have a
   * destructor, an application can alternatively delete the vector directly.
   *
   * If the specified vector is NULL, the column of the table will be removed and
   * the table will be updated to no longer point at the column. If an explicit
   * column is provided, the table is not modified. If a column is deleted that is
   * still being pointed to by a table, behavior is undefined. It is the
   * responsibility of the application to ensure that a table no longer points to
   * a deleted column, by using ecs_table_set_column.
   *
   * Simultaneously, if this operation is used to delete a table column, the
   * application should make sure that if the table contains other columns, they
   * are either also deleted, or that the deleted column is replaced by a column
   * of the same size. Note that this also goes for the entity and record vectors,
   * they should have the same number of elements as the other columns.
   *
   * The vector must be of the same component as the specified column. If the
   * vector is not of the same component, behavior will be undefined. In debug
   * mode the API may assert, though it may not always be able to detect a
   * mismatching vector/column.
   *
   * After this operation the vector should no longer be used by the application.
   *
   * @param table The table.
   * @param column The column index.
   * @param vector The column vector to delete.
   */
  FLECS_API
  void ecs_table_delete_column(
      ecs_world_t *world,
      ecs_table_t *table,
      int32_t column,
      ecs_vector_t *vector);
  
  /** Find a record for a given entity.
   * This operation finds an existing record in the entity index for a given
   * entity. The returned pointer is stable for the lifecycle of the world and can
   * be used as argument for the ecs_record_update operation.
   *
   * The returned record (if found) points to the adminstration that relates an
   * entity id to a table. Updating the value of the returned record will cause
   * operations like ecs_get and ecs_has to look in the updated table.
   *
   * Updating this record to a table in which the entity is not stored causes
   * undefined behavior.
   *
   * When the entity has never been created or is not alive this operation will
   * return NULL.
   *
   * @param world The world.
   * @param entity The entity.
   * @return The record that belongs to the entity, or NULL if not found.
   */
  FLECS_API
  ecs_record_t* ecs_record_find(
      ecs_world_t *world,
      ecs_entity_t entity);
  
  /** Same as ecs_record_find, but creates record if it doesn't exist.
   * If an entity id has not been created with ecs_new_*, this function can be
   * used to ensure that a record exists for an entity id. If the provided id
   * already exists in the world, the operation will return the existing record.
   *
   * @param world The world.
   * @param entity The entity for which to retrieve the record.
   * @return The (new or existing) record that belongs to the entity.
   */
  FLECS_API
  ecs_record_t* ecs_record_ensure(
      ecs_world_t *world,
      ecs_entity_t entity);
  
  /** Get value from record.
   * This operation gets a component value from a record. The provided column
   * index must match the table of the record.
   *
   * @param r The record.
   * @param column The column index of the component to get.
   */ 
  FLECS_API
  void* ecs_record_get_column(
      ecs_record_t *r,
      int32_t column,
      size_t size);
  
  /** Copy value to a component for a record.
   * This operation sets the component value of a single component for a record.
   * If the component type has a copy action it will be used, otherwise the value
   * be memcpyd into the component array.
   *
   * The provided record does not need to be managed by the entity index but does
   * need to point to a valid record in the table. If the provided index is
   * outside of the range indicating the number of records in the table, behavior
   * is undefined. In debug mode it will cause the operation to assert.
   *
   * @param world The world.
   * @param r The record to set.
   * @param column The column index of the component to set.
   * @param size The size of the component.
   * @param value Pointer to the value to copy.
   */
  FLECS_API
  void ecs_record_copy_to(
      ecs_world_t *world,
      ecs_record_t *r,
      int32_t column,
      size_t size,
      const void *value,
      int32_t count);
  
  /** Memcpy value to a component for a record.
   * Same as ecs_record_copy_to, except that this operation will always use
   * memcpy. This operation should only be used for components that can be safely
   * memcpyd. If the operation is used for a component that has a copy or move
   * action, the behavior is undefined. In debug mode the operation may assert.
   *
   * @param world The world.
   * @param r The record to set.
   * @param column The column index of the component to set.
   * @param size The size of the component.
   * @param value Pointer to the value to move. 
   */
  FLECS_API
  void ecs_record_copy_pod_to(
      ecs_world_t *world,
      ecs_record_t *r,
      int32_t column,
      size_t size,
      const void *value,
      int32_t count);
  
  /** Move value to a component for a record.
   * Same as ecs_record_copy_to, except that it uses the move action. If the 
   * component has no move action the value will be memcpyd into the component 
   * array. After this operation the application can no longer assume that the 
   * value passed into the function is valid.
   *
   * @param world The world.
   * @param r The record to set.
   * @param column The column index of the component to set.
   * @param size The size of the component.
   * @param value Pointer to the value to move.
   */
  FLECS_API
  void ecs_record_move_to(
      ecs_world_t *world,
      ecs_record_t *r,
      int32_t column,
      size_t size,
      void *value,
      int32_t count);
  
  #endif
  
  #ifdef __cplusplus
  }
  #endif
  
  #endif
  #ifdef FLECS_STATS
  /**
   * @file stats.h
   * @brief Statistics addon.
   *
   * The statistics addon enables an application to obtain detailed metrics about
   * the storage, systems and operations of a world.
   */
  
  #ifdef FLECS_STATS
  
  #ifndef FLECS_STATS_H
  #define FLECS_STATS_H
  
  
  #ifdef __cplusplus
  extern "C" {
  #endif
  
  #define ECS_STAT_WINDOW (60)
  
  /** Simple value that indicates current state */
  typedef struct ecs_gauge_t {
      float avg[ECS_STAT_WINDOW];
      float min[ECS_STAT_WINDOW];
      float max[ECS_STAT_WINDOW];
  } ecs_gauge_t;
  
  /* Monotonically increasing counter */
  typedef struct ecs_counter_t {
      ecs_gauge_t rate;                          /**< Keep track of deltas too */
      float value[ECS_STAT_WINDOW];
  } ecs_counter_t;
  
  typedef struct ecs_world_stats_t {
      /* Allows struct to be initialized with {0} */
      int32_t dummy_;
  
      ecs_gauge_t entity_count;                 /**< Number of entities */
      ecs_gauge_t component_count;              /**< Number of components */
      ecs_gauge_t query_count;                  /**< Number of queries */
      ecs_gauge_t system_count;                 /**< Number of systems */
      ecs_gauge_t table_count;                  /**< Number of tables */
      ecs_gauge_t empty_table_count;            /**< Number of empty tables */
      ecs_gauge_t singleton_table_count;        /**< Number of singleton tables. Singleton tables are tables with just a single entity that contains itself */
      ecs_gauge_t matched_entity_count;         /**< Number of entities matched by queries */
      ecs_gauge_t matched_table_count;          /**< Number of tables matched by queries */
  
      /* Deferred operations */
      ecs_counter_t new_count;
      ecs_counter_t bulk_new_count;
      ecs_counter_t delete_count;
      ecs_counter_t clear_count;
      ecs_counter_t add_count;
      ecs_counter_t remove_count;
      ecs_counter_t set_count;
      ecs_counter_t discard_count;
  
      /* Timing */
      ecs_counter_t world_time_total_raw;       /**< Actual time passed since simulation start (first time progress() is called) */
      ecs_counter_t world_time_total;           /**< Simulation time passed since simulation start. Takes into account time scaling */
      ecs_counter_t frame_time_total;           /**< Time spent processing a frame. Smaller than world_time_total when load is not 100% */
      ecs_counter_t system_time_total;          /**< Time spent on processing systems. */
      ecs_counter_t merge_time_total;           /**< Time spent on merging deferred actions. */
      ecs_gauge_t fps;                          /**< Frames per second. */
      ecs_gauge_t delta_time;                   /**< Delta_time. */
      
      /* Frame data */
      ecs_counter_t frame_count_total;          /**< Number of frames processed. */
      ecs_counter_t merge_count_total;          /**< Number of merges executed. */
      ecs_counter_t pipeline_build_count_total; /**< Number of system pipeline rebuilds (occurs when an inactive system becomes active). */
      ecs_counter_t systems_ran_frame;          /**< Number of systems ran in the last frame. */
  
      /** Current position in ringbuffer */
      int32_t t;
  } ecs_world_stats_t;
  
  /* Statistics for a single query (use ecs_get_query_stats) */
  typedef struct ecs_query_stats_t {
      ecs_gauge_t matched_table_count;       /**< Number of matched non-empty tables. This is the number of tables 
                                              * iterated over when evaluating a query. */    
  
      ecs_gauge_t matched_empty_table_count; /**< Number of matched empty tables. Empty tables are not iterated over when
                                              * evaluating a query. */
      
      ecs_gauge_t matched_entity_count;      /**< Number of matched entities across all tables */
  
      /** Current position in ringbuffer */
      int32_t t; 
  } ecs_query_stats_t;
  
  /** Statistics for a single system (use ecs_get_system_stats) */
  typedef struct ecs_system_stats_t {
      ecs_query_stats_t query_stats;
      ecs_counter_t time_spent;       /**< Time spent processing a system */
      ecs_counter_t invoke_count;     /**< Number of times system is invoked */
      ecs_gauge_t active;             /**< Whether system is active (is matched with >0 entities) */
      ecs_gauge_t enabled;            /**< Whether system is enabled */
  } ecs_system_stats_t;
  
  /** Statistics for all systems in a pipeline. */
  typedef struct ecs_pipeline_stats_t {
      /** Vector with system ids of all systems in the pipeline. The systems are
       * stored in the order they are executed. Merges are represented by a 0. */
      ecs_vector_t *systems;
  
      /** Map with system statistics. For each system in the systems vector, an
       * entry in the map exists of type ecs_system_stats_t. */
      ecs_map_t *system_stats;
  } ecs_pipeline_stats_t;
  
  /** Get world statistics.
   * Obtain statistics for the provided world. This operation loops several times
   * over the tables in the world, and can impact application performance.
   *
   * @param world The world.
   * @param stats Out parameter for statistics.
   */
  FLECS_API void ecs_get_world_stats(
      ecs_world_t *world,
      ecs_world_stats_t *stats);
  
  /** Print world statistics.
   * Print statistics obtained by ecs_get_world_statistics and in the
   * ecs_world_info_t struct.
   * 
   * @param world The world.
   * @param stats The statistics to print.
   */
  FLECS_API void ecs_dump_world_stats(
      ecs_world_t *world,
      const ecs_world_stats_t *stats);
  
  /** Get query statistics.
   * Obtain statistics for the provided query.
   *
   * @param world The world.
   * @param query The query.
   * @param stats Out parameter for statistics.
   */
  FLECS_API void ecs_get_query_stats(
      ecs_world_t *world,
      ecs_query_t *query,
      ecs_query_stats_t *s);
  
  #ifdef FLECS_SYSTEM
  /** Get system statistics.
   * Obtain statistics for the provided system.
   *
   * @param world The world.
   * @param system The system.
   * @param stats Out parameter for statistics.
   * @return true if success, false if not a system.
   */
  FLECS_API bool ecs_get_system_stats(
      ecs_world_t *world,
      ecs_entity_t system,
      ecs_system_stats_t *stats);
  #endif
  
  #ifdef FLECS_PIPELINE
  /** Get pipeline statistics.
   * Obtain statistics for the provided pipeline.
   *
   * @param world The world.
   * @param pipeline The pipeline.
   * @param stats Out parameter for statistics.
   * @return true if success, false if not a pipeline.
   */
  FLECS_API bool ecs_get_pipeline_stats(
      ecs_world_t *world,
      ecs_entity_t pipeline,
      ecs_pipeline_stats_t *stats);
  #endif
  
  FLECS_API void ecs_gauge_reduce(
      ecs_gauge_t *dst,
      int32_t t_dst,
      ecs_gauge_t *src,
      int32_t t_src);
  
  
  #ifdef __cplusplus
  }
  #endif
  
  #endif
  
  #endif
  #endif
  
  #ifdef __cplusplus
  }
  
  #ifndef FLECS_NO_CPP
  #ifndef FLECS_LEGACY
  /**
   * @file flecs.hpp
   * @brief Flecs C++ API.
   *
   * This is a C++11 wrapper around the Flecs C API.
   */
  
  #pragma once
  
  #include <string>
  #include <sstream>
  #include <array>
  #include <functional>
  
  // Macros so that C++ new calls can allocate using ecs_os_api memory allocation functions
  // Rationale:
  //  - Using macros here instead of a templated function bc clients might override ecs_os_malloc
  //    to contain extra debug info like source tracking location. Using a template function
  //    in that scenario would collapse all source location into said function vs. the
  //    actual call site
  //  - FLECS_PLACEMENT_NEW(): exists to remove any naked new calls/make it easy to identify any regressions
  //    by grepping for new/delete
  #define FLECS_PLACEMENT_NEW(_ptr, _type)  ::new(flecs::_::placement_new_tag, _ptr) _type
  #define FLECS_NEW(_type)                  FLECS_PLACEMENT_NEW(ecs_os_malloc(sizeof(_type)), _type)
  #define FLECS_DELETE(_ptr)          \
    do {                              \
      if (_ptr) {                     \
        flecs::_::destruct_obj(_ptr); \
        ecs_os_free(_ptr);            \
      }                               \
    } while (false)
  
  namespace flecs {
  namespace _
  {
  // Dummy Placement new tag to disambiguate from any other operator new overrides
  struct placement_new_tag_t{};
  constexpr placement_new_tag_t placement_new_tag{};
  template<class Ty> inline void destruct_obj(Ty* _ptr) { _ptr->~Ty(); }
  }
  }
  
  inline void* operator new(size_t,   flecs::_::placement_new_tag_t, void* _ptr) noexcept { return _ptr; }
  inline void  operator delete(void*, flecs::_::placement_new_tag_t, void*)      noexcept {              }
  
  namespace flecs {
  
  ////////////////////////////////////////////////////////////////////////////////
  //// Forward declarations and types
  ////////////////////////////////////////////////////////////////////////////////
  
  using world_t = ecs_world_t;
  using entity_t = ecs_entity_t;
  using type_t = ecs_type_t;
  using snapshot_t = ecs_snapshot_t;
  using filter_t = ecs_filter_t;
  using query_t = ecs_query_t;
  
  class world;
  class snapshot;
  class entity;
  class type;
  class iter;
  class filter;
  class filter_iterator;
  class child_iterator;
  class world_filter;
  class snapshot_filter;
  
  template<typename ... Components>
  class query_iterator;
  
  template<typename ... Components>
  class query;
  
  template<typename ... Components>
  class system;
  
  enum match_kind {
      MatchAll = EcsMatchAll,
      MatchAny = EcsMatchAny,
      MatchExact = EcsMatchExact
  };
  
  namespace _
  {
  template <typename T>
  class component_info;
  
  template <typename ...Components>
  bool pack_args_to_string(
      world_t *world, 
      std::stringstream& str, 
      bool is_each = false);
  }
  
  ////////////////////////////////////////////////////////////////////////////////
  //// Builtin components and tags 
  ////////////////////////////////////////////////////////////////////////////////
  
  /* Builtin components */
  using Component = EcsComponent;
  using ComponentLifecycle = EcsComponentLifecycle;
  using Trigger = EcsTrigger;
  using Type = EcsType;
  using Name = EcsName;
  using Timer = EcsTimer;
  using RateFilter = EcsRateFilter;
  using TickSource = EcsTickSource;
  using SignatureExpr = EcsSignatureExpr;
  using Signature = EcsSignature;
  using Query = EcsQuery;
  using ViewAction = EcsIterAction;
  using Context = EcsContext;
  
  /* Builtin tag ids */
  static const ecs_entity_t Module = EcsModule;
  static const ecs_entity_t Prefab = EcsPrefab;
  static const ecs_entity_t Hidden = EcsHidden;
  static const ecs_entity_t Disabled = EcsDisabled;
  static const ecs_entity_t DisabledIntern = EcsDisabledIntern;
  static const ecs_entity_t Inactive = EcsInactive;
  static const ecs_entity_t OnDemand = EcsOnDemand;
  static const ecs_entity_t Monitor = EcsMonitor;
  static const ecs_entity_t Pipeline = EcsPipeline;
  
  /* Trigger tags */
  static const ecs_entity_t OnAdd = EcsOnAdd;
  static const ecs_entity_t OnRemove = EcsOnRemove;
  static const ecs_entity_t OnSet = EcsOnSet;
  
  /* Builtin pipeline tags */
  static const ecs_entity_t PreFrame = EcsPreFrame;
  static const ecs_entity_t OnLoad = EcsOnLoad;
  static const ecs_entity_t PostLoad = EcsPostLoad;
  static const ecs_entity_t PreUpdate = EcsPreUpdate;
  static const ecs_entity_t OnUpdate = EcsOnUpdate;
  static const ecs_entity_t OnValidate = EcsOnValidate;
  static const ecs_entity_t PostUpdate = EcsPostUpdate;
  static const ecs_entity_t PreStore = EcsPreStore;
  static const ecs_entity_t OnStore = EcsOnStore;
  static const ecs_entity_t PostFrame = EcsPostFrame;
  
  /** Builtin entity ids */
  static const ecs_entity_t World = EcsWorld;
  static const ecs_entity_t Singleton = EcsSingleton;
  
  /** Builtin roles */
  static const ecs_entity_t Childof = ECS_CHILDOF;
  static const ecs_entity_t Instanceof = ECS_INSTANCEOF;
  static const ecs_entity_t Trait = ECS_TRAIT;
  static const ecs_entity_t Switch = ECS_SWITCH;
  static const ecs_entity_t Case = ECS_CASE;
  static const ecs_entity_t Owned = ECS_OWNED;
  
  ////////////////////////////////////////////////////////////////////////////////
  
  /** Unsafe wrapper class around a column.
   * This class can be used when a system does not know the type of a column at
   * compile time.
   */
  class unsafe_column {
  public:
      unsafe_column(void* array, size_t size, size_t count, bool is_shared = false)
          : m_array(array)
          , m_size(size)
          , m_count(count) 
          , m_is_shared(is_shared) {}
  
      /** Return element in component array.
       * This operator may only be used if the column is not shared.
       * 
       * @param index Index of element.
       * @return Reference to element.
       */
      void* operator[](size_t index) {
          ecs_assert(index < m_count, ECS_COLUMN_INDEX_OUT_OF_RANGE, NULL);
          ecs_assert(!m_is_shared, ECS_INVALID_PARAMETER, NULL);
          return ECS_OFFSET(m_array, m_size * index);
      }
  
      /** Return whether component is set.
       * If the column is optional, this method may return false.
       * 
       * @return True if component is set, false if component is not set.
       */
      bool is_set() const {
          return m_array != nullptr;
      }
  
      /** Return whether component is shared.
       * If the column is shared, this method returns true.
       * 
       * @return True if component is shared, false if component is owned.
       */
      bool is_shared() const {
          return m_is_shared;
      }
  
  protected:
      void* m_array;
      size_t m_size;
      size_t m_count;
      bool m_is_shared;        
  };
  
  /** Wrapper class around a column.
   * 
   * @tparam T component type of the column.
   */
  template <typename T>
  class column {
  public:
      /** Create column from component array.
       *
       * @param array Pointer to the component array.
       * @param count Number of elements in component array.
       * @param is_shared Is the component shared or not.
       */
      column(T* array, size_t count, bool is_shared = false)
          : m_array(array)
          , m_count(count) 
          , m_is_shared(is_shared) {}
  
      /** Create column from iterator.
       *
       * @param iter Iterator object.
       * @param column Index of the signature of the query being iterated over.
       */
      column(iter &iter, int column);
  
      /** Return element in component array.
       * This operator may only be used if the column is not shared.
       * 
       * @param index Index of element.
       * @return Reference to element.
       */
      T& operator[](size_t index) {
          ecs_assert(index < m_count, ECS_COLUMN_INDEX_OUT_OF_RANGE, NULL);
          ecs_assert(!index || !m_is_shared, ECS_INVALID_PARAMETER, NULL);
          ecs_assert(m_array != nullptr, ECS_COLUMN_INDEX_OUT_OF_RANGE, NULL);
          return m_array[index];
      }
  
      /** Return first element of component array.
       * This operator is typically used when the column is shared.
       * 
       * @return Reference to the first element.
       */
      T* operator->() {
          ecs_assert(m_array != nullptr, ECS_COLUMN_INDEX_OUT_OF_RANGE, NULL);
          return m_array;
      }
  
      /** Return whether component is set.
       * If the column is optional, this method may return false.
       * 
       * @return True if component is set, false if component is not set.
       */
      bool is_set() const {
          return m_array != nullptr;
      }
  
      /** Return whether component is shared.
       * If the column is shared, this method returns true.
       * 
       * @return True if component is shared, false if component is owned.
       */
      bool is_shared() const {
          return m_is_shared;
      }
  
  protected:
      T* m_array;
      size_t m_count;
      bool m_is_shared;
  };
  
  
  ////////////////////////////////////////////////////////////////////////////////
  
  namespace _ {
  
  /** Similar to flecs::column, but abstracts away from shared / owned columns.
   * 
   * @tparam T component type of the column.
   */
  template <typename T, typename = void>
  class any_column { };
  
  template <typename T>
  class any_column<T, typename std::enable_if<std::is_pointer<T>::value == true>::type > final : public column<typename std::remove_pointer<T>::type> {
  public:
      any_column(T array, std::size_t count, bool is_shared = false)
          : column<typename std::remove_pointer<T>::type>(array, count, is_shared) { }
  
      T operator[](size_t index) {
          if (!this->m_is_shared) {
              ecs_assert(index < this->m_count, ECS_COLUMN_INDEX_OUT_OF_RANGE, NULL);
              if (this->m_array) {
                  return &this->m_array[index];
              } else {
                  return nullptr;
              }
          } else {
              return &this->m_array[0];
          }
      }   
  };
  
  template <typename T>
  class any_column<T, typename std::enable_if<std::is_pointer<T>::value == false>::type> final : public column<T> {
  public:
      any_column(T* array, std::size_t count, bool is_shared = false)
          : column<T>(array, count, is_shared) { }
  
      T& operator[](size_t index) {
          if (!this->m_is_shared) {
              ecs_assert(index < this->m_count, ECS_COLUMN_INDEX_OUT_OF_RANGE, NULL);
              return this->m_array[index];
          } else {
              return this->m_array[0];
          }
      }   
  };
  
  ////////////////////////////////////////////////////////////////////////////////
  
  /** Iterate over an integer range (used to iterate over entity range).
   *
   * @tparam Type of the iterator
   */
  template <typename T>
  class range_iterator
  {
  public:
      explicit range_iterator(T value)
          : m_value(value){}
  
      bool operator!=(range_iterator const& other) const
      {
          return m_value != other.m_value;
      }
  
      T const& operator*() const
      {
          return m_value;
      }
  
      range_iterator& operator++()
      {
          ++m_value;
          return *this;
      }
  
  private:
      T m_value;
  };
  
  } // namespace _
  
  
  ////////////////////////////////////////////////////////////////////////////////
  
  /** Class that enables iterating over table columns.
   */
  class iter final {
      using row_iterator = _::range_iterator<size_t>;
  public:
      /** Construct iterator from C iterator object.
       * This operation is typically not invoked directly by the user.
       *
       * @param it Pointer to C iterator.
       */
      iter(const ecs_iter_t *it) : m_iter(it) { 
          m_begin = 0;
          m_end = static_cast<std::size_t>(it->count);
      }
  
      row_iterator begin() const {
          return row_iterator(m_begin);
      }
  
      row_iterator end() const {
          return row_iterator(m_end);
      }
  
      /** Obtain handle to current system. 
       */
      flecs::entity system() const;
  
      /** Obtain current world. 
       */
      flecs::world world() const;
  
      /** Number of entities to iterate over. 
       */
      size_t count() const {
          return static_cast<size_t>(m_iter->count);
      }
  
      /** Number of columns in iteator.
       */
      int32_t column_count() const {
          return m_iter->column_count;
      }
  
      /** Size of column data type.
       *
       * @param col The column id.
       */
      size_t column_size(int32_t col) const {
          return ecs_column_size(m_iter, col);
      }    
  
      /** Return delta_time of current frame. 
       */
      FLECS_FLOAT delta_time() const {
          return m_iter->delta_time;
      }
  
      /** Return time elapsed since last time system was invoked.
       */
      FLECS_FLOAT delta_system_time() const {
          return m_iter->delta_system_time;
      }
  
      /** Return total time passed in simulation.
       */
      FLECS_FLOAT world_time() const {
          return m_iter->world_time;
      }
  
      /** Returns whether column is shared.
       * 
       * @param col The column id.
       */
      bool is_shared(int32_t col) const {
          return !ecs_is_owned(m_iter, col);
      }
  
      /** Returns whether column is owned.
       * 
       * @param col The column id.
       */
      bool is_owned(int32_t col) const {
          return ecs_is_owned(m_iter, col);
      }    
  
      /** Returns whether column is set.
       * 
       * @param col The column id.
       */
      bool is_set(int32_t col) const {
          return ecs_column_w_size(m_iter, 0, col) != NULL;
      }
      
      /** Access param field. 
       * The param field contains the value assigned to flecs::Context, or the
       * value passed to the `param` argument when invoking system::run.
       */
      void* param() {
          return m_iter->param;
      }
  
      /** Returns whether column is readonly.
       *
       * @param col The column id.
       */
      bool is_readonly(int32_t col) const {
          return ecs_is_readonly(m_iter, col);
      }
  
      /** Obtain column source (0 if self)
       *
       * @param col The column id.
       */    
      flecs::entity column_source(int32_t col) const;
  
      /** Obtain component/tag entity of column.
       *
       * @param col The column id.
       */
      flecs::entity column_entity(int32_t col) const;
  
      /** Obtain type of column 
       *
       * @param col The column id.
       */
      flecs::type column_type(int32_t col) const;
  
      /** Obtain entity being iterated over for row.
       *
       * @param row Row being iterated over.
       */
      flecs::entity entity(size_t row) const;
  
      /** Obtain type of table being iterated over.
       */
      type table_type() const;
  
      /** Obtain the total number of tables the iterator will iterate over.
       */
      int32_t table_count() const {
          return m_iter->table_count;
      }
  
      /** Obtain the total number of inactive tables the query is matched with.
       */
      int32_t inactive_table_count() const {
          return m_iter->inactive_table_count;
      }
  
      /** Obtain untyped pointer to table column.
       *
       * @param table_column Id of table column (corresponds with location in table type).
       * @return Pointer to table column.
       */
      void* table_column(int32_t col) const {
          return ecs_table_column(m_iter, col);
      }
  
      /** Obtain typed pointer to table column.
       * If the table does not contain a column with the specified type, the
       * function will assert.
       *
       * @tparam T Type of the table column.
       */
      template <typename T>
      flecs::column<T> table_column() const {
          auto type = ecs_iter_type(m_iter);
          auto col = ecs_type_index_of(type, _::component_info<T>::id());
          ecs_assert(col != -1, ECS_INVALID_PARAMETER, NULL);
          return flecs::column<T>(static_cast<T*>(ecs_table_column(m_iter, col)), 
              static_cast<std::size_t>(m_iter->count), false);
      }
  
      /** Obtain column with const type.
       * If the specified column id does not match with the provided type, the
       * function will assert.
       *
       * @tparam T Type of the column.
       * @param col The column id.
       * @return The component column.
       */
      template <typename T,
          typename std::enable_if<std::is_const<T>::value, void>::type* = nullptr>
      flecs::column<T> column(int32_t col) const {
          return get_column<T>(col);
      }
  
      /** Obtain column with non-const type.
       * If the specified column id does not match with the provided type or if
       * the column is readonly, the function will assert.
       *
       * @tparam T Type of the column.
       * @param col The column id.
       * @return The component column.
       */
      template <typename T,
          typename std::enable_if<std::is_const<T>::value == false, void>::type* = nullptr>
      flecs::column<T> column(int32_t col) const {
          ecs_assert(!ecs_is_readonly(m_iter, col), ECS_COLUMN_ACCESS_VIOLATION, NULL);
          return get_column<T>(col);
      }  
  
      /** Obtain unsafe column.
       * Unsafe columns are required when a system does not know at compile time
       * which component will be passed to it. 
       *
       * @param col The column id. 
       */
      flecs::unsafe_column column(int32_t col) const {
          return get_unsafe_column(col);
      }
  
      /** Obtain owned column.
       * Same as iter::column, but ensures that column is owned.
       *
       * @tparam Type of the column.
       * @param col The column id.
       * @return The component column.
       */
      template <typename T>
      flecs::column<T> owned(int32_t col) const {
          ecs_assert(!!ecs_is_owned(m_iter, col), ECS_COLUMN_IS_SHARED, NULL);
          return this->column<T>(col);
      }
  
      /** Obtain shared column.
       * Same as iter::column, but ensures that column is shared.
       *
       * @tparam Type of the column.
       * @param col The column id.
       * @return The component column.
       */
      template <typename T>
      const T& shared(int32_t col) const {
          ecs_assert(ecs_column_entity(m_iter, col) == _::component_info<T>::id(m_iter->world), ECS_COLUMN_TYPE_MISMATCH, NULL);
          ecs_assert(!ecs_is_owned(m_iter, col), ECS_COLUMN_IS_NOT_SHARED, NULL);
          return *static_cast<T*>(ecs_column_w_size(m_iter, sizeof(T), col));
      }
  
      /** Obtain single const element of owned or shared column.
       * If the specified column id does not match with the provided type the
       * function will assert.    
       *
       * @tparam Type of the element.
       * @param col The column id.
       * @param row The current row.
       * @return The component element.
       */
      template <typename T,
          typename std::enable_if<std::is_const<T>::value, void>::type* = nullptr>    
      T& element(int32_t col, int32_t row) const {
          return get_element<T>(col, row);
      }
  
      /** Obtain single const element of owned or shared column.
       * If the specified column id does not match with the provided type or if
       * the column is readonly, the function will assert.
       *
       * @tparam Type of the element.
       * @param col The column id.
       * @param row The current row.
       * @return The component element.
       */
      template <typename T,
          typename std::enable_if<std::is_const<T>::value == false, void>::type* = nullptr>
      T& element(int32_t col, int32_t row) const {
          ecs_assert(!ecs_is_readonly(m_iter, col), ECS_COLUMN_ACCESS_VIOLATION, NULL);
          return get_element<T>(col, row);
      }
  
  private:
      /* Get column, check if correct type is used */
      template <typename T>
      flecs::column<T> get_column(int32_t column_id) const {
  #ifndef NDEBUG
          ecs_entity_t column_entity = ecs_column_entity(m_iter, column_id);
          ecs_assert(column_entity & ECS_TRAIT || column_entity & ECS_SWITCH || 
              column_entity & ECS_CASE ||
              column_entity == _::component_info<T>::id(m_iter->world), 
              ECS_COLUMN_TYPE_MISMATCH, NULL);
  #endif
  
          size_t count;
          bool is_shared = !ecs_is_owned(m_iter, column_id);
  
          /* If a shared column is retrieved with 'column', there will only be a
           * single value. Ensure that the application does not accidentally read
           * out of bounds. */
          if (is_shared) {
              count = 1;
          } else {
              /* If column is owned, there will be as many values as there are
               * entities. */
              count = static_cast<size_t>(m_iter->count);
          }
          
          return flecs::column<T>(
              static_cast<T*>(ecs_column_w_size(m_iter, sizeof(T), column_id)), 
              count, is_shared);
      } 
  
      flecs::unsafe_column get_unsafe_column(int32_t column_id) const {
          size_t count;
          size_t size = ecs_column_size(m_iter, column_id);
          bool is_shared = !ecs_is_owned(m_iter, column_id);
  
          /* If a shared column is retrieved with 'column', there will only be a
           * single value. Ensure that the application does not accidentally read
           * out of bounds. */
          if (is_shared) {
              count = 1;
          } else {
              /* If column is owned, there will be as many values as there are
               * entities. */
              count = static_cast<size_t>(m_iter->count);
          }
  
          return flecs::unsafe_column(ecs_column_w_size(m_iter, 0, column_id), size, count, is_shared);
      }       
  
      /* Get single field, check if correct type is used */
      template <typename T>
      T& get_element(int32_t col, int32_t row) const {
          ecs_assert(ecs_column_entity(m_iter, col) == _::component_info<T>::id(m_iter->world), ECS_COLUMN_TYPE_MISMATCH, NULL);
          return *static_cast<T*>(ecs_element_w_size(m_iter, sizeof(T), col, row));
      }       
  
      const ecs_iter_t *m_iter;
      std::size_t m_begin;
      std::size_t m_end;
  };
  
  template <typename T>
  inline column<T>::column(iter &iter, int32_t col) {
      *this = iter.column<T>(col);
  }
  
  
  ////////////////////////////////////////////////////////////////////////////////
  
  /** The world.
   * The world is the container of all ECS data and systems. If the world is
   * deleted, all data in the world will be deleted as well.
   */
  class world final {
  public:
      /** Create world.
       */
      world() 
          : m_world( ecs_init() )
          , m_owned( true ) { init_builtin_components(); }
  
      /** Create world with command line arguments.
       * Currently command line arguments are not interpreted, but they may be
       * used in the future to configure Flecs parameters.
       */
      world(int argc, char *argv[])
          : m_world( ecs_init_w_args(argc, argv) )
          , m_owned( true ) { init_builtin_components(); }
  
      /** Create world from C world.
       */
      explicit world(world_t *w) 
          : m_world( w ) 
          , m_owned( false ) { }
  
      /** Not allowed to copy a world. May only take a reference. 
       */
      world(const world& obj) = delete;
  
      world(world&& obj) {
          m_world = obj.m_world;
          m_owned = obj.m_owned;
          obj.m_world = nullptr;
          obj.m_owned = false;
      }
  
      /** Not allowed to copy a world. May only take a reference.
       */
      world& operator=(const world& obj) = delete;
  
      world& operator=(world&& obj) {
          this->~world();
  
          m_world = obj.m_world;
          m_owned = obj.m_owned;
          obj.m_world = nullptr;
          obj.m_owned = false;
          return *this;
      }
      
      ~world() { 
          if (m_owned && m_world) {
              ecs_fini(m_world); 
          }
      }
  
      /** Obtain pointer to C world object.
       */
      world_t* c_ptr() const {
          return m_world;
      }
  
      /** Enable tracing.
       *
       * @param level The tracing level.
       */
      static void enable_tracing(int level) {
          ecs_tracing_enable(level);
      }
  
      /** Progress world, run all systems.
       *
       * @param delta_time Custom delta_time. If 0 is provided, Flecs will automatically measure delta_tiem.
       */
      bool progress(FLECS_FLOAT delta_time = 0.0) const {
          return ecs_progress(m_world, delta_time);
      }
  
      /** Defer operations until end of frame. 
       * When this operation is invoked while iterating, operations inbetween the
       * defer_begin and defer_end operations are executed at the end of the frame.
       *
       * This operation is thread safe.
       */
      bool defer_begin() {
          return ecs_defer_begin(m_world);
      }
  
      /** End block of operations to defer. 
       * See defer_begin.
       *
       * This operation is thread safe.
       */
      bool defer_end() {
          return ecs_defer_end(m_world);
      }
  
      /** Set number of threads.
       * This will distribute the load evenly across the configured number of 
       * threads for each system.
       *
       * @param threads Number of threads.
       */
      void set_threads(std::int32_t threads) const {
          ecs_set_threads(m_world, threads);
      }
  
      /** Get number of threads.
       *
       * @return Number of configured threads.
       */
      std::int32_t get_threads() const {
          return ecs_get_threads(m_world);
      }
  
      /** Get index of current thread.
       *
       * @return Unique index for current thread.
       */
      std::int32_t get_thread_index() const {
          return ecs_get_thread_index(m_world);
      }
  
      /** Set target FPS
       * This will ensure that the main loop (world::progress) does not run faster
       * than the specified frames per second.
       *
       * @param target_fps Target frames per second.
       */
      void set_target_fps(FLECS_FLOAT target_fps) const {
          ecs_set_target_fps(m_world, target_fps);
      }
  
      /** Get target FPS
       *
       * @return Configured frames per second.
       */
      FLECS_FLOAT get_target_fps() const {
          const ecs_world_info_t *stats = ecs_get_world_info(m_world);
          return stats->target_fps;
      }
  
      /** Get tick
       *
       * @return Monotonically increasing frame count.
       */
      std::int32_t get_tick() const {
          const ecs_world_info_t *stats = ecs_get_world_info(m_world);
          return stats->frame_count_total;
      }
  
      /** Set timescale
       *
       * @return Monotonically increasing frame count.
       */
      void set_time_scale(FLECS_FLOAT mul) const {
          ecs_set_time_scale(m_world, mul);
      }  
  
      /** Get timescale
       *
       * @return Monotonically increasing frame count.
       */
      FLECS_FLOAT get_time_scale() const {
          const ecs_world_info_t *stats = ecs_get_world_info(m_world);
          return stats->time_scale;
      }        
  
      /** Set world context.
       * Set a context value that can be accessed by anyone that has a reference
       * to the world.
       *
       * @param ctx The world context.
       */
      void set_context(void* ctx) const {
          ecs_set_context(m_world, ctx);
      }
  
      /** Get world context.
       *
       * @return The configured world context.
       */
      void* get_context() const {
          return ecs_get_context(m_world);
      }
  
      /** Preallocate memory for number of entities.
       * This function preallocates memory for the entity index.
       *
       * @param entity_count Number of entities to preallocate memory for.
       */
      void dim(std::int32_t entity_count) const {
          ecs_dim(m_world, entity_count);
      }
  
      /** Preallocate memory for type
       * This function preallocates memory for the component arrays of the
       * specified type.
       *
       * @param type Type to preallocate memory for.
       * @param entity_count Number of entities to preallocate memory for.
       */
      void dim_type(type_t t, std::int32_t entity_count) const {
          ecs_dim_type(m_world, t, entity_count);
      }
  
      /** Set entity range.
       * This function limits the range of issued entity ids between min and max.
       *
       * @param min Minimum entity id issued.
       * @param max Maximum entity id issued.
       */
      void set_entity_range(entity_t min, entity_t max) const {
          ecs_set_entity_range(m_world, min, max);
      }
  
      /** Enforce that operations cannot modify entities outside of range.
       * This function ensures that only entities within the specified range can
       * be modified. Use this function if specific parts of the code only are
       * allowed to modify a certain set of entities, as could be the case for
       * networked applications.
       *
       * @param enabled True if range check should be enabled, false if not.
       */
      void enable_range_check(bool enabled) const {
          ecs_enable_range_check(m_world, enabled);
      }
  
      /** Disables inactive systems.
       *
       * This removes systems that are not matched with any entities from the main
       * loop. Systems are only added to the main loop after they first match with
       * entities, but are not removed automatically.
       *
       * This function allows an application to manually disable inactive systems
       * which removes them from the main loop. Doing so will cause Flecs to
       * rebuild the pipeline in the next iteration.
       *
       * @param level The tracing level.
       */
      void deactivate_systems() {
          ecs_deactivate_systems(m_world);
      }    
  
      /** Lookup entity by name.
       * 
       * @param name Entity name.
       */
      flecs::entity lookup(const char *name) const;
  
      /** Lookup entity by name.
       *
       * @overload
       */    
      flecs::entity lookup(std::string& name) const;
  
      /** Set singleton component.
       */
      template <typename T>
      void set(T value) const;
  
      /** Get mut singleton component.
       */
      template <typename T>
      T* get_mut() const;
  
      /** Mark singleton component as modified.
       */
      template <typename T>
      void modified() const;
  
      /** Patch singleton component.
       */
      template <typename T>
      void patch(std::function<void(T&)> func) const;
  
      /** Get singleton component.
       */
      template <typename T>
      const T* get() const;
  
      /** Test if world has singleton component.
       */
      template <typename T>
      bool has() const;
  
      /** Remove singleton component.
       */
      template <typename T>
      void remove() const;
  
      /** Get id for type.
       */
      template <typename T>
      entity_t type_id() {
          return _::component_info<T>::id(m_world);
      }
  
      /** Get singleton entity for type.
       */
      template <typename T>
      flecs::entity singleton();
  
      /** Create alias for component.
       *
       * @tparam Component to create an alias for.
       * @param alias Alias for the component.
       */
      template <typename T>
      flecs::entity use(const char *alias = nullptr);
  
      /** Create alias for entity.
       *
       * @param name Name of the entity.
       * @param alias Alias for the entity.
       */
      flecs::entity use(const char *name, const char *alias = nullptr);    
  
      /** Create alias for entity.
       *
       * @param entity Entity for which to create the alias.
       * @param alias Alias for the entity.
       */
      void use(flecs::entity entity, const char *alias = nullptr);   
  
      /** Delete all entities matching a filter.
       *
       * @param filter The filter to use for matching.
       */
      void delete_entities(flecs::filter filter) const;
  
      /** Add component to all entities matching a filter.
       *
       * @tparam T The component to add.
       * @param filter The filter to use for matching.
       */
      template <typename T>
      void add(flecs::filter filter) const;
  
      /** Add type to all entities.
       *
       * @param type The type to add.
       */
      void add(flecs::type type) const;
  
      /** Add type to all entities matching a filter.
       *
       * @param type The type to add.
       * @param filter The filter to use for matching.
       */    
      void add(flecs::type type, flecs::filter filter) const;
  
      /** Add entity to all entities.
       *
       * @param entity The entity to add.
       */
      void add(flecs::entity entity) const;
  
      /** Add entity to all entities matching a filter.
       *
       * @param entity The entity to add.
       * @param filter The filter to use for matching.
       */    
      void add(flecs::entity entity, flecs::filter filter) const;
  
      /** Remove component from all entities matching a filter.
       *
       * @tparam T The component to remove.
       * @param filter The filter to use for matching.
       */    
      template <typename T>
      void remove(flecs::filter filter) const;
  
      /** Remove type from all entities.
       *
       * @param type The component to remove.
       */ 
      void remove(flecs::type type) const;
  
      /** Remove type from all entities matching a filter.
       *
       * @tparam T The component to remove.
       * @param filter The filter to use for matching.
       */     
      void remove(flecs::type type, flecs::filter filter) const;
  
      /** Remove entity from all entities.
       *
       * @param entity The entity to remove.
       */ 
      void remove(flecs::entity entity) const;
  
      /** Remove entity from all entities matching a filter.
       *
       * @param entity The entity to remove.
       * @param filter The filter to use for matching.
       */     
      void remove(flecs::entity entity, flecs::filter filter) const;
  
      /** Create iterable filter for entities in world.
       *
       * @param filter The filter to create.
       */ 
      world_filter filter(const flecs::filter& filter) const;
  
      flecs::filter_iterator begin() const;
      flecs::filter_iterator end() const;
  
      /** Count entities matching a component.
       *
       * @tparam T The component to use for matching.
       */
      template <typename T>
      int count() const {
          return ecs_count_type(
              m_world, _::component_info<T>::type(m_world));
      }
  
      /** Count entities matching a filter.
       *
       * @param filter The filter to use for matching.
       */
      int count(flecs::filter filter) const;
  
      /** Enable locking.
       * 
       * @param enabled True if locking should be enabled, false if not.
       */
      bool enable_locking(bool enabled) {
          return ecs_enable_locking(m_world, enabled);
      }
  
      /** Lock world.
       */
      void lock() {
          ecs_lock(m_world);
      }
  
      /** Unlock world.
       */
      void unlock() {
          ecs_unlock(m_world);
      }
  
      /** Create a prefab.
       */
      template <typename... Args>
      flecs::entity entity(Args &&... args) const;
  
      /** Create an entity.
       */
      template <typename... Args>
      flecs::entity prefab(Args &&... args) const;
  
      /** Create a type.
       */
      template <typename... Args>
      flecs::type type(Args &&... args) const;
  
      /** Create a module.
       */
      template <typename Module, typename... Args>
      flecs::entity module(Args &&... args) const;
  
      /** Import a module.
       */
      template <typename Module>
      flecs::entity import(); // Cannot be const because modules accept a non-const world
  
      /** Create an system.
       */
      template <typename... Comps, typename... Args>
      flecs::system<Comps...> system(Args &&... args) const;
  
      /** Create a query.
       */
      template <typename... Comps, typename... Args>
      flecs::query<Comps...> query(Args &&... args) const;
  
      /** Register a component.
       */
      template <typename T, typename... Args>
      flecs::entity component(Args &&... args) const;
  
      /** Register a POD component.
       */
      template <typename T, typename... Args>
      flecs::entity pod_component(Args &&... args) const;
  
      /** Register a relocatable component.
       */
      template <typename T, typename... Args>
      flecs::entity relocatable_component(Args &&... args) const;
  
      /** Create a snapshot.
       */
      template <typename... Args>
      flecs::snapshot snapshot(Args &&... args) const;
      
  private:
      void init_builtin_components();
  
      world_t *m_world;
      bool m_owned;
  };
  
  
  ////////////////////////////////////////////////////////////////////////////////
  
  /** Fluent API for chaining entity operations
   * This class contains entity operations that can be chained. For example, by
   * using this class, an entity can be created like this:
   *
   * flecs::entity e = flecs::entity(world)
   *   .add<Position>()
   *   .add<Velocity>();
   */
  template <typename Base>
  class entity_builder {
      using base_type = const Base;
  public:
  
      /** Add an entity to an entity by id.
       * This adds a raw entity id (64 bit integer) to the type of the current
       * entity.
       * 
       * @param entity The entity id to add.
       */
      base_type& add(entity_t entity) const {
          static_cast<base_type*>(this)->invoke(
          [entity](world_t *world, entity_t id) {
              ecs_add_entity(world, id, entity);
          });
          return *static_cast<base_type*>(this);         
      }
  
      /** Add a component to an entity.
       * To ensure the component is initialized, it should have a constructor.
       * 
       * @tparam T the component type to add.
       */
      template <typename T>
      base_type& add() const {
          static_cast<base_type*>(this)->invoke(
          [](world_t *world, entity_t id) {
              ecs_add_entity(world, id, _::component_info<T>::id(world));
          });
          return *static_cast<base_type*>(this);
      }
  
      /** Add an entity to an entity.
       * Add an entity to the entity. This is typically used for tagging.
       *
       * @param entity The entity to add.
       */
      base_type& add(const entity& entity) const;
  
      /** Add a type to an entity by its C pointer.
       * A type is a vector of component ids. This operation adds all components
       * in a single operation, and is a more efficient version of doing 
       * individual add operations.
       *
       * @param type The C type to add.
       */
      base_type& add(type_t type) const {
          static_cast<base_type*>(this)->invoke(
          [type](world_t *world, entity_t id) {
              ecs_add_type(world, id, type);
          });
          return *static_cast<base_type*>(this); 
      }
  
      /** Add a type to an entity.
       * A type is a vector of component ids. This operation adds all components
       * in a single operation, and is a more efficient version of doing 
       * individual add operations.
       * 
       * @param type The type to add.
       */
      base_type& add(type type) const;
  
      /** Add a trait.
       * This operation adds a trait for an entity by entity id. If the trait
       * is a component, a value of the trait type will be associated with the
       * entity. If the trait is not a component, a value of the component type
       * will be associated with the entity. If both the trait and component ids
       * are regular entities, no values will be associated with the entity.
       *
       * @param trait The trait id.
       * @param entity The entity identifier.
       */
      base_type& add_trait(entity_t trait, entity_t entity) const {
          static_cast<base_type*>(this)->invoke(
          [entity, trait](world_t *world, entity_t id) {
              ecs_add_entity(world, id, 
                  ecs_trait(entity, trait));
          });
          return *static_cast<base_type*>(this); 
      }
  
      /** Add a trait.
       * This operation adds a trait for a component. A value of the trait type
       * will be associated with the entity.
       *
       * @tparam T the trait type.
       * @tparam C the component type.
       */
      template<typename T, typename C>
      base_type& add_trait() const {
          static_cast<base_type*>(this)->invoke(
          [](world_t *world, entity_t id) {       
              ecs_add_entity(world, id, 
                  ecs_trait(_::component_info<C>::id(world), 
                            _::component_info<T>::id(world)));
          });
          return *static_cast<base_type*>(this); 
      }
  
      /** Add a trait.
       * This operation adds a trait for a component. A value of the trait 
       * type will be associated with the entity. 
       *
       * @tparam T The trait to add.
       * @param component The component for which to add the trait.
       */
      template<typename T>
      base_type& add_trait(flecs::entity component) const;
  
      /** Add a trait tag.
       * This operation adds a trait tag for a component. A value of the component 
       * type will be associated with the entity. Note that the trait tag passed 
       * into this function should not be a component.
       *
       * @tparam C The component type.
       * @param trait The trait identifier.
       */
      template<typename C>
      base_type& add_trait_tag(flecs::entity trait) const;
  
      /** Add a trait.
       * This operation adds a trait for an entity by entity id. If the trait
       * is a component, a value of the trait type will be associated with the
       * entity. If the trait is not a component, a value of the component type
       * will be associated with the entity. If both the trait and component ids
       * are regular entities, no values will be associated with the entity.
       *
       * @param trait The trait to add.
       * @param entity The tag for which to add the trait.
       */
      base_type& add_trait(flecs::entity trait, flecs::entity entity) const;
  
      /** Remove an entity from an entity by id.
       *
       * @param entity The entity id to remove.
       */
      base_type& remove(entity_t entity) const {
          static_cast<base_type*>(this)->invoke(
          [entity](world_t *world, entity_t id) {
              ecs_remove_entity(world, id, entity);
          });
          return *static_cast<base_type*>(this);
      }    
  
      /** Remove a component from an entity.
       *
       * @tparam T the type of the component to remove.
       */
      template <typename T>
      base_type& remove() const {
          static_cast<base_type*>(this)->invoke(
          [](world_t *world, entity_t id) {
              ecs_remove_entity(world, id, _::component_info<T>::id(world));
          });
          return *static_cast<base_type*>(this);
      }
  
      /** Remove an entity from an entity.
       *
       * @param entity The entity to remove.
       */
      base_type& remove(const entity& entity) const;
  
      /** Remove a type from an entity by its C pointer.
       * A type is a vector of component ids. This operation adds all components
       * in a single operation, and is a more efficient version of doing 
       * individual add operations.
       *
       * @param type the pointer to the type to remove.
       */
      base_type& remove(type_t type) const {
          static_cast<base_type*>(this)->invoke(
          [type](world_t *world, entity_t id) {
              ecs_remove_type(world, id, type);
          });
          return *static_cast<base_type*>(this);         
      }
  
      /** Remove a type from an entity.
       * A type is a vector of component ids. This operation adds all components
       * in a single operation, and is a more efficient version of doing 
       * individual add operations.
       *
       * @param type the type to remove.
       */
      base_type& remove(type type) const;
  
      /** Remove a trait.
       * This operation removes a trait for an entity by entity id.
       *
       * @param trait The trait to remove.
       * @param entity The entity for which to remove the trait.
       */
      base_type& remove_trait(entity_t trait, entity_t entity) const {
          static_cast<base_type*>(this)->invoke(
          [entity, trait](world_t *world, entity_t id) {
              ecs_remove_entity(world, id, 
                  ecs_trait(entity, trait));
          });
          return *static_cast<base_type*>(this);         
      }
  
      /** Remove a trait.
       * This operation removes a trait for a component.
       *
       * @tparam T The trait to remove.
       * @tparam C The component for which to remove the trait.
       */
      template<typename T, typename C>
      base_type& remove_trait() const {
          static_cast<base_type*>(this)->invoke(
          [](world_t *world, entity_t id) {   
              ecs_remove_entity(world, id,
                  ecs_trait(_::component_info<C>::id(world), 
                            _::component_info<T>::id(world)));
          });
          return *static_cast<base_type*>(this);
      }
  
      /** Remove a trait.
       * This operation removes a trait tag for a component. The trait should not
       * be a component.
       *
       * @tparam T The trait to remove.
       * @param component The component for which to remove the trait.
       */
      template<typename T>
      base_type& remove_trait(flecs::entity component) const;
  
      /** Remove a trait tag.
       * This operation removes a trait tag for a component. The trait should not
       * be a component.
       *
       * @tparam C The component for which to remove the trait.
       * @param trait The trait to remove.
       */
      template<typename C>
      base_type& remove_trait_tag(flecs::entity trait) const;
  
      /** Remove a trait.
       * This operation removes a trait for an entity.
       *
       * @param trait The trait to remove.
       * @param entity The entity for which to remove the trait.
       */
      base_type& remove_trait(flecs::entity trait, flecs::entity entity) const;
  
      /** Add a parent entity to an entity by id.
       *
       * @param parent The id of the parent to add.
       */    
      base_type& add_childof(entity_t parent) const {
          static_cast<base_type*>(this)->invoke(
          [parent](world_t *world, entity_t id) {
              ecs_add_entity(world, id, ECS_CHILDOF | parent);
          });
          return *static_cast<base_type*>(this);  
      }
  
      /** Add a parent entity to an entity.
       * 
       * @param parent The parent to add.
       */
      base_type& add_childof(const entity& parent) const;
  
      /** Remove a parent entity from an entity by id.
       *
       * @param parent The id of the parent to remove.
       */
      base_type& remove_childof(entity_t parent) const {
          static_cast<base_type*>(this)->invoke(
          [parent](world_t *world, entity_t id) {
              ecs_remove_entity(world, id, ECS_CHILDOF | parent);
          });
          return *static_cast<base_type*>(this);  
      }
  
      /** Remove a parent entity from an entity.
       *
       * @param parent The parent to remove.
       */
      base_type& remove_childof(const entity& parent) const;
  
      /** Add a base entity to an entity by id.
       *
       * @param base The base id to add.
       */    
      base_type& add_instanceof(entity_t base) const {
          static_cast<base_type*>(this)->invoke(
          [base](world_t *world, entity_t id) {
              ecs_add_entity(world, id, ECS_INSTANCEOF | base);
          });
          return *static_cast<base_type*>(this);  
      }
  
      /** Add a base entity to an entity.
       *
       * @param base The base to add.
       */
      base_type& add_instanceof(const entity& base) const;  
  
      /** Remove a base entity from an entity by id.
       *
       * @param base The base id to remove.
       */
      base_type& remove_instanceof(entity_t base) const {
          static_cast<base_type*>(this)->invoke(
          [base](world_t *world, entity_t id) {
              ecs_remove_entity(world, id, ECS_INSTANCEOF | base);
          });
          return *static_cast<base_type*>(this);
      }
  
      /** Remove a base entity from an entity.
       *
       * @param base The base to remove.
       */
      base_type& remove_instanceof(const entity& base) const;
  
      /** Add owned flag for component (forces ownership when instantiating)
       *
       * @param entity The entity for which to add the OWNED flag
       */    
      base_type& add_owned(entity_t entity) const {
          static_cast<base_type*>(this)->invoke(
          [entity](world_t *world, entity_t id) {
              ecs_add_entity(world, id, ECS_OWNED | entity);
          });
          return *static_cast<base_type*>(this);  
      }
  
      /** Add owned flag for component (forces ownership when instantiating)
       *
       * @tparam T The component for which to add the OWNED flag
       */    
      template <typename T>
      base_type& add_owned() const {
          static_cast<base_type*>(this)->invoke(
          [](world_t *world, entity_t id) {
              ecs_add_entity(world, id, ECS_OWNED | _::component_info<T>::id(world));
          });
          return *static_cast<base_type*>(this);  
      }
  
      /** Add owned flag for type entity.
       * This will ensure that all components in the type are owned for instances
       * of this entity.
       *
       * @param type The type for which to add the OWNED flag
       */    
      base_type& add_owned(flecs::type type) const;
  
      /** Add a switch to an entity by id.
       * The switch entity must be a type, that is it must have the EcsType
       * component. Entities created with flecs::type are valid here.
       *
       * @param sw The switch entity id to add.
       */    
      base_type& add_switch(entity_t sw) const {
          static_cast<base_type*>(this)->invoke(
          [sw](world_t *world, entity_t id) {
              ecs_add_entity(world, id, ECS_SWITCH | sw);
          });
          return *static_cast<base_type*>(this);  
      }
  
      /** Add a switch to an entity.
       * The switch entity must be a type, that is it must have the EcsType
       * component.
       *
       * @param sw The switch entity to add.
       */ 
      base_type& add_switch(const entity& sw) const;
  
      /** Add a switch to an entity.
       * Any instance of flecs::type can be used as a switch.
       *
       * @param sw The switch to add.
       */     
      base_type& add_switch(const type& sw) const;
  
      /** Remove a switch from an entity by id.
       *
       * @param sw The switch entity id to remove.
       */    
      base_type& remove_switch(entity_t sw) const {
          static_cast<base_type*>(this)->invoke(
          [sw](world_t *world, entity_t id) {
              ecs_remove_entity(world, id, ECS_SWITCH | sw);
          });
          return *static_cast<base_type*>(this);  
      }
  
      /** Remove a switch from an entity.
       *
       * @param sw The switch entity to remove.
       */ 
      base_type& remove_switch(const entity& sw) const;
      
      /** Remove a switch from an entity.
       * Any instance of flecs::type can be used as a switch.
       *
       * @param sw The switch to remove.
       */      
      base_type& remove_switch(const type& sw) const;
  
      /** Add a switch to an entity by id.
       * The case must belong to a switch that is already added to the entity.
       *
       * @param sw_case The case entity id to add.
       */    
      base_type& add_case(entity_t sw_case) const {
          static_cast<base_type*>(this)->invoke(
          [sw_case](world_t *world, entity_t id) {
              ecs_add_entity(world, id, ECS_CASE | sw_case);
          });
          return *static_cast<base_type*>(this);
      }
  
      /** Add a switch to an entity by id.
       * The case must belong to a switch that is already added to the entity.
       *
       * @tparam T The case to add.
       */   
      template<typename T>
      base_type& add_case() const {
          return this->add_case(_::component_info<T>::id());
      }
  
      /** Add a case to an entity.
       * The case must belong to a switch that is already added to the entity.
       *
       * @param sw_case The case entity to add.
       */ 
      base_type& add_case(const entity& sw_case) const;
  
      /** Remove a case from an entity by id.
       * The case must belong to a switch that is already added to the entity.
       *
       * @param sw_case The case entity id to remove.
       */    
      base_type& remove_case(entity_t sw_case) const {
          static_cast<base_type*>(this)->invoke(
          [sw_case](world_t *world, entity_t id) {
              ecs_remove_entity(world, id, ECS_CASE | sw_case);
          });
          return *static_cast<base_type*>(this);  
      }
  
      /** Remove a switch from an entity by id.
       * The case must belong to a switch that is already added to the entity.
       *
       * @tparam T The case to remove.
       */   
      template<typename T>
      base_type& remove_case() const {
          return this->remove_case(_::component_info<T>::id());
      }    
  
      /** Remove a case from an entity.
       * The case must belong to a switch that is already added to the entity.
       *
       * @param sw_case The case entity id to remove.
       */ 
      base_type& remove_case(const entity& sw_case) const;
  
      /** Enable an entity.
       * Enabled entities are matched with systems and can be searched with
       * queries.
       */
      base_type& enable() const {
          static_cast<base_type*>(this)->invoke(
          [](world_t *world, entity_t id) {
              ecs_enable(world, id, true);
          });
          return *static_cast<base_type*>(this);
      }
  
      /** Disable an entity.
       * Disabled entities are not matched with systems and cannot be searched 
       * with queries, unless explicitly specified in the query expression.
       */
      base_type& disable() const {
          static_cast<base_type*>(this)->invoke(
          [](world_t *world, entity_t id) {
              ecs_enable(world, id, false);
          });
          return *static_cast<base_type*>(this);
      }
  
      /** Enable a component.
       * This sets the enabled bit for this component. If this is the first time
       * the component is enabled or disabled, the bitset is added.
       *
       * @tparam T The component to enable.
       */   
      template<typename T>
      base_type& enable() const {
          static_cast<base_type*>(this)->invoke(
          [](world_t *world, entity_t id) {
              ecs_enable_component_w_entity(world, id, _::component_info<T>::id(), true);
          });
          return *static_cast<base_type*>(this);
      }  
  
      /** Disable a component.
       * This sets the enabled bit for this component. If this is the first time
       * the component is enabled or disabled, the bitset is added.
       *
       * @tparam T The component to enable.
       */   
      template<typename T>
      base_type& disable() const {
          static_cast<base_type*>(this)->invoke(
          [](world_t *world, entity_t id) {
              ecs_enable_component_w_entity(world, id, _::component_info<T>::id(), false);
          });
          return *static_cast<base_type*>(this);
      }  
  
      /** Enable a component.
       * See enable<T>.
       *
       * @param id The component to enable.
       */   
      base_type& enable(flecs::entity_t id) const {
          static_cast<base_type*>(this)->invoke(
          [id](world_t *world, entity_t e) {
              ecs_enable_component_w_entity(world, e, id, true);
          }); 
          return *static_cast<base_type*>(this);       
      }
  
      /** Disable a component.
       * See disable<T>.
       *
       * @param id The component to disable.
       */   
      base_type& disable(flecs::entity_t id) const {
          static_cast<base_type*>(this)->invoke(
          [id](world_t *world, entity_t e) {
              ecs_enable_component_w_entity(world, e, id, false);
          }); 
          return *static_cast<base_type*>(this);       
      }
  
      /** Enable a component.
       * See enable<T>.
       *
       * @param entity The component to enable.
       */   
      base_type& enable(const flecs::entity& entity) const;
  
      /** Disable a component.
       * See disable<T>.
       *
       * @param entity The component to disable.
       */   
      base_type& disable(const flecs::entity& entity) const;
  
      /** Set a component for an entity.
       * This operation overwrites the component value. If the entity did not yet
       * have the component, this operation will add it.
       *
       * @tparam T The component to set.
       * @param value The value to assign to the component.
       */
      template <typename T>
      const base_type& set(T&& value) const {
          static_cast<base_type*>(this)->invoke(
          [&value](world_t *world, entity_t id) {
              auto comp_id = _::component_info<T>::id(world);
  
              ecs_assert(_::component_info<T>::size() != 0, 
                  ECS_INVALID_PARAMETER, NULL);
  
              ecs_set_ptr_w_entity(
                  world, id, comp_id, sizeof(T), &value);
          });
          return *static_cast<base_type*>(this);
      }
  
      /** Set a component for an entity.
       * This operation overwrites the component value. If the entity did not yet
       * have the component, this operation will add it.
       *
       * @tparam T The component to set.
       * @param value The value to assign to the component.
       */
      template <typename T>
      const base_type& set(const T& value) const {
          static_cast<base_type*>(this)->invoke(
          [&value](world_t *world, entity_t id) {
              auto comp_id = _::component_info<T>::id(world);
  
              ecs_assert(_::component_info<T>::size() != 0, 
                  ECS_INVALID_PARAMETER, NULL);
  
              ecs_set_ptr_w_entity(
                  world, id, comp_id, sizeof(T), &value);
          });
          return *static_cast<base_type*>(this);
      }
  
      /** Set a trait for an entity.
       * This operation overwrites the trait value. If the entity did not yet
       * have the trait, this operation will add it.
       *
       * @tparam T The trait to set.
       * @tparam C The component for which to set the trait.
       * @param value The value to assign to the trait.     
       */
      template <typename T, typename C>
      const base_type& set_trait(const T& value) const {
          static_cast<base_type*>(this)->invoke(
          [&value](world_t *world, entity_t id) {
              auto t_id = _::component_info<T>::id(world);
  
              ecs_assert(_::component_info<T>::size() != 0, 
                  ECS_INVALID_PARAMETER, NULL);
  
              ecs_set_ptr_w_entity(world, id, 
                  ecs_trait(_::component_info<C>::id(world), t_id),
                          sizeof(T), &value);
          });
          return *static_cast<base_type*>(this);
      } 
  
      /** Set a trait tag for a component.
       * This operation overwrites the trait value. If the entity did not yet
       * have the trait, this operation will add it.
       *
       * This operation should be used for traits that are not components. If a
       * trait is not a component, it will assume the type of the component it is
       * assigned to.
       *
       * @tparam C The component for which to set the trait.
       * @param value The value to assign to the trait.      
       */
      template <typename C>
      const base_type& set_trait_tag(flecs::entity trait, const C& value) const;
  
      /** Set a trait for an entity.
       * This operation overwrites the trait value. If the entity did not yet
       * have the trait, this operation will add it.
       *
       * @tparam T The trait to set.
       * @param value The value to assign to the trait. 
       * @param entity The entity for which to set the trait.
       */
      template <typename T>
      const base_type& set_trait(const T& value, flecs::entity entity) const;
  
      /** Patch a component value.
       * This operation allows an application to partially overwrite a component 
       * value. The operation invokes a function with a reference to the value to
       * write, and a boolean indicating if the component already existed.
       *
       * @tparam T The component to patch.
       * @param func The function invoked by this operation.
       */
      template <typename T>
      const base_type& patch(std::function<void(T&, bool)> func) const {
          static_cast<base_type*>(this)->invoke(
          [&func](world_t *world, entity_t id) {
              auto comp_id = _::component_info<T>::id(world);
  
              ecs_assert(_::component_info<T>::size() != 0, 
                  ECS_INVALID_PARAMETER, NULL);
  
              bool is_added;
              T *ptr = static_cast<T*>(ecs_get_mut_w_entity(
                  world, id, comp_id, &is_added));
              if (ptr) {
                  func(*ptr, !is_added);
                  ecs_modified_w_entity(world, id, comp_id);
              }
          });
          return *static_cast<base_type*>(this);
      }      
  
      /** Patch a component value.
       * This operation allows an application to partially overwrite a component 
       * value. The operation invokes a function with a reference to the value to
       * write.
       *
       * @tparam T The component to patch.
       * @param func The function invoked by this operation.
       */
      template <typename T>
      const base_type& patch(std::function<void(T&)> func) const {
          static_cast<base_type*>(this)->invoke(
          [&func](world_t *world, entity_t id) {
              auto comp_id = _::component_info<T>::id(world);
  
              ecs_assert(_::component_info<T>::size() != 0, 
                  ECS_INVALID_PARAMETER, NULL);
  
              bool is_added;
              T *ptr = static_cast<T*>(ecs_get_mut_w_entity(
                  world, id, comp_id, &is_added));
              if (ptr) {
                  func(*ptr);
                  ecs_modified_w_entity(world, id, comp_id);
              }
          });
          return *static_cast<base_type*>(this);
      }            
  };
  
  ////////////////////////////////////////////////////////////////////////////////
  //// Quick and safe access to a component pointer
  ////////////////////////////////////////////////////////////////////////////////
  
  template <typename T>
  class ref {
  public:
      ref()
          : m_world( nullptr )
          , m_entity( 0 )
          , m_ref() 
      {       
      }
  
      ref(world_t *world, entity_t entity) 
          : m_world( world )
          , m_entity( entity )
          , m_ref() 
      {
          auto comp_id = _::component_info<T>::id(world);
  
          ecs_assert(_::component_info<T>::size() != 0, 
                  ECS_INVALID_PARAMETER, NULL);
  
          ecs_get_ref_w_entity(
              m_world, &m_ref, m_entity, comp_id);
      }
  
      const T* operator->() {
          const T* result = static_cast<const T*>(ecs_get_ref_w_entity(
              m_world, &m_ref, m_entity, _::component_info<T>::id(m_world)));
  
          ecs_assert(result != NULL, ECS_INVALID_PARAMETER, NULL);
  
          return result;
      }
  
      const T* get() {
          if (m_entity) {
              ecs_get_ref_w_entity(
                  m_world, &m_ref, m_entity, _::component_info<T>::id(m_world));    
          }
  
          return static_cast<T*>(m_ref.ptr);
      }
  
      flecs::entity entity() const;
  
  private:
      world_t *m_world;
      entity_t m_entity;
      ecs_ref_t m_ref;
  };
  
  
  ////////////////////////////////////////////////////////////////////////////////
  
  /** Entity class
   * This class provides access to entity operations.
   */
  class entity : public entity_builder<entity> {
  public:
      /** Default constructor.
       */
      explicit entity()
          : m_world( nullptr )
          , m_id( 0 ) { }
  
      /** Create entity.
       *
       * @param world The world in which to create the entity.
       */
      explicit entity(const world& world) 
          : m_world( world.c_ptr() )
          , m_id( ecs_new_w_type(m_world, 0) ) { }
  
      /** Create entity.
       *
       * @param world Pointer to the world in which to create the entity.
       */
      explicit entity(world_t *world) 
          : m_world( world )
          , m_id( world ? ecs_new_w_type(world, 0) : 0 ) { }
  
      /** Create a named entity.
       * Named entities can be looked up with the lookup functions. Entity names
       * may be scoped, where each element in the name is separated by "::".
       * For example: "Foo::Bar". If parts of the hierarchy in the scoped name do
       * not yet exist, they will be automatically created.
       *
       * @param world The world in which to create the entity.
       * @param name The entity name.
       * @param is_component If true, the entity will be created from the pool of component ids (default = false).
       */
      entity(const world& world, const char *name, bool is_component = false) 
          : m_world( world.c_ptr() )
          , m_id( ecs_lookup_path_w_sep(m_world, 0, name, "::", "::") ) 
          { 
              if (!m_id) {
                  if (is_component) {
                      m_id = ecs_new_component_id(m_world);
                  }
  
                  m_id = ecs_add_path_w_sep(
                      m_world, m_id, 0, name, "::", "::");
              }
          }
  
      /** Create a named entity.
       * Named entities can be looked up with the lookup functions. Entity names
       * may be scoped, where each element in the name is separated by "::".
       * For example: "Foo::Bar". If parts of the hierarchy in the scoped name do
       * not yet exist, they will be automatically created.
       *
       * @param world The world in which to create the entity.
       * @param name The entity name.
       * @param is_component If true, the entity will be created from the pool of component ids (default = false).
       */
      entity(const world& world, std::string name, bool is_component = false) 
          : m_world( world.c_ptr() )
          , m_id( ecs_lookup_path_w_sep(m_world, 0, name.c_str(), "::", "::") ) 
          { 
              if (!m_id) {
                  if (is_component) {
                      m_id = ecs_new_component_id(m_world);
                  }
  
                  m_id = ecs_add_path_w_sep(
                      m_world, m_id, 0, name.c_str(), "::", "::");
              }
          }         
  
      /** Wrap an existing entity id.
       *
       * @param world The world in which the entity is created.
       * @param id The entity id.
       */
      entity(const world& world, entity_t id) 
          : m_world( world.c_ptr() )
          , m_id(id) { }
  
      /** Wrap an existing entity id.
       *
       * @param world Pointer to the world in which the entity is created.
       * @param id The entity id.
       */
      entity(world_t *world, entity_t id) 
          : m_world( world )
          , m_id(id) { }
  
      /** Equality operator. */
      bool operator==(const entity& e) {
          return this->id() == e.id();
      }  
  
      /** Inequality operator. */
      bool operator!=(const entity& e) {
          return this->id() != e.id();
      }            
  
      explicit operator bool() {
          return m_id != 0;
      }
  
      /** Entity id 0.
       * This function is useful when the API must provide an entity object that
       * belongs to a world, but the entity id is 0.
       *
       * @param world The world.
       */
      static
      flecs::entity null(const world& world) {
          return flecs::entity(world.c_ptr(), (ecs_entity_t)0);
      }
  
      static
      flecs::entity null() {
          return flecs::entity(nullptr, (ecs_entity_t)0);
      }    
  
      /** Get entity id.
       * @return The integer entity id.
       */
      entity_t id() const {
          return m_id;
      }
  
      /** Get lo entity id.
       * @return A new entity containing the lower 32 bits of the entity id.
       */
      flecs::entity lo() const {
          return flecs::entity(m_world, ecs_entity_t_lo(m_id));
      }
  
      /** Get hi entity id.
       * @return A new entity containing the higher 32 bits of the entity id.
       */
      flecs::entity hi() const {
          return flecs::entity(m_world, ecs_entity_t_hi(m_id));
      }
  
      /** Combine two entity ids.
       * @return A new entity that combines the provided entity ids in the lower
       *         and higher 32 bits of the entity id.
       */
      static 
      flecs::entity comb(flecs::entity lo, flecs::entity hi) {
          return flecs::entity(lo.world(), 
              ecs_entity_t_comb(lo.id(), hi.id()));
      }
  
      /** Add role.
       * Roles are added to entity ids in types to indicate which role they play.
       * Examples of roles are flecs::Instanceof and flecs::Childof. 
       *
       * @return A new entity with the specified role set.
       */
      flecs::entity add_role(entity_t role) const {
          return flecs::entity(m_world, m_id | role);
      }
  
      /** Remove role.
       * Roles are added to entity ids in types to indicate which role they play.
       * Examples of roles are flecs::Instanceof and flecs::Childof. 
       *    
       * @return A new entity with any roles removed.
       */
      flecs::entity remove_role() const {
          return flecs::entity(m_world, m_id & ECS_COMPONENT_MASK);
      }
  
      /** Check if entity has specified role.
       * Roles are added to entity ids in types to indicate which role they play.
       * Examples of roles are flecs::Instanceof and flecs::Childof. 
       *    
       * @return True if the entity has the role, false otherwise.
       */
      bool has_role(entity_t role) const {        
          return ((m_id & ECS_ROLE_MASK) == role);
      }
  
      /** Check is entity is alive.
       *
       * @return True if the entity is alive, false otherwise.
       */
      bool is_alive() {
          return ecs_is_alive(m_world, m_id);
      }
  
      /** Return the entity name.
       *
       * @return The entity name, or an empty string if the entity has no name.
       */
      std::string name() const {
          const EcsName *name = static_cast<const EcsName*>(
              ecs_get_w_entity(m_world, m_id, ecs_entity(EcsName)));
          if (name && name->value) {
              return std::string(name->value);
          } else {
              return std::string();
          }
      }
  
      /** Return the entity path.
       *
       * @return The hierarchical entity path, or an empty string if the entity 
       *         has no name.
       */
      std::string path(const char *sep = "::", const char *init_sep = "::") const {
          char *path = ecs_get_path_w_sep(m_world, 0, m_id, 0, sep, init_sep);
          if (path) {
              std::string result = std::string(path);
              ecs_os_free(path);
              return result;
          } else {
              return std::string();
          }
      }   
  
      bool enabled() {
          return !ecs_has_entity(m_world, m_id, flecs::Disabled);
      }
  
      /** Return the world.
       *
       * @return The world the entity is stored in.
       */
      flecs::world world() const {
          return flecs::world(m_world);
      }
  
      /** Return the type.
       *
       * @return Returns the entity type.
       */
      flecs::type type() const;
  
      /** Return type containing the entity.
       *
       * @return A type that contains only this entity.
       */
      flecs::type to_type() const;
  
      /** Get component value.
       * 
       * @tparam T The component to get.
       * @return Pointer to the component value, nullptr if the entity does not
       *         have the component.
       */
      template <typename T>
      const T* get() const {
          ecs_assert(m_world != NULL, ECS_INVALID_PARAMETER, NULL);
          ecs_assert(m_id != 0, ECS_INVALID_PARAMETER, NULL);
  
          auto comp_id = _::component_info<T>::id(m_world);
  
          ecs_assert(_::component_info<T>::size() != 0, 
                  ECS_INVALID_PARAMETER, NULL);
  
          return static_cast<const T*>(
              ecs_get_w_entity(m_world, m_id, comp_id));
      }
  
      /** Get component value (untyped).
       * 
       * @param component The component to get.
       * @return Pointer to the component value, nullptr if the entity does not
       *         have the component.
       */
      const void* get(flecs::entity component) const {
          ecs_assert(m_world != NULL, ECS_INVALID_PARAMETER, NULL);
          ecs_assert(m_id != 0, ECS_INVALID_PARAMETER, NULL);
          return ecs_get_w_entity(m_world, m_id, component.id());
      }
  
      /** Get component value (untyped).
       * 
       * @param component The id of the component to get.
       * @return Pointer to the component value, nullptr if the entity does not
       *         have the component.
       */
      const void* get(entity_t component_id) const {
          ecs_assert(m_world != NULL, ECS_INVALID_PARAMETER, NULL);
          ecs_assert(m_id != 0, ECS_INVALID_PARAMETER, NULL);
          return ecs_get_w_entity(m_world, m_id, component_id);
      } 
  
      /** Get mutable component value.
       * This operation returns a mutable pointer to the component. If the entity
       * did not yet have the component, it will be added. If a base entity had
       * the component, it will be overridden, and the value of the base component
       * will be copied to the entity before this function returns.
       *
       * @tparam T The component to get.
       * @param is_added If provided, this parameter will be set to true if the component was added.
       * @return Pointer to the component value.
       */
      template <typename T>
      T* get_mut(bool *is_added = nullptr) const {
          ecs_assert(m_world != NULL, ECS_INVALID_PARAMETER, NULL);
          ecs_assert(m_id != 0, ECS_INVALID_PARAMETER, NULL);
  
          auto comp_id = _::component_info<T>::id(m_world);
  
          ecs_assert(_::component_info<T>::size() != 0, 
                  ECS_INVALID_PARAMETER, NULL);
  
          return static_cast<T*>(
              ecs_get_mut_w_entity(m_world, m_id, comp_id, is_added));
      }
  
      /** Get mutable component value (untyped).
       * This operation returns a mutable pointer to the component. If the entity
       * did not yet have the component, it will be added. If a base entity had
       * the component, it will be overridden, and the value of the base component
       * will be copied to the entity before this function returns.
       *
       * @param component The component to get.
       * @param is_added If provided, this parameter will be set to true if the component was added.
       * @return Pointer to the component value.
       */
      void* get_mut(flecs::entity component, bool *is_added = nullptr) const {
          ecs_assert(m_world != NULL, ECS_INVALID_PARAMETER, NULL);
          ecs_assert(m_id != 0, ECS_INVALID_PARAMETER, NULL);
          return ecs_get_mut_w_entity(m_world, m_id, component.id(), is_added);
      }
  
      /** Get mutable component value (untyped).
       * This operation returns a mutable pointer to the component. If the entity
       * did not yet have the component, it will be added. If a base entity had
       * the component, it will be overridden, and the value of the base component
       * will be copied to the entity before this function returns.
       *
       * @param component The id of the component to get.
       * @param is_added If provided, this parameter will be set to true if the component was added.
       * @return Pointer to the component value.
       */
      void* get_mut(entity_t component_id, bool *is_added = nullptr) const {
          ecs_assert(m_world != NULL, ECS_INVALID_PARAMETER, NULL);
          ecs_assert(m_id != 0, ECS_INVALID_PARAMETER, NULL);
          return ecs_get_mut_w_entity(m_world, m_id, component_id, is_added);
      }
  
      /** Get trait value.
       * 
       * @tparam T The trait to get.
       * @tparam C The component for which to get the trait.
       * @return Pointer to the trait value, nullptr if the entity does not
       *         have the trait.
       */
      template<typename T, typename C>
      const T* get_trait() const {
          ecs_assert(m_world != NULL, ECS_INVALID_PARAMETER, NULL);
          ecs_assert(m_id != 0, ECS_INVALID_PARAMETER, NULL);
          
          auto t_id = _::component_info<T>::id(m_world);
  
          ecs_assert(_::component_info<T>::size() != 0, 
                  ECS_INVALID_PARAMETER, NULL);
  
          return static_cast<const T*>(ecs_get_w_entity(m_world, m_id, ecs_trait(
              _::component_info<C>::id(m_world), t_id)));
      }   
  
      /** Get trait value.
       * 
       * @tparam T The trait to get.
       * @param component The component for which to get the trait.
       * @return Pointer to the trait value, nullptr if the entity does not
       *         have the trait.
       */
      template<typename T>
      const T* get_trait(flecs::entity component) const {
          ecs_assert(m_world != NULL, ECS_INVALID_PARAMETER, NULL);
          ecs_assert(m_id != 0, ECS_INVALID_PARAMETER, NULL);
  
          auto comp_id = _::component_info<T>::id(m_world);
  
          ecs_assert(_::component_info<T>::size() != 0, 
                  ECS_INVALID_PARAMETER, NULL);
  
          return static_cast<const T*>(ecs_get_w_entity(m_world, m_id, ecs_trait(
              component.id(), comp_id)));
      }
  
      /** Get trait tag value.
       * The trait passed to this function should not be a component. If a trait
       * is not a component, the trait assumes the type of the component it is
       * assigned to.
       * 
       * @tparam C The component for which to get the trait
       * @param trait The trait to get.
       * @return Pointer to the trait value, nullptr if the entity does not
       *         have the trait.
       */
      template<typename C>
      const C* get_trait_tag(flecs::entity trait) const {
          ecs_assert(m_world != NULL, ECS_INVALID_PARAMETER, NULL);
          ecs_assert(m_id != 0, ECS_INVALID_PARAMETER, NULL);
  
          auto comp_id = _::component_info<C>::id(m_world);
  
          ecs_assert(_::component_info<C>::size() != 0, 
                  ECS_INVALID_PARAMETER, NULL);
  
          return static_cast<const C*>(ecs_get_w_entity(m_world, m_id, ecs_trait(
              comp_id, trait.id())));
      }
  
      /** Get trait tag value (untyped).
       * If a trait is not a component, the trait assumes the type of the 
       * component it is assigned to.
       * 
       * @param trait The trait to get.
       * @param component The component for which to get the trait.
       * @return Pointer to the trait value, nullptr if the entity does not
       *         have the trait.
       */
      const void* get_trait(flecs::entity trait, flecs::entity component) const {
          ecs_assert(m_world != NULL, ECS_INVALID_PARAMETER, NULL);
          ecs_assert(m_id != 0, ECS_INVALID_PARAMETER, NULL);
          return ecs_get_w_entity(m_world, m_id, ecs_trait(
              component.id(), trait.id()));
      }
  
      /** Get mutable trait value.
       * This operation returns a mutable pointer to the trait. If the entity
       * did not yet have the trait, it will be added. If a base entity had
       * the trait, it will be overridden, and the value of the base trait
       * will be copied to the entity before this function returns.
       *
       * @tparam T The trait to get.
       * @tparam C The component for which to get the trait.
       * @param is_added If provided, this parameter will be set to true if the trait was added.
       * @return Pointer to the trait value.
       */
      template <typename T, typename C>
      T* get_trait_mut(bool *is_added = nullptr) const {
          ecs_assert(m_world != NULL, ECS_INVALID_PARAMETER, NULL);
          ecs_assert(m_id != 0, ECS_INVALID_PARAMETER, NULL);
  
          auto t_id = _::component_info<T>::id(m_world);
  
          ecs_assert(_::component_info<T>::size() != 0, 
                  ECS_INVALID_PARAMETER, NULL);
  
          return static_cast<T*>(
              ecs_get_mut_w_entity(
                  m_world, m_id, ecs_trait(_::component_info<C>::id(m_world), 
                      t_id), is_added));
      }    
  
      /** Get mutable trait value.
       * This operation returns a mutable pointer to the trait. If the entity
       * did not yet have the trait, it will be added. If a base entity had
       * the trait, it will be overridden, and the value of the base trait
       * will be copied to the entity before this function returns.
       *
       * @tparam T The trait to get.
       * @param component The component for which to get the trait.
       * @param is_added If provided, this parameter will be set to true if the trait was added.
       * @return Pointer to the trait value.
       */
      template <typename T>
      T* get_trait_mut(flecs::entity component, bool *is_added = nullptr) const {
          ecs_assert(m_world != NULL, ECS_INVALID_PARAMETER, NULL);
          ecs_assert(m_id != 0, ECS_INVALID_PARAMETER, NULL);
  
          auto comp_id = _::component_info<T>::id(m_world);
  
          ecs_assert(_::component_info<T>::size() != 0, 
                  ECS_INVALID_PARAMETER, NULL);
  
          return static_cast<T*>(
              ecs_get_mut_w_entity(
                  m_world, m_id, ecs_trait( comp_id, component.id()), is_added));
      }
  
      /** Get mutable trait tag value.
       * This operation returns a mutable pointer to the trait. If the entity
       * did not yet have the trait, it will be added. If a base entity had
       * the trait, it will be overridden, and the value of the base trait
       * will be copied to the entity before this function returns.
       *
       * The trait passed to the function should not be a component.
       *
       * @tparam C The component for which to get the trait.
       * @param trait The trait to get.
       * @param is_added If provided, this parameter will be set to true if the trait was added.
       * @return Pointer to the trait value.
       */
      template <typename C>
      C* get_trait_tag_mut(flecs::entity trait, bool *is_added = nullptr) const {
          ecs_assert(m_world != NULL, ECS_INVALID_PARAMETER, NULL);
          ecs_assert(m_id != 0, ECS_INVALID_PARAMETER, NULL);
          ecs_assert(_::component_info<C>::size() != 0, 
                  ECS_INVALID_PARAMETER, NULL);
          return static_cast<C*>(
              ecs_get_mut_w_entity(
                  m_world, m_id, ecs_trait(
                      _::component_info<C>::id(m_world),
                      trait.id()),
                      is_added));
      }    
  
      /** Signal that component was modified.
       *
       * @tparam T component that was modified.
       */
      template <typename T>
      void modified() const {
          ecs_assert(m_world != NULL, ECS_INVALID_PARAMETER, NULL);
          ecs_assert(m_id != 0, ECS_INVALID_PARAMETER, NULL);
  
          auto comp_id = _::component_info<T>::id(m_world);
  
          ecs_assert(_::component_info<T>::size() != 0, 
                  ECS_INVALID_PARAMETER, NULL);
  
          ecs_modified_w_entity(m_world, m_id, comp_id);
      }
  
      /** Signal that component was modified.
       *
       * @param component component that was modified.
       */
      void modified(flecs::entity component) const {
          ecs_assert(m_world != NULL, ECS_INVALID_PARAMETER, NULL);
          ecs_assert(m_id != 0, ECS_INVALID_PARAMETER, NULL);
          ecs_modified_w_entity(m_world, m_id, component.id());
      }
  
      /** Signal that component was modified.
       *
       * @param component id of component that was modified.
       */
      void modified(entity_t component) const {
          ecs_assert(m_world != NULL, ECS_INVALID_PARAMETER, NULL);
          ecs_assert(m_id != 0, ECS_INVALID_PARAMETER, NULL);
          ecs_modified_w_entity(m_world, m_id, component);
      }        
  
      /** Get reference to component.
       * A reference allows for quick and safe access to a component value, and is
       * a faster alternative to repeatedly calling 'get' for the same component.
       *
       * @tparam T component for which to get a reference.
       * @return The reference.
       */
      template <typename T>
      ref<T> get_ref() const {
          ecs_assert(m_world != NULL, ECS_INVALID_PARAMETER, NULL);
          ecs_assert(m_id != 0, ECS_INVALID_PARAMETER, NULL);
  
          // Ensure component is registered
          _::component_info<T>::id(m_world);
  
          ecs_assert(_::component_info<T>::size() != 0, 
                  ECS_INVALID_PARAMETER, NULL);
  
          return ref<T>(m_world, m_id);
      }
  
      /** Get parent from an entity.
       * This operation retrieves the parent entity that has the specified 
       * component. If no parent with the specified component is found, an entity
       * with id 0 is returned. If multiple parents have the specified component,
       * the operation returns the first encountered one.
       *
       * @tparam T The component for which to find the parent.
       * @return The parent entity.
       */
      template <typename T>
      flecs::entity get_parent() {
          return flecs::entity(m_world, ecs_get_parent_w_entity(m_world, m_id, 
              _::component_info<T>::id(m_world)));
      }
  
      flecs::entity get_parent(flecs::entity e) {
          return flecs::entity(m_world, ecs_get_parent_w_entity(m_world, m_id, e.id()));
      }    
  
      /** Clear an entity.
       * This operation removes all components from an entity without recycling
       * the entity id.
       */
      void clear() const {
          ecs_assert(m_world != NULL, ECS_INVALID_PARAMETER, NULL);
          ecs_assert(m_id != 0, ECS_INVALID_PARAMETER, NULL);
          ecs_clear(m_world, m_id);
      }
  
      /** Delete an entity.
       * Entities have to be deleted explicitly, and are not deleted when the
       * flecs::entity object goes out of scope.
       */
      void destruct() const {
          ecs_assert(m_world != NULL, ECS_INVALID_PARAMETER, NULL);
          ecs_assert(m_id != 0, ECS_INVALID_PARAMETER, NULL);
          ecs_delete(m_world, m_id);
      }
  
      /** Lookup an entity by name.
       * Lookup an entity in the scope of this entity. The provided path may
       * contain double colons as scope separators, for example: "Foo::Bar".
       *
       * @param path The name of the entity to lookup.
       * @return The found entity, or entity::null if no entity matched.
       */
      entity lookup(const char *path) const {
          ecs_assert(m_world != NULL, ECS_INVALID_PARAMETER, NULL);
          ecs_assert(m_id != 0, ECS_INVALID_PARAMETER, NULL);
          auto id = ecs_lookup_path_w_sep(m_world, m_id, path, "::", "::");
          return entity(m_world, id);
      }
  
      /** Check if entity has the provided entity.
       *
       * @param entity The entity id to check.
       * @return True if the entity has the provided entity id, false otherwise.
       */
      bool has(entity_t e) const {
          ecs_assert(m_world != NULL, ECS_INVALID_PARAMETER, NULL);
          ecs_assert(m_id != 0, ECS_INVALID_PARAMETER, NULL);
          return ecs_has_entity(m_world, m_id, e);
      }
  
      /** Check if entity has the provided parent.
       *
       * @param parent The parent id to check.
       * @return True if the entity has the provided parent id, false otherwise.
       */
      bool has_childof(entity_t parent) const {
          ecs_assert(m_world != NULL, ECS_INVALID_PARAMETER, NULL);
          ecs_assert(m_id != 0, ECS_INVALID_PARAMETER, NULL);
          return ecs_has_entity(m_world, m_id, ECS_CHILDOF | parent);
      }    
  
      /** Check if entity has the provided base.
       *
       * @param base The entity id to check.
       * @return True if the entity has the provided base id, false otherwise.
       */
      bool has_instanceof(entity_t base) const {
          ecs_assert(m_world != NULL, ECS_INVALID_PARAMETER, NULL);
          ecs_assert(m_id != 0, ECS_INVALID_PARAMETER, NULL);
          return ecs_has_entity(m_world, m_id, ECS_INSTANCEOF | base);
      }
  
      /** Check if entity has the provided type.
       *
       * @param entity The type pointer to check.
       * @return True if the entity has the provided type, false otherwise.
       */
      bool has(type_t type) const {
          ecs_assert(m_world != NULL, ECS_INVALID_PARAMETER, NULL);
          ecs_assert(m_id != 0, ECS_INVALID_PARAMETER, NULL);
          return ecs_has_type(m_world, m_id, type);
      }
  
      /** Check if entity has the provided entity.
       *
       * @param entity The entity to check.
       * @return True if the entity has the provided entity, false otherwise.
       */
      bool has(const entity& e) const {
          return has(e.id());
      }
  
      /** Check if entity has the provided parent.
       *
       * @param parent The entity to check.
       * @return True if the entity has the provided parent, false otherwise.
       */
      bool has_childof(const entity& parent) const {
          return has_childof(parent.id());
      }  
  
      /** Check if entity has the provided base.
       *
       * @param base The entity to check.
       * @return True if the entity has the provided base, false otherwise.
       */
      bool has_instanceof(const entity& base) const {
          return has_instanceof(base.id());
      }        
  
      /** Check if entity has the provided component.
       *
       * @tparam T The component to check.
       * @return True if the entity has the provided component, false otherwise.
       */
      template <typename T>
      bool has() const {
          return has(_::component_info<T>::id(m_world));
      }
  
      /** Check if entity owns the provided entity id.
       * An entity id is owned if it is not shared from a base entity.
       *
       * @param entity The entity id to check.
       * @return True if the entity owns the provided entity id, false otherwise.
       */
      bool owns(entity_t e) const {
          ecs_assert(m_world != NULL, ECS_INVALID_PARAMETER, NULL);
          ecs_assert(m_id != 0, ECS_INVALID_PARAMETER, NULL);
          return ecs_owns_entity(m_world, m_id, e, true);
      }
  
      /** Check if entity owns the provided type.
       * An type is owned if it is not shared from a base entity.
       *
       * @param type The type to check.
       * @return True if the entity owns the provided type, false otherwise.
       */
      bool owns(type_t type) const {
          ecs_assert(m_world != NULL, ECS_INVALID_PARAMETER, NULL);
          ecs_assert(m_id != 0, ECS_INVALID_PARAMETER, NULL);
          return ecs_type_owns_type(m_world, ecs_get_type(m_world, m_id), type, true);
      }
  
      /** Check if entity owns the provided entity.
       * An entity is owned if it is not shared from a base entity.
       *
       * @param entity The entity to check.
       * @return True if the entity owns the provided entity, false otherwise.
       */
      bool owns(const entity& e) const {
          return owns(e.id());
      }
  
      /** Check if entity owns the provided component.
       * An component is owned if it is not shared from a base entity.
       *
       * @tparam T The component to check.
       * @return True if the entity owns the provided component, false otherwise.
       */
      template <typename T>
      bool owns() const {
          return owns(_::component_info<T>::id(m_world));
      }
  
      /** Check if entity has the provided trait.
       *
       * @tparam T The trait to check.
       * @tparam C The component for which to check the trait.
       * @return True if the entity has the provided trait, false otherwise.
       */
      template<typename T, typename C>
      bool has_trait() const {
          ecs_assert(m_world != NULL, ECS_INVALID_PARAMETER, NULL);
          ecs_assert(m_id != 0, ECS_INVALID_PARAMETER, NULL);
          return ecs_has_entity(m_world, m_id, ecs_trait(
              _::component_info<C>::id(m_world), 
              _::component_info<T>::id(m_world)));
      }
  
      /** Check if entity has the provided trait.
       *
       * @tparam T The trait to check.
       * @param component The component for which to check the trait.
       * @return True if the entity has the provided trait, false otherwise.
       */
      template<typename T>
      bool has_trait(flecs::entity component) const {
          ecs_assert(m_world != NULL, ECS_INVALID_PARAMETER, NULL);
          ecs_assert(m_id != 0, ECS_INVALID_PARAMETER, NULL);
          return ecs_has_entity(m_world, m_id, ecs_trait(
              component.id(), _::component_info<T>::id(m_world)));
      }
  
      /** Check if entity has the provided trait tag.
       * The provided trait tag should not be a component.
       *
       * @tparam C The component for which to check the trait tag.
       * @param trait The trait tag to check.
       * @return True if the entity has the provided trait tag, false otherwise.
       */
      template<typename C>
      bool has_trait_tag(flecs::entity trait) const {
          ecs_assert(m_world != NULL, ECS_INVALID_PARAMETER, NULL);
          ecs_assert(m_id != 0, ECS_INVALID_PARAMETER, NULL);
          return ecs_has_entity(m_world, m_id, ecs_trait(
             _::component_info<C>::id(m_world), trait.id()));
      }
  
      /** Check if entity has the provided trait.
       * The provided trait should not be a component.
       *
       * @param trait The trait to check.
       * @param component The component for which to check the trait.
       * @return True if the entity has the provided trait, false otherwise.
       */
      bool has_trait(flecs::entity trait, flecs::entity e) const {
          ecs_assert(m_world != NULL, ECS_INVALID_PARAMETER, NULL);
          ecs_assert(m_id != 0, ECS_INVALID_PARAMETER, NULL);
          return ecs_has_entity(m_world, m_id, ecs_trait(
              e.id(), trait.id()));
      }
  
      /** Check if entity has the provided switch.
       *
       * @param sw The switch to check.
       * @return True if the entity has the provided switch, false otherwise.
       */
      bool has_switch(flecs::type sw) const;
  
      /** Check if entity has the provided case id.
       *
       * @param sw_case The case id to check.
       * @return True if the entity has the provided case, false otherwise.
       */
      bool has_case(entity_t sw_case) const {
          ecs_assert(m_world != NULL, ECS_INVALID_PARAMETER, NULL);
          ecs_assert(m_id != 0, ECS_INVALID_PARAMETER, NULL);
          return ecs_has_entity(m_world, m_id, flecs::Case | sw_case);
      }
  
      /** Check if entity has the provided case.
       *
       * @param sw_case The case to check.
       * @return True if the entity has the provided case, false otherwise.
       */
      bool has_case(flecs::entity sw_case) const {
          return this->has_case(sw_case.id());
      }
  
      template<typename T>
      bool has_case() const {
          return this->has_case(_::component_info<T>::id(m_world));
      }
  
      /** Get case for switch.
       *
       * @param sw The switch for which to obtain the case.
       * @return True if the entity has the provided case, false otherwise.
       */
      flecs::entity get_case(flecs::type sw) const;
  
      /** Test if component is enabled.
       *
       * @tparam T The component to test.
       * @return True if the component is enabled, false if it has been disabled.
       */
      template<typename T>
      bool is_enabled() {
          return ecs_is_component_enabled_w_entity(
              m_world, m_id, _::component_info<T>::id(m_world));
      }
  
      /** Test if component is enabled.
       *
       * @param id The component to test.
       * @return True if the component is enabled, false if it has been disabled.
       */
      bool is_enabled(flecs::entity_t id) {
          return ecs_is_component_enabled_w_entity(
              m_world, m_id, id);
      }
  
      /** Test if component is enabled.
       *
       * @param entity The component to test.
       * @return True if the component is enabled, false if it has been disabled.
       */
      bool is_enabled(const flecs::entity& e) {
          return is_enabled(e.id());
      }
  
      /** Get current delta time.
       * Convenience function so system implementations can get delta_time, even
       * if they are using the .each() function.
       *
       * @return Current delta_time.
       */
      FLECS_FLOAT delta_time() const {
          const ecs_world_info_t *stats = ecs_get_world_info(m_world);
          return stats->delta_time;
      }
  
      /** Return iterator to entity children.
       * Enables depth-first iteration over entity children.
       *
       * @return Iterator to child entities.
       */
      child_iterator children() const;
  
      /** Used by builder class. Do not invoke. */
      template <typename Func>
      void invoke(Func&& action) const {
          action(m_world, m_id);
      }    
  
  protected:
  
      world_t *m_world;
      entity_t m_id; 
  };
  
  /** Prefab class */
  class prefab final : public entity {
  public:
      explicit prefab(const flecs::world& world, const char *name = nullptr) 
          : entity(world, name)
      {
          this->add(flecs::Prefab);
      }
  };
  
  
  ////////////////////////////////////////////////////////////////////////////////
  //// A collection of component ids used to describe the contents of a table
  ////////////////////////////////////////////////////////////////////////////////
  
  class type final : entity {
  public:
      explicit type(const flecs::world& world, const char *name = nullptr, const char *expr = nullptr)
          : entity(world, ecs_new_type(world.c_ptr(), 0, name, expr))
      { 
          sync_from_flecs();
      }
  
      type(const flecs::world& world, type_t t)
          : entity( world.c_ptr(), 0 )
          , m_type( t )
          , m_normalized( t ) { }
  
      type(world_t *world, type_t t)
          : entity( world, 0 )
          , m_type( t )
          , m_normalized( t ) { }
  
      type& add(const type& t) {
          m_type = ecs_type_add(m_world, m_type, t.id());
          m_normalized = ecs_type_merge(m_world, m_normalized, t.c_ptr(), nullptr);
          sync_from_me();
          return *this;
      }
  
      type& add(const entity& e) {
          m_type = ecs_type_add(m_world, m_type, e.id());
          m_normalized = ecs_type_add(m_world, m_normalized, e.id());
          sync_from_me();
          return *this;
      }
  
      type& add_instanceof(const entity& e) {
          m_type = ecs_type_add(m_world, m_type, e.id() | ECS_INSTANCEOF);
          m_normalized = ecs_type_add(m_world, m_normalized, e.id() | ECS_INSTANCEOF);
          sync_from_me();
          return *this;
      }
  
      type& add_childof(const entity& e) {
          m_type = ecs_type_add(m_world, m_type, e.id() | ECS_CHILDOF);
          m_normalized = ecs_type_add(m_world, m_normalized, e.id() | ECS_CHILDOF);
          sync_from_me();
          return *this;
      }
  
      template <typename T, typename C>
      type& add_trait() {
          m_type = ecs_type_add(m_world, m_type, 
              ecs_trait(_::component_info<C>::id(m_world),
                        _::component_info<T>::id(m_world)));
  
          m_normalized = ecs_type_add(m_world, m_normalized, 
              ecs_trait(_::component_info<C>::id(m_world),
                        _::component_info<T>::id(m_world)));
          
          sync_from_me();
          return *this;
      }
  
      template <typename T>
      type& add_trait(flecs::entity component) {
          m_type = ecs_type_add(m_world, m_type, 
              ecs_trait(component.id(),
                        _::component_info<T>::id(m_world)));
  
          m_normalized = ecs_type_add(m_world, m_normalized, 
              ecs_trait(component.id(),
                        _::component_info<T>::id(m_world)));
          
          sync_from_me();
          return *this;
      }
  
      type& add_trait(flecs::entity trait, flecs::entity component) {
          m_type = ecs_type_add(m_world, m_type, 
              ecs_trait(component.id(), trait.id()));
  
          m_normalized = ecs_type_add(m_world, m_normalized, 
              ecs_trait(component.id(), trait.id()));
          
          sync_from_me();
          return *this;
      }      
  
      template <typename C>
      type& add_trait_tag(flecs::entity trait) {
          m_type = ecs_type_add(m_world, m_type, 
              ecs_trait(_::component_info<C>::id(), trait.id()));
  
          m_normalized = ecs_type_add(m_world, m_normalized, 
              ecs_trait(_::component_info<C>::id(), trait.id()));
          
          sync_from_me();
          return *this;
      }            
  
      template <typename ... Components>
      type& add() {
          std::stringstream str;
          if (!_::pack_args_to_string<Components...>(m_world, str)) {
              ecs_abort(ECS_INVALID_PARAMETER, NULL);
          }
  
          std::string expr = str.str();
          ecs_type_t t = ecs_type_from_str(m_world, expr.c_str());
          m_type = ecs_type_merge(m_world, m_type, t, nullptr);
          m_normalized = ecs_type_merge(m_world, m_normalized, t, nullptr);
          sync_from_me();
  
          return *this;
      }    
  
      std::string str() const {
          char *str = ecs_type_str(m_world, m_type);
          std::string result(str);
          ecs_os_free(str);
          return result;
      }
  
      type_t c_ptr() const {
          return m_type;
      }
  
      // Expose entity id without making the entity class public.
      entity_t id() const {
          return m_id;
      }
  
      type_t c_normalized() const {
          return m_normalized;
      }
  
      void enable() const {
          ecs_assert(m_id != 0, ECS_INVALID_OPERATION, NULL);
          ecs_enable(m_world, m_id, true);
      }
  
      void disable() const {
          ecs_assert(m_id != 0, ECS_INVALID_OPERATION, NULL);
          ecs_enable(m_world, m_id, false);
      }
  
      flecs::vector<entity_t> vector() {
          return flecs::vector<entity_t>( (ecs_vector_t*)m_normalized );
      }
  
  private:
      void sync_from_me() {
          ecs_assert(m_id != 0, ECS_INVALID_OPERATION, NULL);
          EcsType *tc = ecs_get_mut(m_world, m_id, EcsType, NULL);
          if (tc) {
              tc->type = m_type;
              tc->normalized = m_normalized;
          }
      }
  
      void sync_from_flecs() {
          ecs_assert(m_id != 0, ECS_INVALID_OPERATION, NULL);
          EcsType *tc = ecs_get_mut(m_world, m_id, EcsType, NULL);
          if (tc) {
              m_type = tc->type;
              m_normalized = tc->normalized;
          }
      }    
  
      type_t m_type;
      type_t m_normalized;
  };
  
  
  ////////////////////////////////////////////////////////////////////////////////
  //// Entity range, allows for operating on a range of consecutive entities
  ////////////////////////////////////////////////////////////////////////////////
  
  class entity_range final : public entity_builder<entity_range> {
  public:
      entity_range(const world& world, std::int32_t count) 
          : m_world(world.c_ptr())
          , m_ids( ecs_bulk_new_w_type(m_world, nullptr, count))
          , m_count(count) { }
  
      entity_range(const world& world, std::int32_t count, flecs::type type) 
          : m_world(world.c_ptr())
          , m_ids( ecs_bulk_new_w_type(m_world, type.c_ptr(), count))
          , m_count(count) { }
  
      template <typename Func>
      void invoke(Func&& action) const {
          for (int i = 0; i < m_count; i ++) {
              action(m_world, m_ids[i]);
          }
      }
  
  private:
      world_t *m_world;
      const entity_t *m_ids;
      std::int32_t m_count;
  };
  
  
  ////////////////////////////////////////////////////////////////////////////////
  //// Register component, provide global access to component handles / metadata
  ////////////////////////////////////////////////////////////////////////////////
  
  namespace _
  {
      // Trick to obtain typename from type, as described here
      // https://blog.molecular-matters.com/2015/12/11/getting-the-type-of-a-template-argument-as-string-without-rtti/
      //
      // The code from the link has been modified to work with more types, and across
      // multiple compilers.
      //
      struct name_util {
          /* Remove parts from typename that aren't needed for component name */
          static void trim_name(char *typeName) {
              ecs_size_t len = ecs_os_strlen(typeName);
              
              /* Remove 'const' */
              ecs_size_t const_len = ecs_os_strlen("const ");
              if ((len > const_len) && !ecs_os_strncmp(typeName, "const ", const_len)) {
                  ecs_os_memmove(typeName, typeName + const_len, len - const_len);
                  typeName[len - const_len] = '\0';
                  len -= const_len;
              }
  
              /* Remove 'struct' */
              ecs_size_t struct_len = ecs_os_strlen("struct ");
              if ((len > struct_len) && !ecs_os_strncmp(typeName, "struct ", struct_len)) {
                  ecs_os_memmove(typeName, typeName + struct_len, len - struct_len);
                  typeName[len - struct_len] = '\0';
                  len -= struct_len;
              }
  
              /* Remove 'class' */
              ecs_size_t class_len = ecs_os_strlen("class ");
              if ((len > class_len) && !ecs_os_strncmp(typeName, "class ", class_len)) {
                  ecs_os_memmove(typeName, typeName + class_len, len - class_len);
                  typeName[len - class_len] = '\0';
                  len -= class_len;
              }            
  
              while (typeName[len - 1] == ' ' ||
                     typeName[len - 1] == '&' ||
                     typeName[len - 1] == '*') 
              {
                  len --;
                  typeName[len] = '\0';
              }
  
              /* Remove const at end of string */
              if (len > const_len) {
                  if (!ecs_os_strncmp(&typeName[len - const_len], " const", const_len)) {
                      typeName[len - const_len] = '\0';
                  }
              }
          }
      };
  
  // Compiler-specific conversion from __PRETTY_FUNCTION__ to component name. 
  // This code uses a trick that instantiates a function for the component type. 
  // Then __PRETTY_FUNCTION__ is used to obtain the name of the function. Because
  // the result of __PRETTY_FUNCTION__ is not standardized, there are different
  // implementations for clang, gcc and msvc. Code that uses a different compiler
  // needs to register component names explicitly.
  #if defined(__clang__)
    static const unsigned int FRONT_SIZE = sizeof("static const char* flecs::_::name_helper<") - 1u;
    static const unsigned int BACK_SIZE = sizeof(">::name() [T = ]") - 1u;
   
    template <typename T>
    struct name_helper
    {
      static const char* name(void) {
        static const size_t size = (sizeof(__PRETTY_FUNCTION__) - FRONT_SIZE - BACK_SIZE) / 2 + 1u;
        static char typeName[size + 6] = {};
        memcpy(typeName, __PRETTY_FUNCTION__ + FRONT_SIZE, size - 1u);
        name_util::trim_name(typeName);
        return typeName;
      }
    };    
  #elif defined(__GNUC__)
    static const unsigned int FRONT_SIZE = sizeof("static const char* flecs::_::name_helper<T>::name() [with T = ") - 1u;
    static const unsigned int BACK_SIZE = sizeof("]") - 1u;
   
    template <typename T>
    struct name_helper
    {
      static const char* name(void) {
        static const size_t size = sizeof(__PRETTY_FUNCTION__) - FRONT_SIZE - BACK_SIZE;
        static char typeName[size + 6] = {};
        memcpy(typeName, __PRETTY_FUNCTION__ + FRONT_SIZE, size - 1u);
        name_util::trim_name(typeName);
        return typeName;
      }
    };
  #elif defined(_WIN32)
    static const unsigned int FRONT_SIZE = sizeof("flecs::_::name_helper<") - 1u;
    static const unsigned int BACK_SIZE = sizeof(">::name") - 1u;
   
    template <typename T>
    struct name_helper
    {
      static const char* name(void) {
        static const size_t size = sizeof(__FUNCTION__) - FRONT_SIZE - BACK_SIZE;
        static char typeName[size + 6] = {};
        memcpy(typeName, __FUNCTION__ + FRONT_SIZE, size - 1u);
        name_util::trim_name(typeName);
        return typeName;
      }
    };
  #else
  #error "implicit component registration not supported"
  #endif
  
  // Translate a typename into a langauge-agnostic identifier. This allows for
  // registration of components/modules across language boundaries.
  template <typename T>
  struct symbol_helper
  {
      static char* symbol(void) {
          const char *name = name_helper<T>::name();
  
          // Symbol is same as name, but with '::' replaced with '.'
          char *ptr, *sym = ecs_os_strdup(name);
          ecs_size_t i, len = ecs_os_strlen(sym);
          ptr = sym;
          for (i = 0, ptr = sym; i < len && *ptr; i ++, ptr ++) {
              if (*ptr == ':') {
                  sym[i] = '.';
                  ptr ++;
              } else {
                  sym[i] = *ptr;
              }
          }
  
          sym[i] = '\0';
  
          return sym;
      }
  };
  
  // The following functions are lifecycle callbacks that are automatically
  // registered with flecs to ensure component lifecycle is handled correctly. Not
  // all types require this, yet callbacks are registered by default, which
  // introduces some overhead when working with components.
  //
  // An application can optimize this by explicitly registering a component as a
  // plain old datatype, with world.pod_component<T>().
  
  template <typename T>
  void component_ctor(
      ecs_world_t *world,
      ecs_entity_t component,
      const ecs_entity_t *entity_ptr,
      void *ptr,
      size_t size,
      int32_t count,
      void *ctx)
  {
      (void)world;
      (void)component;
      (void)entity_ptr;
      (void)size;
      (void)ctx;
  
      ecs_assert(size == sizeof(T), ECS_INTERNAL_ERROR, NULL);
      T *t_ptr = static_cast<T*>(ptr);
      
      for (int i = 0; i < count; i ++) {
          FLECS_PLACEMENT_NEW(&t_ptr[i], T);
      }
  } 
  
  template <typename T>
  void component_dtor(
      ecs_world_t *world,
      ecs_entity_t component,
      const ecs_entity_t *entity_ptr,
      void *ptr,
      size_t size,
      int32_t count,
      void *ctx)
  {
      (void)world;
      (void)component;
      (void)entity_ptr;
      (void)size;
      (void)ctx;
  
      ecs_assert(size == sizeof(T), ECS_INTERNAL_ERROR, NULL);
      T *t_ptr = static_cast<T*>(ptr);
      
      for (int i = 0; i < count; i ++) {
          t_ptr[i].~T();
      }
  }
  
  template <typename T>
  void component_copy(
      ecs_world_t *world,
      ecs_entity_t component,    
      const ecs_entity_t *dst_entity,
      const ecs_entity_t *src_entity,
      void *dst_ptr,
      const void *src_ptr,
      size_t size,
      int32_t count,
      void *ctx)
  {
      (void)world;
      (void)component;
      (void)dst_entity;
      (void)src_entity;
      (void)size;
      (void)ctx;
  
      ecs_assert(size == sizeof(T), ECS_INTERNAL_ERROR, NULL);
      T *t_dst_ptr = static_cast<T*>(dst_ptr);
      const T *t_src_ptr = static_cast<const T*>(src_ptr);
      
      for (int i = 0; i < count; i ++) {
          t_dst_ptr[i] = t_src_ptr[i];
      }
  }
  
  template <typename T>
  void component_move(
      ecs_world_t *world,
      ecs_entity_t component,    
      const ecs_entity_t *dst_entity,
      const ecs_entity_t *src_entity,
      void *dst_ptr,
      void *src_ptr,
      size_t size,
      int32_t count,
      void *ctx)
  {
      (void)world;
      (void)component;
      (void)dst_entity;
      (void)src_entity;
      (void)size;
      (void)ctx;
  
      ecs_assert(size == sizeof(T), ECS_INTERNAL_ERROR, NULL);
      T *t_dst_ptr = static_cast<T*>(dst_ptr);
      T *t_src_ptr = static_cast<T*>(src_ptr);
      
      for (int i = 0; i < count; i ++) {
          t_dst_ptr[i] = std::move(t_src_ptr[i]);
      }
  }
  
  // Register component lifecycle callbacks with flecs.
  template<typename T>
  void register_lifecycle_actions(
      ecs_world_t *world,
      ecs_entity_t component,
      bool ctor,
      bool dtor,
      bool copy,
      bool move)
  {
      if (!ecs_component_has_actions(world, component)) {
          EcsComponentLifecycle cl{};
          if (ctor) {
              cl.ctor = _::component_ctor<
                  typename std::remove_const<
                      typename std::remove_pointer<T>::type>::type>;
          }
          if (dtor) {
              cl.dtor = _::component_dtor<
                  typename std::remove_const<
                      typename std::remove_pointer<T>::type>::type>;
          }
          if (copy) {
              cl.copy = _::component_copy<
                  typename std::remove_const<
                      typename std::remove_pointer<T>::type>::type>;
          }
          if (move) {
              cl.move = _::component_move<
                  typename std::remove_const<
                      typename std::remove_pointer<T>::type>::type>;
          }
  
          ecs_set_component_actions_w_entity( world, component, &cl);
      }
  }
  
  // Class that holds component identifier and name.
  // This class is used by most component operations to obtain the component id in
  // a transparent way for the application. The component id is stored in a static
  // member of a class, and is shared by all worlds in an application. As such,
  // each world in an application must (and will) have the same id.
  //
  // Because of how global (templated) variables are instantiated, it is possible
  // that different instances for the same component exist across different
  // translation units. This is handled transparently by flecs. When a component
  // id is requested from the component_info class, but the id is uninitialized, a 
  // lookup by name will be performed for the component on the world, which will 
  // return the id with which the component was already registered. This means 
  // component identifiers are eventually consistent across translation units.
  //
  // When a component id is requested for a world that had not yet registered the
  // component, it will be registered with the existing identifier. This ensures
  // that multiple worlds in the same application use the same component ids.
  //
  // There are a few limitations of this approach.
  //
  // 1) When two worlds register components in different orders, it is possible
  //    that different components receive the same identifier. When a world 
  //    attempts to re-register a component with a different identifier, an error
  //    will be thrown. To prevent this from happening, worlds should register
  //    components in the same order.
  //
  // 2) Component names are used to ensure that different translation units use
  //    the same identifiers. If a component is registered under different names
  //    in the same application, id conflicts can occur.
  //
  // Known issues:
  //
  // It seems like component registration does not always work correctly in Unreal
  // engine when recreating a world. A plausible cause for this is the hot 
  // reloading of dynamic libraries by the engine. A workaround for this issue is
  // to call flecs::_::component_info<T>::reset() before recreating the world.
  // This will reset the global component state and avoids conflicts. The exact
  // cause of the issue is investigated here: 
  //   https://github.com/SanderMertens/flecs/issues/293
  
  template <typename T>
  class component_info final {
  public:
      // Initialize component identifier
      static void init(world_t* world, entity_t entity, bool allow_tag = true) {
          // If an identifier was already set, check for consistency
          if (s_id) {
              // If an identifier was registered, a name should've been registered
              // as well.
              ecs_assert(s_name.c_str() != nullptr, ECS_INTERNAL_ERROR, NULL);
  
              // A component cannot be registered using a different identifier.
              ecs_assert(s_id == entity, ECS_INCONSISTENT_COMPONENT_ID, 
                  _::name_helper<T>::name());
  
              ecs_assert(allow_tag == s_allow_tag, ECS_INTERNAL_ERROR, NULL);
  
              // Component was already registered and data is consistent with new
              // identifier, so nothing else to be done.
              return;
          }
  
          // Component wasn't registered yet, set the values. Register component
          // name as the fully qualified flecs path.
          char *path = ecs_get_fullpath(world, entity);
          s_id = entity;
          s_name = path;
          s_allow_tag = allow_tag;
  
          // s_name is an std::string, so it will have made a copy
          ecs_os_free(path);
      }
  
      // Obtain a component identifier without registering lifecycle callbacks.
      static entity_t id_no_lifecycle(world_t *world = nullptr, 
          const char *name = nullptr, bool allow_tag = true) 
      {
          // If no id has been registered yet, do it now.
          if (!s_id) {
              const char *n = _::name_helper<T>::name();
              
              if (!name) {
                  // If no name was provided, retrieve the name implicitly from
                  // the name_helper class.
                  name = n;
              }
  
              s_allow_tag = allow_tag;
  
              // If no world was provided, we can't implicitly register the 
              // component. While there are a few cases where calling this 
              // function without a world is OK, in general functions should 
              // always provide a world to enable implicit registration.
              ecs_assert(world != nullptr, ECS_COMPONENT_NOT_REGISTERED, name);
  
              // Create entity with name first. This ensurs that the component is
              // created in the right location in the hierarchy, in case a scoped
              // name is used. This allows registering components with the same
              // name in different namespaces.
              //
              // If the component was already registered for this world, this will 
              // resolve the existing component identifier. This enables 
              // transparent component registeration across multiple translation 
              // units, as long as the same world is used.
              //
              // The last parameter ('true') ensures that when the component was
              // not yet registered, a new component identifier is created. 
              // Component identifiers and entity identifiers are equivalent,
              // though a pool of identifiers at the start of the id range is 
              // reserved for components. This is a performance optimization, as
              // low ids in some parts of the code allow for direct indexing.
              flecs::world w(world);
              flecs::entity result = entity(w, name, true);
              
              // Init the component_info instance with the identiifer.
              init(world, result.id(), allow_tag);
  
              // Now use the resulting identifier to register the component. Note
              // that the name is not passed into this function, as the entity was
              // already created with the correct name.
              ecs_entity_t entity = ecs_new_component(
                  world, result.id(), nullptr, 
                  size(), 
                  alignment());
  
              ecs_assert(entity != 0, ECS_INTERNAL_ERROR, NULL);
  
              // Set the symbol in the Name component to the actual C++ name.
              // Comparing symbols allows for verifying whether a different 
              // component is being registered under the same name. We can't use
              // the name used for registration, because it is possible that a
              // user (erroneously) attempts to register the same datatype with
              // the same name. Without verifying that the actual C++ type name
              // matches, that scenario would go undetected.
              EcsName *name_comp = ecs_get_mut(world, entity, EcsName, NULL);
              char *symbol = symbol_helper<T>::symbol();
  
              if (name_comp->symbol) {
                  ecs_assert( !strcmp(name_comp->symbol, symbol), 
                      ECS_COMPONENT_NAME_IN_USE, name);
              } else {
                  name_comp->symbol = symbol;
              }
              
              // The identifier returned by the function should be the same as the
              // identifier that was passed in.
              ecs_assert(entity == result.id(), ECS_INTERNAL_ERROR, NULL);
  
          } else if (world && !ecs_exists(world, s_id)) {
              const char *n = _::name_helper<T>::name();
              
              if (!name) {
                  // If no name was provided, retrieve the name implicitly from
                  // the name_helper class.
                  name = n;
              }
  
              ecs_entity_t entity = ecs_new_component(
                  world, s_id, name,
                  size(), 
                  alignment());
                  
              (void)entity;
  
              ecs_assert(entity == s_id, ECS_INTERNAL_ERROR, NULL);
  
              init(world, s_id, allow_tag);
          }
  
          // By now we should have a valid identifier
          ecs_assert(s_id != 0, ECS_INTERNAL_ERROR, NULL);
  
          return s_id;
      }
  
      // Obtain a component identifier, register lifecycle callbacks if this is
      // the first time the component is used.
      static entity_t id(world_t *world = nullptr, const char *name = nullptr, 
          bool allow_tag = true) 
      {
          // If no id has been registered yet, do it now.
          if (!s_id || (world && !ecs_exists(world, s_id))) {
              // This will register a component id, but will not register 
              // lifecycle callbacks.
              id_no_lifecycle(world, name, allow_tag);
  
              // Register lifecycle callbacks, but only if the component has a
              // size. Components that don't have a size are tags, and tags don't
              // require construction/destruction/copy/move's. */
              if (size()) {
                  register_lifecycle_actions<T>(world, s_id,
                      true, true, true, true);
              }
          }
  
          // By now we should have a valid identifier
          ecs_assert(s_id != 0, ECS_INTERNAL_ERROR, NULL);
  
          return s_id;
      }
  
      // Obtain a component name
      static const char* name(world_t *world = nullptr) {
          // If no id has been registered yet, do it now.
          if (!s_id) {
              id(world);
          }
  
          // By now we should have a valid identifier
          ecs_assert(s_id != 0, ECS_INTERNAL_ERROR, NULL);
  
          // If the id is set, the name should also have been set
          return s_name.c_str();
      }
  
      // Obtain a component name, don't register lifecycle if the component hadn't
      // been registered yet. While functionally the same could be achieved by
      // first calling id_no_lifecycle() and then name(), this function ensures
      // that the lifecycle callback templates are not instantiated. This allows
      // some types (such as module classes) to be created without a default
      // constructor.
      static const char* name_no_lifecycle(world_t *world = nullptr) {
          // If no id has been registered yet, do it now.
          if (!s_id) {
              id_no_lifecycle(world);
          }
  
          // By now we should have a valid identifier
          ecs_assert(s_id != 0, ECS_INTERNAL_ERROR, NULL);
  
          // Return 
          return s_name.c_str();
      }    
  
      // Return the type of a component.
      // The type is a vector of component ids. This will return a type with just
      // the current component id.
      static type_t type(world_t *world = nullptr) {
          // If no id has been registered yet, do it now.
          if (!s_id) {
              id(world);
          }
  
          // By now we should have a valid identifier
          ecs_assert(s_id != 0, ECS_INTERNAL_ERROR, NULL);        
  
          // Create a type from the component id.
          if (!s_type) {
              s_type = ecs_type_from_entity(world, s_id);
          }
  
          ecs_assert(s_type != nullptr, ECS_INTERNAL_ERROR, NULL);
  
          return s_type;
      }
  
      // Return the size of a component.
      static size_t size() {
          ecs_assert(s_id != 0, ECS_INTERNAL_ERROR, NULL);
          
          // C++ types that have no members still have a size. Use std::is_empty
          // to check if the type is empty. If so, use 0 for the component size.
          //
          // If s_allow_tag is set to false, the size returned by C++ is used.
          // This is useful in cases where class instances are still required, as
          // is the case with module classes.
          if (s_allow_tag && std::is_empty<T>::value) {
              return 0;
          } else {
              return sizeof(typename std::remove_pointer<T>::type);
          }
      }
  
      // Return the alignment of a component.
      static size_t alignment() {
          ecs_assert(s_id != 0, ECS_INTERNAL_ERROR, NULL);
  
          if (size() == 0) {
              return 0;
          } else {
              return alignof(typename std::remove_pointer<T>::type);
          }
      }
  
      // Was the component already registered.
      static bool registered() {
          return s_id != 0;
      }
  
      // This function is only used to test cross-translation unit features. No
      // code other than test cases should invoke this function.
      static void reset() {
          s_id = 0;
          s_type = NULL;
          s_name.clear();
      }
  
  private:
      static entity_t s_id;
      static type_t s_type;
      static std::string s_name;
      static std::string s_symbol;
      static bool s_allow_tag;
  };
  
  // Global templated variables that hold component identifier and other info
  template <typename T> entity_t component_info<T>::s_id( 0 );
  template <typename T> type_t component_info<T>::s_type( nullptr );
  template <typename T> std::string component_info<T>::s_name("");
  template <typename T> bool component_info<T>::s_allow_tag( true );
  
  
  ////////////////////////////////////////////////////////////////////////////////
  //// Register a component with flecs
  ////////////////////////////////////////////////////////////////////////////////
  
  } // namespace _
  
  /** Plain old datatype, no lifecycle actions are registered */
  template <typename T>
  flecs::entity pod_component(const flecs::world& world, const char *name = nullptr, bool allow_tag = true) {
      if (!name) {
          name = _::name_helper<T>::name();
      }
  
      world_t *world_ptr = world.c_ptr();
      entity_t id = 0;
  
      if (_::component_info<T>::registered()) {
          /* Obtain component id. Because the component is already registered,
           * this operation does nothing besides returning the existing id */
          id = _::component_info<T>::id_no_lifecycle(world_ptr, name, allow_tag);
  
          /* If entity is not empty check if the name matches */
          if (ecs_get_type(world_ptr, id) != nullptr) {
              if (id >= EcsFirstUserComponentId) {
                  char *path = ecs_get_path_w_sep(
                      world_ptr, 0, id, 0, "::", nullptr);
                  ecs_assert(!strcmp(path, name), 
                      ECS_INCONSISTENT_COMPONENT_NAME, name);
                  ecs_os_free(path);
              }
          }
  
          /* Register name with entity, so that when the entity is created the
           * correct id will be resolved from the name. */
          ecs_add_path_w_sep(world_ptr, id, 0, name, "::", "::");
  
          /* If a component was already registered with this id but with a 
           * different size, the ecs_new_component function will fail. */
  
          /* We need to explicitly call ecs_new_component here again. Even though
           * the component was already registered, it may have been registered
           * with a different world. This ensures that the component is registered
           * with the same id for the current world. 
           * If the component was registered already, nothing will change. */
          ecs_entity_t entity = ecs_new_component(
              world.c_ptr(), id, nullptr, 
              _::component_info<T>::size(), 
              _::component_info<T>::alignment());
          
          (void)entity;
          
          ecs_assert(entity == id, ECS_INTERNAL_ERROR, NULL);
  
          /* This functionality could have been put in id_no_lifecycle, but since
           * this code happens when a component is registered, and the entire API
           * calls id_no_lifecycle, this would add a lot of overhead to each call.
           * This is why when using multiple worlds, components should be 
           * registered explicitly. */
      } else {
          /* If the component is not yet registered, ensure no other component
           * or entity has been registered with this name */
          ecs_entity_t entity = ecs_lookup_fullpath(world_ptr, name);
  
          /* If entity exists, compare symbol name to ensure that the component
           * we are trying to register under this name is the same */
          if (entity) {
              const EcsName *name_comp = ecs_get_mut(world.c_ptr(), entity, EcsName, NULL);
              ecs_assert(name_comp != NULL, ECS_INTERNAL_ERROR, NULL);
              ecs_assert(name_comp->symbol != NULL, ECS_INTERNAL_ERROR, NULL);
  
              const char *symbol = _::name_helper<T>::name();
  
              ecs_assert(!strcmp(name_comp->symbol, symbol), 
                  ECS_COMPONENT_NAME_IN_USE, name);
  
              (void)name_comp;
              (void)symbol;
          }
  
          /* Register id as usual */
          id = _::component_info<T>::id_no_lifecycle(world_ptr, name, allow_tag);
      }
  
      _::component_info<T>::init(world_ptr, id, allow_tag);
      _::component_info<const T>::init(world_ptr, id, allow_tag);
      _::component_info<T*>::init(world_ptr, id, allow_tag);
      _::component_info<T&>::init(world_ptr, id, allow_tag);
      
      return world.entity(id);
  }
  
  /** Regular component with ctor, dtor copy and move actions */
  template <typename T>
  flecs::entity component(const flecs::world& world, const char *name = nullptr) {
      flecs::entity result = pod_component<T>(world, name);
  
      if (_::component_info<T>::size()) {
          _::register_lifecycle_actions<T>(world.c_ptr(), result.id(),
              true, true, true, true);
      }
  
      return result;
  }
  
  /** Trivially relocatable component that can be memcpy'd. */
  template <typename T>
  flecs::entity relocatable_component(const flecs::world& world, const char *name = nullptr) {
      flecs::entity result = pod_component<T>(world, name);
  
      _::register_lifecycle_actions<T>(world.c_ptr(), result.id(),
          true, true, true, false);
  
      return result;
  }
  
  template <typename T>
  flecs::entity_t type_id() {
      return _::component_info<T>::id();
  }
  
  
  ////////////////////////////////////////////////////////////////////////////////
  //// Define a module
  ////////////////////////////////////////////////////////////////////////////////
  
  template <typename T>
  flecs::entity module(const flecs::world& world, const char *name = nullptr) {
      ecs_set_scope(world.c_ptr(), 0);
      flecs::entity result = pod_component<T>(world, name, false);
      ecs_set_scope(world.c_ptr(), result.id());
      return result;
  }
  
  
  ////////////////////////////////////////////////////////////////////////////////
  //// Import a module
  ////////////////////////////////////////////////////////////////////////////////
  
  template <typename T>
  ecs_entity_t do_import(world& world) {
      ecs_trace_1("import %s", _::name_helper<T>::name());
      ecs_log_push();
  
      ecs_entity_t scope = ecs_get_scope(world.c_ptr());
  
      // Allocate module, so the this ptr will remain stable
      // TODO: make sure memory is cleaned up with world
      T *module_data = FLECS_NEW(T)(world);
  
      ecs_set_scope(world.c_ptr(), scope);
  
      // It should now be possible to lookup the module
      char *symbol = _::symbol_helper<T>::symbol();
      ecs_entity_t m = ecs_lookup_symbol(world.c_ptr(), symbol);
      ecs_assert(m != 0, ECS_MODULE_UNDEFINED, symbol);
      ecs_os_free(symbol);
  
      _::component_info<T>::init(world.c_ptr(), m, false);
  
      ecs_assert(_::component_info<T>::size() != 0, ECS_INTERNAL_ERROR, NULL);
  
      // Set module singleton component
  
      ecs_set_ptr_w_entity(
          world.c_ptr(), m,
          _::component_info<T>::id_no_lifecycle(world.c_ptr()), 
          _::component_info<T>::size(),
          module_data);
  
      ecs_log_pop();     
  
      return m;
  }
  
  template <typename T>
  flecs::entity import(world& world) {
      const char *symbol = _::name_helper<T>::name();
  
      ecs_entity_t m = ecs_lookup_symbol(world.c_ptr(), symbol);
      
      if (!_::component_info<T>::registered()) {
  
          /* Module is registered with world, initialize static data */
          if (m) {
              _::component_info<T>::init(world.c_ptr(), m, false);
          
          /* Module is not yet registered, register it now */
          } else {
              m = do_import<T>(world);
          }
  
      /* Module has been registered, but could have been for another world. Import
       * if module hasn't been registered for this world. */
      } else if (!m) {
          m = do_import<T>(world);
      }
  
      return flecs::entity(world, m);
  }
  
  
  ////////////////////////////////////////////////////////////////////////////////
  //// A filter is used to match subsets of tables
  ////////////////////////////////////////////////////////////////////////////////
   
  class filter {
  public:
      filter() 
          : m_world( nullptr )
          , m_filter{ } {}
  
      explicit filter(const world& world) 
          : m_world( world.c_ptr() )
          , m_filter{ } { }
  
      filter& include(type type) {
          m_filter.include = ecs_type_merge(m_world, m_filter.include, type.c_ptr(), nullptr);
          return *this;
      }
  
      filter& include(entity entity) {
          m_filter.include = ecs_type_add(m_world, m_filter.include, entity.id());
          return *this;
      }
  
      template <typename T>
      filter& include() {
          m_filter.include = ecs_type_add(m_world, m_filter.include, _::component_info<T>::id(m_world));
          return *this;
      }
  
      filter& include_kind(match_kind kind) {
          m_filter.include_kind = static_cast<ecs_match_kind_t>(kind);
          return *this;
      }
  
      type include() {
          return type(m_world, m_filter.include);
      }
  
      filter& exclude(type type) {
          m_filter.exclude = ecs_type_merge(m_world, m_filter.exclude, type.c_ptr(), nullptr);
          return *this;
      }
  
      filter& exclude(entity entity) {
          m_filter.exclude = ecs_type_add(m_world, m_filter.exclude, entity.id());
          return *this;
      }
  
      template <typename T>
      filter& exclude() {
          m_filter.exclude = ecs_type_add(m_world, m_filter.exclude, _::component_info<T>::id(m_world));
          return *this;
      }
   
      filter& exclude_kind(match_kind kind) {
          m_filter.exclude_kind = static_cast<ecs_match_kind_t>(kind);
          return *this;
      }
  
      type exclude() {
          return type(m_world, m_filter.exclude);
      }  
  
      const filter_t* c_ptr() const {
          if (m_world) {
              return &m_filter;
          } else {
              return nullptr;
          }
      }
  
  private:
      world_t *m_world;
      filter_t m_filter;
  };
  
  
  ////////////////////////////////////////////////////////////////////////////////
  //// Utility to convert template argument pack to array of columns
  ////////////////////////////////////////////////////////////////////////////////
  
  namespace _ {
  
  template <typename ... Components>
  class column_args {
  public:    
      struct Column {
          void *ptr;
          bool is_shared;
      };
  
      using Columns = std::array<Column, sizeof...(Components)>;
  
      column_args(ecs_iter_t* iter) {
          populate_columns(iter, 0, (typename std::remove_reference<typename std::remove_pointer<Components>::type>::type*)nullptr...);
      }
  
      Columns m_columns;
  
  private:
      /* Dummy function when last component has been added */
      void populate_columns(ecs_iter_t *iter, size_t index) { 
          (void)iter;
          (void)index;
      }
  
      /* Populate columns array recursively */
      template <typename T, typename... Targs>
      void populate_columns(ecs_iter_t *iter, size_t index, T comp, Targs... comps) {
          int32_t column = static_cast<int32_t>(index + 1);
          void *ptr = ecs_column_w_size(iter, sizeof(*comp), column);
          m_columns[index].ptr = ptr;
          m_columns[index].is_shared = !ecs_is_owned(iter, column) && ptr != nullptr;
          populate_columns(iter, index + 1, comps ...);
      }
  };
  
  ////////////////////////////////////////////////////////////////////////////////
  //// Utility class to invoke a system each
  ////////////////////////////////////////////////////////////////////////////////
  
  template <typename Func, typename ... Components>
  class each_invoker {
      using Columns = typename column_args<Components ...>::Columns;
  
  public:
      explicit each_invoker(Func&& func) noexcept : m_func(std::move(func)) { }
      explicit each_invoker(const Func& func) noexcept : m_func(func) { }
  
      // Invoke system
      template <typename... Targs,
          typename std::enable_if<sizeof...(Targs) == sizeof...(Components), void>::type* = nullptr>
      static void call_system(ecs_iter_t *iter, const Func& func, size_t index, Columns& columns, Targs... comps) {
          flecs::iter iter_wrapper(iter);
          (void)index;
          (void)columns;
  
          // Use any_column so we can transparently use shared components
          for (auto row : iter_wrapper) {
              func(iter_wrapper.entity(row), (_::any_column<typename std::remove_reference<Components>::type>(
                   (typename std::remove_reference< typename std::remove_pointer<Components>::type >::type*)comps.ptr, 
                      static_cast<size_t>(iter->count), comps.is_shared))[row]...);
          }
      }
  
      // Add components one by one to parameter pack
      template <typename... Targs,
          typename std::enable_if<sizeof...(Targs) != sizeof...(Components), void>::type* = nullptr>
      static void call_system(ecs_iter_t *iter, const Func& func, size_t index, Columns& columns, Targs... comps) {
          each_invoker::call_system(iter, func, index + 1, columns, comps..., columns[index]);
      }
  
      // Callback provided to flecs system
      static void run(ecs_iter_t *iter) {
          const Context *ctx = ecs_get(iter->world, iter->system, EcsContext);
          each_invoker *self = (each_invoker*)ctx->ctx;
          column_args<Components...> columns(iter);
          call_system(iter, self->m_func, 0, columns.m_columns);
      }
  
  private:
      Func m_func;
  };
  
  
  ////////////////////////////////////////////////////////////////////////////////
  //// Utility class to invoke a system action
  ////////////////////////////////////////////////////////////////////////////////
  
  template <typename Func, typename ... Components>
  class action_invoker {
      using Columns = typename column_args<Components ...>::Columns;
  
  public:
      explicit action_invoker(Func&& func) noexcept : m_func(std::move(func)) { }
      explicit action_invoker(const Func& func) noexcept : m_func(func) { }
  
      /* Invoke system */
      template <typename... Targs,
          typename std::enable_if<sizeof...(Targs) == sizeof...(Components), void>::type* = nullptr>
      static void call_system(ecs_iter_t *iter, const Func& func, int index, Columns& columns, Targs... comps) {
          (void)index;
          (void)columns;
  
          flecs::iter iter_wrapper(iter);
          
          func(iter_wrapper, (column<typename std::remove_reference< typename std::remove_pointer<Components>::type >::type>(
              (typename std::remove_reference< typename std::remove_pointer<Components>::type >::type*)comps.ptr, iter->count, comps.is_shared))...);
      }
  
      /** Add components one by one to parameter pack */
      template <typename... Targs,
          typename std::enable_if<sizeof...(Targs) != sizeof...(Components), void>::type* = nullptr>
      static void call_system(ecs_iter_t *iter, const Func& func, int index, Columns& columns, Targs... comps) {
          call_system(iter, func, index + 1, columns, comps..., columns[index]);
      }
  
      /** Callback provided to flecs */
      static void run(ecs_iter_t *iter) {
          const Context *ctx = ecs_get(iter->world, iter->system, EcsContext);
          action_invoker *self = (action_invoker*)ctx->ctx;
          column_args<Components...> columns(iter);
          call_system(iter, self->m_func, 0, columns.m_columns);
      }
  
  private:
      Func m_func;
  };
  
  ////////////////////////////////////////////////////////////////////////////////
  //// Utility class to invoke a system iterate action
  ////////////////////////////////////////////////////////////////////////////////
  
  template <typename Func, typename ... Components>
  class iter_invoker {
      using Columns = typename column_args<Components ...>::Columns;
  
  public:
      explicit iter_invoker(Func&& func) noexcept : m_func(std::move(func)) { }
      explicit iter_invoker(const Func& func) noexcept : m_func(func) { }
  
      /* Invoke system */
      template <typename... Targs,
          typename std::enable_if<sizeof...(Targs) == sizeof...(Components), void>::type* = nullptr>
      static void call_system(ecs_iter_t *iter, const Func& func, size_t index, Columns& columns, Targs... comps) {
          (void)index;
          (void)columns;
          flecs::iter iter_wrapper(iter);
          func(iter_wrapper, ((typename std::remove_reference< typename std::remove_pointer<Components>::type >::type*)comps.ptr)...);
      }
  
      /** Add components one by one to parameter pack */
      template <typename... Targs,
          typename std::enable_if<sizeof...(Targs) != sizeof...(Components), void>::type* = nullptr>
      static void call_system(ecs_iter_t *iter, const Func& func, size_t index, Columns& columns, Targs... comps) {
          call_system(iter, func, index + 1, columns, comps..., columns[index]);
      }
  
      /** Callback provided to flecs */
      static void run(ecs_iter_t *iter) {
          const Context *ctx = ecs_get(iter->world, iter->system, EcsContext);
          iter_invoker *self = (iter_invoker*)ctx->ctx;
          column_args<Components...> columns(iter);
          call_system(iter, self->m_func, 0, columns.m_columns);
      }
  
  private:
      Func m_func;
  };
  
  } // namespace _
  
  
  ////////////////////////////////////////////////////////////////////////////////
  //// Persistent queries
  ////////////////////////////////////////////////////////////////////////////////
  
  class query_base {
  public:
      query_base()
          : m_world(nullptr), m_query(nullptr) { }    
      
      query_base(world_t *world, query_t *query)
          : m_world(world), m_query(query) { }
  
      /** Get pointer to C query object.
       */
      query_t* c_ptr() const {
          return m_query;
      }
  
      /** 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. 
       * Resorting happens when a query iterator is obtained, and only if the table
       * data has changed.
       *
       * If multiple queries that match the same (sub)set of tables specify different 
       * sorting functions, resorting is likely to happen every time an iterator is
       * obtained, which can significantly slow down iterations.
       *
       * The sorting function will be applied to the specified component. Resorting
       * only happens if that component has changed, or when the entity order in the
       * table has changed. If no component is provided, resorting only happens when
       * the entity order changes.
       *
       * @tparam T The component used to sort.
       * @param compare The compare function used to sort the components.
       */
      template <typename T>
      void order_by(int(*compare)(flecs::entity_t, const T*, flecs::entity_t, const T*)) {
          ecs_query_order_by(m_world, m_query, 
              flecs::_::component_info<T>::id(m_world),
              (ecs_compare_action_t)compare);
      }
  
      /** Sort the output of a query.
       * Same as order_by<T>, but with component identifier.
       *
       * @param component The component used to sort.
       * @param compare The compare function used to sort the components.
       */
      void order_by(flecs::entity component, int(*compare)(flecs::entity_t, const void*, flecs::entity_t, const void*)) {
          ecs_query_order_by(m_world, m_query, component.id(), compare);
      }    
  
      /** Group and sort matched tables.
       * Similar yo ecs_query_order_by, but instead of sorting individual entities, this
       * operation only sorts matched tables. This can be useful of a query needs to
       * enforce a certain iteration order upon the tables it is iterating, for 
       * example by giving a certain component or tag a higher priority.
       *
       * The sorting function assigns a "rank" to each type, which is then used to
       * sort the tables. Tables with higher ranks will appear later in the iteration.
       * 
       * Resorting happens when a query iterator is obtained, and only if the set of
       * matched tables for a query has changed. If table sorting is enabled together
       * with entity sorting, table sorting takes precedence, and entities will be
       * sorted within each set of tables that are assigned the same rank.
       *
       * @tparam T The component used to determine the group rank.
       * @param rank The rank action.
       */
      template <typename T>
      void group_by(int(*rank)(flecs::world_t*, flecs::entity_t, flecs::type_t type)) {
          ecs_query_group_by(m_world, m_query, 
              flecs::_::component_info<T>::id(m_world), rank);
      }
  
      /** Group and sort matched tables.
       * Same as group_by<T>, but with component identifier.
       *
       * @param component The component used to determine the group rank.
       * @param rank The rank action.
       */
      void group_by(flecs::entity component, int(*rank)(flecs::world_t*, flecs::entity_t, flecs::type_t type)) {
          ecs_query_group_by(m_world, m_query, component.id(), rank);
      }
  
      /** Returns whether the query data changed since the last iteration.
       * This operation must be invoked before obtaining the iterator, as this will
       * reset the changed state. The operation will return true after:
       * - new entities have been matched with
       * - matched entities were deleted
       * - matched components were changed
       * 
       * @return true if entities changed, otherwise false.
       */
      bool changed() {
          return ecs_query_changed(m_query);
      }
  
      /** Returns whether query is orphaned.
       * When the parent query of a subquery is deleted, it is left in an orphaned
       * state. The only valid operation on an orphaned query is deleting it. Only
       * subqueries can be orphaned.
       *
       * @return true if query is orphaned, otherwise false.
       */
      bool orphaned() {
          return ecs_query_orphaned(m_query);
      }
  
      /** Free the query.
       */
      void destruct() {
          ecs_query_free(m_query);
          m_world = nullptr;
          m_query = nullptr;
      }
  
      template <typename Func>
      void iter(Func&& func) const {
          ecs_iter_t it = ecs_query_iter(m_query);
  
          while (ecs_query_next(&it)) {
              _::column_args<> columns(&it);
              _::iter_invoker<Func>::call_system(&it, func, 0, columns.m_columns);
          }
      }  
  
  protected:
      world_t *m_world;
      query_t *m_query;
  };
  
  template<typename ... Components>
  class query : public query_base {
      using Columns = typename _::column_args<Components...>::Columns;
  
  public:
      query() : query_base(nullptr, nullptr) { }
  
      explicit query(const world& world) {
          std::stringstream str;
          if (!_::pack_args_to_string<Components...>(world.c_ptr(), str, true)) {
              ecs_abort(ECS_INVALID_PARAMETER, NULL);
          }
  
          m_world = world.c_ptr();
          m_query = ecs_query_new(world.c_ptr(), str.str().c_str());
      }
  
      explicit query(const world& world, query_base& parent) {
          std::stringstream str;
          if (!_::pack_args_to_string<Components...>(world.c_ptr(), str, true)) {
              ecs_abort(ECS_INVALID_PARAMETER, NULL);
          }
  
          m_world = world.c_ptr();
          m_query = ecs_subquery_new(world.c_ptr(), parent.c_ptr(), str.str().c_str());
      }
  
      explicit query(const world& world, const char *expr) {
          std::stringstream str;
          m_world = world.c_ptr();
          if (!_::pack_args_to_string<Components...>(world.c_ptr(), str, true)) {
              m_query = ecs_query_new(world.c_ptr(), expr);
          } else {
              str << "," << expr;
              m_query = ecs_query_new(world.c_ptr(), str.str().c_str());
          }
      }
  
      explicit query(const world& world, query_base& parent, const char *expr) {
          std::stringstream str;
          m_world = world.c_ptr();
          if (!_::pack_args_to_string<Components...>(world.c_ptr(), str, true)) {
              m_query = ecs_subquery_new(world.c_ptr(), parent.c_ptr(), expr);
          } else {
              str << "," << expr;
              m_query = ecs_subquery_new(world.c_ptr(), parent.c_ptr(), str.str().c_str());
          }
      }
  
      query_iterator<Components...> begin() const;
  
      query_iterator<Components...> end() const;
  
      template <typename Func>
      void each(Func&& func) const {
          ecs_iter_t it = ecs_query_iter(m_query);
  
          while (ecs_query_next(&it)) {
              _::column_args<Components...> columns(&it);
              _::each_invoker<Func, Components...>::call_system(&it, func, 0, columns.m_columns);
          }
      }
  
      template <typename Func>
      void each(const flecs::filter& filter, Func&& func) const {
          ecs_iter_t it = ecs_query_iter(m_query);
          const filter_t* filter_ptr = filter.c_ptr();
  
          while (ecs_query_next_w_filter(&it, filter_ptr)) {
              _::column_args<Components...> columns(&it);
              _::each_invoker<Func, Components...>::call_system(&it, func, 0, columns.m_columns);
          }
      }
  
      /* DEPRECATED */
      template <typename Func>
      void action(Func&& func) const {
          ecs_iter_t it = ecs_query_iter(m_query);
  
          while (ecs_query_next(&it)) {
              _::column_args<Components...> columns(&it);
              _::action_invoker<Func, Components...>::call_system(&it, func, 0, columns.m_columns);
          }
      }
  
      template <typename Func>
      void iter(Func&& func) const {
          ecs_iter_t it = ecs_query_iter(m_query);
  
          while (ecs_query_next(&it)) {
              _::column_args<Components...> columns(&it);
              _::iter_invoker<Func, Components...>::call_system(&it, func, 0, columns.m_columns);
          }
      }
  
      template <typename Func>
      void iter(const flecs::filter& filter, Func&& func) const {
          ecs_iter_t it = ecs_query_iter(m_query);        
          const filter_t* filter_ptr = filter.c_ptr();
  
          while (ecs_query_next_w_filter(&it, filter_ptr)) {
              _::column_args<Components...> columns(&it);
              _::iter_invoker<Func, Components...>::call_system(&it, func, 0, columns.m_columns);
          }
      }
  };
  
  
  ////////////////////////////////////////////////////////////////////////////////
  //// Snapshots make a copy of the world state that can be restored
  ////////////////////////////////////////////////////////////////////////////////
  
  class snapshot final {
  public:
      explicit snapshot(const world& world)
          : m_world( world )
          , m_snapshot( nullptr ) { }
  
      snapshot(const snapshot& obj) 
          : m_world( obj.m_world )
      { 
          ecs_iter_t it = ecs_snapshot_iter(obj.m_snapshot, nullptr);
          m_snapshot = ecs_snapshot_take_w_iter(&it, ecs_snapshot_next);
      }
  
      snapshot(snapshot&& obj) 
          : m_world(obj.m_world)
          , m_snapshot(obj.m_snapshot)
      {
          obj.m_snapshot = nullptr;
      }
  
      snapshot& operator=(const snapshot& obj) {
          ecs_assert(m_world.c_ptr() == obj.m_world.c_ptr(), ECS_INVALID_PARAMETER, NULL);
          ecs_iter_t it = ecs_snapshot_iter(obj.m_snapshot, nullptr);
          m_snapshot = ecs_snapshot_take_w_iter(&it, ecs_snapshot_next);        
          return *this;
      }
  
      snapshot& operator=(snapshot&& obj) {
          ecs_assert(m_world.c_ptr() == obj.m_world.c_ptr(), ECS_INVALID_PARAMETER, NULL);
          m_snapshot = obj.m_snapshot;
          obj.m_snapshot = nullptr;
          return *this;
      }
  
      void take() {
          if (m_snapshot) {
              ecs_snapshot_free(m_snapshot);
          }
  
          m_snapshot = ecs_snapshot_take(m_world.c_ptr());
      }
  
      void take(flecs::filter filter) {
          if (m_snapshot) {
              ecs_snapshot_free(m_snapshot);
          }
  
          ecs_iter_t it = ecs_filter_iter(m_world.c_ptr(), filter.c_ptr());
          m_snapshot = ecs_snapshot_take_w_iter(
              &it, ecs_filter_next);
      }
  
      void restore() {
          if (m_snapshot) {
              ecs_snapshot_restore(m_world.c_ptr(), m_snapshot);
              m_snapshot = nullptr;
          }
      }
  
      ~snapshot() {
          if (m_snapshot) {
              ecs_snapshot_free(m_snapshot);
          }
      }
  
      snapshot_t* c_ptr() const {
          return m_snapshot;
      }
  
      snapshot_filter filter(const filter& filter);
  
      filter_iterator begin();
  
      filter_iterator end();
  private:
      const world& m_world;
      snapshot_t *m_snapshot;
  };
  
  
  ////////////////////////////////////////////////////////////////////////////////
  //// Fluent interface to run a system manually
  ////////////////////////////////////////////////////////////////////////////////
  
  class system_runner_fluent {
  public:
      system_runner_fluent(world_t *world, entity_t id, FLECS_FLOAT delta_time, void *param)
          : m_world(world)
          , m_id(id)
          , m_delta_time(delta_time)
          , m_param(param)
          , m_filter()
          , m_offset(0)
          , m_limit(0) { }
  
      system_runner_fluent& filter(filter filter) {
          m_filter = filter;
          return *this;
      }
  
      system_runner_fluent& offset(std::int32_t offset) {
          m_offset = offset;
          return *this;
      }
  
      system_runner_fluent& limit(std::int32_t limit) {
          m_limit = limit;
          return *this;
      }
  
      ~system_runner_fluent() {
          ecs_run_w_filter(
              m_world, m_id, m_delta_time, m_offset, m_limit, m_filter.c_ptr(), m_param);
      }
  private:
      world_t *m_world;
      entity_t m_id;
      FLECS_FLOAT m_delta_time;
      void *m_param;
      flecs::filter m_filter;
      std::int32_t m_offset;
      std::int32_t m_limit;
  };
  
  
  ////////////////////////////////////////////////////////////////////////////////
  //// Register a system with Flecs
  ////////////////////////////////////////////////////////////////////////////////
  
  template<typename ... Components>
  class system final : public entity {
  public:
      explicit system(const flecs::world& world, const char *name = nullptr, const char *signature = nullptr) 
          : entity(world, name)
          , m_kind(static_cast<ecs_entity_t>(OnUpdate)) 
          , m_signature(signature)
          , m_interval(0.0)
          , m_on_demand(false)
          , m_hidden(false)
          , m_finalized(false) { 
              ecs_assert(m_id != 0, ECS_INTERNAL_ERROR, NULL);
          }
  
      explicit system(const flecs::world& world, flecs::entity id) 
          : entity(world, id.id())
          , m_finalized(true) { }
  
      system& signature(const char *signature) {
          ecs_assert(!m_finalized, ECS_INVALID_PARAMETER, NULL);
          ecs_assert(!m_signature, ECS_INVALID_PARAMETER, NULL);
          m_signature = signature;
          return *this;
      }
  
      system& kind(entity_t kind) {
          ecs_assert(!m_finalized, ECS_INVALID_PARAMETER, NULL);
          m_kind = static_cast<ecs_entity_t>(kind);
          return *this;
      }
  
      system& interval(FLECS_FLOAT interval) {
          if (!m_finalized) {
              m_interval = interval;
          } else {
              ecs_set_interval(m_world, m_id, interval);
          }
          return *this;
      }
  
      FLECS_FLOAT interval() {
          return ecs_get_interval(m_world, m_id);
      }
  
      // DEPRECATED: use interval instead
      system& period(FLECS_FLOAT period) {
          return this->interval(period);
      }
  
      system& on_demand() {
          ecs_assert(!m_finalized, ECS_INVALID_PARAMETER, NULL);
          m_on_demand = true;
          return *this;
      }
  
      system& hidden() {
          ecs_assert(!m_finalized, ECS_INVALID_PARAMETER, NULL);
          m_hidden = true;
          return *this;
      }
  
      /** Same as query::order_by */
      template <typename T>
      system& order_by(int(*compare)(flecs::entity_t, const T*, flecs::entity_t, const T*)) {
          ecs_compare_action_t cmp = reinterpret_cast<ecs_compare_action_t>(compare);
          return this->order_by(
              flecs::entity(m_world, _::component_info<T>::id(m_world)), cmp);
      }
  
      /** Same as query::order_by */
      system& order_by(flecs::entity component, int(*compare)(flecs::entity_t, const void*, flecs::entity_t, const void*)) {
          if (!m_finalized) {
              m_order_by = reinterpret_cast<ecs_compare_action_t>(compare);
              m_order_by_component = component;
          } else {
              const EcsQuery *q = ecs_get(m_world, m_id, EcsQuery);
              ecs_assert(q != NULL, ECS_INVALID_OPERATION, NULL);
              ecs_query_order_by(m_world, q->query, 
                  component.id(), reinterpret_cast<ecs_compare_action_t>(compare));
          }
          return *this;
      }
  
      /** Same as query::group_by */
      template <typename T>
      system& group_by(int(*rank)(flecs::world_t*, flecs::entity_t, flecs::type_t type)) {
          ecs_rank_type_action_t rnk = reinterpret_cast<ecs_rank_type_action_t>(rank);
          return this->group_by(
              flecs::entity(m_world, _::component_info<T>::id(m_world)), rnk);
      }
  
      /** Same as query::group_by */
      system& group_by(flecs::entity component, int(*rank)(flecs::world_t*, flecs::entity_t, flecs::type_t type)) {
          if (!m_finalized) {
              m_group_by = reinterpret_cast<ecs_rank_type_action_t>(rank);
              m_group_by_component = component;
          } else {
              const EcsQuery *q = ecs_get(m_world, m_id, EcsQuery);
              ecs_assert(q != NULL, ECS_INVALID_OPERATION, NULL);
              ecs_query_group_by(m_world, q->query, component.id(),
                  reinterpret_cast<ecs_rank_type_action_t>(rank));
          }
          return *this;
      }    
  
      void enable() {
          ecs_assert(m_finalized, ECS_INVALID_PARAMETER, NULL);
          ecs_enable(m_world, m_id, true);
      }
  
      void disable() {
          ecs_assert(m_finalized, ECS_INVALID_PARAMETER, NULL);
          ecs_enable(m_world, m_id, false);
      }
  
      void set_period(FLECS_FLOAT period) const {
          ecs_assert(m_finalized, ECS_INVALID_PARAMETER, NULL);
          ecs_set_interval(m_world, m_id, period);
      }
  
      void set_context(void *ctx) {
          if (!m_finalized) {
              m_ctx = ctx;
          } else {
              EcsContext ctx_value = { ctx };
              ecs_set_ptr(m_world, m_id, EcsContext, &ctx_value);
          }
      }
  
      void* get_context() const {
          ecs_assert(m_finalized, ECS_INVALID_PARAMETER, NULL);
  
          const EcsContext *ctx = ecs_get(m_world, m_id, EcsContext);
          if (ctx) {
              return (void*)ctx->ctx;
          } else {
              return NULL;
          }
      }
  
      query_base query() const {
          const EcsQuery *q = ecs_get(m_world, m_id, EcsQuery);
          return query_base(m_world, q->query);
      }
  
      system_runner_fluent run(FLECS_FLOAT delta_time = 0.0f, void *param = nullptr) const {
          return system_runner_fluent(m_world, m_id, delta_time, param);
      }
  
      /* DEPRECATED. Use iter instead. */
      template <typename Func>
      system& action(Func&& func) {
          ecs_assert(!m_finalized, ECS_INVALID_PARAMETER, NULL);
          using invoker_t = typename _::action_invoker<typename std::decay<Func>::type, Components...>;
          auto ctx = FLECS_NEW(invoker_t)(std::forward<Func>(func));        
  
          create_system(invoker_t::run, false);
  
          EcsContext ctx_value = {ctx};
          ecs_set_ptr(m_world, m_id, EcsContext, &ctx_value);
  
          return *this;
      }
  
       /* Iter (or each) is mandatory and always the last thing that 
        * is added in the fluent method chain. Create system signature from both 
        * template parameters and anything provided by the signature method. */
      template <typename Func>
      system& iter(Func&& func) {
          ecs_assert(!m_finalized, ECS_INVALID_PARAMETER, NULL);
          using invoker_t = typename _::iter_invoker<typename std::decay<Func>::type, Components...>;
          auto ctx = FLECS_NEW(invoker_t)(std::forward<Func>(func));
  
          create_system(invoker_t::run, false);
  
          EcsContext ctx_value = {ctx};
          ecs_set_ptr(m_world, m_id, EcsContext, &ctx_value);
  
          return *this;
      }    
  
      /* Each is similar to action, but accepts a function that operates on a
       * single entity */
      template <typename Func>
      system& each(Func&& func) {
          using invoker_t = typename _::each_invoker<typename std::decay<Func>::type, Components...>;
          auto ctx = FLECS_NEW(invoker_t)(std::forward<Func>(func));
  
          create_system(invoker_t::run, true);
  
          EcsContext ctx_value = {ctx};
          ecs_set_ptr(m_world, m_id, EcsContext, &ctx_value);
  
          return *this;
      }
  
      ~system() = default;
  private:
      template <typename Invoker>
      entity_t create_system(Invoker invoker, bool is_each) {
          ecs_assert(m_id != 0, ECS_INTERNAL_ERROR, NULL);
  
          entity_t e;
          bool is_trigger = m_kind == flecs::OnAdd || m_kind == flecs::OnRemove;
  
          if (is_trigger) {
              // Don't add ANY source to each function if this is a trigger
              is_each = false;
          }
  
          std::string signature = build_signature(is_each);
  
          if (!signature.length()) {
              signature = "0";
          }
  
          if (is_trigger) {
              e = ecs_new_trigger(
                  m_world, 
                  m_id,
                  nullptr, 
                  m_kind, 
                  signature.c_str(), 
                  invoker);
          } else {
              e = ecs_new_system(
                  m_world, 
                  m_id,
                  nullptr, 
                  m_kind, 
                  signature.c_str(), 
                  invoker);
          }
  
          ecs_assert(e == m_id, ECS_INTERNAL_ERROR, NULL);
  
          if (m_interval != 0) {
              ecs_set_interval(m_world, e, m_interval);
          }
  
          m_finalized = true;
  
          if (m_ctx) {
              this->set_context(m_ctx);
          }
  
          if (m_order_by) {
              this->order_by(m_order_by_component, m_order_by);
          }
  
          if (m_group_by) {
              this->group_by(m_group_by_component, m_group_by);
          }
  
          return e;
      }
  
      std::string build_signature(bool is_each) {
          bool is_set = false;
  
          std::stringstream str;
          if (_::pack_args_to_string<Components ...>(m_world, str, is_each)) {
              is_set = true;
          }
  
          if (m_signature) {
              if (is_set) {
                  str << ",";
              }
              str << m_signature;
              is_set = true;
          }
  
          if (m_hidden) {
              if (is_set) {
                  str << ",";
              }            
              str << "SYSTEM:Hidden";
              is_set = true;
          }    
  
          if (m_on_demand) {
              if (is_set) {
                  str << ",";
              }            
              str << "SYSTEM:EcsOnDemand";
              is_set = true;
          } 
  
          return str.str();       
      }
  
      ecs_entity_t m_kind;
      const char *m_signature = nullptr;
      void *m_ctx = nullptr;
  
      ecs_compare_action_t m_order_by = nullptr;
      flecs::entity m_order_by_component;
  
      ecs_rank_type_action_t m_group_by = nullptr;
      flecs::entity m_group_by_component;
  
      FLECS_FLOAT m_interval;
      bool m_on_demand;
      bool m_hidden;
      bool m_finalized; // After set to true, system is created & sig is fixed
  };
  
  
  ////////////////////////////////////////////////////////////////////////////////
  //// Persistent queries
  ////////////////////////////////////////////////////////////////////////////////
  
  template<typename ... Components>
  class query_iterator
  {
  public:
      query_iterator()
          : m_has_next(false)
          , m_iter{ } { }
  
      query_iterator(const query<Components...>& query) 
          : m_iter( ecs_query_iter(query.c_ptr()) )
      {
          m_has_next = ecs_query_next(&m_iter);
      }
  
      bool operator!=(query_iterator const& other) const {
          return m_has_next != other.m_has_next;
      }
  
      flecs::iter const operator*() const {
          return flecs::iter(&m_iter);
      }
  
      query_iterator& operator++() {
          m_has_next = ecs_query_next(&m_iter);
          return *this;
      }
  
  private:
      bool m_has_next;
      ecs_iter_t m_iter;
  };
  
  
  ////////////////////////////////////////////////////////////////////////////////
  //// Utility for iterating over tables that match a filter
  ////////////////////////////////////////////////////////////////////////////////
  
  class filter_iterator
  {
  public:
      filter_iterator(ecs_iter_next_action_t action)
          : m_world(nullptr)
          , m_has_next(false)
          , m_iter{ } 
          , m_action(action) { }
  
      filter_iterator(const world& world, const filter& filter, ecs_iter_next_action_t action)
          : m_world( world.c_ptr() )
          , m_iter( ecs_filter_iter(m_world, filter.c_ptr()) ) 
          , m_action(action)
      { 
          m_has_next = m_action(&m_iter);
      }
  
      filter_iterator(const world& world, const snapshot& snapshot, const filter& filter, ecs_iter_next_action_t action) 
          : m_world( world.c_ptr() )
          , m_iter( ecs_snapshot_iter(snapshot.c_ptr(), filter.c_ptr()) )
          , m_action(action)
      {
          m_has_next = m_action(&m_iter);
      }
  
      bool operator!=(filter_iterator const& other) const {
          return m_has_next != other.m_has_next;
      }
  
      flecs::iter const operator*() const {
          return flecs::iter(&m_iter);
      }
  
      filter_iterator& operator++() {
          m_has_next = m_action(&m_iter);
          return *this;
      }
  
  private:
      world_t *m_world;
      bool m_has_next;
      ecs_iter_t m_iter;
      ecs_iter_next_action_t m_action;
  };
  
  
  ////////////////////////////////////////////////////////////////////////////////
  //// Tree iterator
  ////////////////////////////////////////////////////////////////////////////////
  
  class tree_iterator
  {
  public:
      tree_iterator()
          : m_has_next(false)
          , m_iter{ } { }
  
      tree_iterator(flecs::entity entity) 
          : m_iter( ecs_scope_iter(entity.world().c_ptr(), entity.id()) )
      {
          m_has_next = ecs_scope_next(&m_iter);
      }
  
      bool operator!=(tree_iterator const& other) const {
          return m_has_next != other.m_has_next;
      }
  
      flecs::iter const operator*() const {
          return flecs::iter(&m_iter);
      }
  
      tree_iterator& operator++() {
          m_has_next = ecs_scope_next(&m_iter);
          return *this;
      }
  
  private:
      bool m_has_next;
      ecs_iter_t m_iter;
  };
  
  ////////////////////////////////////////////////////////////////////////////////
  //// Utility for creating a world-based filter iterator
  ////////////////////////////////////////////////////////////////////////////////
  
  class world_filter {
  public:
      world_filter(const world& world, const filter& filter) 
          : m_world( world )
          , m_filter( filter ) { }
  
      inline filter_iterator begin() const {
          return filter_iterator(m_world, m_filter, ecs_filter_next);
      }
  
      inline filter_iterator end() const {
          return filter_iterator(ecs_filter_next);
      }
  
  private:
      const world& m_world;
      const filter& m_filter;
  };
  
  
  ////////////////////////////////////////////////////////////////////////////////
  //// Utility for creating a snapshot-based filter iterator
  ////////////////////////////////////////////////////////////////////////////////
  
  class snapshot_filter {
  public:
      snapshot_filter(const world& world, const snapshot& snapshot, const filter& filter) 
          : m_world( world )
          , m_snapshot( snapshot )
          , m_filter( filter ) { }
  
      inline filter_iterator begin() const {
          return filter_iterator(m_world, m_snapshot, m_filter, ecs_snapshot_next);
      }
  
      inline filter_iterator end() const {
          return filter_iterator(ecs_snapshot_next);
      }
  
  private:
      const world& m_world;
      const snapshot& m_snapshot;
      const filter& m_filter;
  };
  
  
  ////////////////////////////////////////////////////////////////////////////////
  //// Utility for creating a child table iterator
  ////////////////////////////////////////////////////////////////////////////////
  
  class child_iterator {
  public:
      child_iterator(const entity& entity) 
          : m_parent( entity ) { }
  
      inline tree_iterator begin() const {
          return tree_iterator(m_parent);
      }
  
      inline tree_iterator end() const {
          return tree_iterator();
      }
  
  private:
      const entity& m_parent;
  };
  
  
  ////////////////////////////////////////////////////////////////////////////////
  //// Reader for world/snapshot serialization
  ////////////////////////////////////////////////////////////////////////////////
  
  class reader final {
  public:
      explicit reader(world& world) {
          m_reader = ecs_reader_init(world.c_ptr());
      }
  
      reader(world& world, snapshot& snapshot) {
          (void)world;
          ecs_iter_t it = ecs_snapshot_iter(snapshot.c_ptr(), nullptr);
          m_reader = ecs_reader_init_w_iter(&it, ecs_snapshot_next);
      }
  
      int32_t read(char *buffer, std::int64_t size) {
          return ecs_reader_read(buffer, static_cast<int32_t>(size), &m_reader);
      }
  
  private:
      ecs_reader_t m_reader;
  };
  
  
  ////////////////////////////////////////////////////////////////////////////////
  //// Writer for world deserialization
  ////////////////////////////////////////////////////////////////////////////////
  
  class writer final {
  public:
      explicit writer(world& world) {
          m_writer = ecs_writer_init(world.c_ptr());
      }
  
      int32_t write(const char *buffer, std::int64_t size) {
          return ecs_writer_write(buffer, static_cast<int32_t>(size), &m_writer);
      }
  
  private:
      ecs_writer_t m_writer;
  };
  
  
  ////////////////////////////////////////////////////////////////////////////////
  //// Filter fwd declared functions
  ////////////////////////////////////////////////////////////////////////////////
  
  inline snapshot_filter snapshot::filter(const flecs::filter& filter) {
      return snapshot_filter(m_world, *this, filter);
  }
  
  inline filter_iterator snapshot::begin() {
      return filter_iterator(m_world, *this, flecs::filter(m_world), ecs_snapshot_next);
  }
  
  inline filter_iterator snapshot::end() {
      return filter_iterator(ecs_snapshot_next);
  }
  
  
  ////////////////////////////////////////////////////////////////////////////////
  //// Query fwd declared functions
  ////////////////////////////////////////////////////////////////////////////////
  
  template<typename ... Components>
  inline query_iterator<Components...> query<Components...>::begin() const {
      return query_iterator<Components...>(*this);
  }
  
  template<typename ... Components>
  inline query_iterator<Components...> query<Components...>::end() const {
      return query_iterator<Components...>();
  }
  
  
  ////////////////////////////////////////////////////////////////////////////////
  //// Cached ptr fwd declared functions
  ////////////////////////////////////////////////////////////////////////////////
  
  template <typename T>
  flecs::entity ref<T>::entity() const {
      return flecs::entity(m_world, m_entity);
  }
  
  
  ////////////////////////////////////////////////////////////////////////////////
  //// Entity fwd declared functions
  ////////////////////////////////////////////////////////////////////////////////
  
  inline flecs::type entity::type() const {
      return flecs::type(m_world, ecs_get_type(m_world, m_id));
  }
  
  inline flecs::type entity::to_type() const {
      ecs_type_t type = ecs_type_from_entity(m_world, m_id);
      return flecs::type(m_world, type);
  }
  
  inline child_iterator entity::children() const {
      return flecs::child_iterator(*this);
  }
  
  ////////////////////////////////////////////////////////////////////////////////
  //// Entity fluent fwd declared functions
  ////////////////////////////////////////////////////////////////////////////////
  
  template <typename base>
  inline typename entity_builder<base>::base_type& entity_builder<base>::add(const entity& entity) const {
      return add(entity.id());
  }
  
  template <typename base>
  inline typename entity_builder<base>::base_type& entity_builder<base>::add(type type) const {
      return add(type.c_ptr());
  }
  
  template <typename base>
  template <typename T>
  inline typename entity_builder<base>::base_type& entity_builder<base>::add_trait(flecs::entity component) const {
      return add_trait(_::component_info<T>::id(), component.id());
  }
  
  template <typename base>
  template <typename C>
  inline typename entity_builder<base>::base_type& entity_builder<base>::add_trait_tag(flecs::entity trait) const {
      return add_trait(trait.id(), _::component_info<C>::id());
  }
  
  template <typename base>
  inline typename entity_builder<base>::base_type& entity_builder<base>::add_trait(flecs::entity trait, flecs::entity entity) const {
      return add_trait(trait.id(), entity.id()); 
  }
  
  template <typename base>
  inline typename entity_builder<base>::base_type& entity_builder<base>::remove(const entity& entity) const {
      return remove(entity.id());
  }
  
  template <typename base>
  inline typename entity_builder<base>::base_type& entity_builder<base>::remove(type type) const {
      return remove(type.c_ptr());
  }
  
  template <typename base>
  template <typename T>
  inline typename entity_builder<base>::base_type& entity_builder<base>::remove_trait(flecs::entity component) const {
      return remove_trait(_::component_info<T>::id(), component.id());
  }
  
  template <typename base>
  template <typename C>
  inline typename entity_builder<base>::base_type& entity_builder<base>::remove_trait_tag(flecs::entity trait) const {
      return remove_trait(trait.id(), _::component_info<C>::id());
  }
  
  template <typename base>
  inline typename entity_builder<base>::base_type& entity_builder<base>::remove_trait(flecs::entity trait, flecs::entity entity) const {
      return remove_trait(trait.id(), entity.id());
  }
  
  template <typename base>
  inline typename entity_builder<base>::base_type& entity_builder<base>::add_childof(const entity& entity) const {
      return add_childof(entity.id());
  }
  
  template <typename base>
  inline typename entity_builder<base>::base_type& entity_builder<base>::remove_childof(const entity& entity) const {
      return remove_childof(entity.id());
  }
  
  template <typename base>
  inline typename entity_builder<base>::base_type& entity_builder<base>::add_instanceof(const entity& entity) const {
      return add_instanceof(entity.id());
  }
  
  template <typename base>
  inline typename entity_builder<base>::base_type& entity_builder<base>::remove_instanceof(const entity& entity) const {
      return remove_instanceof(entity.id());
  }
  
  template <typename base>
  template <typename C>
  inline typename entity_builder<base>::base_type& entity_builder<base>::set_trait_tag(flecs::entity trait, const C& value) const
  {
      static_cast<base_type*>(this)->invoke(
      [trait, &value](world_t *world, entity_t id) {
          ecs_set_ptr_w_entity(world, id, 
              ecs_trait(_::component_info<C>::id(world), trait.id()),
              sizeof(C), &value);
      });
      return *static_cast<base_type*>(this);
  }  
  
  template <typename base>
  template <typename T>
  inline typename entity_builder<base>::base_type& entity_builder<base>::set_trait(const T& value, flecs::entity tag) const
  {
      static_cast<base_type*>(this)->invoke(
      [tag, &value](world_t *world, entity_t id) {
          ecs_set_ptr_w_entity(world, id, 
              ecs_trait(tag.id(), _::component_info<T>::id(world)),
              sizeof(T), &value);
      });
      return *static_cast<base_type*>(this);
  }
  
  template <typename base>
  inline typename entity_builder<base>::base_type& entity_builder<base>::add_owned(flecs::type type) const {
      return add_owned(type.id());
  }
  
  template <typename base>
  inline typename entity_builder<base>::base_type& entity_builder<base>::add_switch(const entity& sw) const {
      return add_switch(sw.id());
  }
  
  template <typename base>
  inline typename entity_builder<base>::base_type& entity_builder<base>::add_switch(const type& sw) const {
      return add_switch(sw.id());
  }
  
  template <typename base>
  inline typename entity_builder<base>::base_type& entity_builder<base>::remove_switch(const entity& sw) const {
      return remove_switch(sw.id());
  }
  
  template <typename base>
  inline typename entity_builder<base>::base_type& entity_builder<base>::remove_switch(const type& sw) const {
      return remove_switch(sw.id());
  }
  
  template <typename base>
  inline typename entity_builder<base>::base_type& entity_builder<base>::add_case(const entity& sw_case) const {
      return add_case(sw_case.id());
  }
  
  template <typename base>
  inline typename entity_builder<base>::base_type& entity_builder<base>::remove_case(const entity& sw_case) const {
      return remove_case(sw_case.id());
  }
  
  template <typename base>
  inline typename entity_builder<base>::base_type& entity_builder<base>::enable(const entity& e) const {
      return enable(e.id());
  }
  
  template <typename base>
  inline typename entity_builder<base>::base_type& entity_builder<base>::disable(const entity& e) const {
      return disable(e.id());
  }
  
  inline bool entity::has_switch(flecs::type type) const {
      return ecs_has_entity(m_world, m_id, flecs::Switch | type.id());
  }
  
  inline flecs::entity entity::get_case(flecs::type sw) const {
      return flecs::entity(m_world, ecs_get_case(m_world, m_id, sw.id()));
  }
  
  
  ////////////////////////////////////////////////////////////////////////////////
  //// Iter fwd declared functions
  ////////////////////////////////////////////////////////////////////////////////
  
  inline flecs::entity iter::system() const {
      return flecs::entity(m_iter->world, m_iter->system);
  }
  
  inline flecs::world iter::world() const {
      return flecs::world(m_iter->world);
  }
  
  inline flecs::entity iter::entity(size_t row) const {
      ecs_assert(row < (size_t)m_iter->count, ECS_COLUMN_INDEX_OUT_OF_RANGE, NULL);
      return flecs::entity(m_iter->world, m_iter->entities[row]);
  }
  
  /* Obtain column source (0 if self) */
  inline flecs::entity iter::column_source(int32_t col) const {
      return flecs::entity(m_iter->world, ecs_column_source(m_iter, col));
  }
  
  /* Obtain component/tag entity of column */
  inline flecs::entity iter::column_entity(int32_t col) const {
      return flecs::entity(m_iter->world, ecs_column_entity(m_iter, col));
  }
  
  /* Obtain type of column */
  inline type iter::column_type(int32_t col) const {
      return flecs::type(m_iter->world, ecs_column_type(m_iter, col));
  }
  
  /* Obtain type of table being iterated over */
  inline type iter::table_type() const {
      return flecs::type(m_iter->world, ecs_iter_type(m_iter));
  }
  
  
  ////////////////////////////////////////////////////////////////////////////////
  //// World fwd declared functions
  ////////////////////////////////////////////////////////////////////////////////
  
  inline void world::delete_entities(flecs::filter filter) const {
      ecs_bulk_delete(m_world, filter.c_ptr());
  }
  
  template <typename T>
  inline void world::add(flecs::filter filter) const {
      ecs_bulk_add_remove_type(
          m_world, _::component_info<T>::type(m_world), nullptr, filter.c_ptr());
  }
  
  inline void world::add(flecs::type t) const {
      ecs_bulk_add_remove_type(m_world, t.c_ptr(), nullptr, nullptr);
  }
  
  inline void world::add(flecs::type t, flecs::filter filter) const {
      ecs_bulk_add_remove_type(m_world, t.c_ptr(), nullptr, filter.c_ptr());
  }
  
  inline void world::add(class flecs::entity e) const {
      ecs_bulk_add_remove_type(m_world, e.to_type().c_ptr(), nullptr, nullptr);
  }
  
  inline void world::add(class flecs::entity e, flecs::filter filter) const {
      ecs_bulk_add_remove_type(m_world, e.to_type().c_ptr(), nullptr, filter.c_ptr());
  }
  
  template <typename T>
  inline void world::remove(flecs::filter filter) const {
      ecs_bulk_add_remove_type(
          m_world, nullptr, _::component_info<T>::type(m_world), filter.c_ptr());
  }
  
  inline void world::remove(flecs::type t) const {
      ecs_bulk_add_remove_type(m_world, nullptr, t.c_ptr(), nullptr);
  }
  
  inline void world::remove(flecs::type t, flecs::filter filter) const {
      ecs_bulk_add_remove_type(m_world, nullptr, t.c_ptr(), filter.c_ptr());
  }
  
  inline void world::remove(class entity e) const {
      ecs_bulk_add_remove_type(m_world, nullptr, e.to_type().c_ptr(), nullptr);
  }
  
  inline void world::remove(class entity e, flecs::filter filter) const {
      ecs_bulk_add_remove_type(m_world, nullptr, e.to_type().c_ptr(), filter.c_ptr());
  }
  
  inline flecs::world_filter world::filter(const flecs::filter& filter) const {
      return flecs::world_filter(*this, filter);
  }
  
  inline filter_iterator world::begin() const {
      return filter_iterator(*this, flecs::filter(*this), ecs_filter_next);
  }
  
  inline filter_iterator world::end() const {
      return filter_iterator(ecs_filter_next);
  }
  
  inline int world::count(flecs::filter filter) const {
      return ecs_count_w_filter(m_world, filter.c_ptr());
  }
  
  inline void world::init_builtin_components() {
      pod_component<Component>("flecs::core::Component");
      pod_component<Type>("flecs::core::Type");
      pod_component<Name>("flecs::core::Name");
  }
  
  template <typename T>
  inline flecs::entity world::use(const char *alias) {
      entity_t id = _::component_info<T>::id(m_world);
      const char *name = alias;
      if (!name) {
          // If no name is defined, use the entity name without the scope
          name = ecs_get_name(m_world, id);
      }
      ecs_use(m_world, id, name);
      return flecs::entity(m_world, id);
  }
  
  inline flecs::entity world::use(const char *name, const char *alias) {
      entity_t id = ecs_lookup_path_w_sep(m_world, 0, name, "::", "::");
      ecs_assert(id != 0, ECS_INVALID_PARAMETER, NULL);
  
      ecs_use(m_world, id, alias);
      return flecs::entity(m_world, id);
  }
  
  inline void world::use(flecs::entity e, const char *alias) {
      entity_t id = e.id();
      const char *name = alias;
      if (!name) {
          // If no name is defined, use the entity name without the scope
          ecs_get_name(m_world, id);
      }
      ecs_use(m_world, id, alias);
  }
  
  inline entity world::lookup(const char *name) const {
      auto id = ecs_lookup_path_w_sep(m_world, 0, name, "::", "::");
      return flecs::entity(*this, id);
  }
  
  inline entity world::lookup(std::string& name) const {
      auto id = ecs_lookup_path_w_sep(m_world, 0, name.c_str(), "::", "::");
      return flecs::entity(*this, id);
  }
  
  template <typename T>
  void world::set(T value) const {
      flecs::entity e(m_world, _::component_info<T>::id(m_world));
      e.set<T>(value);
  }
  
  template <typename T>
  T* world::get_mut() const {
      flecs::entity e(m_world, _::component_info<T>::id(m_world));
      return e.get_mut<T>();
  }
  
  template <typename T>
  void world::modified() const {
      flecs::entity e(m_world, _::component_info<T>::id(m_world));
      return e.modified<T>();
  }
  
  template <typename T>
  void world::patch(std::function<void(T&)> func) const {
      flecs::entity e(m_world, _::component_info<T>::id(m_world));
      e.patch<T>(func);
  } 
  
  template <typename T>
  const T* world::get() const {
      flecs::entity e(m_world, _::component_info<T>::id(m_world));
      return e.get<T>();
  }
  
  template <typename T>
  bool world::has() const {
      flecs::entity e(m_world, _::component_info<T>::id(m_world));
      return e.has<T>();
  }
  
  template <typename T>
  void world::remove() const {
      flecs::entity e(m_world, _::component_info<T>::id(m_world));
      e.remove<T>();
  }
  
  template <typename T>
  flecs::entity world::singleton() {
      return flecs::entity(m_world, _::component_info<T>::id(m_world));
  }
  
  template <typename... Args>
  inline flecs::entity world::entity(Args &&... args) const {
      return flecs::entity(*this, std::forward<Args>(args)...);
  }
  
  template <typename... Args>
  inline flecs::entity world::prefab(Args &&... args) const {
      return flecs::prefab(*this, std::forward<Args>(args)...);
  }
  
  template <typename... Args>
  inline flecs::type world::type(Args &&... args) const {
      return flecs::type(*this, std::forward<Args>(args)...);
  }
  
  template <typename... Comps, typename... Args>
  inline flecs::system<Comps...> world::system(Args &&... args) const {
      return flecs::system<Comps...>(*this, std::forward<Args>(args)...);
  }
  
  template <typename... Comps, typename... Args>
  inline flecs::query<Comps...> world::query(Args &&... args) const {
      return flecs::query<Comps...>(*this, std::forward<Args>(args)...);
  }
  
  template <typename Module, typename... Args>
  inline flecs::entity world::module(Args &&... args) const {
      return flecs::module<Module>(*this, std::forward<Args>(args)...);
  }
  
  template <typename Module>
  inline flecs::entity world::import() {
      return flecs::import<Module>(*this);
  }
  
  template <typename T, typename... Args>
  inline flecs::entity world::component(Args &&... args) const {
      return flecs::component<T>(*this, std::forward<Args>(args)...);
  }
  
  template <typename T, typename... Args>
  inline flecs::entity world::pod_component(Args &&... args) const {
      return flecs::pod_component<T>(*this, std::forward<Args>(args)...);
  }
  
  template <typename T, typename... Args>
  inline flecs::entity world::relocatable_component(Args &&... args) const {
      return flecs::relocatable_component<T>(*this, std::forward<Args>(args)...);
  }
  
  template <typename... Args>
  inline flecs::snapshot world::snapshot(Args &&... args) const {
      return flecs::snapshot(*this, std::forward<Args>(args)...);
  }
  
  /** Utilities to convert type trait to flecs signature syntax */
  
  namespace _
  {
  
  template <typename T,
      typename std::enable_if< std::is_const<T>::value == true, void>::type* = nullptr>
  constexpr const char *inout_modifier() {
      return "[in] ";
  }
  
  template <typename T,
      typename std::enable_if< std::is_reference<T>::value == true, void>::type* = nullptr>
  constexpr const char *inout_modifier() {
      return "[out] ";
  }
  
  template <typename T,
      typename std::enable_if<std::is_const<T>::value == false && std::is_reference<T>::value == false, void>::type* = nullptr>
  constexpr const char *inout_modifier() {
      return "";
  }
  
  template <typename T,
      typename std::enable_if< std::is_pointer<T>::value == true, void>::type* = nullptr>
  constexpr const char *optional_modifier() {
      return "?";
  }
  
  template <typename T,
      typename std::enable_if< std::is_pointer<T>::value == false, void>::type* = nullptr>
  constexpr const char *optional_modifier() {
      return "";
  } 
  
  /** Convert template arguments to string */
  template <typename ...Components>
  bool pack_args_to_string(world_t *world, std::stringstream& str, bool is_each) {
      (void)world;
  
      std::array<const char*, sizeof...(Components)> ids = {
          (_::component_info<Components>::name(world))...
      };
  
      std::array<const char*, sizeof...(Components)> inout_modifiers = {
          (inout_modifier<Components>())...
      }; 
  
      std::array<const char*, sizeof...(Components)> optional_modifiers = {
          (optional_modifier<Components>())...
      };        
  
      size_t i = 0;
      for (auto id : ids) {
          if (i) {
              str << ",";
          }
          
          str << inout_modifiers[i];
          str << optional_modifiers[i];
  
          if (is_each) {
              str << "ANY:";
          }
          str << id;
          i ++;
      }  
  
      return i != 0;
  }
  
  } // namespace _
  
  } // namespace flecs
  
  #endif
  #endif
  
  #endif
  
  #endif
  