strvec.c (5350B)
1#include "strvec.h" 2#include "dvec.h" 3#include "allocator.h" 4 5#include <stddef.h> 6#include <string.h> 7 8int 9strvec_init(struct strvec *strvec, size_t cap, 10 const struct allocator *allocator) 11{ 12 int rc; 13 14 LIBSTRVEC_ABORT_ON_ARGS(!strvec || !allocator); 15 16 rc = dvec_init(&strvec->vec, sizeof(char *), cap, allocator); 17 LIBSTRVEC_ABORT_ON_ALLOC(rc < 0); 18 19 return rc; 20} 21 22int 23strvec_deinit(struct strvec *strvec) 24{ 25 int rc; 26 27 LIBSTRVEC_ABORT_ON_ALLOC(!strvec); 28 29 rc = dvec_deinit(&strvec->vec); 30 LIBSTRVEC_ABORT_ON_ALLOC(rc < 0); 31 32 return rc; 33} 34 35struct strvec * 36strvec_alloc(size_t cap, const struct allocator *allocator, int *_rc) 37{ 38 struct strvec *strvec; 39 int *rc, stub; 40 41 LIBSTRVEC_ABORT_ON_ARGS(!allocator); 42 43 rc = _rc ? _rc : &stub; 44 45 strvec = allocator->alloc(allocator, sizeof(struct strvec), rc); 46 if (!strvec && _rc) *rc = -*rc; 47 if (!strvec) return NULL; 48 49 *rc = strvec_init(strvec, cap, allocator); 50 if (*rc) { 51 allocator->free(allocator, strvec); 52 return NULL; 53 } 54 55 return strvec; 56} 57 58int 59strvec_free(struct strvec *strvec) 60{ 61 const struct allocator *allocator; 62 int rc; 63 64 LIBSTRVEC_ABORT_ON_ARGS(!allocator); 65 66 allocator = strvec->vec.allocator; 67 68 rc = dvec_deinit(&strvec->vec); 69 LIBSTRVEC_ABORT_ON_ALLOC(rc < 0); 70 if (rc) return rc; 71 72 rc = allocator->free(allocator, strvec); 73 LIBSTRVEC_ABORT_ON_ALLOC(rc); 74 if (rc) return -rc; 75 76 return 0; 77} 78 79int 80strvec_copy(struct strvec *dst, struct strvec *src, 81 const struct allocator *allocator) 82{ 83 char **str, *nstr; 84 size_t len; 85 int rc; 86 87 LIBSTRVEC_ABORT_ON_ARGS(!dst || !src); 88 89 dvec_copy(&dst->vec, &src->vec); 90 for (DVEC_ITER(&dst->vec, str)) { 91 if (!*str) continue; 92 len = strlen(*str); 93 nstr = allocator->alloc(allocator, len + 1, &rc); 94 LIBSTRVEC_ABORT_ON_ALLOC(!nstr); 95 if (!nstr) return rc; 96 strncpy(nstr, *str, len + 1); 97 *str = nstr; 98 } 99 100 return 0; 101} 102 103void 104strvec_move(struct strvec *dst, struct strvec *src) 105{ 106 LIBSTRVEC_ABORT_ON_ARGS(!dst || !src); 107 108 memcpy(dst, src, sizeof(struct strvec)); 109} 110 111void 112strvec_swap(struct strvec *dst, struct strvec *src) 113{ 114 struct strvec tmp; 115 116 LIBSTRVEC_ABORT_ON_ARGS(!dst || !src); 117 118 memcpy(&tmp, dst, sizeof(struct dvec)); 119 memcpy(dst, src, sizeof(struct dvec)); 120 memcpy(src, &tmp, sizeof(struct dvec)); 121} 122 123int 124strvec_reserve(struct strvec *strvec, size_t cap) 125{ 126 int rc; 127 128 LIBSTRVEC_ABORT_ON_ARGS(!strvec); 129 130 rc = dvec_reserve(&strvec->vec, cap); 131 LIBSTRVEC_ABORT_ON_ALLOC(rc < 0); 132 133 return rc; 134} 135 136void 137strvec_clear(struct strvec *strvec) 138{ 139 LIBSTRVEC_ABORT_ON_ARGS(!strvec); 140 141 dvec_clear(&strvec->vec); 142} 143 144int 145strvec_shrink(struct strvec *strvec) 146{ 147 int rc; 148 149 LIBSTRVEC_ABORT_ON_ARGS(!strvec); 150 151 rc = dvec_shrink(&strvec->vec); 152 LIBSTRVEC_ABORT_ON_ALLOC(rc < 0); 153 154 return rc; 155} 156 157int 158strvec_pushn(struct strvec *strvec, const char **str, size_t count) 159{ 160 const char **dst; 161 int rc; 162 163 LIBSTRVEC_ABORT_ON_ARGS(!strvec || !str || !count); 164 165 rc = dvec_add_back(&strvec->vec, count); 166 LIBSTRVEC_ABORT_ON_ALLOC(rc < 0); 167 if (rc) return rc; 168 169 dst = dvec_at_back(&strvec->vec, count - 1); 170 memcpy(dst, str, count * sizeof(char *)); 171 172 return 0; 173} 174 175const char ** 176strvec_popn(struct strvec *strvec, size_t count) 177{ 178 const char **pos; 179 180 LIBSTRVEC_ABORT_ON_ARGS(!strvec || !count); 181 182 pos = dvec_at_back(&strvec->vec, count); 183 dvec_rm_back(&strvec->vec, count); 184 185 return pos; 186} 187 188void 189strvec_replace(struct strvec *strvec, size_t index, const char *str) 190{ 191 const char **pos; 192 193 LIBSTRVEC_ABORT_ON_ARGS(!strvec || index >= dvec_len(&strvec->vec)) 194 195 pos = dvec_at(&strvec->vec, index); 196 *pos = str; 197} 198 199void 200strvec_remove(struct strvec *strvec, size_t index, size_t count) 201{ 202 LIBSTRVEC_ABORT_ON_ARGS(!strvec); 203 204 dvec_rm(&strvec->vec, index, count); 205} 206 207int 208strvec_remove_str(struct strvec *strvec, const char *str, 209 const struct allocator *allocator) 210{ 211 const char **ent; 212 size_t i; 213 int rc; 214 215 LIBSTRVEC_ABORT_ON_ARGS(!strvec); 216 217 for (i = 0; i < strvec->vec.len; ) { 218 ent = strvec_at(strvec, i); 219 if (!str && !*ent || !strcmp(str, *ent)) { 220 if (allocator) { 221 rc = allocator->free(allocator, (char *) *ent); 222 if (rc) return -rc; 223 } 224 strvec_remove(strvec, i, 1); 225 } else { 226 i++; 227 } 228 } 229 230 return 0; 231} 232 233ssize_t 234strvec_find(struct strvec *strvec, size_t start, const char *str) 235{ 236 const char **ent; 237 size_t i; 238 239 LIBSTRVEC_ABORT_ON_ARGS(!strvec); 240 241 for (i = start; i < strvec->vec.len; i++) { 242 ent = strvec_at(strvec, i); 243 if (!str && !*ent) return (ssize_t) i; 244 if (!strcmp(str, *ent)) return (ssize_t) i; 245 } 246 247 return -1; 248} 249 250char * 251strvec_join(struct strvec *strvec, const char *sep, 252 const struct allocator *allocator, int *_rc) 253{ 254 const char **ent; 255 size_t len, seplen; 256 char *str; 257 258 seplen = strlen(sep); 259 260 len = 0; 261 for (STRVEC_ITER(strvec, ent)) { 262 if (!*ent) continue; 263 if (len) len += seplen; 264 len += strlen(*ent); 265 } 266 267 str = allocator->alloc(allocator, len + 1, _rc); 268 if (!str && _rc) *_rc = -*_rc; 269 if (!str) return NULL; 270 271 len = 0; 272 for (STRVEC_ITER(strvec, ent)) { 273 if (!*ent) continue; 274 275 if (len) { 276 strcpy(str + len, sep); 277 len += seplen; 278 } 279 280 strcpy(str + len, *ent); 281 len += strlen(*ent); 282 } 283 284 return str; 285} 286 287const char ** 288strvec_iter_fwd(const struct strvec *strvec, const char **p) 289{ 290 LIBSTRVEC_ABORT_ON_ARGS(!strvec); 291 292 return dvec_iter_fwd(&strvec->vec, p); 293} 294 295const char ** 296strvec_iter_bwd(const struct strvec *strvec, const char **p) 297{ 298 LIBSTRVEC_ABORT_ON_ARGS(!strvec); 299 300 return dvec_iter_bwd(&strvec->vec, p); 301}