#include "strvec.h" #include "dvec.h" #include "allocator.h" #include int strvec_init(struct strvec *strvec, size_t cap, const struct allocator *allocator) { int rc; LIBSTRVEC_ABORT_ON_ARGS(!strvec || !allocator); rc = dvec_init(&strvec->vec, sizeof(char *), cap, allocator); LIBSTRVEC_ABORT_ON_ALLOC(rc < 0); return rc; } int strvec_deinit(struct strvec *strvec) { int rc; LIBSTRVEC_ABORT_ON_ALLOC(!strvec); rc = dvec_deinit(&strvec->vec); LIBSTRVEC_ABORT_ON_ALLOC(rc < 0); return rc; } struct strvec * strvec_alloc(size_t cap, const struct allocator *allocator, int *_rc) { struct strvec *strvec; int *rc, stub; LIBSTRVEC_ABORT_ON_ARGS(!allocator); rc = _rc ? _rc : &stub; strvec = allocator->alloc(allocator, sizeof(struct strvec), rc); if (!strvec && _rc) *rc = -*rc; if (!strvec) return NULL; *rc = strvec_init(strvec, cap, allocator); if (*rc) { allocator->free(allocator, strvec); return NULL; } return strvec; } int strvec_free(struct strvec *strvec) { const struct allocator *allocator; int rc; LIBSTRVEC_ABORT_ON_ARGS(!allocator); allocator = strvec->vec.allocator; rc = dvec_deinit(&strvec->vec); LIBSTRVEC_ABORT_ON_ALLOC(rc < 0); if (rc) return rc; rc = allocator->free(allocator, strvec); LIBSTRVEC_ABORT_ON_ALLOC(rc); if (rc) return -rc; return 0; } int strvec_copy(struct strvec *dst, struct strvec *src, const struct allocator *allocator) { char **str, *nstr; size_t len; int rc; LIBSTRVEC_ABORT_ON_ARGS(!dst || !src); dvec_copy(&dst->vec, &src->vec); for (DVEC_ITER(&dst->vec, str)) { if (!*str) continue; len = strlen(*str); nstr = allocator->alloc(allocator, len + 1, &rc); LIBSTRVEC_ABORT_ON_ALLOC(!nstr); if (!nstr) return rc; strncpy(nstr, *str, len + 1); *str = nstr; } return 0; } void strvec_move(struct strvec *dst, struct strvec *src) { LIBSTRVEC_ABORT_ON_ARGS(!dst || !src); memcpy(dst, src, sizeof(struct strvec)); } void strvec_swap(struct strvec *dst, struct strvec *src) { struct strvec tmp; LIBSTRVEC_ABORT_ON_ARGS(!dst || !src); memcpy(&tmp, dst, sizeof(struct dvec)); memcpy(dst, src, sizeof(struct dvec)); memcpy(src, &tmp, sizeof(struct dvec)); } int strvec_reserve(struct strvec *strvec, size_t cap) { int rc; LIBSTRVEC_ABORT_ON_ARGS(!strvec); rc = dvec_reserve(&strvec->vec, cap); LIBSTRVEC_ABORT_ON_ALLOC(rc < 0); return rc; } void strvec_clear(struct strvec *strvec) { LIBSTRVEC_ABORT_ON_ARGS(!strvec); dvec_clear(&strvec->vec); } int strvec_shrink(struct strvec *strvec) { int rc; LIBSTRVEC_ABORT_ON_ARGS(!strvec); rc = dvec_shrink(&strvec->vec); LIBSTRVEC_ABORT_ON_ALLOC(rc < 0); return rc; } int strvec_pushn(struct strvec *strvec, const char **str, size_t count) { const char **dst; int rc; LIBSTRVEC_ABORT_ON_ARGS(!strvec || !str || !count); rc = dvec_add_back(&strvec->vec, count); LIBSTRVEC_ABORT_ON_ALLOC(rc < 0); if (rc) return rc; dst = dvec_at_back(&strvec->vec, count - 1); memcpy(dst, str, count * sizeof(char *)); return 0; } const char ** strvec_popn(struct strvec *strvec, size_t count) { const char **pos; LIBSTRVEC_ABORT_ON_ARGS(!strvec || !count); pos = dvec_at_back(&strvec->vec, count); dvec_rm_back(&strvec->vec, count); return pos; } void strvec_replace(struct strvec *strvec, size_t index, const char *str) { const char **pos; LIBSTRVEC_ABORT_ON_ARGS(!strvec || index >= dvec_len(&strvec->vec)) pos = dvec_at(&strvec->vec, index); *pos = str; } void strvec_remove(struct strvec *strvec, size_t index, size_t count) { LIBSTRVEC_ABORT_ON_ARGS(!strvec); dvec_rm(&strvec->vec, index, count); } const char ** strvec_iter_fwd(const struct strvec *strvec, const char **p) { LIBSTRVEC_ABORT_ON_ARGS(!strvec); return dvec_iter_fwd(&strvec->vec, p); } const char ** strvec_iter_bwd(const struct strvec *strvec, const char **p) { LIBSTRVEC_ABORT_ON_ARGS(!strvec); return dvec_iter_bwd(&strvec->vec, p); }