5 * This file is part of Maemo Mapper.
7 * Maemo Mapper is free software: you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation, either version 3 of the License, or
10 * (at your option) any later version.
12 * Maemo Mapper is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with Maemo Mapper. If not, see <http://www.gnu.org/licenses/>.
21 * Parts of this code have been ported from Xastir by Rob Williams (10 Aug 2008):
23 * * XASTIR, Amateur Station Tracking and Information Reporting
24 * Copyright (C) 1999,2000 Frank Giannandrea
25 * Copyright (C) 2000-2007 The Xastir Group
26 * Copyright (C) 2004 Christopher Clark <firstname.lastname@cl.cam.ac.uk>
40 #include "hashtable.h"
41 #include "hashtable_private.h"
44 Credit for primes table: Aaron Krowne
45 http://br.endernet.org/~akrowne/
46 http://planetmath.org/encyclopedia/GoodHashTablePrimes.html
48 static const unsigned int primes[] = {
50 769, 1543, 3079, 6151,
51 12289, 24593, 49157, 98317,
52 196613, 393241, 786433, 1572869,
53 3145739, 6291469, 12582917, 25165843,
54 50331653, 100663319, 201326611, 402653189,
57 const unsigned int prime_table_length = sizeof(primes)/sizeof(primes[0]);
58 const float max_load_factor = 0.65;
60 /*****************************************************************************/
62 create_hashtable(unsigned int minsize,
63 unsigned int (*hashf) (void*),
64 int (*eqf) (void*,void*))
67 unsigned int pindex, size = primes[0];
68 /* Check requested hashtable isn't too large */
69 if (minsize > (1u << 30)) return NULL;
70 /* Enforce size as prime */
71 for (pindex=0; pindex < prime_table_length; pindex++) {
72 if (primes[pindex] > minsize) { size = primes[pindex]; break; }
74 h = (struct hashtable *)malloc(sizeof(struct hashtable));
75 if (NULL == h) return NULL; /*oom*/
76 h->table = (struct entry **)malloc(sizeof(struct entry*) * size);
77 if (NULL == h->table) { free(h); return NULL; } /*oom*/
78 memset(h->table, 0, size * sizeof(struct entry *));
79 h->tablelength = size;
80 h->primeindex = pindex;
84 h->loadlimit = (unsigned int) ceil(size * max_load_factor);
88 /*****************************************************************************/
90 hash(struct hashtable *h, void *k)
92 /* Aim to protect against poor hash functions by adding logic here
93 * - logic taken from java 1.4 hashtable source */
94 unsigned int i = h->hashfn(k);
96 i ^= ((i >> 14) | (i << 18)); /* >>> */
98 i ^= ((i >> 10) | (i << 22)); /* >>> */
102 /*****************************************************************************/
104 hashtable_expand(struct hashtable *h)
106 /* Double the size of the table to accomodate more entries */
107 struct entry **newtable;
110 unsigned int newsize, i, index;
111 /* Check we're not hitting max capacity */
112 if (h->primeindex == (prime_table_length - 1)) return 0;
113 newsize = primes[++(h->primeindex)];
115 newtable = (struct entry **)malloc(sizeof(struct entry*) * newsize);
116 if (NULL != newtable)
118 memset(newtable, 0, newsize * sizeof(struct entry *));
119 /* This algorithm is not 'stable'. ie. it reverses the list
120 * when it transfers entries between the tables */
121 for (i = 0; i < h->tablelength; i++) {
122 while (NULL != (e = h->table[i])) {
123 h->table[i] = e->next;
124 index = indexFor(newsize,e->h);
125 e->next = newtable[index];
132 /* Plan B: realloc instead */
135 newtable = (struct entry **)
136 realloc(h->table, newsize * sizeof(struct entry *));
137 if (NULL == newtable) { (h->primeindex)--; return 0; }
139 memset(newtable[h->tablelength], 0, newsize - h->tablelength);
140 for (i = 0; i < h->tablelength; i++) {
141 for (pE = &(newtable[i]), e = *pE; e != NULL; e = *pE) {
142 index = indexFor(newsize,e->h);
150 e->next = newtable[index];
156 h->tablelength = newsize;
157 h->loadlimit = (unsigned int) ceil(newsize * max_load_factor);
161 /*****************************************************************************/
163 hashtable_count(struct hashtable *h)
165 return h->entrycount;
168 /*****************************************************************************/
170 hashtable_insert(struct hashtable *h, void *k, void *v)
172 /* This method allows duplicate keys - but they shouldn't be used */
175 if (++(h->entrycount) > h->loadlimit)
177 /* Ignore the return value. If expand fails, we should
178 * still try cramming just this value into the existing table
179 * -- we may not have memory for a larger table, but one more
180 * element may be ok. Next time we insert, we'll try expanding again.*/
183 e = (struct entry *)malloc(sizeof(struct entry));
184 if (NULL == e) { --(h->entrycount); return 0; } /*oom*/
186 index = indexFor(h->tablelength,e->h);
189 e->next = h->table[index];
194 /*****************************************************************************/
195 void * /* returns value associated with key */
196 hashtable_search(struct hashtable *h, void *k)
199 unsigned int hashvalue, index;
200 hashvalue = hash(h,k);
201 index = indexFor(h->tablelength,hashvalue);
205 /* Check hash value to short circuit heavier comparison */
206 if ((hashvalue == e->h) && (h->eqfn(k, e->k))) return e->v;
212 /*****************************************************************************/
213 void * /* returns value associated with key */
214 hashtable_remove(struct hashtable *h, void *k)
216 /* TODO: consider compacting the table when the load factor drops enough,
217 * or provide a 'compact' method. */
222 unsigned int hashvalue, index;
224 hashvalue = hash(h,k);
225 index = indexFor(h->tablelength,hash(h,k));
226 pE = &(h->table[index]);
230 /* Check hash value to short circuit heavier comparison */
231 if ((hashvalue == e->h) && (h->eqfn(k, e->k)))
246 /*****************************************************************************/
249 hashtable_destroy(struct hashtable *h, int free_values)
253 struct entry **table = h->table;
256 for (i = 0; i < h->tablelength; i++)
260 { f = e; e = e->next; freekey(f->k); free(f->v); free(f); }
265 for (i = 0; i < h->tablelength; i++)
269 { f = e; e = e->next; freekey(f->k); free(f); }
276 #endif // INCLUDE_APRS
279 * Copyright (C) 2002 Christopher Clark <firstname.lastname@cl.cam.ac.uk>
281 * Permission is hereby granted, free of charge, to any person obtaining a copy
282 * of this software and associated documentation files (the "Software"), to
283 * deal in the Software without restriction, including without limitation the
284 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
285 * sell copies of the Software, and to permit persons to whom the Software is
286 * furnished to do so, subject to the following conditions:
288 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
289 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
290 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
291 * THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
292 * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
293 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.