vect.c revision a0a6a54a41d828c9a018829033443b0faabefb2f
1/*
2 * This file is part of ltrace.
3 * Copyright (C) 2011,2012 Petr Machata, Red Hat Inc.
4 *
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License as
7 * published by the Free Software Foundation; either version 2 of the
8 * License, or (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13 * General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
18 * 02110-1301 USA
19 */
20
21#include <stdlib.h>
22#include <assert.h>
23#include <string.h>
24#include "vect.h"
25
26static void *
27slot(struct vect *vec, size_t i)
28{
29	return ((char *)vec->data) + vec->elt_size * i;
30}
31
32void
33vect_init(struct vect *vec, size_t elt_size)
34{
35	*vec = (struct vect){ NULL, 0, 0, elt_size };
36}
37
38static int
39copy_elt(void *tgt, void *src, void *data)
40{
41	struct vect *target = data;
42	memcpy(tgt, src, target->elt_size);
43	return 0;
44}
45
46int
47vect_clone(struct vect *target, struct vect *source,
48	   int (*clone)(void *tgt, void *src, void *data),
49	   void (*dtor)(void *elt, void *data),
50	   void *data)
51{
52	vect_init(target, source->elt_size);
53	if (vect_reserve(target, source->size) < 0)
54		return -1;
55
56	if (clone == NULL) {
57		assert(dtor == NULL);
58		clone = copy_elt;
59		data = target;
60	} else {
61		assert(dtor != NULL);
62	}
63
64	size_t i;
65	for (i = 0; i < source->size; ++i)
66		if (clone(slot(target, i), slot(source, i), data) < 0)
67			goto fail;
68
69	target->size = source->size;
70	return 0;
71
72fail:
73	/* N.B. destroy the elements in opposite order.  */
74	if (dtor != NULL)
75		while (i-- != 0)
76			dtor(slot(target, i), data);
77	vect_destroy(target, NULL, NULL);
78	return -1;
79}
80
81int
82vect_reserve(struct vect *vec, size_t count)
83{
84	if (count > vec->allocated) {
85		size_t na = vec->allocated != 0 ? 2 * vec->allocated : 4;
86		void *n = realloc(vec->data, na * vec->elt_size);
87		if (n == NULL)
88			return -1;
89		vec->data = n;
90		vec->allocated = na;
91	}
92	assert(count <= vec->allocated);
93	return 0;
94}
95
96size_t
97vect_size(struct vect *vec)
98{
99	return vec->size;
100}
101
102int
103vect_empty(struct vect *vec)
104{
105	return vec->size == 0;
106}
107
108int
109vect_reserve_additional(struct vect *vec, size_t count)
110{
111	return vect_reserve(vec, vect_size(vec) + count);
112}
113
114int
115vect_pushback(struct vect *vec, void *eltp)
116{
117	if (vect_reserve_additional(vec, 1) < 0)
118		return -1;
119	memcpy(slot(vec, vec->size++), eltp, vec->elt_size);
120	return 0;
121}
122
123void
124vect_destroy(struct vect *vec, void (*dtor)(void *emt, void *data), void *data)
125{
126	if (vec == NULL)
127		return;
128
129	if (dtor != NULL) {
130		size_t i;
131		size_t sz = vect_size(vec);
132		for (i = 0; i < sz; ++i)
133			dtor(slot(vec, i), data);
134	}
135	free(vec->data);
136}
137