mirror of https://gerrit.osmocom.org/libosmocore
199 lines
3.8 KiB
C
199 lines
3.8 KiB
C
/*! \file vector.c
|
|
* Generic vector interface routine. */
|
|
/*
|
|
* Copyright (C) 1997 Kunihiro Ishiguro
|
|
*
|
|
* SPDX-License-Identifier: GPL-2.0+
|
|
*
|
|
* This file is part of GNU Zebra.
|
|
*
|
|
* GNU Zebra is free software; you can redistribute it and/or modify it
|
|
* under the terms of the GNU General Public License as published by the
|
|
* Free Software Foundation; either version 2, or (at your option) any
|
|
* later version.
|
|
*
|
|
* GNU Zebra 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
|
|
* General Public License for more details.
|
|
*/
|
|
|
|
#include <stdlib.h>
|
|
#include <unistd.h>
|
|
|
|
#include <osmocom/vty/vector.h>
|
|
#include <osmocom/vty/vty.h>
|
|
#include <osmocom/core/talloc.h>
|
|
#include <string.h>
|
|
|
|
/*! \addtogroup vector
|
|
* @{
|
|
* Generic vector routines, used by VTY internally
|
|
*/
|
|
|
|
void *tall_vty_vec_ctx;
|
|
|
|
/* Initialize vector : allocate memory and return vector. */
|
|
vector vector_init(unsigned int size)
|
|
{
|
|
vector v = talloc_zero(tall_vty_vec_ctx, struct _vector);
|
|
if (!v)
|
|
return NULL;
|
|
|
|
/* allocate at least one slot */
|
|
if (size == 0)
|
|
size = 1;
|
|
|
|
v->alloced = size;
|
|
v->active = 0;
|
|
v->index = _talloc_zero(tall_vty_vec_ctx, sizeof(void *) * size,
|
|
"vector_init:index");
|
|
if (!v->index) {
|
|
talloc_free(v);
|
|
return NULL;
|
|
}
|
|
return v;
|
|
}
|
|
|
|
void vector_only_wrapper_free(vector v)
|
|
{
|
|
talloc_free(v);
|
|
}
|
|
|
|
void vector_only_index_free(void *index)
|
|
{
|
|
talloc_free(index);
|
|
}
|
|
|
|
void vector_free(vector v)
|
|
{
|
|
talloc_free(v->index);
|
|
talloc_free(v);
|
|
}
|
|
|
|
vector vector_copy(vector v)
|
|
{
|
|
unsigned int size;
|
|
vector new = talloc_zero(tall_vty_vec_ctx, struct _vector);
|
|
if (!new)
|
|
return NULL;
|
|
|
|
new->active = v->active;
|
|
new->alloced = v->alloced;
|
|
|
|
size = sizeof(void *) * (v->alloced);
|
|
new->index = _talloc_zero(tall_vty_vec_ctx, size, "vector_copy:index");
|
|
if (!new->index) {
|
|
talloc_free(new);
|
|
return NULL;
|
|
}
|
|
memcpy(new->index, v->index, size);
|
|
|
|
return new;
|
|
}
|
|
|
|
/* Check assigned index, and if it runs short double index pointer */
|
|
void vector_ensure(vector v, unsigned int num)
|
|
{
|
|
if (v->alloced > num)
|
|
return;
|
|
|
|
v->index = talloc_realloc_size(tall_vty_vec_ctx, v->index,
|
|
sizeof(void *) * (v->alloced * 2));
|
|
memset(&v->index[v->alloced], 0, sizeof(void *) * v->alloced);
|
|
v->alloced *= 2;
|
|
|
|
if (v->alloced <= num)
|
|
vector_ensure(v, num);
|
|
}
|
|
|
|
/* This function only returns next empty slot index. It dose not mean
|
|
the slot's index memory is assigned, please call vector_ensure()
|
|
after calling this function. */
|
|
int vector_empty_slot(vector v)
|
|
{
|
|
unsigned int i;
|
|
|
|
if (v->active == 0)
|
|
return 0;
|
|
|
|
for (i = 0; i < v->active; i++)
|
|
if (v->index[i] == 0)
|
|
return i;
|
|
|
|
return i;
|
|
}
|
|
|
|
/* Set value to the smallest empty slot. */
|
|
int vector_set(vector v, void *val)
|
|
{
|
|
unsigned int i;
|
|
|
|
i = vector_empty_slot(v);
|
|
vector_ensure(v, i);
|
|
|
|
v->index[i] = val;
|
|
|
|
if (v->active <= i)
|
|
v->active = i + 1;
|
|
|
|
return i;
|
|
}
|
|
|
|
/* Set value to specified index slot. */
|
|
int vector_set_index(vector v, unsigned int i, void *val)
|
|
{
|
|
vector_ensure(v, i);
|
|
|
|
v->index[i] = val;
|
|
|
|
if (v->active <= i)
|
|
v->active = i + 1;
|
|
|
|
return i;
|
|
}
|
|
|
|
/* Look up vector. */
|
|
void *vector_lookup(vector v, unsigned int i)
|
|
{
|
|
if (i >= v->active)
|
|
return NULL;
|
|
return v->index[i];
|
|
}
|
|
|
|
/* Lookup vector, ensure it. */
|
|
void *vector_lookup_ensure(vector v, unsigned int i)
|
|
{
|
|
vector_ensure(v, i);
|
|
return v->index[i];
|
|
}
|
|
|
|
/* Unset value at specified index slot. */
|
|
void vector_unset(vector v, unsigned int i)
|
|
{
|
|
if (i >= v->alloced)
|
|
return;
|
|
|
|
v->index[i] = NULL;
|
|
|
|
if (i + 1 == v->active) {
|
|
v->active--;
|
|
while (i && v->index[--i] == NULL && v->active--) ; /* Is this ugly ? */
|
|
}
|
|
}
|
|
|
|
/* Count the number of not emplty slot. */
|
|
unsigned int vector_count(vector v)
|
|
{
|
|
unsigned int i;
|
|
unsigned count = 0;
|
|
|
|
for (i = 0; i < v->active; i++)
|
|
if (v->index[i] != NULL)
|
|
count++;
|
|
|
|
return count;
|
|
}
|
|
|
|
/*! @} */
|