Moved ecs.c into core and added much better error and debug handling.

This commit is contained in:
Ulysse Cura 2026-07-24 03:23:53 +02:00
parent 50abbec84b
commit 011e960cfc
21 changed files with 83 additions and 638 deletions

6
.ccls
View File

@ -1,9 +1,9 @@
gcc gcc
# Headers # Headers
-Isrc/headers -Isrc/components/headers
-Isrc/ecs/headers
-Isrc/ecs/components/headers
-ISDL2_Core/src/headers -ISDL2_Core/src/headers
#-INCurses_Core/src/headers #-INCurses_Core/src/headers
-Iassets/asset_builder/src/headers -Iassets/asset_builder/src/headers
# Macros
-DASSET_FILE_NAME="$(make print-ASSET_OUTPUT)" -DASSET_FILE_NAME="$(make print-ASSET_OUTPUT)"
-DDEBUG=1

View File

@ -4,13 +4,13 @@ SHELL = /usr/bin/env bash
BUILD_DIR = build BUILD_DIR = build
# Source output target name # Source output target name
SOURCE_OUTPUT := $(BUILD_DIR)/2D_Engine SOURCE_OUTPUT = $(BUILD_DIR)/2D_Engine
# Core output target name # Core output target name
CORE_OUTPUT := $(BUILD_DIR)/libcore.a CORE_OUTPUT = $(BUILD_DIR)/libcore.a
# Assets output # Assets output
ASSET_OUTPUT := $(BUILD_DIR)/game.data ASSET_OUTPUT = $(BUILD_DIR)/game.data
# Verbosity # Verbosity
Q := @ Q := @

@ -1 +0,0 @@
Subproject commit 911bdd7999a5c8af912ea3d23ba86140541fd064

@ -1 +1 @@
Subproject commit d193aa5fd49666be31f2b97e6dcc9a0788d58d7d Subproject commit 2e1eaf4c1c512761c7585267175bed420154172d

View File

@ -1,12 +1,10 @@
# Source files # Source files
SOURCES := \ SOURCES := \
main.c \
game.c \ game.c \
ecs/ecs.c \ components/transform_component.c \
ecs/components/transform_component.c \ components/sprite_component.c \
ecs/components/sprite_component.c \ components/animation_system.c \
ecs/components/animation_system.c \ components/player_system.c
ecs/components/player_system.c
# Compiler and flags # Compiler and flags
SRC_CC = gcc SRC_CC = gcc
@ -23,7 +21,7 @@ SRC_CFLAGS = --std=c17 --pedantic -O0 -g \
-Wold-style-definition # DEVELOPEMENT -Wold-style-definition # DEVELOPEMENT
endif endif
SRC_INCLUDE_DIRS = $(SOURCE_DIR)/headers $(SOURCE_DIR)/ecs/headers $(SOURCE_DIR)/ecs/components/headers $(CORE_DIR)/headers SRC_INCLUDE_DIRS = $(SOURCE_DIR)/components/headers $(CORE_DIR)/headers
SRC_INCLUDE_DIRS := $(addprefix -I, $(SRC_INCLUDE_DIRS)) SRC_INCLUDE_DIRS := $(addprefix -I, $(SRC_INCLUDE_DIRS))
SRC_LDFLAGS = SRC_LDFLAGS =

View File

@ -1,6 +1,8 @@
#include "memory_alloc.h"
#include "animation_system.h" #include "animation_system.h"
#include "game.h" #include "game.h"
#include "memory_alloc.h"
#include "errors.h"
// Args : size_t nb_frames, size_t actual_frame, float frame_delay_ms, bool play, bool loop, bool reverse // Args : size_t nb_frames, size_t actual_frame, float frame_delay_ms, bool play, bool loop, bool reverse
void animation_system_init(component_t *component, va_list args) void animation_system_init(component_t *component, va_list args)
@ -8,6 +10,7 @@ void animation_system_init(component_t *component, va_list args)
animation_system_data_t *system_data = component->component_data; animation_system_data_t *system_data = component->component_data;
system_data->sprite_component_data = get_component(component->entity, SPRITE_COMPONENT)->component_data; system_data->sprite_component_data = get_component(component->entity, SPRITE_COMPONENT)->component_data;
if(!system_data->sprite_component_data) return;
system_data->nb_frames = va_arg(args, size_t); system_data->nb_frames = va_arg(args, size_t);
system_data->actual_frame_nb= va_arg(args, size_t); system_data->actual_frame_nb= va_arg(args, size_t);
@ -106,9 +109,10 @@ void animation_system_create_frames_clips(animation_system_data_t *system_data)
inline void animation_system_change_animation(animation_system_data_t *system_data, const char *name, size_t nb_frames) inline void animation_system_change_animation(animation_system_data_t *system_data, const char *name, size_t nb_frames)
{ {
sprite_component_set_texture(system_data->sprite_component_data, name); system_data->sprite_component_data->texture = asset_manager_get_texture(&game.asset_manager, name);
system_data->sprite_component_data->src_rect = *(rect_t *)system_data->actual_frame->data;
system_data->nb_frames = nb_frames; system_data->nb_frames = nb_frames;
animation_system_create_frames_clips(system_data); animation_system_create_frames_clips(system_data);
system_data->sprite_component_data->src_rect = *(rect_t *)system_data->actual_frame->data;
} }

