1108428Sache/* 2108428Sache * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved. 3108428Sache * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved. 4108428Sache * Copyright (c) 1996-2003 Intel Corporation. All rights reserved. 5108428Sache * 6174990Sache * This software is available to you under a choice of one of two 7108428Sache * licenses. You may choose to be licensed under the terms of the GNU 8108428Sache * General Public License (GPL) Version 2, available from the file 9108428Sache * COPYING in the main directory of this source tree, or the 10108428Sache * OpenIB.org BSD license below: 11108428Sache * 12108428Sache * Redistribution and use in source and binary forms, with or 13108428Sache * without modification, are permitted provided that the following 14108428Sache * conditions are met: 15108428Sache * 16108428Sache * - Redistributions of source code must retain the above 17108428Sache * copyright notice, this list of conditions and the following 18108428Sache * disclaimer. 19108428Sache * 20108428Sache * - Redistributions in binary form must reproduce the above 21174990Sache * copyright notice, this list of conditions and the following 22108428Sache * disclaimer in the documentation and/or other materials 23108428Sache * provided with the distribution. 24108428Sache * 25108428Sache * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 26108428Sache * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 27108428Sache * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 28108428Sache * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 29108428Sache * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 30108428Sache * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 31108428Sache * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 32108428Sache * SOFTWARE. 33108428Sache * 34108428Sache */ 35108428Sache 36174990Sache/* 37108428Sache * Abstract: 38108428Sache * This file contains ivector and isvector implementations. 39108428Sache * 40108428Sache */ 41108428Sache 42108428Sache#if HAVE_CONFIG_H 43108428Sache# include <config.h> 44108428Sache#endif /* HAVE_CONFIG_H */ 45108428Sache 46174990Sache#include <stdlib.h> 47108428Sache#include <string.h> 48108428Sache#include <complib/cl_ptr_vector.h> 49108428Sache 50108428Sachevoid cl_ptr_vector_construct(IN cl_ptr_vector_t * const p_vector) 51108428Sache{ 52108428Sache CL_ASSERT(p_vector); 53108428Sache 54108428Sache memset(p_vector, 0, sizeof(cl_ptr_vector_t)); 55108428Sache 56108428Sache p_vector->state = CL_UNINITIALIZED; 57108428Sache} 58108428Sache 59108428Sachecl_status_t cl_ptr_vector_init(IN cl_ptr_vector_t * const p_vector, 60108428Sache IN const size_t min_size, 61108428Sache IN const size_t grow_size) 62108428Sache{ 63108428Sache cl_status_t status = CL_SUCCESS; 64108428Sache 65108428Sache CL_ASSERT(p_vector); 66108428Sache 67108428Sache cl_ptr_vector_construct(p_vector); 68108428Sache 69108428Sache p_vector->grow_size = grow_size; 70108428Sache 71108428Sache /* 72108428Sache * Set the state to initialized so that the call to set_size 73108428Sache * doesn't assert. 74108428Sache */ 75108428Sache p_vector->state = CL_INITIALIZED; 76108428Sache 77108428Sache /* get the storage needed by the user */ 78108428Sache if (min_size) { 79108428Sache status = cl_ptr_vector_set_size(p_vector, min_size); 80174990Sache if (status != CL_SUCCESS) 81108428Sache cl_ptr_vector_destroy(p_vector); 82108428Sache } 83108428Sache 84108428Sache return (status); 85108428Sache} 86108428Sache 87108428Sachevoid cl_ptr_vector_destroy(IN cl_ptr_vector_t * const p_vector) 88108428Sache{ 89108428Sache CL_ASSERT(p_vector); 90108428Sache CL_ASSERT(cl_is_state_valid(p_vector->state)); 91108428Sache 92108428Sache /* Call the user's destructor for each element in the array. */ 93108428Sache if (p_vector->state == CL_INITIALIZED) { 94108428Sache /* Destroy the page vector. */ 95108428Sache if (p_vector->p_ptr_array) { 96108428Sache free((void *)p_vector->p_ptr_array); 97108428Sache p_vector->p_ptr_array = NULL; 98108428Sache } 99108428Sache } 100108428Sache 101108428Sache p_vector->state = CL_UNINITIALIZED; 102108428Sache} 103 104cl_status_t cl_ptr_vector_at(IN const cl_ptr_vector_t * const p_vector, 105 IN const size_t index, OUT void **const p_element) 106{ 107 CL_ASSERT(p_vector); 108 CL_ASSERT(p_vector->state == CL_INITIALIZED); 109 110 /* Range check */ 111 if (index >= p_vector->size) 112 return (CL_INVALID_PARAMETER); 113 114 *p_element = cl_ptr_vector_get(p_vector, index); 115 return (CL_SUCCESS); 116} 117 118cl_status_t cl_ptr_vector_set(IN cl_ptr_vector_t * const p_vector, 119 IN const size_t index, 120 IN const void *const element) 121{ 122 cl_status_t status; 123 124 CL_ASSERT(p_vector); 125 CL_ASSERT(p_vector->state == CL_INITIALIZED); 126 127 /* Determine if the vector has room for this element. */ 128 if (index >= p_vector->size) { 129 /* Resize to accomodate the given index. */ 130 status = cl_ptr_vector_set_size(p_vector, index + 1); 131 132 /* Check for failure on or before the given index. */ 133 if ((status != CL_SUCCESS) && (p_vector->size < index)) 134 return (status); 135 } 136 137 /* At this point, the array is guaranteed to be big enough */ 138 p_vector->p_ptr_array[index] = element; 139 140 return (CL_SUCCESS); 141} 142 143void *cl_ptr_vector_remove(IN cl_ptr_vector_t * const p_vector, 144 IN const size_t index) 145{ 146 size_t src; 147 const void *element; 148 149 CL_ASSERT(p_vector); 150 CL_ASSERT(p_vector->state == CL_INITIALIZED); 151 CL_ASSERT(p_vector->size > index); 152 153 /* Store a copy of the element to return. */ 154 element = p_vector->p_ptr_array[index]; 155 /* Shift all items above the removed item down. */ 156 if (index < --p_vector->size) { 157 for (src = index; src < p_vector->size; src++) 158 p_vector->p_ptr_array[src] = 159 p_vector->p_ptr_array[src + 1]; 160 } 161 /* Clear the entry for the element just outside of the new upper bound. */ 162 p_vector->p_ptr_array[p_vector->size] = NULL; 163 164 return ((void *)element); 165} 166 167cl_status_t cl_ptr_vector_set_capacity(IN cl_ptr_vector_t * const p_vector, 168 IN const size_t new_capacity) 169{ 170 void *p_new_ptr_array; 171 172 CL_ASSERT(p_vector); 173 CL_ASSERT(p_vector->state == CL_INITIALIZED); 174 175 /* Do we have to do anything here? */ 176 if (new_capacity <= p_vector->capacity) { 177 /* Nope */ 178 return (CL_SUCCESS); 179 } 180 181 /* Allocate our pointer array. */ 182 p_new_ptr_array = malloc(new_capacity * sizeof(void *)); 183 if (!p_new_ptr_array) 184 return (CL_INSUFFICIENT_MEMORY); 185 else 186 memset(p_new_ptr_array, 0, new_capacity * sizeof(void *)); 187 188 if (p_vector->p_ptr_array) { 189 /* Copy the old pointer array into the new. */ 190 memcpy(p_new_ptr_array, p_vector->p_ptr_array, 191 p_vector->capacity * sizeof(void *)); 192 193 /* Free the old pointer array. */ 194 free((void *)p_vector->p_ptr_array); 195 } 196 197 /* Set the new array. */ 198 p_vector->p_ptr_array = p_new_ptr_array; 199 200 /* Update the vector with the new capactity. */ 201 p_vector->capacity = new_capacity; 202 203 return (CL_SUCCESS); 204} 205 206cl_status_t cl_ptr_vector_set_size(IN cl_ptr_vector_t * const p_vector, 207 IN const size_t size) 208{ 209 cl_status_t status; 210 size_t new_capacity; 211 212 CL_ASSERT(p_vector); 213 CL_ASSERT(p_vector->state == CL_INITIALIZED); 214 215 /* Check to see if the requested size is the same as the existing size. */ 216 if (size == p_vector->size) 217 return (CL_SUCCESS); 218 219 /* Determine if the vector has room for this element. */ 220 if (size >= p_vector->capacity) { 221 if (!p_vector->grow_size) 222 return (CL_INSUFFICIENT_MEMORY); 223 224 /* Calculate the new capacity, taking into account the grow size. */ 225 new_capacity = size; 226 if (size % p_vector->grow_size) { 227 /* Round up to nearest grow_size boundary. */ 228 new_capacity += p_vector->grow_size - 229 (size % p_vector->grow_size); 230 } 231 232 status = cl_ptr_vector_set_capacity(p_vector, new_capacity); 233 if (status != CL_SUCCESS) 234 return (status); 235 } 236 237 p_vector->size = size; 238 return (CL_SUCCESS); 239} 240 241cl_status_t cl_ptr_vector_set_min_size(IN cl_ptr_vector_t * const p_vector, 242 IN const size_t min_size) 243{ 244 CL_ASSERT(p_vector); 245 CL_ASSERT(p_vector->state == CL_INITIALIZED); 246 247 if (min_size > p_vector->size) { 248 /* We have to resize the array */ 249 return (cl_ptr_vector_set_size(p_vector, min_size)); 250 } 251 252 /* We didn't have to do anything */ 253 return (CL_SUCCESS); 254} 255 256void cl_ptr_vector_apply_func(IN const cl_ptr_vector_t * const p_vector, 257 IN cl_pfn_ptr_vec_apply_t pfn_callback, 258 IN const void *const context) 259{ 260 size_t i; 261 262 CL_ASSERT(p_vector); 263 CL_ASSERT(p_vector->state == CL_INITIALIZED); 264 CL_ASSERT(pfn_callback); 265 266 for (i = 0; i < p_vector->size; i++) 267 pfn_callback(i, (void *)p_vector->p_ptr_array[i], 268 (void *)context); 269} 270 271size_t cl_ptr_vector_find_from_start(IN const cl_ptr_vector_t * const p_vector, 272 IN cl_pfn_ptr_vec_find_t pfn_callback, 273 IN const void *const context) 274{ 275 size_t i; 276 277 CL_ASSERT(p_vector); 278 CL_ASSERT(p_vector->state == CL_INITIALIZED); 279 CL_ASSERT(pfn_callback); 280 281 for (i = 0; i < p_vector->size; i++) { 282 /* Invoke the callback */ 283 if (pfn_callback(i, (void *)p_vector->p_ptr_array[i], 284 (void *)context) == CL_SUCCESS) { 285 break; 286 } 287 } 288 return (i); 289} 290 291size_t cl_ptr_vector_find_from_end(IN const cl_ptr_vector_t * const p_vector, 292 IN cl_pfn_ptr_vec_find_t pfn_callback, 293 IN const void *const context) 294{ 295 size_t i; 296 297 CL_ASSERT(p_vector); 298 CL_ASSERT(p_vector->state == CL_INITIALIZED); 299 CL_ASSERT(pfn_callback); 300 301 i = p_vector->size; 302 303 while (i) { 304 /* Invoke the callback for the current element. */ 305 i--; 306 if (pfn_callback(i, (void *)p_vector->p_ptr_array[i], 307 (void *)context) == CL_SUCCESS) { 308 return (i); 309 } 310 } 311 312 return (p_vector->size); 313} 314