Properly link flecs library

This commit is contained in:
2023-11-09 11:38:29 +01:00
parent dc585396c3
commit 8edcf9305c
1392 changed files with 390081 additions and 164 deletions

View File

@@ -0,0 +1,288 @@
/**
* @file addons.h
* @brief Include enabled addons.
*
* This file should only be included by the main flecs.h header.
*/
#ifndef FLECS_ADDONS_H
#define FLECS_ADDONS_H
/* Blacklist macros */
#ifdef FLECS_NO_CPP
#undef FLECS_CPP
#endif
#ifdef FLECS_NO_MODULE
#undef FLECS_MODULE
#endif
#ifdef FLECS_NO_PARSER
#undef FLECS_PARSER
#endif
#ifdef FLECS_NO_PLECS
#undef FLECS_PLECS
#endif
#ifdef FLECS_NO_RULES
#undef FLECS_RULES
#endif
#ifdef FLECS_NO_SNAPSHOT
#undef FLECS_SNAPSHOT
#endif
#ifdef FLECS_NO_MONITOR
#undef FLECS_MONITOR
#endif
#ifdef FLECS_NO_STATS
#undef FLECS_STATS
#endif
#ifdef FLECS_NO_SYSTEM
#undef FLECS_SYSTEM
#endif
#ifdef FLECS_NO_PIPELINE
#undef FLECS_PIPELINE
#endif
#ifdef FLECS_NO_TIMER
#undef FLECS_TIMER
#endif
#ifdef FLECS_NO_META
#undef FLECS_META
#endif
#ifdef FLECS_NO_META_C
#undef FLECS_META_C
#endif
#ifdef FLECS_NO_UNITS
#undef FLECS_UNITS
#endif
#ifdef FLECS_NO_EXPR
#undef FLECS_EXPR
#endif
#ifdef FLECS_NO_JSON
#undef FLECS_JSON
#endif
#ifdef FLECS_NO_DOC
#undef FLECS_DOC
#endif
#ifdef FLECS_NO_COREDOC
#undef FLECS_COREDOC
#endif
#ifdef FLECS_NO_LOG
#undef FLECS_LOG
#endif
#ifdef FLECS_NO_APP
#undef FLECS_APP
#endif
#ifdef FLECS_NO_OS_API_IMPL
#undef FLECS_OS_API_IMPL
#endif
#ifdef FLECS_NO_HTTP
#undef FLECS_HTTP
#endif
#ifdef FLECS_NO_REST
#undef FLECS_REST
#endif
#ifdef FLECS_NO_JOURNAL
#undef FLECS_JOURNAL
#endif
/* Always included, if disabled functions are replaced with dummy macros */
#include "flecs/addons/journal.h"
#include "flecs/addons/log.h"
/* Handle addon dependencies that need declarations to be visible in header */
#ifdef FLECS_MONITOR
#ifndef FLECS_STATS
#define FLECS_STATS
#endif
#ifndef FLECS_SYSTEM
#define FLECS_SYSTEM
#endif
#ifndef FLECS_TIMER
#define FLECS_TIMER
#endif
#endif
#ifdef FLECS_REST
#define FLECS_HTTP
#endif
#ifdef FLECS_PLECS
#define FLECS_EXPR
#endif
#ifdef FLECS_APP
#ifdef FLECS_NO_APP
#error "FLECS_NO_APP failed: APP is required by other addons"
#endif
#include "../addons/app.h"
#endif
#ifdef FLECS_HTTP
#ifdef FLECS_NO_HTTP
#error "FLECS_NO_HTTP failed: HTTP is required by other addons"
#endif
#include "../addons/http.h"
#endif
#ifdef FLECS_REST
#ifdef FLECS_NO_REST
#error "FLECS_NO_REST failed: REST is required by other addons"
#endif
#include "../addons/rest.h"
#endif
#ifdef FLECS_TIMER
#ifdef FLECS_NO_TIMER
#error "FLECS_NO_TIMER failed: TIMER is required by other addons"
#endif
#include "../addons/timer.h"
#endif
#ifdef FLECS_PIPELINE
#ifdef FLECS_NO_PIPELINE
#error "FLECS_NO_PIPELINE failed: PIPELINE is required by other addons"
#endif
#include "../addons/pipeline.h"
#endif
#ifdef FLECS_SYSTEM
#ifdef FLECS_NO_SYSTEM
#error "FLECS_NO_SYSTEM failed: SYSTEM is required by other addons"
#endif
#include "../addons/system.h"
#endif
#ifdef FLECS_STATS
#ifdef FLECS_NO_STATS
#error "FLECS_NO_STATS failed: STATS is required by other addons"
#endif
#include "../addons/stats.h"
#endif
#ifdef FLECS_METRICS
#ifdef FLECS_NO_METRICS
#error "FLECS_NO_METRICS failed: METRICS is required by other addons"
#endif
#include "../addons/metrics.h"
#endif
#ifdef FLECS_ALERTS
#ifdef FLECS_NO_ALERTS
#error "FLECS_NO_ALERTS failed: ALERTS is required by other addons"
#endif
#include "../addons/alerts.h"
#endif
#ifdef FLECS_MONITOR
#ifdef FLECS_NO_MONITOR
#error "FLECS_NO_MONITOR failed: MONITOR is required by other addons"
#endif
#include "../addons/monitor.h"
#endif
#ifdef FLECS_COREDOC
#ifdef FLECS_NO_COREDOC
#error "FLECS_NO_COREDOC failed: COREDOC is required by other addons"
#endif
#include "../addons/coredoc.h"
#endif
#ifdef FLECS_DOC
#ifdef FLECS_NO_DOC
#error "FLECS_NO_DOC failed: DOC is required by other addons"
#endif
#include "../addons/doc.h"
#endif
#ifdef FLECS_JSON
#ifdef FLECS_NO_JSON
#error "FLECS_NO_JSON failed: JSON is required by other addons"
#endif
#include "../addons/json.h"
#endif
#if defined(FLECS_EXPR) || defined(FLECS_META_C)
#ifndef FLECS_META
#define FLECS_META
#endif
#endif
#ifdef FLECS_UNITS
#ifdef FLECS_NO_UNITS
#error "FLECS_NO_UNITS failed: UNITS is required by other addons"
#endif
#include "../addons/units.h"
#endif
#ifdef FLECS_META
#ifdef FLECS_NO_META
#error "FLECS_NO_META failed: META is required by other addons"
#endif
#include "../addons/meta.h"
#endif
#ifdef FLECS_EXPR
#ifdef FLECS_NO_EXPR
#error "FLECS_NO_EXPR failed: EXPR is required by other addons"
#endif
#include "../addons/expr.h"
#endif
#ifdef FLECS_META_C
#ifdef FLECS_NO_META_C
#error "FLECS_NO_META_C failed: META_C is required by other addons"
#endif
#include "../addons/meta_c.h"
#endif
#ifdef FLECS_PLECS
#ifdef FLECS_NO_PLECS
#error "FLECS_NO_PLECS failed: PLECS is required by other addons"
#endif
#include "../addons/plecs.h"
#endif
#ifdef FLECS_RULES
#ifdef FLECS_NO_RULES
#error "FLECS_NO_RULES failed: RULES is required by other addons"
#endif
#include "../addons/rules.h"
#endif
#ifdef FLECS_SNAPSHOT
#ifdef FLECS_NO_SNAPSHOT
#error "FLECS_NO_SNAPSHOT failed: SNAPSHOT is required by other addons"
#endif
#include "../addons/snapshot.h"
#endif
#ifdef FLECS_PARSER
#ifdef FLECS_NO_PARSER
#error "FLECS_NO_PARSER failed: PARSER is required by other addons"
#endif
#include "../addons/parser.h"
#endif
#ifdef FLECS_OS_API_IMPL
#ifdef FLECS_NO_OS_API_IMPL
#error "FLECS_NO_OS_API_IMPL failed: OS_API_IMPL is required by other addons"
#endif
#include "../addons/os_api_impl.h"
#endif
#ifdef FLECS_MODULE
#ifdef FLECS_NO_MODULE
#error "FLECS_NO_MODULE failed: MODULE is required by other addons"
#endif
#include "../addons/module.h"
#endif
#ifdef FLECS_CPP
#ifdef FLECS_NO_CPP
#error "FLECS_NO_CPP failed: CPP is required by other addons"
#endif
#include "../addons/flecs_cpp.h"
#ifdef __cplusplus
#include "../addons/cpp/flecs.hpp"
#endif // __cplusplus
#endif // FLECS_CPP
#endif

View File

@@ -0,0 +1,73 @@
/**
* @file allocator.h
* @brief Allocator that returns memory objects of any size.
*/
#ifndef FLECS_ALLOCATOR_H
#define FLECS_ALLOCATOR_H
#include "api_defines.h"
FLECS_DBG_API extern int64_t ecs_block_allocator_alloc_count;
FLECS_DBG_API extern int64_t ecs_block_allocator_free_count;
FLECS_DBG_API extern int64_t ecs_stack_allocator_alloc_count;
FLECS_DBG_API extern int64_t ecs_stack_allocator_free_count;
struct ecs_allocator_t {
ecs_block_allocator_t chunks;
struct ecs_sparse_t sizes; /* <size, block_allocator_t> */
};
FLECS_API
void flecs_allocator_init(
ecs_allocator_t *a);
FLECS_API
void flecs_allocator_fini(
ecs_allocator_t *a);
FLECS_API
ecs_block_allocator_t* flecs_allocator_get(
ecs_allocator_t *a,
ecs_size_t size);
FLECS_API
char* flecs_strdup(
ecs_allocator_t *a,
const char* str);
FLECS_API
void flecs_strfree(
ecs_allocator_t *a,
char* str);
FLECS_API
void* flecs_dup(
ecs_allocator_t *a,
ecs_size_t size,
const void *src);
#define flecs_allocator(obj) (&obj->allocators.dyn)
#define flecs_alloc(a, size) flecs_balloc(flecs_allocator_get(a, size))
#define flecs_alloc_t(a, T) flecs_alloc(a, ECS_SIZEOF(T))
#define flecs_alloc_n(a, T, count) flecs_alloc(a, ECS_SIZEOF(T) * (count))
#define flecs_calloc(a, size) flecs_bcalloc(flecs_allocator_get(a, size))
#define flecs_calloc_t(a, T) flecs_calloc(a, ECS_SIZEOF(T))
#define flecs_calloc_n(a, T, count) flecs_calloc(a, ECS_SIZEOF(T) * (count))
#define flecs_free(a, size, ptr) flecs_bfree(flecs_allocator_get(a, size), ptr)
#define flecs_free_t(a, T, ptr) flecs_free(a, ECS_SIZEOF(T), ptr)
#define flecs_free_n(a, T, count, ptr) flecs_free(a, ECS_SIZEOF(T) * (count), ptr)
#define flecs_realloc(a, size_dst, size_src, ptr)\
flecs_brealloc(flecs_allocator_get(a, size_dst),\
flecs_allocator_get(a, size_src),\
ptr)
#define flecs_realloc_n(a, T, count_dst, count_src, ptr)\
flecs_realloc(a, ECS_SIZEOF(T) * (count_dst), ECS_SIZEOF(T) * (count_src), ptr)
#define flecs_dup_n(a, T, count, ptr) flecs_dup(a, ECS_SIZEOF(T) * (count), ptr)
#endif

