]> www.fi.muni.cz Git - evince.git/blob - backend/dvi/mdvi-lib/hash.c
Reorganize source tree.
[evince.git] / backend / dvi / mdvi-lib / hash.c
1 /*
2  * Copyright (C) 2000, Matias Atria
3  *
4  * This program is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation; either version 2 of the License, or
7  * (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software
16  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
17  */
18
19 #include "mdvi.h"
20
21 /* simple hash tables for MDVI */
22
23
24 struct _DviHashBucket {
25         DviHashBucket *next;
26         DviHashKey      key;
27         Ulong   hvalue;
28         void    *data;
29 };
30
31 static Ulong hash_string(DviHashKey key)
32 {
33         Uchar   *p;
34         Ulong   h, g;
35         
36         for(h = 0, p = (Uchar *)key; *p; p++) {
37                 h = (h << 4UL) + *p;
38                 if((g = h & 0xf0000000L) != 0) {
39                         h ^= (g >> 24UL);
40                         h ^= g;
41                 }
42         }
43                 
44         return h;
45 }
46
47 static int hash_compare(DviHashKey k1, DviHashKey k2)
48 {
49         return strcmp((char *)k1, (char *)k2);
50 }
51
52 void    mdvi_hash_init(DviHashTable *hash)
53 {
54         hash->buckets = NULL;
55         hash->nbucks  = 0;
56         hash->nkeys   = 0;
57         hash->hash_func = NULL;
58         hash->hash_comp = NULL;
59         hash->hash_free = NULL;
60 }
61
62 void    mdvi_hash_create(DviHashTable *hash, int size)
63 {
64         int     i;
65         
66         hash->nbucks = size;
67         hash->buckets = xnalloc(DviHashBucket *, size);
68         for(i = 0; i < size; i++)
69                 hash->buckets[i] = NULL;
70         hash->hash_func = hash_string;
71         hash->hash_comp = hash_compare;
72         hash->hash_free = NULL;
73         hash->nkeys = 0;
74 }
75
76 static DviHashBucket *hash_find(DviHashTable *hash, DviHashKey key)
77 {
78         Ulong   hval;
79         DviHashBucket *buck;
80         
81         hval = (hash->hash_func(key) % hash->nbucks);
82         
83         for(buck = hash->buckets[hval]; buck; buck = buck->next)
84                 if(hash->hash_comp(buck->key, key) == 0)
85                         break;
86         return buck;
87 }
88
89 /* Neither keys nor data are duplicated */
90 int     mdvi_hash_add(DviHashTable *hash, DviHashKey key, void *data, int rep)
91 {
92         DviHashBucket *buck = NULL;
93         Ulong   hval;
94         
95         if(rep != MDVI_HASH_UNCHECKED) {
96                 buck = hash_find(hash, key);
97                 if(buck != NULL) {
98                         if(buck->data == data)
99                                 return 0;
100                         if(rep == MDVI_HASH_UNIQUE)
101                                 return -1;
102                         if(hash->hash_free != NULL)
103                                 hash->hash_free(buck->key, buck->data);
104                 }
105         }
106         if(buck == NULL) {
107                 buck = xalloc(DviHashBucket);
108                 buck->hvalue = hash->hash_func(key);
109                 hval = (buck->hvalue % hash->nbucks);
110                 buck->next = hash->buckets[hval];
111                 hash->buckets[hval] = buck;
112                 hash->nkeys++;
113         }
114         
115         /* save key and data */
116         buck->key = key;
117         buck->data = data;
118         
119         return 0;
120 }
121
122 void    *mdvi_hash_lookup(DviHashTable *hash, DviHashKey key)
123 {
124         DviHashBucket *buck = hash_find(hash, key);
125
126         return buck ? buck->data : NULL;
127 }
128
129 static DviHashBucket *hash_remove(DviHashTable *hash, DviHashKey key)
130 {
131         DviHashBucket *buck, *last;
132         Ulong   hval;
133         
134         hval = hash->hash_func(key);
135         hval %= hash->nbucks;
136         
137         for(last = NULL, buck = hash->buckets[hval]; buck; buck = buck->next) {
138                 if(hash->hash_comp(buck->key, key) == 0)
139                         break;
140                 last = buck;
141         }
142         if(buck == NULL)
143                 return NULL;
144         if(last)
145                 last->next = buck->next;
146         else
147                 hash->buckets[hval] = buck->next;
148         hash->nkeys--;
149         return buck;
150 }
151
152 void    *mdvi_hash_remove(DviHashTable *hash, DviHashKey key)
153 {
154         DviHashBucket *buck = hash_remove(hash, key);
155         void    *data = NULL;
156
157         if(buck) {
158                 data = buck->data;
159                 mdvi_free(buck);
160         }
161         return data;
162 }
163
164 void    *mdvi_hash_remove_ptr(DviHashTable *hash, DviHashKey key)
165 {
166         DviHashBucket *buck, *last;
167         Ulong   hval;
168         void    *ptr;
169         
170         hval = hash->hash_func(key);
171         hval %= hash->nbucks;
172         
173         for(last = NULL, buck = hash->buckets[hval]; buck; buck = buck->next) {
174                 if(buck->key == key)
175                         break;
176                 last = buck;
177         }
178         if(buck == NULL)
179                 return NULL;
180         if(last)
181                 last->next = buck->next;
182         else
183                 hash->buckets[hval] = buck->next;
184         hash->nkeys--;
185         /* destroy the bucket */
186         ptr = buck->data;
187         mdvi_free(buck);
188         return ptr;
189 }
190
191 int     mdvi_hash_destroy_key(DviHashTable *hash, DviHashKey key)
192 {
193         DviHashBucket *buck = hash_remove(hash, key);
194         
195         if(buck == NULL)
196                 return -1;
197         if(hash->hash_free)
198                 hash->hash_free(buck->key, buck->data);
199         mdvi_free(buck);
200         return 0;       
201 }
202
203 void    mdvi_hash_reset(DviHashTable *hash, int reuse)
204 {
205         int     i;
206         DviHashBucket *buck;
207         
208         /* remove all keys in the hash table */
209         for(i = 0; i < hash->nbucks; i++) {
210                 for(; (buck = hash->buckets[i]); ) {
211                         hash->buckets[i] = buck->next;
212                         if(hash->hash_free)
213                                 hash->hash_free(buck->key, buck->data);
214                         mdvi_free(buck);
215                 }
216         }
217         hash->nkeys = 0;
218         if(!reuse && hash->buckets) {
219                 mdvi_free(hash->buckets);
220                 hash->buckets = NULL;
221                 hash->nbucks = 0;
222         } /* otherwise, it is left empty, ready to be reused */
223 }