chiark / gitweb /
Implementation of atom tables (for example, as found in X11).
authormdw <mdw>
Sat, 20 Jan 2001 11:50:16 +0000 (11:50 +0000)
committermdw <mdw>
Sat, 20 Jan 2001 11:50:16 +0000 (11:50 +0000)
atom.c [new file with mode: 0644]
atom.h [new file with mode: 0644]

diff --git a/atom.c b/atom.c
new file mode 100644 (file)
index 0000000..66e9b57
--- /dev/null
+++ b/atom.c
@@ -0,0 +1,218 @@
+/* -*-c-*-
+ *
+ * $Id: atom.c,v 1.1 2001/01/20 11:50:16 mdw Exp $
+ *
+ * Atom management
+ *
+ * (c) 2000 Straylight/Edgeware
+ */
+
+/*----- Licensing notice --------------------------------------------------* 
+ *
+ * This file is part of the mLib utilities library.
+ *
+ * mLib is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Library General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ * 
+ * mLib is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Library General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Library General Public
+ * License along with mLib; if not, write to the Free
+ * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+ * MA 02111-1307, USA.
+ */
+
+/*----- Revision history --------------------------------------------------* 
+ *
+ * $Log: atom.c,v $
+ * Revision 1.1  2001/01/20 11:50:16  mdw
+ * Implementation of atom tables (for example, as found in X11).
+ *
+ */
+
+/*----- Header files ------------------------------------------------------*/
+
+#include <stdio.h>
+#include <string.h>
+
+#include "alloc.h"
+#include "atom.h"
+#include "hash.h"
+#include "sym.h"
+
+/*----- Static variables --------------------------------------------------*/
+
+static atom_table atoms;
+
+/*----- Handy macros ------------------------------------------------------*/
+
+#define ATOM_RESOLVE(t) do {                                           \
+  if (t == ATOM_GLOBAL)                                                        \
+    t = &atoms;                                                                \
+  if (!t->t.t.v)                                                       \
+    atom_createtable(t);                                               \
+} while (0)
+
+/*----- Main code ---------------------------------------------------------*/
+
+/* --- @atom_createtable@ --- *
+ *
+ * Arguments:  @atom_table *t@ = pointer to an atom table
+ *
+ * Returns:    ---
+ *
+ * Use:                Initializes an atom table.
+ */
+
+void atom_createtable(atom_table *t)
+{
+  sym_create(&t->t);
+  t->g = 0;
+  t->gseq = 0;
+}
+
+/* --- @atom_destroytable@ --- *
+ *
+ * Arguments:  @atom_table *t@ = pointer to an atom table
+ *
+ * Returns:    ---
+ *
+ * Use:                Destroys all of the atoms in an atom table.  All of the atoms
+ *             (including uninterned atoms) are freed.  Any references to
+ *             atoms from the table become invalid, and any association
+ *             tables dependent on the atom table are unusable, except that
+ *             they may be destroyed safely.
+ */
+
+void atom_destroytable(atom_table *t)
+{
+  atom *a, *aa;
+
+  ATOM_RESOLVE(t);
+  for (a = (atom *)t->g; a; a = aa) {
+    aa = (atom *)a->b.b.next;
+    x_free(t->t.t.a, a);
+  }
+  sym_destroy(&t->t);
+}
+
+/* --- @atom_intern@ --- *
+ *
+ * Arguments:  @atom_table *t@ = pointer to an atom table
+ *             @const char *p@ = pointer to the string to intern
+ *
+ * Returns:    A pointer to the atom block for the given symbol string.
+ *
+ * Use:                Interns an atom, returning the atom block.  The string can be
+ *             extracted from the atom by means of the @ATOM_NAME@ macro.
+ */
+
+atom *atom_intern(atom_table *t, const char *p)
+{
+  atom *a;
+  unsigned f;
+
+  ATOM_RESOLVE(t);
+  a = sym_find(&t->t, p, -1, sizeof(atom), &f);
+  if (!f)
+    a->f = 0;
+  return (a);
+}
+
+/* --- @atom_gensym@ --- *
+ *
+ * Arguments:  @atom_table *t@ = pointer to a symbol table
+ *
+ * Returns:    A pointer to a new atom block, not previously interned.
+ *
+ * Use:                Creates a new, uninterned atom.  This atom will never be
+ *             returned by either @atom_intern@ or any other call to
+ *             @atom_gensym@, while the symbol table exists.
+ */
+
+atom *atom_gensym(atom_table *t)
+{
+  atom *a;
+  char buf[64];
+  size_t sz;
+
+  ATOM_RESOLVE(t);
+  sprintf(buf, "*gen-%lu*", t->gseq++);
+  sz = strlen(buf) + 1;
+  a = x_alloc(t->t.t.a, sizeof(atom) + sz);
+  a->b.name = (char *)(a + 1);
+  memcpy(a->b.name, buf, sz);
+  a->b.len = sz;
+  CRC32(a->b.b.hash, 0, buf, sz);
+  a->f = ATOMF_GENSYM;
+  a->b.b.next = t->g;
+  t->g = &a->b.b;
+  return (a);
+}
+
+/* --- @atom_name@ --- *
+ *
+ * Arguments:  @atom *a@ = pointer to an atom
+ *
+ * Returns:    The atom's textual name.
+ *
+ * Use:                Given an atom, returns the name with which it was interned
+ *             (or a made-up name if it was created using @gensym@.
+ */
+
+const char *atom_name(const atom *a) { return ATOM_NAME(a); }
+
+/* --- @atom_len@ --- *
+ *
+ * Arguments:  @atom *a@ = pointer to an atom
+ *
+ * Returns:    The atom string's length.
+ *
+ * Use:                Given an atom, return the length of its textual
+ *             representation.
+ */
+
+size_t atom_len(const atom *a) { return ATOM_LEN(a); }
+
+/* --- @atom_hash@ --- *
+ *
+ * Arguments:  @atom *a@ = pointer to an atom
+ *
+ * Returns:    The atom's hash.
+ *
+ * Use:                Given an atom, returns its hash.
+ */
+
+uint32 atom_hash(const atom *a) { return ATOM_HASH(a); }
+
+/* --- @atom_mkiter@ , @atom_next@ --- *
+ *
+ * Arguments:  @atom_table *t@ = pointer to an atom table
+ *             @atom_iter *i@ = pointer to an iterator structure
+ *
+ * Returns:    Next atom, for @atom_next@; nothing for @atom_mkiter@.
+ *
+ * Use:                Iterates over atoms (both interned and uninterned).
+ */
+
+void atom_mkiter(atom_iter *i, atom_table *t)
+{
+  ATOM_RESOLVE(t);
+  i->i.i.t = &t->t.t;
+  i->i.i.p = t->g;
+  i->i.i.i = 0;
+}
+
+atom *atom_next(atom_iter *i)
+{
+  atom *a;
+  SYM_NEXT(&i->i, a);
+  return (a);
+}
+
+/*----- That's all, folks -------------------------------------------------*/
diff --git a/atom.h b/atom.h
new file mode 100644 (file)
index 0000000..7adf195
--- /dev/null
+++ b/atom.h
@@ -0,0 +1,190 @@
+/* -*-c-*-
+ *
+ * $Id: atom.h,v 1.1 2001/01/20 11:50:16 mdw Exp $
+ *
+ * Atom management
+ *
+ * (c) 2000 Straylight/Edgeware
+ */
+
+/*----- Licensing notice --------------------------------------------------* 
+ *
+ * This file is part of the mLib utilities library.
+ *
+ * mLib is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Library General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ * 
+ * mLib is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Library General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Library General Public
+ * License along with mLib; if not, write to the Free
+ * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+ * MA 02111-1307, USA.
+ */
+
+/*----- Revision history --------------------------------------------------* 
+ *
+ * $Log: atom.h,v $
+ * Revision 1.1  2001/01/20 11:50:16  mdw
+ * Implementation of atom tables (for example, as found in X11).
+ *
+ */
+
+#ifndef MLIB_ATOM_H
+#define MLIB_ATOM_H
+
+#ifdef __cplusplus
+  extern "C" {
+#endif
+
+/*----- Header files ------------------------------------------------------*/
+
+#ifndef MLIB_SYM_H
+#  include "sym.h"
+#endif
+
+/*----- Data structures ---------------------------------------------------*/
+
+typedef struct atom_table {
+  sym_table t;                         /* Symbol table of interned atoms */
+  hash_base *g;                                /* List of uninterned atoms */
+  unsigned long gseq;                  /* Sequence number for @gensym@ */
+} atom_table;
+
+typedef struct atom {
+  sym_base b;                          /* Base structure for symbol table */
+  unsigned f;                          /* Various useful flags */
+} atom;
+
+#define ATOMF_GENSYM 1u                        /* Atom is uninterned */
+
+typedef struct { sym_iter i; } atom_iter;
+
+/*----- Global magic ------------------------------------------------------*/
+
+#define ATOM_GLOBAL 0
+
+/*----- Functions provided ------------------------------------------------*/
+
+/* --- @atom_createtable@ --- *
+ *
+ * Arguments:  @atom_table *t@ = pointer to an atom table
+ *
+ * Returns:    ---
+ *
+ * Use:                Initializes an atom table.
+ */
+
+extern void atom_createtable(atom_table */*t*/);
+
+/* --- @atom_destroytable@ --- *
+ *
+ * Arguments:  @atom_table *t@ = pointer to an atom table
+ *
+ * Returns:    ---
+ *
+ * Use:                Destroys all of the atoms in an atom table.  All of the atoms
+ *             (including uninterned atoms) are freed.  Any references to
+ *             atoms from the table become invalid, and any association
+ *             tables dependent on the atom table are unusable, except that
+ *             they may be destroyed safely.
+ */
+
+extern void atom_destroytable(atom_table */*t*/);
+
+/* --- @atom_intern@ --- *
+ *
+ * Arguments:  @atom_table *t@ = pointer to an atom table
+ *             @const char *p@ = pointer to the string to intern
+ *
+ * Returns:    A pointer to the atom block for the given symbol string.
+ *
+ * Use:                Interns an atom, returning the atom block.  The string can be
+ *             extracted from the atom by means of the @ATOM_NAME@ macro.
+ */
+
+#define INTERN(p) atom_intern(ATOM_GLOBAL, (p))
+
+extern atom *atom_intern(atom_table */*t*/, const char */*p*/);
+
+/* --- @atom_gensym@ --- *
+ *
+ * Arguments:  @atom_table *t@ = pointer to a symbol table
+ *
+ * Returns:    A pointer to a new atom block, not previously interned.
+ *
+ * Use:                Creates a new, uninterned atom.  This atom will never be
+ *             returned by either @atom_intern@ or any other call to
+ *             @atom_gensym@, while the symbol table exists.
+ */
+
+#define GENSYM atom_gensym(ATOM_GLOBAL)
+
+extern atom *atom_gensym(atom_table */*t*/);
+
+/* --- @atom_name@ --- *
+ *
+ * Arguments:  @atom *a@ = pointer to an atom
+ *
+ * Returns:    The atom's textual name.
+ *
+ * Use:                Given an atom, returns the name with which it was interned
+ *             (or a made-up name if it was created using @gensym@.
+ */
+
+#define ATOM_NAME(a) SYM_NAME(a)
+
+extern const char *atom_name(const atom */*a*/);
+
+/* --- @atom_len@ --- *
+ *
+ * Arguments:  @atom *a@ = pointer to an atom
+ *
+ * Returns:    The atom string's length.
+ *
+ * Use:                Given an atom, return the length of its textual
+ *             representation.
+ */
+
+#define ATOM_LEN(a) (SYM_LEN(a) - 1)
+
+extern size_t atom_len(const atom */*a*/);
+
+/* --- @atom_hash@ --- *
+ *
+ * Arguments:  @atom *a@ = pointer to an atom
+ *
+ * Returns:    The atom's hash.
+ *
+ * Use:                Given an atom, returns its hash.
+ */
+
+#define ATOM_HASH(a) SYM_HASH(a)
+
+extern uint32 atom_hash(const atom */*a*/);
+
+/* --- @atom_mkiter@ , @atom_next@ --- *
+ *
+ * Arguments:  @atom_table *t@ = pointer to an atom table
+ *             @atom_iter *i@ = pointer to an iterator structure
+ *
+ * Returns:    Next atom, for @atom_next@; nothing for @atom_mkiter@.
+ *
+ * Use:                Iterates over atoms (both interned and uninterned).
+ */
+
+extern void atom_mkiter(atom_iter */*i*/, atom_table */*t*/);
+extern atom *atom_next(atom_iter */*i*/);
+
+/*----- That's all, folks -------------------------------------------------*/
+
+#ifdef __cplusplus
+  }
+#endif
+
+#endif