1 /*
2 * The contents of this file are subject to the terms of the
3 * Common Development and Distribution License, Version 1.0 only
4 * (the "License"). You may not use this file except in compliance
5 * with the License.
6 *
7 * See the file CDDL.Schily.txt in this distribution for details.
8 *
9 * When distributing Covered Code, include this CDDL HEADER in each
10 * file and include the License file CDDL.Schily.txt from this distribution.
11 */
12 /*
13 * @(#)lhash.c 1.3 17/05/24 Copyright 1988-2017 J. Schilling
14 */
15 #if defined(sun)
16 #pragma ident "@(#)lhash.c 1.3 17/05/24 Copyright 1988-2017 J. Schilling"
17 #endif
18
19 #if defined(sun)
20 #pragma ident "@(#)lhash.c"
21 #pragma ident "@(#)sccs:lib/comobj/lhash.c"
22 #endif
23 #include <defines.h>
24
25
26 #define HASH_DFLT_SIZE 128
27
28 static struct h_elem {
29 struct h_elem *h_next;
30 char h_data[1]; /* Variable size. */
31 } **h_tab;
32
33 static size_t h_size;
34
35 EXPORT size_t lhash_size __PR((size_t size));
36 EXPORT void lhash_destroy __PR((void));
37 EXPORT char *lhash_add __PR((char *str));
38 LOCAL char *_lhash_add __PR((char *str, struct h_elem **htab));
39 EXPORT char *lhash_lookup __PR((char *str));
40 LOCAL int lhashval __PR((unsigned char *str, unsigned int maxsize));
41
42 EXPORT size_t
lhash_size(size)43 lhash_size(size)
44 size_t size;
45 {
46 if (h_size == 0)
47 h_size = size;
48 return (h_size);
49 }
50
51 /*
52 * Warning: we use fmalloc() and thus our memory is freed by ffreeall(), but
53 * the variables h_size and h_tab keep their values unless we clear them.
54 */
55 EXPORT void
lhash_destroy()56 lhash_destroy()
57 {
58 h_size = 0;
59 h_tab = NULL;
60 }
61
62 EXPORT char *
lhash_add(str)63 lhash_add(str)
64 char *str;
65 {
66 if (h_tab == NULL) {
67 register int i;
68 register size_t size = lhash_size(HASH_DFLT_SIZE);
69
70 h_tab = fmalloc(size * sizeof (struct h_elem *));
71 for (i = 0; i < size; i++) {
72 h_tab[i] = NULL;
73 }
74 }
75 return (_lhash_add(str, h_tab));
76 }
77
78 LOCAL char *
_lhash_add(str,htab)79 _lhash_add(str, htab)
80 char *str;
81 register struct h_elem **htab;
82 {
83 register struct h_elem *hp;
84 register int len;
85 register int hv;
86 register size_t size;
87
88 size = lhash_size(HASH_DFLT_SIZE);
89 len = strlen(str);
90 if (len == 0)
91 return ("");
92
93 hp = fmalloc((size_t)len + 1 + sizeof (struct h_elem *));
94 strcpy(hp->h_data, str);
95 hv = lhashval((unsigned char *)str, size);
96 hp->h_next = htab[hv];
97 htab[hv] = hp;
98 return (hp->h_data);
99 }
100
101 EXPORT char *
lhash_lookup(str)102 lhash_lookup(str)
103 char *str;
104 {
105 register struct h_elem *hp;
106 register int hv;
107
108 if (h_tab == NULL)
109 return (lhash_add(str));
110
111 hv = lhashval((unsigned char *)str, h_size);
112 for (hp = h_tab[hv]; hp; hp = hp->h_next)
113 if (equal(str, hp->h_data))
114 return (hp->h_data);
115 return (lhash_add(str));
116 }
117
118 LOCAL int
lhashval(str,maxsize)119 lhashval(str, maxsize)
120 register unsigned char *str;
121 unsigned maxsize;
122 {
123 register int sum = 0;
124 register int i;
125 register int c;
126
127 for (i = 0; (c = *str++) != '\0'; i++)
128 sum ^= (c << (i&7));
129 return (sum % maxsize);
130 }
131