View File

@ -7,12 +7,12 @@
typedef struct animation_system_data_t { typedef struct animation_system_data_t {
sprite_component_data_t *sprite_component_data; sprite_component_data_t *sprite_component_data;
elem_t *actual_frame;
size_t actual_frame_nb;
size_t nb_frames; size_t nb_frames;
linked_list_t frames; linked_list_t frames;
elem_t *actual_frame;
size_t actual_frame_nb;
float frame_delay_ms; float frame_delay_ms;
float frame_timer_ms; float frame_timer_ms;

View File

@ -20,10 +20,8 @@ void sprite_component_init(component_t *, va_list);
void sprite_component_update(component_t *); void sprite_component_update(component_t *);
void sprite_component_draw(component_t *); int sprite_component_draw(component_t *);
void sprite_component_destroy(component_t *); void sprite_component_destroy(component_t *);
void sprite_component_set_texture(sprite_component_data_t *, const char *);
#endif // SPRITE_COMPONENT_H #endif // SPRITE_COMPONENT_H

View File

@ -1,9 +1,10 @@
#include "memory_alloc.h"
#include "player_system.h" #include "player_system.h"
#include "game.h"
#include "memory_alloc.h"
#include "animation_system.h" #include "animation_system.h"
#include "sprite_component.h" #include "sprite_component.h"
#include "transform_component.h" #include "transform_component.h"
#include "game.h"
// No args // No args
void player_system_init(component_t *component, va_list args __attribute__((unused))) void player_system_init(component_t *component, va_list args __attribute__((unused)))
@ -15,9 +16,6 @@ void player_system_init(component_t *component, va_list args __attribute__((unus
system_data->transform_component_data = system_data->sprite_component_data->transform_component_data; system_data->transform_component_data = system_data->sprite_component_data->transform_component_data;
system_data->state = PLAYER_IDLE; system_data->state = PLAYER_IDLE;
asset_manager_load_asset(&game.asset_manager, "player_idle_sheet", ASSET_TEXTURE);
asset_manager_load_asset(&game.asset_manager, "player_walk_sheet", ASSET_TEXTURE);
} }
// Only for this file // Only for this file
@ -87,7 +85,5 @@ void player_system_update(component_t *component)
void player_system_destroy(component_t *component) void player_system_destroy(component_t *component)
{ {
asset_manager_let_go_asset(&game.asset_manager, "player_idle_sheet");
asset_manager_let_go_asset(&game.asset_manager, "player_walk_sheet");
free(component->component_data); free(component->component_data);
} }

View File

@ -15,7 +15,7 @@ void sprite_component_init(component_t *component, va_list args)
component_data->flip = false; component_data->flip = false;
sprite_component_set_texture(component_data, va_arg(args, const char *)); component_data->texture = asset_manager_get_texture(&game.asset_manager, va_arg(args, const char *));
} }
inline void sprite_component_update(component_t *component) inline void sprite_component_update(component_t *component)
@ -24,18 +24,15 @@ inline void sprite_component_update(component_t *component)
frect_to_rect(&component_data->transform_component_data->bounds, &component_data->dst_rect); frect_to_rect(&component_data->transform_component_data->bounds, &component_data->dst_rect);
} }
inline void sprite_component_draw(component_t *component) inline int sprite_component_draw(component_t *component)
{ {
sprite_component_data_t *component_data = component->component_data; sprite_component_data_t *component_data = component->component_data;
asset_manager_draw_texture(component_data->texture, &component_data->src_rect, &component_data->dst_rect, component_data->flip); if(asset_manager_draw_texture(component_data->texture, &component_data->src_rect, &component_data->dst_rect, component_data->flip)) return EXIT_FAILURE;
return EXIT_SUCCESS;
} }
inline void sprite_component_destroy(component_t *component) inline void sprite_component_destroy(component_t *component)
{ {
free(component->component_data); free(component->component_data);
} }
inline void sprite_component_set_texture(sprite_component_data_t *component_data, const char *name)
{
component_data->texture = asset_manager_get_texture(&game.asset_manager, name);
}