View File

@@ -0,0 +1,424 @@
/**
* @file api_defines.h
* @brief Supporting defines for the public API.
*
* This file contains constants / macros 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
#include "api_flags.h"
#if defined(_WIN32) || defined(_MSC_VER)
#define ECS_TARGET_WINDOWS
#elif defined(__ANDROID__)
#define ECS_TARGET_ANDROID
#define ECS_TARGET_POSIX
#elif defined(__linux__)
#define ECS_TARGET_LINUX
#define ECS_TARGET_POSIX
#elif defined(__FreeBSD__)
#define ECS_TARGET_FREEBSD
#define ECS_TARGET_POSIX
#elif defined(__APPLE__) && defined(__MACH__)
#define ECS_TARGET_DARWIN
#define ECS_TARGET_POSIX
#elif defined(__EMSCRIPTEN__)
#define ECS_TARGET_EM
#define ECS_TARGET_POSIX
#endif
#if defined(__MINGW32__) || defined(__MINGW64__)
#define ECS_TARGET_MINGW
#endif
#if defined(_MSC_VER)
#ifndef __clang__
#define ECS_TARGET_MSVC
#endif
#endif
#if defined(__clang__)
#define ECS_TARGET_CLANG
#endif
#if defined(__GNUC__)
#define ECS_TARGET_GNU
#endif
/* Map between clang and apple clang versions, as version 13 has a difference in
* the format of __PRETTY_FUNCTION__ which enum reflection depends on. */
#if defined(__clang__)
#if defined(__APPLE__)
#if __clang_major__ == 13
#if __clang_minor__ < 1
#define ECS_CLANG_VERSION 12
#else
#define ECS_CLANG_VERSION 13
#endif
#else
#define ECS_CLANG_VERSION __clang_major__
#endif
#else
#define ECS_CLANG_VERSION __clang_major__
#endif
#endif
/* Ignored warnings */
#if defined(ECS_TARGET_CLANG)
/* Ignore unknown options so we don't have to care about the compiler version */
#pragma clang diagnostic ignored "-Wunknown-warning-option"
/* Warns for double or redundant semicolons. There are legitimate cases where a
* semicolon after an empty statement is useful, for example after a macro that
* is replaced with a code block. With this warning enabled, semicolons would
* only have to be added after macro's that are not code blocks, which in some
* cases isn't possible as the implementation of a macro can be different in
* debug/release mode. */
#pragma clang diagnostic ignored "-Wextra-semi-stmt"
/* This is valid in C99, and Flecs must be compiled as C99. */
#pragma clang diagnostic ignored "-Wdeclaration-after-statement"
/* Clang attribute to detect fallthrough isn't supported on older versions.
* Implicit fallthrough is still detected by gcc and ignored with "fall through"
* comments */
#pragma clang diagnostic ignored "-Wimplicit-fallthrough"
/* This warning prevents adding a default case when all enum constants are part
* of the switch. In C however an enum type can assume any value in the range of
* the type, and this warning makes it harder to catch invalid enum values. */
#pragma clang diagnostic ignored "-Wcovered-switch-default"
/* This warning prevents some casts of function results to a different kind of
* type, e.g. casting an int result to double. Not very useful in practice, as
* it just forces the code to assign to a variable first, then cast. */
#pragma clang diagnostic ignored "-Wbad-function-cast"
/* Format strings can be passed down from other functions. */
#pragma clang diagnostic ignored "-Wformat-nonliteral"
/* Useful, but not reliable enough. It can incorrectly flag macro's as unused
* in standalone builds. */
#pragma clang diagnostic ignored "-Wunused-macros"
#if __clang_major__ == 13
/* clang 13 can throw this warning for a define in ctype.h */
#pragma clang diagnostic ignored "-Wreserved-identifier"
#endif
/* Filenames aren't consistent across targets as they can use different casing
* (e.g. WinSock2 vs winsock2). */
#pragma clang diagnostic ignored "-Wnonportable-system-include-path"
/* Enum reflection relies on testing constant values that may not be valid for
* the enumeration. */
#pragma clang diagnostic ignored "-Wenum-constexpr-conversion"
/* Very difficult to workaround this warning in C, especially for an ECS. */
#pragma clang diagnostic ignored "-Wunsafe-buffer-usage"
/* This warning gets thrown when trying to cast pointer returned from dlproc */
#pragma clang diagnostic ignored "-Wcast-function-type-strict"
/* This warning can get thrown for expressions that evaluate to constants
* in debug/release mode. */
#pragma clang diagnostic ignored "-Wconstant-logical-operand"
#elif defined(ECS_TARGET_GNU)
#ifndef __cplusplus
#pragma GCC diagnostic ignored "-Wdeclaration-after-statement"
#pragma GCC diagnostic ignored "-Wbad-function-cast"
#endif
#pragma GCC diagnostic ignored "-Wformat-nonliteral"
#pragma GCC diagnostic ignored "-Wunused-macros"
/* This warning gets thrown *sometimes* when not all members for a struct are
* provided in an initializer. Flecs heavily relies on descriptor structs that
* only require partly initialization, so this warning isn't useful.
* It doesn't introduce any safety issues (fields are guaranteed to be 0
* initialized), and later versions of gcc (>=11) seem to no longer throw this
* warning. */
#pragma GCC diagnostic ignored "-Wmissing-field-initializers"
#endif
/* Standard library dependencies */
#include <assert.h>
#include <stdarg.h>
#include <string.h>
/* Non-standard but required. If not provided by platform, add manually. */
#include <stdint.h>
/* Contains macros for importing / exporting symbols */
#include "../bake_config.h"
#ifdef __cplusplus
extern "C" {
#endif
#ifdef __BAKE_LEGACY__
#define FLECS_LEGACY
#endif
/* Some symbols are only exported when building in debug build, to enable
* whitebox testing of internal datastructures */
#ifndef FLECS_NDEBUG
#define FLECS_DBG_API FLECS_API
#else
#define FLECS_DBG_API
#endif
////////////////////////////////////////////////////////////////////////////////
//// Language support defines
////////////////////////////////////////////////////////////////////////////////
#ifndef FLECS_LEGACY
#include <stdbool.h>
#endif
#ifndef NULL
#define NULL ((void*)0)
#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
/* Utility types to indicate usage as bitmask */
typedef uint8_t ecs_flags8_t;
typedef uint16_t ecs_flags16_t;
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;
/* Allocator type */
typedef struct ecs_allocator_t ecs_allocator_t;
#define ECS_SIZEOF(T) ECS_CAST(ecs_size_t, sizeof(T))
/* Use alignof in C++, or a trick in C. */
#ifdef __cplusplus
#define ECS_ALIGNOF(T) static_cast<int64_t>(alignof(T))
#elif defined(ECS_TARGET_MSVC)
#define ECS_ALIGNOF(T) (int64_t)__alignof(T)
#elif defined(ECS_TARGET_GNU)
#define ECS_ALIGNOF(T) (int64_t)__alignof__(T)
#else
#define ECS_ALIGNOF(T) ((int64_t)&((struct { char c; T d; } *)0)->d)
#endif
#ifndef FLECS_NO_DEPRECATED_WARNINGS
#if defined(ECS_TARGET_GNU)
#define ECS_DEPRECATED(msg) __attribute__((deprecated(msg)))
#elif defined(ECS_TARGET_MSVC)
#define ECS_DEPRECATED(msg) __declspec(deprecated(msg))
#else
#define ECS_DEPRECATED(msg)
#endif
#else
#define ECS_DEPRECATED(msg)
#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)
#define ECS_MIN(a, b) (((a) < (b)) ? a : b)
/* Abstraction on top of C-style casts so that C functions can be used in C++
* code without producing warnings */
#ifndef __cplusplus
#define ECS_CAST(T, V) ((T)(V))
#else
#define ECS_CAST(T, V) (static_cast<T>(V))
#endif
/* Utility macro for doing const casts without warnings */
#ifndef __cplusplus
#define ECS_CONST_CAST(type, value) ((type)(uintptr_t)(value))
#else
#define ECS_CONST_CAST(type, value) (const_cast<type>(value))
#endif
/* Utility macro for doing pointer casts without warnings */
#ifndef __cplusplus
#define ECS_PTR_CAST(type, value) ((type)(uintptr_t)(value))
#else
#define ECS_PTR_CAST(type, value) (reinterpret_cast<type>(value))
#endif
/* Utility macro's to do bitwise comparisons between floats without warnings */
#define ECS_EQ(a, b) (ecs_os_memcmp(&(a), &(b), sizeof(a)) == 0)
#define ECS_NEQ(a, b) (!ECS_EQ(a, b))
#define ECS_EQZERO(a) ECS_EQ(a, (uint64_t){0})
#define ECS_NEQZERO(a) ECS_NEQ(a, (uint64_t){0})
#define ECS_CONCAT(a, b) a ## b
////////////////////////////////////////////////////////////////////////////////
//// Magic numbers for sanity checking
////////////////////////////////////////////////////////////////////////////////
/* Magic number to identify the type of the object */
#define ecs_world_t_magic (0x65637377)
#define ecs_stage_t_magic (0x65637373)
#define ecs_query_t_magic (0x65637371)
#define ecs_rule_t_magic (0x65637375)
#define ecs_table_t_magic (0x65637374)
#define ecs_filter_t_magic (0x65637366)
#define ecs_trigger_t_magic (0x65637372)
#define ecs_observer_t_magic (0x65637362)
////////////////////////////////////////////////////////////////////////////////
//// Entity id macros
////////////////////////////////////////////////////////////////////////////////
#define ECS_ROW_MASK (0x0FFFFFFFu)
#define ECS_ROW_FLAGS_MASK (~ECS_ROW_MASK)
#define ECS_RECORD_TO_ROW(v) (ECS_CAST(int32_t, (ECS_CAST(uint32_t, v) & ECS_ROW_MASK)))
#define ECS_RECORD_TO_ROW_FLAGS(v) (ECS_CAST(uint32_t, v) & ECS_ROW_FLAGS_MASK)
#define ECS_ROW_TO_RECORD(row, flags) (ECS_CAST(uint32_t, (ECS_CAST(uint32_t, row) | (flags))))
#define ECS_ID_FLAGS_MASK (0xFFull << 60)
#define ECS_ENTITY_MASK (0xFFFFFFFFull)
#define ECS_GENERATION_MASK (0xFFFFull << 32)
#define ECS_GENERATION(e) ((e & ECS_GENERATION_MASK) >> 32)
#define ECS_GENERATION_INC(e) ((e & ~ECS_GENERATION_MASK) | ((0xFFFF & (ECS_GENERATION(e) + 1)) << 32))
#define ECS_COMPONENT_MASK (~ECS_ID_FLAGS_MASK)
#define ECS_HAS_ID_FLAG(e, flag) ((e) & ECS_##flag)
#define ECS_IS_PAIR(id) (((id) & ECS_ID_FLAGS_MASK) == ECS_PAIR)
#define ECS_PAIR_FIRST(e) (ecs_entity_t_hi(e & ECS_COMPONENT_MASK))
#define ECS_PAIR_SECOND(e) (ecs_entity_t_lo(e))
#define ECS_HAS_RELATION(e, rel) (ECS_HAS_ID_FLAG(e, PAIR) && (ECS_PAIR_FIRST(e) == rel))
////////////////////////////////////////////////////////////////////////////////
//// Convert between C typenames and variables
////////////////////////////////////////////////////////////////////////////////
/** Translate C type to id. */
#define ecs_id(T) FLECS_ID##T##ID_
////////////////////////////////////////////////////////////////////////////////
//// Utilities for working with pair identifiers
////////////////////////////////////////////////////////////////////////////////
#define ecs_entity_t_lo(value) ECS_CAST(uint32_t, value)
#define ecs_entity_t_hi(value) ECS_CAST(uint32_t, (value) >> 32)
#define ecs_entity_t_comb(lo, hi) ((ECS_CAST(uint64_t, hi) << 32) + ECS_CAST(uint32_t, lo))
#define ecs_pair(pred, obj) (ECS_PAIR | ecs_entity_t_comb(obj, pred))
#define ecs_pair_t(pred, obj) (ECS_PAIR | ecs_entity_t_comb(obj, ecs_id(pred)))
#define ecs_pair_first(world, pair) ecs_get_alive(world, ECS_PAIR_FIRST(pair))
#define ecs_pair_second(world, pair) ecs_get_alive(world, ECS_PAIR_SECOND(pair))
#define ecs_pair_relation ecs_pair_first
#define ecs_pair_object ecs_pair_second
#define ecs_poly_id(tag) ecs_pair(ecs_id(EcsPoly), tag)
////////////////////////////////////////////////////////////////////////////////
//// Debug macros
////////////////////////////////////////////////////////////////////////////////
#ifndef FLECS_NDEBUG
#define ECS_TABLE_LOCK(world, table) ecs_table_lock(world, table)
#define ECS_TABLE_UNLOCK(world, table) ecs_table_unlock(world, table)
#else
#define ECS_TABLE_LOCK(world, table)
#define ECS_TABLE_UNLOCK(world, table)
#endif
////////////////////////////////////////////////////////////////////////////////
//// Actions that drive iteration
////////////////////////////////////////////////////////////////////////////////
#define EcsIterNextYield (0) /* Move to next table, yield current */
#define EcsIterYield (-1) /* Stay on current table, yield */
#define EcsIterNext (1) /* Move to next table, don't yield */
////////////////////////////////////////////////////////////////////////////////
//// Convenience macros for ctor, dtor, move and copy
////////////////////////////////////////////////////////////////////////////////
#ifndef FLECS_LEGACY
/* Constructor/Destructor convenience macro */
#define ECS_XTOR_IMPL(type, postfix, var, ...)\
void type##_##postfix(\
void *_ptr,\
int32_t _count,\
const ecs_type_info_t *type_info)\
{\
(void)_ptr;\
(void)_count;\
(void)type_info;\
for (int32_t i = 0; i < _count; i ++) {\
type *var = &((type*)_ptr)[i];\
(void)var;\
__VA_ARGS__\
}\
}
/* Copy convenience macro */
#define ECS_COPY_IMPL(type, dst_var, src_var, ...)\
void type##_##copy(\
void *_dst_ptr,\
const void *_src_ptr,\
int32_t _count,\
const ecs_type_info_t *type_info)\
{\
(void)_dst_ptr;\
(void)_src_ptr;\
(void)_count;\
(void)type_info;\
for (int32_t i = 0; i < _count; i ++) {\
type *dst_var = &((type*)_dst_ptr)[i];\
const type *src_var = &((const type*)_src_ptr)[i];\
(void)dst_var;\
(void)src_var;\
__VA_ARGS__\
}\
}
/* Move convenience macro */
#define ECS_MOVE_IMPL(type, dst_var, src_var, ...)\
void type##_##move(\
void *_dst_ptr,\
void *_src_ptr,\
int32_t _count,\
const ecs_type_info_t *type_info)\
{\
(void)_dst_ptr;\
(void)_src_ptr;\
(void)_count;\
(void)type_info;\
for (int32_t i = 0; i < _count; i ++) {\
type *dst_var = &((type*)_dst_ptr)[i];\
type *src_var = &((type*)_src_ptr)[i];\
(void)dst_var;\
(void)src_var;\
__VA_ARGS__\
}\
}
#define ECS_HOOK_IMPL(type, func, var, ...)\
void func(ecs_iter_t *_it)\
{\
for (int32_t i = 0; i < _it->count; i ++) {\
ecs_entity_t entity = _it->entities[i];\
type *var = &((type*)_it->ptrs[0])[i];\
(void)entity;\
(void)var;\
__VA_ARGS__\
}\
}
#endif
#ifdef __cplusplus
}
#endif
#endif

