4da5e45b9c54be5744c29295692849a9fff70760
[openssl.git] / crypto / objects / o_names.c
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  */
11 static LHASH *names_lh=NULL;
12 static int names_type_num=OBJ_NAME_TYPE_NUM;
13 static STACK *names_cmp=NULL;
14 static STACK *names_hash=NULL;
15 static STACK *names_free=NULL;
16
17 static unsigned long obj_name_hash(OBJ_NAME *a);
18 static int obj_name_cmp(OBJ_NAME *a,OBJ_NAME *b);
19
20 int 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
29 int 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
67 static 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
86 static 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
104 const 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
134 int 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
179 int 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
205 static int free_type;
206
207 static 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
218 void 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