Compare commits
No commits in common. "4f549290ab9c4a8161ad061e59ecadba793ba423" and "275dbdc748dc878bb21c0f9bc52ad3484f079771" have entirely different histories.
4f549290ab
...
275dbdc748
|
@ -133,9 +133,6 @@ case $1 in
|
||||||
"b" | "build-dependencies")
|
"b" | "build-dependencies")
|
||||||
build_dependencies
|
build_dependencies
|
||||||
;;
|
;;
|
||||||
"t" | "test")
|
|
||||||
./build_tests.bash
|
|
||||||
;;
|
|
||||||
"h" | "help")
|
"h" | "help")
|
||||||
echo "Known Actions:"
|
echo "Known Actions:"
|
||||||
echo "[ d | dbg | debug ]: Build in the debug profile; build with debug symbols."
|
echo "[ d | dbg | debug ]: Build in the debug profile; build with debug symbols."
|
||||||
|
|
|
@ -4,7 +4,6 @@ cd $(dirname "$(pwd)/$0")
|
||||||
REPOSITORY_FOLDER=$(pwd)
|
REPOSITORY_FOLDER=$(pwd)
|
||||||
|
|
||||||
MAIN_OBJECTS_FOLDER="$REPOSITORY_FOLDER/.build/objects/"
|
MAIN_OBJECTS_FOLDER="$REPOSITORY_FOLDER/.build/objects/"
|
||||||
CC_OPTIONS="-g3 -Wall -Wextra -Wpedantic"
|
|
||||||
DEFAULT_INCLUDE_PATHS="
|
DEFAULT_INCLUDE_PATHS="
|
||||||
-I .build/depends/libRR/Core/core/exports/
|
-I .build/depends/libRR/Core/core/exports/
|
||||||
-I .build/depends/libRR/Core/platform/exports/
|
-I .build/depends/libRR/Core/platform/exports/
|
||||||
|
@ -56,7 +55,7 @@ function compile_single_test() {
|
||||||
|
|
||||||
get_include_path_configuration $TEST_PATH
|
get_include_path_configuration $TEST_PATH
|
||||||
get_linkage_path_configuration $TEST_PATH
|
get_linkage_path_configuration $TEST_PATH
|
||||||
gcc $CC_OPTIONS -o $TEST_PATH/$TEST_NAME.elf $TEST_PATH/*.c $LINKAGE_PATHS $INCLUDE_STATEMENTS
|
gcc -g3 -o $TEST_PATH/$TEST_NAME.elf $TEST_PATH/*.c $LINKAGE_PATHS $INCLUDE_STATEMENTS
|
||||||
}
|
}
|
||||||
|
|
||||||
function compile_all_tests_of_module() {
|
function compile_all_tests_of_module() {
|
||||||
|
|
|
@ -1,5 +1,3 @@
|
||||||
tests/internal/basic-tag-registry-usage
|
tests/internal/basic-tag-registry-usage
|
||||||
tests/internal/entity-lookup
|
tests/internal/entity-lookup
|
||||||
tests/interface/entity-queries
|
tests/interface/entity-creation
|
||||||
tests/interface/entity-creation
|
|
||||||
tests/interface/entity-tagging-api
|
|
|
@ -6,15 +6,14 @@
|
||||||
#include <librr/types.h>
|
#include <librr/types.h>
|
||||||
#include <librr/linear_algebra.h>
|
#include <librr/linear_algebra.h>
|
||||||
|
|
||||||
typedef void MtEntity;
|
typedef void * MtEntity;
|
||||||
|
|
||||||
/// @brief: An MtTask is a piece of functionality with an own state/context which will be executed on the same thread or set of threads.
|
/// @brief: An MtTask is a piece of functionality with an own state/context which will be executed on the same thread or set of threads.
|
||||||
typedef void MtTask;
|
typedef void * MtTask;
|
||||||
typedef void MtState;
|
typedef void * MtState;
|
||||||
|
|
||||||
typedef void (*MtEffectorFn) (MtEntity *entity, void *userdata, usz_t invocation_id);
|
typedef void (*MtEffectorFn) (MtEntity entity, void *userdata, usz_t invocation_id);
|
||||||
typedef void (*MtTaskMainFn) (MtTask *task, void *userdata);
|
typedef void (*MtTaskMainFn) (MtTask task, void *userdata);
|
||||||
typedef bool_t (*MtQueryMatcherFn) (MtEntity *entity, void *userdata);
|
|
||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
|
@ -28,18 +27,18 @@ typedef struct
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
MtState * mt_initialize(char *app_name);
|
MtState mt_initialize(char *app_name);
|
||||||
void mt_cleanup(MtState *state);
|
void mt_cleanup(MtState state);
|
||||||
void mt_start(MtState *state);
|
void mt_start(MtState state);
|
||||||
|
|
||||||
MtEntity * mt_summon(MtState *state);
|
MtEntity mt_summon(MtState state);
|
||||||
void mt_drop(MtEntity *entity);
|
void mt_drop(MtEntity entity);
|
||||||
|
|
||||||
void mt_add_create_effector(MtState *state, char *effector_name, MtEffectorFn function, void *userdata);
|
void mt_add_create_effector(MtState state, char *effector_name, MtEffectorFn function, void *userdata);
|
||||||
void mt_add_delete_effector(MtState *state, char *effector_name, MtEffectorFn function, void *userdata);
|
void mt_add_delete_effector(MtState state, char *effector_name, MtEffectorFn function, void *userdata);
|
||||||
void mt_add_entity_effector(MtState *state, char *effector_name, usz_t ticks_delta, MtEffectorFn function, void *userdata);
|
void mt_add_entity_effector(MtState state, char *effector_name, usz_t ticks_delta, MtEffectorFn function, void *userdata);
|
||||||
void mt_add_tick_effector(MtState *state, char *effector_name, usz_t ticks_delta, MtEffectorFn function, void *userdata);
|
void mt_add_tick_effector(MtState state, char *effector_name, usz_t ticks_delta, MtEffectorFn function, void *userdata);
|
||||||
void mt_remove_effector(MtState *state, const char *effector_name);
|
void mt_remove_effector(MtState state, const char *effector_name);
|
||||||
|
|
||||||
/// @brief Adds a tick effector which only acts upon entitys with certain tags.
|
/// @brief Adds a tick effector which only acts upon entitys with certain tags.
|
||||||
/// @param state The state in which the tick effector should reside.
|
/// @param state The state in which the tick effector should reside.
|
||||||
|
@ -47,32 +46,29 @@ void mt_remove_effector(MtState *state, const char *effector_name);
|
||||||
/// @param ticks_delta The wanted number of ticks between two invocations of the effector.
|
/// @param ticks_delta The wanted number of ticks between two invocations of the effector.
|
||||||
/// @param function The function to call for an entity if it contains all necessary tags.
|
/// @param function The function to call for an entity if it contains all necessary tags.
|
||||||
/// @param tag_names A nullpointer-terminated list of tag-ids that must be present in an entity for that entity to be effected.
|
/// @param tag_names A nullpointer-terminated list of tag-ids that must be present in an entity for that entity to be effected.
|
||||||
void mt_add_tagged_tick_effector(MtState *state, char *effector_name, usz_t ticks_delta, MtEffectorFn function, char **tag_names);
|
void mt_add_tagged_tick_effector(MtState state, char *effector_name, usz_t ticks_delta, MtEffectorFn function, char **tag_names);
|
||||||
|
|
||||||
usz_t mt_query(MtState *state, const char **tags, MtEntity **entities, usz_t count);
|
void mt_tag_i64(MtEntity entity, char *name, i64_t integer);
|
||||||
usz_t mt_match_query(MtState *state, const char **tags, MtEntity **entities, usz_t count, MtQueryMatcherFn matcher, void *userdata);
|
void mt_tag_f64(MtEntity entity, char *name, f64_t real);
|
||||||
|
void mt_tag_str(MtEntity entity, char *name, char *string);
|
||||||
|
void mt_tag_ptr(MtEntity entity, char *name, void *pointer);
|
||||||
|
void mt_tag_vec2(MtEntity entity, char *name, rr_vec2f_s vector);
|
||||||
|
void mt_tag_vec3(MtEntity entity, char *name, rr_vec3f_s vector);
|
||||||
|
void mt_tag_vec4(MtEntity entity, char *name, rr_vec4f_s vector);
|
||||||
|
|
||||||
void mt_tag_i64(MtEntity *entity, char *name, i64_t integer);
|
void mt_untag(MtEntity entity, char *name);
|
||||||
void mt_tag_f64(MtEntity *entity, char *name, f64_t real);
|
|
||||||
void mt_tag_str(MtEntity *entity, char *name, char *string);
|
|
||||||
void mt_tag_ptr(MtEntity *entity, char *name, void *pointer);
|
|
||||||
void mt_tag_vec2(MtEntity *entity, char *name, rr_vec2f_s vector);
|
|
||||||
void mt_tag_vec3(MtEntity *entity, char *name, rr_vec3f_s vector);
|
|
||||||
void mt_tag_vec4(MtEntity *entity, char *name, rr_vec4f_s vector);
|
|
||||||
|
|
||||||
void mt_untag(MtEntity *entity, char *name);
|
i64_t mt_get_i64_tag(MtEntity entity, char *name);
|
||||||
|
f64_t mt_get_f64_tag(MtEntity entity, char *name);
|
||||||
|
char * mt_get_str_tag(MtEntity entity, char *name);
|
||||||
|
void * mt_get_ptr_tag(MtEntity entity, char *name);
|
||||||
|
rr_vec2f_s mt_get_vec2_tag(MtEntity entity, char *name);
|
||||||
|
rr_vec3f_s mt_get_vec3_tag(MtEntity entity, char *name);
|
||||||
|
rr_vec4f_s mt_get_vec4_tag(MtEntity entity, char *name);
|
||||||
|
|
||||||
i64_t mt_get_i64_tag(MtEntity *entity, char *name);
|
MtTask mt_create_task(MtState state, MtTaskCreationInfo creation_info);
|
||||||
f64_t mt_get_f64_tag(MtEntity *entity, char *name);
|
void mt_delete_task(MtTask task);
|
||||||
char * mt_get_str_tag(MtEntity *entity, char *name);
|
|
||||||
void * mt_get_ptr_tag(MtEntity *entity, char *name);
|
|
||||||
rr_vec2f_s mt_get_vec2_tag(MtEntity *entity, char *name);
|
|
||||||
rr_vec3f_s mt_get_vec3_tag(MtEntity *entity, char *name);
|
|
||||||
rr_vec4f_s mt_get_vec4_tag(MtEntity *entity, char *name);
|
|
||||||
|
|
||||||
MtTask mt_create_task(MtState *state, MtTaskCreationInfo creation_info);
|
void mt_task_remove_effector(MtTask task, const char *effector_name);
|
||||||
void mt_delete_task(MtTask *task);
|
|
||||||
|
|
||||||
void mt_task_remove_effector(MtTask *task, const char *effector_name);
|
|
||||||
|
|
||||||
#endif // MAINTREE_H
|
#endif // MAINTREE_H
|
||||||
|
|
|
@ -89,7 +89,6 @@ void mt_tag_vec2(MtEntity *entity, char *name, rr_vec2f_s vector);
|
||||||
void mt_tag_vec3(MtEntity *entity, char *name, rr_vec3f_s vector);
|
void mt_tag_vec3(MtEntity *entity, char *name, rr_vec3f_s vector);
|
||||||
void mt_tag_vec4(MtEntity *entity, char *name, rr_vec4f_s vector);
|
void mt_tag_vec4(MtEntity *entity, char *name, rr_vec4f_s vector);
|
||||||
|
|
||||||
bool_t mt_has_tag(MtEntity *entity, const char *name);
|
|
||||||
void mt_untag(MtEntity *entity, char *name);
|
void mt_untag(MtEntity *entity, char *name);
|
||||||
|
|
||||||
i64_t mt_get_i64_tag(MtEntity *entity, char *name);
|
i64_t mt_get_i64_tag(MtEntity *entity, char *name);
|
||||||
|
|
|
@ -9,7 +9,6 @@
|
||||||
#include <librr/alloc/generic.h>
|
#include <librr/alloc/generic.h>
|
||||||
|
|
||||||
typedef struct MtState MtState;
|
typedef struct MtState MtState;
|
||||||
typedef bool_t (*MtQueryMatcherFn) (MtEntity *entity, void *userdata);
|
|
||||||
|
|
||||||
struct MtState
|
struct MtState
|
||||||
{
|
{
|
||||||
|
@ -26,7 +25,4 @@ void mt_start(MtState *state);
|
||||||
MtEntity * mt_summon(MtState *state);
|
MtEntity * mt_summon(MtState *state);
|
||||||
void mt_drop(MtEntity *entity);
|
void mt_drop(MtEntity *entity);
|
||||||
|
|
||||||
usz_t mt_query(MtState *state, const char **tags, MtEntity **entities, usz_t count);
|
|
||||||
usz_t mt_match_query(MtState *state, const char **tags, MtEntity **entities, usz_t count, MtQueryMatcherFn matcher, void *userdata);
|
|
||||||
|
|
||||||
#endif // MT_STATE_H
|
#endif // MT_STATE_H
|
||||||
|
|
|
@ -30,11 +30,6 @@ struct MtTagEntry
|
||||||
{
|
{
|
||||||
u32_t identifier;
|
u32_t identifier;
|
||||||
char *label;
|
char *label;
|
||||||
|
|
||||||
usz_t entities_capacity;
|
|
||||||
usz_t num_entities;
|
|
||||||
/// @brief An array ofhe identifiers of all entities which have a tag of this type.
|
|
||||||
u32_t *entity_identifiers;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct MtTagCollection
|
struct MtTagCollection
|
||||||
|
@ -42,7 +37,7 @@ struct MtTagCollection
|
||||||
u32_t capacity;
|
u32_t capacity;
|
||||||
u32_t usage;
|
u32_t usage;
|
||||||
|
|
||||||
/// @brief An array of indices into the tag-registry's 'entries'-array.
|
/// @brief An array of indices for the tag-registry's 'entries'-array.
|
||||||
u32_t *tag_indices;
|
u32_t *tag_indices;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -51,9 +46,5 @@ void mt_delete_tag_registry(MtTagRegistry registry);
|
||||||
|
|
||||||
u32_t mt_get_tag_id(MtTagRegistry *registry, const char *tag_label);
|
u32_t mt_get_tag_id(MtTagRegistry *registry, const char *tag_label);
|
||||||
const char * mt_get_tag_label(MtTagRegistry *registry, u32_t tag_identifier);
|
const char * mt_get_tag_label(MtTagRegistry *registry, u32_t tag_identifier);
|
||||||
MtTagEntry * mt_get_tag_entry(MtTagRegistry *registry, const char *tag_label);
|
|
||||||
|
|
||||||
void mt_add_entity_to_tag_lookup_list(MtTagRegistry *registry, const char *tag_label, u32_t entity_identifier);
|
|
||||||
void mt_remove_entity_from_tag_lookup_list(MtTagRegistry *registry, const char *tag_label, u32_t entity_identifier);
|
|
||||||
|
|
||||||
#endif // MT_TAG_REGISTRY_H
|
#endif // MT_TAG_REGISTRY_H
|
||||||
|
|
|
@ -89,7 +89,6 @@ void mt_delete_entity_data(MtEntity *entity)
|
||||||
{
|
{
|
||||||
if(entity->tags != NULL)
|
if(entity->tags != NULL)
|
||||||
free(entity->tags);
|
free(entity->tags);
|
||||||
entity->tags = NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -20,8 +20,6 @@ i16_t mt_get_entity_tag_slot_index(MtEntity *entity, const char *name)
|
||||||
|
|
||||||
MtTag * mt_get_entity_tag_slot(MtEntity *entity, char *name)
|
MtTag * mt_get_entity_tag_slot(MtEntity *entity, char *name)
|
||||||
{
|
{
|
||||||
MtState *state = entity->parent_state;
|
|
||||||
|
|
||||||
i16_t tag_slot_index = mt_get_entity_tag_slot_index(entity, name);
|
i16_t tag_slot_index = mt_get_entity_tag_slot_index(entity, name);
|
||||||
if(tag_slot_index >= 0)
|
if(tag_slot_index >= 0)
|
||||||
return &entity->tags[tag_slot_index];
|
return &entity->tags[tag_slot_index];
|
||||||
|
@ -36,87 +34,51 @@ MtTag * mt_get_entity_tag_slot(MtEntity *entity, char *name)
|
||||||
|
|
||||||
entity->tags = realloc(entity->tags, sizeof(struct MtTag) * entity->tags_capacity);
|
entity->tags = realloc(entity->tags, sizeof(struct MtTag) * entity->tags_capacity);
|
||||||
}
|
}
|
||||||
entity->tags[entity->num_tags].identifier = mt_get_tag_id(&state->tag_registry, name);
|
|
||||||
return &entity->tags[entity->num_tags++];
|
return &entity->tags[entity->num_tags++];
|
||||||
}
|
}
|
||||||
|
|
||||||
void mt_tag_i64(MtEntity *entity, char *name, i64_t integer)
|
void mt_tag_i64(MtEntity *entity, char *name, i64_t integer)
|
||||||
{
|
{
|
||||||
MtState *state = entity->parent_state;
|
|
||||||
MtTag *tag = mt_get_entity_tag_slot(entity, name);
|
MtTag *tag = mt_get_entity_tag_slot(entity, name);
|
||||||
|
|
||||||
mt_add_entity_to_tag_lookup_list(&state->tag_registry, name, entity->identifier);
|
|
||||||
tag->data.integer = integer;
|
tag->data.integer = integer;
|
||||||
}
|
}
|
||||||
|
|
||||||
void mt_tag_f64(MtEntity *entity, char *name, f64_t real)
|
void mt_tag_f64(MtEntity *entity, char *name, f64_t real)
|
||||||
{
|
{
|
||||||
MtState *state = entity->parent_state;
|
|
||||||
MtTag *tag = mt_get_entity_tag_slot(entity, name);
|
MtTag *tag = mt_get_entity_tag_slot(entity, name);
|
||||||
|
|
||||||
mt_add_entity_to_tag_lookup_list(&state->tag_registry, name, entity->identifier);
|
|
||||||
tag->data.real = real;
|
tag->data.real = real;
|
||||||
}
|
}
|
||||||
|
|
||||||
void mt_tag_str(MtEntity *entity, char *name, char *string)
|
void mt_tag_str(MtEntity *entity, char *name, char *string)
|
||||||
{
|
{
|
||||||
MtState *state = entity->parent_state;
|
|
||||||
MtTag *tag = mt_get_entity_tag_slot(entity, name);
|
MtTag *tag = mt_get_entity_tag_slot(entity, name);
|
||||||
|
|
||||||
mt_add_entity_to_tag_lookup_list(&state->tag_registry, name, entity->identifier);
|
|
||||||
tag->data.string = string;
|
tag->data.string = string;
|
||||||
}
|
}
|
||||||
|
|
||||||
void mt_tag_ptr(MtEntity *entity, char *name, void *pointer)
|
void mt_tag_ptr(MtEntity *entity, char *name, void *pointer)
|
||||||
{
|
{
|
||||||
MtState *state = entity->parent_state;
|
|
||||||
MtTag *tag = mt_get_entity_tag_slot(entity, name);
|
MtTag *tag = mt_get_entity_tag_slot(entity, name);
|
||||||
|
|
||||||
mt_add_entity_to_tag_lookup_list(&state->tag_registry, name, entity->identifier);
|
|
||||||
tag->data.pointer = pointer;
|
tag->data.pointer = pointer;
|
||||||
}
|
}
|
||||||
|
|
||||||
void mt_tag_vec2(MtEntity *entity, char *name, rr_vec2f_s vector)
|
void mt_tag_vec2(MtEntity *entity, char *name, rr_vec2f_s vector)
|
||||||
{
|
{
|
||||||
MtState *state = entity->parent_state;
|
|
||||||
MtTag *tag = mt_get_entity_tag_slot(entity, name);
|
MtTag *tag = mt_get_entity_tag_slot(entity, name);
|
||||||
|
|
||||||
mt_add_entity_to_tag_lookup_list(&state->tag_registry, name, entity->identifier);
|
|
||||||
tag->data.vec2f = vector;
|
tag->data.vec2f = vector;
|
||||||
}
|
}
|
||||||
|
|
||||||
void mt_tag_vec3(MtEntity *entity, char *name, rr_vec3f_s vector)
|
void mt_tag_vec3(MtEntity *entity, char *name, rr_vec3f_s vector)
|
||||||
{
|
{
|
||||||
MtState *state = entity->parent_state;
|
|
||||||
MtTag *tag = mt_get_entity_tag_slot(entity, name);
|
MtTag *tag = mt_get_entity_tag_slot(entity, name);
|
||||||
|
|
||||||
mt_add_entity_to_tag_lookup_list(&state->tag_registry, name, entity->identifier);
|
|
||||||
tag->data.vec3f = vector;
|
tag->data.vec3f = vector;
|
||||||
}
|
}
|
||||||
void mt_tag_vec4(MtEntity *entity, char *name, rr_vec4f_s vector)
|
void mt_tag_vec4(MtEntity *entity, char *name, rr_vec4f_s vector)
|
||||||
{
|
{
|
||||||
MtState *state = entity->parent_state;
|
|
||||||
MtTag *tag = mt_get_entity_tag_slot(entity, name);
|
MtTag *tag = mt_get_entity_tag_slot(entity, name);
|
||||||
|
|
||||||
mt_add_entity_to_tag_lookup_list(&state->tag_registry, name, entity->identifier);
|
|
||||||
tag->data.vec4f = vector;
|
tag->data.vec4f = vector;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool_t mt_has_tag(MtEntity *entity, const char *name)
|
|
||||||
{
|
|
||||||
MtState *state = entity->parent_state;
|
|
||||||
usz_t tag_id = mt_get_tag_id(&state->tag_registry, name);
|
|
||||||
|
|
||||||
usz_t tag_index = 0;
|
|
||||||
while(tag_index < entity->num_tags)
|
|
||||||
{
|
|
||||||
if(entity->tags[tag_index].identifier == tag_id)
|
|
||||||
return TRUE;
|
|
||||||
|
|
||||||
++tag_index;
|
|
||||||
}
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
void mt_untag(MtEntity *entity, char *name)
|
void mt_untag(MtEntity *entity, char *name)
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,107 +0,0 @@
|
||||||
#include <state.h>
|
|
||||||
#include <entity.h>
|
|
||||||
|
|
||||||
usz_t mt_find_tag_with_least_entries(MtState *state, const char **tags)
|
|
||||||
{
|
|
||||||
u32_t least_entries_count = 0xffffffff;
|
|
||||||
usz_t least_entries_index = 0;
|
|
||||||
|
|
||||||
usz_t tag_index = 0;
|
|
||||||
while(tags[tag_index] != NULL)
|
|
||||||
{
|
|
||||||
MtTagEntry *tag_entry = mt_get_tag_entry(&state->tag_registry, tags[tag_index]);
|
|
||||||
if(tag_entry->num_entities > least_entries_count)
|
|
||||||
{
|
|
||||||
least_entries_count = tag_entry->num_entities;
|
|
||||||
least_entries_index = tag_index;
|
|
||||||
}
|
|
||||||
++tag_index;
|
|
||||||
}
|
|
||||||
return least_entries_index;
|
|
||||||
}
|
|
||||||
|
|
||||||
usz_t mt_count_entities_with_matching_tags(MtState *state, const char **tags)
|
|
||||||
{
|
|
||||||
usz_t num_matching_entities = 0;
|
|
||||||
|
|
||||||
const char *least_used_tag = tags[mt_find_tag_with_least_entries(state, tags)];
|
|
||||||
MtTagEntry *tag_entry = mt_get_tag_entry(&state->tag_registry, least_used_tag);
|
|
||||||
usz_t entity_index = 0;
|
|
||||||
while(entity_index < tag_entry->num_entities)
|
|
||||||
{
|
|
||||||
MtEntity *entity = mt_get_entity(state, tag_entry->entity_identifiers[entity_index]);
|
|
||||||
bool_t matching = TRUE;
|
|
||||||
usz_t wanted_tag_index = 0;
|
|
||||||
while(tags[wanted_tag_index] != NULL)
|
|
||||||
{
|
|
||||||
if(!mt_has_tag(entity, tags[wanted_tag_index]))
|
|
||||||
{
|
|
||||||
matching = FALSE;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
++wanted_tag_index;
|
|
||||||
}
|
|
||||||
if(matching)
|
|
||||||
++num_matching_entities;
|
|
||||||
|
|
||||||
++entity_index;
|
|
||||||
}
|
|
||||||
return num_matching_entities;
|
|
||||||
}
|
|
||||||
|
|
||||||
usz_t mt_query(MtState *state, const char **tags, MtEntity **entities, usz_t count)
|
|
||||||
{
|
|
||||||
if(count == 0)
|
|
||||||
return mt_count_entities_with_matching_tags(state, tags);;
|
|
||||||
|
|
||||||
usz_t num_written_entities = 0;
|
|
||||||
const char *least_used_tag = tags[mt_find_tag_with_least_entries(state, tags)];
|
|
||||||
MtTagEntry *tag_entry = mt_get_tag_entry(&state->tag_registry, least_used_tag);
|
|
||||||
usz_t entity_index = 0;
|
|
||||||
while((entity_index < tag_entry->num_entities) && (num_written_entities < count))
|
|
||||||
{
|
|
||||||
MtEntity *entity = mt_get_entity(state, tag_entry->entity_identifiers[entity_index]);
|
|
||||||
bool_t matching = TRUE;
|
|
||||||
usz_t wanted_tag_index = 0;
|
|
||||||
while(tags[wanted_tag_index] != NULL)
|
|
||||||
{
|
|
||||||
if(!mt_has_tag(entity, tags[wanted_tag_index]))
|
|
||||||
{
|
|
||||||
matching = FALSE;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
++wanted_tag_index;
|
|
||||||
}
|
|
||||||
if(matching)
|
|
||||||
{
|
|
||||||
entities[num_written_entities] = entity;
|
|
||||||
++num_written_entities;
|
|
||||||
}
|
|
||||||
++entity_index;
|
|
||||||
}
|
|
||||||
return num_written_entities;
|
|
||||||
}
|
|
||||||
|
|
||||||
usz_t mt_match_query(MtState *state, const char **tags, MtEntity **entities, usz_t count, MtQueryMatcherFn matcher, void *userdata)
|
|
||||||
{
|
|
||||||
usz_t num_matching_entities = mt_query(state, tags, entities, 0);
|
|
||||||
if(count == 0)
|
|
||||||
return num_matching_entities;
|
|
||||||
|
|
||||||
// TODO: If 'num_matching_entities" is too big, this must be allocated on the heap!
|
|
||||||
MtEntity *generally_matching_entities[num_matching_entities];
|
|
||||||
mt_query(state, tags, &generally_matching_entities[0], num_matching_entities);
|
|
||||||
|
|
||||||
usz_t written_entities = 0;
|
|
||||||
usz_t entity_index = 0;
|
|
||||||
while((entity_index < num_matching_entities) && (written_entities < count))
|
|
||||||
{
|
|
||||||
if(matcher(generally_matching_entities[entity_index], userdata))
|
|
||||||
{
|
|
||||||
entities[written_entities] = generally_matching_entities[entity_index];
|
|
||||||
++written_entities;
|
|
||||||
}
|
|
||||||
++entity_index;
|
|
||||||
}
|
|
||||||
return written_entities;
|
|
||||||
}
|
|
|
@ -5,10 +5,6 @@
|
||||||
|
|
||||||
MtState * mt_initialize(char *app_name)
|
MtState * mt_initialize(char *app_name)
|
||||||
{
|
{
|
||||||
if(app_name == NULL)
|
|
||||||
{
|
|
||||||
app_name = "Unnamed Application";
|
|
||||||
}
|
|
||||||
usz_t len_app_name = rr_measure_string(app_name);
|
usz_t len_app_name = rr_measure_string(app_name);
|
||||||
MtState *state = malloc(sizeof(struct MtState));
|
MtState *state = malloc(sizeof(struct MtState));
|
||||||
|
|
||||||
|
|
|
@ -3,8 +3,6 @@
|
||||||
#include <librr/memory.h>
|
#include <librr/memory.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|
||||||
#define MT_INITIAL_ENTITIES_CAPACITY_PER_TAG 32
|
|
||||||
|
|
||||||
MtTagRegistry mt_create_tag_registry(void *parent_state)
|
MtTagRegistry mt_create_tag_registry(void *parent_state)
|
||||||
{
|
{
|
||||||
MtTagRegistry registry;
|
MtTagRegistry registry;
|
||||||
|
@ -84,30 +82,9 @@ u32_t mt_tag_label_to_hash(const char *tag_label, usz_t range)
|
||||||
|
|
||||||
MtTagEntry * mt_create_tag_hash_entry(MtTagRegistry *registry, const char *tag_label)
|
MtTagEntry * mt_create_tag_hash_entry(MtTagRegistry *registry, const char *tag_label)
|
||||||
{
|
{
|
||||||
// Create a new entry in the flat array of entries
|
|
||||||
|
|
||||||
usz_t entry_index = registry->num_entries;
|
|
||||||
MtTagEntry *entry = ®istry->entries[entry_index];
|
|
||||||
++registry->num_entries;
|
|
||||||
|
|
||||||
usz_t len_tag_label = rr_measure_string(tag_label);
|
|
||||||
|
|
||||||
// TODO: There MUST be an arena allocator for this!
|
|
||||||
entry->label = malloc(len_tag_label + 1);
|
|
||||||
rr_memcopy(entry->label, tag_label, len_tag_label+1);
|
|
||||||
entry->entities_capacity = MT_INITIAL_ENTITIES_CAPACITY_PER_TAG;
|
|
||||||
entry->entity_identifiers = calloc(sizeof(u32_t), entry->entities_capacity);
|
|
||||||
entry->num_entities = 0;
|
|
||||||
entry->identifier = registry->next_identifier;
|
|
||||||
++registry->next_identifier;
|
|
||||||
|
|
||||||
// Create an entry in the lookup structure
|
|
||||||
|
|
||||||
u32_t collection_index = mt_tag_label_to_hash(tag_label, registry->num_collections);
|
u32_t collection_index = mt_tag_label_to_hash(tag_label, registry->num_collections);
|
||||||
MtTagCollection *collection = ®istry->collections[collection_index];
|
MtTagCollection *collection = ®istry->collections[collection_index];
|
||||||
|
|
||||||
// Resize the collection to be larger if needed
|
|
||||||
|
|
||||||
if(collection->usage >= collection->capacity)
|
if(collection->usage >= collection->capacity)
|
||||||
{
|
{
|
||||||
collection->capacity *= 2;
|
collection->capacity *= 2;
|
||||||
|
@ -117,14 +94,23 @@ MtTagEntry * mt_create_tag_hash_entry(MtTagRegistry *registry, const char *tag_l
|
||||||
collection->tag_indices = realloc(collection->tag_indices, sizeof(u32_t) * collection->capacity);
|
collection->tag_indices = realloc(collection->tag_indices, sizeof(u32_t) * collection->capacity);
|
||||||
rr_memset(&collection->tag_indices[collection->usage], collection->capacity - collection->usage, 0x00);
|
rr_memset(&collection->tag_indices[collection->usage], collection->capacity - collection->usage, 0x00);
|
||||||
}
|
}
|
||||||
|
MtTagEntry *entry = ®istry->entries[collection->tag_indices[collection->usage]];
|
||||||
collection->tag_indices[collection->usage] = entry_index;
|
++registry->num_entries;
|
||||||
++collection->usage;
|
++collection->usage;
|
||||||
|
|
||||||
|
usz_t len_tag_label = rr_measure_string(tag_label);
|
||||||
|
|
||||||
|
// TODO: There must be an arena allocator for this!
|
||||||
|
entry->label = malloc(len_tag_label + 1);
|
||||||
|
rr_memcopy(entry->label, tag_label, len_tag_label+1);
|
||||||
|
|
||||||
|
entry->identifier = registry->next_identifier;
|
||||||
|
++registry->next_identifier;
|
||||||
|
|
||||||
return entry;
|
return entry;
|
||||||
}
|
}
|
||||||
|
|
||||||
MtTagEntry * mt_get_tag_entry(MtTagRegistry *registry, const char *tag_label)
|
u32_t mt_get_tag_id(MtTagRegistry *registry, const char *tag_label)
|
||||||
{
|
{
|
||||||
u32_t collection_index = mt_tag_label_to_hash(tag_label, registry->num_collections);
|
u32_t collection_index = mt_tag_label_to_hash(tag_label, registry->num_collections);
|
||||||
MtTagCollection collection = registry->collections[collection_index];
|
MtTagCollection collection = registry->collections[collection_index];
|
||||||
|
@ -133,16 +119,12 @@ MtTagEntry * mt_get_tag_entry(MtTagRegistry *registry, const char *tag_label)
|
||||||
{
|
{
|
||||||
MtTagEntry *entry = ®istry->entries[collection.tag_indices[entry_index]];
|
MtTagEntry *entry = ®istry->entries[collection.tag_indices[entry_index]];
|
||||||
if(rr_strings_equal(entry->label, tag_label))
|
if(rr_strings_equal(entry->label, tag_label))
|
||||||
return entry;
|
return entry->identifier;
|
||||||
|
|
||||||
++entry_index;
|
++entry_index;
|
||||||
}
|
}
|
||||||
return mt_create_tag_hash_entry(registry, tag_label);
|
MtTagEntry *entry = mt_create_tag_hash_entry(registry, tag_label);
|
||||||
}
|
return entry->identifier;
|
||||||
|
|
||||||
u32_t mt_get_tag_id(MtTagRegistry *registry, const char *tag_label)
|
|
||||||
{
|
|
||||||
return mt_get_tag_entry(registry, tag_label)->identifier;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const char * mt_get_tag_label(MtTagRegistry *registry, u32_t tag_identifier)
|
const char * mt_get_tag_label(MtTagRegistry *registry, u32_t tag_identifier)
|
||||||
|
@ -158,47 +140,3 @@ const char * mt_get_tag_label(MtTagRegistry *registry, u32_t tag_identifier)
|
||||||
}
|
}
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
u32_t mt_get_or_create_entity_id_slot_in_tag_entry(MtTagEntry *entry, u32_t entity_identifier)
|
|
||||||
{
|
|
||||||
// Option 1: Find the entity identifier (if it was already registered)
|
|
||||||
|
|
||||||
usz_t index = 0;
|
|
||||||
while(index < entry->num_entities)
|
|
||||||
{
|
|
||||||
if(entry->entity_identifiers[index] == entity_identifier)
|
|
||||||
return index;
|
|
||||||
|
|
||||||
++index;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Option 2: Get a slot for the entity identifier and write the ID.
|
|
||||||
|
|
||||||
// Resize the entity_identifiers array if needed
|
|
||||||
|
|
||||||
if(entry->num_entities >= entry->entities_capacity)
|
|
||||||
{
|
|
||||||
entry->entities_capacity *= 2;
|
|
||||||
if(entry->entities_capacity == 0)
|
|
||||||
entry->entities_capacity = MT_INITIAL_ENTITIES_CAPACITY_PER_TAG;
|
|
||||||
entry->entity_identifiers = realloc(entry->entity_identifiers, sizeof(u32_t) * entry->entities_capacity);
|
|
||||||
}
|
|
||||||
usz_t entity_identifier_index = entry->num_entities;
|
|
||||||
entry->entity_identifiers[entity_identifier_index] = entity_identifier;
|
|
||||||
++entry->num_entities;
|
|
||||||
return entity_identifier_index;
|
|
||||||
}
|
|
||||||
|
|
||||||
void mt_add_entity_to_tag_lookup_list(MtTagRegistry *registry, const char *tag_label, u32_t entity_identifier)
|
|
||||||
{
|
|
||||||
MtTagEntry *entry = mt_get_tag_entry(registry, tag_label);
|
|
||||||
mt_get_or_create_entity_id_slot_in_tag_entry(entry, entity_identifier);
|
|
||||||
}
|
|
||||||
|
|
||||||
void mt_remove_entity_from_tag_lookup_list(MtTagRegistry *registry, const char *tag_label, u32_t entity_identifier)
|
|
||||||
{
|
|
||||||
MtTagEntry *entry = mt_get_tag_entry(registry, tag_label);
|
|
||||||
u32_t entity_index = mt_get_or_create_entity_id_slot_in_tag_entry(entry, entity_identifier);
|
|
||||||
entry->entity_identifiers[entity_index] = entry->entity_identifiers[entry->num_entities-1];
|
|
||||||
--entry->num_entities;
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,13 +1,9 @@
|
||||||
#include <maintree/maintree.h>
|
#include <maintree/maintree.h>
|
||||||
#include <stdio.h>
|
|
||||||
|
|
||||||
int main()
|
int main(int argc, char **argv)
|
||||||
{
|
{
|
||||||
MtState *state = mt_initialize("Interface Test");;
|
MtState state = mt_initialize("Interface Test");;
|
||||||
MtEntity* entity = mt_summon(state);
|
MtEntity entity = mt_summon(state);
|
||||||
mt_drop(entity);
|
mt_drop(entity);
|
||||||
mt_cleanup(state);
|
mt_cleanup(state);
|
||||||
puts("The program reached the end; this test is considered as passed. SUCCESS!");
|
|
||||||
puts("Note: A memory leak check utility should be used to verify the success.");
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,49 +0,0 @@
|
||||||
#include <state.h>
|
|
||||||
#include <entity.h>
|
|
||||||
|
|
||||||
#include <stdio.h>
|
|
||||||
|
|
||||||
int main()
|
|
||||||
{
|
|
||||||
MtState *state = mt_initialize("Interface Test");
|
|
||||||
MtEntity *entity_1 = mt_summon(state);
|
|
||||||
mt_tag_i64(entity_1, "some_tag", 3);
|
|
||||||
mt_tag_i64(entity_1, "another_tag", 42);
|
|
||||||
mt_tag_i64(entity_1, "listed_tag", 1337);
|
|
||||||
|
|
||||||
MtEntity *entity_2 = mt_summon(state);
|
|
||||||
mt_tag_i64(entity_2, "some_tag", 3);
|
|
||||||
mt_tag_i64(entity_2, "another_tag", 42);
|
|
||||||
|
|
||||||
MtEntity *entity_3 = mt_summon(state);
|
|
||||||
mt_tag_i64(entity_3, "some_tag", 3);
|
|
||||||
mt_tag_i64(entity_3, "another_tag", 42);
|
|
||||||
mt_tag_i64(entity_3, "listed_tag", 236512);
|
|
||||||
|
|
||||||
const char *tag_list[4] =
|
|
||||||
{
|
|
||||||
"some_tag",
|
|
||||||
"another_tag",
|
|
||||||
"listed_tag",
|
|
||||||
NULL
|
|
||||||
};
|
|
||||||
usz_t num_matching_entities = mt_query(state, tag_list, NULL, 0);
|
|
||||||
printf("Number of matching entities: %ld\n", num_matching_entities);
|
|
||||||
|
|
||||||
MtEntity *entities[8];
|
|
||||||
mt_query(state, tag_list, entities, 8);
|
|
||||||
|
|
||||||
printf("Entity 1: %p\nEntity 2: %p\nEntity 3: %p\n", (void *) entity_1, (void *) entity_2, (void *) entity_3);
|
|
||||||
usz_t entity_index = 0;
|
|
||||||
while(entity_index < num_matching_entities)
|
|
||||||
{
|
|
||||||
printf("Entity-Pointer: %p\n", (void *) entities[entity_index]);
|
|
||||||
++entity_index;
|
|
||||||
}
|
|
||||||
|
|
||||||
mt_drop(entity_1);
|
|
||||||
mt_drop(entity_2);
|
|
||||||
mt_drop(entity_3);
|
|
||||||
mt_cleanup(state);
|
|
||||||
return 0;
|
|
||||||
}
|
|
|
@ -1,26 +0,0 @@
|
||||||
#include <maintree/maintree.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
|
|
||||||
#define TEST_INTEGER 1337
|
|
||||||
|
|
||||||
int main()
|
|
||||||
{
|
|
||||||
MtState *state = mt_initialize("Interface Test");
|
|
||||||
MtEntity* entity = mt_summon(state);
|
|
||||||
mt_tag_i64(entity, "test-tag", TEST_INTEGER);
|
|
||||||
i64_t returned_integer = mt_get_i64_tag(entity, "test-tag");
|
|
||||||
if(returned_integer != TEST_INTEGER)
|
|
||||||
{
|
|
||||||
puts("The integer returned from the get_i64_tag-function doesn't match the tag which was put in!");
|
|
||||||
printf("Input: %d\nOutput: %ld\n", TEST_INTEGER, returned_integer);
|
|
||||||
mt_drop(entity);
|
|
||||||
mt_cleanup(state);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
mt_drop(entity);
|
|
||||||
mt_cleanup(state);
|
|
||||||
puts("The program reached the end; this test is considered as passed. SUCCESS!");
|
|
||||||
puts("Note: A memory leak check utility should be used to verify the success.");
|
|
||||||
return 0;
|
|
||||||
}
|
|
|
@ -2,43 +2,14 @@
|
||||||
#include <librr/types.h>
|
#include <librr/types.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|
||||||
int main()
|
int main(int argc, char **argv)
|
||||||
{
|
{
|
||||||
MtTagRegistry tag_registry = mt_create_tag_registry(NULL);
|
MtTagRegistry tag_registry = mt_create_tag_registry(NULL);
|
||||||
u32_t some_tag = mt_get_tag_id(&tag_registry, "some_tag");
|
u32_t some_tag = mt_get_tag_id(&tag_registry, "some_tag");
|
||||||
u32_t another_tag = mt_get_tag_id(&tag_registry, "another_tag");
|
|
||||||
u32_t theres_more = mt_get_tag_id(&tag_registry, "there's more");
|
|
||||||
if(some_tag != mt_get_tag_id(&tag_registry, "some_tag"))
|
if(some_tag != mt_get_tag_id(&tag_registry, "some_tag"))
|
||||||
{
|
{
|
||||||
puts("Inconsistently returned tag identifier in test subject 1. ERROR!");
|
puts("Inconsistent returned tag identifiers.");
|
||||||
mt_delete_tag_registry(tag_registry);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
if(another_tag != mt_get_tag_id(&tag_registry, "another_tag"))
|
|
||||||
{
|
|
||||||
puts("Inconsistently returned tag identifier in test subject 2. ERROR!");
|
|
||||||
mt_delete_tag_registry(tag_registry);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
if(theres_more != mt_get_tag_id(&tag_registry, "there's more"))
|
|
||||||
{
|
|
||||||
puts("Inconsistently returned tag identifier in test subject 3. ERROR!");
|
|
||||||
mt_delete_tag_registry(tag_registry);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
if(some_tag == theres_more)
|
|
||||||
{
|
|
||||||
puts("Tags are being duplicated in test subject 4. ERROR!");
|
|
||||||
mt_delete_tag_registry(tag_registry);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
if(some_tag == another_tag)
|
|
||||||
{
|
|
||||||
puts("Tags are being duplicated in test subject 5. ERROR!");
|
|
||||||
mt_delete_tag_registry(tag_registry);
|
|
||||||
return -1;
|
|
||||||
}
|
}
|
||||||
mt_delete_tag_registry(tag_registry);
|
mt_delete_tag_registry(tag_registry);
|
||||||
puts("The identifier which is returned for a tag name is consistent. SUCCESS!");
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,21 +3,17 @@
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|
||||||
int main()
|
int main(int argc, char **argv)
|
||||||
{
|
{
|
||||||
MtState *state = mt_initialize("Internal Test");
|
MtState *state = mt_initialize("Interface Test");;
|
||||||
MtEntity *entity = mt_summon(state);
|
MtEntity *entity = mt_summon(state);
|
||||||
MtEntity *looked_up_entity = mt_get_entity(state, entity->identifier);
|
MtEntity *looked_up_entity = mt_get_entity(state, entity->identifier);
|
||||||
|
|
||||||
if(entity != looked_up_entity)
|
if(entity != looked_up_entity)
|
||||||
{
|
printf("Failed looking up entity; the pointers don't match:\nOriginal: %p\nLooked Up: %p\n", entity, looked_up_entity);
|
||||||
printf("Failed looking up entity; the pointers don't match:\nOriginal: %p\nLooked Up: %p\nERROR!", (void *) entity, (void *) looked_up_entity);
|
else
|
||||||
mt_drop(entity);
|
puts("The entity which was looked up from the identifier does match the original. SUCCESS!");
|
||||||
mt_cleanup(state);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
puts("The entity which was looked up from the identifier does match the original. SUCCESS!");
|
|
||||||
mt_drop(entity);
|
mt_drop(entity);
|
||||||
mt_cleanup(state);
|
mt_cleanup(state);
|
||||||
return 0;
|
}
|
||||||
}
|
|
Reference in New Issue