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:
parent
da75ccde23
commit
9d7669fd35
|
@ -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 *))
|
||||||
{
|
{
|
||||||
|
|
|
@ -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*));
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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*
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
|
|
Loading…
Reference in New Issue