1219820Sjeff/*
2219820Sjeff * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved.
3219820Sjeff * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
4219820Sjeff * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
5219820Sjeff *
6219820Sjeff * This software is available to you under a choice of one of two
7219820Sjeff * licenses.  You may choose to be licensed under the terms of the GNU
8219820Sjeff * General Public License (GPL) Version 2, available from the file
9219820Sjeff * COPYING in the main directory of this source tree, or the
10219820Sjeff * OpenIB.org BSD license below:
11219820Sjeff *
12219820Sjeff *     Redistribution and use in source and binary forms, with or
13219820Sjeff *     without modification, are permitted provided that the following
14219820Sjeff *     conditions are met:
15219820Sjeff *
16219820Sjeff *      - Redistributions of source code must retain the above
17219820Sjeff *        copyright notice, this list of conditions and the following
18219820Sjeff *        disclaimer.
19219820Sjeff *
20219820Sjeff *      - Redistributions in binary form must reproduce the above
21219820Sjeff *        copyright notice, this list of conditions and the following
22219820Sjeff *        disclaimer in the documentation and/or other materials
23219820Sjeff *        provided with the distribution.
24219820Sjeff *
25219820Sjeff * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
26219820Sjeff * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
27219820Sjeff * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
28219820Sjeff * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
29219820Sjeff * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
30219820Sjeff * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
31219820Sjeff * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
32219820Sjeff * SOFTWARE.
33219820Sjeff *
34219820Sjeff */
35219820Sjeff
36219820Sjeff/*
37219820Sjeff * Abstract:
38219820Sjeff *	This file contains ivector and isvector implementations.
39219820Sjeff *
40219820Sjeff */
41219820Sjeff
42219820Sjeff#if HAVE_CONFIG_H
43219820Sjeff#  include <config.h>
44219820Sjeff#endif				/* HAVE_CONFIG_H */
45219820Sjeff
46219820Sjeff#include <stdlib.h>
47219820Sjeff#include <string.h>
48219820Sjeff#include <complib/cl_vector.h>
49219820Sjeff
50219820Sjeff/*
51219820Sjeff * Define the maximum size for array pages in an cl_vector_t.
52219820Sjeff * This size is in objects, not bytes.
53219820Sjeff */
54219820Sjeff#define SVEC_MAX_PAGE_SIZE 0x1000
55219820Sjeff
56219820Sjeff/*
57219820Sjeff * cl_vector_copy_general
58219820Sjeff *
59219820Sjeff * Description:
60219820Sjeff *	copy operator used when size of the user object doesn't fit one of the
61219820Sjeff *	other optimized copy functions.
62219820Sjeff *
63219820Sjeff * Inputs:
64219820Sjeff *	p_src - source for copy
65219820Sjeff *
66219820Sjeff * Outputs:
67219820Sjeff *	p_dest - destination for copy
68219820Sjeff *
69219820Sjeff * Returns:
70219820Sjeff *	None
71219820Sjeff *
72219820Sjeff */
73219820Sjeffstatic void
74219820Sjeffcl_vector_copy_general(OUT void *const p_dest,
75219820Sjeff		       IN const void *const p_src, IN const size_t size)
76219820Sjeff{
77219820Sjeff	memcpy(p_dest, p_src, size);
78219820Sjeff}
79219820Sjeff
80219820Sjeff/*
81219820Sjeff * cl_vector_copy8
82219820Sjeff *
83219820Sjeff * Description:
84219820Sjeff *	copy operator used when the user structure is only 8 bits long.
85219820Sjeff *
86219820Sjeff * Inputs:
87219820Sjeff *	p_src - source for copy
88219820Sjeff *
89219820Sjeff * Outputs:
90219820Sjeff *	p_dest - destination for copy
91219820Sjeff *
92219820Sjeff * Returns:
93219820Sjeff *	None
94219820Sjeff *
95219820Sjeff */
96219820Sjeffstatic void
97219820Sjeffcl_vector_copy8(OUT void *const p_dest,
98219820Sjeff		IN const void *const p_src, IN const size_t size)
99219820Sjeff{
100219820Sjeff	CL_ASSERT(size == sizeof(uint8_t));
101219820Sjeff	UNUSED_PARAM(size);
102219820Sjeff
103219820Sjeff	*(uint8_t *) p_dest = *(uint8_t *) p_src;
104219820Sjeff}
105219820Sjeff
106219820Sjeff/*
107219820Sjeff * cl_vector_copy16
108219820Sjeff *
109219820Sjeff * Description:
110219820Sjeff *	copy operator used when the user structure is only 16 bits long.
111219820Sjeff *
112219820Sjeff * Inputs:
113219820Sjeff *	p_src - source for copy
114219820Sjeff *
115219820Sjeff * Outputs:
116219820Sjeff *	p_dest - destination for copy
117219820Sjeff *
118219820Sjeff * Returns:
119219820Sjeff *	None
120219820Sjeff *
121219820Sjeff */
122219820Sjeffvoid
123219820Sjeffcl_vector_copy16(OUT void *const p_dest,
124219820Sjeff		 IN const void *const p_src, IN const size_t size)
125219820Sjeff{
126219820Sjeff	CL_ASSERT(size == sizeof(uint16_t));
127219820Sjeff	UNUSED_PARAM(size);
128219820Sjeff
129219820Sjeff	*(uint16_t *) p_dest = *(uint16_t *) p_src;
130219820Sjeff}
131219820Sjeff
132219820Sjeff/*
133219820Sjeff * cl_vector_copy32
134219820Sjeff *
135219820Sjeff * Description:
136219820Sjeff *	copy operator used when the user structure is only 32 bits long.
137219820Sjeff *
138219820Sjeff * Inputs:
139219820Sjeff *	p_src - source for copy
140219820Sjeff *
141219820Sjeff * Outputs:
142219820Sjeff *	p_dest - destination for copy
143219820Sjeff *
144219820Sjeff * Returns:
145219820Sjeff *	None
146219820Sjeff *
147219820Sjeff */
148219820Sjeffvoid
149219820Sjeffcl_vector_copy32(OUT void *const p_dest,
150219820Sjeff		 IN const void *const p_src, IN const size_t size)
151219820Sjeff{
152219820Sjeff	CL_ASSERT(size == sizeof(uint32_t));
153219820Sjeff	UNUSED_PARAM(size);
154219820Sjeff
155219820Sjeff	*(uint32_t *) p_dest = *(uint32_t *) p_src;
156219820Sjeff}
157219820Sjeff
158219820Sjeff/*
159219820Sjeff * cl_vector_copy64
160219820Sjeff *
161219820Sjeff * Description:
162219820Sjeff *	copy operator used when the user structure is only 64 bits long.
163219820Sjeff *
164219820Sjeff * Inputs:
165219820Sjeff *	p_src - source for copy
166219820Sjeff *
167219820Sjeff * Outputs:
168219820Sjeff *	p_dest - destination for copy
169219820Sjeff *
170219820Sjeff * Returns:
171219820Sjeff *	None
172219820Sjeff *
173219820Sjeff */
174219820Sjeffvoid
175219820Sjeffcl_vector_copy64(OUT void *const p_dest,
176219820Sjeff		 IN const void *const p_src, IN const size_t size)
177219820Sjeff{
178219820Sjeff	CL_ASSERT(size == sizeof(uint64_t));
179219820Sjeff	UNUSED_PARAM(size);
180219820Sjeff
181219820Sjeff	*(uint64_t *) p_dest = *(uint64_t *) p_src;
182219820Sjeff}
183219820Sjeff
184219820Sjeffvoid cl_vector_construct(IN cl_vector_t * const p_vector)
185219820Sjeff{
186219820Sjeff	CL_ASSERT(p_vector);
187219820Sjeff
188219820Sjeff	memset(p_vector, 0, sizeof(cl_vector_t));
189219820Sjeff
190219820Sjeff	p_vector->state = CL_UNINITIALIZED;
191219820Sjeff}
192219820Sjeff
193219820Sjeffcl_status_t
194219820Sjeffcl_vector_init(IN cl_vector_t * const p_vector,
195219820Sjeff	       IN const size_t min_size,
196219820Sjeff	       IN const size_t grow_size,
197219820Sjeff	       IN const size_t element_size,
198219820Sjeff	       IN cl_pfn_vec_init_t pfn_init OPTIONAL,
199219820Sjeff	       IN cl_pfn_vec_dtor_t pfn_dtor OPTIONAL,
200219820Sjeff	       IN const void *const context)
201219820Sjeff{
202219820Sjeff	cl_status_t status = CL_SUCCESS;
203219820Sjeff
204219820Sjeff	CL_ASSERT(p_vector);
205219820Sjeff	CL_ASSERT(element_size);
206219820Sjeff
207219820Sjeff	cl_vector_construct(p_vector);
208219820Sjeff
209219820Sjeff	p_vector->grow_size = grow_size;
210219820Sjeff	p_vector->element_size = element_size;
211219820Sjeff	p_vector->pfn_init = pfn_init;
212219820Sjeff	p_vector->pfn_dtor = pfn_dtor;
213219820Sjeff	p_vector->context = context;
214219820Sjeff
215219820Sjeff	/*
216219820Sjeff	 * Try to choose a smart copy operator
217219820Sjeff	 * someday, we could simply let the users pass one in
218219820Sjeff	 */
219219820Sjeff	switch (element_size) {
220219820Sjeff	case sizeof(uint8_t):
221219820Sjeff		p_vector->pfn_copy = cl_vector_copy8;
222219820Sjeff		break;
223219820Sjeff
224219820Sjeff	case sizeof(uint16_t):
225219820Sjeff		p_vector->pfn_copy = cl_vector_copy16;
226219820Sjeff		break;
227219820Sjeff
228219820Sjeff	case sizeof(uint32_t):
229219820Sjeff		p_vector->pfn_copy = cl_vector_copy32;
230219820Sjeff		break;
231219820Sjeff
232219820Sjeff	case sizeof(uint64_t):
233219820Sjeff		p_vector->pfn_copy = cl_vector_copy64;
234219820Sjeff		break;
235219820Sjeff
236219820Sjeff	default:
237219820Sjeff		p_vector->pfn_copy = cl_vector_copy_general;
238219820Sjeff		break;
239219820Sjeff	}
240219820Sjeff
241219820Sjeff	/*
242219820Sjeff	 * Set the state to initialized so that the call to set_size
243219820Sjeff	 * doesn't assert.
244219820Sjeff	 */
245219820Sjeff	p_vector->state = CL_INITIALIZED;
246219820Sjeff
247219820Sjeff	/* Initialize the allocation list */
248219820Sjeff	cl_qlist_init(&p_vector->alloc_list);
249219820Sjeff
250219820Sjeff	/* get the storage needed by the user */
251219820Sjeff	if (min_size) {
252219820Sjeff		status = cl_vector_set_size(p_vector, min_size);
253219820Sjeff		if (status != CL_SUCCESS)
254219820Sjeff			cl_vector_destroy(p_vector);
255219820Sjeff	}
256219820Sjeff
257219820Sjeff	return (status);
258219820Sjeff}
259219820Sjeff
260219820Sjeffvoid cl_vector_destroy(IN cl_vector_t * const p_vector)
261219820Sjeff{
262219820Sjeff	size_t i;
263219820Sjeff	void *p_element;
264219820Sjeff
265219820Sjeff	CL_ASSERT(p_vector);
266219820Sjeff	CL_ASSERT(cl_is_state_valid(p_vector->state));
267219820Sjeff
268219820Sjeff	/* Call the user's destructor for each element in the array. */
269219820Sjeff	if (p_vector->state == CL_INITIALIZED) {
270219820Sjeff		if (p_vector->pfn_dtor) {
271219820Sjeff			for (i = 0; i < p_vector->size; i++) {
272219820Sjeff				p_element = p_vector->p_ptr_array[i];
273219820Sjeff				/* Sanity check! */
274219820Sjeff				CL_ASSERT(p_element);
275219820Sjeff				p_vector->pfn_dtor(p_element,
276219820Sjeff						   (void *)p_vector->context);
277219820Sjeff			}
278219820Sjeff		}
279219820Sjeff
280219820Sjeff		/* Deallocate the pages */
281219820Sjeff		while (!cl_is_qlist_empty(&p_vector->alloc_list))
282219820Sjeff			free(cl_qlist_remove_head(&p_vector->alloc_list));
283219820Sjeff
284219820Sjeff		/* Destroy the page vector. */
285219820Sjeff		if (p_vector->p_ptr_array) {
286219820Sjeff			free(p_vector->p_ptr_array);
287219820Sjeff			p_vector->p_ptr_array = NULL;
288219820Sjeff		}
289219820Sjeff	}
290219820Sjeff
291219820Sjeff	p_vector->state = CL_UNINITIALIZED;
292219820Sjeff}
293219820Sjeff
294219820Sjeffcl_status_t
295219820Sjeffcl_vector_at(IN const cl_vector_t * const p_vector,
296219820Sjeff	     IN const size_t index, OUT void *const p_element)
297219820Sjeff{
298219820Sjeff	CL_ASSERT(p_vector);
299219820Sjeff	CL_ASSERT(p_vector->state == CL_INITIALIZED);
300219820Sjeff
301219820Sjeff	/* Range check */
302219820Sjeff	if (index >= p_vector->size)
303219820Sjeff		return (CL_INVALID_PARAMETER);
304219820Sjeff
305219820Sjeff	cl_vector_get(p_vector, index, p_element);
306219820Sjeff	return (CL_SUCCESS);
307219820Sjeff}
308219820Sjeff
309219820Sjeffcl_status_t
310219820Sjeffcl_vector_set(IN cl_vector_t * const p_vector,
311219820Sjeff	      IN const size_t index, IN void *const p_element)
312219820Sjeff{
313219820Sjeff	cl_status_t status;
314219820Sjeff	void *p_dest;
315219820Sjeff
316219820Sjeff	CL_ASSERT(p_vector);
317219820Sjeff	CL_ASSERT(p_vector->state == CL_INITIALIZED);
318219820Sjeff	CL_ASSERT(p_element);
319219820Sjeff
320219820Sjeff	/* Determine if the vector has room for this element. */
321219820Sjeff	if (index >= p_vector->size) {
322219820Sjeff		/* Resize to accomodate the given index. */
323219820Sjeff		status = cl_vector_set_size(p_vector, index + 1);
324219820Sjeff
325219820Sjeff		/* Check for failure on or before the given index. */
326219820Sjeff		if ((status != CL_SUCCESS) && (p_vector->size < index))
327219820Sjeff			return (status);
328219820Sjeff	}
329219820Sjeff
330219820Sjeff	/* At this point, the array is guaranteed to be big enough */
331219820Sjeff	p_dest = cl_vector_get_ptr(p_vector, index);
332219820Sjeff	/* Sanity check! */
333219820Sjeff	CL_ASSERT(p_dest);
334219820Sjeff
335219820Sjeff	/* Copy the data into the array */
336219820Sjeff	p_vector->pfn_copy(p_dest, p_element, p_vector->element_size);
337219820Sjeff
338219820Sjeff	return (CL_SUCCESS);
339219820Sjeff}
340219820Sjeff
341219820Sjeffcl_status_t
342219820Sjeffcl_vector_set_capacity(IN cl_vector_t * const p_vector,
343219820Sjeff		       IN const size_t new_capacity)
344219820Sjeff{
345219820Sjeff	size_t new_elements;
346219820Sjeff	size_t alloc_size;
347219820Sjeff	size_t i;
348219820Sjeff	cl_list_item_t *p_buf;
349219820Sjeff	void *p_new_ptr_array;
350219820Sjeff
351219820Sjeff	CL_ASSERT(p_vector);
352219820Sjeff	CL_ASSERT(p_vector->state == CL_INITIALIZED);
353219820Sjeff
354219820Sjeff	/* Do we have to do anything here? */
355219820Sjeff	if (new_capacity <= p_vector->capacity) {
356219820Sjeff		/* Nope */
357219820Sjeff		return (CL_SUCCESS);
358219820Sjeff	}
359219820Sjeff
360219820Sjeff	/* Allocate our pointer array. */
361219820Sjeff	p_new_ptr_array = malloc(new_capacity * sizeof(void *));
362219820Sjeff	if (!p_new_ptr_array)
363219820Sjeff		return (CL_INSUFFICIENT_MEMORY);
364219820Sjeff	else
365219820Sjeff		memset(p_new_ptr_array, 0, new_capacity * sizeof(void *));
366219820Sjeff
367219820Sjeff	if (p_vector->p_ptr_array) {
368219820Sjeff		/* Copy the old pointer array into the new. */
369219820Sjeff		memcpy(p_new_ptr_array, p_vector->p_ptr_array,
370219820Sjeff		       p_vector->capacity * sizeof(void *));
371219820Sjeff
372219820Sjeff		/* Free the old pointer array. */
373219820Sjeff		free(p_vector->p_ptr_array);
374219820Sjeff	}
375219820Sjeff
376219820Sjeff	/* Set the new array. */
377219820Sjeff	p_vector->p_ptr_array = p_new_ptr_array;
378219820Sjeff
379219820Sjeff	/*
380219820Sjeff	 * We have to add capacity to the array.  Determine how many
381219820Sjeff	 * elements to add.
382219820Sjeff	 */
383219820Sjeff	new_elements = new_capacity - p_vector->capacity;
384219820Sjeff	/* Determine the allocation size for the new array elements. */
385219820Sjeff	alloc_size = new_elements * p_vector->element_size;
386219820Sjeff
387219820Sjeff	p_buf = (cl_list_item_t *) malloc(alloc_size + sizeof(cl_list_item_t));
388219820Sjeff	if (!p_buf)
389219820Sjeff		return (CL_INSUFFICIENT_MEMORY);
390219820Sjeff	else
391219820Sjeff		memset(p_buf, 0, alloc_size + sizeof(cl_list_item_t));
392219820Sjeff
393219820Sjeff	cl_qlist_insert_tail(&p_vector->alloc_list, p_buf);
394219820Sjeff	/* Advance the buffer pointer past the list item. */
395219820Sjeff	p_buf++;
396219820Sjeff
397219820Sjeff	for (i = p_vector->capacity; i < new_capacity; i++) {
398219820Sjeff		p_vector->p_ptr_array[i] = p_buf;
399219820Sjeff		/* Move the buffer pointer to the next element. */
400219820Sjeff		p_buf = (void *)(((uint8_t *) p_buf) + p_vector->element_size);
401219820Sjeff	}
402219820Sjeff
403219820Sjeff	/* Update the vector with the new capactity. */
404219820Sjeff	p_vector->capacity = new_capacity;
405219820Sjeff
406219820Sjeff	return (CL_SUCCESS);
407219820Sjeff}
408219820Sjeff
409219820Sjeffcl_status_t
410219820Sjeffcl_vector_set_size(IN cl_vector_t * const p_vector, IN const size_t size)
411219820Sjeff{
412219820Sjeff	cl_status_t status;
413219820Sjeff	size_t new_capacity;
414219820Sjeff	size_t index;
415219820Sjeff	void *p_element;
416219820Sjeff
417219820Sjeff	CL_ASSERT(p_vector);
418219820Sjeff	CL_ASSERT(p_vector->state == CL_INITIALIZED);
419219820Sjeff
420219820Sjeff	/* Check to see if the requested size is the same as the existing size. */
421219820Sjeff	if (size == p_vector->size)
422219820Sjeff		return (CL_SUCCESS);
423219820Sjeff
424219820Sjeff	/* Determine if the vector has room for this element. */
425219820Sjeff	if (size >= p_vector->capacity) {
426219820Sjeff		if (!p_vector->grow_size)
427219820Sjeff			return (CL_INSUFFICIENT_MEMORY);
428219820Sjeff
429219820Sjeff		/* Calculate the new capacity, taking into account the grow size. */
430219820Sjeff		new_capacity = size;
431219820Sjeff		if (size % p_vector->grow_size) {
432219820Sjeff			/* Round up to nearest grow_size boundary. */
433219820Sjeff			new_capacity += p_vector->grow_size -
434219820Sjeff			    (size % p_vector->grow_size);
435219820Sjeff		}
436219820Sjeff
437219820Sjeff		status = cl_vector_set_capacity(p_vector, new_capacity);
438219820Sjeff		if (status != CL_SUCCESS)
439219820Sjeff			return (status);
440219820Sjeff	}
441219820Sjeff
442219820Sjeff	/* Are we growing the array and need to invoke an initializer callback? */
443219820Sjeff	if (size > p_vector->size && p_vector->pfn_init) {
444219820Sjeff		for (index = p_vector->size; index < size; index++) {
445219820Sjeff			/* Get a pointer to this element */
446219820Sjeff			p_element = cl_vector_get_ptr(p_vector, index);
447219820Sjeff
448219820Sjeff			/* Call the user's initializer and trap failures. */
449219820Sjeff			status =
450219820Sjeff			    p_vector->pfn_init(p_element,
451219820Sjeff					       (void *)p_vector->context);
452219820Sjeff			if (status != CL_SUCCESS) {
453219820Sjeff				/* Call the destructor for this object */
454219820Sjeff				if (p_vector->pfn_dtor)
455219820Sjeff					p_vector->pfn_dtor(p_element,
456219820Sjeff							   (void *)p_vector->
457219820Sjeff							   context);
458219820Sjeff
459219820Sjeff				/* Return the failure status to the caller. */
460219820Sjeff				return (status);
461219820Sjeff			}
462219820Sjeff
463219820Sjeff			/* The array just grew by one element */
464219820Sjeff			p_vector->size++;
465219820Sjeff		}
466219820Sjeff	} else if (p_vector->pfn_dtor) {
467219820Sjeff		/* The array is shrinking and there is a destructor to invoke. */
468219820Sjeff		for (index = size; index < p_vector->size; index++) {
469219820Sjeff			/* compute the address of the new elements */
470219820Sjeff			p_element = cl_vector_get_ptr(p_vector, index);
471219820Sjeff			/* call the user's destructor */
472219820Sjeff			p_vector->pfn_dtor(p_element,
473219820Sjeff					   (void *)p_vector->context);
474219820Sjeff		}
475219820Sjeff	}
476219820Sjeff
477219820Sjeff	p_vector->size = size;
478219820Sjeff	return (CL_SUCCESS);
479219820Sjeff}
480219820Sjeff
481219820Sjeffcl_status_t
482219820Sjeffcl_vector_set_min_size(IN cl_vector_t * const p_vector,
483219820Sjeff		       IN const size_t min_size)
484219820Sjeff{
485219820Sjeff	CL_ASSERT(p_vector);
486219820Sjeff	CL_ASSERT(p_vector->state == CL_INITIALIZED);
487219820Sjeff
488219820Sjeff	if (min_size > p_vector->size) {
489219820Sjeff		/* We have to resize the array */
490219820Sjeff		return (cl_vector_set_size(p_vector, min_size));
491219820Sjeff	}
492219820Sjeff
493219820Sjeff	/* We didn't have to do anything */
494219820Sjeff	return (CL_SUCCESS);
495219820Sjeff}
496219820Sjeff
497219820Sjeffvoid
498219820Sjeffcl_vector_apply_func(IN const cl_vector_t * const p_vector,
499219820Sjeff		     IN cl_pfn_vec_apply_t pfn_callback,
500219820Sjeff		     IN const void *const context)
501219820Sjeff{
502219820Sjeff	size_t i;
503219820Sjeff	void *p_element;
504219820Sjeff
505219820Sjeff	CL_ASSERT(p_vector);
506219820Sjeff	CL_ASSERT(p_vector->state == CL_INITIALIZED);
507219820Sjeff	CL_ASSERT(pfn_callback);
508219820Sjeff
509219820Sjeff	for (i = 0; i < p_vector->size; i++) {
510219820Sjeff		p_element = cl_vector_get_ptr(p_vector, i);
511219820Sjeff		pfn_callback(i, p_element, (void *)context);
512219820Sjeff	}
513219820Sjeff}
514219820Sjeff
515219820Sjeffsize_t
516219820Sjeffcl_vector_find_from_start(IN const cl_vector_t * const p_vector,
517219820Sjeff			  IN cl_pfn_vec_find_t pfn_callback,
518219820Sjeff			  IN const void *const context)
519219820Sjeff{
520219820Sjeff	size_t i;
521219820Sjeff	void *p_element;
522219820Sjeff
523219820Sjeff	CL_ASSERT(p_vector);
524219820Sjeff	CL_ASSERT(p_vector->state == CL_INITIALIZED);
525219820Sjeff	CL_ASSERT(pfn_callback);
526219820Sjeff
527219820Sjeff	for (i = 0; i < p_vector->size; i++) {
528219820Sjeff		p_element = cl_vector_get_ptr(p_vector, i);
529219820Sjeff		/* Invoke the callback */
530219820Sjeff		if (pfn_callback(i, p_element, (void *)context) == CL_SUCCESS)
531219820Sjeff			break;
532219820Sjeff	}
533219820Sjeff	return (i);
534219820Sjeff}
535219820Sjeff
536219820Sjeffsize_t
537219820Sjeffcl_vector_find_from_end(IN const cl_vector_t * const p_vector,
538219820Sjeff			IN cl_pfn_vec_find_t pfn_callback,
539219820Sjeff			IN const void *const context)
540219820Sjeff{
541219820Sjeff	size_t i;
542219820Sjeff	void *p_element;
543219820Sjeff
544219820Sjeff	CL_ASSERT(p_vector);
545219820Sjeff	CL_ASSERT(p_vector->state == CL_INITIALIZED);
546219820Sjeff	CL_ASSERT(pfn_callback);
547219820Sjeff
548219820Sjeff	i = p_vector->size;
549219820Sjeff
550219820Sjeff	while (i) {
551219820Sjeff		/* Get a pointer to the element in the array. */
552219820Sjeff		p_element = cl_vector_get_ptr(p_vector, --i);
553219820Sjeff		CL_ASSERT(p_element);
554219820Sjeff
555219820Sjeff		/* Invoke the callback for the current element. */
556219820Sjeff		if (pfn_callback(i, p_element, (void *)context) == CL_SUCCESS)
557219820Sjeff			return (i);
558219820Sjeff	}
559219820Sjeff
560219820Sjeff	return (p_vector->size);
561219820Sjeff}
562