diff options
Diffstat (limited to 'strv.c')
-rw-r--r-- | strv.c | 117 |
1 files changed, 117 insertions, 0 deletions
diff --git a/strv.c b/strv.c new file mode 100644 index 0000000000..ecad6d5980 --- /dev/null +++ b/strv.c @@ -0,0 +1,117 @@ +/*-*- Mode: C; c-basic-offset: 8 -*-*/ + +#include <assert.h> +#include <stdlib.h> +#include <stdarg.h> +#include <string.h> + +#include "util.h" +#include "strv.h" + +char *strv_find(char **l, const char *name) { + assert(l); + assert(name); + + for (; *l; l++) + if (streq(*l, name)) + return *l; + + return NULL; +} + +void strv_free(char **l) { + char **k; + + if (!l) + return; + + for (k = l; *k; k++) + free(*k); + + free(l); +} + +char **strv_copy(char **l) { + char **r, **k; + + if (!(r = new(char*, strv_length(l)+1))) + return NULL; + + for (k = r; *l; k++, l++) + if (!(*k = strdup(*l))) + goto fail; + + *k = NULL; + return r; + +fail: + for (k--, l--; k >= r; k--, l--) + free(*k); + + return NULL; +} + +unsigned strv_length(char **l) { + unsigned n = 0; + + if (!l) + return 0; + + for (; *l; l++) + n++; + + return n; +} + +char **strv_new(const char *x, ...) { + const char *s; + char **a; + unsigned n = 0, i = 0; + va_list ap; + + if (x) { + n = 1; + + va_start(ap, x); + + while (va_arg(ap, const char*)) + n++; + + va_end(ap); + } + + if (!(a = new(char*, n+1))) + return NULL; + + if (x) { + if (!(a[i] = strdup(x))) { + free(a); + return NULL; + } + + i++; + + va_start(ap, x); + + while ((s = va_arg(ap, const char*))) { + if (!(a[i] = strdup(s))) + goto fail; + + i++; + } + + va_end(ap); + } + + a[i] = NULL; + return a; + +fail: + + for (; i > 0; i--) + if (a[i-1]) + free(a[i-1]); + + free(a); + return NULL; +} |