use only generic structures
This commit is contained in:
parent
440e4499c7
commit
6503897ece
@ -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
|
||||
|
@ -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)
|
||||
|
@ -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; \
|
||||
} \
|
||||
|
@ -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; \
|
||||
} \
|
||||
|
@ -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
|
||||
|
@ -1,77 +0,0 @@
|
||||
#define _POSIX_C_SOURCE 200809l
|
||||
#define _DEFAULT_SOURCE
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
|
||||
#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;
|
||||
}
|
@ -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
|
Loading…
Reference in New Issue
Block a user