328 lines
7.8 KiB
C
328 lines
7.8 KiB
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;
|
|
size_t v_size;
|
|
size_t 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)
|
|
{
|
|
size_t 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, usize_t index)
|
|
{
|
|
if (vector->v_size <= vector->v_len + 1) {
|
|
size_t newsize = 2 * vector->v_size * sizeof(vector->v_list[0]);
|
|
void **list;
|
|
|
|
if (newsize < vector->v_size * sizeof(vector->v_list[0])) /* overflow */
|
|
return -1;
|
|
|
|
if (vector->v_list != (void **)(vector + 1) && index == vector->v_len) {
|
|
if (!(list = su_realloc(vector->v_home, vector->v_list, newsize)))
|
|
return 0;
|
|
}
|
|
else {
|
|
if (!(list = su_alloc(vector->v_home, newsize)))
|
|
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 *= 2;
|
|
}
|
|
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
|
|
*
|
|
* @retval 0 when successful
|
|
* @retval -1 upon an error
|
|
*/
|
|
int su_vector_insert(su_vector_t *vector, usize_t index, void *item)
|
|
{
|
|
if (vector &&
|
|
index <= vector->v_len &&
|
|
su_vector_make_place(vector, index) > 0) {
|
|
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
|
|
*
|
|
* @retval 0 when successful
|
|
* @retval -1 upon an error
|
|
*/
|
|
int su_vector_remove(su_vector_t *vector, usize_t 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
|
|
*
|
|
* @retval 0 if successful
|
|
* @retval -1 upon an error
|
|
*/
|
|
int su_vector_empty(su_vector_t *vector)
|
|
{
|
|
size_t 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)
|
|
{
|
|
size_t index;
|
|
|
|
if (vector == 0)
|
|
return -1;
|
|
|
|
index = vector->v_len;
|
|
|
|
if (su_vector_make_place(vector, index) <= 0)
|
|
return -1;
|
|
|
|
vector->v_list[index] = item;
|
|
return 0;
|
|
}
|
|
|
|
/**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, usize_t 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.
|
|
*/
|
|
usize_t 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;
|
|
size_t newsize = sizeof(retval[0]) * (vector->v_len + 1);
|
|
|
|
retval = su_alloc(vector->v_home, newsize);
|
|
|
|
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);
|
|
}
|