View File

@@ -0,0 +1,203 @@
/**
* @file api_flags.h
* @brief Bitset flags used by internals.
*/
#ifndef FLECS_API_FLAGS_H
#define FLECS_API_FLAGS_H
#ifdef __cplusplus
extern "C" {
#endif
////////////////////////////////////////////////////////////////////////////////
//// World flags
////////////////////////////////////////////////////////////////////////////////
#define EcsWorldQuitWorkers (1u << 0)
#define EcsWorldReadonly (1u << 1)
#define EcsWorldInit (1u << 2)
#define EcsWorldQuit (1u << 3)
#define EcsWorldFini (1u << 4)
#define EcsWorldMeasureFrameTime (1u << 5)
#define EcsWorldMeasureSystemTime (1u << 6)
#define EcsWorldMultiThreaded (1u << 7)
////////////////////////////////////////////////////////////////////////////////
//// OS API flags
////////////////////////////////////////////////////////////////////////////////
#define EcsOsApiHighResolutionTimer (1u << 0)
#define EcsOsApiLogWithColors (1u << 1)
#define EcsOsApiLogWithTimeStamp (1u << 2)
#define EcsOsApiLogWithTimeDelta (1u << 3)
////////////////////////////////////////////////////////////////////////////////
//// Entity flags (set in upper bits of ecs_record_t::row)
////////////////////////////////////////////////////////////////////////////////
#define EcsEntityIsId (1u << 31)
#define EcsEntityIsTarget (1u << 30)
#define EcsEntityIsTraversable (1u << 29)
////////////////////////////////////////////////////////////////////////////////
//// Id flags (used by ecs_id_record_t::flags)
////////////////////////////////////////////////////////////////////////////////
#define EcsIdOnDeleteRemove (1u << 0)
#define EcsIdOnDeleteDelete (1u << 1)
#define EcsIdOnDeletePanic (1u << 2)
#define EcsIdOnDeleteMask\
(EcsIdOnDeletePanic|EcsIdOnDeleteRemove|EcsIdOnDeleteDelete)
#define EcsIdOnDeleteObjectRemove (1u << 3)
#define EcsIdOnDeleteObjectDelete (1u << 4)
#define EcsIdOnDeleteObjectPanic (1u << 5)
#define EcsIdOnDeleteObjectMask\
(EcsIdOnDeleteObjectPanic|EcsIdOnDeleteObjectRemove|\
EcsIdOnDeleteObjectDelete)
#define EcsIdExclusive (1u << 6)
#define EcsIdDontInherit (1u << 7)
#define EcsIdTraversable (1u << 8)
#define EcsIdTag (1u << 9)
#define EcsIdWith (1u << 10)
#define EcsIdUnion (1u << 11)
#define EcsIdAlwaysOverride (1u << 12)
#define EcsIdHasOnAdd (1u << 16) /* Same values as table flags */
#define EcsIdHasOnRemove (1u << 17)
#define EcsIdHasOnSet (1u << 18)
#define EcsIdHasUnSet (1u << 19)
#define EcsIdHasOnTableFill (1u << 20)
#define EcsIdHasOnTableEmpty (1u << 21)
#define EcsIdHasOnTableCreate (1u << 22)
#define EcsIdHasOnTableDelete (1u << 23)
#define EcsIdEventMask\
(EcsIdHasOnAdd|EcsIdHasOnRemove|EcsIdHasOnSet|EcsIdHasUnSet|\
EcsIdHasOnTableFill|EcsIdHasOnTableEmpty|EcsIdHasOnTableCreate|\
EcsIdHasOnTableDelete)
#define EcsIdMarkedForDelete (1u << 30)
/* Utilities for converting from flags to delete policies and vice versa */
#define ECS_ID_ON_DELETE(flags) \
((ecs_entity_t[]){0, EcsRemove, EcsDelete, 0, EcsPanic}\
[((flags) & EcsIdOnDeleteMask)])
#define ECS_ID_ON_DELETE_TARGET(flags) ECS_ID_ON_DELETE(flags >> 3)
#define ECS_ID_ON_DELETE_FLAG(id) (1u << ((id) - EcsRemove))
#define ECS_ID_ON_DELETE_TARGET_FLAG(id) (1u << (3 + ((id) - EcsRemove)))
////////////////////////////////////////////////////////////////////////////////
//// Iterator flags (used by ecs_iter_t::flags)
////////////////////////////////////////////////////////////////////////////////
#define EcsIterIsValid (1u << 0u) /* Does iterator contain valid result */
#define EcsIterNoData (1u << 1u) /* Does iterator provide (component) data */
#define EcsIterIsInstanced (1u << 2u) /* Is iterator instanced */
#define EcsIterHasShared (1u << 3u) /* Does result have shared terms */
#define EcsIterTableOnly (1u << 4u) /* Result only populates table */
#define EcsIterEntityOptional (1u << 5u) /* Treat terms with entity subject as optional */
#define EcsIterNoResults (1u << 6u) /* Iterator has no results */
#define EcsIterIgnoreThis (1u << 7u) /* Only evaluate non-this terms */
#define EcsIterMatchVar (1u << 8u)
#define EcsIterHasCondSet (1u << 10u) /* Does iterator have conditionally set fields */
#define EcsIterProfile (1u << 11u) /* Profile iterator performance */
////////////////////////////////////////////////////////////////////////////////
//// Event flags (used by ecs_event_decs_t::flags)
////////////////////////////////////////////////////////////////////////////////
#define EcsEventTableOnly (1u << 4u) /* Table event (no data, same as iter flags) */
#define EcsEventNoOnSet (1u << 16u) /* Don't emit OnSet/UnSet for inherited ids */
////////////////////////////////////////////////////////////////////////////////
//// Filter flags (used by ecs_filter_t::flags)
////////////////////////////////////////////////////////////////////////////////
#define EcsFilterMatchThis (1u << 1u) /* Has terms that match This */
#define EcsFilterMatchOnlyThis (1u << 2u) /* Has only terms that match This */
#define EcsFilterMatchPrefab (1u << 3u) /* Does filter match prefabs */
#define EcsFilterMatchDisabled (1u << 4u) /* Does filter match disabled entities */
#define EcsFilterMatchEmptyTables (1u << 5u) /* Does filter return empty tables */
#define EcsFilterMatchAnything (1u << 6u) /* False if filter has no/only Not terms */
#define EcsFilterNoData (1u << 7u) /* When true, data fields won't be populated */
#define EcsFilterIsInstanced (1u << 8u) /* Is filter instanced (see ecs_filter_desc_t) */
#define EcsFilterPopulate (1u << 9u) /* Populate data, ignore non-matching fields */
#define EcsFilterHasCondSet (1u << 10u) /* Does filter have conditionally set fields */
#define EcsFilterUnresolvedByName (1u << 11u) /* Use by-name matching for unresolved entity identifiers */
#define EcsFilterHasPred (1u << 12u) /* Filter has equality predicates */
#define EcsFilterHasScopes (1u << 13u) /* Filter has query scopes */
////////////////////////////////////////////////////////////////////////////////
//// Table flags (used by ecs_table_t::flags)
////////////////////////////////////////////////////////////////////////////////
#define EcsTableHasBuiltins (1u << 1u) /* Does table have builtin components */
#define EcsTableIsPrefab (1u << 2u) /* Does the table store prefabs */
#define EcsTableHasIsA (1u << 3u) /* Does the table have IsA relationship */
#define EcsTableHasChildOf (1u << 4u) /* Does the table type ChildOf relationship */
#define EcsTableHasName (1u << 5u) /* Does the table type have (Identifier, Name) */
#define EcsTableHasPairs (1u << 6u) /* Does the table type have pairs */
#define EcsTableHasModule (1u << 7u) /* Does the table have module data */
#define EcsTableIsDisabled (1u << 8u) /* Does the table type has EcsDisabled */
#define EcsTableHasCtors (1u << 9u)
#define EcsTableHasDtors (1u << 10u)
#define EcsTableHasCopy (1u << 11u)
#define EcsTableHasMove (1u << 12u)
#define EcsTableHasUnion (1u << 13u)
#define EcsTableHasToggle (1u << 14u)
#define EcsTableHasOverrides (1u << 15u)
#define EcsTableHasOnAdd (1u << 16u) /* Same values as id flags */
#define EcsTableHasOnRemove (1u << 17u)
#define EcsTableHasOnSet (1u << 18u)
#define EcsTableHasUnSet (1u << 19u)
#define EcsTableHasOnTableFill (1u << 20u)
#define EcsTableHasOnTableEmpty (1u << 21u)
#define EcsTableHasOnTableCreate (1u << 22u)
#define EcsTableHasOnTableDelete (1u << 23u)
#define EcsTableHasTraversable (1u << 25u)
#define EcsTableHasTarget (1u << 26u)
#define EcsTableMarkedForDelete (1u << 30u)
/* Composite table flags */
#define EcsTableHasLifecycle (EcsTableHasCtors | EcsTableHasDtors)
#define EcsTableIsComplex (EcsTableHasLifecycle | EcsTableHasUnion | EcsTableHasToggle)
#define EcsTableHasAddActions (EcsTableHasIsA | EcsTableHasUnion | EcsTableHasCtors | EcsTableHasOnAdd | EcsTableHasOnSet)
#define EcsTableHasRemoveActions (EcsTableHasIsA | EcsTableHasDtors | EcsTableHasOnRemove | EcsTableHasUnSet)
////////////////////////////////////////////////////////////////////////////////
//// Query flags (used by ecs_query_t::flags)
////////////////////////////////////////////////////////////////////////////////
#define EcsQueryHasRefs (1u << 1u) /* Does query have references */
#define EcsQueryIsSubquery (1u << 2u) /* Is query a subquery */
#define EcsQueryIsOrphaned (1u << 3u) /* Is subquery orphaned */
#define EcsQueryHasOutTerms (1u << 4u) /* Does query have out terms */
#define EcsQueryHasNonThisOutTerms (1u << 5u) /* Does query have non-this out terms */
#define EcsQueryHasMonitor (1u << 6u) /* Does query track changes */
#define EcsQueryTrivialIter (1u << 7u) /* Does the query require special features to iterate */
////////////////////////////////////////////////////////////////////////////////
//// Aperiodic action flags (used by ecs_run_aperiodic)
////////////////////////////////////////////////////////////////////////////////
#define EcsAperiodicEmptyTables (1u << 1u) /* Process pending empty table events */
#define EcsAperiodicComponentMonitors (1u << 2u) /* Process component monitors */
#define EcsAperiodicEmptyQueries (1u << 4u) /* Process empty queries */
#ifdef __cplusplus
}
#endif
#endif