View File

@ -1,163 +0,0 @@
#include <stdarg.h>
#include "memory_alloc.h"
#include "ecs.h"
#include "components.h"
component_t *create_component(component_type_t component_type)
{
component_t *component = malloc(sizeof(component_t));
component->component_type = component_type;
switch(component_type)
{
#define COMPONENT(NAME, PREFIX, DRAW) \
case NAME: \
component->component_init = PREFIX##_init; \
component->component_update = PREFIX##_update; \
component->component_draw = DRAW(PREFIX); \
component->component_data = malloc(sizeof(PREFIX##_data_t)); \
if(!component->component_data){ free(component); return NULL; } \
component->component_deleter = PREFIX##_destroy; \
break;
#include "components.def"
default:
free(component);
return NULL;
}
return component;
}
inline void destroy_component(component_t *component)
{
component->component_deleter(component);
free(component);
}
entity_t *create_entity(const unsigned int id)
{
entity_t *entity = malloc(sizeof(entity_t));
if(!entity) return NULL;
entity->id = id;
entity->draw_priority = 0;
linked_list_init(&entity->components, sizeof(component_t), (deleter_t)destroy_component);
return entity;
}
void add_component(entity_t *entity, component_t *component, ...)
{
if(!component) return;
component->entity = entity;
va_list args, args_copy;
va_start(args, component);
va_copy(args_copy, args);
component->component_init(component, args_copy);
va_end(args_copy);
va_end(args);
linked_list_push_back(&entity->components, component);
}
// Only for this file
// Arg : component_type_t component_type
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)
{
return linked_list_get_if(&entity->components, condition_is_component_type, component_type);
}
// Only for this file
// No args
static inline void action_update_component(elem_t *elem, va_list args __attribute__((unused)))
{
component_t *component = elem->data;
component->component_update(component);
}
inline void update_entity(entity_t *entity)
{
linked_list_for_each(&entity->components, action_update_component);
}
// Only for this file
// No args
static inline void action_draw_component(elem_t *elem, va_list args __attribute__((unused)))
{
component_t *component = elem->data;
if(component->component_draw) component->component_draw(component);
}
inline void draw_entity(entity_t *entity)
{
linked_list_for_each(&entity->components, action_draw_component);
}
inline void destroy_entity(entity_t *entity)
{
linked_list_clear(&entity->components);
free(entity);
}
inline void entity_manager_init(entity_manager_t *entity_manager)
{
linked_list_init(&entity_manager->entities, sizeof(entity_t), (deleter_t)destroy_entity);
}
inline void entity_manager_add_entity(entity_manager_t *entity_manager, entity_t *entity)
{
linked_list_push_back(&entity_manager->entities, entity);
}
// Only for this file
// No args
static inline void action_update_entity(elem_t *elem, va_list args __attribute__((unused)))
{
update_entity((entity_t *)elem->data);
}
inline void entity_manager_update(entity_manager_t *entity_manager)
{
linked_list_for_each(&entity_manager->entities, action_update_entity);
}
// Only for this file
// No args
static inline void action_draw_entity(elem_t *elem, va_list args __attribute__((unused)))
{
draw_entity((entity_t *)elem->data);
}
inline void entity_manager_draw(entity_manager_t *entity_manager)
{
linked_list_for_each(&entity_manager->entities, action_draw_entity);
}
// Only for this file
// Arg : unsigned int id
static inline bool condition_is_entity_name(elem_t *elem, va_list args)
{
return ((entity_t *)elem->data)->id == va_arg(args, unsigned int);
}
inline void entity_manager_remove_entity(entity_manager_t *entity_manager, unsigned int id)
{
linked_list_remove_if(&entity_manager->entities, condition_is_entity_name, id);
}
inline void entity_manager_exit(entity_manager_t *entity_manager)
{
linked_list_clear(&entity_manager->entities);
}

View File

@ -1,78 +0,0 @@
#ifndef ECS_H
#define ECS_H
#include <stdarg.h>
#include <stddef.h>
#include "linked_list.h"
typedef enum component_type_t {
#define COMPONENT(NAME, PREFIX, DRAW) NAME,
#include "components.def"
} component_type_t;
// Component forwarding
typedef struct component_t component_t;
// Component init function. It is called when component added to entity. This function is necessary.
typedef void (*component_init_t)(component_t *component, va_list args);
// Component update function. It is called in the main loop to update the component. This function is necessary.
typedef void (*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 void (*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 struct component_t {
component_init_t component_init;
component_update_t component_update;
component_draw_t component_draw;
void *component_data;
component_deleter_t component_deleter;
struct entity_t *entity;
component_type_t component_type;
} component_t;
component_t *create_component(component_type_t component_type);
void destroy_component(component_t *component);
typedef struct entity_t {
unsigned int id;
size_t draw_priority;
linked_list_t components;
} entity_t;
entity_t *create_entity(const unsigned int id);
void add_component(entity_t *entity, component_t *component, ...);
component_t *get_component(entity_t *entity, component_type_t component_type);
void update_entity(entity_t *entity);
void 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);
void entity_manager_add_entity(entity_manager_t *entity_manager, entity_t *entity);
void entity_manager_update(entity_manager_t *entity_manager);
void entity_manager_draw(entity_manager_t *entity_manager);
void entity_manager_remove_entity(entity_manager_t *entity_manager, const unsigned int id);
void entity_manager_exit(entity_manager_t *entity_manager);
#endif // ECS_H

View File

@ -1,15 +1,20 @@
#include <time.h>
#include <event.h>
#include <display.h>
#include <asset_manager.h>
#include "game.h" #include "game.h"
#include <time.h>
#include "display.h"
#include "asset_manager.h"
#include "ecs.h"
#include "components.h" #include "components.h"
void game_init(void) #include <SDL2/SDL_timer.h>
{
display_init();
asset_manager_init(&game.asset_manager); int game_init(void)
{
game.is_running = false;
if(display_init()) return EXIT_FAILURE;
if(asset_manager_init(&game.asset_manager)) return EXIT_FAILURE;
entity_manager_init(&game.entity_manager); entity_manager_init(&game.entity_manager);
entity_t *player = create_entity(0); entity_t *player = create_entity(0);
@ -18,12 +23,24 @@ void game_init(void)
frect_t player_bounds = {10.0f, 10.0f, 32.0f, 32.0f}; frect_t player_bounds = {10.0f, 10.0f, 32.0f, 32.0f};
add_component(player, create_component(TRANSFORM_COMPONENT), player_bounds, PLAYER_DEFAULT_SPEED); if(asset_manager_load_asset(&game.asset_manager, "player_idle_sheet", ASSET_TEXTURE)) return EXIT_FAILURE;
add_component(player, create_component(SPRITE_COMPONENT), "player_idle_sheet"); if(asset_manager_load_asset(&game.asset_manager, "player_walk_sheet", ASSET_TEXTURE)) return EXIT_FAILURE;
add_component(player, create_component(ANIMATION_SYSTEM), 4, 0, PLAYER_DEFAULT_IDLE_ANIMATION_SPEED, true, true, false);
add_component(player, create_component(PLAYER_SYSTEM)); component_t *component = create_component(TRANSFORM_COMPONENT); if(!component) return EXIT_FAILURE;
add_component(player, component, player_bounds, PLAYER_DEFAULT_SPEED);
component = create_component(SPRITE_COMPONENT); if(!component) return EXIT_FAILURE;
add_component(player, component, "player_idle_sheet");
component = create_component(ANIMATION_SYSTEM); if(!component) return EXIT_FAILURE;
add_component(player, component, 4, 0, PLAYER_DEFAULT_IDLE_ANIMATION_SPEED, true, true, false);
component = create_component(PLAYER_SYSTEM); if(!component) return EXIT_FAILURE;
add_component(player, component);
game.is_running = true; game.is_running = true;
return EXIT_SUCCESS;
} }
void game_handle_event(void) void game_handle_event(void)
@ -57,19 +74,36 @@ void game_update(void)
entity_manager_update(&game.entity_manager); entity_manager_update(&game.entity_manager);
} }
void game_render(void) int game_render(void)
{ {
display_clear(); if(display_clear())
{
game.is_running = false;
return EXIT_FAILURE;
}
if(entity_manager_draw(&game.entity_manager))
{
game.is_running = false;
return EXIT_FAILURE;
}
entity_manager_draw(&game.entity_manager);
display_update(); display_update();
return EXIT_SUCCESS;
} }
void game_exit(void) int game_exit(void)
{ {
entity_manager_exit(&game.entity_manager); entity_manager_exit(&game.entity_manager);
asset_manager_exit(&game.asset_manager);
if(asset_manager_let_go_asset(&game.asset_manager, "player_idle_sheet")) return EXIT_FAILURE;
if(asset_manager_let_go_asset(&game.asset_manager, "player_walk_sheet")) return EXIT_FAILURE;
if(asset_manager_exit(&game.asset_manager)) return EXIT_FAILURE;
display_exit(); display_exit();
return EXIT_SUCCESS;
} }

