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
parent
cdd2906de3
commit
699a0b841c
146
src/atom.c
146
src/atom.c
|
@ -72,46 +72,81 @@ 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;
|
||||||
|
@ -121,16 +156,16 @@ xkb_atom_intern(struct xkb_context *context, const char *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;
|
|
||||||
}
|
|
||||||
|
|
21
src/atom.h
21
src/atom.h
|
@ -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 */
|
||||||
|
|
|
@ -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);
|
||||||
|
}
|
||||||
|
|
|
@ -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);
|
||||||
|
|
||||||
|
|
|
@ -218,7 +218,6 @@ compile_keymap(struct xkb_context *context, XkbFile *file)
|
||||||
|
|
||||||
err:
|
err:
|
||||||
FreeXKBFile(file);
|
FreeXKBFile(file);
|
||||||
XkbcFreeAllAtoms();
|
|
||||||
return keymap;
|
return keymap;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
Loading…
Reference in New Issue