vect.c revision c28410e3f4bb4d40e48d58440800fbb080b2e3d6
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 ((unsigned char *)vec->data) + vec->elt_size * i; 30} 31 32static const void * 33cslot(const struct vect *vec, size_t i) 34{ 35 return ((const unsigned char *)vec->data) + vec->elt_size * i; 36} 37 38void 39vect_init(struct vect *vec, size_t elt_size) 40{ 41 *vec = (struct vect){ NULL, 0, 0, elt_size }; 42} 43 44static int 45copy_elt(void *tgt, const void *src, void *data) 46{ 47 struct vect *target = data; 48 memcpy(tgt, src, target->elt_size); 49 return 0; 50} 51 52int 53vect_clone(struct vect *target, const struct vect *source, 54 int (*clone)(void *tgt, const void *src, void *data), 55 void (*dtor)(void *elt, void *data), 56 void *data) 57{ 58 vect_init(target, source->elt_size); 59 if (vect_reserve(target, source->size) < 0) 60 return -1; 61 62 if (clone == NULL) { 63 assert(dtor == NULL); 64 clone = copy_elt; 65 data = target; 66 } else { 67 assert(dtor != NULL); 68 } 69 70 size_t i; 71 for (i = 0; i < source->size; ++i) 72 if (clone(slot(target, i), cslot(source, i), data) < 0) 73 goto fail; 74 75 target->size = source->size; 76 return 0; 77 78fail: 79 /* N.B. destroy the elements in opposite order. */ 80 if (dtor != NULL) 81 while (i-- != 0) 82 dtor(slot(target, i), data); 83 vect_destroy(target, NULL, NULL); 84 return -1; 85} 86 87int 88vect_reserve(struct vect *vec, size_t count) 89{ 90 if (count > vec->allocated) { 91 size_t na = vec->allocated != 0 ? 2 * vec->allocated : 4; 92 while (na < count) 93 na *= 2; 94 void *n = realloc(vec->data, na * vec->elt_size); 95 if (n == NULL) 96 return -1; 97 vec->data = n; 98 vec->allocated = na; 99 } 100 assert(count <= vec->allocated); 101 return 0; 102} 103 104size_t 105vect_size(const struct vect *vec) 106{ 107 return vec->size; 108} 109 110int 111vect_empty(const struct vect *vec) 112{ 113 return vec->size == 0; 114} 115 116int 117vect_reserve_additional(struct vect *vec, size_t count) 118{ 119 return vect_reserve(vec, vect_size(vec) + count); 120} 121 122int 123vect_pushback(struct vect *vec, void *eltp) 124{ 125 if (vect_reserve_additional(vec, 1) < 0) 126 return -1; 127 memcpy(slot(vec, vec->size++), eltp, vec->elt_size); 128 return 0; 129} 130 131void 132vect_erase(struct vect *vec, size_t start, size_t end, 133 void (*dtor)(void *emt, void *data), void *data) 134{ 135 assert(start < vect_size(vec) || start == 0); 136 assert(end <= vect_size(vec)); 137 138 /* First, destroy the elements that are to be erased. */ 139 if (dtor != NULL) { 140 size_t i; 141 for (i = start; i < end; ++i) 142 dtor(slot(vec, i), data); 143 } 144 145 /* Now move the tail forward and adjust size. */ 146 memmove(slot(vec, start), slot(vec, end), vec->size - end); 147 vec->size -= end - start; 148} 149 150void 151vect_popback(struct vect *vec, 152 void (*dtor)(void *emt, void *data), void *data) 153{ 154 assert(vect_size(vec) > 0); 155 vect_erase(vec, vect_size(vec)-1, vect_size(vec), dtor, data); 156} 157 158void 159vect_destroy(struct vect *vec, void (*dtor)(void *emt, void *data), void *data) 160{ 161 if (vec == NULL) 162 return; 163 164 vect_erase(vec, 0, vect_size(vec), dtor, data); 165 assert(vect_size(vec) == 0); 166 free(vec->data); 167} 168 169void * 170vect_each(struct vect *vec, void *start_after, 171 enum callback_status (*cb)(void *, void *), void *data) 172{ 173 size_t i = start_after == NULL ? 0 174 : ((start_after - vec->data) / vec->elt_size) + 1; 175 176 for (; i < vec->size; ++i) { 177 void *slt = slot(vec, i); 178 switch ((*cb)(slt, data)) { 179 case CBS_FAIL: 180 /* XXX handle me */ 181 case CBS_STOP: 182 return slt; 183 case CBS_CONT: 184 break; 185 } 186 } 187 188 return NULL; 189} 190