Evince
Evince is a document viewer capable of displaying multiple and single page document formats like PDF and Postscript.
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
hash.c
Go to the documentation of this file.
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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17  */
18 
19 #include <config.h>
20 #include "mdvi.h"
21 
22 /* simple hash tables for MDVI */
23 
24 
29  void *data;
30 };
31 
33 {
34  Uchar *p;
35  Ulong h, g;
36 
37  for(h = 0, p = (Uchar *)key; *p; p++) {
38  h = (h << 4UL) + *p;
39  if((g = h & 0xf0000000L) != 0) {
40  h ^= (g >> 24UL);
41  h ^= g;
42  }
43  }
44 
45  return h;
46 }
47 
49 {
50  return strcmp((char *)k1, (char *)k2);
51 }
52 
54 {
55  hash->buckets = NULL;
56  hash->nbucks = 0;
57  hash->nkeys = 0;
58  hash->hash_func = NULL;
59  hash->hash_comp = NULL;
60  hash->hash_free = NULL;
61 }
62 
63 void mdvi_hash_create(DviHashTable *hash, int size)
64 {
65  int i;
66 
67  hash->nbucks = size;
68  hash->buckets = xnalloc(DviHashBucket *, size);
69  for(i = 0; i < size; i++)
70  hash->buckets[i] = NULL;
71  hash->hash_func = hash_string;
72  hash->hash_comp = hash_compare;
73  hash->hash_free = NULL;
74  hash->nkeys = 0;
75 }
76 
78 {
79  Ulong hval;
80  DviHashBucket *buck;
81 
82  hval = (hash->hash_func(key) % hash->nbucks);
83 
84  for(buck = hash->buckets[hval]; buck; buck = buck->next)
85  if(hash->hash_comp(buck->key, key) == 0)
86  break;
87  return buck;
88 }
89 
90 /* Neither keys nor data are duplicated */
91 int mdvi_hash_add(DviHashTable *hash, DviHashKey key, void *data, int rep)
92 {
93  DviHashBucket *buck = NULL;
94  Ulong hval;
95 
96  if(rep != MDVI_HASH_UNCHECKED) {
97  buck = hash_find(hash, key);
98  if(buck != NULL) {
99  if(buck->data == data)
100  return 0;
101  if(rep == MDVI_HASH_UNIQUE)
102  return -1;
103  if(hash->hash_free != NULL)
104  hash->hash_free(buck->key, buck->data);
105  }
106  }
107  if(buck == NULL) {
108  buck = xalloc(DviHashBucket);
109  buck->hvalue = hash->hash_func(key);
110  hval = (buck->hvalue % hash->nbucks);
111  buck->next = hash->buckets[hval];
112  hash->buckets[hval] = buck;
113  hash->nkeys++;
114  }
115 
116  /* save key and data */
117  buck->key = key;
118  buck->data = data;
119 
120  return 0;
121 }
122 
124 {
125  DviHashBucket *buck = hash_find(hash, key);
126 
127  return buck ? buck->data : NULL;
128 }
129 
131 {
132  DviHashBucket *buck, *last;
133  Ulong hval;
134 
135  hval = hash->hash_func(key);
136  hval %= hash->nbucks;
137 
138  for(last = NULL, buck = hash->buckets[hval]; buck; buck = buck->next) {
139  if(hash->hash_comp(buck->key, key) == 0)
140  break;
141  last = buck;
142  }
143  if(buck == NULL)
144  return NULL;
145  if(last)
146  last->next = buck->next;
147  else
148  hash->buckets[hval] = buck->next;
149  hash->nkeys--;
150  return buck;
151 }
152 
154 {
155  DviHashBucket *buck = hash_remove(hash, key);
156  void *data = NULL;
157 
158  if(buck) {
159  data = buck->data;
160  mdvi_free(buck);
161  }
162  return data;
163 }
164 
166 {
167  DviHashBucket *buck, *last;
168  Ulong hval;
169  void *ptr;
170 
171  hval = hash->hash_func(key);
172  hval %= hash->nbucks;
173 
174  for(last = NULL, buck = hash->buckets[hval]; buck; buck = buck->next) {
175  if(buck->key == key)
176  break;
177  last = buck;
178  }
179  if(buck == NULL)
180  return NULL;
181  if(last)
182  last->next = buck->next;
183  else
184  hash->buckets[hval] = buck->next;
185  hash->nkeys--;
186  /* destroy the bucket */
187  ptr = buck->data;
188  mdvi_free(buck);
189  return ptr;
190 }
191 
193 {
194  DviHashBucket *buck = hash_remove(hash, key);
195 
196  if(buck == NULL)
197  return -1;
198  if(hash->hash_free)
199  hash->hash_free(buck->key, buck->data);
200  mdvi_free(buck);
201  return 0;
202 }
203 
204 void mdvi_hash_reset(DviHashTable *hash, int reuse)
205 {
206  int i;
207  DviHashBucket *buck;
208 
209  /* remove all keys in the hash table */
210  for(i = 0; i < hash->nbucks; i++) {
211  for(; (buck = hash->buckets[i]); ) {
212  hash->buckets[i] = buck->next;
213  if(hash->hash_free)
214  hash->hash_free(buck->key, buck->data);
215  mdvi_free(buck);
216  }
217  }
218  hash->nkeys = 0;
219  if(!reuse && hash->buckets) {
220  mdvi_free(hash->buckets);
221  hash->buckets = NULL;
222  hash->nbucks = 0;
223  } /* otherwise, it is left empty, ready to be reused */
224 }