diff options
Diffstat (limited to 'src/util/string.c')
| -rw-r--r-- | src/util/string.c | 144 |
1 files changed, 144 insertions, 0 deletions
diff --git a/src/util/string.c b/src/util/string.c new file mode 100644 index 0000000..db565c0 --- /dev/null +++ b/src/util/string.c @@ -0,0 +1,144 @@ +#include "string.h" + +#include <stdarg.h> +#include <stdlib.h> +#include <string.h> + +char *strdup(const char *s) { + if (NULL == s) { + return NULL; + } + + size_t len = strlen(s); + char *buf = malloc(len+1); + + if (buf) { + memcpy(buf, s, len + 1); + } + return buf; +} + +char *stranjoin(char sep, const char *a[], size_t nmemb) { + char *dst; + + if (nmemb > 0) { + /* determine length of joined string */ + size_t len = 0; + for (size_t i = 0; i < nmemb; i++) { + len += strlen(a[i]) + 1; + } + + /* then, join strings */ + dst = calloc(len, sizeof(char)); + if (!dst) { + return NULL; + } + + char *p = dst; + for (size_t i = 0; i < nmemb; i++) { + if (i > 0) + *p++ = sep; + size_t l = strlen(a[i]); + memcpy(p, a[i], l); + p += l; + } + + *p = '\0'; + } else { + dst = strdup(""); + } + + return dst; +} + +char *_strjoin(char sep, /* const char * */...) { + const char *s; + char *dst, *p; + va_list ap; + size_t len, l; + + va_start(ap, sep); + + s = va_arg(ap, const char *); + + if (s) { + /* determine length of joined string */ + len = strlen(s) + 1; + + while ((s = va_arg(ap, const char *))) { + len += strlen(s) + 1; + } + va_end(ap); + + /* Then, join strings */ + dst = calloc(len, sizeof(char)); + if (!dst) { + return NULL; + } + p = dst; + + va_start(ap, sep); + + /* copy first element */ + s = va_arg(ap, const char *); + l = strlen(s); + strcpy(dst, s); + p += l; + + /* then the others */ + while ((s = va_arg(ap, const char *))) { + l = strlen(s); + + *p++ = sep; + strncpy(p, s, l); + p += l; + } + + *p = '\0'; + } else { + dst = strdup(""); + } + + va_end(ap); + + return dst; +} + +size_t strsplit(const char *restrict in, const char *restrict sep, void *buf) { + size_t i = 0; + char **arr = buf; + + if (0 == strlen(in)) { + /* special case: empty string */ + if (arr) arr[0] = NULL; + return sizeof(char *); + } + + char *tok, *saveptr, *tmp = strdup(in); + + tok = strtok_r(tmp, sep, &saveptr); + do { + if (arr) { + arr[i] = (char *)(tok - tmp); /* save char offset */ + } + i++; + } while ((tok = strtok_r(NULL, sep, &saveptr))); + + size_t strtokoffset = ((i+1)*sizeof(*arr)), + strtoklen = strlen(in) + 1; + + if (arr) { + /* update array pointers */ + for (int j = 0; j < i; j++) { + arr[j] = (char *)((size_t)buf + strtokoffset + (size_t)arr[j]); + } + arr[i] = NULL; /* NULL termination */ + + /* copy tokenized string from tmp to the back of buf */ + (void)memcpy(buf + strtokoffset, tmp, strtoklen); + } + + free(tmp); + + return (strtoklen + strtokoffset); +} |
