Added a reserve function to linked lists. This came along an allocator function and better memory management. Elements and error handling has exploded everywere, that's why there is so much changes.
This commit is contained in:
parent
4b5babd9b9
commit
b1dd9baf98
|
|
@ -8,22 +8,21 @@
|
|||
#include "display.h"
|
||||
#include "errors.h"
|
||||
|
||||
asset_t *create_asset(asset_type_t asset_type)
|
||||
int create_asset(asset_t *asset, va_list args)
|
||||
{
|
||||
asset_t *asset = malloc(sizeof(asset_t));
|
||||
if(!asset)
|
||||
{
|
||||
error_printf("Failed to allocate memory : %d", errno);
|
||||
return NULL;
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
asset->type = asset_type;
|
||||
asset->type = va_arg(args, asset_type_t);
|
||||
asset->nb_refs = 0;
|
||||
|
||||
return asset;
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
void destroy_asset(asset_t *asset)
|
||||
int destroy_asset(asset_t *asset)
|
||||
{
|
||||
free(asset->name);
|
||||
|
||||
|
|
@ -38,21 +37,22 @@ void destroy_asset(asset_t *asset)
|
|||
break;
|
||||
}
|
||||
|
||||
free(asset);
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
void destroy_asset_header_def(asset_header_def_t *asset_header_def)
|
||||
int destroy_asset_header_def(asset_header_def_t *asset_header_def)
|
||||
{
|
||||
free(asset_header_def->name);
|
||||
free(asset_header_def);
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
int asset_manager_init(asset_manager_t *asset_manager)
|
||||
{
|
||||
assert("Asset manager cannot be NULL" && asset_manager);
|
||||
|
||||
linked_list_init(&asset_manager->assets, sizeof(asset_t), (deleter_t)destroy_asset);
|
||||
linked_list_init(&asset_manager->assets_header_defs, sizeof(asset_header_def_t), (deleter_t)destroy_asset_header_def);
|
||||
linked_list_init(&asset_manager->assets, sizeof(asset_t), (allocator_t)create_asset, (deleter_t)destroy_asset);
|
||||
linked_list_init(&asset_manager->assets_header_defs, sizeof(asset_header_def_t), NULL, (deleter_t)destroy_asset_header_def);
|
||||
|
||||
asset_manager->asset_file = fopen(ASSET_FILE_NAME, "rb");
|
||||
if(!asset_manager->asset_file)
|
||||
|
|
@ -69,28 +69,34 @@ int asset_manager_init(asset_manager_t *asset_manager)
|
|||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
if(linked_list_reserve(&asset_manager->assets_header_defs, nb_assets + 1)) return EXIT_FAILURE;
|
||||
|
||||
for(size_t i = 0; i < nb_assets; i++)
|
||||
{
|
||||
elem_t *elem = elem_create(&asset_manager->assets_header_defs);
|
||||
if(!elem) return EXIT_FAILURE;
|
||||
elem_t *asset_header_def_elem = create_elem(&asset_manager->assets_header_defs);
|
||||
if(!asset_header_def_elem) return EXIT_FAILURE;
|
||||
asset_header_def_t *asset_header_def = asset_header_def_elem->data;
|
||||
|
||||
size_t cap = 0;
|
||||
|
||||
ret = getdelim(&((asset_header_def_t *)elem->data)->name, &cap, '\0', asset_manager->asset_file);
|
||||
char *asset_name;
|
||||
ret = getdelim(&asset_name, &cap, '\0', asset_manager->asset_file);
|
||||
if(ret == SIZE_MAX)
|
||||
{
|
||||
error_printf("Failed to read asset file.");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
asset_header_def->name = calloc(strlen(asset_name) + 1, sizeof(char));
|
||||
strcpy(asset_header_def->name, asset_name);
|
||||
|
||||
ret = fread(&((asset_header_def_t *)elem->data)->start, sizeof(((asset_header_def_t *)elem->data)->start), 1, asset_manager->asset_file);
|
||||
ret = fread(&asset_header_def->start, sizeof(asset_header_def->start), 1, asset_manager->asset_file);
|
||||
if(ret != 1)
|
||||
{
|
||||
error_printf("Failed to read asset file.");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
if(linked_list_push_back_elem(&asset_manager->assets_header_defs, elem)) return EXIT_FAILURE;
|
||||
if(linked_list_push_back(&asset_manager->assets_header_defs, asset_header_def_elem)) return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
debug_printf("Initialized asset manager.");
|
||||
|
|
@ -101,8 +107,8 @@ int asset_manager_exit(asset_manager_t *asset_manager)
|
|||
{
|
||||
assert("Asset manager cannot be NULL" && asset_manager);
|
||||
|
||||
linked_list_clear(&asset_manager->assets_header_defs);
|
||||
linked_list_clear(&asset_manager->assets);
|
||||
if(linked_list_clear(&asset_manager->assets_header_defs)) return EXIT_FAILURE;
|
||||
if(linked_list_clear(&asset_manager->assets)) return EXIT_FAILURE;
|
||||
|
||||
if(fclose(asset_manager->asset_file))
|
||||
{
|
||||
|
|
@ -125,7 +131,9 @@ inline int asset_manager_collect_garbage(asset_manager_t *asset_manager)
|
|||
{
|
||||
assert("Asset manager cannot be NULL" && asset_manager);
|
||||
|
||||
return linked_list_remove_if(&asset_manager->assets, condition_is_asset_unused);
|
||||
if(linked_list_remove_if(&asset_manager->assets, condition_is_asset_unused)) return EXIT_FAILURE;
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
// Only for this file
|
||||
|
|
@ -210,21 +218,31 @@ int asset_manager_load_asset(asset_manager_t *asset_manager, const char *asset_n
|
|||
assert("Asset manager cannot be NULL" && asset_manager);
|
||||
|
||||
// Check if asset has alread been loaded.
|
||||
asset_t *asset = linked_list_get_if(&asset_manager->assets, condition_is_asset_name, asset_name);
|
||||
if(!asset)
|
||||
elem_t *asset_elem = linked_list_get_if(&asset_manager->assets, condition_is_asset_name, asset_name);
|
||||
if(asset_elem)
|
||||
{
|
||||
((asset_t *)asset_elem->data)->nb_refs++;
|
||||
|
||||
debug_printf("Asset \"%s\" has already been loaded, nb refs : %lu", ((asset_t *)asset_elem->data)->name, ((asset_t *)asset_elem->data)->nb_refs);
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
else
|
||||
{
|
||||
// If it didn't, load it
|
||||
asset_header_def_t *asset_header_def = linked_list_get_if(&asset_manager->assets_header_defs, condition_is_asset_header_def_name, asset_name);
|
||||
if(!asset_header_def)
|
||||
elem_t *asset_header_def_elem = linked_list_get_if(&asset_manager->assets_header_defs, condition_is_asset_header_def_name, asset_name);
|
||||
if(!asset_header_def_elem)
|
||||
{
|
||||
error_printf("Asset doesn't exist in asset file : %s", asset_name);
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
asset_header_def_t *asset_header_def = asset_header_def_elem->data;
|
||||
|
||||
asset = create_asset(asset_type);
|
||||
if(!asset) return EXIT_FAILURE;
|
||||
asset_elem = create_elem(&asset_manager->assets, asset_type);
|
||||
if(!asset_elem) return EXIT_FAILURE;
|
||||
asset_t *asset = asset_elem->data;
|
||||
|
||||
asset->name = malloc(strlen(asset_name) + 1);
|
||||
asset->name = calloc(strlen(asset_name) + 1, sizeof(char));
|
||||
if(!asset->name)
|
||||
{
|
||||
error_printf("Failed to allocate memory for asset name : %d", errno);
|
||||
|
|
@ -243,46 +261,56 @@ int asset_manager_load_asset(asset_manager_t *asset_manager, const char *asset_n
|
|||
default:
|
||||
error_printf("Asset type doesn't exists : %d", asset_type);
|
||||
destroy_asset(asset);
|
||||
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
linked_list_push_back(&asset_manager->assets, asset);
|
||||
}
|
||||
asset->nb_refs++;
|
||||
|
||||
asset->nb_refs++;
|
||||
debug_printf("Asset \"%s\" has been loaded, nb refs : %lu", asset->name, asset->nb_refs);
|
||||
return EXIT_SUCCESS;
|
||||
linked_list_push_back(&asset_manager->assets, asset_elem);
|
||||
|
||||
debug_printf("Asset \"%s\" has been loaded, nb refs : %lu", asset->name, asset->nb_refs);
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
}
|
||||
|
||||
int asset_manager_let_go_asset(asset_manager_t *asset_manager, const char *asset_name)
|
||||
{
|
||||
assert("Asset manager cannot be NULL" && asset_manager);
|
||||
|
||||
asset_t *asset = linked_list_get_if(&asset_manager->assets, condition_is_asset_name, asset_name);
|
||||
if(!asset)
|
||||
elem_t *asset_elem = linked_list_get_if(&asset_manager->assets, condition_is_asset_name, asset_name);
|
||||
if(!asset_elem)
|
||||
{
|
||||
error_printf("Asset doesn't exists : %s", asset_name);
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
asset_t *asset = asset_elem->data;
|
||||
|
||||
asset->nb_refs--;
|
||||
|
||||
debug_printf("Asset \"%s\" has been let go, nb refs : %lu", asset->name, asset->nb_refs);
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
texture_t *asset_manager_get_texture(asset_manager_t *asset_manager, const char *asset_name)
|
||||
texture_t *asset_manager_get_texture(asset_manager_t *asset_manager, const char *texture_name)
|
||||
{
|
||||
assert("Asset manager cannot be NULL" && asset_manager);
|
||||
|
||||
asset_t *asset = linked_list_get_if(&asset_manager->assets, condition_is_asset_name, asset_name);
|
||||
if(!asset)
|
||||
elem_t *asset_elem = linked_list_get_if(&asset_manager->assets, condition_is_asset_name, texture_name);
|
||||
if(!asset_elem)
|
||||
{
|
||||
error_printf("Asset \"%s\" hasn't been loaded yet.", asset_name);
|
||||
error_printf("Asset \"%s\" hasn't been loaded yet.", texture_name);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
asset_t *asset = asset_elem->data;
|
||||
|
||||
if(asset->type != ASSET_TEXTURE)
|
||||
{
|
||||
error_printf("Asset \"%s\" isn't of type ASSET_TEXTURE.", asset_name);
|
||||
error_printf("Asset \"%s\" isn't of type ASSET_TEXTURE.", texture_name);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
|
|
|||
133
src/ecs.c
133
src/ecs.c
|
|
@ -4,18 +4,17 @@
|
|||
#include "components.h"
|
||||
#include "errors.h"
|
||||
|
||||
component_t *create_component(component_type_t component_type)
|
||||
int create_component(component_t *component, va_list args)
|
||||
{
|
||||
component_t *component = malloc(sizeof(component_t));
|
||||
if(!component)
|
||||
{
|
||||
error_printf("Failed to allocate memory : %d", errno);
|
||||
return NULL;
|
||||
error_printf("Component cannot be NULL");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
component->component_type = component_type;
|
||||
component->component_type = va_arg(args, component_type_t);
|
||||
|
||||
switch(component_type)
|
||||
switch(component->component_type)
|
||||
{
|
||||
#define COMPONENT(NAME, PREFIX, DRAW) \
|
||||
case NAME: \
|
||||
|
|
@ -25,61 +24,76 @@ component_t *create_component(component_type_t component_type)
|
|||
component->component_data = malloc(sizeof(PREFIX##_data_t)); \
|
||||
if(!component->component_data) \
|
||||
{ \
|
||||
free(component); \
|
||||
error_printf("Failed to allocate memory : %d", errno); \
|
||||
return NULL; \
|
||||
return EXIT_FAILURE; \
|
||||
} \
|
||||
component->component_deleter = PREFIX##_destroy; \
|
||||
break;
|
||||
#include "components.def"
|
||||
|
||||
default:
|
||||
free(component);
|
||||
error_printf("Component type doesn't exists : %d", component_type);
|
||||
return NULL;
|
||||
error_printf("Component type doesn't exists : %d", component->component_type);
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
return component;
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
inline void destroy_component(component_t *component)
|
||||
inline int destroy_component(component_t *component)
|
||||
{
|
||||
component->component_deleter(component);
|
||||
free(component);
|
||||
if(!component)
|
||||
{
|
||||
error_printf("Component cannot be NULL");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
if(component->component_deleter(component)) return EXIT_FAILURE;
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
entity_t *create_entity(const unsigned int id)
|
||||
int create_entity(entity_t *entity, va_list args)
|
||||
{
|
||||
entity_t *entity = malloc(sizeof(entity_t));
|
||||
if(!entity)
|
||||
{
|
||||
error_printf("Failed to allocate memory : %d", errno);
|
||||
return NULL;
|
||||
error_printf("Entity cannot be NULL");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
entity->id = id;
|
||||
entity->id = va_arg(args, size_t);
|
||||
entity->draw_priority = 0;
|
||||
|
||||
linked_list_init(&entity->components, sizeof(component_t), (deleter_t)destroy_component);
|
||||
linked_list_init(&entity->components, sizeof(component_t), (allocator_t)create_component, (deleter_t)destroy_component);
|
||||
|
||||
return entity;
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
void add_component(entity_t *entity, component_t *component, ...)
|
||||
inline int destroy_entity(entity_t *entity)
|
||||
{
|
||||
if(!entity)
|
||||
{
|
||||
error_printf("Entity cannot be NULL");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
if(linked_list_clear(&entity->components)) return EXIT_FAILURE;
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
component_t *entity_new_component(entity_t *entity, component_type_t component_type)
|
||||
{
|
||||
elem_t *component_elem = create_elem(&entity->components, component_type);
|
||||
if(!component_elem) return NULL;
|
||||
component_t *component = component_elem->data;
|
||||
|
||||
component->entity = entity;
|
||||
|
||||
va_list args, args_copy;
|
||||
if(component->component_init(component)) return NULL;
|
||||
|
||||
va_start(args, component);
|
||||
va_copy(args_copy, args);
|
||||
if(linked_list_push_front(&entity->components, component_elem)) return NULL;
|
||||
|
||||
component->component_init(component, args_copy);
|
||||
|
||||
va_end(args_copy);
|
||||
va_end(args);
|
||||
|
||||
linked_list_push_back(&entity->components, component);
|
||||
return component;
|
||||
}
|
||||
|
||||
// Only for this file
|
||||
|
|
@ -89,12 +103,13 @@ static inline bool condition_is_component_type(elem_t *elem, va_list args)
|
|||
return ((component_t *)elem->data)->component_type == va_arg(args, component_type_t);
|
||||
}
|
||||
|
||||
inline component_t *get_component(entity_t *entity, component_type_t component_type)
|
||||
inline component_t *entity_get_component(entity_t *entity, component_type_t component_type)
|
||||
{
|
||||
component_t *component = linked_list_get_if(&entity->components, condition_is_component_type, component_type);
|
||||
elem_t *elem = linked_list_get_if(&entity->components, condition_is_component_type, component_type);
|
||||
component_t *component = elem->data;
|
||||
if(!component)
|
||||
{
|
||||
error_printf("Entity with id:%d doesn't have componant of type : %d", entity->id, component_type);
|
||||
error_printf("Entity with id:%lu doesn't have componant of type : %d", entity->id, component_type);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
|
@ -106,14 +121,16 @@ inline component_t *get_component(entity_t *entity, component_type_t component_t
|
|||
static inline int action_update_component(elem_t *elem, va_list args __attribute__((unused)))
|
||||
{
|
||||
component_t *component = elem->data;
|
||||
component->component_update(component);
|
||||
if(component->component_update(component)) return EXIT_FAILURE;
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
inline int update_entity(entity_t *entity)
|
||||
{
|
||||
return linked_list_for_each(&entity->components, action_update_component);
|
||||
if(linked_list_for_each(&entity->components, action_update_component)) return EXIT_FAILURE;
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
// Only for this file
|
||||
|
|
@ -121,39 +138,39 @@ inline int update_entity(entity_t *entity)
|
|||
static inline int action_draw_component(elem_t *elem, va_list args __attribute__((unused)))
|
||||
{
|
||||
component_t *component = elem->data;
|
||||
if(component->component_draw) component->component_draw(component);
|
||||
if(component->component_draw) if(component->component_draw(component)) return EXIT_FAILURE;
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
inline int draw_entity(entity_t *entity)
|
||||
{
|
||||
return linked_list_for_each(&entity->components, action_draw_component);
|
||||
}
|
||||
if(linked_list_for_each(&entity->components, action_draw_component)) return EXIT_FAILURE;
|
||||
|
||||
inline void destroy_entity(entity_t *entity)
|
||||
{
|
||||
linked_list_clear(&entity->components);
|
||||
free(entity);
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
inline void entity_manager_init(entity_manager_t *entity_manager)
|
||||
{
|
||||
assert("Entity manager cannot be NULL" && entity_manager);
|
||||
|
||||
linked_list_init(&entity_manager->entities, sizeof(entity_t), (deleter_t)destroy_entity);
|
||||
linked_list_init(&entity_manager->entities, sizeof(entity_t), (allocator_t)create_entity, (deleter_t)destroy_entity);
|
||||
|
||||
debug_printf("Initialized entity manager.");
|
||||
}
|
||||
|
||||
inline int entity_manager_add_entity(entity_manager_t *entity_manager, entity_t *entity)
|
||||
inline entity_t *entity_manager_new_entity(entity_manager_t *entity_manager, size_t id)
|
||||
{
|
||||
assert("Entity manager cannot be NULL" && entity_manager);
|
||||
|
||||
if(linked_list_push_back(&entity_manager->entities, entity)) return EXIT_FAILURE;
|
||||
elem_t *entity_elem = create_elem(&entity_manager->entities, id);
|
||||
if(!entity_elem) return NULL;
|
||||
|
||||
debug_printf("Added entity %d to entity manager.", entity->id);
|
||||
if(linked_list_push_back(&entity_manager->entities, entity_elem)) return NULL;
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
debug_printf("Added entity %lu to entity manager.", id);
|
||||
|
||||
return entity_elem->data;
|
||||
}
|
||||
|
||||
// Only for this file
|
||||
|
|
@ -167,7 +184,9 @@ inline int entity_manager_update(entity_manager_t *entity_manager)
|
|||
{
|
||||
assert("Entity manager cannot be NULL" && entity_manager);
|
||||
|
||||
return linked_list_for_each(&entity_manager->entities, action_update_entity);
|
||||
if(linked_list_for_each(&entity_manager->entities, action_update_entity)) return EXIT_FAILURE;
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
// Only for this file
|
||||
|
|
@ -181,7 +200,9 @@ inline int entity_manager_draw(entity_manager_t *entity_manager)
|
|||
{
|
||||
assert("Entity manager cannot be NULL" && entity_manager);
|
||||
|
||||
return linked_list_for_each(&entity_manager->entities, action_draw_entity);
|
||||
if(linked_list_for_each(&entity_manager->entities, action_draw_entity)) return EXIT_FAILURE;
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
// Only for this file
|
||||
|
|
@ -195,14 +216,18 @@ inline int entity_manager_remove_entity(entity_manager_t *entity_manager, unsign
|
|||
{
|
||||
assert("Entity manager cannot be NULL" && entity_manager);
|
||||
|
||||
return linked_list_remove_if(&entity_manager->entities, condition_is_entity_name, id);
|
||||
if(linked_list_remove_if(&entity_manager->entities, condition_is_entity_name, id)) return EXIT_FAILURE;
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
inline void entity_manager_exit(entity_manager_t *entity_manager)
|
||||
inline int entity_manager_exit(entity_manager_t *entity_manager)
|
||||
{
|
||||
assert("Entity manager cannot be NULL" && entity_manager);
|
||||
|
||||
linked_list_clear(&entity_manager->entities);
|
||||
if(linked_list_clear(&entity_manager->entities)) return EXIT_FAILURE;
|
||||
|
||||
debug_printf("Exited entity manager.");
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -25,16 +25,16 @@ typedef struct asset_t {
|
|||
asset_type_t type;
|
||||
} asset_t;
|
||||
|
||||
asset_t *create_asset(asset_type_t asset_type);
|
||||
int create_asset(asset_t *asset, va_list args);
|
||||
|
||||
void destroy_asset(asset_t *asset);
|
||||
int destroy_asset(asset_t *asset);
|
||||
|
||||
typedef struct asset_header_def_t {
|
||||
char *name;
|
||||
size_t start;
|
||||
} asset_header_def_t;
|
||||
|
||||
void destroy_asset_header_def(asset_header_def_t *asset_header_def);
|
||||
int destroy_asset_header_def(asset_header_def_t *asset_header_def);
|
||||
|
||||
typedef struct asset_manager_t {
|
||||
linked_list_t assets_header_defs;
|
||||
|
|
|
|||
|
|
@ -14,13 +14,13 @@ typedef enum component_type_t {
|
|||
typedef struct component_t component_t;
|
||||
|
||||
// Component init function. It is called when component added to entity. This function is necessary.
|
||||
typedef int (*component_init_t)(component_t *component, va_list args);
|
||||
typedef int (*component_init_t)(component_t *component);
|
||||
// Component update function. It is called in the main loop to update the component. This function is necessary.
|
||||
typedef int (*component_update_t)(component_t *component);
|
||||
// Component draw function. It is called in the main loop to draw the component on screen. This function is not necessary.
|
||||
typedef int (*component_draw_t)(component_t *component);
|
||||
// Component deleter function. It is called when the component is removed. It should free the data in the component data but not the component itself.
|
||||
typedef void (*component_deleter_t)(component_t *component);
|
||||
typedef int (*component_deleter_t)(component_t *component);
|
||||
|
||||
typedef struct component_t {
|
||||
component_init_t component_init;
|
||||
|
|
@ -37,35 +37,35 @@ typedef struct component_t {
|
|||
|
||||
} component_t;
|
||||
|
||||
component_t *create_component(component_type_t component_type);
|
||||
int create_component(component_t *component, va_list args);
|
||||
|
||||
void destroy_component(component_t *component);
|
||||
int destroy_component(component_t *component);
|
||||
|
||||
typedef struct entity_t {
|
||||
unsigned int id;
|
||||
size_t id;
|
||||
size_t draw_priority;
|
||||
linked_list_t components;
|
||||
} entity_t;
|
||||
|
||||
entity_t *create_entity(const unsigned int id);
|
||||
int create_entity(entity_t *entity, va_list args);
|
||||
|
||||
void add_component(entity_t *entity, component_t *component, ...);
|
||||
int destroy_entity(entity_t *entity);
|
||||
|
||||
component_t *get_component(entity_t *entity, component_type_t component_type);
|
||||
component_t *entity_new_component(entity_t *entity, component_type_t component_type);
|
||||
|
||||
component_t *entity_get_component(entity_t *entity, component_type_t component_type);
|
||||
|
||||
int update_entity(entity_t *entity);
|
||||
|
||||
int draw_entity(entity_t *entity);
|
||||
|
||||
void destroy_entity(entity_t *entity);
|
||||
|
||||
typedef struct entity_manager_t {
|
||||
linked_list_t entities;
|
||||
} entity_manager_t;
|
||||
|
||||
void entity_manager_init(entity_manager_t *entity_manager);
|
||||
|
||||
int entity_manager_add_entity(entity_manager_t *entity_manager, entity_t *entity);
|
||||
entity_t *entity_manager_new_entity(entity_manager_t *entity_manager, size_t id);
|
||||
|
||||
int entity_manager_update(entity_manager_t *entity_manager);
|
||||
|
||||
|
|
@ -73,6 +73,6 @@ int entity_manager_draw(entity_manager_t *entity_manager);
|
|||
|
||||
int entity_manager_remove_entity(entity_manager_t *entity_manager, const unsigned int id);
|
||||
|
||||
void entity_manager_exit(entity_manager_t *entity_manager);
|
||||
int entity_manager_exit(entity_manager_t *entity_manager);
|
||||
|
||||
#endif // ECS_H
|
||||
|
|
@ -21,194 +21,177 @@ typedef struct elem_t {
|
|||
} elem_t;
|
||||
|
||||
/**
|
||||
* @brief A type for deleters used during the destruction of data stored in elements.
|
||||
* @brief A type for allocators used during the creation of data stored in elements' data.
|
||||
*
|
||||
* During the initialisation of linked lists you can pass in argument an allocator.
|
||||
* You can pass NULL to the initialisation to not use an allocator.
|
||||
* Your allocator_t function declaration must look like this :
|
||||
*
|
||||
* int name_of_your_allocator(void* data, va_list args);
|
||||
*
|
||||
* Then do what you need to fill your data.
|
||||
*
|
||||
* @param data Data to fill.
|
||||
*
|
||||
* @return EXIT_SUCCESS, EXIT_FAILURE on error.
|
||||
*/
|
||||
typedef int (*allocator_t)(void *data, va_list args);
|
||||
|
||||
/**
|
||||
* @brief A type for deleters used during the destruction of data stored in elements' data.
|
||||
*
|
||||
* During the initialisation of linked lists you can pass in argument a deleter.
|
||||
* It is used during the destruction of an element.
|
||||
* You can pass NULL to the initialisation to use the default deleter (free(elem->data)).
|
||||
* You can pass NULL to the initialisation to not use a deleter.
|
||||
* Your deleter_t function declaration must look like this :
|
||||
*
|
||||
* void name_of_your_deleter(void *data);
|
||||
*
|
||||
* Then do what you need to destroy your data (don't forget to free the data itself...) but not the elements.
|
||||
* You should always define your function with "inline" if it's no too long.
|
||||
* Then do what you need to destroy your data (don't free the data itself).
|
||||
*
|
||||
* @param data Data to free.
|
||||
*/
|
||||
typedef void (*deleter_t)(void *data);
|
||||
typedef int (*deleter_t)(void *data);
|
||||
|
||||
/**
|
||||
* @brief A type for condition used for function like linked_list_remove_if
|
||||
* @brief A type for condition used for function like linked_list_remove_if.
|
||||
*
|
||||
* For function like linked_list_remove_if you need a condition.
|
||||
* It have two argument which are "elem_t *" and "va_list", that is because it passes the element on the actual index
|
||||
* and the args passed to the function.
|
||||
* Your condition_t function declaration must look like this :
|
||||
*
|
||||
* bool name_of_your_condition(elem_t *elem, va_list);
|
||||
*
|
||||
* Then return true if you want the element to be removed from the list or false if not.
|
||||
* You should always define your function with "static", and "inline".
|
||||
* @param elem Processed element
|
||||
* @param args Arguments to pass to the function
|
||||
*
|
||||
* @return False, true for the element to be removed.
|
||||
*/
|
||||
typedef bool (*condition_t)(elem_t *elem, va_list args);
|
||||
|
||||
/**
|
||||
* @brief A type for action used for function like linked_list_for_each
|
||||
*
|
||||
* For function like linked_list_for_each you need an action to do.
|
||||
* It have two argument which are "elem_t *" and "va_list", that is because it passes the element on the actual index
|
||||
* and the args passed to the function.
|
||||
* You can use the return value to indicate an error with EXIT_SUCCESS or EXIT_FAILURE.
|
||||
* Your condition_t function declaration must look like this :
|
||||
*
|
||||
* int name_of_your_condition(elem_t *elem, va_list);
|
||||
*
|
||||
* Then do whatever you want with the element data, just don't free it.
|
||||
* You should always define your function with "static", and "inline".
|
||||
* @param elem Processed element
|
||||
* @param args Arguments to pass to the function
|
||||
*
|
||||
* @return EXIT_SUCCESS, EXIT_FAILURE on error.
|
||||
*/
|
||||
typedef int (*action_t)(elem_t *elem, va_list args);
|
||||
|
||||
/**
|
||||
* @brief Base of linked lists.
|
||||
* This struct is the base for creating linked lists.
|
||||
*
|
||||
* @param data_size Size of the data stored in elements of the linked list (used while creating new elements)
|
||||
* @param first Pointer to the first element in the linked list
|
||||
* @param last Pointer to the last element in the linked list
|
||||
* @param size Size of the linked list
|
||||
* @param deleter Deleter of the data when removing an element
|
||||
* @param data_size Size of the data stored in elements
|
||||
* @param allocator Allocator of data when creating new elements
|
||||
* @param deleter Deleter of data when removing elements
|
||||
* @param first Pointer to the first element in the list
|
||||
* @param last Pointer to the last element in the list
|
||||
* @param size Size of the linked list
|
||||
* @param reserved Pointer to the first reserved element
|
||||
* @param target_max_size Total target number of elements in the list
|
||||
*/
|
||||
typedef struct linked_list_t {
|
||||
size_t data_size;
|
||||
allocator_t allocator;
|
||||
deleter_t deleter;
|
||||
elem_t *first;
|
||||
elem_t *last;
|
||||
size_t size;
|
||||
deleter_t elem_deleter;
|
||||
elem_t *reserved;
|
||||
size_t target_max_size;
|
||||
} linked_list_t;
|
||||
|
||||
/**
|
||||
* @brief Init a linked list
|
||||
* This function is necessary if you create a linked list.
|
||||
* @brief Init a linked list.
|
||||
*
|
||||
* WARNING : It doesn't allocate the memory for you !
|
||||
*
|
||||
* @param linked_list Pointer to an linked list
|
||||
* @param data_size Data size for elements in the linked list
|
||||
* @param deleter The deleter used during destroyement of an elem
|
||||
* @param linked_list Pointer to a linked list
|
||||
* @param data_size Data size for elements data in the linked list
|
||||
* @param deleter The deleter for elem
|
||||
*/
|
||||
void linked_list_init(linked_list_t *linked_list, const size_t data_size, deleter_t deleter);
|
||||
void linked_list_init(linked_list_t *linked_list, size_t data_size, const allocator_t allocator, const deleter_t deleter);
|
||||
|
||||
/**
|
||||
* @brief Create an elem to fill with data to insert in a linked list.
|
||||
* This function is usefull when you want to initialise an elem with the proper data_size strored in the linked list.
|
||||
*
|
||||
* WARNING : Don't change the "data" ptr after calling this function or it will lead to memory leaks !
|
||||
* Instead do something like this : *(int *)elem->data = 42;
|
||||
* @brief Pre-allocate elements for a target size.
|
||||
* If you want n more elements in your list, then you want linked_list.size + n target_size.
|
||||
*
|
||||
* @param linked_list Pointer to a linked list
|
||||
* @param target_size Target size of linked list
|
||||
*
|
||||
* @return EXIT_SUCCESS, EXIT_FAILURE on error.
|
||||
*/
|
||||
int linked_list_reserve(linked_list_t *linked_list, size_t target_size);
|
||||
|
||||
/**
|
||||
* @brief Create an elem to insert in a linked list. The data pointer is allocated.
|
||||
* If there is an element available in reserved list then it will be used.
|
||||
*
|
||||
* @param linked_list Pointer to an linked list
|
||||
* @param ... Arguments to pass to the allocator
|
||||
*
|
||||
* @return Address of initialised elem, NULL on error.
|
||||
* @return pointer to initialised elem, NULL on error.
|
||||
*/
|
||||
elem_t *elem_create(const linked_list_t *linked_list);
|
||||
elem_t *create_elem(linked_list_t *linked_list, ...);
|
||||
|
||||
/**
|
||||
* @brief Destroy the given element and its data.
|
||||
* This function is usefull when you want to free an element.
|
||||
* The deleter is used for the data only and you can pass NULL to use the default deleter.
|
||||
* May move the element into the reserved list for future use depending on target size of the list.
|
||||
*
|
||||
* @param linked_list Pointer to a linked list
|
||||
* @param elem Pointer to an element
|
||||
* @param elem_deleter Function to use to free the data
|
||||
*
|
||||
* @return EXIT_SUCCESS, EXIT_FAILURE on error.
|
||||
*/
|
||||
void destroy_elem(elem_t *elem, const deleter_t elem_deleter);
|
||||
int destroy_elem(linked_list_t *linked_list, elem_t *elem);
|
||||
|
||||
/**
|
||||
* @brief Insert an element from the back in a linked list, do nothing on error.
|
||||
*
|
||||
* @param linked_list Pointer to a linked list
|
||||
* @param elem Pointer to an element
|
||||
*
|
||||
* @return EXIT_SUCCESS, EXIT_FAILURE on error.
|
||||
*/
|
||||
int linked_list_push_back_elem(linked_list_t *linked_list, elem_t *elem);
|
||||
int linked_list_push_back(linked_list_t *linked_list, elem_t *elem);
|
||||
|
||||
/**
|
||||
* @brief Insert an element from the front in a linked list, do nothing on error.
|
||||
*
|
||||
* @param linked_list Pointer to a linked list
|
||||
* @param elem Pointer to an element
|
||||
*
|
||||
* @return EXIT_SUCCESS, EXIT_FAILURE on error.
|
||||
*/
|
||||
int linked_list_push_front_elem(linked_list_t *linked_list, elem_t *elem);
|
||||
int linked_list_push_front(linked_list_t *linked_list, elem_t *elem);
|
||||
|
||||
/**
|
||||
* @brief Insert an element initialised and filled with data from the back in a linked list, do nothing on error.
|
||||
* @brief Remove and return the last element in the given linked list, do nothing on error.
|
||||
*
|
||||
* @param linked_list Pointer to a linked list
|
||||
* @param data Pointer to any data
|
||||
*
|
||||
* @return Pointer to element, NULL on error.
|
||||
*/
|
||||
int linked_list_push_back(linked_list_t *linked_list, void *data);
|
||||
elem_t *linked_list_pop_back(linked_list_t *linked_list);
|
||||
|
||||
/**
|
||||
* @brief Insert an element filled with data from the front in a linked list.
|
||||
* @brief Remove and return the first element in the given linked list, do nothing on error.
|
||||
*
|
||||
* @param linked_list Pointer to a linked list
|
||||
* @param data Pointer to any data
|
||||
*/
|
||||
int linked_list_push_front(linked_list_t *linked_list, void *data);
|
||||
|
||||
/**
|
||||
* @brief Delete the last element in the given linked list, do nothing on error.
|
||||
*
|
||||
* @param linked_list Pointer to a linked list
|
||||
* @return EXIT_SUCCESS, EXIT_FAILURE on error.
|
||||
*/
|
||||
int linked_list_pop_back(linked_list_t *linked_list);
|
||||
|
||||
/**
|
||||
* @brief Delete the first element in the given linked list, do nothing on error.
|
||||
*
|
||||
* @param linked_list Pointer to a linked list
|
||||
*/
|
||||
int linked_list_pop_front(linked_list_t *linked_list);
|
||||
elem_t *linked_list_pop_front(linked_list_t *linked_list);
|
||||
|
||||
/**
|
||||
* @brief Clear the given linked list, do nothing on error.
|
||||
* May move the elements into the reserved list for future use depending on target size of the list.
|
||||
*
|
||||
* @brief linked_list Pointer to a linked list
|
||||
*
|
||||
* @return EXIT_SUCCESS, EXIT_FAILURE on error.
|
||||
*/
|
||||
void linked_list_clear(linked_list_t *linked_list);
|
||||
|
||||
/**
|
||||
* @brief Check if the given linked list is empty.
|
||||
*
|
||||
* @param linked_list Pointer to a linked list
|
||||
*
|
||||
* @return True if the given linked list is empty else false.
|
||||
*/
|
||||
bool linked_list_is_empty(const linked_list_t *linked_list);
|
||||
|
||||
/**
|
||||
* @brief Check if the given index is whithin the range of the linked list.
|
||||
*
|
||||
* @param linked_list Pointer to an linked_list_t
|
||||
*
|
||||
* @return True if index in within the range of the linked list else false.
|
||||
*/
|
||||
bool linked_list_is_in_bound(const linked_list_t *linked_list, const size_t index);
|
||||
|
||||
/**
|
||||
* @brief Get element at the given index in the linked list.
|
||||
*
|
||||
* @param linked_list Pointer to a linked list
|
||||
* @param index Index of the element
|
||||
*
|
||||
* @return Element, NULL on error.
|
||||
*/
|
||||
elem_t *linked_list_get_elem(const linked_list_t *linked_list, const size_t index);
|
||||
|
||||
/**
|
||||
* @brief Get data in the element at the given index in the linked list.
|
||||
*
|
||||
* @param linked_list Pointer to an linked list
|
||||
* @param index Index of the wanted element
|
||||
*
|
||||
* @return Data, NULL on error.
|
||||
*/
|
||||
void *linked_list_get(const linked_list_t *linked_list, const size_t index);
|
||||
int linked_list_clear(linked_list_t *linked_list);
|
||||
|
||||
/**
|
||||
* @brief Insert element at the given index in the linked list, do nothing on error.
|
||||
|
|
@ -216,55 +199,42 @@ void *linked_list_get(const linked_list_t *linked_list, const size_t index);
|
|||
* @param linked_list Pointer to a linked list
|
||||
* @param elem Pointer to an element
|
||||
* @param index Index to insert element
|
||||
*/
|
||||
int linked_list_insert_elem(linked_list_t *linked_list, elem_t *elem, const size_t index);
|
||||
|
||||
/**
|
||||
* @brief Insert element with data at the given index in the linked list, do nothing on error.
|
||||
*
|
||||
* @param linked_list Pointer to a linked list
|
||||
* @param data Data to put in the new element
|
||||
* @param index Index to insert the element
|
||||
* @return EXIT_SUCCESS, EXIT_FAILURE on error.
|
||||
*/
|
||||
int linked_list_insert(linked_list_t *linked_list, void *data, const size_t index);
|
||||
int linked_list_insert(linked_list_t *linked_list, elem_t *elem, size_t index);
|
||||
|
||||
/**
|
||||
* @brief Remove the given elem in the linked list, do nothing on error.
|
||||
*
|
||||
* @param linked_list Pointer to a linked list
|
||||
* @param elem Element to remove
|
||||
*/
|
||||
int linked_list_remove_elem(linked_list_t *linked_list, elem_t *elem);
|
||||
|
||||
/**
|
||||
* @brief Remove element at the given index in the linked list, do nothing on error.
|
||||
* @brief Get element at the given index in the linked list.
|
||||
*
|
||||
* @param linked_list Pointer to a linked list
|
||||
* @param index Index of the element
|
||||
*
|
||||
* @return Pointer to element, NULL on error.
|
||||
*/
|
||||
int linked_list_remove(linked_list_t *linked_list, const size_t index);
|
||||
elem_t *linked_list_get(const linked_list_t *linked_list, size_t index);
|
||||
|
||||
/**
|
||||
* @brief Return first element that the condition verify
|
||||
* @brief Remove the given elem in the linked list, do nothing on error.
|
||||
* May move the elements into the reserved list for future use depending on target size of the list.
|
||||
*
|
||||
* @param linked_list Pointer to a linked list
|
||||
* @param elem Element to remove
|
||||
*
|
||||
* @return EXIT_SUCCESS, EXIT_FAILURE on error.
|
||||
*/
|
||||
int linked_list_remove(linked_list_t *linked_list, elem_t *elem);
|
||||
|
||||
/**
|
||||
* @brief Return first element that the condition verify.
|
||||
*
|
||||
* @param linked_list Pointer to a linked list
|
||||
* @param condition Condition to verify
|
||||
* @param ... Argument to pass to the condition
|
||||
*
|
||||
* @return Element, NULL if no element verify the condition or if an error ocurred.
|
||||
* @return Pointer to element, NULL if no element verify the condition or if an error occurred.
|
||||
*/
|
||||
elem_t *linked_list_get_elem_if(const linked_list_t *linked_list, const condition_t condition, ...);
|
||||
|
||||
/**
|
||||
* @brief Return data in the first element that the condition verify
|
||||
*
|
||||
* @param linked_list Pointer to a linked list
|
||||
* @param condition Condition to verify
|
||||
* @param ... Argument to pass to the condition
|
||||
*
|
||||
* @return Element data, NULL if no element verify the condition or if an error ocurred.
|
||||
*/
|
||||
void *linked_list_get_if(const linked_list_t *linked_list, const condition_t condition, ...);
|
||||
elem_t *linked_list_get_if(const linked_list_t *linked_list, const condition_t condition, ...);
|
||||
|
||||
/**
|
||||
* @brief Remove every elements that the condition verify, do nothing on error.
|
||||
|
|
@ -272,19 +242,20 @@ void *linked_list_get_if(const linked_list_t *linked_list, const condition_t con
|
|||
* @param linked_list Pointer to an linked list
|
||||
* @param condition Condition to verify
|
||||
* @param ... Argument to pass to the condition
|
||||
*
|
||||
* @return Pointer to element, NULL if no element verify the condition or if an error occurred.
|
||||
*/
|
||||
int linked_list_remove_if(linked_list_t *linked_list, const condition_t condition, ...);
|
||||
|
||||
/**
|
||||
* @brief Apply an action to every elements in the list.
|
||||
* Useful for changing a value in every single element data.
|
||||
* The action can be anything that doesn't destroy the element.
|
||||
*
|
||||
* @param linked_list Pointer to an linked list
|
||||
* @param action Action to apply
|
||||
* @param ... Argument to pass to the action
|
||||
*
|
||||
* @return The success of the action if supported by the action.
|
||||
* @return EXIT_SUCCESS, EXIT_FAILURE on error.
|
||||
*/
|
||||
int linked_list_for_each(const linked_list_t *linked_list, const action_t action, ...);
|
||||
|
||||
|
|
|
|||
|
|
@ -3,54 +3,124 @@
|
|||
#include "linked_list.h"
|
||||
#include "errors.h"
|
||||
|
||||
elem_t *elem_create(const linked_list_t *linked_list)
|
||||
elem_t *create_elem(linked_list_t *linked_list, ...)
|
||||
{
|
||||
assert("Linked list cannot be NULL" && linked_list);
|
||||
|
||||
elem_t *elem;
|
||||
elem = malloc(sizeof(elem_t));
|
||||
if(!elem)
|
||||
|
||||
if(linked_list->reserved)
|
||||
{
|
||||
error_printf("Failed to allocate memory : %d", errno);
|
||||
return NULL;
|
||||
elem = linked_list->reserved;
|
||||
linked_list->reserved = elem->next;
|
||||
}
|
||||
else
|
||||
{
|
||||
elem = malloc(sizeof(elem_t));
|
||||
if(!elem)
|
||||
{
|
||||
error_printf("Failed to allocate memory : %d", errno);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
elem->data = malloc(linked_list->data_size);
|
||||
if(!elem->data)
|
||||
{
|
||||
error_printf("Failed to allocate memory : %d", errno);
|
||||
free(elem);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
elem->data = malloc(linked_list->data_size);
|
||||
if(!elem->data)
|
||||
if(linked_list->allocator)
|
||||
{
|
||||
error_printf("Failed to allocate memory : %d", errno);
|
||||
free(elem);
|
||||
return NULL;
|
||||
va_list args, args_copy;
|
||||
va_start(args, linked_list);
|
||||
va_copy(args_copy, args);
|
||||
|
||||
if(linked_list->allocator(elem->data, args_copy)) return NULL;
|
||||
|
||||
va_end(args_copy);
|
||||
va_end(args);
|
||||
}
|
||||
|
||||
return elem;
|
||||
}
|
||||
|
||||
inline void destroy_elem(elem_t *elem, const deleter_t elem_deleter)
|
||||
{
|
||||
if(!elem) return; // Not fatal
|
||||
|
||||
if(elem_deleter)
|
||||
elem_deleter(elem->data);
|
||||
else
|
||||
free(elem->data);
|
||||
|
||||
free(elem);
|
||||
}
|
||||
|
||||
void linked_list_init(linked_list_t *linked_list, const size_t data_size, const deleter_t elem_deleter)
|
||||
inline int destroy_elem(linked_list_t *linked_list, elem_t *elem)
|
||||
{
|
||||
assert("Linked list cannot be NULL" && linked_list);
|
||||
|
||||
if(!elem)
|
||||
{
|
||||
error_printf("Elem cannot be NULL.");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
if(linked_list->deleter)
|
||||
if(linked_list->deleter(elem->data)) return EXIT_FAILURE;
|
||||
|
||||
if(linked_list->size < linked_list->target_max_size)
|
||||
{
|
||||
elem->next = linked_list->reserved;
|
||||
linked_list->reserved = elem;
|
||||
}
|
||||
else
|
||||
{
|
||||
free(elem->data);
|
||||
free(elem);
|
||||
}
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
void linked_list_init(linked_list_t *linked_list, const size_t data_size, const allocator_t allocator, const deleter_t elem_deleter)
|
||||
{
|
||||
assert("Linked list cannot be NULL" && linked_list);
|
||||
|
||||
linked_list->data_size = data_size;
|
||||
linked_list->allocator = allocator;
|
||||
linked_list->deleter = elem_deleter;
|
||||
|
||||
linked_list->first = NULL;
|
||||
linked_list->last = NULL;
|
||||
linked_list->size = 0;
|
||||
|
||||
linked_list->data_size = data_size;
|
||||
linked_list->elem_deleter = elem_deleter;
|
||||
linked_list->reserved = NULL;
|
||||
linked_list->target_max_size = 0;
|
||||
}
|
||||
|
||||
int linked_list_push_back_elem(linked_list_t *linked_list, elem_t *elem)
|
||||
int linked_list_reserve(linked_list_t *linked_list, size_t target_max_size)
|
||||
{
|
||||
assert("Linked list cannot be NULL" && linked_list);
|
||||
|
||||
linked_list->target_max_size = target_max_size;
|
||||
|
||||
for(size_t i = linked_list->size; i < target_max_size; i++)
|
||||
{
|
||||
elem_t *elem = malloc(sizeof(elem_t));
|
||||
if(!elem)
|
||||
{
|
||||
error_printf("Failed to allocate memory : %d", errno);
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
elem->data = malloc(linked_list->data_size);
|
||||
if(!elem->data)
|
||||
{
|
||||
error_printf("Failed to allocate memory : %d", errno);
|
||||
free(elem);
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
elem->next = linked_list->reserved;
|
||||
linked_list->reserved = elem;
|
||||
}
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
int linked_list_push_back(linked_list_t *linked_list, elem_t *elem)
|
||||
{
|
||||
assert("Linked list cannot be NULL" && linked_list);
|
||||
|
||||
|
|
@ -75,7 +145,7 @@ int linked_list_push_back_elem(linked_list_t *linked_list, elem_t *elem)
|
|||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
int linked_list_push_front_elem(linked_list_t *linked_list, elem_t *elem)
|
||||
int linked_list_push_front(linked_list_t *linked_list, elem_t *elem)
|
||||
{
|
||||
assert("Linked list cannot be NULL" && linked_list);
|
||||
|
||||
|
|
@ -100,110 +170,74 @@ int linked_list_push_front_elem(linked_list_t *linked_list, elem_t *elem)
|
|||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
int linked_list_push_back(linked_list_t *linked_list, void *data)
|
||||
elem_t *linked_list_pop_back(linked_list_t *linked_list)
|
||||
{
|
||||
assert("Linked list cannot be NULL" && linked_list);
|
||||
|
||||
elem_t *tmp = malloc(sizeof(elem_t));
|
||||
if(!tmp)
|
||||
{
|
||||
error_printf("Failed to allocate memory : %d", errno);
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
tmp->data = data;
|
||||
|
||||
if(linked_list_push_back_elem(linked_list, tmp)) return EXIT_FAILURE;
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
int linked_list_push_front(linked_list_t *linked_list, void *data)
|
||||
{
|
||||
assert("Linked list cannot be NULL" && linked_list);
|
||||
|
||||
elem_t *tmp = malloc(sizeof(elem_t));
|
||||
if(!tmp)
|
||||
{
|
||||
error_printf("Failed to allocate memory : %d", errno);
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
tmp->data = data;
|
||||
|
||||
if(linked_list_push_front_elem(linked_list, tmp)) return EXIT_FAILURE;
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
int linked_list_pop_back(linked_list_t *linked_list)
|
||||
{
|
||||
assert("Linked list cannot be NULL" && linked_list);
|
||||
|
||||
elem_t *tmp = linked_list->last;
|
||||
if(!tmp)
|
||||
elem_t *elem = linked_list->last;
|
||||
if(!elem)
|
||||
{
|
||||
error_printf("No elem to pop back.");
|
||||
return EXIT_FAILURE;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
linked_list->last = tmp->prev;
|
||||
linked_list->last = elem->prev;
|
||||
|
||||
if(linked_list->last)
|
||||
linked_list->last->next = NULL;
|
||||
else
|
||||
linked_list->first = NULL;
|
||||
|
||||
destroy_elem(tmp, linked_list->elem_deleter);
|
||||
|
||||
linked_list->size--;
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
return elem;
|
||||
}
|
||||
|
||||
int linked_list_pop_front(linked_list_t *linked_list)
|
||||
elem_t *linked_list_pop_front(linked_list_t *linked_list)
|
||||
{
|
||||
assert("Linked list cannot be NULL" && linked_list);
|
||||
|
||||
elem_t *tmp = linked_list->first;
|
||||
if(!tmp)
|
||||
elem_t *elem = linked_list->first;
|
||||
if(!elem)
|
||||
{
|
||||
error_printf("No elem to pop front.");
|
||||
return EXIT_FAILURE;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
linked_list->first = tmp->next;
|
||||
linked_list->first = elem->next;
|
||||
|
||||
if(linked_list->first)
|
||||
linked_list->first->prev = NULL;
|
||||
else
|
||||
linked_list->last = NULL;
|
||||
|
||||
destroy_elem(tmp, linked_list->elem_deleter);
|
||||
|
||||
linked_list->size--;
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
return elem;
|
||||
}
|
||||
|
||||
void linked_list_clear(linked_list_t *linked_list)
|
||||
int linked_list_clear(linked_list_t *linked_list)
|
||||
{
|
||||
assert("Linked list cannot be NULL" && linked_list);
|
||||
|
||||
elem_t *actual_elem = linked_list->first;
|
||||
elem_t *current_elem = linked_list->first;
|
||||
elem_t *tmp;
|
||||
|
||||
while(actual_elem)
|
||||
while(current_elem)
|
||||
{
|
||||
tmp = actual_elem;
|
||||
tmp = current_elem;
|
||||
|
||||
actual_elem = actual_elem->next;
|
||||
current_elem = current_elem->next;
|
||||
|
||||
destroy_elem(tmp, linked_list->elem_deleter);
|
||||
if(destroy_elem(linked_list, tmp)) return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
linked_list->first = NULL;
|
||||
linked_list->last = NULL;
|
||||
|
||||
linked_list->size = 0;
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
inline bool linked_list_is_empty(const linked_list_t *linked_list)
|
||||
|
|
@ -213,18 +247,11 @@ inline bool linked_list_is_empty(const linked_list_t *linked_list)
|
|||
return !linked_list->first;
|
||||
}
|
||||
|
||||
inline bool linked_list_is_in_bound(const linked_list_t *linked_list, size_t index)
|
||||
elem_t *linked_list_get(const linked_list_t *linked_list, size_t index)
|
||||
{
|
||||
assert("Linked list cannot be NULL" && linked_list);
|
||||
|
||||
return index < linked_list->size;
|
||||
}
|
||||
|
||||
elem_t *linked_list_get_elem(const linked_list_t *linked_list, size_t index)
|
||||
{
|
||||
assert("Linked list cannot be NULL" && linked_list);
|
||||
|
||||
if(!linked_list_is_in_bound(linked_list, index))
|
||||
if(index >= linked_list->size)
|
||||
{
|
||||
error_printf("List index out of range.");
|
||||
return NULL;
|
||||
|
|
@ -235,31 +262,18 @@ elem_t *linked_list_get_elem(const linked_list_t *linked_list, size_t index)
|
|||
if(index == linked_list->size - 1)
|
||||
return linked_list->last;
|
||||
|
||||
elem_t *actual_elem = linked_list->first;
|
||||
if(!actual_elem) return NULL;
|
||||
elem_t *current_elem = linked_list->first;
|
||||
if(!current_elem) return NULL;
|
||||
|
||||
for (size_t i = 0; i < index; i++)
|
||||
{
|
||||
actual_elem = actual_elem->next;
|
||||
current_elem = current_elem->next;
|
||||
}
|
||||
|
||||
return actual_elem;
|
||||
return current_elem;
|
||||
}
|
||||
|
||||
void *linked_list_get(const linked_list_t *linked_list, size_t index)
|
||||
{
|
||||
assert("Linked list cannot be NULL" && linked_list);
|
||||
|
||||
elem_t *tmp = linked_list_get_elem(linked_list, index);
|
||||
if(!tmp)
|
||||
{
|
||||
error_printf("Failed to get elem.");
|
||||
return NULL;
|
||||
}
|
||||
return tmp->data;
|
||||
}
|
||||
|
||||
int linked_list_insert_elem(linked_list_t *linked_list, elem_t *elem, size_t index)
|
||||
int linked_list_insert(linked_list_t *linked_list, elem_t *elem, size_t index) // XXX TODO SIMPLIFY INSERT FUNC XXX //
|
||||
{
|
||||
assert("Linked list cannot be NULL" && linked_list);
|
||||
|
||||
|
|
@ -277,14 +291,14 @@ int linked_list_insert_elem(linked_list_t *linked_list, elem_t *elem, size_t ind
|
|||
|
||||
if(index == 0)
|
||||
{
|
||||
return linked_list_push_front_elem(linked_list, elem);
|
||||
return linked_list_push_front(linked_list, elem);
|
||||
}
|
||||
else if(index == linked_list->size)
|
||||
{
|
||||
return linked_list_push_back_elem(linked_list, elem);
|
||||
return linked_list_push_back(linked_list, elem);
|
||||
}
|
||||
|
||||
elem_t *next_insert_elem = linked_list_get_elem(linked_list, index);
|
||||
elem_t *next_insert_elem = linked_list_get(linked_list, index);
|
||||
if(!next_insert_elem) return EXIT_FAILURE;
|
||||
elem_t *prev_insert_elem = next_insert_elem->prev;
|
||||
|
||||
|
|
@ -299,22 +313,7 @@ int linked_list_insert_elem(linked_list_t *linked_list, elem_t *elem, size_t ind
|
|||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
int linked_list_insert(linked_list_t *linked_list, void *data, size_t index)
|
||||
{
|
||||
assert("Linked list cannot be NULL" && linked_list);
|
||||
|
||||
elem_t *tmp = malloc(sizeof(elem_t));
|
||||
if(!tmp)
|
||||
{
|
||||
error_printf("Failed to allocate memory : %d", errno);
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
tmp->data = data;
|
||||
|
||||
return linked_list_insert_elem(linked_list, tmp, index);
|
||||
}
|
||||
|
||||
int linked_list_remove_elem(linked_list_t *linked_list, elem_t *elem)
|
||||
int linked_list_remove(linked_list_t *linked_list, elem_t *elem)
|
||||
{
|
||||
assert("Linked list cannot be NULL" && linked_list);
|
||||
|
||||
|
|
@ -324,39 +323,20 @@ int linked_list_remove_elem(linked_list_t *linked_list, elem_t *elem)
|
|||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
if(elem == linked_list->first)
|
||||
{
|
||||
return linked_list_pop_front(linked_list);
|
||||
}
|
||||
else if(elem == linked_list->last)
|
||||
{
|
||||
return linked_list_pop_back(linked_list);
|
||||
}
|
||||
|
||||
elem_t *prev_elem = elem->prev;
|
||||
elem_t *next_elem = elem->next;
|
||||
|
||||
prev_elem->next = next_elem;
|
||||
next_elem->prev = prev_elem;
|
||||
if(prev_elem) prev_elem->next = next_elem;
|
||||
if(next_elem) next_elem->prev = prev_elem;
|
||||
|
||||
destroy_elem(elem, linked_list->elem_deleter);
|
||||
if(destroy_elem(linked_list, elem)) return EXIT_FAILURE;
|
||||
|
||||
linked_list->size--;
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
int linked_list_remove(linked_list_t *linked_list, size_t index)
|
||||
{
|
||||
assert("Linked list cannot be NULL" && linked_list);
|
||||
|
||||
elem_t *tmp = linked_list_get_elem(linked_list, index);
|
||||
if(!tmp) return EXIT_FAILURE;
|
||||
|
||||
return linked_list_remove_elem(linked_list, tmp);
|
||||
}
|
||||
|
||||
elem_t *linked_list_get_elem_if(const linked_list_t *linked_list, const condition_t condition, ...)
|
||||
elem_t *linked_list_get_if(const linked_list_t *linked_list, const condition_t condition, ...)
|
||||
{
|
||||
assert("Linked list cannot be NULL" && linked_list);
|
||||
assert("Condition cannot be NULL" && condition);
|
||||
|
|
@ -364,63 +344,27 @@ elem_t *linked_list_get_elem_if(const linked_list_t *linked_list, const conditio
|
|||
va_list args;
|
||||
va_start(args, condition);
|
||||
|
||||
elem_t *actual_elem = linked_list->first;
|
||||
elem_t *current_elem = linked_list->first;
|
||||
elem_t *next_elem;
|
||||
|
||||
while(actual_elem)
|
||||
while(current_elem)
|
||||
{
|
||||
next_elem = actual_elem->next;
|
||||
next_elem = current_elem->next;
|
||||
|
||||
va_list args_copy;
|
||||
va_copy(args_copy, args);
|
||||
|
||||
if(condition(actual_elem, args_copy))
|
||||
if(condition(current_elem, args_copy))
|
||||
{
|
||||
va_end(args_copy);
|
||||
va_end(args);
|
||||
|
||||
return actual_elem;
|
||||
return current_elem;
|
||||
}
|
||||
|
||||
va_end(args_copy);
|
||||
|
||||
actual_elem = next_elem;
|
||||
}
|
||||
|
||||
va_end(args);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void *linked_list_get_if(const linked_list_t *linked_list, const condition_t condition, ...)
|
||||
{
|
||||
assert("Linked list cannot be NULL" && linked_list);
|
||||
assert("Condition cannot be NULL" && condition);
|
||||
|
||||
va_list args;
|
||||
va_start(args, condition);
|
||||
|
||||
elem_t *actual_elem = linked_list->first;
|
||||
elem_t *next_elem;
|
||||
|
||||
while(actual_elem)
|
||||
{
|
||||
next_elem = actual_elem->next;
|
||||
|
||||
va_list args_copy;
|
||||
va_copy(args_copy, args);
|
||||
|
||||
if(condition(actual_elem, args_copy))
|
||||
{
|
||||
va_end(args_copy);
|
||||
va_end(args);
|
||||
|
||||
return actual_elem->data;
|
||||
}
|
||||
|
||||
va_end(args_copy);
|
||||
|
||||
actual_elem = next_elem;
|
||||
current_elem = next_elem;
|
||||
}
|
||||
|
||||
va_end(args);
|
||||
|
|
@ -448,7 +392,7 @@ int linked_list_remove_if(linked_list_t *linked_list, const condition_t conditio
|
|||
|
||||
if(condition(actual_elem, args_copy))
|
||||
{
|
||||
if(linked_list_remove_elem(linked_list, actual_elem))
|
||||
if(linked_list_remove(linked_list, actual_elem))
|
||||
{
|
||||
va_end(args_copy);
|
||||
va_end(args);
|
||||
|
|
@ -475,14 +419,14 @@ int linked_list_for_each(const linked_list_t *linked_list, const action_t action
|
|||
va_list args;
|
||||
va_start(args, action);
|
||||
|
||||
elem_t *actual_elem = linked_list->first;
|
||||
elem_t *current_elem = linked_list->first;
|
||||
|
||||
while(actual_elem)
|
||||
while(current_elem)
|
||||
{
|
||||
va_list args_copy;
|
||||
va_copy(args_copy, args);
|
||||
|
||||
if(action(actual_elem, args_copy))
|
||||
if(action(current_elem, args_copy))
|
||||
{
|
||||
va_end(args_copy);
|
||||
va_end(args);
|
||||
|
|
@ -492,7 +436,7 @@ int linked_list_for_each(const linked_list_t *linked_list, const action_t action
|
|||
|
||||
va_end(args_copy);
|
||||
|
||||
actual_elem = actual_elem->next;
|
||||
current_elem = current_elem->next;
|
||||
}
|
||||
|
||||
va_end(args);
|
||||
|
|
|
|||
Loading…
Reference in New Issue