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