xref: /openbsd-src/lib/libcrypto/stack/stack.c (revision 1fc27e414118cd8922c6b93fbaeb7a5246bfd593)
1 /* crypto/stack/stack.c */
2 /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
3  * All rights reserved.
4  *
5  * This package is an SSL implementation written
6  * by Eric Young (eay@cryptsoft.com).
7  * The implementation was written so as to conform with Netscapes SSL.
8  *
9  * This library is free for commercial and non-commercial use as long as
10  * the following conditions are aheared to.  The following conditions
11  * apply to all code found in this distribution, be it the RC4, RSA,
12  * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
13  * included with this distribution is covered by the same copyright terms
14  * except that the holder is Tim Hudson (tjh@cryptsoft.com).
15  *
16  * Copyright remains Eric Young's, and as such any Copyright notices in
17  * the code are not to be removed.
18  * If this package is used in a product, Eric Young should be given attribution
19  * as the author of the parts of the library used.
20  * This can be in the form of a textual message at program startup or
21  * in documentation (online or textual) provided with the package.
22  *
23  * Redistribution and use in source and binary forms, with or without
24  * modification, are permitted provided that the following conditions
25  * are met:
26  * 1. Redistributions of source code must retain the copyright
27  *    notice, this list of conditions and the following disclaimer.
28  * 2. Redistributions in binary form must reproduce the above copyright
29  *    notice, this list of conditions and the following disclaimer in the
30  *    documentation and/or other materials provided with the distribution.
31  * 3. All advertising materials mentioning features or use of this software
32  *    must display the following acknowledgement:
33  *    "This product includes cryptographic software written by
34  *     Eric Young (eay@cryptsoft.com)"
35  *    The word 'cryptographic' can be left out if the rouines from the library
36  *    being used are not cryptographic related :-).
37  * 4. If you include any Windows specific code (or a derivative thereof) from
38  *    the apps directory (application code) you must include an acknowledgement:
39  *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
40  *
41  * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
42  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
43  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
44  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
45  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
46  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
47  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
48  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
49  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
50  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
51  * SUCH DAMAGE.
52  *
53  * The licence and distribution terms for any publically available version or
54  * derivative of this code cannot be changed.  i.e. this code cannot simply be
55  * copied and put under another distribution licence
56  * [including the GNU Public Licence.]
57  */
58 
59 /* Code for stacks
60  * Author - Eric Young v 1.0
61  * 1.2 eay 12-Mar-97 -	Modified sk_find so that it _DOES_ return the
62  *			lowest index for the seached item.
63  *
64  * 1.1 eay - Take from netdb and added to SSLeay
65  *
66  * 1.0 eay - First version 29/07/92
67  */
68 #include <stdio.h>
69 #include "cryptlib.h"
70 #include <openssl/stack.h>
71 
72 #undef MIN_NODES
73 #define MIN_NODES	4
74 
75 const char *STACK_version="Stack" OPENSSL_VERSION_PTEXT;
76 
77 #define	FP_ICC	(int (*)(const void *,const void *))
78 #include <errno.h>
79 
80 int (*sk_set_cmp_func(STACK *sk, int (*c)()))(void)
81 	{
82 	int (*old)()=sk->comp;
83 
84 	if (sk->comp != c)
85 		sk->sorted=0;
86 	sk->comp=c;
87 
88 	return old;
89 	}
90 
91 STACK *sk_dup(STACK *sk)
92 	{
93 	STACK *ret;
94 	char **s;
95 
96 	if ((ret=sk_new(sk->comp)) == NULL) goto err;
97 	s=(char **)Realloc((char *)ret->data,
98 		(unsigned int)sizeof(char *)*sk->num_alloc);
99 	if (s == NULL) goto err;
100 	ret->data=s;
101 
102 	ret->num=sk->num;
103 	memcpy(ret->data,sk->data,sizeof(char *)*sk->num);
104 	ret->sorted=sk->sorted;
105 	ret->num_alloc=sk->num_alloc;
106 	ret->comp=sk->comp;
107 	return(ret);
108 err:
109 	return(NULL);
110 	}
111 
112 STACK *sk_new(int (*c)())
113 	{
114 	STACK *ret;
115 	int i;
116 
117 	if ((ret=(STACK *)Malloc(sizeof(STACK))) == NULL)
118 		goto err0;
119 	if ((ret->data=(char **)Malloc(sizeof(char *)*MIN_NODES)) == NULL)
120 		goto err1;
121 	for (i=0; i<MIN_NODES; i++)
122 		ret->data[i]=NULL;
123 	ret->comp=c;
124 	ret->num_alloc=MIN_NODES;
125 	ret->num=0;
126 	ret->sorted=0;
127 	return(ret);
128 err1:
129 	Free((char *)ret);
130 err0:
131 	return(NULL);
132 	}
133 
134 int sk_insert(STACK *st, char *data, int loc)
135 	{
136 	char **s;
137 
138 	if(st == NULL) return 0;
139 	if (st->num_alloc <= st->num+1)
140 		{
141 		s=(char **)Realloc((char *)st->data,
142 			(unsigned int)sizeof(char *)*st->num_alloc*2);
143 		if (s == NULL)
144 			return(0);
145 		st->data=s;
146 		st->num_alloc*=2;
147 		}
148 	if ((loc >= (int)st->num) || (loc < 0))
149 		st->data[st->num]=data;
150 	else
151 		{
152 		int i;
153 		char **f,**t;
154 
155 		f=(char **)st->data;
156 		t=(char **)&(st->data[1]);
157 		for (i=st->num; i>=loc; i--)
158 			t[i]=f[i];
159 
160 #ifdef undef /* no memmove on sunos :-( */
161 		memmove( (char *)&(st->data[loc+1]),
162 			(char *)&(st->data[loc]),
163 			sizeof(char *)*(st->num-loc));
164 #endif
165 		st->data[loc]=data;
166 		}
167 	st->num++;
168 	st->sorted=0;
169 	return(st->num);
170 	}
171 
172 char *sk_delete_ptr(STACK *st, char *p)
173 	{
174 	int i;
175 
176 	for (i=0; i<st->num; i++)
177 		if (st->data[i] == p)
178 			return(sk_delete(st,i));
179 	return(NULL);
180 	}
181 
182 char *sk_delete(STACK *st, int loc)
183 	{
184 	char *ret;
185 	int i,j;
186 
187 	if ((st == NULL) || (st->num == 0) || (loc < 0)
188 					 || (loc >= st->num)) return(NULL);
189 
190 	ret=st->data[loc];
191 	if (loc != st->num-1)
192 		{
193 		j=st->num-1;
194 		for (i=loc; i<j; i++)
195 			st->data[i]=st->data[i+1];
196 		/* In theory memcpy is not safe for this
197 		 * memcpy( &(st->data[loc]),
198 		 *	&(st->data[loc+1]),
199 		 *	sizeof(char *)*(st->num-loc-1));
200 		 */
201 		}
202 	st->num--;
203 	return(ret);
204 	}
205 
206 int sk_find(STACK *st, char *data)
207 	{
208 	char **r;
209 	int i;
210 	int (*comp_func)();
211 	if(st == NULL) return -1;
212 
213 	if (st->comp == NULL)
214 		{
215 		for (i=0; i<st->num; i++)
216 			if (st->data[i] == data)
217 				return(i);
218 		return(-1);
219 		}
220 	sk_sort(st);
221 	if (data == NULL) return(-1);
222 	comp_func=(int (*)())st->comp;
223 	r=(char **)bsearch(&data,(char *)st->data,
224 		st->num,sizeof(char *),FP_ICC comp_func);
225 	if (r == NULL) return(-1);
226 	i=(int)(r-st->data);
227 	for ( ; i>0; i--)
228 		if ((*st->comp)(&(st->data[i-1]),&data) < 0)
229 			break;
230 	return(i);
231 	}
232 
233 int sk_push(STACK *st, char *data)
234 	{
235 	return(sk_insert(st,data,st->num));
236 	}
237 
238 int sk_unshift(STACK *st, char *data)
239 	{
240 	return(sk_insert(st,data,0));
241 	}
242 
243 char *sk_shift(STACK *st)
244 	{
245 	if (st == NULL) return(NULL);
246 	if (st->num <= 0) return(NULL);
247 	return(sk_delete(st,0));
248 	}
249 
250 char *sk_pop(STACK *st)
251 	{
252 	if (st == NULL) return(NULL);
253 	if (st->num <= 0) return(NULL);
254 	return(sk_delete(st,st->num-1));
255 	}
256 
257 void sk_zero(STACK *st)
258 	{
259 	if (st == NULL) return;
260 	if (st->num <= 0) return;
261 	memset((char *)st->data,0,sizeof(st->data)*st->num);
262 	st->num=0;
263 	}
264 
265 void sk_pop_free(STACK *st, void (*func)())
266 	{
267 	int i;
268 
269 	if (st == NULL) return;
270 	for (i=0; i<st->num; i++)
271 		if (st->data[i] != NULL)
272 			func(st->data[i]);
273 	sk_free(st);
274 	}
275 
276 void sk_free(STACK *st)
277 	{
278 	if (st == NULL) return;
279 	if (st->data != NULL) Free((char *)st->data);
280 	Free((char *)st);
281 	}
282 
283 int sk_num(STACK *st)
284 {
285 	if(st == NULL) return -1;
286 	return st->num;
287 }
288 
289 char *sk_value(STACK *st, int i)
290 {
291 	if(st == NULL) return NULL;
292 	return st->data[i];
293 }
294 
295 char *sk_set(STACK *st, int i, char *value)
296 {
297 	if(st == NULL) return NULL;
298 	return (st->data[i] = value);
299 }
300 
301 void sk_sort(STACK *st)
302     {
303     if (!st->sorted)
304 	{
305 	int (*comp_func)();
306 
307 	comp_func=(int (*)())st->comp;
308 	qsort(st->data,st->num,sizeof(char *),FP_ICC comp_func);
309 	st->sorted=1;
310 	}
311     }
312