1321936Shselasky/*
2321936Shselasky * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved.
3321936Shselasky * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
4321936Shselasky * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
5321936Shselasky *
6321936Shselasky * This software is available to you under a choice of one of two
7321936Shselasky * licenses.  You may choose to be licensed under the terms of the GNU
8321936Shselasky * General Public License (GPL) Version 2, available from the file
9321936Shselasky * COPYING in the main directory of this source tree, or the
10321936Shselasky * OpenIB.org BSD license below:
11321936Shselasky *
12321936Shselasky *     Redistribution and use in source and binary forms, with or
13321936Shselasky *     without modification, are permitted provided that the following
14321936Shselasky *     conditions are met:
15321936Shselasky *
16321936Shselasky *      - Redistributions of source code must retain the above
17321936Shselasky *        copyright notice, this list of conditions and the following
18321936Shselasky *        disclaimer.
19321936Shselasky *
20321936Shselasky *      - Redistributions in binary form must reproduce the above
21321936Shselasky *        copyright notice, this list of conditions and the following
22321936Shselasky *        disclaimer in the documentation and/or other materials
23321936Shselasky *        provided with the distribution.
24321936Shselasky *
25321936Shselasky * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
26321936Shselasky * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
27321936Shselasky * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
28321936Shselasky * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
29321936Shselasky * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
30321936Shselasky * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
31321936Shselasky * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
32321936Shselasky * SOFTWARE.
33321936Shselasky *
34321936Shselasky */
35321936Shselasky
36321936Shselasky/*
37321936Shselasky * Abstract:
38321936Shselasky *	This file contains ivector and isvector implementations.
39321936Shselasky *
40321936Shselasky */
41321936Shselasky
42321936Shselasky#if HAVE_CONFIG_H
43321936Shselasky#  include <config.h>
44321936Shselasky#endif				/* HAVE_CONFIG_H */
45321936Shselasky
46321936Shselasky#include <stdlib.h>
47321936Shselasky#include <string.h>
48321936Shselasky#include <complib/cl_vector.h>
49321936Shselasky
50321936Shselasky/*
51321936Shselasky * Define the maximum size for array pages in an cl_vector_t.
52321936Shselasky * This size is in objects, not bytes.
53321936Shselasky */
54321936Shselasky#define SVEC_MAX_PAGE_SIZE 0x1000
55321936Shselasky
56321936Shselasky/*
57321936Shselasky * cl_vector_copy_general
58321936Shselasky *
59321936Shselasky * Description:
60321936Shselasky *	copy operator used when size of the user object doesn't fit one of the
61321936Shselasky *	other optimized copy functions.
62321936Shselasky *
63321936Shselasky * Inputs:
64321936Shselasky *	p_src - source for copy
65321936Shselasky *
66321936Shselasky * Outputs:
67321936Shselasky *	p_dest - destination for copy
68321936Shselasky *
69321936Shselasky * Returns:
70321936Shselasky *	None
71321936Shselasky *
72321936Shselasky */
73321936Shselaskystatic void cl_vector_copy_general(OUT void *const p_dest,
74321936Shselasky				   IN const void *const p_src,
75321936Shselasky				   IN const size_t size)
76321936Shselasky{
77321936Shselasky	memcpy(p_dest, p_src, size);
78321936Shselasky}
79321936Shselasky
80321936Shselasky/*
81321936Shselasky * cl_vector_copy8
82321936Shselasky *
83321936Shselasky * Description:
84321936Shselasky *	copy operator used when the user structure is only 8 bits long.
85321936Shselasky *
86321936Shselasky * Inputs:
87321936Shselasky *	p_src - source for copy
88321936Shselasky *
89321936Shselasky * Outputs:
90321936Shselasky *	p_dest - destination for copy
91321936Shselasky *
92321936Shselasky * Returns:
93321936Shselasky *	None
94321936Shselasky *
95321936Shselasky */
96321936Shselaskystatic void cl_vector_copy8(OUT void *const p_dest,
97321936Shselasky			    IN const void *const p_src, IN const size_t size)
98321936Shselasky{
99321936Shselasky	CL_ASSERT(size == sizeof(uint8_t));
100321936Shselasky	UNUSED_PARAM(size);
101321936Shselasky
102321936Shselasky	*(uint8_t *) p_dest = *(uint8_t *) p_src;
103321936Shselasky}
104321936Shselasky
105321936Shselasky/*
106321936Shselasky * cl_vector_copy16
107321936Shselasky *
108321936Shselasky * Description:
109321936Shselasky *	copy operator used when the user structure is only 16 bits long.
110321936Shselasky *
111321936Shselasky * Inputs:
112321936Shselasky *	p_src - source for copy
113321936Shselasky *
114321936Shselasky * Outputs:
115321936Shselasky *	p_dest - destination for copy
116321936Shselasky *
117321936Shselasky * Returns:
118321936Shselasky *	None
119321936Shselasky *
120321936Shselasky */
121321936Shselaskyvoid cl_vector_copy16(OUT void *const p_dest,
122321936Shselasky		      IN const void *const p_src, IN const size_t size)
123321936Shselasky{
124321936Shselasky	CL_ASSERT(size == sizeof(uint16_t));
125321936Shselasky	UNUSED_PARAM(size);
126321936Shselasky
127321936Shselasky	*(uint16_t *) p_dest = *(uint16_t *) p_src;
128321936Shselasky}
129321936Shselasky
130321936Shselasky/*
131321936Shselasky * cl_vector_copy32
132321936Shselasky *
133321936Shselasky * Description:
134321936Shselasky *	copy operator used when the user structure is only 32 bits long.
135321936Shselasky *
136321936Shselasky * Inputs:
137321936Shselasky *	p_src - source for copy
138321936Shselasky *
139321936Shselasky * Outputs:
140321936Shselasky *	p_dest - destination for copy
141321936Shselasky *
142321936Shselasky * Returns:
143321936Shselasky *	None
144321936Shselasky *
145321936Shselasky */
146321936Shselaskyvoid cl_vector_copy32(OUT void *const p_dest,
147321936Shselasky		      IN const void *const p_src, IN const size_t size)
148321936Shselasky{
149321936Shselasky	CL_ASSERT(size == sizeof(uint32_t));
150321936Shselasky	UNUSED_PARAM(size);
151321936Shselasky
152321936Shselasky	*(uint32_t *) p_dest = *(uint32_t *) p_src;
153321936Shselasky}
154321936Shselasky
155321936Shselasky/*
156321936Shselasky * cl_vector_copy64
157321936Shselasky *
158321936Shselasky * Description:
159321936Shselasky *	copy operator used when the user structure is only 64 bits long.
160321936Shselasky *
161321936Shselasky * Inputs:
162321936Shselasky *	p_src - source for copy
163321936Shselasky *
164321936Shselasky * Outputs:
165321936Shselasky *	p_dest - destination for copy
166321936Shselasky *
167321936Shselasky * Returns:
168321936Shselasky *	None
169321936Shselasky *
170321936Shselasky */
171321936Shselaskyvoid cl_vector_copy64(OUT void *const p_dest,
172321936Shselasky		      IN const void *const p_src, IN const size_t size)
173321936Shselasky{
174321936Shselasky	CL_ASSERT(size == sizeof(uint64_t));
175321936Shselasky	UNUSED_PARAM(size);
176321936Shselasky
177321936Shselasky	*(uint64_t *) p_dest = *(uint64_t *) p_src;
178321936Shselasky}
179321936Shselasky
180321936Shselaskyvoid cl_vector_construct(IN cl_vector_t * const p_vector)
181321936Shselasky{
182321936Shselasky	CL_ASSERT(p_vector);
183321936Shselasky
184321936Shselasky	memset(p_vector, 0, sizeof(cl_vector_t));
185321936Shselasky
186321936Shselasky	p_vector->state = CL_UNINITIALIZED;
187321936Shselasky}
188321936Shselasky
189321936Shselaskycl_status_t cl_vector_init(IN cl_vector_t * const p_vector,
190321936Shselasky			   IN const size_t min_size, IN const size_t grow_size,
191321936Shselasky			   IN const size_t element_size,
192321936Shselasky			   IN cl_pfn_vec_init_t pfn_init OPTIONAL,
193321936Shselasky			   IN cl_pfn_vec_dtor_t pfn_dtor OPTIONAL,
194321936Shselasky			   IN const void *const context)
195321936Shselasky{
196321936Shselasky	cl_status_t status = CL_SUCCESS;
197321936Shselasky
198321936Shselasky	CL_ASSERT(p_vector);
199321936Shselasky	CL_ASSERT(element_size);
200321936Shselasky
201321936Shselasky	cl_vector_construct(p_vector);
202321936Shselasky
203321936Shselasky	p_vector->grow_size = grow_size;
204321936Shselasky	p_vector->element_size = element_size;
205321936Shselasky	p_vector->pfn_init = pfn_init;
206321936Shselasky	p_vector->pfn_dtor = pfn_dtor;
207321936Shselasky	p_vector->context = context;
208321936Shselasky
209321936Shselasky	/*
210321936Shselasky	 * Try to choose a smart copy operator
211321936Shselasky	 * someday, we could simply let the users pass one in
212321936Shselasky	 */
213321936Shselasky	switch (element_size) {
214321936Shselasky	case sizeof(uint8_t):
215321936Shselasky		p_vector->pfn_copy = cl_vector_copy8;
216321936Shselasky		break;
217321936Shselasky
218321936Shselasky	case sizeof(uint16_t):
219321936Shselasky		p_vector->pfn_copy = cl_vector_copy16;
220321936Shselasky		break;
221321936Shselasky
222321936Shselasky	case sizeof(uint32_t):
223321936Shselasky		p_vector->pfn_copy = cl_vector_copy32;
224321936Shselasky		break;
225321936Shselasky
226321936Shselasky	case sizeof(uint64_t):
227321936Shselasky		p_vector->pfn_copy = cl_vector_copy64;
228321936Shselasky		break;
229321936Shselasky
230321936Shselasky	default:
231321936Shselasky		p_vector->pfn_copy = cl_vector_copy_general;
232321936Shselasky		break;
233321936Shselasky	}
234321936Shselasky
235321936Shselasky	/*
236321936Shselasky	 * Set the state to initialized so that the call to set_size
237321936Shselasky	 * doesn't assert.
238321936Shselasky	 */
239321936Shselasky	p_vector->state = CL_INITIALIZED;
240321936Shselasky
241321936Shselasky	/* Initialize the allocation list */
242321936Shselasky	cl_qlist_init(&p_vector->alloc_list);
243321936Shselasky
244321936Shselasky	/* get the storage needed by the user */
245321936Shselasky	if (min_size) {
246321936Shselasky		status = cl_vector_set_size(p_vector, min_size);
247321936Shselasky		if (status != CL_SUCCESS)
248321936Shselasky			cl_vector_destroy(p_vector);
249321936Shselasky	}
250321936Shselasky
251321936Shselasky	return (status);
252321936Shselasky}
253321936Shselasky
254321936Shselaskyvoid cl_vector_destroy(IN cl_vector_t * const p_vector)
255321936Shselasky{
256321936Shselasky	size_t i;
257321936Shselasky	void *p_element;
258321936Shselasky
259321936Shselasky	CL_ASSERT(p_vector);
260321936Shselasky	CL_ASSERT(cl_is_state_valid(p_vector->state));
261321936Shselasky
262321936Shselasky	/* Call the user's destructor for each element in the array. */
263321936Shselasky	if (p_vector->state == CL_INITIALIZED) {
264321936Shselasky		if (p_vector->pfn_dtor) {
265321936Shselasky			for (i = 0; i < p_vector->size; i++) {
266321936Shselasky				p_element = p_vector->p_ptr_array[i];
267321936Shselasky				/* Sanity check! */
268321936Shselasky				CL_ASSERT(p_element);
269321936Shselasky				p_vector->pfn_dtor(p_element,
270321936Shselasky						   (void *)p_vector->context);
271321936Shselasky			}
272321936Shselasky		}
273321936Shselasky
274321936Shselasky		/* Deallocate the pages */
275321936Shselasky		while (!cl_is_qlist_empty(&p_vector->alloc_list))
276321936Shselasky			free(cl_qlist_remove_head(&p_vector->alloc_list));
277321936Shselasky
278321936Shselasky		/* Destroy the page vector. */
279321936Shselasky		if (p_vector->p_ptr_array) {
280321936Shselasky			free(p_vector->p_ptr_array);
281321936Shselasky			p_vector->p_ptr_array = NULL;
282321936Shselasky		}
283321936Shselasky	}
284321936Shselasky
285321936Shselasky	p_vector->state = CL_UNINITIALIZED;
286321936Shselasky}
287321936Shselasky
288321936Shselaskycl_status_t cl_vector_at(IN const cl_vector_t * const p_vector,
289321936Shselasky			 IN const size_t index, OUT void *const p_element)
290321936Shselasky{
291321936Shselasky	CL_ASSERT(p_vector);
292321936Shselasky	CL_ASSERT(p_vector->state == CL_INITIALIZED);
293321936Shselasky
294321936Shselasky	/* Range check */
295321936Shselasky	if (index >= p_vector->size)
296321936Shselasky		return (CL_INVALID_PARAMETER);
297321936Shselasky
298321936Shselasky	cl_vector_get(p_vector, index, p_element);
299321936Shselasky	return (CL_SUCCESS);
300321936Shselasky}
301321936Shselasky
302321936Shselaskycl_status_t cl_vector_set(IN cl_vector_t * const p_vector,
303321936Shselasky			  IN const size_t index, IN void *const p_element)
304321936Shselasky{
305321936Shselasky	cl_status_t status;
306321936Shselasky	void *p_dest;
307321936Shselasky
308321936Shselasky	CL_ASSERT(p_vector);
309321936Shselasky	CL_ASSERT(p_vector->state == CL_INITIALIZED);
310321936Shselasky	CL_ASSERT(p_element);
311321936Shselasky
312321936Shselasky	/* Determine if the vector has room for this element. */
313321936Shselasky	if (index >= p_vector->size) {
314321936Shselasky		/* Resize to accomodate the given index. */
315321936Shselasky		status = cl_vector_set_size(p_vector, index + 1);
316321936Shselasky
317321936Shselasky		/* Check for failure on or before the given index. */
318321936Shselasky		if ((status != CL_SUCCESS) && (p_vector->size < index))
319321936Shselasky			return (status);
320321936Shselasky	}
321321936Shselasky
322321936Shselasky	/* At this point, the array is guaranteed to be big enough */
323321936Shselasky	p_dest = cl_vector_get_ptr(p_vector, index);
324321936Shselasky	/* Sanity check! */
325321936Shselasky	CL_ASSERT(p_dest);
326321936Shselasky
327321936Shselasky	/* Copy the data into the array */
328321936Shselasky	p_vector->pfn_copy(p_dest, p_element, p_vector->element_size);
329321936Shselasky
330321936Shselasky	return (CL_SUCCESS);
331321936Shselasky}
332321936Shselasky
333321936Shselaskycl_status_t cl_vector_set_capacity(IN cl_vector_t * const p_vector,
334321936Shselasky				   IN const size_t new_capacity)
335321936Shselasky{
336321936Shselasky	size_t new_elements;
337321936Shselasky	size_t alloc_size;
338321936Shselasky	size_t i;
339321936Shselasky	cl_list_item_t *p_buf;
340321936Shselasky	void *p_new_ptr_array;
341321936Shselasky
342321936Shselasky	CL_ASSERT(p_vector);
343321936Shselasky	CL_ASSERT(p_vector->state == CL_INITIALIZED);
344321936Shselasky
345321936Shselasky	/* Do we have to do anything here? */
346321936Shselasky	if (new_capacity <= p_vector->capacity) {
347321936Shselasky		/* Nope */
348321936Shselasky		return (CL_SUCCESS);
349321936Shselasky	}
350321936Shselasky
351321936Shselasky	/* Allocate our pointer array. */
352321936Shselasky	p_new_ptr_array = malloc(new_capacity * sizeof(void *));
353321936Shselasky	if (!p_new_ptr_array)
354321936Shselasky		return (CL_INSUFFICIENT_MEMORY);
355321936Shselasky	else
356321936Shselasky		memset(p_new_ptr_array, 0, new_capacity * sizeof(void *));
357321936Shselasky
358321936Shselasky	if (p_vector->p_ptr_array) {
359321936Shselasky		/* Copy the old pointer array into the new. */
360321936Shselasky		memcpy(p_new_ptr_array, p_vector->p_ptr_array,
361321936Shselasky		       p_vector->capacity * sizeof(void *));
362321936Shselasky
363321936Shselasky		/* Free the old pointer array. */
364321936Shselasky		free(p_vector->p_ptr_array);
365321936Shselasky	}
366321936Shselasky
367321936Shselasky	/* Set the new array. */
368321936Shselasky	p_vector->p_ptr_array = p_new_ptr_array;
369321936Shselasky
370321936Shselasky	/*
371321936Shselasky	 * We have to add capacity to the array.  Determine how many
372321936Shselasky	 * elements to add.
373321936Shselasky	 */
374321936Shselasky	new_elements = new_capacity - p_vector->capacity;
375321936Shselasky	/* Determine the allocation size for the new array elements. */
376321936Shselasky	alloc_size = new_elements * p_vector->element_size;
377321936Shselasky
378321936Shselasky	p_buf = (cl_list_item_t *) malloc(alloc_size + sizeof(cl_list_item_t));
379321936Shselasky	if (!p_buf)
380321936Shselasky		return (CL_INSUFFICIENT_MEMORY);
381321936Shselasky	else
382321936Shselasky		memset(p_buf, 0, alloc_size + sizeof(cl_list_item_t));
383321936Shselasky
384321936Shselasky	cl_qlist_insert_tail(&p_vector->alloc_list, p_buf);
385321936Shselasky	/* Advance the buffer pointer past the list item. */
386321936Shselasky	p_buf++;
387321936Shselasky
388321936Shselasky	for (i = p_vector->capacity; i < new_capacity; i++) {
389321936Shselasky		p_vector->p_ptr_array[i] = p_buf;
390321936Shselasky		/* Move the buffer pointer to the next element. */
391321936Shselasky		p_buf = (void *)(((uint8_t *) p_buf) + p_vector->element_size);
392321936Shselasky	}
393321936Shselasky
394321936Shselasky	/* Update the vector with the new capactity. */
395321936Shselasky	p_vector->capacity = new_capacity;
396321936Shselasky
397321936Shselasky	return (CL_SUCCESS);
398321936Shselasky}
399321936Shselasky
400321936Shselaskycl_status_t cl_vector_set_size(IN cl_vector_t * const p_vector,
401321936Shselasky			       IN const size_t size)
402321936Shselasky{
403321936Shselasky	cl_status_t status;
404321936Shselasky	size_t new_capacity;
405321936Shselasky	size_t index;
406321936Shselasky	void *p_element;
407321936Shselasky
408321936Shselasky	CL_ASSERT(p_vector);
409321936Shselasky	CL_ASSERT(p_vector->state == CL_INITIALIZED);
410321936Shselasky
411321936Shselasky	/* Check to see if the requested size is the same as the existing size. */
412321936Shselasky	if (size == p_vector->size)
413321936Shselasky		return (CL_SUCCESS);
414321936Shselasky
415321936Shselasky	/* Determine if the vector has room for this element. */
416321936Shselasky	if (size >= p_vector->capacity) {
417321936Shselasky		if (!p_vector->grow_size)
418321936Shselasky			return (CL_INSUFFICIENT_MEMORY);
419321936Shselasky
420321936Shselasky		/* Calculate the new capacity, taking into account the grow size. */
421321936Shselasky		new_capacity = size;
422321936Shselasky		if (size % p_vector->grow_size) {
423321936Shselasky			/* Round up to nearest grow_size boundary. */
424321936Shselasky			new_capacity += p_vector->grow_size -
425321936Shselasky			    (size % p_vector->grow_size);
426321936Shselasky		}
427321936Shselasky
428321936Shselasky		status = cl_vector_set_capacity(p_vector, new_capacity);
429321936Shselasky		if (status != CL_SUCCESS)
430321936Shselasky			return (status);
431321936Shselasky	}
432321936Shselasky
433321936Shselasky	/* Are we growing the array and need to invoke an initializer callback? */
434321936Shselasky	if (size > p_vector->size && p_vector->pfn_init) {
435321936Shselasky		for (index = p_vector->size; index < size; index++) {
436321936Shselasky			/* Get a pointer to this element */
437321936Shselasky			p_element = cl_vector_get_ptr(p_vector, index);
438321936Shselasky
439321936Shselasky			/* Call the user's initializer and trap failures. */
440321936Shselasky			status =
441321936Shselasky			    p_vector->pfn_init(p_element,
442321936Shselasky					       (void *)p_vector->context);
443321936Shselasky			if (status != CL_SUCCESS) {
444321936Shselasky				/* Call the destructor for this object */
445321936Shselasky				if (p_vector->pfn_dtor)
446321936Shselasky					p_vector->pfn_dtor(p_element,
447321936Shselasky							   (void *)p_vector->
448321936Shselasky							   context);
449321936Shselasky
450321936Shselasky				/* Return the failure status to the caller. */
451321936Shselasky				return (status);
452321936Shselasky			}
453321936Shselasky
454321936Shselasky			/* The array just grew by one element */
455321936Shselasky			p_vector->size++;
456321936Shselasky		}
457321936Shselasky	} else if (p_vector->pfn_dtor) {
458321936Shselasky		/* The array is shrinking and there is a destructor to invoke. */
459321936Shselasky		for (index = size; index < p_vector->size; index++) {
460321936Shselasky			/* compute the address of the new elements */
461321936Shselasky			p_element = cl_vector_get_ptr(p_vector, index);
462321936Shselasky			/* call the user's destructor */
463321936Shselasky			p_vector->pfn_dtor(p_element,
464321936Shselasky					   (void *)p_vector->context);
465321936Shselasky		}
466321936Shselasky	}
467321936Shselasky
468321936Shselasky	p_vector->size = size;
469321936Shselasky	return (CL_SUCCESS);
470321936Shselasky}
471321936Shselasky
472321936Shselaskycl_status_t cl_vector_set_min_size(IN cl_vector_t * const p_vector,
473321936Shselasky				   IN const size_t min_size)
474321936Shselasky{
475321936Shselasky	CL_ASSERT(p_vector);
476321936Shselasky	CL_ASSERT(p_vector->state == CL_INITIALIZED);
477321936Shselasky
478321936Shselasky	if (min_size > p_vector->size) {
479321936Shselasky		/* We have to resize the array */
480321936Shselasky		return (cl_vector_set_size(p_vector, min_size));
481321936Shselasky	}
482321936Shselasky
483321936Shselasky	/* We didn't have to do anything */
484321936Shselasky	return (CL_SUCCESS);
485321936Shselasky}
486321936Shselasky
487321936Shselaskyvoid cl_vector_apply_func(IN const cl_vector_t * const p_vector,
488321936Shselasky			  IN cl_pfn_vec_apply_t pfn_callback,
489321936Shselasky			  IN const void *const context)
490321936Shselasky{
491321936Shselasky	size_t i;
492321936Shselasky	void *p_element;
493321936Shselasky
494321936Shselasky	CL_ASSERT(p_vector);
495321936Shselasky	CL_ASSERT(p_vector->state == CL_INITIALIZED);
496321936Shselasky	CL_ASSERT(pfn_callback);
497321936Shselasky
498321936Shselasky	for (i = 0; i < p_vector->size; i++) {
499321936Shselasky		p_element = cl_vector_get_ptr(p_vector, i);
500321936Shselasky		pfn_callback(i, p_element, (void *)context);
501321936Shselasky	}
502321936Shselasky}
503321936Shselasky
504321936Shselaskysize_t cl_vector_find_from_start(IN const cl_vector_t * const p_vector,
505321936Shselasky				 IN cl_pfn_vec_find_t pfn_callback,
506321936Shselasky				 IN const void *const context)
507321936Shselasky{
508321936Shselasky	size_t i;
509321936Shselasky	void *p_element;
510321936Shselasky
511321936Shselasky	CL_ASSERT(p_vector);
512321936Shselasky	CL_ASSERT(p_vector->state == CL_INITIALIZED);
513321936Shselasky	CL_ASSERT(pfn_callback);
514321936Shselasky
515321936Shselasky	for (i = 0; i < p_vector->size; i++) {
516321936Shselasky		p_element = cl_vector_get_ptr(p_vector, i);
517321936Shselasky		/* Invoke the callback */
518321936Shselasky		if (pfn_callback(i, p_element, (void *)context) == CL_SUCCESS)
519321936Shselasky			break;
520321936Shselasky	}
521321936Shselasky	return (i);
522321936Shselasky}
523321936Shselasky
524321936Shselaskysize_t cl_vector_find_from_end(IN const cl_vector_t * const p_vector,
525321936Shselasky			       IN cl_pfn_vec_find_t pfn_callback,
526321936Shselasky			       IN const void *const context)
527321936Shselasky{
528321936Shselasky	size_t i;
529321936Shselasky	void *p_element;
530321936Shselasky
531321936Shselasky	CL_ASSERT(p_vector);
532321936Shselasky	CL_ASSERT(p_vector->state == CL_INITIALIZED);
533321936Shselasky	CL_ASSERT(pfn_callback);
534321936Shselasky
535321936Shselasky	i = p_vector->size;
536321936Shselasky
537321936Shselasky	while (i) {
538321936Shselasky		/* Get a pointer to the element in the array. */
539321936Shselasky		p_element = cl_vector_get_ptr(p_vector, --i);
540321936Shselasky		CL_ASSERT(p_element);
541321936Shselasky
542321936Shselasky		/* Invoke the callback for the current element. */
543321936Shselasky		if (pfn_callback(i, p_element, (void *)context) == CL_SUCCESS)
544321936Shselasky			return (i);
545321936Shselasky	}
546321936Shselasky
547321936Shselasky	return (p_vector->size);
548321936Shselasky}
549