Compare commits
2 Commits
457de07ecb
...
b1dd9baf98
| Author | SHA1 | Date |
|---|---|---|
|
|
b1dd9baf98 | |
|
|
4b5babd9b9 |
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -33,8 +33,6 @@ inline int display_init(void)
|
|||
for(int i = 0; i < NB_DRIVERS; i++)
|
||||
debug_printf("%d : %s", i, SDL_GetRenderDriver(i));
|
||||
|
||||
const char *DRIVERS = "vulkan,gpu,software";
|
||||
|
||||
warning_printf("This build of 2D_Engine_C only support the following drivers : %s", DRIVERS);
|
||||
|
||||
renderer = SDL_CreateRenderer(window, DRIVERS);
|
||||
|
|
|
|||
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;
|
||||
|
|
|
|||
|
|
@ -10,6 +10,9 @@
|
|||
#define DISPLAY_HEIGHT 224
|
||||
#define RENDER_SCALE 2
|
||||
|
||||
#define DRIVERS "vulkan,gpu,software"
|
||||
|
||||
|
||||
extern SDL_Window *window;
|
||||
extern SDL_Renderer *renderer;
|
||||
|
||||
|
|
|
|||
|
|
@ -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