tsm: unicode: add symbol-table contexts
We should avoid any global state in shared libraries. As the TSM code is becoming a shared library, we definitely need contexts for symbol tables. However, we don't want to fix up all code now so we use a default table NULL instead. This can be fixed later but is ok for now. Signed-off-by: David Herrmann <dh.herrmann@googlemail.com>
This commit is contained in:
parent
52d2eb09b1
commit
d5a0c9644c
@ -88,7 +88,7 @@ static int kmscon_font_8x16_render(struct kmscon_font *font,
|
||||
const uint32_t *val;
|
||||
size_t len;
|
||||
|
||||
val = tsm_symbol_get(&sym, &len);
|
||||
val = tsm_symbol_get(NULL, &sym, &len);
|
||||
if (len > 1 || *val >= 256)
|
||||
return -ERANGE;
|
||||
|
||||
|
@ -181,7 +181,7 @@ static int get_glyph(struct face *face, struct kmscon_glyph **out,
|
||||
* TODO: Fix this by drawing all related characters into a single glyph
|
||||
* and saving it or simply refer to the pango backend which already does
|
||||
* that. */
|
||||
val = tsm_symbol_get(&ch, &len);
|
||||
val = tsm_symbol_get(NULL, &ch, &len);
|
||||
if (len > 1 || !*val) {
|
||||
ret = -ERANGE;
|
||||
goto out_glyph;
|
||||
|
@ -149,7 +149,7 @@ static int get_glyph(struct face *face, struct kmscon_glyph **out,
|
||||
/* no line spacing */
|
||||
pango_layout_set_spacing(layout, 0);
|
||||
|
||||
val = tsm_symbol_get_u8(ch, &len);
|
||||
val = tsm_symbol_get_u8(NULL, ch, &len);
|
||||
pango_layout_set_text(layout, val, len);
|
||||
tsm_symbol_free_u8(val);
|
||||
|
||||
|
@ -84,7 +84,7 @@ static int kmscon_font_unifont_render(struct kmscon_font *font,
|
||||
const uint32_t *val;
|
||||
size_t len;
|
||||
|
||||
val = tsm_symbol_get(&sym, &len);
|
||||
val = tsm_symbol_get(NULL, &sym, &len);
|
||||
if (len > 1 || *val >= kmscon_text_font_unifont_data_hex_len)
|
||||
return -ERANGE;
|
||||
|
||||
|
@ -56,7 +56,6 @@
|
||||
|
||||
#include <errno.h>
|
||||
#include <inttypes.h>
|
||||
#include <pthread.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "shl_array.h"
|
||||
@ -100,10 +99,14 @@
|
||||
const tsm_symbol_t tsm_symbol_default = 0;
|
||||
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 shl_hashtable *table_symbols;
|
||||
struct tsm_symbol_table {
|
||||
uint32_t next_id;
|
||||
struct shl_array *index;
|
||||
struct shl_hashtable *symbols;
|
||||
};
|
||||
|
||||
/* TODO: remove the default context */
|
||||
static struct tsm_symbol_table tsm_symbol_table_default;
|
||||
|
||||
static unsigned int hash_ucs4(const void *key)
|
||||
{
|
||||
@ -143,27 +146,27 @@ static bool cmp_ucs4(const void *a, const void *b)
|
||||
}
|
||||
}
|
||||
|
||||
static int table__init()
|
||||
static int table__init(struct tsm_symbol_table *tbl)
|
||||
{
|
||||
static const uint32_t *val = NULL; /* we need a valid lvalue */
|
||||
int ret;
|
||||
|
||||
if (table_symbols)
|
||||
if (tbl->symbols)
|
||||
return 0;
|
||||
|
||||
table_next_id = TSM_UCS4_MAX + 2;
|
||||
tbl->next_id = TSM_UCS4_MAX + 2;
|
||||
|
||||
ret = shl_array_new(&table_index, sizeof(uint32_t*), 4);
|
||||
ret = shl_array_new(&tbl->index, sizeof(uint32_t*), 4);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/* first entry is not used so add dummy */
|
||||
shl_array_push(table_index, &val);
|
||||
shl_array_push(tbl->index, &val);
|
||||
|
||||
ret = shl_hashtable_new(&table_symbols, hash_ucs4, cmp_ucs4,
|
||||
free, NULL);
|
||||
ret = shl_hashtable_new(&tbl->symbols, hash_ucs4, cmp_ucs4,
|
||||
free, NULL);
|
||||
if (ret) {
|
||||
shl_array_free(table_index);
|
||||
shl_array_free(tbl->index);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
@ -189,7 +192,8 @@ tsm_symbol_t tsm_symbol_make(uint32_t ucs4)
|
||||
* This always returns a valid value. If an error happens, the default character
|
||||
* is returned. If \size is NULL, then the size value is omitted.
|
||||
*/
|
||||
static const uint32_t *table__get(tsm_symbol_t *sym, size_t *size)
|
||||
static const uint32_t *table__get(struct tsm_symbol_table *tbl,
|
||||
tsm_symbol_t *sym, size_t *size)
|
||||
{
|
||||
uint32_t *ucs4;
|
||||
|
||||
@ -199,13 +203,13 @@ static const uint32_t *table__get(tsm_symbol_t *sym, size_t *size)
|
||||
return sym;
|
||||
}
|
||||
|
||||
if (table__init()) {
|
||||
if (table__init(tbl)) {
|
||||
if (size)
|
||||
*size = 1;
|
||||
return &tsm_symbol_default;
|
||||
}
|
||||
|
||||
ucs4 = *SHL_ARRAY_AT(table_index, uint32_t*,
|
||||
ucs4 = *SHL_ARRAY_AT(tbl->index, uint32_t*,
|
||||
*sym - (TSM_UCS4_MAX + 1));
|
||||
if (!ucs4) {
|
||||
if (size)
|
||||
@ -222,18 +226,21 @@ static const uint32_t *table__get(tsm_symbol_t *sym, size_t *size)
|
||||
return ucs4;
|
||||
}
|
||||
|
||||
const uint32_t *tsm_symbol_get(tsm_symbol_t *sym, size_t *size)
|
||||
const uint32_t *tsm_symbol_get(struct tsm_symbol_table *tbl,
|
||||
tsm_symbol_t *sym, size_t *size)
|
||||
{
|
||||
const uint32_t *res;
|
||||
|
||||
pthread_mutex_lock(&table_mutex);
|
||||
res = table__get(sym, size);
|
||||
pthread_mutex_unlock(&table_mutex);
|
||||
if (!tbl)
|
||||
tbl = &tsm_symbol_table_default;
|
||||
|
||||
res = table__get(tbl, sym, size);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
tsm_symbol_t tsm_symbol_append(tsm_symbol_t sym, uint32_t ucs4)
|
||||
tsm_symbol_t tsm_symbol_append(struct tsm_symbol_table *tbl,
|
||||
tsm_symbol_t sym, uint32_t ucs4)
|
||||
{
|
||||
uint32_t buf[TSM_UCS4_MAXLEN + 1], nsym, *nval;
|
||||
const uint32_t *ptr;
|
||||
@ -242,9 +249,10 @@ tsm_symbol_t tsm_symbol_append(tsm_symbol_t sym, uint32_t ucs4)
|
||||
void *tmp;
|
||||
bool res;
|
||||
|
||||
pthread_mutex_lock(&table_mutex);
|
||||
if (!tbl)
|
||||
tbl = &tsm_symbol_table_default;
|
||||
|
||||
if (table__init()) {
|
||||
if (table__init(tbl)) {
|
||||
rsym = sym;
|
||||
goto unlock;
|
||||
}
|
||||
@ -254,7 +262,7 @@ tsm_symbol_t tsm_symbol_append(tsm_symbol_t sym, uint32_t ucs4)
|
||||
goto unlock;
|
||||
}
|
||||
|
||||
ptr = table__get(&sym, &s);
|
||||
ptr = table__get(tbl, &sym, &s);
|
||||
if (s >= TSM_UCS4_MAXLEN) {
|
||||
rsym = sym;
|
||||
goto unlock;
|
||||
@ -264,7 +272,7 @@ tsm_symbol_t tsm_symbol_append(tsm_symbol_t sym, uint32_t ucs4)
|
||||
buf[s++] = ucs4;
|
||||
buf[s++] = TSM_UCS4_MAX + 1;
|
||||
|
||||
res = shl_hashtable_find(table_symbols, &tmp, buf);
|
||||
res = shl_hashtable_find(tbl->symbols, &tmp, buf);
|
||||
if (res) {
|
||||
rsym = (uint32_t)(long)tmp;
|
||||
goto unlock;
|
||||
@ -277,13 +285,12 @@ tsm_symbol_t tsm_symbol_append(tsm_symbol_t sym, uint32_t ucs4)
|
||||
}
|
||||
|
||||
memcpy(nval, buf, s * sizeof(uint32_t));
|
||||
nsym = table_next_id++;
|
||||
shl_hashtable_insert(table_symbols, nval, (void*)(long)nsym);
|
||||
shl_array_push(table_index, &nval);
|
||||
nsym = tbl->next_id++;
|
||||
shl_hashtable_insert(tbl->symbols, nval, (void*)(long)nsym);
|
||||
shl_array_push(tbl->index, &nval);
|
||||
rsym = nsym;
|
||||
|
||||
unlock:
|
||||
pthread_mutex_unlock(&table_mutex);
|
||||
return rsym;
|
||||
}
|
||||
|
||||
@ -321,13 +328,17 @@ static size_t ucs4_to_utf8(uint32_t g, char *txt)
|
||||
}
|
||||
}
|
||||
|
||||
const char *tsm_symbol_get_u8(tsm_symbol_t sym, size_t *size)
|
||||
const char *tsm_symbol_get_u8(struct tsm_symbol_table *tbl,
|
||||
tsm_symbol_t sym, size_t *size)
|
||||
{
|
||||
const uint32_t *ucs4;
|
||||
char *val;
|
||||
size_t i, pos, len;
|
||||
|
||||
ucs4 = tsm_symbol_get(&sym, &len);
|
||||
if (!tbl)
|
||||
tbl = &tsm_symbol_table_default;
|
||||
|
||||
ucs4 = tsm_symbol_get(tbl, &sym, &len);
|
||||
val = malloc(4 * len);
|
||||
if (!val)
|
||||
goto err_out;
|
||||
|
@ -45,14 +45,18 @@
|
||||
|
||||
/* symbols */
|
||||
|
||||
struct tsm_symbol_table;
|
||||
typedef uint32_t tsm_symbol_t;
|
||||
|
||||
extern const tsm_symbol_t tsm_symbol_default;
|
||||
|
||||
tsm_symbol_t tsm_symbol_make(uint32_t ucs4);
|
||||
tsm_symbol_t tsm_symbol_append(tsm_symbol_t sym, uint32_t ucs4);
|
||||
const uint32_t *tsm_symbol_get(tsm_symbol_t *sym, size_t *size);
|
||||
const char *tsm_symbol_get_u8(tsm_symbol_t sym, size_t *size);
|
||||
tsm_symbol_t tsm_symbol_append(struct tsm_symbol_table *tbl,
|
||||
tsm_symbol_t sym, uint32_t ucs4);
|
||||
const uint32_t *tsm_symbol_get(struct tsm_symbol_table *tbl,
|
||||
tsm_symbol_t *sym, size_t *size);
|
||||
const char *tsm_symbol_get_u8(struct tsm_symbol_table *tbl,
|
||||
tsm_symbol_t sym, size_t *size);
|
||||
void tsm_symbol_free_u8(const char *s);
|
||||
|
||||
/* utf8 state machine */
|
||||
|
@ -2625,7 +2625,7 @@ bool kmscon_vte_handle_keyboard(struct kmscon_vte *vte, uint32_t keysym,
|
||||
vte_write_raw(vte, &val, 1);
|
||||
} else {
|
||||
sym = tsm_symbol_make(unicode);
|
||||
u8 = tsm_symbol_get_u8(sym, &len);
|
||||
u8 = tsm_symbol_get_u8(NULL, sym, &len);
|
||||
vte_write_raw(vte, u8, len);
|
||||
tsm_symbol_free_u8(u8);
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user