|
Packit |
0021fb |
/*
|
|
Packit |
0021fb |
* This file is part of ltrace.
|
|
Packit |
0021fb |
* Copyright (C) 2011,2012,2013 Petr Machata, Red Hat Inc.
|
|
Packit |
0021fb |
*
|
|
Packit |
0021fb |
* This program is free software; you can redistribute it and/or
|
|
Packit |
0021fb |
* modify it under the terms of the GNU General Public License as
|
|
Packit |
0021fb |
* published by the Free Software Foundation; either version 2 of the
|
|
Packit |
0021fb |
* License, or (at your option) any later version.
|
|
Packit |
0021fb |
*
|
|
Packit |
0021fb |
* This program is distributed in the hope that it will be useful, but
|
|
Packit |
0021fb |
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
Packit |
0021fb |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
Packit |
0021fb |
* General Public License for more details.
|
|
Packit |
0021fb |
*
|
|
Packit |
0021fb |
* You should have received a copy of the GNU General Public License
|
|
Packit |
0021fb |
* along with this program; if not, write to the Free Software
|
|
Packit |
0021fb |
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
|
|
Packit |
0021fb |
* 02110-1301 USA
|
|
Packit |
0021fb |
*/
|
|
Packit |
0021fb |
|
|
Packit |
0021fb |
#include <stdlib.h>
|
|
Packit |
0021fb |
#include <assert.h>
|
|
Packit |
0021fb |
#include <string.h>
|
|
Packit |
0021fb |
#include "vect.h"
|
|
Packit |
0021fb |
|
|
Packit |
0021fb |
static void *
|
|
Packit |
0021fb |
slot(struct vect *vec, size_t i)
|
|
Packit |
0021fb |
{
|
|
Packit |
0021fb |
return ((unsigned char *)vec->data) + vec->elt_size * i;
|
|
Packit |
0021fb |
}
|
|
Packit |
0021fb |
|
|
Packit |
0021fb |
static const void *
|
|
Packit |
0021fb |
cslot(const struct vect *vec, size_t i)
|
|
Packit |
0021fb |
{
|
|
Packit |
0021fb |
return ((const unsigned char *)vec->data) + vec->elt_size * i;
|
|
Packit |
0021fb |
}
|
|
Packit |
0021fb |
|
|
Packit |
0021fb |
void
|
|
Packit |
0021fb |
vect_init(struct vect *vec, size_t elt_size)
|
|
Packit |
0021fb |
{
|
|
Packit |
0021fb |
*vec = (struct vect){ NULL, 0, 0, elt_size };
|
|
Packit |
0021fb |
}
|
|
Packit |
0021fb |
|
|
Packit |
0021fb |
static int
|
|
Packit |
0021fb |
copy_elt(void *tgt, const void *src, void *data)
|
|
Packit |
0021fb |
{
|
|
Packit |
0021fb |
struct vect *target = data;
|
|
Packit |
0021fb |
memcpy(tgt, src, target->elt_size);
|
|
Packit |
0021fb |
return 0;
|
|
Packit |
0021fb |
}
|
|
Packit |
0021fb |
|
|
Packit |
0021fb |
int
|
|
Packit |
0021fb |
vect_clone(struct vect *target, const struct vect *source,
|
|
Packit |
0021fb |
int (*clone)(void *tgt, const void *src, void *data),
|
|
Packit |
0021fb |
void (*dtor)(void *elt, void *data),
|
|
Packit |
0021fb |
void *data)
|
|
Packit |
0021fb |
{
|
|
Packit |
0021fb |
vect_init(target, source->elt_size);
|
|
Packit |
0021fb |
if (vect_reserve(target, source->size) < 0)
|
|
Packit |
0021fb |
return -1;
|
|
Packit |
0021fb |
|
|
Packit |
0021fb |
if (clone == NULL) {
|
|
Packit |
0021fb |
assert(dtor == NULL);
|
|
Packit |
0021fb |
clone = copy_elt;
|
|
Packit |
0021fb |
data = target;
|
|
Packit |
0021fb |
} else {
|
|
Packit |
0021fb |
assert(dtor != NULL);
|
|
Packit |
0021fb |
}
|
|
Packit |
0021fb |
|
|
Packit |
0021fb |
size_t i;
|
|
Packit |
0021fb |
for (i = 0; i < source->size; ++i)
|
|
Packit |
0021fb |
if (clone(slot(target, i), cslot(source, i), data) < 0)
|
|
Packit |
0021fb |
goto fail;
|
|
Packit |
0021fb |
|
|
Packit |
0021fb |
target->size = source->size;
|
|
Packit |
0021fb |
return 0;
|
|
Packit |
0021fb |
|
|
Packit |
0021fb |
fail:
|
|
Packit |
0021fb |
/* N.B. destroy the elements in opposite order. */
|
|
Packit |
0021fb |
if (dtor != NULL)
|
|
Packit |
0021fb |
while (i-- != 0)
|
|
Packit |
0021fb |
dtor(slot(target, i), data);
|
|
Packit |
0021fb |
vect_destroy(target, NULL, NULL);
|
|
Packit |
0021fb |
return -1;
|
|
Packit |
0021fb |
}
|
|
Packit |
0021fb |
|
|
Packit |
0021fb |
int
|
|
Packit |
0021fb |
vect_reserve(struct vect *vec, size_t count)
|
|
Packit |
0021fb |
{
|
|
Packit |
0021fb |
if (count > vec->allocated) {
|
|
Packit |
0021fb |
size_t na = vec->allocated != 0 ? 2 * vec->allocated : 4;
|
|
Packit |
0021fb |
while (na < count)
|
|
Packit |
0021fb |
na *= 2;
|
|
Packit |
0021fb |
void *n = realloc(vec->data, na * vec->elt_size);
|
|
Packit |
0021fb |
if (n == NULL)
|
|
Packit |
0021fb |
return -1;
|
|
Packit |
0021fb |
vec->data = n;
|
|
Packit |
0021fb |
vec->allocated = na;
|
|
Packit |
0021fb |
}
|
|
Packit |
0021fb |
assert(count <= vec->allocated);
|
|
Packit |
0021fb |
return 0;
|
|
Packit |
0021fb |
}
|
|
Packit |
0021fb |
|
|
Packit |
0021fb |
size_t
|
|
Packit |
0021fb |
vect_size(const struct vect *vec)
|
|
Packit |
0021fb |
{
|
|
Packit |
0021fb |
return vec->size;
|
|
Packit |
0021fb |
}
|
|
Packit |
0021fb |
|
|
Packit |
0021fb |
int
|
|
Packit |
0021fb |
vect_empty(const struct vect *vec)
|
|
Packit |
0021fb |
{
|
|
Packit |
0021fb |
return vec->size == 0;
|
|
Packit |
0021fb |
}
|
|
Packit |
0021fb |
|
|
Packit |
0021fb |
int
|
|
Packit |
0021fb |
vect_reserve_additional(struct vect *vec, size_t count)
|
|
Packit |
0021fb |
{
|
|
Packit |
0021fb |
return vect_reserve(vec, vect_size(vec) + count);
|
|
Packit |
0021fb |
}
|
|
Packit |
0021fb |
|
|
Packit |
0021fb |
int
|
|
Packit |
0021fb |
vect_pushback(struct vect *vec, void *eltp)
|
|
Packit |
0021fb |
{
|
|
Packit |
0021fb |
if (vect_reserve_additional(vec, 1) < 0)
|
|
Packit |
0021fb |
return -1;
|
|
Packit |
0021fb |
memcpy(slot(vec, vec->size++), eltp, vec->elt_size);
|
|
Packit |
0021fb |
return 0;
|
|
Packit |
0021fb |
}
|
|
Packit |
0021fb |
|
|
Packit |
0021fb |
void
|
|
Packit |
0021fb |
vect_erase(struct vect *vec, size_t start, size_t end,
|
|
Packit |
0021fb |
void (*dtor)(void *emt, void *data), void *data)
|
|
Packit |
0021fb |
{
|
|
Packit |
0021fb |
assert(start < vect_size(vec) || start == 0);
|
|
Packit |
0021fb |
assert(end <= vect_size(vec));
|
|
Packit |
0021fb |
|
|
Packit |
0021fb |
/* First, destroy the elements that are to be erased. */
|
|
Packit |
0021fb |
if (dtor != NULL) {
|
|
Packit |
0021fb |
size_t i;
|
|
Packit |
0021fb |
for (i = start; i < end; ++i)
|
|
Packit |
0021fb |
dtor(slot(vec, i), data);
|
|
Packit |
0021fb |
}
|
|
Packit |
0021fb |
|
|
Packit |
0021fb |
/* Now move the tail forward and adjust size. */
|
|
Packit |
0021fb |
memmove(slot(vec, start), slot(vec, end),
|
|
Packit |
0021fb |
slot(vec, vec->size) - slot(vec, end));
|
|
Packit |
0021fb |
vec->size -= end - start;
|
|
Packit |
0021fb |
}
|
|
Packit |
0021fb |
|
|
Packit |
0021fb |
void
|
|
Packit |
0021fb |
vect_popback(struct vect *vec,
|
|
Packit |
0021fb |
void (*dtor)(void *emt, void *data), void *data)
|
|
Packit |
0021fb |
{
|
|
Packit |
0021fb |
assert(vect_size(vec) > 0);
|
|
Packit |
0021fb |
vect_erase(vec, vect_size(vec)-1, vect_size(vec), dtor, data);
|
|
Packit |
0021fb |
}
|
|
Packit |
0021fb |
|
|
Packit |
0021fb |
void
|
|
Packit |
0021fb |
vect_destroy(struct vect *vec, void (*dtor)(void *emt, void *data), void *data)
|
|
Packit |
0021fb |
{
|
|
Packit |
0021fb |
if (vec == NULL)
|
|
Packit |
0021fb |
return;
|
|
Packit |
0021fb |
|
|
Packit |
0021fb |
vect_erase(vec, 0, vect_size(vec), dtor, data);
|
|
Packit |
0021fb |
assert(vect_size(vec) == 0);
|
|
Packit |
0021fb |
free(vec->data);
|
|
Packit |
0021fb |
}
|
|
Packit |
0021fb |
|
|
Packit |
0021fb |
void *
|
|
Packit |
0021fb |
vect_each(struct vect *vec, void *start_after,
|
|
Packit |
0021fb |
enum callback_status (*cb)(void *, void *), void *data)
|
|
Packit |
0021fb |
{
|
|
Packit |
0021fb |
size_t i = start_after == NULL ? 0
|
|
Packit |
0021fb |
: ((start_after - vec->data) / vec->elt_size) + 1;
|
|
Packit |
0021fb |
|
|
Packit |
0021fb |
for (; i < vec->size; ++i) {
|
|
Packit |
0021fb |
void *slt = slot(vec, i);
|
|
Packit |
0021fb |
switch ((*cb)(slt, data)) {
|
|
Packit |
0021fb |
case CBS_FAIL:
|
|
Packit |
0021fb |
/* XXX handle me */
|
|
Packit |
0021fb |
case CBS_STOP:
|
|
Packit |
0021fb |
return slt;
|
|
Packit |
0021fb |
case CBS_CONT:
|
|
Packit |
0021fb |
break;
|
|
Packit |
0021fb |
}
|
|
Packit |
0021fb |
}
|
|
Packit |
0021fb |
|
|
Packit |
0021fb |
return NULL;
|
|
Packit |
0021fb |
}
|
|
Packit |
0021fb |
|
|
Packit |
0021fb |
void
|
|
Packit |
0021fb |
vect_qsort(struct vect *vec, int (*compar)(const void *, const void *))
|
|
Packit |
0021fb |
{
|
|
Packit |
0021fb |
qsort(vec->data, vec->size, vec->elt_size, compar);
|
|
Packit |
0021fb |
}
|
|
Packit |
0021fb |
|
|
Packit |
0021fb |
const void *
|
|
Packit |
0021fb |
vect_each_cst(const struct vect *vec, const void *start_after,
|
|
Packit |
0021fb |
enum callback_status (*cb)(const void *, void *), void *data)
|
|
Packit |
0021fb |
{
|
|
Packit |
0021fb |
return vect_each((struct vect *)vec, (void *)start_after,
|
|
Packit |
0021fb |
(void *)cb, data);
|
|
Packit |
0021fb |
}
|
|
Packit |
0021fb |
|
|
Packit |
0021fb |
void
|
|
Packit |
0021fb |
vect_dtor_string(char **key, void *data)
|
|
Packit |
0021fb |
{
|
|
Packit |
0021fb |
free(*key);
|
|
Packit |
0021fb |
}
|