chiark / gitweb /
Merge branch 'master' of /home/mdw/public-git/mLib
[mLib] / assoc.c
CommitLineData
dcda5944 1/* -*-c-*-
2 *
8656dc50 3 * $Id: assoc.c,v 1.4 2004/04/08 01:36:11 mdw Exp $
dcda5944 4 *
5 * Assocation tables
6 *
7 * (c) 2000 Straylight/Edgeware
8 */
9
d4efbcd9 10/*----- Licensing notice --------------------------------------------------*
dcda5944 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.
d4efbcd9 18 *
dcda5944 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.
d4efbcd9 23 *
dcda5944 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
dcda5944 30/*----- Header files ------------------------------------------------------*/
31
32#include "alloc.h"
33#include "assoc.h"
34#include "atom.h"
35#include "hash.h"
36
37/*----- Main code ---------------------------------------------------------*/
38
39/* --- @assoc_create@ --- *
40 *
41 * Arguments: @assoc_table *t@ = pointer to an association table
42 *
43 * Returns: ---
44 *
45 * Use: Creates a new association table.
46 */
47
48void assoc_create(assoc_table *t)
49{
50 hash_create(&t->t, SYM_INITSZ);
51 t->load = SYM_LIMIT(SYM_INITSZ);
52}
53
54/* --- @assoc_destroy@ --- *
55 *
56 * Arguments: @assoc_table *t@ = pointer to an association table
57 *
58 * Returns: ---
59 *
60 * Use: Destroys an association table.
61 */
62
63void assoc_destroy(assoc_table *t)
64{
65 hash_iter i;
66
67 HASH_MKITER(&i, &t->t);
68 for (;;) {
69 hash_base *p;
70 HASH_NEXT(&i, p);
6f5e97ac 71 if (!p)
72 break;
dcda5944 73 x_free(t->t.a, p);
74 }
75 hash_destroy(&t->t);
76}
77
78/* --- @assoc_find@ --- *
79 *
80 * Arguments: @assoc_table *t@ = pointer to an association table
81 * @atom *a@ = an atom to label the item
82 * @size_t sz@ = size of block to allocate
83 * @unsigned *f@ = pointer to `found' flag
84 *
85 * Returns: A pointer to the item located or null.
86 *
87 * Use: Looks up an atom in an association table. If the atom is
88 * found, the association is returned. If not, and @sz@ is
89 * zero, a null pointer is returned. Otherwise, a block of size
90 * @sz@ is allocated, its @assoc_base@ header is filled in, and
91 * the pointer returned. The flag @*f@ is cleared if the item
92 * couldn't be found, or set if it was.
93 *
d4efbcd9 94 * All the atoms used in a particular table should
dcda5944 95 */
96
97void *assoc_find(assoc_table *t, atom *a, size_t sz, unsigned *f)
98{
efa99d05 99 hash_base **bin = HASH_BIN(&t->t, ATOM_HASH(a)), **p;
dcda5944 100 assoc_base *q;
101
102 /* --- Try to find the association --- */
103
104 for (p = bin; *p; p = &(*p)->next) {
105 q = (assoc_base *)*p;
106 if (q->a == a) {
107 *p = q->b.next;
108 q->b.next = *bin;
109 *bin = &q->b;
110 if (f) *f = 1;
111 return (q);
112 }
113 }
114
115 /* --- Failed to find a match --- */
116
117 if (f) *f = 0;
118 if (!sz) return (0);
119
120 /* --- Make a new assoication --- */
121
122 q = x_alloc(t->t.a, sz);
6f5e97ac 123 q->a = a;
dcda5944 124 q->b.next = *bin;
125 q->b.hash = ATOM_HASH(a);
126 *bin = &q->b;
127
128 /* --- Maybe extend the table --- */
129
130 if (t->load)
131 t->load--;
132 if (!t->load && hash_extend(&t->t))
133 t->load = SYM_LIMIT(t->t.mask + 1);
134 return (q);
135}
136
137/* --- @assoc_remove@ --- *
138 *
139 * Arguments: @assoc_table *t@ = pointer to an association table
140 * @void *p@ = pointer to a block to remove
141 *
142 * Returns: ---
143 *
144 * Use: Removes an association from a table.
145 */
146
147void assoc_remove(assoc_table *t, void *p)
148{
149 assoc_base *q = p;
150 hash_remove(&t->t, &q->b);
151 x_free(t->t.a, q);
152 t->load++;
153}
154
155/* --- @assoc_mkiter@, @assoc_next@ --- *
156 *
157 * Arguments: @assoc_iter *i@ = pointer to an iterator
158 * @assoc_table *t@ = pointer to an association table
159 *
160 * Returns: Next association, or null, for @assoc_next@; nothing for
161 * @assoc_mkiter@.
162 *
163 * Use: Iterates over the associations in a table.
164 */
165
166void assoc_mkiter(assoc_iter *i, assoc_table *t) { ASSOC_MKITER(i, t); }
167void *assoc_next(assoc_iter *i) { void *p; ASSOC_NEXT(i, p); return (p); }
168
169/*----- That's all, folks -------------------------------------------------*/