#include "string.h" #include #include #include #ifndef HAVE_STRDUP 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; } #endif size_t stranjoin_r( char *restrict buf, size_t buflen, char sep, const char *restrict a[], size_t nmemb) { size_t len = 0; if (NULL != buf && 0 < buflen) { /* clear buf string */ *buf = '\0'; } for (size_t i = 0; i < nmemb; ++i) { if (0 < len) { /* add separator */ if (NULL != buf && len < buflen) { *(buf+len) = sep; } ++len; } if (NULL != buf) { /* append element */ strncpy(buf+len, a[i], (buflen - len)); } len += strlen(a[i]); } return len; } char *stranjoin(char sep, const char *a[], size_t nmemb) { /* determine length of result string */ size_t len = stranjoin_r(NULL, 0, sep, a, nmemb); /* allocate destination buffer */ char *dest = malloc(len+1); if (NULL != dest) { (void)stranjoin_r(dest, len+1, sep, a, nmemb); } return dest; } size_t _vstrjoin_r(char *restrict buf, size_t buflen, char sep, va_list ap) { const char *s; size_t len = 0; if (NULL != buf && 0 < buflen) { /* clear buf string */ *buf = '\0'; } while (NULL != (s = va_arg(ap, const char *restrict))) { if (0 < len) { /* add separator */ if (NULL != buf && len < buflen) { *(buf+len) = sep; } ++len; } if (NULL != buf) { /* append element */ strncpy(buf+len, s, (buflen - len)); } len += strlen(s); } return len; } size_t _strjoin_r( char *restrict buf, size_t buflen, char sep, /* const char *restrict */...) { va_list ap; va_start(ap, sep); size_t len = _vstrjoin_r(buf, buflen, sep, ap); va_end(ap); return len; } char *_strjoin(char sep, /* const char *restrict */...) { va_list ap; /* determine length of result string */ va_start(ap, sep); size_t len = _vstrjoin_r(NULL, 0, sep, ap); va_end(ap); /* allocate destination buffer */ char *dest = malloc(len+1); if (NULL != dest) { (void)_vstrjoin_r(dest, len+1, sep, ap); } return dest; } 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); }