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