xref: /netbsd-src/external/mpl/dhcp/dist/omapip/array.c (revision f407d9293b6650aa8c33d6a995f797bb6aaefd90)
1 /*	$NetBSD: array.c,v 1.3 2022/04/03 01:10:59 christos Exp $	*/
2 
3 /* listener.c
4 
5    Subroutines that support the omapi extensible array type. */
6 
7 /*
8  * Copyright (C) 2004-2022 Internet Systems Consortium, Inc. ("ISC")
9  * Copyright (c) 2001-2003 by Internet Software Consortium
10  *
11  * This Source Code Form is subject to the terms of the Mozilla Public
12  * License, v. 2.0. If a copy of the MPL was not distributed with this
13  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
14  *
15  * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
16  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
17  * MERCHANTABILITY AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR
18  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
19  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
20  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
21  * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
22  *
23  *   Internet Systems Consortium, Inc.
24  *   PO Box 360
25  *   Newmarket, NH 03857 USA
26  *   <info@isc.org>
27  *   https://www.isc.org/
28  *
29  */
30 
31 #include <sys/cdefs.h>
32 __RCSID("$NetBSD: array.c,v 1.3 2022/04/03 01:10:59 christos Exp $");
33 
34 #include "dhcpd.h"
35 
36 #include <omapip/omapip_p.h>
37 
38 /* Allocate a new extensible array. */
39 
omapi_array_allocate(omapi_array_t ** array,omapi_array_ref_t ref,omapi_array_deref_t deref,const char * file,int line)40 isc_result_t omapi_array_allocate (omapi_array_t **array,
41 				   omapi_array_ref_t ref,
42 				   omapi_array_deref_t deref,
43 				   const char *file, int line)
44 {
45 	omapi_array_t *aptr;
46 
47 	if (!array || *array)
48 		return DHCP_R_INVALIDARG;
49 	aptr = dmalloc (sizeof (omapi_array_t),file, line);
50 	if (!aptr)
51 		return ISC_R_NOMEMORY;
52 	*array = aptr;
53 	aptr -> ref = ref;
54 	aptr -> deref = deref;
55 	return ISC_R_SUCCESS;
56 }
57 
omapi_array_free(omapi_array_t ** array,const char * file,int line)58 isc_result_t omapi_array_free (omapi_array_t **array,
59 			       const char *file, int line)
60 {
61 	omapi_array_t *aptr;
62 	int i;
63 
64 	if (!array || !*array)
65 		return DHCP_R_INVALIDARG;
66 	aptr = *array;
67 	for (i = 0; i < aptr -> count; i++)
68 		if (aptr -> data [i] && aptr -> deref)
69 			(*aptr -> deref) (&aptr -> data [i], file, line);
70 	dfree (aptr -> data, MDL);
71 	dfree (aptr, MDL);
72 	*array = (omapi_array_t *)0;
73 	return ISC_R_SUCCESS;
74 }
75 
76 /* Extend the size of the array by one entry (we may allocate more than that)
77    and store the specified value in the new array element. */
78 
omapi_array_extend(omapi_array_t * array,char * ptr,int * index,const char * file,int line)79 isc_result_t omapi_array_extend (omapi_array_t *array, char *ptr,
80 				 int *index, const char *file, int line)
81 {
82 	isc_result_t status;
83 	int new = array -> count;
84 	status = omapi_array_set (array, ptr, new, file, line);
85 	if (index && status == ISC_R_SUCCESS)
86 		*index = new;
87 	return status;
88 }
89 
90 /* Set a value in the specified array, extending it if necessary. */
91 
omapi_array_set(omapi_array_t * array,void * ptr,int index,const char * file,int line)92 isc_result_t omapi_array_set (omapi_array_t *array, void *ptr, int index,
93 			      const char *file, int line)
94 {
95 	char **newbuf;
96 	int delta;
97 	isc_result_t status;
98 
99 	if (!array)
100 		return DHCP_R_INVALIDARG;
101 	if (!ptr)
102 		return DHCP_R_INVALIDARG;
103 	if (index < 0)
104 		return DHCP_R_INVALIDARG;
105 
106 	/* If the proposed index is larger than the current available
107 	   space in the array, make more space in the array. */
108 	if (array -> max <= index) {
109 		delta = index - array -> max + 10;
110 		newbuf = dmalloc ((array -> max + delta) * sizeof (char *),
111 				  file, line);
112 		if (!newbuf)
113 			return ISC_R_NOMEMORY;
114 		/* Zero the new elements. */
115 		memset (&newbuf [array -> max], 0, (sizeof (char *)) * delta);
116 		array -> max += delta;
117 		/* Copy the old array data into the new buffer. */
118 		if (array -> data) {
119 		    memcpy (newbuf,
120 			    array -> data, array -> count * sizeof (char *));
121 		    dfree (array -> data, file, line);
122 		}
123 		array -> data = newbuf;
124 	} else {
125 		/* If there's already data there, and this is an array
126 		   of references, dereference what's there. */
127 		if (array -> data [index]) {
128 			status = ((*array -> deref) (&array -> data [index],
129 						     file, line));
130 
131 			if (status != ISC_R_SUCCESS)
132 				return status;
133 		}
134 	}
135 
136 	/* Store the pointer using the referencer function.  We have
137 	   either just memset this to zero or dereferenced what was
138 	   there previously, so there is no need to do anything if the
139 	   pointer we have been asked to store is null. */
140 	if (ptr) {
141 		status = (*array -> ref) (&array -> data [index], ptr,
142 					  file, line);
143 		if (status != ISC_R_SUCCESS)
144 			return status;
145 	}
146 	if (index >= array -> count)
147 		array -> count = index + 1;
148 	return ISC_R_SUCCESS;
149 }
150 
omapi_array_lookup(char ** ptr,omapi_array_t * array,int index,const char * file,int line)151 isc_result_t omapi_array_lookup (char **ptr, omapi_array_t *array, int index,
152 				 const char *file, int line)
153 {
154 	if (!array || !ptr || *ptr || index < 0 || index >= array -> count)
155 		return DHCP_R_INVALIDARG;
156 	if (array -> data [index])
157 		return (*array -> ref) (ptr,
158 					array -> data [index], file, line);
159 	return ISC_R_NOTFOUND;
160 }
161