use only generic structures

master
Alessandro Mauri 2 years ago
parent 440e4499c7
commit 6503897ece
Signed by: alema
GPG Key ID: 2B7BF9531FF03BE8
  1. 11
      text_rendering/Makefile
  2. 8
      text_rendering/font.c
  3. 23
      text_rendering/generic_cache.h
  4. 14
      text_rendering/generic_hash.h
  5. 2
      text_rendering/genmake.sh
  6. 77
      text_rendering/hash.c
  7. 21
      text_rendering/hash.h

@ -1,17 +1,16 @@
CC = gcc CC = gcc
LDFLAGS = -lm -lgrapheme -lSDL2 -lGLEW -lGL 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 .PHONY: clean all
all: test all: test
font.o: font.c font.h stb_truetype.h stb_image_write.h util.h \ font.o: font.c font.h stb_truetype.h stb_image_write.h util.h \
generic_cache.h hash.h generic_cache.h generic_hash.h
hash.o: hash.c hash.h util.h
main.o: main.c ren.h util.h main.o: main.c ren.h util.h
ren.o: ren.c util.h font.h ren.h generic_stack.h ren.o: ren.c util.h font.h ren.h generic_stack.h
util.o: util.c util.h util.o: util.c util.h
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 hash.o main.o ren.o util.o ${CC} ${LDFLAGS} -o test font.o main.o ren.o util.o
clean: 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" #include "util.h"
// generic cache type // 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" #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) #define UTF8(c) (c&0x80)

@ -2,7 +2,7 @@
#define CACHE_GENERIC_H #define CACHE_GENERIC_H
#include "hash.h" #include "generic_hash.h"
#define CACHE_SIZE 512 #define CACHE_SIZE 512
#define CACHE_NCYCLES (CACHE_SIZE/2) #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_BSET(b, x) b[(x)>>6] |= (uint64_t)1<<((x)%64)
#define CACHE_BTEST(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) \ #define CACHE_SET(c, x) \
{ \ { \
c->cycles = (c->cycles+1)%CACHE_NCYCLES; \ 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 cachename { \
struct hm_ref *table; \ struct cachename##table_ref *table; \
type *array; \ type *array; \
uint64_t *bitmap; \ uint64_t *bitmap; \
int cycles; \ int cycles; \
@ -30,7 +34,9 @@ struct cachename { \
\ \
struct cachename cachename##_init(void) \ 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); \ type *a = malloc(sizeof(type)*CACHE_SIZE); \
uint64_t *b = malloc(sizeof(uint64_t)*CACHE_BSIZE); \ uint64_t *b = malloc(sizeof(uint64_t)*CACHE_BSIZE); \
CACHE_BRESET(b); \ CACHE_BRESET(b); \
@ -41,7 +47,7 @@ struct cachename cachename##_init(void) \
void cachename##_free(struct cachename *cache) \ void cachename##_free(struct cachename *cache) \
{ \ { \
if (cache) { \ if (cache) { \
hm_destroy(cache->table); \ cachename##table_destroy(cache->table); \
free(cache->array); \ free(cache->array); \
free(cache->bitmap); \ free(cache->bitmap); \
} \ } \
@ -52,7 +58,8 @@ const type * cachename##_search(struct cachename *cache, unsigned int code) \
{ \ { \
if (!cache) \ if (!cache) \
return NULL; \ return NULL; \
struct hm_entry *r = hm_search(cache->table, code); \ struct cachename##table_entry *r; \
r = cachename##table_search(cache->table, code); \
/* MISS */ \ /* MISS */ \
if (!r) \ if (!r) \
return NULL; \ return NULL; \
@ -90,8 +97,8 @@ const type * cachename##_insert(struct cachename *cache, const type *g, unsigned
CACHE_SET(cache, x) \ CACHE_SET(cache, x) \
spot = &(cache->array[x]); \ spot = &(cache->array[x]); \
*spot = *g; \ *spot = *g; \
struct hm_entry e = { .code = code, .data = spot}; \ struct cachename##table_entry e = { .code = code, .data = spot}; \
if (!hm_insert(cache->table, &e)) \ if (!cachename##table_insert(cache->table, &e)) \
return NULL; \ return NULL; \
return spot; \ return spot; \
} \ } \

@ -14,21 +14,21 @@
/* Ready-made compares */ /* Ready-made compares */
int hash_compare_u32(unsigned int a, unsigned int b) { return a == b; } static int hash_cp_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; } static int hash_cp_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_str(const char *a, const char *b) { return strcmp(a, b) == 0; }
/* Ready-made hashes */ /* 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); 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); 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; unsigned int h = HASH_STRSALT;
const unsigned char *v = (const unsigned char *)(s); 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->size = size; \
h->hash = hash; \ h->hash = hash; \
h->compare = compare; \ h->compare = compare; \
memset(h->bucket, 0, sizeof(struct hashname##_ref)*size); \ memset(h->bucket, 0, sizeof(struct hashname##_entry)*size); \
} \ } \
return h; \ return h; \
} \ } \

@ -16,7 +16,7 @@ rm -f objlist
cat > Makefile << EOF cat > Makefile << EOF
CC = gcc CC = gcc
LDFLAGS = -lm -lgrapheme -lSDL2 -lGLEW -lGL 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 .PHONY: clean all
all: test 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…
Cancel
Save