xref: /freebsd/contrib/ofed/opensm/complib/cl_vector.c (revision 87181516ef48be852d5e5fee53c6e0dbfc62f21e)
1*d6b92ffaSHans Petter Selasky /*
2*d6b92ffaSHans Petter Selasky  * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved.
3*d6b92ffaSHans Petter Selasky  * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
4*d6b92ffaSHans Petter Selasky  * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
5*d6b92ffaSHans Petter Selasky  *
6*d6b92ffaSHans Petter Selasky  * This software is available to you under a choice of one of two
7*d6b92ffaSHans Petter Selasky  * licenses.  You may choose to be licensed under the terms of the GNU
8*d6b92ffaSHans Petter Selasky  * General Public License (GPL) Version 2, available from the file
9*d6b92ffaSHans Petter Selasky  * COPYING in the main directory of this source tree, or the
10*d6b92ffaSHans Petter Selasky  * OpenIB.org BSD license below:
11*d6b92ffaSHans Petter Selasky  *
12*d6b92ffaSHans Petter Selasky  *     Redistribution and use in source and binary forms, with or
13*d6b92ffaSHans Petter Selasky  *     without modification, are permitted provided that the following
14*d6b92ffaSHans Petter Selasky  *     conditions are met:
15*d6b92ffaSHans Petter Selasky  *
16*d6b92ffaSHans Petter Selasky  *      - Redistributions of source code must retain the above
17*d6b92ffaSHans Petter Selasky  *        copyright notice, this list of conditions and the following
18*d6b92ffaSHans Petter Selasky  *        disclaimer.
19*d6b92ffaSHans Petter Selasky  *
20*d6b92ffaSHans Petter Selasky  *      - Redistributions in binary form must reproduce the above
21*d6b92ffaSHans Petter Selasky  *        copyright notice, this list of conditions and the following
22*d6b92ffaSHans Petter Selasky  *        disclaimer in the documentation and/or other materials
23*d6b92ffaSHans Petter Selasky  *        provided with the distribution.
24*d6b92ffaSHans Petter Selasky  *
25*d6b92ffaSHans Petter Selasky  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
26*d6b92ffaSHans Petter Selasky  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
27*d6b92ffaSHans Petter Selasky  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
28*d6b92ffaSHans Petter Selasky  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
29*d6b92ffaSHans Petter Selasky  * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
30*d6b92ffaSHans Petter Selasky  * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
31*d6b92ffaSHans Petter Selasky  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
32*d6b92ffaSHans Petter Selasky  * SOFTWARE.
33*d6b92ffaSHans Petter Selasky  *
34*d6b92ffaSHans Petter Selasky  */
35*d6b92ffaSHans Petter Selasky 
36*d6b92ffaSHans Petter Selasky /*
37*d6b92ffaSHans Petter Selasky  * Abstract:
38*d6b92ffaSHans Petter Selasky  *	This file contains ivector and isvector implementations.
39*d6b92ffaSHans Petter Selasky  *
40*d6b92ffaSHans Petter Selasky  */
41*d6b92ffaSHans Petter Selasky 
42*d6b92ffaSHans Petter Selasky #if HAVE_CONFIG_H
43*d6b92ffaSHans Petter Selasky #  include <config.h>
44*d6b92ffaSHans Petter Selasky #endif				/* HAVE_CONFIG_H */
45*d6b92ffaSHans Petter Selasky 
46*d6b92ffaSHans Petter Selasky #include <stdlib.h>
47*d6b92ffaSHans Petter Selasky #include <string.h>
48*d6b92ffaSHans Petter Selasky #include <complib/cl_vector.h>
49*d6b92ffaSHans Petter Selasky 
50*d6b92ffaSHans Petter Selasky /*
51*d6b92ffaSHans Petter Selasky  * Define the maximum size for array pages in an cl_vector_t.
52*d6b92ffaSHans Petter Selasky  * This size is in objects, not bytes.
53*d6b92ffaSHans Petter Selasky  */
54*d6b92ffaSHans Petter Selasky #define SVEC_MAX_PAGE_SIZE 0x1000
55*d6b92ffaSHans Petter Selasky 
56*d6b92ffaSHans Petter Selasky /*
57*d6b92ffaSHans Petter Selasky  * cl_vector_copy_general
58*d6b92ffaSHans Petter Selasky  *
59*d6b92ffaSHans Petter Selasky  * Description:
60*d6b92ffaSHans Petter Selasky  *	copy operator used when size of the user object doesn't fit one of the
61*d6b92ffaSHans Petter Selasky  *	other optimized copy functions.
62*d6b92ffaSHans Petter Selasky  *
63*d6b92ffaSHans Petter Selasky  * Inputs:
64*d6b92ffaSHans Petter Selasky  *	p_src - source for copy
65*d6b92ffaSHans Petter Selasky  *
66*d6b92ffaSHans Petter Selasky  * Outputs:
67*d6b92ffaSHans Petter Selasky  *	p_dest - destination for copy
68*d6b92ffaSHans Petter Selasky  *
69*d6b92ffaSHans Petter Selasky  * Returns:
70*d6b92ffaSHans Petter Selasky  *	None
71*d6b92ffaSHans Petter Selasky  *
72*d6b92ffaSHans Petter Selasky  */
cl_vector_copy_general(OUT void * const p_dest,IN const void * const p_src,IN const size_t size)73*d6b92ffaSHans Petter Selasky static void cl_vector_copy_general(OUT void *const p_dest,
74*d6b92ffaSHans Petter Selasky 				   IN const void *const p_src,
75*d6b92ffaSHans Petter Selasky 				   IN const size_t size)
76*d6b92ffaSHans Petter Selasky {
77*d6b92ffaSHans Petter Selasky 	memcpy(p_dest, p_src, size);
78*d6b92ffaSHans Petter Selasky }
79*d6b92ffaSHans Petter Selasky 
80*d6b92ffaSHans Petter Selasky /*
81*d6b92ffaSHans Petter Selasky  * cl_vector_copy8
82*d6b92ffaSHans Petter Selasky  *
83*d6b92ffaSHans Petter Selasky  * Description:
84*d6b92ffaSHans Petter Selasky  *	copy operator used when the user structure is only 8 bits long.
85*d6b92ffaSHans Petter Selasky  *
86*d6b92ffaSHans Petter Selasky  * Inputs:
87*d6b92ffaSHans Petter Selasky  *	p_src - source for copy
88*d6b92ffaSHans Petter Selasky  *
89*d6b92ffaSHans Petter Selasky  * Outputs:
90*d6b92ffaSHans Petter Selasky  *	p_dest - destination for copy
91*d6b92ffaSHans Petter Selasky  *
92*d6b92ffaSHans Petter Selasky  * Returns:
93*d6b92ffaSHans Petter Selasky  *	None
94*d6b92ffaSHans Petter Selasky  *
95*d6b92ffaSHans Petter Selasky  */
cl_vector_copy8(OUT void * const p_dest,IN const void * const p_src,IN const size_t size)96*d6b92ffaSHans Petter Selasky static void cl_vector_copy8(OUT void *const p_dest,
97*d6b92ffaSHans Petter Selasky 			    IN const void *const p_src, IN const size_t size)
98*d6b92ffaSHans Petter Selasky {
99*d6b92ffaSHans Petter Selasky 	CL_ASSERT(size == sizeof(uint8_t));
100*d6b92ffaSHans Petter Selasky 	UNUSED_PARAM(size);
101*d6b92ffaSHans Petter Selasky 
102*d6b92ffaSHans Petter Selasky 	*(uint8_t *) p_dest = *(uint8_t *) p_src;
103*d6b92ffaSHans Petter Selasky }
104*d6b92ffaSHans Petter Selasky 
105*d6b92ffaSHans Petter Selasky /*
106*d6b92ffaSHans Petter Selasky  * cl_vector_copy16
107*d6b92ffaSHans Petter Selasky  *
108*d6b92ffaSHans Petter Selasky  * Description:
109*d6b92ffaSHans Petter Selasky  *	copy operator used when the user structure is only 16 bits long.
110*d6b92ffaSHans Petter Selasky  *
111*d6b92ffaSHans Petter Selasky  * Inputs:
112*d6b92ffaSHans Petter Selasky  *	p_src - source for copy
113*d6b92ffaSHans Petter Selasky  *
114*d6b92ffaSHans Petter Selasky  * Outputs:
115*d6b92ffaSHans Petter Selasky  *	p_dest - destination for copy
116*d6b92ffaSHans Petter Selasky  *
117*d6b92ffaSHans Petter Selasky  * Returns:
118*d6b92ffaSHans Petter Selasky  *	None
119*d6b92ffaSHans Petter Selasky  *
120*d6b92ffaSHans Petter Selasky  */
cl_vector_copy16(OUT void * const p_dest,IN const void * const p_src,IN const size_t size)121*d6b92ffaSHans Petter Selasky void cl_vector_copy16(OUT void *const p_dest,
122*d6b92ffaSHans Petter Selasky 		      IN const void *const p_src, IN const size_t size)
123*d6b92ffaSHans Petter Selasky {
124*d6b92ffaSHans Petter Selasky 	CL_ASSERT(size == sizeof(uint16_t));
125*d6b92ffaSHans Petter Selasky 	UNUSED_PARAM(size);
126*d6b92ffaSHans Petter Selasky 
127*d6b92ffaSHans Petter Selasky 	*(uint16_t *) p_dest = *(uint16_t *) p_src;
128*d6b92ffaSHans Petter Selasky }
129*d6b92ffaSHans Petter Selasky 
130*d6b92ffaSHans Petter Selasky /*
131*d6b92ffaSHans Petter Selasky  * cl_vector_copy32
132*d6b92ffaSHans Petter Selasky  *
133*d6b92ffaSHans Petter Selasky  * Description:
134*d6b92ffaSHans Petter Selasky  *	copy operator used when the user structure is only 32 bits long.
135*d6b92ffaSHans Petter Selasky  *
136*d6b92ffaSHans Petter Selasky  * Inputs:
137*d6b92ffaSHans Petter Selasky  *	p_src - source for copy
138*d6b92ffaSHans Petter Selasky  *
139*d6b92ffaSHans Petter Selasky  * Outputs:
140*d6b92ffaSHans Petter Selasky  *	p_dest - destination for copy
141*d6b92ffaSHans Petter Selasky  *
142*d6b92ffaSHans Petter Selasky  * Returns:
143*d6b92ffaSHans Petter Selasky  *	None
144*d6b92ffaSHans Petter Selasky  *
145*d6b92ffaSHans Petter Selasky  */
cl_vector_copy32(OUT void * const p_dest,IN const void * const p_src,IN const size_t size)146*d6b92ffaSHans Petter Selasky void cl_vector_copy32(OUT void *const p_dest,
147*d6b92ffaSHans Petter Selasky 		      IN const void *const p_src, IN const size_t size)
148*d6b92ffaSHans Petter Selasky {
149*d6b92ffaSHans Petter Selasky 	CL_ASSERT(size == sizeof(uint32_t));
150*d6b92ffaSHans Petter Selasky 	UNUSED_PARAM(size);
151*d6b92ffaSHans Petter Selasky 
152*d6b92ffaSHans Petter Selasky 	*(uint32_t *) p_dest = *(uint32_t *) p_src;
153*d6b92ffaSHans Petter Selasky }
154*d6b92ffaSHans Petter Selasky 
155*d6b92ffaSHans Petter Selasky /*
156*d6b92ffaSHans Petter Selasky  * cl_vector_copy64
157*d6b92ffaSHans Petter Selasky  *
158*d6b92ffaSHans Petter Selasky  * Description:
159*d6b92ffaSHans Petter Selasky  *	copy operator used when the user structure is only 64 bits long.
160*d6b92ffaSHans Petter Selasky  *
161*d6b92ffaSHans Petter Selasky  * Inputs:
162*d6b92ffaSHans Petter Selasky  *	p_src - source for copy
163*d6b92ffaSHans Petter Selasky  *
164*d6b92ffaSHans Petter Selasky  * Outputs:
165*d6b92ffaSHans Petter Selasky  *	p_dest - destination for copy
166*d6b92ffaSHans Petter Selasky  *
167*d6b92ffaSHans Petter Selasky  * Returns:
168*d6b92ffaSHans Petter Selasky  *	None
169*d6b92ffaSHans Petter Selasky  *
170*d6b92ffaSHans Petter Selasky  */
cl_vector_copy64(OUT void * const p_dest,IN const void * const p_src,IN const size_t size)171*d6b92ffaSHans Petter Selasky void cl_vector_copy64(OUT void *const p_dest,
172*d6b92ffaSHans Petter Selasky 		      IN const void *const p_src, IN const size_t size)
173*d6b92ffaSHans Petter Selasky {
174*d6b92ffaSHans Petter Selasky 	CL_ASSERT(size == sizeof(uint64_t));
175*d6b92ffaSHans Petter Selasky 	UNUSED_PARAM(size);
176*d6b92ffaSHans Petter Selasky 
177*d6b92ffaSHans Petter Selasky 	*(uint64_t *) p_dest = *(uint64_t *) p_src;
178*d6b92ffaSHans Petter Selasky }
179*d6b92ffaSHans Petter Selasky 
cl_vector_construct(IN cl_vector_t * const p_vector)180*d6b92ffaSHans Petter Selasky void cl_vector_construct(IN cl_vector_t * const p_vector)
181*d6b92ffaSHans Petter Selasky {
182*d6b92ffaSHans Petter Selasky 	CL_ASSERT(p_vector);
183*d6b92ffaSHans Petter Selasky 
184*d6b92ffaSHans Petter Selasky 	memset(p_vector, 0, sizeof(cl_vector_t));
185*d6b92ffaSHans Petter Selasky 
186*d6b92ffaSHans Petter Selasky 	p_vector->state = CL_UNINITIALIZED;
187*d6b92ffaSHans Petter Selasky }
188*d6b92ffaSHans Petter Selasky 
cl_vector_init(IN cl_vector_t * const p_vector,IN const size_t min_size,IN const size_t grow_size,IN const size_t element_size,IN cl_pfn_vec_init_t pfn_init OPTIONAL,IN cl_pfn_vec_dtor_t pfn_dtor OPTIONAL,IN const void * const context)189*d6b92ffaSHans Petter Selasky cl_status_t cl_vector_init(IN cl_vector_t * const p_vector,
190*d6b92ffaSHans Petter Selasky 			   IN const size_t min_size, IN const size_t grow_size,
191*d6b92ffaSHans Petter Selasky 			   IN const size_t element_size,
192*d6b92ffaSHans Petter Selasky 			   IN cl_pfn_vec_init_t pfn_init OPTIONAL,
193*d6b92ffaSHans Petter Selasky 			   IN cl_pfn_vec_dtor_t pfn_dtor OPTIONAL,
194*d6b92ffaSHans Petter Selasky 			   IN const void *const context)
195*d6b92ffaSHans Petter Selasky {
196*d6b92ffaSHans Petter Selasky 	cl_status_t status = CL_SUCCESS;
197*d6b92ffaSHans Petter Selasky 
198*d6b92ffaSHans Petter Selasky 	CL_ASSERT(p_vector);
199*d6b92ffaSHans Petter Selasky 	CL_ASSERT(element_size);
200*d6b92ffaSHans Petter Selasky 
201*d6b92ffaSHans Petter Selasky 	cl_vector_construct(p_vector);
202*d6b92ffaSHans Petter Selasky 
203*d6b92ffaSHans Petter Selasky 	p_vector->grow_size = grow_size;
204*d6b92ffaSHans Petter Selasky 	p_vector->element_size = element_size;
205*d6b92ffaSHans Petter Selasky 	p_vector->pfn_init = pfn_init;
206*d6b92ffaSHans Petter Selasky 	p_vector->pfn_dtor = pfn_dtor;
207*d6b92ffaSHans Petter Selasky 	p_vector->context = context;
208*d6b92ffaSHans Petter Selasky 
209*d6b92ffaSHans Petter Selasky 	/*
210*d6b92ffaSHans Petter Selasky 	 * Try to choose a smart copy operator
211*d6b92ffaSHans Petter Selasky 	 * someday, we could simply let the users pass one in
212*d6b92ffaSHans Petter Selasky 	 */
213*d6b92ffaSHans Petter Selasky 	switch (element_size) {
214*d6b92ffaSHans Petter Selasky 	case sizeof(uint8_t):
215*d6b92ffaSHans Petter Selasky 		p_vector->pfn_copy = cl_vector_copy8;
216*d6b92ffaSHans Petter Selasky 		break;
217*d6b92ffaSHans Petter Selasky 
218*d6b92ffaSHans Petter Selasky 	case sizeof(uint16_t):
219*d6b92ffaSHans Petter Selasky 		p_vector->pfn_copy = cl_vector_copy16;
220*d6b92ffaSHans Petter Selasky 		break;
221*d6b92ffaSHans Petter Selasky 
222*d6b92ffaSHans Petter Selasky 	case sizeof(uint32_t):
223*d6b92ffaSHans Petter Selasky 		p_vector->pfn_copy = cl_vector_copy32;
224*d6b92ffaSHans Petter Selasky 		break;
225*d6b92ffaSHans Petter Selasky 
226*d6b92ffaSHans Petter Selasky 	case sizeof(uint64_t):
227*d6b92ffaSHans Petter Selasky 		p_vector->pfn_copy = cl_vector_copy64;
228*d6b92ffaSHans Petter Selasky 		break;
229*d6b92ffaSHans Petter Selasky 
230*d6b92ffaSHans Petter Selasky 	default:
231*d6b92ffaSHans Petter Selasky 		p_vector->pfn_copy = cl_vector_copy_general;
232*d6b92ffaSHans Petter Selasky 		break;
233*d6b92ffaSHans Petter Selasky 	}
234*d6b92ffaSHans Petter Selasky 
235*d6b92ffaSHans Petter Selasky 	/*
236*d6b92ffaSHans Petter Selasky 	 * Set the state to initialized so that the call to set_size
237*d6b92ffaSHans Petter Selasky 	 * doesn't assert.
238*d6b92ffaSHans Petter Selasky 	 */
239*d6b92ffaSHans Petter Selasky 	p_vector->state = CL_INITIALIZED;
240*d6b92ffaSHans Petter Selasky 
241*d6b92ffaSHans Petter Selasky 	/* Initialize the allocation list */
242*d6b92ffaSHans Petter Selasky 	cl_qlist_init(&p_vector->alloc_list);
243*d6b92ffaSHans Petter Selasky 
244*d6b92ffaSHans Petter Selasky 	/* get the storage needed by the user */
245*d6b92ffaSHans Petter Selasky 	if (min_size) {
246*d6b92ffaSHans Petter Selasky 		status = cl_vector_set_size(p_vector, min_size);
247*d6b92ffaSHans Petter Selasky 		if (status != CL_SUCCESS)
248*d6b92ffaSHans Petter Selasky 			cl_vector_destroy(p_vector);
249*d6b92ffaSHans Petter Selasky 	}
250*d6b92ffaSHans Petter Selasky 
251*d6b92ffaSHans Petter Selasky 	return (status);
252*d6b92ffaSHans Petter Selasky }
253*d6b92ffaSHans Petter Selasky 
cl_vector_destroy(IN cl_vector_t * const p_vector)254*d6b92ffaSHans Petter Selasky void cl_vector_destroy(IN cl_vector_t * const p_vector)
255*d6b92ffaSHans Petter Selasky {
256*d6b92ffaSHans Petter Selasky 	size_t i;
257*d6b92ffaSHans Petter Selasky 	void *p_element;
258*d6b92ffaSHans Petter Selasky 
259*d6b92ffaSHans Petter Selasky 	CL_ASSERT(p_vector);
260*d6b92ffaSHans Petter Selasky 	CL_ASSERT(cl_is_state_valid(p_vector->state));
261*d6b92ffaSHans Petter Selasky 
262*d6b92ffaSHans Petter Selasky 	/* Call the user's destructor for each element in the array. */
263*d6b92ffaSHans Petter Selasky 	if (p_vector->state == CL_INITIALIZED) {
264*d6b92ffaSHans Petter Selasky 		if (p_vector->pfn_dtor) {
265*d6b92ffaSHans Petter Selasky 			for (i = 0; i < p_vector->size; i++) {
266*d6b92ffaSHans Petter Selasky 				p_element = p_vector->p_ptr_array[i];
267*d6b92ffaSHans Petter Selasky 				/* Sanity check! */
268*d6b92ffaSHans Petter Selasky 				CL_ASSERT(p_element);
269*d6b92ffaSHans Petter Selasky 				p_vector->pfn_dtor(p_element,
270*d6b92ffaSHans Petter Selasky 						   (void *)p_vector->context);
271*d6b92ffaSHans Petter Selasky 			}
272*d6b92ffaSHans Petter Selasky 		}
273*d6b92ffaSHans Petter Selasky 
274*d6b92ffaSHans Petter Selasky 		/* Deallocate the pages */
275*d6b92ffaSHans Petter Selasky 		while (!cl_is_qlist_empty(&p_vector->alloc_list))
276*d6b92ffaSHans Petter Selasky 			free(cl_qlist_remove_head(&p_vector->alloc_list));
277*d6b92ffaSHans Petter Selasky 
278*d6b92ffaSHans Petter Selasky 		/* Destroy the page vector. */
279*d6b92ffaSHans Petter Selasky 		if (p_vector->p_ptr_array) {
280*d6b92ffaSHans Petter Selasky 			free(p_vector->p_ptr_array);
281*d6b92ffaSHans Petter Selasky 			p_vector->p_ptr_array = NULL;
282*d6b92ffaSHans Petter Selasky 		}
283*d6b92ffaSHans Petter Selasky 	}
284*d6b92ffaSHans Petter Selasky 
285*d6b92ffaSHans Petter Selasky 	p_vector->state = CL_UNINITIALIZED;
286*d6b92ffaSHans Petter Selasky }
287*d6b92ffaSHans Petter Selasky 
cl_vector_at(IN const cl_vector_t * const p_vector,IN const size_t index,OUT void * const p_element)288*d6b92ffaSHans Petter Selasky cl_status_t cl_vector_at(IN const cl_vector_t * const p_vector,
289*d6b92ffaSHans Petter Selasky 			 IN const size_t index, OUT void *const p_element)
290*d6b92ffaSHans Petter Selasky {
291*d6b92ffaSHans Petter Selasky 	CL_ASSERT(p_vector);
292*d6b92ffaSHans Petter Selasky 	CL_ASSERT(p_vector->state == CL_INITIALIZED);
293*d6b92ffaSHans Petter Selasky 
294*d6b92ffaSHans Petter Selasky 	/* Range check */
295*d6b92ffaSHans Petter Selasky 	if (index >= p_vector->size)
296*d6b92ffaSHans Petter Selasky 		return (CL_INVALID_PARAMETER);
297*d6b92ffaSHans Petter Selasky 
298*d6b92ffaSHans Petter Selasky 	cl_vector_get(p_vector, index, p_element);
299*d6b92ffaSHans Petter Selasky 	return (CL_SUCCESS);
300*d6b92ffaSHans Petter Selasky }
301*d6b92ffaSHans Petter Selasky 
cl_vector_set(IN cl_vector_t * const p_vector,IN const size_t index,IN void * const p_element)302*d6b92ffaSHans Petter Selasky cl_status_t cl_vector_set(IN cl_vector_t * const p_vector,
303*d6b92ffaSHans Petter Selasky 			  IN const size_t index, IN void *const p_element)
304*d6b92ffaSHans Petter Selasky {
305*d6b92ffaSHans Petter Selasky 	cl_status_t status;
306*d6b92ffaSHans Petter Selasky 	void *p_dest;
307*d6b92ffaSHans Petter Selasky 
308*d6b92ffaSHans Petter Selasky 	CL_ASSERT(p_vector);
309*d6b92ffaSHans Petter Selasky 	CL_ASSERT(p_vector->state == CL_INITIALIZED);
310*d6b92ffaSHans Petter Selasky 	CL_ASSERT(p_element);
311*d6b92ffaSHans Petter Selasky 
312*d6b92ffaSHans Petter Selasky 	/* Determine if the vector has room for this element. */
313*d6b92ffaSHans Petter Selasky 	if (index >= p_vector->size) {
314*d6b92ffaSHans Petter Selasky 		/* Resize to accomodate the given index. */
315*d6b92ffaSHans Petter Selasky 		status = cl_vector_set_size(p_vector, index + 1);
316*d6b92ffaSHans Petter Selasky 
317*d6b92ffaSHans Petter Selasky 		/* Check for failure on or before the given index. */
318*d6b92ffaSHans Petter Selasky 		if ((status != CL_SUCCESS) && (p_vector->size < index))
319*d6b92ffaSHans Petter Selasky 			return (status);
320*d6b92ffaSHans Petter Selasky 	}
321*d6b92ffaSHans Petter Selasky 
322*d6b92ffaSHans Petter Selasky 	/* At this point, the array is guaranteed to be big enough */
323*d6b92ffaSHans Petter Selasky 	p_dest = cl_vector_get_ptr(p_vector, index);
324*d6b92ffaSHans Petter Selasky 	/* Sanity check! */
325*d6b92ffaSHans Petter Selasky 	CL_ASSERT(p_dest);
326*d6b92ffaSHans Petter Selasky 
327*d6b92ffaSHans Petter Selasky 	/* Copy the data into the array */
328*d6b92ffaSHans Petter Selasky 	p_vector->pfn_copy(p_dest, p_element, p_vector->element_size);
329*d6b92ffaSHans Petter Selasky 
330*d6b92ffaSHans Petter Selasky 	return (CL_SUCCESS);
331*d6b92ffaSHans Petter Selasky }
332*d6b92ffaSHans Petter Selasky 
cl_vector_set_capacity(IN cl_vector_t * const p_vector,IN const size_t new_capacity)333*d6b92ffaSHans Petter Selasky cl_status_t cl_vector_set_capacity(IN cl_vector_t * const p_vector,
334*d6b92ffaSHans Petter Selasky 				   IN const size_t new_capacity)
335*d6b92ffaSHans Petter Selasky {
336*d6b92ffaSHans Petter Selasky 	size_t new_elements;
337*d6b92ffaSHans Petter Selasky 	size_t alloc_size;
338*d6b92ffaSHans Petter Selasky 	size_t i;
339*d6b92ffaSHans Petter Selasky 	cl_list_item_t *p_buf;
340*d6b92ffaSHans Petter Selasky 	void *p_new_ptr_array;
341*d6b92ffaSHans Petter Selasky 
342*d6b92ffaSHans Petter Selasky 	CL_ASSERT(p_vector);
343*d6b92ffaSHans Petter Selasky 	CL_ASSERT(p_vector->state == CL_INITIALIZED);
344*d6b92ffaSHans Petter Selasky 
345*d6b92ffaSHans Petter Selasky 	/* Do we have to do anything here? */
346*d6b92ffaSHans Petter Selasky 	if (new_capacity <= p_vector->capacity) {
347*d6b92ffaSHans Petter Selasky 		/* Nope */
348*d6b92ffaSHans Petter Selasky 		return (CL_SUCCESS);
349*d6b92ffaSHans Petter Selasky 	}
350*d6b92ffaSHans Petter Selasky 
351*d6b92ffaSHans Petter Selasky 	/* Allocate our pointer array. */
352*d6b92ffaSHans Petter Selasky 	p_new_ptr_array = malloc(new_capacity * sizeof(void *));
353*d6b92ffaSHans Petter Selasky 	if (!p_new_ptr_array)
354*d6b92ffaSHans Petter Selasky 		return (CL_INSUFFICIENT_MEMORY);
355*d6b92ffaSHans Petter Selasky 	else
356*d6b92ffaSHans Petter Selasky 		memset(p_new_ptr_array, 0, new_capacity * sizeof(void *));
357*d6b92ffaSHans Petter Selasky 
358*d6b92ffaSHans Petter Selasky 	if (p_vector->p_ptr_array) {
359*d6b92ffaSHans Petter Selasky 		/* Copy the old pointer array into the new. */
360*d6b92ffaSHans Petter Selasky 		memcpy(p_new_ptr_array, p_vector->p_ptr_array,
361*d6b92ffaSHans Petter Selasky 		       p_vector->capacity * sizeof(void *));
362*d6b92ffaSHans Petter Selasky 
363*d6b92ffaSHans Petter Selasky 		/* Free the old pointer array. */
364*d6b92ffaSHans Petter Selasky 		free(p_vector->p_ptr_array);
365*d6b92ffaSHans Petter Selasky 	}
366*d6b92ffaSHans Petter Selasky 
367*d6b92ffaSHans Petter Selasky 	/* Set the new array. */
368*d6b92ffaSHans Petter Selasky 	p_vector->p_ptr_array = p_new_ptr_array;
369*d6b92ffaSHans Petter Selasky 
370*d6b92ffaSHans Petter Selasky 	/*
371*d6b92ffaSHans Petter Selasky 	 * We have to add capacity to the array.  Determine how many
372*d6b92ffaSHans Petter Selasky 	 * elements to add.
373*d6b92ffaSHans Petter Selasky 	 */
374*d6b92ffaSHans Petter Selasky 	new_elements = new_capacity - p_vector->capacity;
375*d6b92ffaSHans Petter Selasky 	/* Determine the allocation size for the new array elements. */
376*d6b92ffaSHans Petter Selasky 	alloc_size = new_elements * p_vector->element_size;
377*d6b92ffaSHans Petter Selasky 
378*d6b92ffaSHans Petter Selasky 	p_buf = (cl_list_item_t *) malloc(alloc_size + sizeof(cl_list_item_t));
379*d6b92ffaSHans Petter Selasky 	if (!p_buf)
380*d6b92ffaSHans Petter Selasky 		return (CL_INSUFFICIENT_MEMORY);
381*d6b92ffaSHans Petter Selasky 	else
382*d6b92ffaSHans Petter Selasky 		memset(p_buf, 0, alloc_size + sizeof(cl_list_item_t));
383*d6b92ffaSHans Petter Selasky 
384*d6b92ffaSHans Petter Selasky 	cl_qlist_insert_tail(&p_vector->alloc_list, p_buf);
385*d6b92ffaSHans Petter Selasky 	/* Advance the buffer pointer past the list item. */
386*d6b92ffaSHans Petter Selasky 	p_buf++;
387*d6b92ffaSHans Petter Selasky 
388*d6b92ffaSHans Petter Selasky 	for (i = p_vector->capacity; i < new_capacity; i++) {
389*d6b92ffaSHans Petter Selasky 		p_vector->p_ptr_array[i] = p_buf;
390*d6b92ffaSHans Petter Selasky 		/* Move the buffer pointer to the next element. */
391*d6b92ffaSHans Petter Selasky 		p_buf = (void *)(((uint8_t *) p_buf) + p_vector->element_size);
392*d6b92ffaSHans Petter Selasky 	}
393*d6b92ffaSHans Petter Selasky 
394*d6b92ffaSHans Petter Selasky 	/* Update the vector with the new capactity. */
395*d6b92ffaSHans Petter Selasky 	p_vector->capacity = new_capacity;
396*d6b92ffaSHans Petter Selasky 
397*d6b92ffaSHans Petter Selasky 	return (CL_SUCCESS);
398*d6b92ffaSHans Petter Selasky }
399*d6b92ffaSHans Petter Selasky 
cl_vector_set_size(IN cl_vector_t * const p_vector,IN const size_t size)400*d6b92ffaSHans Petter Selasky cl_status_t cl_vector_set_size(IN cl_vector_t * const p_vector,
401*d6b92ffaSHans Petter Selasky 			       IN const size_t size)
402*d6b92ffaSHans Petter Selasky {
403*d6b92ffaSHans Petter Selasky 	cl_status_t status;
404*d6b92ffaSHans Petter Selasky 	size_t new_capacity;
405*d6b92ffaSHans Petter Selasky 	size_t index;
406*d6b92ffaSHans Petter Selasky 	void *p_element;
407*d6b92ffaSHans Petter Selasky 
408*d6b92ffaSHans Petter Selasky 	CL_ASSERT(p_vector);
409*d6b92ffaSHans Petter Selasky 	CL_ASSERT(p_vector->state == CL_INITIALIZED);
410*d6b92ffaSHans Petter Selasky 
411*d6b92ffaSHans Petter Selasky 	/* Check to see if the requested size is the same as the existing size. */
412*d6b92ffaSHans Petter Selasky 	if (size == p_vector->size)
413*d6b92ffaSHans Petter Selasky 		return (CL_SUCCESS);
414*d6b92ffaSHans Petter Selasky 
415*d6b92ffaSHans Petter Selasky 	/* Determine if the vector has room for this element. */
416*d6b92ffaSHans Petter Selasky 	if (size >= p_vector->capacity) {
417*d6b92ffaSHans Petter Selasky 		if (!p_vector->grow_size)
418*d6b92ffaSHans Petter Selasky 			return (CL_INSUFFICIENT_MEMORY);
419*d6b92ffaSHans Petter Selasky 
420*d6b92ffaSHans Petter Selasky 		/* Calculate the new capacity, taking into account the grow size. */
421*d6b92ffaSHans Petter Selasky 		new_capacity = size;
422*d6b92ffaSHans Petter Selasky 		if (size % p_vector->grow_size) {
423*d6b92ffaSHans Petter Selasky 			/* Round up to nearest grow_size boundary. */
424*d6b92ffaSHans Petter Selasky 			new_capacity += p_vector->grow_size -
425*d6b92ffaSHans Petter Selasky 			    (size % p_vector->grow_size);
426*d6b92ffaSHans Petter Selasky 		}
427*d6b92ffaSHans Petter Selasky 
428*d6b92ffaSHans Petter Selasky 		status = cl_vector_set_capacity(p_vector, new_capacity);
429*d6b92ffaSHans Petter Selasky 		if (status != CL_SUCCESS)
430*d6b92ffaSHans Petter Selasky 			return (status);
431*d6b92ffaSHans Petter Selasky 	}
432*d6b92ffaSHans Petter Selasky 
433*d6b92ffaSHans Petter Selasky 	/* Are we growing the array and need to invoke an initializer callback? */
434*d6b92ffaSHans Petter Selasky 	if (size > p_vector->size && p_vector->pfn_init) {
435*d6b92ffaSHans Petter Selasky 		for (index = p_vector->size; index < size; index++) {
436*d6b92ffaSHans Petter Selasky 			/* Get a pointer to this element */
437*d6b92ffaSHans Petter Selasky 			p_element = cl_vector_get_ptr(p_vector, index);
438*d6b92ffaSHans Petter Selasky 
439*d6b92ffaSHans Petter Selasky 			/* Call the user's initializer and trap failures. */
440*d6b92ffaSHans Petter Selasky 			status =
441*d6b92ffaSHans Petter Selasky 			    p_vector->pfn_init(p_element,
442*d6b92ffaSHans Petter Selasky 					       (void *)p_vector->context);
443*d6b92ffaSHans Petter Selasky 			if (status != CL_SUCCESS) {
444*d6b92ffaSHans Petter Selasky 				/* Call the destructor for this object */
445*d6b92ffaSHans Petter Selasky 				if (p_vector->pfn_dtor)
446*d6b92ffaSHans Petter Selasky 					p_vector->pfn_dtor(p_element,
447*d6b92ffaSHans Petter Selasky 							   (void *)p_vector->
448*d6b92ffaSHans Petter Selasky 							   context);
449*d6b92ffaSHans Petter Selasky 
450*d6b92ffaSHans Petter Selasky 				/* Return the failure status to the caller. */
451*d6b92ffaSHans Petter Selasky 				return (status);
452*d6b92ffaSHans Petter Selasky 			}
453*d6b92ffaSHans Petter Selasky 
454*d6b92ffaSHans Petter Selasky 			/* The array just grew by one element */
455*d6b92ffaSHans Petter Selasky 			p_vector->size++;
456*d6b92ffaSHans Petter Selasky 		}
457*d6b92ffaSHans Petter Selasky 	} else if (p_vector->pfn_dtor) {
458*d6b92ffaSHans Petter Selasky 		/* The array is shrinking and there is a destructor to invoke. */
459*d6b92ffaSHans Petter Selasky 		for (index = size; index < p_vector->size; index++) {
460*d6b92ffaSHans Petter Selasky 			/* compute the address of the new elements */
461*d6b92ffaSHans Petter Selasky 			p_element = cl_vector_get_ptr(p_vector, index);
462*d6b92ffaSHans Petter Selasky 			/* call the user's destructor */
463*d6b92ffaSHans Petter Selasky 			p_vector->pfn_dtor(p_element,
464*d6b92ffaSHans Petter Selasky 					   (void *)p_vector->context);
465*d6b92ffaSHans Petter Selasky 		}
466*d6b92ffaSHans Petter Selasky 	}
467*d6b92ffaSHans Petter Selasky 
468*d6b92ffaSHans Petter Selasky 	p_vector->size = size;
469*d6b92ffaSHans Petter Selasky 	return (CL_SUCCESS);
470*d6b92ffaSHans Petter Selasky }
471*d6b92ffaSHans Petter Selasky 
cl_vector_set_min_size(IN cl_vector_t * const p_vector,IN const size_t min_size)472*d6b92ffaSHans Petter Selasky cl_status_t cl_vector_set_min_size(IN cl_vector_t * const p_vector,
473*d6b92ffaSHans Petter Selasky 				   IN const size_t min_size)
474*d6b92ffaSHans Petter Selasky {
475*d6b92ffaSHans Petter Selasky 	CL_ASSERT(p_vector);
476*d6b92ffaSHans Petter Selasky 	CL_ASSERT(p_vector->state == CL_INITIALIZED);
477*d6b92ffaSHans Petter Selasky 
478*d6b92ffaSHans Petter Selasky 	if (min_size > p_vector->size) {
479*d6b92ffaSHans Petter Selasky 		/* We have to resize the array */
480*d6b92ffaSHans Petter Selasky 		return (cl_vector_set_size(p_vector, min_size));
481*d6b92ffaSHans Petter Selasky 	}
482*d6b92ffaSHans Petter Selasky 
483*d6b92ffaSHans Petter Selasky 	/* We didn't have to do anything */
484*d6b92ffaSHans Petter Selasky 	return (CL_SUCCESS);
485*d6b92ffaSHans Petter Selasky }
486*d6b92ffaSHans Petter Selasky 
cl_vector_apply_func(IN const cl_vector_t * const p_vector,IN cl_pfn_vec_apply_t pfn_callback,IN const void * const context)487*d6b92ffaSHans Petter Selasky void cl_vector_apply_func(IN const cl_vector_t * const p_vector,
488*d6b92ffaSHans Petter Selasky 			  IN cl_pfn_vec_apply_t pfn_callback,
489*d6b92ffaSHans Petter Selasky 			  IN const void *const context)
490*d6b92ffaSHans Petter Selasky {
491*d6b92ffaSHans Petter Selasky 	size_t i;
492*d6b92ffaSHans Petter Selasky 	void *p_element;
493*d6b92ffaSHans Petter Selasky 
494*d6b92ffaSHans Petter Selasky 	CL_ASSERT(p_vector);
495*d6b92ffaSHans Petter Selasky 	CL_ASSERT(p_vector->state == CL_INITIALIZED);
496*d6b92ffaSHans Petter Selasky 	CL_ASSERT(pfn_callback);
497*d6b92ffaSHans Petter Selasky 
498*d6b92ffaSHans Petter Selasky 	for (i = 0; i < p_vector->size; i++) {
499*d6b92ffaSHans Petter Selasky 		p_element = cl_vector_get_ptr(p_vector, i);
500*d6b92ffaSHans Petter Selasky 		pfn_callback(i, p_element, (void *)context);
501*d6b92ffaSHans Petter Selasky 	}
502*d6b92ffaSHans Petter Selasky }
503*d6b92ffaSHans Petter Selasky 
cl_vector_find_from_start(IN const cl_vector_t * const p_vector,IN cl_pfn_vec_find_t pfn_callback,IN const void * const context)504*d6b92ffaSHans Petter Selasky size_t cl_vector_find_from_start(IN const cl_vector_t * const p_vector,
505*d6b92ffaSHans Petter Selasky 				 IN cl_pfn_vec_find_t pfn_callback,
506*d6b92ffaSHans Petter Selasky 				 IN const void *const context)
507*d6b92ffaSHans Petter Selasky {
508*d6b92ffaSHans Petter Selasky 	size_t i;
509*d6b92ffaSHans Petter Selasky 	void *p_element;
510*d6b92ffaSHans Petter Selasky 
511*d6b92ffaSHans Petter Selasky 	CL_ASSERT(p_vector);
512*d6b92ffaSHans Petter Selasky 	CL_ASSERT(p_vector->state == CL_INITIALIZED);
513*d6b92ffaSHans Petter Selasky 	CL_ASSERT(pfn_callback);
514*d6b92ffaSHans Petter Selasky 
515*d6b92ffaSHans Petter Selasky 	for (i = 0; i < p_vector->size; i++) {
516*d6b92ffaSHans Petter Selasky 		p_element = cl_vector_get_ptr(p_vector, i);
517*d6b92ffaSHans Petter Selasky 		/* Invoke the callback */
518*d6b92ffaSHans Petter Selasky 		if (pfn_callback(i, p_element, (void *)context) == CL_SUCCESS)
519*d6b92ffaSHans Petter Selasky 			break;
520*d6b92ffaSHans Petter Selasky 	}
521*d6b92ffaSHans Petter Selasky 	return (i);
522*d6b92ffaSHans Petter Selasky }
523*d6b92ffaSHans Petter Selasky 
cl_vector_find_from_end(IN const cl_vector_t * const p_vector,IN cl_pfn_vec_find_t pfn_callback,IN const void * const context)524*d6b92ffaSHans Petter Selasky size_t cl_vector_find_from_end(IN const cl_vector_t * const p_vector,
525*d6b92ffaSHans Petter Selasky 			       IN cl_pfn_vec_find_t pfn_callback,
526*d6b92ffaSHans Petter Selasky 			       IN const void *const context)
527*d6b92ffaSHans Petter Selasky {
528*d6b92ffaSHans Petter Selasky 	size_t i;
529*d6b92ffaSHans Petter Selasky 	void *p_element;
530*d6b92ffaSHans Petter Selasky 
531*d6b92ffaSHans Petter Selasky 	CL_ASSERT(p_vector);
532*d6b92ffaSHans Petter Selasky 	CL_ASSERT(p_vector->state == CL_INITIALIZED);
533*d6b92ffaSHans Petter Selasky 	CL_ASSERT(pfn_callback);
534*d6b92ffaSHans Petter Selasky 
535*d6b92ffaSHans Petter Selasky 	i = p_vector->size;
536*d6b92ffaSHans Petter Selasky 
537*d6b92ffaSHans Petter Selasky 	while (i) {
538*d6b92ffaSHans Petter Selasky 		/* Get a pointer to the element in the array. */
539*d6b92ffaSHans Petter Selasky 		p_element = cl_vector_get_ptr(p_vector, --i);
540*d6b92ffaSHans Petter Selasky 		CL_ASSERT(p_element);
541*d6b92ffaSHans Petter Selasky 
542*d6b92ffaSHans Petter Selasky 		/* Invoke the callback for the current element. */
543*d6b92ffaSHans Petter Selasky 		if (pfn_callback(i, p_element, (void *)context) == CL_SUCCESS)
544*d6b92ffaSHans Petter Selasky 			return (i);
545*d6b92ffaSHans Petter Selasky 	}
546*d6b92ffaSHans Petter Selasky 
547*d6b92ffaSHans Petter Selasky 	return (p_vector->size);
548*d6b92ffaSHans Petter Selasky }
549