From 6503897ece71c8e8ee7a99688dc45d30bf955055 Mon Sep 17 00:00:00 2001 From: Alessandro Mauri Date: Tue, 7 Mar 2023 23:05:58 +0100 Subject: [PATCH] use only generic structures --- text_rendering/Makefile | 11 +++-- text_rendering/font.c | 8 +++- text_rendering/generic_cache.h | 23 ++++++---- text_rendering/generic_hash.h | 14 +++---- text_rendering/genmake.sh | 2 +- text_rendering/hash.c | 77 ---------------------------------- text_rendering/hash.h | 21 ---------- 7 files changed, 35 insertions(+), 121 deletions(-) delete mode 100644 text_rendering/hash.c delete mode 100644 text_rendering/hash.h diff --git a/text_rendering/Makefile b/text_rendering/Makefile index 1b9cf93..8ecf368 100644 --- a/text_rendering/Makefile +++ b/text_rendering/Makefile @@ -1,17 +1,16 @@ CC = gcc LDFLAGS = -lm -lgrapheme -lSDL2 -lGLEW -lGL -CFLAGS = -g -Wall -Wextra -pedantic -fno-omit-frame-pointer +CFLAGS = -ggdb3 -Wall -Wextra -pedantic -fno-omit-frame-pointer .PHONY: clean all all: test font.o: font.c font.h stb_truetype.h stb_image_write.h util.h \ - generic_cache.h hash.h -hash.o: hash.c hash.h util.h + generic_cache.h generic_hash.h main.o: main.c ren.h util.h ren.o: ren.c util.h font.h ren.h generic_stack.h util.o: util.c util.h -test: font.o hash.o main.o ren.o util.o - ${CC} ${LDFLAGS} -o test font.o hash.o main.o ren.o util.o +test: font.o main.o ren.o util.o + ${CC} ${LDFLAGS} -o test font.o main.o ren.o util.o clean: - rm -f test font.o hash.o main.o ren.o util.o + rm -f test font.o main.o ren.o util.o diff --git a/text_rendering/font.c b/text_rendering/font.c index 840e706..89ad189 100644 --- a/text_rendering/font.c +++ b/text_rendering/font.c @@ -12,8 +12,14 @@ #include "util.h" // generic cache type +static unsigned int hash(unsigned int code) +{ + // identity map the ascii range + if (code < 128) return code; + return (uint32_t)((uint64_t)(code*2654435761)>>32); +} #include "generic_cache.h" -CACHE_DECL(cache, struct font_glyph) +CACHE_DECL(cache, struct font_glyph, hash, hash_cp_u32) #define UTF8(c) (c&0x80) diff --git a/text_rendering/generic_cache.h b/text_rendering/generic_cache.h index 1285ca5..060f909 100644 --- a/text_rendering/generic_cache.h +++ b/text_rendering/generic_cache.h @@ -2,7 +2,7 @@ #define CACHE_GENERIC_H -#include "hash.h" +#include "generic_hash.h" #define CACHE_SIZE 512 #define CACHE_NCYCLES (CACHE_SIZE/2) @@ -11,6 +11,9 @@ #define CACHE_BSET(b, x) b[(x)>>6] |= (uint64_t)1<<((x)%64) #define CACHE_BTEST(b, x) (b[(x)>>6]&((uint64_t)1<<((x)%64))) +// FIXME: this cache implementation is not really generic since it expects an unsigned +// as the code and not a generic type + #define CACHE_SET(c, x) \ { \ c->cycles = (c->cycles+1)%CACHE_NCYCLES; \ @@ -19,9 +22,10 @@ } -#define CACHE_DECL(cachename, type) \ +#define CACHE_DECL(cachename, type, hashfn, comparefn) \ +HASH_DECL(cachename##table, unsigned int, void *) \ struct cachename { \ - struct hm_ref *table; \ + struct cachename##table_ref *table; \ type *array; \ uint64_t *bitmap; \ int cycles; \ @@ -30,7 +34,9 @@ struct cachename { \ \ struct cachename cachename##_init(void) \ { \ - struct hm_ref *t = hm_create(CACHE_SIZE); \ + struct cachename##table_ref *t = cachename##table_create( \ + CACHE_SIZE, hashfn, comparefn \ + ); \ type *a = malloc(sizeof(type)*CACHE_SIZE); \ uint64_t *b = malloc(sizeof(uint64_t)*CACHE_BSIZE); \ CACHE_BRESET(b); \ @@ -41,7 +47,7 @@ struct cachename cachename##_init(void) \ void cachename##_free(struct cachename *cache) \ { \ if (cache) { \ - hm_destroy(cache->table); \ + cachename##table_destroy(cache->table); \ free(cache->array); \ free(cache->bitmap); \ } \ @@ -52,7 +58,8 @@ const type * cachename##_search(struct cachename *cache, unsigned int code) \ { \ if (!cache) \ return NULL; \ - struct hm_entry *r = hm_search(cache->table, code); \ + struct cachename##table_entry *r; \ + r = cachename##table_search(cache->table, code); \ /* MISS */ \ if (!r) \ return NULL; \ @@ -90,8 +97,8 @@ const type * cachename##_insert(struct cachename *cache, const type *g, unsigned CACHE_SET(cache, x) \ spot = &(cache->array[x]); \ *spot = *g; \ - struct hm_entry e = { .code = code, .data = spot}; \ - if (!hm_insert(cache->table, &e)) \ + struct cachename##table_entry e = { .code = code, .data = spot}; \ + if (!cachename##table_insert(cache->table, &e)) \ return NULL; \ return spot; \ } \ diff --git a/text_rendering/generic_hash.h b/text_rendering/generic_hash.h index 37f8b81..f11a4ac 100644 --- a/text_rendering/generic_hash.h +++ b/text_rendering/generic_hash.h @@ -14,21 +14,21 @@ /* Ready-made compares */ -int hash_compare_u32(unsigned int a, unsigned int b) { return a == b; } -int hash_compare_u64(unsigned long long int a, unsigned long long int b) { return a == b; } -int hash_compare_str(const char *a, const char *b) { return strcmp(a, b) == 0; } +static int hash_cp_u32(unsigned int a, unsigned int b) { return a == b; } +static int hash_cp_u64(unsigned long long int a, unsigned long long int b) { return a == b; } +static int hash_cp_str(const char *a, const char *b) { return strcmp(a, b) == 0; } /* Ready-made hashes */ -unsigned int hash_u64(unsigned long long int c) +static unsigned int hash_u64(unsigned long long int c) { return (unsigned long long int)((unsigned long long int)(c*HASH_RATIO64)>>32); } -unsigned int hash_u32(unsigned int c) +static unsigned int hash_u32(unsigned int c) { return (unsigned int)((unsigned long long int)(c*HASH_RATIO32)>>32); } -unsigned int hash_str(const char *s) +static unsigned int hash_str(const char *s) { unsigned int h = HASH_STRSALT; const unsigned char *v = (const unsigned char *)(s); @@ -76,7 +76,7 @@ struct hashname##_ref * hashname##_create(unsigned int size, unsigned int (*hash h->size = size; \ h->hash = hash; \ h->compare = compare; \ - memset(h->bucket, 0, sizeof(struct hashname##_ref)*size); \ + memset(h->bucket, 0, sizeof(struct hashname##_entry)*size); \ } \ return h; \ } \ diff --git a/text_rendering/genmake.sh b/text_rendering/genmake.sh index be25540..3bcf991 100755 --- a/text_rendering/genmake.sh +++ b/text_rendering/genmake.sh @@ -16,7 +16,7 @@ rm -f objlist cat > Makefile << EOF CC = gcc LDFLAGS = -lm -lgrapheme -lSDL2 -lGLEW -lGL -CFLAGS = -g -Wall -Wextra -pedantic -fno-omit-frame-pointer +CFLAGS = -ggdb3 -Wall -Wextra -pedantic -fno-omit-frame-pointer .PHONY: clean all all: test diff --git a/text_rendering/hash.c b/text_rendering/hash.c deleted file mode 100644 index 7a554db..0000000 --- a/text_rendering/hash.c +++ /dev/null @@ -1,77 +0,0 @@ -#define _POSIX_C_SOURCE 200809l -#define _DEFAULT_SOURCE - -#include -#include -#include - -#include "hash.h" -#include "util.h" - -#define MAXSIZE 4096 - - -static unsigned int hash(unsigned int code) -{ - // identity map the ascii range - if (code < 128) return code; - return (uint32_t)((uint64_t)(code*2654435761)>>32); -} - - -struct hm_ref * hm_create(unsigned int size) -{ - if (!size || size > MAXSIZE) - return NULL; - - // round to the greater power of two - size = 1<<__builtin_clz(size); - - // FIXME: check for intger overflow here - struct hm_ref *h = emalloc(sizeof(struct hm_ref)+sizeof(struct hm_entry)*size); - if (h) { - h->items = 0; - h->size = size; - memset(h->bucket, 0, sizeof(struct hm_ref)*size); - } - return h; -} - - -void hm_destroy(struct hm_ref *hm) -{ - efree(hm); -} - - -static struct hm_entry * lookup(struct hm_ref *hm, unsigned int code) -{ - // fast modulo operation for power-of-2 size - unsigned int mask = hm->size - 1; - unsigned int i = hash(code); - for (unsigned int j = 1; ; i += j++) { - if (!hm->bucket[i&mask].code || hm->bucket[i].code == code) - return &(hm->bucket[i&mask]); - } - return NULL; -} - - -struct hm_entry * hm_search(struct hm_ref *hm, unsigned int code) -{ - struct hm_entry *r = lookup(hm, code); - if (r) { - if (r->code == code) - return r; - return NULL; - } - return r; -} - - -struct hm_entry * hm_insert(struct hm_ref *hm, struct hm_entry *entry) -{ - struct hm_entry *r = lookup(hm, entry->code); - if (r) *r = *entry; - return r; -} diff --git a/text_rendering/hash.h b/text_rendering/hash.h deleted file mode 100644 index 65263b8..0000000 --- a/text_rendering/hash.h +++ /dev/null @@ -1,21 +0,0 @@ -#ifndef _HASH_H -#define _HASH_H - -struct hm_entry { - unsigned long code; - void *data; -}; - - -struct hm_ref { - unsigned int items, size; - struct hm_entry bucket[]; -}; - - -struct hm_ref * hm_create(unsigned int size); -void hm_destroy(struct hm_ref *hm); -struct hm_entry * hm_search(struct hm_ref *hm, unsigned int code); -struct hm_entry * hm_insert(struct hm_ref *hm, struct hm_entry *entry); - -#endif