o_names.c revision 55714
1#include <stdio.h>
2#include <stdlib.h>
3#include <string.h>
4
5#include <openssl/lhash.h>
6#include <openssl/objects.h>
7
8/* I use the ex_data stuff to manage the identifiers for the obj_name_types
9 * that applications may define.  I only really use the free function field.
10 */
11static LHASH *names_lh=NULL;
12static int names_type_num=OBJ_NAME_TYPE_NUM;
13static STACK *names_cmp=NULL;
14static STACK *names_hash=NULL;
15static STACK *names_free=NULL;
16
17static unsigned long obj_name_hash(OBJ_NAME *a);
18static int obj_name_cmp(OBJ_NAME *a,OBJ_NAME *b);
19
20int OBJ_NAME_init(void)
21	{
22	if (names_lh != NULL) return(1);
23	MemCheck_off();
24	names_lh=lh_new(obj_name_hash,obj_name_cmp);
25	MemCheck_on();
26	return(names_lh != NULL);
27	}
28
29int OBJ_NAME_new_index(unsigned long (*hash_func)(), int (*cmp_func)(),
30	     void (*free_func)())
31	{
32	int ret;
33	int i;
34
35	if (names_free == NULL)
36		{
37		MemCheck_off();
38		names_hash=sk_new_null();
39		names_cmp=sk_new_null();
40		names_free=sk_new_null();
41		MemCheck_on();
42		}
43	if ((names_free == NULL) || (names_hash == NULL) || (names_cmp == NULL))
44		{
45		/* ERROR */
46		return(0);
47		}
48	ret=names_type_num;
49	names_type_num++;
50	for (i=sk_num(names_free); i<names_type_num; i++)
51		{
52		MemCheck_off();
53		sk_push(names_hash,(char *)strcmp);
54		sk_push(names_cmp,(char *)lh_strhash);
55		sk_push(names_free,NULL);
56		MemCheck_on();
57		}
58	if (hash_func != NULL)
59		sk_set(names_hash,ret,(char *)hash_func);
60	if (cmp_func != NULL)
61		sk_set(names_cmp,ret,(char *)cmp_func);
62	if (free_func != NULL)
63		sk_set(names_free,ret,(char *)free_func);
64	return(ret);
65	}
66
67static int obj_name_cmp(OBJ_NAME *a, OBJ_NAME *b)
68	{
69	int ret;
70	int (*cmp)();
71
72	ret=a->type-b->type;
73	if (ret == 0)
74		{
75		if ((names_cmp != NULL) && (sk_num(names_cmp) > a->type))
76			{
77			cmp=(int (*)())sk_value(names_cmp,a->type);
78			ret=cmp(a->name,b->name);
79			}
80		else
81			ret=strcmp(a->name,b->name);
82		}
83	return(ret);
84	}
85
86static unsigned long obj_name_hash(OBJ_NAME *a)
87	{
88	unsigned long ret;
89	unsigned long (*hash)();
90
91	if ((names_hash != NULL) && (sk_num(names_hash) > a->type))
92		{
93		hash=(unsigned long (*)())sk_value(names_hash,a->type);
94		ret=hash(a->name);
95		}
96	else
97		{
98		ret=lh_strhash(a->name);
99		}
100	ret^=a->type;
101	return(ret);
102	}
103
104const char *OBJ_NAME_get(const char *name, int type)
105	{
106	OBJ_NAME on,*ret;
107	int num=0,alias;
108
109	if (name == NULL) return(NULL);
110	if ((names_lh == NULL) && !OBJ_NAME_init()) return(NULL);
111
112	alias=type&OBJ_NAME_ALIAS;
113	type&= ~OBJ_NAME_ALIAS;
114
115	on.name=name;
116	on.type=type;
117
118	for (;;)
119		{
120		ret=(OBJ_NAME *)lh_retrieve(names_lh,(char *)&on);
121		if (ret == NULL) return(NULL);
122		if ((ret->alias) && !alias)
123			{
124			if (++num > 10) return(NULL);
125			on.name=ret->data;
126			}
127		else
128			{
129			return(ret->data);
130			}
131		}
132	}
133
134int OBJ_NAME_add(const char *name, int type, const char *data)
135	{
136	void (*f)();
137	OBJ_NAME *onp,*ret;
138	int alias;
139
140	if ((names_lh == NULL) && !OBJ_NAME_init()) return(0);
141
142	alias=type&OBJ_NAME_ALIAS;
143	type&= ~OBJ_NAME_ALIAS;
144
145	onp=(OBJ_NAME *)Malloc(sizeof(OBJ_NAME));
146	if (onp == NULL)
147		{
148		/* ERROR */
149		return(0);
150		}
151
152	onp->name=name;
153	onp->alias=alias;
154	onp->type=type;
155	onp->data=data;
156
157	ret=(OBJ_NAME *)lh_insert(names_lh,(char *)onp);
158	if (ret != NULL)
159		{
160		/* free things */
161		if ((names_free != NULL) && (sk_num(names_free) > ret->type))
162			{
163			f=(void (*)())sk_value(names_free,ret->type);
164			f(ret->name,ret->type,ret->data);
165			}
166		Free((char *)ret);
167		}
168	else
169		{
170		if (lh_error(names_lh))
171			{
172			/* ERROR */
173			return(0);
174			}
175		}
176	return(1);
177	}
178
179int OBJ_NAME_remove(const char *name, int type)
180	{
181	OBJ_NAME on,*ret;
182	void (*f)();
183
184	if (names_lh == NULL) return(0);
185
186	type&= ~OBJ_NAME_ALIAS;
187	on.name=name;
188	on.type=type;
189	ret=(OBJ_NAME *)lh_delete(names_lh,(char *)&on);
190	if (ret != NULL)
191		{
192		/* free things */
193		if ((names_free != NULL) && (sk_num(names_free) > type))
194			{
195			f=(void (*)())sk_value(names_free,type);
196			f(ret->name,ret->type,ret->data);
197			}
198		Free((char *)ret);
199		return(1);
200		}
201	else
202		return(0);
203	}
204
205static int free_type;
206
207static void names_lh_free(OBJ_NAME *onp, int type)
208{
209	if(onp == NULL)
210	    return;
211
212	if ((free_type < 0) || (free_type == onp->type))
213		{
214		OBJ_NAME_remove(onp->name,onp->type);
215		}
216	}
217
218void OBJ_NAME_cleanup(int type)
219	{
220	unsigned long down_load;
221
222	if (names_lh == NULL) return;
223
224	free_type=type;
225	down_load=names_lh->down_load;
226	names_lh->down_load=0;
227
228	lh_doall(names_lh,names_lh_free);
229	if (type < 0)
230		{
231		lh_free(names_lh);
232		sk_free(names_hash);
233		sk_free(names_cmp);
234		sk_free(names_free);
235		names_lh=NULL;
236		names_hash=NULL;
237		names_cmp=NULL;
238		names_free=NULL;
239		}
240	else
241		names_lh->down_load=down_load;
242	}
243
244