📄 su_vector.c
字号:
/* * This file is part of the Sofia-SIP package * * Copyright (C) 2005 Nokia Corporation. * * Contact: Pekka Pessi <pekka.pessi@nokia.com> * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License * as published by the Free Software Foundation; either version 2.1 of * the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA * *//**@defgroup su_vector Vectors * * Pointer vectors. * * Unidimensional arrays using #su_home_t. * *//**@ingroup su_vector * @CFILE su_vector.c * @brief Simple pointer vectors * * The vectors are resizeable unidimensional arrays. * * @author Pekka Pessi <Pekka.Pessi@nokia.com> * * @date Created: Fri Sep 27 14:43:29 2002 ppessi */#include "config.h"#include <stdlib.h>#include <stddef.h>#include <memory.h>#include <limits.h>#include <string.h>#include <assert.h>#include "sofia-sip/su_config.h"#include "sofia-sip/su_vector.h"enum { N = 8 };struct su_vector_s{ su_home_t v_home[1]; su_home_t *v_parent; unsigned v_size; unsigned v_len; su_free_func_t v_free_func; void **v_list;};/** Create a vector. * * The function su_vector_create() creates a pointer vector object. The * vector is initially empty. The function clones a memory home for the * vector object from @a home. If a @a free_func is provided then that * will be used to free the individual nodes (NULL if not used). */su_vector_t *su_vector_create(su_home_t *home, su_free_func_t free_func){ su_vector_t *vector; vector = su_home_clone(home, sizeof(*vector) + N * sizeof(*vector->v_list)); if (vector) { vector->v_parent = home; vector->v_size = N; vector->v_free_func = free_func; vector->v_list = (void **)(vector + 1); } return vector;}/** Destroy a vector. * * The function su_vector_destroy() destroys a vector and frees all * its nodes if a freeing function is available */void su_vector_destroy(su_vector_t *vector){ int i; if (vector) { if (vector->v_free_func != NULL) { for (i = 0; i < vector->v_len; i++) { (vector->v_free_func)(vector->v_list[i]); } } su_home_zap(vector->v_home); }}/** Increase the list size for next item, if necessary. */static int su_vector_make_place(su_vector_t *vector, unsigned index){ if (vector->v_size <= vector->v_len + 1) { unsigned n = 2 * vector->v_size; void **list; if (n < vector->v_size || n * sizeof(vector->v_list[0]) < n) return -1; if (vector->v_list != (void **)(vector + 1) && index == vector->v_len) { if (!(list = su_realloc(vector->v_home, vector->v_list, n * sizeof(vector->v_list[0])))) return 0; } else { if (!(list = su_alloc(vector->v_home, n * sizeof(vector->v_list[0])))) return 0; memcpy(list, vector->v_list, index * sizeof(vector->v_list[0])); memcpy(list + index + 1, vector->v_list + index, (vector->v_len - index) * sizeof(vector->v_list[0])); if (vector->v_list != (void **)(vector + 1)) { su_free(vector->v_home, vector->v_list); } } vector->v_list = list; vector->v_size = n; } else { memmove(vector->v_list + index + 1, vector->v_list + index, (vector->v_len - index) * sizeof(vector->v_list[0])); } vector->v_len++; return 1;}/**Insert an item to vector. * * The function su_vector_insert() inserts an @a item to the @a vector. * The items after the @a index will be moved further within the vector. * * @param vector pointer to a vector object * @param item item to be appended * @param index index for the new item * @return * Pointer to string, if successful, or NULL upon an error. */int su_vector_insert(su_vector_t *vector, unsigned index, void *item){ if (vector && index <= vector->v_len && su_vector_make_place(vector, index)) { vector->v_list[index] = item; return 0; } return -1;}/**Remove an item from vector. * * The function su_vector_remove() removes an item from the @a vector. * The items after the @a index will be moved backwards within the vector. * * @param vector pointer to a vector object * @param index index for the removed item * @return * Pointer to string, if successful, or NULL upon an error. */int su_vector_remove(su_vector_t *vector, unsigned index){ if (vector && index < vector->v_len) { if (vector->v_free_func) (vector->v_free_func)(vector->v_list[index]); memmove(vector->v_list + index, vector->v_list + index + 1, (vector->v_len - index - 1) * sizeof(vector->v_list[0])); vector->v_len--; return 0; } return -1;}/**Remove all items from vector. * * The function su_vector_empty() removes all items from the @a vector. * * @param vector pointer to a vector object */int su_vector_empty(su_vector_t *vector){ int i; if (vector) { if (vector->v_free_func != NULL) { for (i = 0; i < vector->v_len; i++) { (vector->v_free_func)(vector->v_list[i]); } } vector->v_len = 0; return 0; } return -1;}/**Append an item to vector. * * The function su_vector_append() appends an @a item to the @a vector. * * @param vector pointer to a vector object * @param item item to be appended * * @retval 0 if successful * @retval -1 upon an error */int su_vector_append(su_vector_t *vector, void *item){ unsigned index = vector->v_len; if (vector && su_vector_make_place(vector, index)) { vector->v_list[index] = item; return 0; } return -1;}/**Get a numbered item from list. * * The function su_vector_item() returns a numbered item from vector. The * numbering starts from 0. * * @param vector pointer to a vector object * @param i index * * @return * Pointer, if item exists, or NULL upon an error. */void *su_vector_item(su_vector_t const *vector, unsigned i){ if (vector && i < vector->v_len) return vector->v_list[i]; else return NULL;}/** Get number of items in list. * * The function su_vector_len() returns the number of items in the * vector. */unsigned su_vector_len(su_vector_t const *l){ return l ? l->v_len : 0;}int su_vector_is_empty(su_vector_t const *vector){ return su_vector_len(vector) == 0;}/**Get a pointer array from list. * * The function su_vector_get_array() returns an array of pointer. The * length of the array is always one longer than the length of the vector, * and the last item in the returned array is always NULL. * * @param vector pointer to a vector object * * @return * Pointer to array, or NULL if error occurred. */void **su_vector_get_array(su_vector_t *vector){ if (vector) { void **retval = su_alloc(vector->v_home, sizeof(retval[0]) * (vector->v_len + 1)); if (retval) { retval[vector->v_len] = NULL; return memcpy(retval, vector->v_list, sizeof(retval[0]) * vector->v_len); } } return NULL;}/**Free a string array. * * The function su_vector_free_array() discards a string array allocated * with su_vector_get_array(). * * @param vector pointer to a vector object * @param array string array to be freed * */void su_vector_free_array(su_vector_t *vector, void **array){ su_free(vector->v_home, array);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -