Some updates regarding asset management

Had an idea of self-cleaning the cache but it didn't hold. Leaving the
stuff I wrote that might not be useless in the future.
This commit is contained in:
Linus Probert 2018-05-06 13:27:29 +02:00
parent da75ccde23
commit 9d7669fd35
7 changed files with 179 additions and 11 deletions

View File

@ -134,12 +134,66 @@ ht_get(Hashtable *table, const char *key)
return entry->value; 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 void
ht_destroy(Hashtable *table) ht_destroy(Hashtable *table)
{ {
ht_destroy_custom(table, free); 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 void
ht_destroy_custom(Hashtable *table, void (*destroy_value)(void *)) ht_destroy_custom(Hashtable *table, void (*destroy_value)(void *))
{ {

View File

@ -36,6 +36,10 @@ void ht_set(Hashtable*, const char *key, void *val);
void* ht_get(Hashtable*, const char *key); 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(Hashtable*);
void ht_destroy_custom(Hashtable*, void (*destroy_value)(void*)); void ht_destroy_custom(Hashtable*, void (*destroy_value)(void*));

View File

@ -32,6 +32,8 @@ texture_create(void)
t->dim.width = 0; t->dim.width = 0;
t->texture = NULL; t->texture = NULL;
t->font = NULL; t->font = NULL;
t->lastAccess = SDL_GetTicks();
t->path = "";
return t; return t;
} }
@ -65,6 +67,9 @@ texture_load_from_file(Texture *texture,
SDL_GetError()); SDL_GetError());
} }
texture->lastAccess = SDL_GetTicks();
texture->path = path;
SDL_FreeSurface(surface); SDL_FreeSurface(surface);
} }
@ -82,6 +87,7 @@ texture_load_font(Texture *t, const char *path, unsigned int size)
TTF_GetError()); TTF_GetError());
return; return;
} }
t->path = path;
} }
static void static void
@ -120,6 +126,7 @@ texture_load_from_text(Texture *t,
} }
load_from_surface(t, surface, renderer); load_from_surface(t, surface, renderer);
t->lastAccess = SDL_GetTicks();
} }
void void
@ -169,6 +176,8 @@ texture_render_clip(Texture *texture, SDL_Rect *box, SDL_Rect *clip, Camera *cam
texture->texture, texture->texture,
clip, clip,
box); box);
texture->lastAccess = SDL_GetTicks();
} }
void void
@ -184,6 +193,8 @@ texture_render_clip_ex(Texture *texture, SDL_Rect *box, SDL_Rect *clip, double a
angle, angle,
point, point,
flipType); flipType);
texture->lastAccess = SDL_GetTicks();
} }
void texture_destroy(Texture *texture) void texture_destroy(Texture *texture)

View File

@ -29,6 +29,8 @@ typedef struct {
SDL_Texture *texture; SDL_Texture *texture;
TTF_Font *font; TTF_Font *font;
Dimension dim; Dimension dim;
const char *path;
unsigned long lastAccess;
} Texture; } Texture;
Texture* Texture*

View File

@ -16,12 +16,23 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#include <SDL.h>
#include <assert.h>
#include "texturecache.h" #include "texturecache.h"
#include "hashtable.h" #include "hashtable.h"
#include "defines.h"
#include "util.h" #include "util.h"
#include "timer.h"
static Hashtable *textures = NULL; 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 void
texturecache_init(SDL_Renderer *rend) texturecache_init(SDL_Renderer *rend)
@ -33,30 +44,51 @@ texturecache_init(SDL_Renderer *rend)
Texture* Texture*
texturecache_add(const char *path) texturecache_add(const char *path)
{ {
Texture *t = ht_get(textures, path); TextureContainer *tc = ht_get(textures, path);
if (!t) { if (!tc) {
t = texture_create(); tc = ec_malloc(sizeof(TextureContainer));
texture_load_from_file(t, path, renderer); tc->texture = texture_create();
ht_set(textures, path, t); texture_load_from_file(tc->texture, path, renderer);
ht_set(textures, path, tc);
debug("Cached texture: %s", path); debug("Cached texture: %s", path);
} else { } else {
debug("Retrieved cached texture: %s", path); debug("Retrieved cached texture: %s", path);
} }
return t; return tc->texture;
} }
Texture* Texture*
texturecache_get(const char *path) texturecache_get(const char *path)
{ {
Texture *t = ht_get(textures, path); TextureContainer *tc = ht_get(textures, path);
if (!t) if (!tc)
fatal("Texture not loaded: %s", path); 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 void
texturecache_close(void) texturecache_close(void)
{ {
ht_destroy_custom(textures, (void(*)(void*)) texture_destroy); ht_destroy_custom(textures, (void(*)(void*)) texturecache_texture_container_destroy);
} }

View File

@ -31,6 +31,9 @@ texturecache_add(const char *path);
Texture* Texture*
texturecache_get(const char *path); texturecache_get(const char *path);
bool
texturecache_remove(Texture **texture);
void void
texturecache_close(void); texturecache_close(void);

View File

@ -17,6 +17,8 @@
*/ */
#include <check.h> #include <check.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include "../src/hashtable.h" #include "../src/hashtable.h"
@ -76,6 +78,64 @@ START_TEST(test_hashtable_set_get)
} }
END_TEST 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) static Suite* t_suite_create(void)
{ {
Suite *s; 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_create);
tcase_add_test(tc_core, test_hashtable_set_get); 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); suite_add_tcase(s, tc_core);
return s; return s;