#pragma once #include "dvec.h" #include "allocator.h" #include #include #define STRVEC_ITER(strvec, p) (p) = NULL; ((p) = strvec_iter_fwd((strvec), (p))); #define STRVEC_ITER_BWD(strvec, p) (p) = NULL; ((p) = strvec_iter_bwd((strvec), (p))); #ifdef LIBSTRVEC_ASSERT_ARGS #include "stdlib.h" #define LIBSTRVEC_ABORT_ON_ARGS(cond) do { if (cond) abort(); } while (0) #else #define LIBSTRVEC_ABORT_ON_ARGS(cond) #endif #ifdef LIBSTRVEC_ASSERT_ALLOC #include "stdlib.h" #define LIBSTRVEC_ABORT_ON_ALLOC(cond) do { if (cond) abort(); } while (0) #else #define LIBSTRVEC_ABORT_ON_ALLOC(cond) #endif struct strvec { struct dvec vec; }; int strvec_init(struct strvec *strvec, size_t cap, const struct allocator *allocator); int strvec_deinit(struct strvec *strvec); struct strvec *strvec_alloc(size_t reserved, const struct allocator *allocator, int *rc); int strvec_free(struct strvec *strvec); int strvec_copy(struct strvec *dst, struct strvec *src, const struct allocator *allocator); void strvec_move(struct strvec *dst, struct strvec *src); void strvec_swap(struct strvec *dst, struct strvec *src); void strvec_clear(struct strvec *strvec); int strvec_reserve(struct strvec *strvec, size_t cap); int strvec_shrink(struct strvec *strvec); static inline const char **strvec_stra(struct strvec *strvec); static inline const char **strvec_at(struct strvec *strvec, size_t index); static inline const char *strvec_get(struct strvec *strvec, size_t index); static inline const char *strvec_front(struct strvec *strvec); static inline const char *strvec_back(struct strvec *strvec); static inline size_t strvec_len(struct strvec *strvec); static inline bool strvec_empty(struct strvec *strvec); int strvec_pushn(struct strvec *strvec, const char **str, size_t n); static inline int strvec_push(struct strvec *strvec, const char *str); const char **strvec_popn(struct strvec *strvec, size_t n); static inline const char *strvec_pop(struct strvec *strvec); void strvec_replace(struct strvec *strvec, size_t index, const char *str); void strvec_remove(struct strvec *strvec, size_t index, size_t n); int strvec_remove_str(struct strvec *strvec, const char *str, const struct allocator *allocator); ssize_t strvec_find(struct strvec *strvec, size_t start, const char *str); char *strvec_join(struct strvec *strvec, const char *sep, const struct allocator *allocator, int *rc); const char **strvec_iter_fwd(const struct strvec *strvec, const char **p); const char **strvec_iter_bwd(const struct strvec *strvec, const char **p); static inline const char ** strvec_stra(struct strvec *strvec) { LIBSTRVEC_ABORT_ON_ARGS(!strvec && !strvec->vec.data); return (const char **)strvec->vec.data; } static inline const char ** strvec_at(struct strvec *strvec, size_t index) { LIBSTRVEC_ABORT_ON_ARGS(!strvec); return dvec_at(&strvec->vec, index); } static inline size_t strvec_len(struct strvec *strvec) { LIBSTRVEC_ABORT_ON_ARGS(!strvec); return strvec->vec.len; } static inline bool strvec_empty(struct strvec *strvec) { return strvec_len(strvec) == 0; } static inline const char * strvec_get(struct strvec *strvec, size_t index) { return *strvec_at(strvec, index); } static inline const char * strvec_front(struct strvec *strvec) { return *strvec_at(strvec, 0); } static inline const char * strvec_back(struct strvec *strvec) { LIBSTRVEC_ABORT_ON_ARGS(!strvec || strvec_empty(strvec)); return *strvec_at(strvec, strvec_len(strvec) - 1); } static inline int strvec_push(struct strvec *strvec, const char *str) { return strvec_pushn(strvec, &str, 1); } static inline const char * strvec_pop(struct strvec *strvec) { return *strvec_popn(strvec, 1); }