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,46 +72,81 @@ SOFTWARE.
#include "atom.h"
#define InitialTableSize 100
#define INITIAL_TABLE_SIZE 100
typedef struct _Node {
struct _Node *left, *right;
struct atom_node {
struct atom_node *left, *right;
uint32_t a;
unsigned int fingerPrint;
unsigned int fingerprint;
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;
static NodePtr atomRoot;
static unsigned long tableLength;
static NodePtr *nodeTable;
struct atom_table *
atom_table_new(void)
{
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 *
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 NULL;
if (!(node = nodeTable[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;
@ -121,16 +156,16 @@ xkb_atom_intern(struct xkb_context *context, const char *string)
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;
}

View File

@ -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 */

View File

@ -29,15 +29,19 @@
#include <unistd.h>
#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);
}

View File

@ -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);

View File

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

View File

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