diff --git a/src/hashtable.c b/src/hashtable.c index bdfa6d3..513d596 100644 --- a/src/hashtable.c +++ b/src/hashtable.c @@ -134,12 +134,66 @@ ht_get(Hashtable *table, const char *key) return entry->value; } +void* +ht_remove(Hashtable *table, const char *key) +{ + unsigned int hashkey = 0; + Entry *entry, *last; + + hashkey = hash(table, key); + + entry = table->entries[hashkey]; + last = NULL; + + while (entry && entry->key && strcmp(entry->key, key) < 0) { + last = entry; + entry = entry->next; + } + + if (!entry || !entry->key || strcmp(entry->key, key) != 0) { + return NULL; + } + + if (last == NULL) { + table->entries[hashkey] = entry->next; + } else { + last->next = entry->next; + } + + void *value = entry->value; + free(entry->key); + free(entry); + + return value; +} + void ht_destroy(Hashtable *table) { ht_destroy_custom(table, free); } +void +ht_foreach(Hashtable *table, void (*func)(void*)) +{ + Entry *entry; + unsigned int i; + + if (table == NULL) { + return; + } + + for (i = 0; i < table->size; ++i) { + entry = table->entries[i]; + if (entry == NULL) + continue; + while (entry) { + func(entry->value); + entry = entry->next; + } + } +} + void ht_destroy_custom(Hashtable *table, void (*destroy_value)(void *)) { diff --git a/src/hashtable.h b/src/hashtable.h index a57c217..62f1f6d 100644 --- a/src/hashtable.h +++ b/src/hashtable.h @@ -36,6 +36,10 @@ void ht_set(Hashtable*, const char *key, void *val); void* ht_get(Hashtable*, const char *key); +void* ht_remove(Hashtable*, const char *key); + +void ht_foreach(Hashtable*, void (*)(void*)); + void ht_destroy(Hashtable*); void ht_destroy_custom(Hashtable*, void (*destroy_value)(void*)); diff --git a/src/texture.c b/src/texture.c index 6a68672..d920c5f 100644 --- a/src/texture.c +++ b/src/texture.c @@ -32,6 +32,8 @@ texture_create(void) t->dim.width = 0; t->texture = NULL; t->font = NULL; + t->lastAccess = SDL_GetTicks(); + t->path = ""; return t; } @@ -65,6 +67,9 @@ texture_load_from_file(Texture *texture, SDL_GetError()); } + texture->lastAccess = SDL_GetTicks(); + texture->path = path; + SDL_FreeSurface(surface); } @@ -82,6 +87,7 @@ texture_load_font(Texture *t, const char *path, unsigned int size) TTF_GetError()); return; } + t->path = path; } static void @@ -120,6 +126,7 @@ texture_load_from_text(Texture *t, } load_from_surface(t, surface, renderer); + t->lastAccess = SDL_GetTicks(); } void @@ -169,6 +176,8 @@ texture_render_clip(Texture *texture, SDL_Rect *box, SDL_Rect *clip, Camera *cam texture->texture, clip, box); + + texture->lastAccess = SDL_GetTicks(); } void @@ -184,6 +193,8 @@ texture_render_clip_ex(Texture *texture, SDL_Rect *box, SDL_Rect *clip, double a angle, point, flipType); + + texture->lastAccess = SDL_GetTicks(); } void texture_destroy(Texture *texture) diff --git a/src/texture.h b/src/texture.h index 1c94d99..489a01a 100644 --- a/src/texture.h +++ b/src/texture.h @@ -29,6 +29,8 @@ typedef struct { SDL_Texture *texture; TTF_Font *font; Dimension dim; + const char *path; + unsigned long lastAccess; } Texture; Texture* diff --git a/src/texturecache.c b/src/texturecache.c index 31e6771..a1dcf76 100644 --- a/src/texturecache.c +++ b/src/texturecache.c @@ -16,12 +16,23 @@ * along with this program. If not, see . */ +#include +#include #include "texturecache.h" #include "hashtable.h" +#include "defines.h" #include "util.h" +#include "timer.h" static Hashtable *textures = NULL; -static SDL_Renderer *renderer; +static SDL_Renderer *renderer = NULL; + +typedef struct TexureContainer { + Texture *texture; +} TextureContainer; + +static void +texturecache_texture_container_destroy(TextureContainer *); void texturecache_init(SDL_Renderer *rend) @@ -33,30 +44,51 @@ texturecache_init(SDL_Renderer *rend) Texture* texturecache_add(const char *path) { - Texture *t = ht_get(textures, path); - if (!t) { - t = texture_create(); - texture_load_from_file(t, path, renderer); - ht_set(textures, path, t); + TextureContainer *tc = ht_get(textures, path); + if (!tc) { + tc = ec_malloc(sizeof(TextureContainer)); + tc->texture = texture_create(); + texture_load_from_file(tc->texture, path, renderer); + ht_set(textures, path, tc); debug("Cached texture: %s", path); } else { debug("Retrieved cached texture: %s", path); } - return t; + return tc->texture; } Texture* texturecache_get(const char *path) { - Texture *t = ht_get(textures, path); - if (!t) + TextureContainer *tc = ht_get(textures, path); + if (!tc) fatal("Texture not loaded: %s", path); - return t; + + return tc->texture; +} + +bool +texturecache_remove(Texture **texture) +{ + TextureContainer *tc = ht_get(textures, (*texture)->path); + if (!tc) + return false; + assert(tc->texture == *texture); + texturecache_texture_container_destroy(tc); + *texture = NULL; + return true; +} + +static void +texturecache_texture_container_destroy(TextureContainer *tc) +{ + texture_destroy(tc->texture); + free(tc); } void texturecache_close(void) { - ht_destroy_custom(textures, (void(*)(void*)) texture_destroy); + ht_destroy_custom(textures, (void(*)(void*)) texturecache_texture_container_destroy); } diff --git a/src/texturecache.h b/src/texturecache.h index 2ea1389..e5ac78a 100644 --- a/src/texturecache.h +++ b/src/texturecache.h @@ -31,6 +31,9 @@ texturecache_add(const char *path); Texture* texturecache_get(const char *path); +bool +texturecache_remove(Texture **texture); + void texturecache_close(void); diff --git a/test/check_hashtable.c b/test/check_hashtable.c index a87c886..1c1c70c 100644 --- a/test/check_hashtable.c +++ b/test/check_hashtable.c @@ -17,6 +17,8 @@ */ #include +#include +#include #include #include "../src/hashtable.h" @@ -76,6 +78,64 @@ START_TEST(test_hashtable_set_get) } END_TEST +static bool checklist[] = { + false, + false, + false, + false, + false, + false, + false, + false, + false, + false +}; + +static void check_number(int *num) +{ + checklist[*num] = true; +} + +START_TEST(test_hashtable_foreach) +{ + Hashtable *table = ht_create(10); + + for (int i = 0; i < 10; i++) { + char str[4]; + int *num = malloc(sizeof(int)); + ck_assert( num != NULL ); + *num = i; + sprintf(str, "%d", *num); + ht_set(table, str, num); + } + + ht_foreach(table, (void (*)(void*)) check_number); + for (int i = 0; i < 10; i++) { + ck_assert(checklist[i]); + } +} +END_TEST + +START_TEST(test_hashtable_remove) +{ + char key1[] = "key1"; + char value1[] = "value1"; + char key2[] = "key2"; + char value2[] = "value2"; + char key3[] = "key3"; + char value3[] = "value3"; + char *getVal; + + Hashtable *table = ht_create(10); + ht_set(table, key1, value1); + ht_set(table, key2, value2); + ht_set(table, key3, value3); + getVal = ht_remove(table, key2); + ck_assert(strcmp(value2, getVal) == 0); + ck_assert(ht_get(table, key2) == NULL); +} +END_TEST + static Suite* t_suite_create(void) { Suite *s; @@ -86,6 +146,8 @@ static Suite* t_suite_create(void) tcase_add_test(tc_core, test_hashtable_create); tcase_add_test(tc_core, test_hashtable_set_get); + tcase_add_test(tc_core, test_hashtable_foreach); + tcase_add_test(tc_core, test_hashtable_remove); suite_add_tcase(s, tc_core); return s;