From 699a0b841c26020815cf276980ad5ccaded7494a Mon Sep 17 00:00:00 2001 From: Ran Benita Date: Wed, 9 May 2012 14:02:26 +0300 Subject: [PATCH] Contextualize the atom table Each context gets its own table, i.e. interning a string in one context does not affect any other context. The existing xkb_atom_* functions are turned into wrappers around a new standalone atom_table object. Signed-off-by: Ran Benita [daniels: Updated for xkb -> keymap.] --- src/atom.c | 152 +++++++++++++++++++++++++++----------------------- src/atom.h | 21 +++---- src/context.c | 29 ++++++++++ src/xkb-priv.h | 13 +++++ src/xkbcomp/xkbcomp.c | 1 - src/xkbcomp/xkbcomp.h | 1 - 6 files changed, 135 insertions(+), 82 deletions(-) diff --git a/src/atom.c b/src/atom.c index bca64d5..e283632 100644 --- a/src/atom.c +++ b/src/atom.c @@ -72,65 +72,100 @@ SOFTWARE. #include "atom.h" -#define InitialTableSize 100 +#define INITIAL_TABLE_SIZE 100 + +struct atom_node { + struct atom_node *left, *right; + uint32_t a; + unsigned int fingerprint; + char *string; +}; + +struct atom_table { + xkb_atom_t last_atom; + struct atom_node *atom_root; + size_t table_length; + struct atom_node **node_table; +}; + +struct atom_table * +atom_table_new(void) +{ + struct atom_table *table; -typedef struct _Node { - struct _Node *left, *right; - uint32_t a; - unsigned int fingerPrint; - char *string; -} NodeRec, *NodePtr; + table = calloc(1, sizeof(*table)); + if (!table) + return NULL; -#define BAD_RESOURCE 0xe0000000 + table->last_atom = XKB_ATOM_NONE; -static xkb_atom_t lastAtom = XKB_ATOM_NONE; -static NodePtr atomRoot; -static unsigned long tableLength; -static NodePtr *nodeTable; + return table; +} -const char * -xkb_atom_text(struct xkb_context *context, xkb_atom_t atom) +static void +free_atom(struct atom_node *patom) { - NodePtr node; + if (!patom) + return; - if ((atom == XKB_ATOM_NONE) || (atom > lastAtom)) - return NULL; - if (!(node = nodeTable[atom])) + free_atom(patom->left); + free_atom(patom->right); + free(patom->string); + free(patom); +} + +void +atom_table_free(struct atom_table *table) +{ + if (!table) + return; + + free_atom(table->atom_root); + free(table->node_table); + free(table); +} + +const char * +atom_text(struct atom_table *table, xkb_atom_t atom) +{ + if (atom == XKB_ATOM_NONE || atom > table->last_atom || + !table->node_table[atom]) return NULL; - return node->string; + + return table->node_table[atom]->string; } char * -xkb_atom_strdup(struct xkb_context *context, xkb_atom_t atom) +atom_strdup(struct atom_table *table, xkb_atom_t atom) { - const char *ret = xkb_atom_text(context, atom); + const char *ret = atom_text(table, atom); return ret ? strdup(ret) : NULL; } xkb_atom_t -xkb_atom_intern(struct xkb_context *context, const char *string) +atom_intern(struct atom_table *table, const char *string) { - NodePtr *np; - NodePtr nd; + struct atom_node **np; + struct atom_node *nd; unsigned i; int comp; unsigned int fp = 0; size_t len; if (!string) - return XKB_ATOM_NONE; + return XKB_ATOM_NONE; len = strlen(string); - np = &atomRoot; + np = &table->atom_root; for (i = 0; i < (len + 1) / 2; i++) { fp = fp * 27 + string[i]; fp = fp * 27 + string[len - 1 - i]; } while (*np) { - if (fp < (*np)->fingerPrint) + if (fp < (*np)->fingerprint) np = &((*np)->left); - else if (fp > (*np)->fingerPrint) + else if (fp > (*np)->fingerprint) np = &((*np)->right); else { /* now start testing the strings */ @@ -144,69 +179,46 @@ xkb_atom_intern(struct xkb_context *context, const char *string) } } - nd = malloc(sizeof(NodeRec)); + nd = malloc(sizeof(*nd)); if (!nd) - return BAD_RESOURCE; + return XKB_ATOM_NONE; nd->string = malloc(len + 1); if (!nd->string) { free(nd); - return BAD_RESOURCE; + return XKB_ATOM_NONE; } strncpy(nd->string, string, len); nd->string[len] = 0; - if ((lastAtom + 1) >= tableLength) { - NodePtr *table; - int newLength; + if ((table->last_atom + 1) >= table->table_length) { + struct atom_node **new_node_table; + int new_length; - if (tableLength == 0) - newLength = InitialTableSize; + if (table->table_length == 0) + new_length = INITIAL_TABLE_SIZE; else - newLength = tableLength * 2; + new_length = table->table_length * 2; - table = realloc(nodeTable, newLength * sizeof(NodePtr)); - if (!table) { + new_node_table = realloc(table->node_table, + new_length * sizeof(*new_node_table)); + if (!new_node_table) { if (nd->string != string) free(nd->string); free(nd); - return BAD_RESOURCE; + return XKB_ATOM_NONE; } - tableLength = newLength; - table[XKB_ATOM_NONE] = NULL; + new_node_table[XKB_ATOM_NONE] = NULL; - nodeTable = table; + table->table_length = new_length; + table->node_table = new_node_table; } *np = nd; nd->left = nd->right = NULL; - nd->fingerPrint = fp; - nd->a = (++lastAtom); - *(nodeTable + lastAtom) = nd; + nd->fingerprint = fp; + nd->a = (++table->last_atom); + *(table->node_table + table->last_atom) = nd; return nd->a; } - -static void -FreeAtom(NodePtr patom) -{ - if (patom->left) - FreeAtom(patom->left); - if (patom->right) - FreeAtom(patom->right); - free(patom->string); - free(patom); -} - -void -XkbcFreeAllAtoms(void) -{ - if (atomRoot == NULL) - return; - FreeAtom(atomRoot); - atomRoot = NULL; - free(nodeTable); - nodeTable = NULL; - lastAtom = XKB_ATOM_NONE; - tableLength = 0; -} diff --git a/src/atom.h b/src/atom.h index d9fc0b8..6294106 100644 --- a/src/atom.h +++ b/src/atom.h @@ -29,20 +29,21 @@ authorization from the authors. #include "xkb-priv.h" -typedef uint32_t xkb_atom_t; +struct atom_table; -#define XKB_ATOM_NONE 0 +struct atom_table * +atom_table_new(void); -extern xkb_atom_t -xkb_atom_intern(struct xkb_context *context, const char *string); +void +atom_table_free(struct atom_table *table); -extern char * -xkb_atom_strdup(struct xkb_context *context, xkb_atom_t atom); +xkb_atom_t +atom_intern(struct atom_table *table, const char *string); -extern const char * -xkb_atom_text(struct xkb_context *context, xkb_atom_t atom); +char * +atom_strdup(struct atom_table *table, xkb_atom_t atom); -extern void -XkbcFreeAllAtoms(void); +const char * +atom_text(struct atom_table *table, xkb_atom_t atom); #endif /* ATOM_H */ diff --git a/src/context.c b/src/context.c index 190a1c5..bf3b07a 100644 --- a/src/context.c +++ b/src/context.c @@ -29,15 +29,19 @@ #include #include "xkb-priv.h" +#include "atom.h" struct xkb_context { int refcnt; + char **include_paths; int num_include_paths; int size_include_paths; /* xkbcomp needs to assign sequential IDs to XkbFile's it creates. */ int file_id; + + struct atom_table *atom_table; }; /** @@ -179,6 +183,7 @@ xkb_context_unref(struct xkb_context *context) return; xkb_context_include_path_clear(context); + atom_table_free(context->atom_table); free(context); } @@ -201,5 +206,29 @@ xkb_context_new(enum xkb_context_flags flags) return NULL; } + context->atom_table = atom_table_new(); + if (!context->atom_table) { + xkb_context_unref(context); + return NULL; + } + return context; } + +xkb_atom_t +xkb_atom_intern(struct xkb_context *context, const char *string) +{ + return atom_intern(context->atom_table, string); +} + +char * +xkb_atom_strdup(struct xkb_context *context, xkb_atom_t atom) +{ + return atom_strdup(context->atom_table, atom); +} + +const char * +xkb_atom_text(struct xkb_context *context, xkb_atom_t atom) +{ + return atom_text(context->atom_table, atom); +} diff --git a/src/xkb-priv.h b/src/xkb-priv.h index 518abc1..584447e 100644 --- a/src/xkb-priv.h +++ b/src/xkb-priv.h @@ -426,6 +426,19 @@ struct xkb_state { struct xkb_keymap *keymap; }; +typedef uint32_t xkb_atom_t; + +#define XKB_ATOM_NONE 0 + +xkb_atom_t +xkb_atom_intern(struct xkb_context *context, const char *string); + +char * +xkb_atom_strdup(struct xkb_context *context, xkb_atom_t atom); + +const char * +xkb_atom_text(struct xkb_context *context, xkb_atom_t atom); + extern unsigned int xkb_key_get_group(struct xkb_state *state, xkb_keycode_t key); diff --git a/src/xkbcomp/xkbcomp.c b/src/xkbcomp/xkbcomp.c index 0ec97ec..d408c29 100644 --- a/src/xkbcomp/xkbcomp.c +++ b/src/xkbcomp/xkbcomp.c @@ -218,7 +218,6 @@ compile_keymap(struct xkb_context *context, XkbFile *file) err: FreeXKBFile(file); - XkbcFreeAllAtoms(); return keymap; } diff --git a/src/xkbcomp/xkbcomp.h b/src/xkbcomp/xkbcomp.h index b4b2ed9..5c0dc96 100644 --- a/src/xkbcomp/xkbcomp.h +++ b/src/xkbcomp/xkbcomp.h @@ -28,7 +28,6 @@ #define XKBCOMP_H 1 #include "xkb-priv.h" -#include "atom.h" #define TypeUnknown 0 #define TypeBoolean 1 -- 2.7.4