1 /*  GNU Thales - IRC to Relational Database Gateway
2  *  Copyright (C) 2002 Lucas Nussbaum <lucas@lucas-nussbaum.net>
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 "hashlist.h"
20 #include "log.h"
21 
22 extern int verbose;
23 
24 /* creates a new hashlist */
newhashlist()25 hashlist newhashlist()
26 {
27 	hashlist h = (hashlist) malloc(sizeof(struct item *) * 256);
28 	memset(h, 0, sizeof(struct item *) * 256);
29 	return h;
30 }
31 
32 /* returns an hashcode for the given string */
33 #define HASHSHIFT 5
hash(char * s,int keytype)34 int hash(char *s, int keytype)
35 {
36 	int h = 0;
37 	if (verbose)
38 		/* dont use the # if chan */
39 		if (keytype == KEYCHAN)
40 			s++;
41 	while (*s)
42 	{
43 		/* imported from ispell and modified */
44 		h = (h << HASHSHIFT)
45 			| ((h >> (8 - HASHSHIFT)) & ((1 << HASHSHIFT) - 1));
46 		h ^= *s++;
47 	}
48 	return h & ((1 << 8) - 1);
49 }
50 
51 /* adds an element to the hashlist */
hash_add(hashlist h,char * str,int n,int keytype)52 void hash_add(hashlist h, char *str, int n, int keytype)
53 {
54 	struct item *pio;
55 	struct item *pin;
56 	int key = hash(str, keytype);
57 	if (verbose)
58 		mylog("HASH : hash_add %d, %s, %d, %d", (int) h, str, n, keytype);
59 	pio = h[key];
60 	pin = (struct item *) malloc(sizeof(struct item));
61 	pin->str = strdup(str);
62 	pin->n = n;
63 	pin->next = pio;
64 	h[key] = pin;
65 }
66 
67 /* deletes an element from the hashlist */
hash_del(hashlist h,char * str,int keytype)68 void hash_del(hashlist h, char *str, int keytype)
69 {
70 	struct item *pi, **piold;
71 	if (verbose)
72 		mylog("HASH : hash_del %d, %s, %d", (int) h, str, keytype);
73 	for (piold = &h[hash(str, keytype)], pi = *piold; pi; pi = pi->next)
74 	{
75 		if (!strcmp(str, pi->str))
76 		{
77 			*piold = pi->next;
78 			free(pi->str);
79 			free(pi);
80 			if (hash_find_unsure(h, str, keytype) != -1)
81 				fatal("deleted %s but still present !", str);
82 			return;
83 		}
84 		piold = &(pi->next);
85 	}
86 	fatal("hashlist element %s not found !", str);
87 }
88 
89 /* finds an element in the hashlist - crash if not found */
hash_find(hashlist h,char * str,int keytype)90 int hash_find(hashlist h, char *str, int keytype)
91 {
92 	int res;
93 	if (verbose)
94 		mylog("HASH : hash_find %d, %s, %d", (int) h, str, keytype);
95 	res = hash_find_unsure(h, str, keytype);
96 	if (res != -1)
97 		return res;
98 	fatal("hashlist element %s not found !", str);
99 	return 0;						  /* prevents compiler warnings */
100 }
101 
102 /* finds an element in the hashlist - returns -1 if not found */
hash_find_unsure(hashlist h,char * str,int keytype)103 int hash_find_unsure(hashlist h, char *str, int keytype)
104 {
105 	struct item *pi;
106 	if (verbose)
107 		mylog("HASH : hash_find_unsure %d, %s, %d", (int) h, str, keytype);
108 	for (pi = h[hash(str, keytype)]; pi; pi = pi->next)
109 		if (!strcmp(str, pi->str))
110 			return pi->n;
111 	return -1;
112 }
113 
114 /* finds an element in the hashlist, then remove it */
115 /* Findel, Luxembourg - where I worked when I wrote this :) */
hash_findel(hashlist h,char * str,int keytype)116 int hash_findel(hashlist h, char *str, int keytype)
117 {
118 	int n;
119 	struct item *pi, **piold;
120 	if (verbose)
121 		mylog("HASH : hash_findel %d, %s, %d", (int) h, str, keytype);
122 
123 	for (piold = &h[hash(str, keytype)], pi = *piold; pi; pi = pi->next)
124 	{
125 		if (!strcmp(str, pi->str))
126 		{
127 			n = pi->n;
128 			*piold = pi->next;
129 			free(pi->str);
130 			free(pi);
131 			return n;
132 		}
133 		piold = &(pi->next);
134 	}
135 	fatal("hashlist element %s not found !", str);
136 	return 0;						  /* to prevent compiler warnings */
137 }
138 
139 /* update an item */
hash_update(hashlist h,char * newinfo,char * str,int keytype)140 void hash_update(hashlist h, char *newinfo, char *str, int keytype)
141 {
142 	int key;
143 	int key2;
144 	if (verbose)
145 		mylog("HASH : hash_update %d, %s, %s, %d", (int) h, newinfo, str,
146 			 keytype);
147 	if ((key = hash(str, keytype)) == (key2 = hash(newinfo, keytype)))
148 	{
149 		struct item *pi;
150 
151 		for (pi = h[key]; pi; pi = pi->next)
152 			if (!strcmp(str, pi->str))
153 			{
154 				free(pi->str);
155 				pi->str = strdup(newinfo);
156 				return;
157 			}
158 		fatal("hashlist element %s not found !", str);
159 	}
160 	else
161 	{
162 		/* find and delete the old, create the new */
163 		int n;
164 		struct item *pi, **piold;
165 		struct item *pio;
166 
167 		for (piold = &h[key], pi = *piold; pi; pi = pi->next)
168 		{
169 			if (!strcmp(str, pi->str))
170 			{
171 				/* save and delete the old entry */
172 				n = pi->n;
173 				*piold = pi->next;
174 				free(pi->str);
175 				/* create the new */
176 				pio = h[key2];
177 				pi->str = strdup(newinfo);
178 				pi->n = n;
179 				pi->next = pio;
180 				h[key2] = pi;
181 				return;
182 			}
183 			piold = &(pi->next);
184 		}
185 		fatal("hashlist element %s not found !", str);
186 	}
187 }
188