View File

@@ -0,0 +1,100 @@
/**
* @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
#include "api_types.h"
#ifdef __cplusplus
extern "C" {
#endif
/** This is the largest possible component id. Components for the most part
* occupy the same id range as entities, however they are not allowed to overlap
* with (8) bits reserved for id flags. */
#define ECS_MAX_COMPONENT_ID (~((uint32_t)(ECS_ID_FLAGS_MASK >> 32)))
/** The maximum number of nested function calls before the core will throw a
* cycle detected error */
#define ECS_MAX_RECURSION (512)
/** Maximum length of a parser token (used by parser-related addons) */
#define ECS_MAX_TOKEN_SIZE (256)
////////////////////////////////////////////////////////////////////////////////
//// Global type handles
////////////////////////////////////////////////////////////////////////////////
/** This allows passing 0 as type to functions that accept ids */
#define FLECS_ID0ID_ 0
FLECS_API
char* ecs_module_path_from_c(
const char *c_name);
bool ecs_identifier_is_0(
const char *id);
/* Constructor that zeromem's a component value */
FLECS_API
void ecs_default_ctor(
void *ptr,
int32_t count,
const ecs_type_info_t *ctx);
/* Create allocated string from format */
FLECS_DBG_API
char* ecs_vasprintf(
const char *fmt,
va_list args);
/* Create allocated string from format */
FLECS_API
char* ecs_asprintf(
const char *fmt,
...);
/* Convert identifier to snake case */
FLECS_API
char* flecs_to_snake_case(
const char *str);
FLECS_DBG_API
int32_t flecs_table_observed_count(
const ecs_table_t *table);
FLECS_DBG_API
void flecs_dump_backtrace(
void *stream);
/** Calculate offset from address */
#ifdef __cplusplus
#define ECS_OFFSET(o, offset) reinterpret_cast<void*>((reinterpret_cast<uintptr_t>(o)) + (static_cast<uintptr_t>(offset)))
#else
#define ECS_OFFSET(o, offset) (void*)(((uintptr_t)(o)) + ((uintptr_t)(offset)))
#endif
#define ECS_OFFSET_T(o, T) ECS_OFFSET(o, ECS_SIZEOF(T))
#define ECS_ELEM(ptr, size, index) ECS_OFFSET(ptr, (size) * (index))
#define ECS_ELEM_T(o, T, index) ECS_ELEM(o, ECS_SIZEOF(T), index)
/** Enable/disable bitsets */
#define ECS_BIT_SET(flags, bit) (flags) |= (bit)
#define ECS_BIT_CLEAR(flags, bit) (flags) &= ~(bit)
#define ECS_BIT_COND(flags, bit, cond) ((cond) \
? (ECS_BIT_SET(flags, bit)) \
: (ECS_BIT_CLEAR(flags, bit)))
#define ECS_BIT_IS_SET(flags, bit) ((flags) & (bit))
#ifdef __cplusplus
}
#endif
#endif

View File

