chiark / gitweb /
Initial revision
[ssr] / StraySrc / SDLS / cdll / c / hashtable
1 /*
2  * hashtable.c
3  *
4  * Hash table handling for strings
5  *
6  * © 1994-1998 Straylight
7  */
8
9 /*----- Licensing note ----------------------------------------------------*
10  *
11  * This file is part of Straylight's Dynamic Linking System (SDLS)
12  *
13  * SDLS is free software; you can redistribute it and/or modify
14  * it under the terms of the GNU General Public License as published by
15  * the Free Software Foundation; either version 2, or (at your option)
16  * any later version.
17  *
18  * SDLS is distributed in the hope that it will be useful,
19  * but WITHOUT ANY WARRANTY; without even the implied warranty of
20  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
21  * GNU General Public License for more details.
22  *
23  * You should have received a copy of the GNU General Public License
24  * along with SDLS.  If not, write to the Free Software Foundation,
25  * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
26  */
27
28 #include <stdio.h>
29 #include <stdlib.h>
30 #include <string.h>
31
32 #include "hashtable.h"
33 #include "crc32.h"
34
35 /*----- Constants ---------------------------------------------------------*/
36
37 #define hash__SIZE 512                  /* A respectable size table     */
38                                         /* Note: must be power of 2     */
39
40 /*----- Some good ol' data structures -------------------------------------*/
41
42 typedef struct hash__link
43 {
44   struct hash__link *next;              /* Link in hash table bucket    */
45   struct hash__link *left;              /* Link in ordinal tree         */
46   struct hash__link *right;             /* Link in ordinal tree         */
47   unsigned int ord;                     /* Ordinal value                */
48   char string[1];                       /* String (unsized array)       */
49 }
50 hash__link;
51
52 typedef struct hash__table
53 {
54   hash__link *tbl[hash__SIZE];          /* The actual hash table        */
55   hash__link *root;                     /* The ordinal tree root        */
56 }
57 hash__table;
58
59 /*----- Private code ------------------------------------------------------*/
60
61 #define hash__hash(s) (crc32(0,s,strlen(s),1) & (hash__SIZE - 1))
62
63 static int hash__addToTree(hash__link **root,hash__link *l)
64 {
65   if (*root)
66   {
67     if ((*root)->ord > l->ord)
68       return (hash__addToTree(&(*root)->left,l));
69     else if ((*root)->ord < l->ord || l->ord == 0xFFFFFFFF)
70       return (hash__addToTree(&(*root)->right,l));
71     else
72       return (1);
73   }
74   else
75   {
76     *root=l;
77     return (0);
78   }
79 }
80
81 static void hash__traverse(hash__link *l,
82                            void (*func)(char *string,
83                                         unsigned int ord,
84                                         void *handle),
85                            void *handle)
86 {
87   if (l)
88   {
89     hash__traverse(l->left,func,handle);
90     func(l->string,l->ord,handle);
91     hash__traverse(l->right,func,handle);
92   }
93 }
94
95 static void hash__dump(char *string,unsigned int ord,void *handle)
96 {
97   handle=handle;
98   printf(" ** %s (%08x)\n",string,ord);
99 }
100
101 /*----- Public code -------------------------------------------------------*/
102
103 hashtable hash_create(void)
104 {
105   return (calloc(1,sizeof(hash__table)));
106 }
107
108 int hash_find(hashtable h,char *string)
109 {
110   int sh=hash__hash(string);
111   hash__link *l;
112   for (l=h->tbl[sh];l;l=l->next)
113   {
114     if (!strcmp(l->string,string))
115       return (1);
116   }
117   return (0);
118 }
119
120 int hash_add(hashtable h,char *string)
121 {
122   return (hash_addWithOrd(h,string,0xFFFFFFFF));
123 }
124
125 int hash_addWithOrd(hashtable h,char *string,unsigned int ord)
126 {
127   int sh=hash__hash(string);
128   hash__link *l;
129   if (hash_find(h,string))
130     return (1);
131   if (l=malloc(sizeof(hash__link)+strlen(string)),!l)
132     return (0);
133   strcpy(l->string,string);
134   l->ord=ord;
135   l->next=h->tbl[sh];
136   h->tbl[sh]=l;
137   l->left=l->right=0;
138   if (hash__addToTree(&h->root,l))
139   {
140     l->ord=0xFFFFFFFF;
141     hash__addToTree(&h->root,l);
142   }
143   return (1);
144 }
145
146 void hash_delete(hashtable h)
147 {
148   hash__link *l;
149   hash__link *n;
150   int i;
151   for (i=0;i<hash__SIZE;i++)
152   {
153     for (l=h->tbl[i];l;l=n)
154     {
155       n=l->next;
156       free(l);
157     }
158   }
159   free(h);
160 }
161
162 int hash_subset(hashtable super,
163                 hashtable sub,
164                 void (*proc)(char *p))
165 {
166   hash__link *l;
167   int i;
168   int s=1;
169   for (i=0;i<hash__SIZE;i++)
170   {
171     for (l=sub->tbl[i];l;l=l->next)
172     {
173       if (!hash_find(super,l->string))
174       {
175         s=0;
176         proc(l->string);
177       }
178     }
179   }
180   return (s);
181 }
182
183 void hash_dump(hashtable h)
184 {
185   hash_enumOrdered(h,hash__dump,0);
186 }
187 void hash_enumerate(hashtable h,
188                     void (*func)(char *string,void *handle),
189                     void *handle)
190 {
191   hash__link *l;
192   int i;
193   for (i=0;i<hash__SIZE;i++)
194   {
195     for (l=h->tbl[i];l;l=l->next)
196       func(l->string,handle);
197   }
198 }
199
200 void hash_enumOrdered(hashtable h,
201                       void (*func)(char *string,
202                                    unsigned int ord,
203                                    void *handle),
204                       void *handle)
205 {
206   hash__traverse(h->root,func,handle);
207 }
208
209 int hash_count(hashtable h)
210 {
211   int count=0;
212   hash__link *l;
213   int i;
214   for (i=0;i<hash__SIZE;i++)
215   {
216     for (l=h->tbl[i];l;l=l->next)
217       count++;
218   }
219   return (count);
220 }