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;