@@ -0,0 +1,312 @@
/**
* @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
#include "api_defines.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;
/** Table data */
typedef struct ecs_data_t ecs_data_t;
/* Switch list */
typedef struct ecs_switch_t ecs_switch_t;
/* Cached query table data */
typedef struct ecs_query_table_match_t ecs_query_table_match_t;
////////////////////////////////////////////////////////////////////////////////
//// Non-opaque types
////////////////////////////////////////////////////////////////////////////////
/** Mixin for emitting events to triggers/observers */
/** All observers for a specific event */
typedef struct ecs_event_record_t {
struct ecs_event_id_record_t *any;
struct ecs_event_id_record_t *wildcard;
struct ecs_event_id_record_t *wildcard_pair;
ecs_map_t event_ids; /* map<id, ecs_event_id_record_t> */
ecs_entity_t event;
} ecs_event_record_t;
struct ecs_observable_t {
ecs_event_record_t on_add;
ecs_event_record_t on_remove;
ecs_event_record_t on_set;
ecs_event_record_t un_set;
ecs_event_record_t on_wildcard;
ecs_sparse_t events; /* sparse<event, ecs_event_record_t> */
};
/** Record for entity index */
struct ecs_record_t {
ecs_id_record_t *idr; /* Id record to (*, entity) for target entities */
ecs_table_t *table; /* Identifies a type (and table) in world */
uint32_t row; /* Table row of the entity */
int32_t dense; /* Index in dense array */
};
/** Range in table */
typedef struct ecs_table_range_t {
ecs_table_t *table;
int32_t offset; /* Leave both members to 0 to cover entire table */
int32_t count;
} ecs_table_range_t;
/** Value of query variable */
typedef struct ecs_var_t {
ecs_table_range_t range; /* Set when variable stores a range of entities */
ecs_entity_t entity; /* Set when variable stores single entity */
/* Most entities can be stored as a range by setting range.count to 1,
* however in order to also be able to store empty entities in variables,
* a separate entity member is needed. Both range and entity may be set at
* the same time, as long as they are consistent. */
} ecs_var_t;
/** Cached reference. */
struct ecs_ref_t {
ecs_entity_t entity; /* Entity */
ecs_entity_t id; /* Component id */
struct ecs_table_record_t *tr; /* Table record for component */
ecs_record_t *record; /* Entity index record */
};
/* Cursor to stack allocator. Type is public to allow for white box testing. */
struct ecs_stack_page_t;
typedef struct ecs_stack_cursor_t {
struct ecs_stack_cursor_t *prev;
struct ecs_stack_page_t *page;
int16_t sp;
bool is_free;
#ifdef FLECS_DEBUG
struct ecs_stack_t *owner;
#endif
} ecs_stack_cursor_t;
/* Page-iterator specific data */
typedef struct ecs_page_iter_t {
int32_t offset;
int32_t limit;
int32_t remaining;
} ecs_page_iter_t;
/* Worker-iterator specific data */
typedef struct ecs_worker_iter_t {
int32_t index;
int32_t count;
} ecs_worker_iter_t;
/* Convenience struct to iterate table array for id */
typedef struct ecs_table_cache_iter_t {
struct ecs_table_cache_hdr_t *cur, *next;
struct ecs_table_cache_hdr_t *next_list;
} ecs_table_cache_iter_t;
/** Term-iterator specific data */
typedef struct ecs_term_iter_t {
ecs_term_t term;
ecs_id_record_t *self_index;
ecs_id_record_t *set_index;
ecs_id_record_t *cur;
ecs_table_cache_iter_t it;
int32_t index;
int32_t observed_table_count;
ecs_table_t *table;
int32_t cur_match;
int32_t match_count;
int32_t last_column;
bool empty_tables;
/* Storage */
ecs_id_t id;
int32_t column;
ecs_entity_t subject;
ecs_size_t size;
void *ptr;
} ecs_term_iter_t;
typedef enum ecs_iter_kind_t {
EcsIterEvalCondition,
EcsIterEvalTables,
EcsIterEvalChain,
EcsIterEvalNone
} ecs_iter_kind_t;
/** Filter-iterator specific data */
typedef struct ecs_filter_iter_t {
const ecs_filter_t *filter;
ecs_iter_kind_t kind;
ecs_term_iter_t term_iter;
int32_t matches_left;
int32_t pivot_term;
} ecs_filter_iter_t;
/** Query-iterator specific data */
typedef struct ecs_query_iter_t {
ecs_query_t *query;
ecs_query_table_match_t *node, *prev, *last;
int32_t sparse_smallest;
int32_t sparse_first;
int32_t bitset_first;
int32_t skip_count;
} ecs_query_iter_t;
/** Snapshot-iterator specific data */
typedef struct ecs_snapshot_iter_t {
ecs_filter_t filter;
ecs_vec_t tables; /* ecs_table_leaf_t */
int32_t index;
} ecs_snapshot_iter_t;
typedef struct ecs_rule_op_profile_t {
int32_t count[2]; /* 0 = enter, 1 = redo */
} ecs_rule_op_profile_t;
/** Rule-iterator specific data */
typedef struct ecs_rule_iter_t {
const ecs_rule_t *rule;
struct ecs_var_t *vars; /* Variable storage */
const struct ecs_rule_var_t *rule_vars;
const struct ecs_rule_op_t *ops;
struct ecs_rule_op_ctx_t *op_ctx; /* Operation-specific state */
uint64_t *written;
#ifdef FLECS_DEBUG
ecs_rule_op_profile_t *profile;
#endif
bool redo;
int16_t op;
int16_t sp;
} ecs_rule_iter_t;
/* Bits for tracking whether a cache was used/whether the array was allocated.
* Used by flecs_iter_init, flecs_iter_validate and ecs_iter_fini.
* Constants are named to enable easy macro substitution. */
#define flecs_iter_cache_ids (1u << 0u)
#define flecs_iter_cache_columns (1u << 1u)
#define flecs_iter_cache_sources (1u << 2u)
#define flecs_iter_cache_ptrs (1u << 3u)
#define flecs_iter_cache_match_indices (1u << 4u)
#define flecs_iter_cache_variables (1u << 5u)
#define flecs_iter_cache_all (255)
/* Inline iterator arrays to prevent allocations for small array sizes */
typedef struct ecs_iter_cache_t {
ecs_stack_cursor_t *stack_cursor; /* Stack cursor to restore to */
ecs_flags8_t used; /* For which fields is the cache used */
ecs_flags8_t allocated; /* Which fields are allocated */
} ecs_iter_cache_t;
/* Private iterator data. Used by iterator implementations to keep track of
* progress & to provide builtin storage. */
typedef struct ecs_iter_private_t {
union {
ecs_term_iter_t term;
ecs_filter_iter_t filter;
ecs_query_iter_t query;
ecs_rule_iter_t rule;
ecs_snapshot_iter_t snapshot;
ecs_page_iter_t page;
ecs_worker_iter_t worker;
} iter; /* Iterator specific data */
void *entity_iter; /* Filter applied after matching a table */
ecs_iter_cache_t cache; /* Inline arrays to reduce allocations */
} ecs_iter_private_t;
/** Iterator */
struct ecs_iter_t {
/* World */
ecs_world_t *world; /* The world */
ecs_world_t *real_world; /* Actual world. This differs from world when in readonly mode */
/* Matched data */
ecs_entity_t *entities; /* Entity identifiers */
void **ptrs; /* Pointers to components. Array if from this, pointer if not. */
ecs_size_t *sizes; /* Component sizes */
ecs_table_t *table; /* Current table */
ecs_table_t *other_table; /* Prev or next table when adding/removing */
ecs_id_t *ids; /* (Component) ids */
ecs_var_t *variables; /* Values of variables (if any) */
int32_t *columns; /* Query term to table column mapping */
ecs_entity_t *sources; /* Entity on which the id was matched (0 if same as entities) */
int32_t *match_indices; /* Indices of current match for term. Allows an iterator to iterate
* all permutations of wildcards in query. */
ecs_ref_t *references; /* Cached refs to components (if iterating a cache) */
ecs_flags64_t constrained_vars; /* Bitset that marks constrained variables */
uint64_t group_id; /* Group id for table, if group_by is used */
int32_t field_count; /* Number of fields in iterator */
/* Input information */
ecs_entity_t system; /* The system (if applicable) */
ecs_entity_t event; /* The event (if applicable) */
ecs_id_t event_id; /* The (component) id for the event */
/* Query information */
ecs_term_t *terms; /* Terms of query being evaluated */
int32_t table_count; /* Active table count for query */
int32_t term_index; /* Index of term that emitted an event.
* This field will be set to the 'index' field
* of an observer term. */
int32_t variable_count; /* Number of variables for query */
char **variable_names; /* Names of variables (if any) */
/* Context */
void *param; /* Param passed to ecs_run */
void *ctx; /* System context */
void *binding_ctx; /* Binding context */
/* Time */
ecs_ftime_t delta_time; /* Time elapsed since last frame */
ecs_ftime_t delta_system_time;/* Time elapsed since last system invocation */
/* Iterator counters */
int32_t frame_offset; /* Offset relative to start of iteration */
int32_t offset; /* Offset relative to current table */
int32_t count; /* Number of entities to iterate */
int32_t instance_count; /* Number of entities to iterate before next table */
/* Iterator flags */
ecs_flags32_t flags;
ecs_entity_t interrupted_by; /* When set, system execution is interrupted */
ecs_iter_private_t priv; /* Private data */
/* Chained iterators */
ecs_iter_next_action_t next; /* Function to progress iterator */
ecs_iter_action_t callback; /* Callback of system or observer */
ecs_iter_action_t set_var; /* Invoked after setting variable (optionally set) */
ecs_iter_fini_action_t fini; /* Function to cleanup iterator resources */
ecs_iter_t *chain_it; /* Optional, allows for creating iterator chains */
};
#ifdef __cplusplus
}
#endif
#endif

View File

@@ -0,0 +1,78 @@
/**
* @file bitset.h
* @brief Bitset data structure.
*/
#ifndef FLECS_BITSET_H
#define FLECS_BITSET_H
#include "flecs/private/api_defines.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. */
FLECS_DBG_API
void flecs_bitset_init(
ecs_bitset_t *bs);
/** Deinialize bitset. */
FLECS_DBG_API
void flecs_bitset_fini(
ecs_bitset_t *bs);
/** Add n elements to bitset. */
FLECS_DBG_API
void flecs_bitset_addn(
ecs_bitset_t *bs,
int32_t count);
/** Ensure element exists. */
FLECS_DBG_API
void flecs_bitset_ensure(
ecs_bitset_t *bs,
int32_t count);
/** Set element. */
FLECS_DBG_API
void flecs_bitset_set(
ecs_bitset_t *bs,
int32_t elem,
bool value);
/** Get element. */
FLECS_DBG_API
bool flecs_bitset_get(
const ecs_bitset_t *bs,
int32_t elem);
/** Return number of elements. */
FLECS_DBG_API
int32_t flecs_bitset_count(
const ecs_bitset_t *bs);
/** Remove from bitset. */
FLECS_DBG_API
void flecs_bitset_remove(
ecs_bitset_t *bs,
int32_t elem);
/** Swap values in bitset. */
FLECS_DBG_API
void flecs_bitset_swap(
ecs_bitset_t *bs,
int32_t elem_a,
int32_t elem_b);
#ifdef __cplusplus
}
#endif
#endif

View File

