From f3e3973d56a1396c68521f779bb0058bd0338fde Mon Sep 17 00:00:00 2001 From: David Herrmann Date: Sun, 16 Sep 2012 09:13:30 +0200 Subject: [PATCH] shl: move kmscon_hashtable to shl This moves the whole hashtable implementation into the SHL library. Now we can link it only to the applications that really use it. Signed-off-by: David Herrmann --- Makefile.am | 9 +- src/shl_hashtable.h | 177 ++++++++++++++++++++++++++++++++++++++ src/static_misc.c | 129 --------------------------- src/static_misc.h | 21 ----- src/text_font_freetype2.c | 15 ++-- src/text_font_pango.c | 15 ++-- src/text_gltex.c | 17 ++-- src/unicode.c | 9 +- 8 files changed, 213 insertions(+), 179 deletions(-) create mode 100644 src/shl_hashtable.h diff --git a/Makefile.am b/Makefile.am index ae6265a..068d2aa 100644 --- a/Makefile.am +++ b/Makefile.am @@ -83,6 +83,10 @@ SHL_DLIST = \ src/shl_dlist.h SHL_ARRAY = \ src/shl_array.h +SHL_HASHTABLE = \ + src/shl_hashtable.h \ + external/htable.h \ + external/htable.c # # libeloop @@ -252,6 +256,7 @@ src/text_font_unifont_data.c: $(UNIFONT) genunifont$(EXEEXT) libkmscon_core_la_SOURCES = \ $(SHL_DLIST) \ $(SHL_ARRAY) \ + $(SHL_HASHTABLE) \ src/main.h \ src/conf.c src/conf.h \ src/ui.c src/ui.h \ @@ -329,9 +334,7 @@ libkmscon_static_la_SOURCES = \ src/static_llog.h \ src/static_hook.h \ src/static_misc.h \ - src/static_misc.c \ - external/htable.h \ - external/htable.c + src/static_misc.c nodist_libkmscon_static_la_SOURCES = libkmscon_static_la_CPPFLAGS = \ diff --git a/src/shl_hashtable.h b/src/shl_hashtable.h new file mode 100644 index 0000000..a7691c3 --- /dev/null +++ b/src/shl_hashtable.h @@ -0,0 +1,177 @@ +/* + * shl - Dynamic Array + * + * Copyright (c) 2011-2012 David Herrmann + * Copyright (c) 2011 University of Tuebingen + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files + * (the "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY + * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +/* + * A dynamic hash table implementation + */ + +#ifndef SHL_HASHTABLE_H +#define SHL_HASHTABLE_H + +#include +#include +#include +#include +#include +#include "external/htable.h" + +struct shl_hashtable; + +typedef unsigned int (*shl_hash_cb) (const void *data); +typedef bool (*shl_equal_cb) (const void *data1, const void *data2); +typedef void (*shl_free_cb) (void *data); + +struct shl_hashentry { + void *key; + void *value; +}; + +struct shl_hashtable { + struct htable tbl; + shl_hash_cb hash_cb; + shl_equal_cb equal_cb; + shl_free_cb free_key; + shl_free_cb free_value; +}; + +static inline unsigned int shl_direct_hash(const void *data) +{ + return (unsigned int)(unsigned long)data; +} + +static inline bool shl_direct_equal(const void *data1, const void *data2) +{ + return data1 == data2; +} + +static size_t shl_rehash(const void *ele, void *priv) +{ + struct shl_hashtable *tbl = priv; + const struct shl_hashentry *ent = ele; + + return tbl->hash_cb(ent->key); +} + +static inline int shl_hashtable_new(struct shl_hashtable **out, + shl_hash_cb hash_cb, + shl_equal_cb equal_cb, + shl_free_cb free_key, + shl_free_cb free_value) +{ + struct shl_hashtable *tbl; + + if (!out || !hash_cb || !equal_cb) + return -EINVAL; + + tbl = malloc(sizeof(*tbl)); + if (!tbl) + return -ENOMEM; + memset(tbl, 0, sizeof(*tbl)); + tbl->hash_cb = hash_cb; + tbl->equal_cb = equal_cb; + tbl->free_key = free_key; + tbl->free_value = free_value; + + htable_init(&tbl->tbl, shl_rehash, tbl); + + *out = tbl; + return 0; +} + +static inline void shl_hashtable_free(struct shl_hashtable *tbl) +{ + struct htable_iter i; + struct shl_hashentry *entry; + + if (!tbl) + return; + + for (entry = htable_first(&tbl->tbl, &i); + entry; + entry = htable_next(&tbl->tbl, &i)) { + htable_delval(&tbl->tbl, &i); + if (tbl->free_key) + tbl->free_key(entry->key); + if (tbl->free_value) + tbl->free_value(entry->value); + free(entry); + } + + htable_clear(&tbl->tbl); + free(tbl); +} + +static inline int shl_hashtable_insert(struct shl_hashtable *tbl, void *key, + void *value) +{ + struct shl_hashentry *entry; + size_t hash; + + if (!tbl) + return -EINVAL; + + entry = malloc(sizeof(*entry)); + if (!entry) + return -ENOMEM; + entry->key = key; + entry->value = value; + + hash = tbl->hash_cb(key); + + if (!htable_add(&tbl->tbl, hash, entry)) { + free(entry); + return -ENOMEM; + } + + return 0; +} + +static inline bool shl_hashtable_find(struct shl_hashtable *tbl, void **out, + void *key) +{ + struct htable_iter i; + struct shl_hashentry *entry; + size_t hash; + + if (!tbl) + return false; + + hash = tbl->hash_cb(key); + + for (entry = htable_firstval(&tbl->tbl, &i, hash); + entry; + entry = htable_nextval(&tbl->tbl, &i, hash)) { + if (tbl->equal_cb(key, entry->key)) { + if (out) + *out = entry->value; + return true; + } + } + + return false; +} + +#endif /* SHL_HASHTABLE_H */ diff --git a/src/static_misc.c b/src/static_misc.c index 5c4693d..f696b3f 100644 --- a/src/static_misc.c +++ b/src/static_misc.c @@ -169,135 +169,6 @@ next: } } -struct kmscon_hashentry { - void *key; - void *value; -}; - -struct kmscon_hashtable { - struct htable tbl; - kmscon_hash_cb hash_cb; - kmscon_equal_cb equal_cb; - kmscon_free_cb free_key; - kmscon_free_cb free_value; -}; - -unsigned int kmscon_direct_hash(const void *data) -{ - return (unsigned int)(unsigned long)data; -} - -bool kmscon_direct_equal(const void *data1, const void *data2) -{ - return data1 == data2; -} - -static size_t rehash(const void *ele, void *priv) -{ - struct kmscon_hashtable *tbl = priv; - const struct kmscon_hashentry *ent = ele; - - return tbl->hash_cb(ent->key); -} - -int kmscon_hashtable_new(struct kmscon_hashtable **out, - kmscon_hash_cb hash_cb, - kmscon_equal_cb equal_cb, - kmscon_free_cb free_key, - kmscon_free_cb free_value) -{ - struct kmscon_hashtable *tbl; - - if (!out || !hash_cb || !equal_cb) - return -EINVAL; - - tbl = malloc(sizeof(*tbl)); - if (!tbl) - return -ENOMEM; - memset(tbl, 0, sizeof(*tbl)); - tbl->hash_cb = hash_cb; - tbl->equal_cb = equal_cb; - tbl->free_key = free_key; - tbl->free_value = free_value; - - htable_init(&tbl->tbl, rehash, tbl); - - *out = tbl; - return 0; -} - -void kmscon_hashtable_free(struct kmscon_hashtable *tbl) -{ - struct htable_iter i; - struct kmscon_hashentry *entry; - - if (!tbl) - return; - - for (entry = htable_first(&tbl->tbl, &i); - entry; - entry = htable_next(&tbl->tbl, &i)) { - htable_delval(&tbl->tbl, &i); - if (tbl->free_key) - tbl->free_key(entry->key); - if (tbl->free_value) - tbl->free_value(entry->value); - free(entry); - } - - htable_clear(&tbl->tbl); - free(tbl); -} - -int kmscon_hashtable_insert(struct kmscon_hashtable *tbl, void *key, - void *value) -{ - struct kmscon_hashentry *entry; - size_t hash; - - if (!tbl) - return -EINVAL; - - entry = malloc(sizeof(*entry)); - if (!entry) - return -ENOMEM; - entry->key = key; - entry->value = value; - - hash = tbl->hash_cb(key); - - if (!htable_add(&tbl->tbl, hash, entry)) { - free(entry); - return -ENOMEM; - } - - return 0; -} - -bool kmscon_hashtable_find(struct kmscon_hashtable *tbl, void **out, void *key) -{ - struct htable_iter i; - struct kmscon_hashentry *entry; - size_t hash; - - if (!tbl) - return false; - - hash = tbl->hash_cb(key); - - for (entry = htable_firstval(&tbl->tbl, &i, hash); - entry; - entry = htable_nextval(&tbl->tbl, &i, hash)) { - if (tbl->equal_cb(key, entry->key)) { - if (out) - *out = entry->value; - return true; - } - } - - return false; -} - struct kmscon_timer { struct timespec start; uint64_t elapsed; diff --git a/src/static_misc.h b/src/static_misc.h index e621ca2..ab6d3a0 100644 --- a/src/static_misc.h +++ b/src/static_misc.h @@ -50,27 +50,6 @@ int kmscon_ring_write(struct kmscon_ring *ring, const char *val, size_t len); const char *kmscon_ring_peek(struct kmscon_ring *ring, size_t *len); void kmscon_ring_drop(struct kmscon_ring *ring, size_t len); -/* hash-tables */ - -struct kmscon_hashtable; - -typedef unsigned int (*kmscon_hash_cb) (const void *data); -typedef bool (*kmscon_equal_cb) (const void *data1, const void *data2); -typedef void (*kmscon_free_cb) (void *data); - -unsigned int kmscon_direct_hash(const void *data); -bool kmscon_direct_equal(const void *data1, const void *data2); - -int kmscon_hashtable_new(struct kmscon_hashtable **out, - kmscon_hash_cb hash_cb, - kmscon_equal_cb equal_cb, - kmscon_free_cb free_key, - kmscon_free_cb free_value); -void kmscon_hashtable_free(struct kmscon_hashtable *tbl); -int kmscon_hashtable_insert(struct kmscon_hashtable *tbl, void *key, - void *data); -bool kmscon_hashtable_find(struct kmscon_hashtable *tbl, void **out, void *key); - /* time measurement */ struct kmscon_timer; diff --git a/src/text_font_freetype2.c b/src/text_font_freetype2.c index f17775d..aa6c9eb 100644 --- a/src/text_font_freetype2.c +++ b/src/text_font_freetype2.c @@ -46,6 +46,7 @@ #include #include "log.h" #include "shl_dlist.h" +#include "shl_hashtable.h" #include "static_misc.h" #include "text.h" #include "unicode.h" @@ -68,7 +69,7 @@ struct face { unsigned int baseline; FT_Face face; pthread_mutex_t glyph_lock; - struct kmscon_hashtable *glyphs; + struct shl_hashtable *glyphs; struct kmscon_glyph empty; struct kmscon_glyph inval; @@ -154,7 +155,7 @@ static int get_glyph(struct face *face, struct kmscon_glyph **out, int ret, hoff1, hoff2, woff1, woff2; pthread_mutex_lock(&face->glyph_lock); - res = kmscon_hashtable_find(face->glyphs, (void**)&glyph, + res = shl_hashtable_find(face->glyphs, (void**)&glyph, (void*)(long)ch); pthread_mutex_unlock(&face->glyph_lock); if (res) { @@ -269,7 +270,7 @@ static int get_glyph(struct face *face, struct kmscon_glyph **out, } pthread_mutex_lock(&face->glyph_lock); - ret = kmscon_hashtable_insert(face->glyphs, (void*)(long)ch, glyph); + ret = shl_hashtable_insert(face->glyphs, (void*)(long)ch, glyph); pthread_mutex_unlock(&face->glyph_lock); if (ret) { log_error("cannot add glyph to hashtable"); @@ -348,8 +349,8 @@ static int manager_get_face(struct face **out, struct kmscon_font_attr *attr) goto err_free; } - ret = kmscon_hashtable_new(&face->glyphs, kmscon_direct_hash, - kmscon_direct_equal, NULL, free_glyph); + ret = shl_hashtable_new(&face->glyphs, shl_direct_hash, + shl_direct_equal, NULL, free_glyph); if (ret) { log_error("cannot allocate hashtable"); goto err_lock; @@ -504,7 +505,7 @@ static int manager_get_face(struct face **out, struct kmscon_font_attr *attr) err_face: FT_Done_Face(face->face); err_htable: - kmscon_hashtable_free(face->glyphs); + shl_hashtable_free(face->glyphs); err_lock: pthread_mutex_destroy(&face->glyph_lock); err_free: @@ -522,7 +523,7 @@ static void manager_put_face(struct face *face) if (!--face->ref) { shl_dlist_unlink(&face->list); - kmscon_hashtable_free(face->glyphs); + shl_hashtable_free(face->glyphs); pthread_mutex_destroy(&face->glyph_lock); FT_Done_Face(face->face); free(face); diff --git a/src/text_font_pango.c b/src/text_font_pango.c index 134e1bf..75630a6 100644 --- a/src/text_font_pango.c +++ b/src/text_font_pango.c @@ -53,6 +53,7 @@ #include #include "log.h" #include "shl_dlist.h" +#include "shl_hashtable.h" #include "static_misc.h" #include "text.h" #include "unicode.h" @@ -69,7 +70,7 @@ struct face { unsigned int baseline; PangoContext *ctx; pthread_mutex_t glyph_lock; - struct kmscon_hashtable *glyphs; + struct shl_hashtable *glyphs; }; static pthread_mutex_t manager_mutex = PTHREAD_MUTEX_INITIALIZER; @@ -123,7 +124,7 @@ static int get_glyph(struct face *face, struct kmscon_glyph **out, int ret; pthread_mutex_lock(&face->glyph_lock); - res = kmscon_hashtable_find(face->glyphs, (void**)&glyph, + res = shl_hashtable_find(face->glyphs, (void**)&glyph, (void*)(long)ch); pthread_mutex_unlock(&face->glyph_lock); if (res) { @@ -190,7 +191,7 @@ static int get_glyph(struct face *face, struct kmscon_glyph **out, pango_ft2_render_layout_line(&bitmap, line, -rec.x, -rec.y); pthread_mutex_lock(&face->glyph_lock); - ret = kmscon_hashtable_insert(face->glyphs, (void*)(long)ch, glyph); + ret = shl_hashtable_insert(face->glyphs, (void*)(long)ch, glyph); pthread_mutex_unlock(&face->glyph_lock); if (ret) { log_error("cannot add glyph to hashtable"); @@ -261,8 +262,8 @@ static int manager_get_face(struct face **out, struct kmscon_font_attr *attr) goto err_free; } - ret = kmscon_hashtable_new(&face->glyphs, kmscon_direct_hash, - kmscon_direct_equal, NULL, free_glyph); + ret = shl_hashtable_new(&face->glyphs, shl_direct_hash, + shl_direct_equal, NULL, free_glyph); if (ret) { log_error("cannot allocate hashtable"); goto err_lock; @@ -328,7 +329,7 @@ static int manager_get_face(struct face **out, struct kmscon_font_attr *attr) err_face: g_object_unref(face->ctx); - kmscon_hashtable_free(face->glyphs); + shl_hashtable_free(face->glyphs); err_lock: pthread_mutex_destroy(&face->glyph_lock); err_free: @@ -346,7 +347,7 @@ static void manager_put_face(struct face *face) if (!--face->ref) { shl_dlist_unlink(&face->list); - kmscon_hashtable_free(face->glyphs); + shl_hashtable_free(face->glyphs); pthread_mutex_destroy(&face->glyph_lock); g_object_unref(face->ctx); free(face); diff --git a/src/text_gltex.c b/src/text_gltex.c index 6ec57ad..004e945 100644 --- a/src/text_gltex.c +++ b/src/text_gltex.c @@ -47,6 +47,7 @@ #include #include "log.h" #include "shl_dlist.h" +#include "shl_hashtable.h" #include "static_gl.h" #include "static_misc.h" #include "text.h" @@ -87,7 +88,7 @@ struct glyph { #define GLYPH_DATA(gly) ((gly)->glyph->buf.data) struct gltex { - struct kmscon_hashtable *glyphs; + struct shl_hashtable *glyphs; unsigned int max_tex_size; bool supports_rowlen; @@ -151,9 +152,9 @@ static int gltex_set(struct kmscon_text *txt) memset(gt, 0, sizeof(*gt)); shl_dlist_init(>->atlases); - ret = kmscon_hashtable_new(>->glyphs, kmscon_direct_hash, - kmscon_direct_equal, NULL, - free_glyph); + ret = shl_hashtable_new(>->glyphs, shl_direct_hash, + shl_direct_equal, NULL, + free_glyph); if (ret) return ret; @@ -207,7 +208,7 @@ static int gltex_set(struct kmscon_text *txt) err_shader: gl_shader_unref(gt->shader); err_htable: - kmscon_hashtable_free(gt->glyphs); + shl_hashtable_free(gt->glyphs); return ret; } @@ -225,7 +226,7 @@ static void gltex_unset(struct kmscon_text *txt) log_warning("cannot activate OpenGL-CTX during destruction"); } - kmscon_hashtable_free(gt->glyphs); + shl_hashtable_free(gt->glyphs); while (!shl_dlist_empty(>->atlases)) { iter = gt->atlases.next; @@ -377,7 +378,7 @@ static int find_glyph(struct kmscon_text *txt, struct glyph **out, GLenum err; uint8_t *packed_data, *dst, *src; - res = kmscon_hashtable_find(gt->glyphs, (void**)&glyph, + res = shl_hashtable_find(gt->glyphs, (void**)&glyph, (void*)(unsigned long)ch); if (res) { *out = glyph; @@ -480,7 +481,7 @@ static int find_glyph(struct kmscon_text *txt, struct glyph **out, glyph->atlas = atlas; glyph->texoff = atlas->fill; - ret = kmscon_hashtable_insert(gt->glyphs, (void*)(long)ch, glyph); + ret = shl_hashtable_insert(gt->glyphs, (void*)(long)ch, glyph); if (ret) goto err_free; diff --git a/src/unicode.c b/src/unicode.c index 548d1f7..d0077e5 100644 --- a/src/unicode.c +++ b/src/unicode.c @@ -61,6 +61,7 @@ #include #include "log.h" #include "shl_array.h" +#include "shl_hashtable.h" #include "static_misc.h" #include "unicode.h" @@ -106,7 +107,7 @@ static const char default_u8[] = { 0 }; static pthread_mutex_t table_mutex = PTHREAD_MUTEX_INITIALIZER; static uint32_t table_next_id; static struct shl_array *table_index; -static struct kmscon_hashtable *table_symbols; +static struct shl_hashtable *table_symbols; static unsigned int hash_ucs4(const void *key) { @@ -165,7 +166,7 @@ static int table__init() /* first entry is not used so add dummy */ shl_array_push(table_index, &val); - ret = kmscon_hashtable_new(&table_symbols, hash_ucs4, cmp_ucs4, + ret = shl_hashtable_new(&table_symbols, hash_ucs4, cmp_ucs4, free, NULL); if (ret) { shl_array_free(table_index); @@ -272,7 +273,7 @@ tsm_symbol_t tsm_symbol_append(tsm_symbol_t sym, uint32_t ucs4) buf[s++] = ucs4; buf[s++] = TSM_UCS4_MAX + 1; - res = kmscon_hashtable_find(table_symbols, &tmp, buf); + res = shl_hashtable_find(table_symbols, &tmp, buf); if (res) { rsym = (uint32_t)(long)tmp; goto unlock; @@ -288,7 +289,7 @@ tsm_symbol_t tsm_symbol_append(tsm_symbol_t sym, uint32_t ucs4) memcpy(nval, buf, s * sizeof(uint32_t)); nsym = table_next_id++; - kmscon_hashtable_insert(table_symbols, nval, (void*)(long)nsym); + shl_hashtable_insert(table_symbols, nval, (void*)(long)nsym); shl_array_push(table_index, &nval); rsym = nsym;