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