@@ -0,0 +1,82 @@
/**
* @file block_allocator.h
* @brief Block allocator.
*/
#ifndef FLECS_BLOCK_ALLOCATOR_H
#define FLECS_BLOCK_ALLOCATOR_H
#include "api_defines.h"
typedef struct ecs_block_allocator_block_t {
void *memory;
struct ecs_block_allocator_block_t *next;
} ecs_block_allocator_block_t;
typedef struct ecs_block_allocator_chunk_header_t {
struct ecs_block_allocator_chunk_header_t *next;
} ecs_block_allocator_chunk_header_t;
typedef struct ecs_block_allocator_t {
ecs_block_allocator_chunk_header_t *head;
ecs_block_allocator_block_t *block_head;
ecs_block_allocator_block_t *block_tail;
int32_t chunk_size;
int32_t data_size;
int32_t chunks_per_block;
int32_t block_size;
int32_t alloc_count;
} ecs_block_allocator_t;
FLECS_API
void flecs_ballocator_init(
ecs_block_allocator_t *ba,
ecs_size_t size);
#define flecs_ballocator_init_t(ba, T)\
flecs_ballocator_init(ba, ECS_SIZEOF(T))
#define flecs_ballocator_init_n(ba, T, count)\
flecs_ballocator_init(ba, ECS_SIZEOF(T) * count)
FLECS_API
ecs_block_allocator_t* flecs_ballocator_new(
ecs_size_t size);
#define flecs_ballocator_new_t(T)\
flecs_ballocator_new(ECS_SIZEOF(T))
#define flecs_ballocator_new_n(T, count)\
flecs_ballocator_new(ECS_SIZEOF(T) * count)
FLECS_API
void flecs_ballocator_fini(
ecs_block_allocator_t *ba);
FLECS_API
void flecs_ballocator_free(
ecs_block_allocator_t *ba);
FLECS_API
void* flecs_balloc(
ecs_block_allocator_t *allocator);
FLECS_API
void* flecs_bcalloc(
ecs_block_allocator_t *allocator);
FLECS_API
void flecs_bfree(
ecs_block_allocator_t *allocator,
void *memory);
FLECS_API
void* flecs_brealloc(
ecs_block_allocator_t *dst,
ecs_block_allocator_t *src,
void *memory);
FLECS_API
void* flecs_bdup(
ecs_block_allocator_t *ba,
void *memory);
#endif

View File

@@ -0,0 +1,148 @@
/**
* @file hashmap.h
* @brief Hashmap data structure.
*/
#ifndef FLECS_HASHMAP_H
#define FLECS_HASHMAP_H
#include "api_defines.h"
#ifdef __cplusplus
extern "C" {
#endif
typedef struct {
ecs_vec_t keys;
ecs_vec_t values;
} ecs_hm_bucket_t;
typedef struct {
ecs_hash_value_action_t hash;
ecs_compare_action_t compare;
ecs_size_t key_size;
ecs_size_t value_size;
ecs_block_allocator_t *hashmap_allocator;
ecs_block_allocator_t bucket_allocator;
ecs_map_t impl;
} ecs_hashmap_t;
typedef struct {
ecs_map_iter_t it;
ecs_hm_bucket_t *bucket;
int32_t index;
} flecs_hashmap_iter_t;
typedef struct {
void *key;
void *value;
uint64_t hash;
} flecs_hashmap_result_t;
FLECS_DBG_API
void flecs_hashmap_init_(
ecs_hashmap_t *hm,
ecs_size_t key_size,
ecs_size_t value_size,
ecs_hash_value_action_t hash,
ecs_compare_action_t compare,
ecs_allocator_t *allocator);
#define flecs_hashmap_init(hm, K, V, hash, compare, allocator)\
flecs_hashmap_init_(hm, ECS_SIZEOF(K), ECS_SIZEOF(V), hash, compare, allocator)
FLECS_DBG_API
void flecs_hashmap_fini(
ecs_hashmap_t *map);
FLECS_DBG_API
void* flecs_hashmap_get_(
const ecs_hashmap_t *map,
ecs_size_t key_size,
const void *key,
ecs_size_t value_size);
#define flecs_hashmap_get(map, key, V)\
(V*)flecs_hashmap_get_(map, ECS_SIZEOF(*key), key, ECS_SIZEOF(V))
FLECS_DBG_API
flecs_hashmap_result_t flecs_hashmap_ensure_(
ecs_hashmap_t *map,
ecs_size_t key_size,
const void *key,
ecs_size_t value_size);
#define flecs_hashmap_ensure(map, key, V)\
flecs_hashmap_ensure_(map, ECS_SIZEOF(*key), key, ECS_SIZEOF(V))
FLECS_DBG_API
void flecs_hashmap_set_(
ecs_hashmap_t *map,
ecs_size_t key_size,
void *key,
ecs_size_t value_size,
const void *value);
#define flecs_hashmap_set(map, key, value)\
flecs_hashmap_set_(map, ECS_SIZEOF(*key), key, ECS_SIZEOF(*value), value)
FLECS_DBG_API
void flecs_hashmap_remove_(
ecs_hashmap_t *map,
ecs_size_t key_size,
const void *key,
ecs_size_t value_size);
#define flecs_hashmap_remove(map, key, V)\
flecs_hashmap_remove_(map, ECS_SIZEOF(*key), key, ECS_SIZEOF(V))
FLECS_DBG_API
void flecs_hashmap_remove_w_hash_(
ecs_hashmap_t *map,
ecs_size_t key_size,
const void *key,
ecs_size_t value_size,
uint64_t hash);
#define flecs_hashmap_remove_w_hash(map, key, V, hash)\
flecs_hashmap_remove_w_hash_(map, ECS_SIZEOF(*key), key, ECS_SIZEOF(V), hash)
FLECS_DBG_API
ecs_hm_bucket_t* flecs_hashmap_get_bucket(
const ecs_hashmap_t *map,
uint64_t hash);
FLECS_DBG_API
void flecs_hm_bucket_remove(
ecs_hashmap_t *map,
ecs_hm_bucket_t *bucket,
uint64_t hash,
int32_t index);
FLECS_DBG_API
void flecs_hashmap_copy(
ecs_hashmap_t *dst,
const ecs_hashmap_t *src);
FLECS_DBG_API
flecs_hashmap_iter_t flecs_hashmap_iter(
ecs_hashmap_t *map);
FLECS_DBG_API
void* flecs_hashmap_next_(
flecs_hashmap_iter_t *it,
ecs_size_t key_size,
void *key_out,
ecs_size_t value_size);
#define flecs_hashmap_next(map, V)\
(V*)flecs_hashmap_next_(map, 0, NULL, ECS_SIZEOF(V))
#define flecs_hashmap_next_w_key(map, K, key, V)\
(V*)flecs_hashmap_next_(map, ECS_SIZEOF(K), key, ECS_SIZEOF(V))
#ifdef __cplusplus
}
#endif
#endif

View File

