libstrvec-c

C string vector library
git clone https://git.sinitax.com/sinitax/libstrvec-c
Log | Files | Refs | LICENSE | sfeed.txt

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}