1/* 2 * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved. 3 * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved. 4 * Copyright (c) 1996-2003 Intel Corporation. All rights reserved. 5 * 6 * This software is available to you under a choice of one of two 7 * licenses. You may choose to be licensed under the terms of the GNU 8 * General Public License (GPL) Version 2, available from the file 9 * COPYING in the main directory of this source tree, or the 10 * OpenIB.org BSD license below: 11 * 12 * Redistribution and use in source and binary forms, with or 13 * without modification, are permitted provided that the following 14 * conditions are met: 15 * 16 * - Redistributions of source code must retain the above 17 * copyright notice, this list of conditions and the following 18 * disclaimer. 19 * 20 * - Redistributions in binary form must reproduce the above 21 * copyright notice, this list of conditions and the following 22 * disclaimer in the documentation and/or other materials 23 * provided with the distribution. 24 * 25 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 26 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 27 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 28 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 29 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 30 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 31 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 32 * SOFTWARE. 33 * 34 */ 35 36/* 37 * Abstract: 38 * This file contains ivector and isvector implementations. 39 * 40 */ 41 42#if HAVE_CONFIG_H 43# include <config.h> 44#endif /* HAVE_CONFIG_H */ 45 46#include <stdlib.h> 47#include <string.h> 48#include <complib/cl_ptr_vector.h> 49 50void cl_ptr_vector_construct(IN cl_ptr_vector_t * const p_vector) 51{ 52 CL_ASSERT(p_vector); 53 54 memset(p_vector, 0, sizeof(cl_ptr_vector_t)); 55 56 p_vector->state = CL_UNINITIALIZED; 57} 58 59cl_status_t 60cl_ptr_vector_init(IN cl_ptr_vector_t * const p_vector, 61 IN const size_t min_size, IN const size_t grow_size) 62{ 63 cl_status_t status = CL_SUCCESS; 64 65 CL_ASSERT(p_vector); 66 67 cl_ptr_vector_construct(p_vector); 68 69 p_vector->grow_size = grow_size; 70 71 /* 72 * Set the state to initialized so that the call to set_size 73 * doesn't assert. 74 */ 75 p_vector->state = CL_INITIALIZED; 76 77 /* get the storage needed by the user */ 78 if (min_size) { 79 status = cl_ptr_vector_set_size(p_vector, min_size); 80 if (status != CL_SUCCESS) 81 cl_ptr_vector_destroy(p_vector); 82 } 83 84 return (status); 85} 86 87void cl_ptr_vector_destroy(IN cl_ptr_vector_t * const p_vector) 88{ 89 CL_ASSERT(p_vector); 90 CL_ASSERT(cl_is_state_valid(p_vector->state)); 91 92 /* Call the user's destructor for each element in the array. */ 93 if (p_vector->state == CL_INITIALIZED) { 94 /* Destroy the page vector. */ 95 if (p_vector->p_ptr_array) { 96 free((void *)p_vector->p_ptr_array); 97 p_vector->p_ptr_array = NULL; 98 } 99 } 100 101 p_vector->state = CL_UNINITIALIZED; 102} 103 104cl_status_t 105cl_ptr_vector_at(IN const cl_ptr_vector_t * const p_vector, 106 IN const size_t index, OUT void **const p_element) 107{ 108 CL_ASSERT(p_vector); 109 CL_ASSERT(p_vector->state == CL_INITIALIZED); 110 111 /* Range check */ 112 if (index >= p_vector->size) 113 return (CL_INVALID_PARAMETER); 114 115 *p_element = cl_ptr_vector_get(p_vector, index); 116 return (CL_SUCCESS); 117} 118 119cl_status_t 120cl_ptr_vector_set(IN cl_ptr_vector_t * const p_vector, 121 IN const size_t index, IN const void *const element) 122{ 123 cl_status_t status; 124 125 CL_ASSERT(p_vector); 126 CL_ASSERT(p_vector->state == CL_INITIALIZED); 127 128 /* Determine if the vector has room for this element. */ 129 if (index >= p_vector->size) { 130 /* Resize to accomodate the given index. */ 131 status = cl_ptr_vector_set_size(p_vector, index + 1); 132 133 /* Check for failure on or before the given index. */ 134 if ((status != CL_SUCCESS) && (p_vector->size < index)) 135 return (status); 136 } 137 138 /* At this point, the array is guaranteed to be big enough */ 139 p_vector->p_ptr_array[index] = element; 140 141 return (CL_SUCCESS); 142} 143 144void *cl_ptr_vector_remove(IN cl_ptr_vector_t * const p_vector, 145 IN const size_t index) 146{ 147 size_t src; 148 const void *element; 149 150 CL_ASSERT(p_vector); 151 CL_ASSERT(p_vector->state == CL_INITIALIZED); 152 CL_ASSERT(p_vector->size > index); 153 154 /* Store a copy of the element to return. */ 155 element = p_vector->p_ptr_array[index]; 156 /* Shift all items above the removed item down. */ 157 if (index < --p_vector->size) { 158 for (src = index; src < p_vector->size; src++) 159 p_vector->p_ptr_array[src] = 160 p_vector->p_ptr_array[src + 1]; 161 } 162 /* Clear the entry for the element just outside of the new upper bound. */ 163 p_vector->p_ptr_array[p_vector->size] = NULL; 164 165 return ((void *)element); 166} 167 168cl_status_t 169cl_ptr_vector_set_capacity(IN cl_ptr_vector_t * const p_vector, 170 IN const size_t new_capacity) 171{ 172 void *p_new_ptr_array; 173 174 CL_ASSERT(p_vector); 175 CL_ASSERT(p_vector->state == CL_INITIALIZED); 176 177 /* Do we have to do anything here? */ 178 if (new_capacity <= p_vector->capacity) { 179 /* Nope */ 180 return (CL_SUCCESS); 181 } 182 183 /* Allocate our pointer array. */ 184 p_new_ptr_array = malloc(new_capacity * sizeof(void *)); 185 if (!p_new_ptr_array) 186 return (CL_INSUFFICIENT_MEMORY); 187 else 188 memset(p_new_ptr_array, 0, new_capacity * sizeof(void *)); 189 190 if (p_vector->p_ptr_array) { 191 /* Copy the old pointer array into the new. */ 192 memcpy(p_new_ptr_array, p_vector->p_ptr_array, 193 p_vector->capacity * sizeof(void *)); 194 195 /* Free the old pointer array. */ 196 free((void *)p_vector->p_ptr_array); 197 } 198 199 /* Set the new array. */ 200 p_vector->p_ptr_array = p_new_ptr_array; 201 202 /* Update the vector with the new capactity. */ 203 p_vector->capacity = new_capacity; 204 205 return (CL_SUCCESS); 206} 207 208cl_status_t 209cl_ptr_vector_set_size(IN cl_ptr_vector_t * const p_vector, 210 IN const size_t size) 211{ 212 cl_status_t status; 213 size_t new_capacity; 214 215 CL_ASSERT(p_vector); 216 CL_ASSERT(p_vector->state == CL_INITIALIZED); 217 218 /* Check to see if the requested size is the same as the existing size. */ 219 if (size == p_vector->size) 220 return (CL_SUCCESS); 221 222 /* Determine if the vector has room for this element. */ 223 if (size >= p_vector->capacity) { 224 if (!p_vector->grow_size) 225 return (CL_INSUFFICIENT_MEMORY); 226 227 /* Calculate the new capacity, taking into account the grow size. */ 228 new_capacity = size; 229 if (size % p_vector->grow_size) { 230 /* Round up to nearest grow_size boundary. */ 231 new_capacity += p_vector->grow_size - 232 (size % p_vector->grow_size); 233 } 234 235 status = cl_ptr_vector_set_capacity(p_vector, new_capacity); 236 if (status != CL_SUCCESS) 237 return (status); 238 } 239 240 p_vector->size = size; 241 return (CL_SUCCESS); 242} 243 244cl_status_t 245cl_ptr_vector_set_min_size(IN cl_ptr_vector_t * const p_vector, 246 IN const size_t min_size) 247{ 248 CL_ASSERT(p_vector); 249 CL_ASSERT(p_vector->state == CL_INITIALIZED); 250 251 if (min_size > p_vector->size) { 252 /* We have to resize the array */ 253 return (cl_ptr_vector_set_size(p_vector, min_size)); 254 } 255 256 /* We didn't have to do anything */ 257 return (CL_SUCCESS); 258} 259 260void 261cl_ptr_vector_apply_func(IN const cl_ptr_vector_t * const p_vector, 262 IN cl_pfn_ptr_vec_apply_t pfn_callback, 263 IN const void *const context) 264{ 265 size_t i; 266 267 CL_ASSERT(p_vector); 268 CL_ASSERT(p_vector->state == CL_INITIALIZED); 269 CL_ASSERT(pfn_callback); 270 271 for (i = 0; i < p_vector->size; i++) 272 pfn_callback(i, (void *)p_vector->p_ptr_array[i], 273 (void *)context); 274} 275 276size_t 277cl_ptr_vector_find_from_start(IN const cl_ptr_vector_t * const p_vector, 278 IN cl_pfn_ptr_vec_find_t pfn_callback, 279 IN const void *const context) 280{ 281 size_t i; 282 283 CL_ASSERT(p_vector); 284 CL_ASSERT(p_vector->state == CL_INITIALIZED); 285 CL_ASSERT(pfn_callback); 286 287 for (i = 0; i < p_vector->size; i++) { 288 /* Invoke the callback */ 289 if (pfn_callback(i, (void *)p_vector->p_ptr_array[i], 290 (void *)context) == CL_SUCCESS) { 291 break; 292 } 293 } 294 return (i); 295} 296 297size_t 298cl_ptr_vector_find_from_end(IN const cl_ptr_vector_t * const p_vector, 299 IN cl_pfn_ptr_vec_find_t pfn_callback, 300 IN const void *const context) 301{ 302 size_t i; 303 304 CL_ASSERT(p_vector); 305 CL_ASSERT(p_vector->state == CL_INITIALIZED); 306 CL_ASSERT(pfn_callback); 307 308 i = p_vector->size; 309 310 while (i) { 311 /* Invoke the callback for the current element. */ 312 if (pfn_callback(i, (void *)p_vector->p_ptr_array[--i], 313 (void *)context) == CL_SUCCESS) { 314 return (i); 315 } 316 } 317 318 return (p_vector->size); 319} 320