@@ -0,0 +1,193 @@
/**
* @file map.h
* @brief Map data structure.
*/
#ifndef FLECS_MAP_H
#define FLECS_MAP_H
#include "api_defines.h"
#ifdef __cplusplus
extern "C" {
#endif
typedef uint64_t ecs_map_data_t;
typedef ecs_map_data_t ecs_map_key_t;
typedef ecs_map_data_t ecs_map_val_t;
/* Map type */
typedef struct ecs_bucket_entry_t {
ecs_map_key_t key;
ecs_map_val_t value;
struct ecs_bucket_entry_t *next;
} ecs_bucket_entry_t;
typedef struct ecs_bucket_t {
ecs_bucket_entry_t *first;
} ecs_bucket_t;
typedef struct ecs_map_t {
uint8_t bucket_shift;
bool shared_allocator;
ecs_bucket_t *buckets;
int32_t bucket_count;
int32_t count;
struct ecs_block_allocator_t *entry_allocator;
struct ecs_allocator_t *allocator;
} ecs_map_t;
typedef struct ecs_map_iter_t {
const ecs_map_t *map;
ecs_bucket_t *bucket;
ecs_bucket_entry_t *entry;
ecs_map_data_t *res;
} ecs_map_iter_t;
typedef struct ecs_map_params_t {
struct ecs_allocator_t *allocator;
struct ecs_block_allocator_t entry_allocator;
} ecs_map_params_t;
/* Function/macro postfixes meaning:
* _ptr: access ecs_map_val_t as void*
* _ref: access ecs_map_val_t* as T**
* _deref: dereferences a _ref
* _alloc: if _ptr is NULL, alloc
* _free: if _ptr is not NULL, free
*/
FLECS_API
void ecs_map_params_init(
ecs_map_params_t *params,
struct ecs_allocator_t *allocator);
FLECS_API
void ecs_map_params_fini(
ecs_map_params_t *params);
/** Initialize new map. */
FLECS_API
void ecs_map_init(
ecs_map_t *map,
struct ecs_allocator_t *allocator);
/** Initialize new map. */
FLECS_API
void ecs_map_init_w_params(
ecs_map_t *map,
ecs_map_params_t *params);
/** Initialize new map if uninitialized, leave as is otherwise */
FLECS_API
void ecs_map_init_if(
ecs_map_t *map,
struct ecs_allocator_t *allocator);
FLECS_API
void ecs_map_init_w_params_if(
ecs_map_t *result,
ecs_map_params_t *params);
/** Deinitialize map. */
FLECS_API
void ecs_map_fini(
ecs_map_t *map);
/** Get element for key, returns NULL if they key doesn't exist. */
FLECS_API
ecs_map_val_t* ecs_map_get(
const ecs_map_t *map,
ecs_map_key_t key);
/* Get element as pointer (auto-dereferences _ptr) */
FLECS_API
void* ecs_map_get_deref_(
const ecs_map_t *map,
ecs_map_key_t key);
/** Get or insert element for key. */
FLECS_API
ecs_map_val_t* ecs_map_ensure(
ecs_map_t *map,
ecs_map_key_t key);
/** Get or insert pointer element for key, allocate if the pointer is NULL */
FLECS_API
void* ecs_map_ensure_alloc(
ecs_map_t *map,
ecs_size_t elem_size,
ecs_map_key_t key);
/** Insert element for key. */
FLECS_API
void ecs_map_insert(
ecs_map_t *map,
ecs_map_key_t key,
ecs_map_val_t value);
/** Insert pointer element for key, populate with new allocation. */
FLECS_API
void* ecs_map_insert_alloc(
ecs_map_t *map,
ecs_size_t elem_size,
ecs_map_key_t key);
/** Remove key from map. */
FLECS_API
ecs_map_val_t ecs_map_remove(
ecs_map_t *map,
ecs_map_key_t key);
/* Remove pointer element, free if not NULL */
FLECS_API
void ecs_map_remove_free(
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. */
#define ecs_map_count(map) ((map) ? (map)->count : 0)
/** Is map initialized */
#define ecs_map_is_init(map) ((map) ? (map)->bucket_shift != 0 : false)
/** 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
bool ecs_map_next(
ecs_map_iter_t *iter);
/** Copy map. */
FLECS_API
void ecs_map_copy(
ecs_map_t *dst,
const ecs_map_t *src);
#define ecs_map_get_ref(m, T, k) ECS_CAST(T**, ecs_map_get(m, k))
#define ecs_map_get_deref(m, T, k) ECS_CAST(T*, ecs_map_get_deref_(m, k))
#define ecs_map_ensure_ref(m, T, k) ECS_CAST(T**, ecs_map_ensure(m, k))
#define ecs_map_insert_ptr(m, k, v) ecs_map_insert(m, k, ECS_CAST(ecs_map_val_t, ECS_PTR_CAST(uintptr_t, v)))
#define ecs_map_insert_alloc_t(m, T, k) ECS_CAST(T*, ecs_map_insert_alloc(m, ECS_SIZEOF(T), k))
#define ecs_map_ensure_alloc_t(m, T, k) ECS_PTR_CAST(T*, (uintptr_t)ecs_map_ensure_alloc(m, ECS_SIZEOF(T), k))
#define ecs_map_remove_ptr(m, k) (ECS_PTR_CAST(void*, ECS_CAST(uintptr_t, (ecs_map_remove(m, k)))))
#define ecs_map_key(it) ((it)->res[0])
#define ecs_map_value(it) ((it)->res[1])
#define ecs_map_ptr(it) ECS_PTR_CAST(void*, ECS_CAST(uintptr_t, ecs_map_value(it)))
#define ecs_map_ref(it, T) (ECS_CAST(T**, &((it)->res[1])))
#ifdef __cplusplus
}
#endif
#endif

View File

@@ -0,0 +1,215 @@
/**
* @file sparse.h
* @brief Sparse set data structure.
*/
#ifndef FLECS_SPARSE_H
#define FLECS_SPARSE_H
#include "flecs/private/api_defines.h"
#ifdef __cplusplus
extern "C" {
#endif
/** The number of elements in a single page */
#define FLECS_SPARSE_PAGE_SIZE (1 << FLECS_SPARSE_PAGE_BITS)
typedef struct ecs_sparse_t {
ecs_vec_t dense; /* Dense array with indices to sparse array. The
* dense array stores both alive and not alive
* sparse indices. The 'count' member keeps
* track of which indices are alive. */
ecs_vec_t pages; /* Chunks with sparse arrays & data */
ecs_size_t size; /* Element size */
int32_t count; /* Number of alive entries */
uint64_t max_id; /* Local max index (if no global is set) */
struct ecs_allocator_t *allocator;
struct ecs_block_allocator_t *page_allocator;
} ecs_sparse_t;
/** Initialize sparse set */
FLECS_DBG_API
void flecs_sparse_init(
ecs_sparse_t *sparse,
struct ecs_allocator_t *allocator,
struct ecs_block_allocator_t *page_allocator,
ecs_size_t elem_size);
#define flecs_sparse_init_t(sparse, allocator, page_allocator, T)\
flecs_sparse_init(sparse, allocator, page_allocator, ECS_SIZEOF(T))
FLECS_DBG_API
void flecs_sparse_fini(
ecs_sparse_t *sparse);
/** Remove all elements from sparse set */
FLECS_DBG_API
void flecs_sparse_clear(
ecs_sparse_t *sparse);
/** Add element to sparse set, this generates or recycles an id */
FLECS_DBG_API
void* flecs_sparse_add(
ecs_sparse_t *sparse,
ecs_size_t elem_size);
#define flecs_sparse_add_t(sparse, T)\
ECS_CAST(T*, flecs_sparse_add(sparse, ECS_SIZEOF(T)))
/** Get last issued id. */
FLECS_DBG_API
uint64_t flecs_sparse_last_id(
const ecs_sparse_t *sparse);
/** Generate or recycle a new id. */
FLECS_DBG_API
uint64_t flecs_sparse_new_id(
ecs_sparse_t *sparse);
/** Remove an element */
FLECS_DBG_API
void flecs_sparse_remove(
ecs_sparse_t *sparse,
ecs_size_t elem_size,
uint64_t id);
#define flecs_sparse_remove_t(sparse, T, id)\
flecs_sparse_remove(sparse, ECS_SIZEOF(T), id)
/** Test if id is alive, which requires the generation count to match. */
FLECS_DBG_API
bool flecs_sparse_is_alive(
const ecs_sparse_t *sparse,
uint64_t id);
/** Get value from sparse set by dense id. This function is useful in
* combination with flecs_sparse_count for iterating all values in the set. */
FLECS_DBG_API
void* flecs_sparse_get_dense(
const ecs_sparse_t *sparse,
ecs_size_t elem_size,
int32_t index);
#define flecs_sparse_get_dense_t(sparse, T, index)\
ECS_CAST(T*, flecs_sparse_get_dense(sparse, ECS_SIZEOF(T), index))
/** Get the number of alive elements in the sparse set. */
FLECS_DBG_API
int32_t flecs_sparse_count(
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_DBG_API
void* flecs_sparse_get(
const ecs_sparse_t *sparse,
ecs_size_t elem_size,
uint64_t id);
#define flecs_sparse_get_t(sparse, T, index)\
ECS_CAST(T*, flecs_sparse_get(sparse, ECS_SIZEOF(T), index))
/** Same as flecs_sparse_get, but doesn't assert if id is not alive. */
FLECS_DBG_API
void* flecs_sparse_try(
const ecs_sparse_t *sparse,
ecs_size_t elem_size,
uint64_t id);
#define flecs_sparse_try_t(sparse, T, index)\
ECS_CAST(T*, flecs_sparse_try(sparse, ECS_SIZEOF(T), index))
/** Like get_sparse, but don't care whether element is alive or not. */
FLECS_DBG_API
void* flecs_sparse_get_any(
const ecs_sparse_t *sparse,
ecs_size_t elem_size,
uint64_t id);
#define flecs_sparse_get_any_t(sparse, T, index)\
ECS_CAST(T*, flecs_sparse_get_any(sparse, ECS_SIZEOF(T), index))
/** Get or create element by (sparse) id. */
FLECS_DBG_API
void* flecs_sparse_ensure(
ecs_sparse_t *sparse,
ecs_size_t elem_size,
uint64_t id);
#define flecs_sparse_ensure_t(sparse, T, index)\
ECS_CAST(T*, flecs_sparse_ensure(sparse, ECS_SIZEOF(T), index))
/** Fast version of ensure, no liveliness checking */
FLECS_DBG_API
void* flecs_sparse_ensure_fast(
ecs_sparse_t *sparse,
ecs_size_t elem_size,
uint64_t id);
#define flecs_sparse_ensure_fast_t(sparse, T, index)\
ECS_CAST(T*, flecs_sparse_ensure_fast(sparse, ECS_SIZEOF(T), index))
/** Get pointer to ids (alive and not alive). Use with count() or size(). */
FLECS_DBG_API
const uint64_t* flecs_sparse_ids(
const ecs_sparse_t *sparse);
/* Publicly exposed APIs
* The flecs_ functions aren't exposed directly as this can cause some
* optimizers to not consider them for link time optimization. */
FLECS_API
void ecs_sparse_init(
ecs_sparse_t *sparse,
ecs_size_t elem_size);
#define ecs_sparse_init_t(sparse, T)\
ecs_sparse_init(sparse, ECS_SIZEOF(T))
FLECS_API
void* ecs_sparse_add(
ecs_sparse_t *sparse,
ecs_size_t elem_size);
#define ecs_sparse_add_t(sparse, T)\
ECS_CAST(T*, ecs_sparse_add(sparse, ECS_SIZEOF(T)))
FLECS_API
uint64_t ecs_sparse_last_id(
const ecs_sparse_t *sparse);
FLECS_API
int32_t ecs_sparse_count(
const ecs_sparse_t *sparse);
/** Override the generation count for a specific id */
FLECS_API
void flecs_sparse_set_generation(
ecs_sparse_t *sparse,
uint64_t id);
FLECS_API
void* ecs_sparse_get_dense(
const ecs_sparse_t *sparse,
ecs_size_t elem_size,
int32_t index);
#define ecs_sparse_get_dense_t(sparse, T, index)\
ECS_CAST(T*, ecs_sparse_get_dense(sparse, ECS_SIZEOF(T), index))
FLECS_API
void* ecs_sparse_get(
const ecs_sparse_t *sparse,
ecs_size_t elem_size,
uint64_t id);
#define ecs_sparse_get_t(sparse, T, index)\
ECS_CAST(T*, ecs_sparse_get(sparse, ECS_SIZEOF(T), index))
#ifdef __cplusplus
}
#endif
#endif

View File

@@ -0,0 +1,247 @@
/**
* @file strbuf.h
* @brief Utility for constructing strings.
*/
#ifndef FLECS_STRBUF_H_
#define FLECS_STRBUF_H_
#include "api_defines.h"
#ifdef __cplusplus
extern "C" {
#endif
#ifdef __cplusplus
/* Fixes missing field initializer warning on g++ */
#define ECS_STRBUF_INIT (ecs_strbuf_t){}
#else
#define ECS_STRBUF_INIT (ecs_strbuf_t){0}
#endif
#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;
/* This is set to the output string after calling ecs_strbuf_get */
char *content;
/* This is set to the output string length after calling ecs_strbuf_get */
int32_t length;
} 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 character to buffer.
* Returns false when max is reached, true when there is still space */
FLECS_API
bool ecs_strbuf_appendch(
ecs_strbuf_t *buffer,
char ch);
/* Append int to buffer.
* Returns false when max is reached, true when there is still space */
FLECS_API
bool ecs_strbuf_appendint(
ecs_strbuf_t *buffer,
int64_t v);
/* Append float to buffer.
* Returns false when max is reached, true when there is still space */
FLECS_API
bool ecs_strbuf_appendflt(
ecs_strbuf_t *buffer,
double v,
char nan_delim);
/* Append boolean to buffer.
* Returns false when max is reached, true when there is still space */
FLECS_API
bool ecs_strbuf_appendbool(
ecs_strbuf_t *buffer,
bool v);
/* 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, transfer ownership to buffer.
* Returns false when max is reached, true when there is still space */
FLECS_API
bool ecs_strbuf_appendstr_zerocpyn(
ecs_strbuf_t *buffer,
char *str,
int32_t n);
/* 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 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_zerocpyn_const(
ecs_strbuf_t *buffer,
const char *str,
int32_t n);
/* 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 */
FLECS_API
char *ecs_strbuf_get(
ecs_strbuf_t *buffer);
/* Return small string from first element (appends \0) */
FLECS_API
char *ecs_strbuf_get_small(
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 character to as new element in list. */
FLECS_API
bool ecs_strbuf_list_appendch(
ecs_strbuf_t *buffer,
char ch);
/* 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);
/* Append string as a new element in list */
FLECS_API
bool ecs_strbuf_list_appendstrn(
ecs_strbuf_t *buffer,
const char *str,
int32_t n);
FLECS_API
int32_t ecs_strbuf_written(
const ecs_strbuf_t *buffer);
#define ecs_strbuf_appendlit(buf, str)\
ecs_strbuf_appendstrn(buf, str, (int32_t)(sizeof(str) - 1))
#define ecs_strbuf_list_appendlit(buf, str)\
ecs_strbuf_list_appendstrn(buf, str, (int32_t)(sizeof(str) - 1))
#ifdef __cplusplus
}
#endif
#endif

View File

@@ -0,0 +1,129 @@
/**
* @file switch_list.h
* @brief Interleaved linked list for storing mutually exclusive values.
*/
#ifndef FLECS_SWITCH_LIST_H
#define FLECS_SWITCH_LIST_H
#include "flecs/private/api_defines.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;
struct ecs_switch_t {
ecs_map_t hdrs; /* map<uint64_t, ecs_switch_header_t> */
ecs_vec_t nodes; /* vec<ecs_switch_node_t> */
ecs_vec_t values; /* vec<uint64_t> */
};
/** Init new switch. */
FLECS_DBG_API
void flecs_switch_init(
ecs_switch_t* sw,
ecs_allocator_t *allocator,
int32_t elements);
/** Fini switch. */
FLECS_DBG_API
void flecs_switch_fini(
ecs_switch_t *sw);
/** Remove all values. */
FLECS_DBG_API
void flecs_switch_clear(
ecs_switch_t *sw);
/** Add element to switch, initialize value to 0 */
FLECS_DBG_API
void flecs_switch_add(
ecs_switch_t *sw);
/** Set number of elements in switch list */
FLECS_DBG_API
void flecs_switch_set_count(
ecs_switch_t *sw,
int32_t count);
/** Get number of elements */
FLECS_DBG_API
int32_t flecs_switch_count(
ecs_switch_t *sw);
/** Ensure that element exists. */
FLECS_DBG_API
void flecs_switch_ensure(
ecs_switch_t *sw,
int32_t count);
/** Add n elements. */
FLECS_DBG_API
void flecs_switch_addn(
ecs_switch_t *sw,
int32_t count);
/** Set value of element. */
FLECS_DBG_API
void flecs_switch_set(
ecs_switch_t *sw,
int32_t element,
uint64_t value);
/** Remove element. */
FLECS_DBG_API
void flecs_switch_remove(
ecs_switch_t *sw,
int32_t element);
/** Get value for element. */
FLECS_DBG_API
uint64_t flecs_switch_get(
const ecs_switch_t *sw,
int32_t element);
/** Swap element. */
FLECS_DBG_API
void flecs_switch_swap(
ecs_switch_t *sw,
int32_t elem_1,
int32_t elem_2);
/** Get vector with all values. Use together with count(). */
FLECS_DBG_API
ecs_vec_t* flecs_switch_values(
const ecs_switch_t *sw);
/** Return number of different values. */
FLECS_DBG_API
int32_t flecs_switch_case_count(
const ecs_switch_t *sw,
uint64_t value);
/** Return first element for value. */
FLECS_DBG_API
int32_t flecs_switch_first(
const ecs_switch_t *sw,
uint64_t value);
/** Return next element for value. Use with first(). */
FLECS_DBG_API
int32_t flecs_switch_next(
const ecs_switch_t *sw,
int32_t elem);
#ifdef __cplusplus
extern "C" {
#endif
#ifdef __cplusplus
}
#endif
#endif

View File

@@ -0,0 +1,199 @@
/**
* @file vec.h
* @brief Vector with allocator support.
*/
#ifndef FLECS_VEC_H
#define FLECS_VEC_H
#ifdef __cplusplus
extern "C" {
#endif
/** A component column. */
typedef struct ecs_vec_t {
void *array;
int32_t count;
int32_t size;
#ifdef FLECS_SANITIZE
ecs_size_t elem_size;
#endif
} ecs_vec_t;
FLECS_API
ecs_vec_t* ecs_vec_init(
struct ecs_allocator_t *allocator,
ecs_vec_t *vec,
ecs_size_t size,
int32_t elem_count);
#define ecs_vec_init_t(allocator, vec, T, elem_count) \
ecs_vec_init(allocator, vec, ECS_SIZEOF(T), elem_count)
FLECS_API
void ecs_vec_init_if(
ecs_vec_t *vec,
ecs_size_t size);
#define ecs_vec_init_if_t(vec, T) \
ecs_vec_init_if(vec, ECS_SIZEOF(T))
FLECS_API
void ecs_vec_fini(
struct ecs_allocator_t *allocator,
ecs_vec_t *vec,
ecs_size_t size);
#define ecs_vec_fini_t(allocator, vec, T) \
ecs_vec_fini(allocator, vec, ECS_SIZEOF(T))
FLECS_API
ecs_vec_t* ecs_vec_reset(
struct ecs_allocator_t *allocator,
ecs_vec_t *vec,
ecs_size_t size);
#define ecs_vec_reset_t(allocator, vec, T) \
ecs_vec_reset(allocator, vec, ECS_SIZEOF(T))
FLECS_API
void ecs_vec_clear(
ecs_vec_t *vec);
FLECS_API
void* ecs_vec_append(
struct ecs_allocator_t *allocator,
ecs_vec_t *vec,
ecs_size_t size);
#define ecs_vec_append_t(allocator, vec, T) \
ECS_CAST(T*, ecs_vec_append(allocator, vec, ECS_SIZEOF(T)))
FLECS_API
void ecs_vec_remove(
ecs_vec_t *vec,
ecs_size_t size,
int32_t elem);
#define ecs_vec_remove_t(vec, T, elem) \
ecs_vec_remove(vec, ECS_SIZEOF(T), elem)
FLECS_API
void ecs_vec_remove_last(
ecs_vec_t *vec);
FLECS_API
ecs_vec_t ecs_vec_copy(
struct ecs_allocator_t *allocator,
const ecs_vec_t *vec,
ecs_size_t size);
#define ecs_vec_copy_t(allocator, vec, T) \
ecs_vec_copy(allocator, vec, ECS_SIZEOF(T))
FLECS_API
void ecs_vec_reclaim(
struct ecs_allocator_t *allocator,
ecs_vec_t *vec,
ecs_size_t size);
#define ecs_vec_reclaim_t(allocator, vec, T) \
ecs_vec_reclaim(allocator, vec, ECS_SIZEOF(T))
FLECS_API
void ecs_vec_set_size(
struct ecs_allocator_t *allocator,
ecs_vec_t *vec,
ecs_size_t size,
int32_t elem_count);
#define ecs_vec_set_size_t(allocator, vec, T, elem_count) \
ecs_vec_set_size(allocator, vec, ECS_SIZEOF(T), elem_count)
FLECS_API
void ecs_vec_set_min_size(
struct ecs_allocator_t *allocator,
ecs_vec_t *vec,
ecs_size_t size,
int32_t elem_count);
#define ecs_vec_set_min_size_t(allocator, vec, T, elem_count) \
ecs_vec_set_min_size(allocator, vec, ECS_SIZEOF(T), elem_count)
FLECS_API
void ecs_vec_set_min_count(
struct ecs_allocator_t *allocator,
ecs_vec_t *vec,
ecs_size_t size,
int32_t elem_count);
#define ecs_vec_set_min_count_t(allocator, vec, T, elem_count) \
ecs_vec_set_min_count(allocator, vec, ECS_SIZEOF(T), elem_count)
FLECS_API
void ecs_vec_set_min_count_zeromem(
struct ecs_allocator_t *allocator,
ecs_vec_t *vec,
ecs_size_t size,
int32_t elem_count);
#define ecs_vec_set_min_count_zeromem_t(allocator, vec, T, elem_count) \
ecs_vec_set_min_count_zeromem(allocator, vec, ECS_SIZEOF(T), elem_count)
FLECS_API
void ecs_vec_set_count(
struct ecs_allocator_t *allocator,
ecs_vec_t *vec,
ecs_size_t size,
int32_t elem_count);
#define ecs_vec_set_count_t(allocator, vec, T, elem_count) \
ecs_vec_set_count(allocator, vec, ECS_SIZEOF(T), elem_count)
FLECS_API
void* ecs_vec_grow(
struct ecs_allocator_t *allocator,
ecs_vec_t *vec,
ecs_size_t size,
int32_t elem_count);
#define ecs_vec_grow_t(allocator, vec, T, elem_count) \
ecs_vec_grow(allocator, vec, ECS_SIZEOF(T), elem_count)
FLECS_API
int32_t ecs_vec_count(
const ecs_vec_t *vec);
FLECS_API
int32_t ecs_vec_size(
const ecs_vec_t *vec);
FLECS_API
void* ecs_vec_get(
const ecs_vec_t *vec,
ecs_size_t size,
int32_t index);
#define ecs_vec_get_t(vec, T, index) \
ECS_CAST(T*, ecs_vec_get(vec, ECS_SIZEOF(T), index))
FLECS_API
void* ecs_vec_first(
const ecs_vec_t *vec);
#define ecs_vec_first_t(vec, T) \
ECS_CAST(T*, ecs_vec_first(vec))
FLECS_API
void* ecs_vec_last(
const ecs_vec_t *vec,
ecs_size_t size);
#define ecs_vec_last_t(vec, T) \
ECS_CAST(T*, ecs_vec_last(vec, ECS_SIZEOF(T)))
#ifdef __cplusplus
}
#endif
#endif