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 <ran234@gmail.com>

[daniels: Updated for xkb -> keymap.]
master
Ran Benita 2012-05-09 14:02:26 +03:00 committed by Daniel Stone
parent cdd2906de3
commit 699a0b841c
6 changed files with 135 additions and 82 deletions

View File

@ -72,65 +72,100 @@ SOFTWARE.
#include "atom.h" #include "atom.h"
#define InitialTableSize 100 #define INITIAL_TABLE_SIZE 100
typedef struct _Node { struct atom_node {
struct _Node *left, *right; struct atom_node *left, *right;
uint32_t a; uint32_t a;
unsigned int fingerPrint; unsigned int fingerprint;
char *string; char *string;
} NodeRec, *NodePtr; };
#define BAD_RESOURCE 0xe0000000 struct atom_table {
xkb_atom_t last_atom;
struct atom_node *atom_root;
size_t table_length;
struct atom_node **node_table;
};
static xkb_atom_t lastAtom = XKB_ATOM_NONE; struct atom_table *
static NodePtr atomRoot; atom_table_new(void)
static unsigned long tableLength; {
static NodePtr *nodeTable; struct atom_table *table;
table = calloc(1, sizeof(*table));
if (!table)
return NULL;
table->last_atom = XKB_ATOM_NONE;
return table;
}
static void
free_atom(struct atom_node *patom)
{
if (!patom)
return;
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 * const char *
xkb_atom_text(struct xkb_context *context, xkb_atom_t atom) atom_text(struct atom_table *table, xkb_atom_t atom)
{ {
NodePtr node; if (atom == XKB_ATOM_NONE || atom > table->last_atom ||
!table->node_table[atom])
return NULL;
if ((atom == XKB_ATOM_NONE) || (atom > lastAtom)) return table->node_table[atom]->string;
return NULL;
if (!(node = nodeTable[atom]))
return NULL;
return node->string;
} }
char * 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; return ret ? strdup(ret) : NULL;
} }
xkb_atom_t xkb_atom_t
xkb_atom_intern(struct xkb_context *context, const char *string) atom_intern(struct atom_table *table, const char *string)
{ {
NodePtr *np; struct atom_node **np;
NodePtr nd; struct atom_node *nd;
unsigned i; unsigned i;
int comp; int comp;
unsigned int fp = 0; unsigned int fp = 0;
size_t len; size_t len;
if (!string) if (!string)
return XKB_ATOM_NONE; return XKB_ATOM_NONE;
len = strlen(string); len = strlen(string);
np = &atomRoot; np = &table->atom_root;
for (i = 0; i < (len + 1) / 2; i++) { for (i = 0; i < (len + 1) / 2; i++) {
fp = fp * 27 + string[i]; fp = fp * 27 + string[i];
fp = fp * 27 + string[len - 1 - i]; fp = fp * 27 + string[len - 1 - i];
} }
while (*np) { while (*np) {
if (fp < (*np)->fingerPrint) if (fp < (*np)->fingerprint)
np = &((*np)->left); np = &((*np)->left);
else if (fp > (*np)->fingerPrint) else if (fp > (*np)->fingerprint)
np = &((*np)->right); np = &((*np)->right);
else { else {
/* now start testing the strings */ /* 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) if (!nd)
return BAD_RESOURCE; return XKB_ATOM_NONE;
nd->string = malloc(len + 1); nd->string = malloc(len + 1);
if (!nd->string) { if (!nd->string) {
free(nd); free(nd);
return BAD_RESOURCE; return XKB_ATOM_NONE;
} }
strncpy(nd->string, string, len); strncpy(nd->string, string, len);
nd->string[len] = 0; nd->string[len] = 0;
if ((lastAtom + 1) >= tableLength) { if ((table->last_atom + 1) >= table->table_length) {
NodePtr *table; struct atom_node **new_node_table;
int newLength; int new_length;
if (tableLength == 0) if (table->table_length == 0)
newLength = InitialTableSize; new_length = INITIAL_TABLE_SIZE;
else else
newLength = tableLength * 2; new_length = table->table_length * 2;
table = realloc(nodeTable, newLength * sizeof(NodePtr)); new_node_table = realloc(table->node_table,
if (!table) { new_length * sizeof(*new_node_table));
if (!new_node_table) {
if (nd->string != string) if (nd->string != string)
free(nd->string); free(nd->string);
free(nd); free(nd);
return BAD_RESOURCE; return XKB_ATOM_NONE;
} }
tableLength = newLength; new_node_table[XKB_ATOM_NONE] = NULL;
table[XKB_ATOM_NONE] = NULL;
nodeTable = table; table->table_length = new_length;
table->node_table = new_node_table;
} }
*np = nd; *np = nd;
nd->left = nd->right = NULL; nd->left = nd->right = NULL;
nd->fingerPrint = fp; nd->fingerprint = fp;
nd->a = (++lastAtom); nd->a = (++table->last_atom);
*(nodeTable + lastAtom) = nd; *(table->node_table + table->last_atom) = nd;
return nd->a; 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;
}

View File

@ -29,20 +29,21 @@ authorization from the authors.
#include "xkb-priv.h" #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 void
xkb_atom_intern(struct xkb_context *context, const char *string); atom_table_free(struct atom_table *table);
extern char * xkb_atom_t
xkb_atom_strdup(struct xkb_context *context, xkb_atom_t atom); atom_intern(struct atom_table *table, const char *string);
extern const char * char *
xkb_atom_text(struct xkb_context *context, xkb_atom_t atom); atom_strdup(struct atom_table *table, xkb_atom_t atom);
extern void const char *
XkbcFreeAllAtoms(void); atom_text(struct atom_table *table, xkb_atom_t atom);
#endif /* ATOM_H */ #endif /* ATOM_H */

View File

@ -29,15 +29,19 @@
#include <unistd.h> #include <unistd.h>
#include "xkb-priv.h" #include "xkb-priv.h"
#include "atom.h"
struct xkb_context { struct xkb_context {
int refcnt; int refcnt;
char **include_paths; char **include_paths;
int num_include_paths; int num_include_paths;
int size_include_paths; int size_include_paths;
/* xkbcomp needs to assign sequential IDs to XkbFile's it creates. */ /* xkbcomp needs to assign sequential IDs to XkbFile's it creates. */
int file_id; int file_id;
struct atom_table *atom_table;
}; };
/** /**
@ -179,6 +183,7 @@ xkb_context_unref(struct xkb_context *context)
return; return;
xkb_context_include_path_clear(context); xkb_context_include_path_clear(context);
atom_table_free(context->atom_table);
free(context); free(context);
} }
@ -201,5 +206,29 @@ xkb_context_new(enum xkb_context_flags flags)
return NULL; return NULL;
} }
context->atom_table = atom_table_new();
if (!context->atom_table) {
xkb_context_unref(context);
return NULL;
}
return context; 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);
}

View File

@ -426,6 +426,19 @@ struct xkb_state {
struct xkb_keymap *keymap; 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 extern unsigned int
xkb_key_get_group(struct xkb_state *state, xkb_keycode_t key); xkb_key_get_group(struct xkb_state *state, xkb_keycode_t key);

View File

@ -218,7 +218,6 @@ compile_keymap(struct xkb_context *context, XkbFile *file)
err: err:
FreeXKBFile(file); FreeXKBFile(file);
XkbcFreeAllAtoms();
return keymap; return keymap;
} }

View File

@ -28,7 +28,6 @@
#define XKBCOMP_H 1 #define XKBCOMP_H 1
#include "xkb-priv.h" #include "xkb-priv.h"
#include "atom.h"
#define TypeUnknown 0 #define TypeUnknown 0
#define TypeBoolean 1 #define TypeBoolean 1