This repository has been archived on 2024-02-21. You can view files and clone it, but cannot push or open issues or pull requests.
MainTree/core/src-c/queries.c

108 lines
3.4 KiB
C

#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;
}