+
+char *strextend(char **x, ...) {
+ va_list ap;
+ size_t f, l;
+ char *r, *p;
+
+ assert(x);
+
+ l = f = *x ? strlen(*x) : 0;
+
+ va_start(ap, x);
+ for (;;) {
+ const char *t;
+ size_t n;
+
+ t = va_arg(ap, const char *);
+ if (!t)
+ break;
+
+ n = strlen(t);
+ if (n > ((size_t) -1) - l) {
+ va_end(ap);
+ return NULL;
+ }
+
+ l += n;
+ }
+ va_end(ap);
+
+ r = realloc(*x, l+1);
+ if (!r)
+ return NULL;
+
+ p = r + f;
+
+ va_start(ap, x);
+ for (;;) {
+ const char *t;
+
+ t = va_arg(ap, const char *);
+ if (!t)
+ break;
+
+ p = stpcpy(p, t);
+ }
+ va_end(ap);
+
+ *p = 0;
+ *x = r;
+
+ return r + l;
+}
+
+char *strrep(const char *s, unsigned n) {
+ size_t l;
+ char *r, *p;
+ unsigned i;
+
+ assert(s);
+
+ l = strlen(s);
+ p = r = malloc(l * n + 1);
+ if (!r)
+ return NULL;
+
+ for (i = 0; i < n; i++)
+ p = stpcpy(p, s);
+
+ *p = 0;
+ return r;
+}
+
+void* greedy_realloc(void **p, size_t *allocated, size_t need) {
+ size_t a;
+ void *q;
+
+ if (*allocated >= need)
+ return *p;
+
+ a = MAX(64u, need * 2);
+ q = realloc(*p, a);
+ if (!q)
+ return NULL;
+
+ *p = q;
+ *allocated = a;
+ return q;
+}
+
+bool id128_is_valid(const char *s) {
+ size_t i, l;
+
+ l = strlen(s);
+ if (l == 32) {
+
+ /* Simple formatted 128bit hex string */
+
+ for (i = 0; i < l; i++) {
+ char c = s[i];
+
+ if (!(c >= '0' && c <= '9') &&
+ !(c >= 'a' && c <= 'z') &&
+ !(c >= 'A' && c <= 'Z'))
+ return false;
+ }
+
+ } else if (l == 36) {
+
+ /* Formatted UUID */
+
+ for (i = 0; i < l; i++) {
+ char c = s[i];
+
+ if ((i == 8 || i == 13 || i == 18 || i == 23)) {
+ if (c != '-')
+ return false;
+ } else {
+ if (!(c >= '0' && c <= '9') &&
+ !(c >= 'a' && c <= 'z') &&
+ !(c >= 'A' && c <= 'Z'))
+ return false;
+ }
+ }
+
+ } else
+ return false;
+
+ return true;
+}