chiark / gitweb /
Be more conservative in base-64 encoding.
[mLib] / atom.c
1 /* -*-c-*-
2  *
3  * $Id: atom.c,v 1.1 2001/01/20 11:50:16 mdw Exp $
4  *
5  * Atom management
6  *
7  * (c) 2000 Straylight/Edgeware
8  */
9
10 /*----- Licensing notice --------------------------------------------------* 
11  *
12  * This file is part of the mLib utilities library.
13  *
14  * mLib is free software; you can redistribute it and/or modify
15  * it under the terms of the GNU Library General Public License as
16  * published by the Free Software Foundation; either version 2 of the
17  * License, or (at your option) any later version.
18  * 
19  * mLib is distributed in the hope that it will be useful,
20  * but WITHOUT ANY WARRANTY; without even the implied warranty of
21  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
22  * GNU Library General Public License for more details.
23  * 
24  * You should have received a copy of the GNU Library General Public
25  * License along with mLib; if not, write to the Free
26  * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
27  * MA 02111-1307, USA.
28  */
29
30 /*----- Revision history --------------------------------------------------* 
31  *
32  * $Log: atom.c,v $
33  * Revision 1.1  2001/01/20 11:50:16  mdw
34  * Implementation of atom tables (for example, as found in X11).
35  *
36  */
37
38 /*----- Header files ------------------------------------------------------*/
39
40 #include <stdio.h>
41 #include <string.h>
42
43 #include "alloc.h"
44 #include "atom.h"
45 #include "hash.h"
46 #include "sym.h"
47
48 /*----- Static variables --------------------------------------------------*/
49
50 static atom_table atoms;
51
52 /*----- Handy macros ------------------------------------------------------*/
53
54 #define ATOM_RESOLVE(t) do {                                            \
55   if (t == ATOM_GLOBAL)                                                 \
56     t = &atoms;                                                         \
57   if (!t->t.t.v)                                                        \
58     atom_createtable(t);                                                \
59 } while (0)
60
61 /*----- Main code ---------------------------------------------------------*/
62
63 /* --- @atom_createtable@ --- *
64  *
65  * Arguments:   @atom_table *t@ = pointer to an atom table
66  *
67  * Returns:     ---
68  *
69  * Use:         Initializes an atom table.
70  */
71
72 void atom_createtable(atom_table *t)
73 {
74   sym_create(&t->t);
75   t->g = 0;
76   t->gseq = 0;
77 }
78
79 /* --- @atom_destroytable@ --- *
80  *
81  * Arguments:   @atom_table *t@ = pointer to an atom table
82  *
83  * Returns:     ---
84  *
85  * Use:         Destroys all of the atoms in an atom table.  All of the atoms
86  *              (including uninterned atoms) are freed.  Any references to
87  *              atoms from the table become invalid, and any association
88  *              tables dependent on the atom table are unusable, except that
89  *              they may be destroyed safely.
90  */
91
92 void atom_destroytable(atom_table *t)
93 {
94   atom *a, *aa;
95
96   ATOM_RESOLVE(t);
97   for (a = (atom *)t->g; a; a = aa) {
98     aa = (atom *)a->b.b.next;
99     x_free(t->t.t.a, a);
100   }
101   sym_destroy(&t->t);
102 }
103
104 /* --- @atom_intern@ --- *
105  *
106  * Arguments:   @atom_table *t@ = pointer to an atom table
107  *              @const char *p@ = pointer to the string to intern
108  *
109  * Returns:     A pointer to the atom block for the given symbol string.
110  *
111  * Use:         Interns an atom, returning the atom block.  The string can be
112  *              extracted from the atom by means of the @ATOM_NAME@ macro.
113  */
114
115 atom *atom_intern(atom_table *t, const char *p)
116 {
117   atom *a;
118   unsigned f;
119
120   ATOM_RESOLVE(t);
121   a = sym_find(&t->t, p, -1, sizeof(atom), &f);
122   if (!f)
123     a->f = 0;
124   return (a);
125 }
126
127 /* --- @atom_gensym@ --- *
128  *
129  * Arguments:   @atom_table *t@ = pointer to a symbol table
130  *
131  * Returns:     A pointer to a new atom block, not previously interned.
132  *
133  * Use:         Creates a new, uninterned atom.  This atom will never be
134  *              returned by either @atom_intern@ or any other call to
135  *              @atom_gensym@, while the symbol table exists.
136  */
137
138 atom *atom_gensym(atom_table *t)
139 {
140   atom *a;
141   char buf[64];
142   size_t sz;
143
144   ATOM_RESOLVE(t);
145   sprintf(buf, "*gen-%lu*", t->gseq++);
146   sz = strlen(buf) + 1;
147   a = x_alloc(t->t.t.a, sizeof(atom) + sz);
148   a->b.name = (char *)(a + 1);
149   memcpy(a->b.name, buf, sz);
150   a->b.len = sz;
151   CRC32(a->b.b.hash, 0, buf, sz);
152   a->f = ATOMF_GENSYM;
153   a->b.b.next = t->g;
154   t->g = &a->b.b;
155   return (a);
156 }
157
158 /* --- @atom_name@ --- *
159  *
160  * Arguments:   @atom *a@ = pointer to an atom
161  *
162  * Returns:     The atom's textual name.
163  *
164  * Use:         Given an atom, returns the name with which it was interned
165  *              (or a made-up name if it was created using @gensym@.
166  */
167
168 const char *atom_name(const atom *a) { return ATOM_NAME(a); }
169
170 /* --- @atom_len@ --- *
171  *
172  * Arguments:   @atom *a@ = pointer to an atom
173  *
174  * Returns:     The atom string's length.
175  *
176  * Use:         Given an atom, return the length of its textual
177  *              representation.
178  */
179
180 size_t atom_len(const atom *a) { return ATOM_LEN(a); }
181
182 /* --- @atom_hash@ --- *
183  *
184  * Arguments:   @atom *a@ = pointer to an atom
185  *
186  * Returns:     The atom's hash.
187  *
188  * Use:         Given an atom, returns its hash.
189  */
190
191 uint32 atom_hash(const atom *a) { return ATOM_HASH(a); }
192
193 /* --- @atom_mkiter@ , @atom_next@ --- *
194  *
195  * Arguments:   @atom_table *t@ = pointer to an atom table
196  *              @atom_iter *i@ = pointer to an iterator structure
197  *
198  * Returns:     Next atom, for @atom_next@; nothing for @atom_mkiter@.
199  *
200  * Use:         Iterates over atoms (both interned and uninterned).
201  */
202
203 void atom_mkiter(atom_iter *i, atom_table *t)
204 {
205   ATOM_RESOLVE(t);
206   i->i.i.t = &t->t.t;
207   i->i.i.p = t->g;
208   i->i.i.i = 0;
209 }
210
211 atom *atom_next(atom_iter *i)
212 {
213   atom *a;
214   SYM_NEXT(&i->i, a);
215   return (a);
216 }
217
218 /*----- That's all, folks -------------------------------------------------*/