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