YAP 7.1.0
hash.c
1/*
2Copyright (C) 2004,2005,2006 (Nuno A. Fonseca) <nuno.fonseca@gmail.com>
3
4This program is free software; you can redistribute it and/or
5modify it under the terms of the GNU General Public License
6as published by the Free Software Foundation; either
7version 2 of the License, or (at your option) any later
8version.
9
10This program is distributed in the hope that it will be useful,
11but WITHOUT ANY WARRANTY; without even the implied warranty of
12MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13GNU General Public License for more details.
14
15You should have received a copy of the GNU General Public License
16along with this program; if not, write to the Free Software
17Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18
19
20Last rev: $Id: hash.c,v 1.2 2006-06-04 19:02:07 nunofonseca Exp $
21*/
22#include <stdio.h>
23#include <stdlib.h>
24
25#include "hash.h"
26
27#define BUCKET(table,i) table->buckets[i]
28#define HASHSIZE(table) table->size
29
30static int mhash(hashtable,ulong);
31static hashnode* hash_lookup(hashtable,ulong);
32
33
34static hashnode* hash_lookup(hashtable table,ulong key){
35
36 table->last_node = BUCKET(table,mhash(table,key)); /* set a pointer to the first bucket */
37 while ( table->last_node != NULL ) {
38 if( table->last_node->value==key) return table->last_node;
39 table->last_node = table->last_node->next;
40 }
41 return NULL;
42}
43__ptr_t get_next_object(hashtable table,ulong key)
44{
45 if(table->last_node==NULL)
46 return NULL;
47 table->last_node = table->last_node->next;
48 while ( table->last_node != NULL ) {
49 if( table->last_node->value==key) return table->last_node->obj;
50 table->last_node = table->last_node->next;
51 }
52 return NULL;
53}
54
55
56/* removes the element with key 'key' and returns the object stored on it */
57__ptr_t delete(hashtable table,ulong key)
58{
59 __ptr_t obj;
60 hashnode *b,*prev=NULL;
61 int c=mhash(table,key);
62 b=BUCKET(table,c); /* set a pointer to the first bucket */
63 while( b!=NULL) {
64 if( b->value==key){
65 obj=b->obj;
66 if(prev==NULL) /* first element */
67 BUCKET(table,c)=b->next;
68 else
69 prev->next=b->next;
70 free(b);
71 table->n_entries--;
72 return obj;
73 }
74 prev = b;
75 b = b->next;
76 };
77 return NULL;
78}
79
80__ptr_t replace_object(hashtable table,ulong key,__ptr_t newobj)
81{
82 __ptr_t old;
83 hashnode *b=hash_lookup(table,key);
84
85 if(b==NULL)return NULL;
86 old=b->obj;
87 b->obj=newobj;
88 return old;
89}
90
91/* looks a 'bucket' in the hashing table whith 'key' and return the
92 pointer to the object stored in that bucket or NULL if no bucket is found */
93__ptr_t get_object(hashtable table,ulong key){
94
95 hashnode *b=hash_lookup(table,key);
96 if(b==NULL)
97 return NULL;
98 return b->obj;
99}
100
101/* Allocates space to a new hash table */
102hashtable new_hashtable(ulong hashsize) {
103 hashtable new;
104 register int i;
105
106 if( (new = (hashtable)malloc(sizeof(struct hashtable_s)))==NULL) return NULL;
107
108 if( (new->buckets = (hashnode**)malloc(sizeof(hashnode*)*hashsize))==NULL)
109 return NULL;
110 new->size=hashsize;
111 new->last_bucket=0;
112 new->last_node=NULL;
113 new->n_entries=0;
114 for(i=0;i<hashsize;++i) BUCKET(new,i) = NULL;
115 return new;
116}
117
118/* A very simple hashing function */
119static int mhash(hashtable table,ulong key)
120{
121 return (int)(key%HASHSIZE(table));
122}
123
124/* inserts a new element in the hash table*/
125int insere(hashtable table,ulong key,__ptr_t obj)
126{
127 int ind;
128 hashnode *new;
129 if((new=(hashnode *)malloc(sizeof(hashnode)))==NULL) return -1;
130 ind=mhash(table,key);
131
132 new->next = BUCKET(table,ind);
133 new->value=key;
134 new->obj=obj;
135 BUCKET(table,ind)=new;
136 table->n_entries++;
137 return 1;
138}
139
140void free_hashtable(hashtable table)
141{
142 register int i;
143 hashnode *n,*tmp;
144 //fprintf(stderr,"free_hashtable\n");fflush(stderr);
145 if (table==NULL) return;
146 for(i=0;i<HASHSIZE(table);++i) {
147 n=BUCKET(table,i);
148 while(n!=NULL) {
149 tmp=n;
150 n=n->next;
151 free(tmp);
152 }
153 }
154 free(table->buckets);
155 free(table);
156}
157/*********************************************************************************/
158/*
159 * Returns all objects stored in a basket by making successive calls
160 */
161void init_hash_traversal(hashtable table) {
162 table->last_bucket=0;
163 table->last_node=NULL;
164}
165/*
166 * Returns all objects stored in a basket by making successive calls
167 */
168__ptr_t next_hash_object(hashtable table)
169{
170 // first time....
171 if( table->last_bucket>=HASHSIZE(table))
172 return NULL;
173
174 if( table->last_node==NULL ) {
175 // find bucket
176 // find next bucket
177 while ( table->last_node == NULL && table->last_bucket+1<HASHSIZE(table)) {
178 ++table->last_bucket;
179 table->last_node = BUCKET(table,table->last_bucket);
180 }
181 if (table->last_node==NULL)
182 return NULL;
183 return table->last_node->obj;
184 }
185 // Next in bucket
186 table->last_node=table->last_node->next;
187 if (table->last_node==NULL) return next_hash_object(table);
188 return table->last_node->obj;
189}
190
191/*
192 * Returns all hash nodes stored in a basket by making successive calls
193 */
194__ptr_t next_hashnode(hashtable table)
195{
196 // first time....
197 if( table->last_bucket>=HASHSIZE(table))
198 return NULL;
199
200 if( table->last_node==NULL ) {
201 // find bucket
202 // find next bucket
203 while ( table->last_node == NULL && table->last_bucket+1<HASHSIZE(table)) {
204 ++table->last_bucket;
205 table->last_node = BUCKET(table,table->last_bucket);
206 }
207 if (table->last_node==NULL)
208 return NULL;
209 return table->last_node;
210 }
211 // Next in bucket
212 table->last_node=table->last_node->next;
213 if (table->last_node==NULL) return next_hashnode(table);
214 return table->last_node;
215}
216
Definition: hash.h:40