View File

@ -1,12 +0,0 @@
#ifndef EVENTS_H
#define EVENTS_H
#include <keycodes.h>
#include <vector2d.h>
typedef struct events_t {
vector2d_t cursor_pos;
bool keys[MAX_KEYCODES];
} events_t;
#endif // EVENTS_H

View File

@ -1,47 +0,0 @@
#ifndef GAME_H
#define GAME_H
#include <stdbool.h>
#include "events.h"
#include "asset_manager.h"
#include "ecs.h"
/**
* @brief Game data.
* There should be only one instance of this struct.
*
* @param event Events data
* @param texture_manager Texture manager instance
* @param entity_manager Entity manager instance
* @param is_running Game running state
* @param delta_time_ms Frame time
*/
typedef struct game_t {
asset_manager_t asset_manager;
entity_manager_t entity_manager;
events_t events;
float delta_time_ms;
bool is_running;
} game_t;
// Global game instance
extern game_t game;
// Initialise game
void game_init(void);
// Handle event like inputs
void game_handle_event(void);
// Update game
void game_update(void);
// Render game
void game_render(void);
// Free game instance
void game_exit(void);
#endif // GAME_H

View File

@ -1,281 +0,0 @@
#include "game.h"
//#define TEXTURE_TEST
//#define LINKED_LIST_TEST
game_t game;
int main(void)
{
game_init();
while(game.is_running)
{
game_handle_event();
game_update();
game_render();
}
game_exit();
return 0;
}
// Texture Unit Tests
#ifdef TEXTURE_TEST
#include "texture_manager.h"
int main(void)
{
display_clear(C_BLACK);
texture_manager_t texture_manager;
texture_manager_init(&texture_manager);
texture_manager_load_builtin_textures(&texture_manager);
texture_t *texture = texture_manager_get_texture(&texture_manager, "player_run_sheet");
rect_t srcR = {0,0,32,32};
rect_t dstR = srcR;
draw_texture(texture, &src, &dst);
src.x = 33;
dst.x = 33;
draw_texture(texture, &src, &dst);
texture_manager_remove_texture(&texture_manager, "player_run_sheet");
src.w = 128;
dst.x = 0;
dst.y = 33;
texture_manager_draw_texture(&texture_manager, "player_idle_sheet", &src, &dst);
texture_manager_clear(&texture_manager);
display_update();
getkey();
return 1;
}
#endif // TEXTURE_TEST
// Linked List Unit Tests
#ifdef LINKED_LIST_TEST
#include "linked_list.h"
int main(void)
{
display_clear(C_BLACK);
linked_list_t linked_list;
linked_list_init(&linked_list, sizeof(int), NULL);
if(linked_list.first == linked_list.last &&
linked_list.first == NULL)
{
dtext(1, 0, C_BLACK, "linked_list is initialised correctly");
}
else
{
goto Exit;
}
elem_t *elem1 = NULL;
elem_t *elem2 = NULL;
elem_t *elem3 = NULL;
elem_t *elem4 = NULL;
elem1 = elem_create(&linked_list);
if(elem1 && elem1->data)
{
dtext(1, 10, C_BLACK, "elem1 is initalised correctly");
}
else
{
goto Exit;
}
linked_list_push_back_elem(&linked_list, elem1);
if(linked_list.first == linked_list.last &&
linked_list.first == elem1 &&
!linked_list.first->prev &&
!linked_list.first->next &&
!linked_list.last->prev &&
!linked_list.last->next)
{
dtext(1, 20, C_BLACK, "elem1 is correctly pushed back");
}
else
{
goto Exit;
}
linked_list_pop_back(&linked_list);
if(linked_list.first == linked_list.last &&
linked_list.first == NULL)
{
dtext(1, 30, C_BLACK, "elem1 is correctly poped back");
}
else
{
goto Exit;
}
elem1 = elem_create(&linked_list);
elem2 = elem_create(&linked_list);
elem3 = elem_create(&linked_list);
elem4 = elem_create(&linked_list);
linked_list_push_back_elem(&linked_list, elem1);
linked_list_push_back_elem(&linked_list, elem2);
if(linked_list.first == elem1 &&
linked_list.last == elem2 &&
!linked_list.first->prev &&
linked_list.first->next &&
linked_list.last->prev &&
!linked_list.last->next &&
linked_list.first->next == elem2 &&
linked_list.last->prev == elem1)
{
dtext(1, 40, C_BLACK, "elem1 and elem2 are correctly pushed back");
}
else
{
goto Exit;
}
linked_list_push_front_elem(&linked_list, elem3);
linked_list_push_front_elem(&linked_list, elem4);
if(!linked_list.first->prev &&
!linked_list.last->next &&
linked_list.first == elem4 &&
linked_list.first->next == elem3 &&
linked_list.first->next->next == elem1 &&
linked_list.first->next->next->next == elem2 &&
linked_list.last == elem2 &&
linked_list.last->prev == elem1 &&
linked_list.last->prev->prev == elem3 &&
linked_list.last->prev->prev->prev == elem4)
{
dtext(1, 50, C_BLACK, "elem3 and elem4 are correctly pushed front");
}
else
{
goto Exit;
}
if(linked_list_get_elem(&linked_list, 2) == elem1)
{
dtext(1, 60, C_BLACK, "elem4 is got correctly");
}
else
{
goto Exit;
}
linked_list_pop_back(&linked_list);
if(!linked_list.first->prev &&
!linked_list.last->next &&
linked_list.first == elem4 &&
linked_list.first->next == elem3 &&
linked_list.first->next->next == elem1 &&
linked_list.last == elem1 &&
linked_list.last->prev == elem3 &&
linked_list.last->prev->prev == elem4)
{
dtext(1, 70, C_BLACK, "elem2 is correctly poped back");
}
else
{
goto Exit;
}
linked_list_remove(&linked_list, 1);
if(!linked_list.first->prev &&
!linked_list.last->next &&
linked_list.first == elem4 &&
linked_list.first->next == elem1 &&
linked_list.last == elem1 &&
linked_list.last->prev == elem4)
{
dtext(1, 80, C_BLACK, "elem3 is correctly removed");
}
else
{
goto Exit;
}
linked_list_clear(&linked_list);
if(linked_list.first == linked_list.last &&
linked_list.first == NULL)
{
dtext(1, 90, C_BLACK, "linked list is correctly cleared");
}
else
{
goto Exit;
}
elem1 = elem_create(&linked_list);
elem2 = elem_create(&linked_list);
elem3 = elem_create(&linked_list);
elem4 = elem_create(&linked_list);
linked_list_push_back_elem(&linked_list, elem1);
linked_list_push_back_elem(&linked_list, elem2);
linked_list_push_front_elem(&linked_list, elem3);
if(linked_list.first == elem3 &&
linked_list.last == elem2 &&
!linked_list.first->prev &&
linked_list.first->next &&
linked_list.last->prev &&
!linked_list.last->next &&
linked_list.first->next == elem1 &&
linked_list.first->next->next == elem2 &&
linked_list.last->prev == elem1 &&
linked_list.last->prev->prev == elem3)
{
dtext(1, 100, C_BLACK, "elem1, elem2 and elem3 are correctly pushed");
}
else
{
goto Exit;
}
linked_list_insert_elem(&linked_list, elem4, 1);
if(linked_list.first == elem3 &&
linked_list.last == elem2 &&
!linked_list.first->prev &&
linked_list.first->next &&
linked_list.last->prev &&
!linked_list.last->next &&
linked_list.first->next == elem4 &&
linked_list.first->next->next == elem1 &&
linked_list.first->next->next->next == elem2 &&
linked_list.last->prev == elem1 &&
linked_list.last->prev->prev == elem4 &&
linked_list.last->prev->prev->prev == elem3)
{
dtext(1, 110, C_BLACK, "elem3 is correctly inserted");
}
else
{
goto Exit;
}
linked_list_clear(&linked_list);
Exit:
display_update();
getkey();
return 1;
}
#endif // LINKED_LIST_TEST