Initial import from FreeBSD RELENG_4:
[dragonfly.git] / contrib / isc-dhcp / omapip / array.c
1 /* listener.c
2
3    Subroutines that support the omapi extensible array type. */
4
5 /*
6  * Copyright (c) 2001 Internet Software Consortium.
7  * All rights reserved.
8  *
9  * Redistribution and use in source and binary forms, with or without
10  * modification, are permitted provided that the following conditions
11  * are met:
12  *
13  * 1. Redistributions of source code must retain the above copyright
14  *    notice, this list of conditions and the following disclaimer.
15  * 2. Redistributions in binary form must reproduce the above copyright
16  *    notice, this list of conditions and the following disclaimer in the
17  *    documentation and/or other materials provided with the distribution.
18  * 3. Neither the name of The Internet Software Consortium nor the names
19  *    of its contributors may be used to endorse or promote products derived
20  *    from this software without specific prior written permission.
21  *
22  * THIS SOFTWARE IS PROVIDED BY THE INTERNET SOFTWARE CONSORTIUM AND
23  * CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
24  * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
25  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
26  * DISCLAIMED.  IN NO EVENT SHALL THE INTERNET SOFTWARE CONSORTIUM OR
27  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
28  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
29  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
30  * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
32  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
33  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34  * SUCH DAMAGE.
35  *
36  * This software has been written for the Internet Software Consortium
37  * by Ted Lemon in cooperation with Vixie Enterprises and Nominum, Inc.
38  * To learn more about the Internet Software Consortium, see
39  * ``http://www.isc.org/''.  To learn more about Vixie Enterprises,
40  * see ``http://www.vix.com''.   To learn more about Nominum, Inc., see
41  * ``http://www.nominum.com''.
42  */
43
44 #include <omapip/omapip_p.h>
45
46 /* Allocate a new extensible array. */
47
48 isc_result_t omapi_array_allocate (omapi_array_t **array,
49                                    omapi_array_ref_t ref,
50                                    omapi_array_deref_t deref,
51                                    const char *file, int line)
52 {
53         isc_result_t status;
54         omapi_array_t *aptr;
55
56         if (!array || *array)
57                 return ISC_R_INVALIDARG;
58         aptr = dmalloc (sizeof (omapi_array_t),file, line);
59         if (!aptr)
60                 return ISC_R_NOMEMORY;
61         *array = aptr;
62         aptr -> ref = ref;
63         aptr -> deref = deref;
64         return ISC_R_SUCCESS;
65 }
66
67 isc_result_t omapi_array_free (omapi_array_t **array,
68                                const char *file, int line)
69 {
70         isc_result_t status;
71         omapi_array_t *aptr;
72         int i;
73
74         if (!array || !*array)
75                 return ISC_R_INVALIDARG;
76         aptr = *array;
77         for (i = 0; i < aptr -> count; i++)
78                 if (aptr -> data [i] && aptr -> deref)
79                         (*aptr -> deref) (&aptr -> data [i], file, line);
80         dfree (aptr -> data, MDL);
81         dfree (aptr, MDL);
82         *array = (omapi_array_t *)0;
83         return ISC_R_SUCCESS;
84 }
85
86 /* Extend the size of the array by one entry (we may allocate more than that)
87    and store the specified value in the new array element. */
88
89 isc_result_t omapi_array_extend (omapi_array_t *array, char *ptr,
90                                  int *index, const char *file, int line)
91 {
92         isc_result_t status;
93         int new = array -> count;
94         status = omapi_array_set (array, ptr, new, file, line);
95         if (index && status == ISC_R_SUCCESS)
96                 *index = new;
97         return status;
98 }
99
100 /* Set a value in the specified array, extending it if necessary. */
101
102 isc_result_t omapi_array_set (omapi_array_t *array, void *ptr, int index,
103                               const char *file, int line)
104 {
105         char **newbuf;
106         int delta;
107         isc_result_t status;
108
109         if (!array)
110                 return ISC_R_INVALIDARG;
111         if (!ptr)
112                 return ISC_R_INVALIDARG;
113         if (index < 0)
114                 return ISC_R_INVALIDARG;
115
116         /* If the proposed index is larger than the current available
117            space in the array, make more space in the array. */
118         if (array -> max <= index) {
119                 delta = index - array -> max + 10;
120                 newbuf = dmalloc ((array -> max + delta) * sizeof (char *),
121                                   file, line);
122                 if (!newbuf)
123                         return ISC_R_NOMEMORY;
124                 /* Zero the new elements. */
125                 memset (&newbuf [array -> max], 0, (sizeof (char *)) * delta);
126                 array -> max += delta;
127                 /* Copy the old array data into the new buffer. */
128                 if (array -> data) {
129                     memcpy (newbuf,
130                             array -> data, array -> count * sizeof (char *));
131                     dfree (array -> data, file, line);
132                 }
133                 array -> data = newbuf;
134         } else {
135                 /* If there's already data there, and this is an array
136                    of references, dereference what's there. */
137                 if (array -> data [index]) {
138                         status = ((*array -> deref) (&array -> data [index],
139                                                      file, line));
140                 
141                         if (status != ISC_R_SUCCESS)
142                                 return status;
143                 }
144         }
145
146         /* Store the pointer using the referencer function.  We have
147            either just memset this to zero or dereferenced what was
148            there previously, so there is no need to do anything if the
149            pointer we have been asked to store is null. */
150         if (ptr) {
151                 status = (*array -> ref) (&array -> data [index], ptr,
152                                           file, line);
153                 if (status != ISC_R_SUCCESS)
154                         return status;
155         }
156         if (index >= array -> count)
157                 array -> count = index + 1;
158         return ISC_R_SUCCESS;
159 }
160
161 isc_result_t omapi_array_lookup (char **ptr, omapi_array_t *array, int index,
162                                  const char *file, int line)
163 {
164         if (!array || !ptr || *ptr || index < 0 || index >= array -> count)
165                 return ISC_R_INVALIDARG;
166         if (array -> data [index])
167                 return (*array -> ref) (ptr,
168                                         array -> data [index], file, line);
169         return ISC_R_NOTFOUND;
170 }
171
172 OMAPI_ARRAY_TYPE_DECL(omapi_object, omapi_object_t);