aboutsummaryrefslogtreecommitdiff
path: root/vendor/librune/lib/builder/u8strgrow.c
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/librune/lib/builder/u8strgrow.c')
-rw-r--r--vendor/librune/lib/builder/u8strgrow.c41
1 files changed, 41 insertions, 0 deletions
diff --git a/vendor/librune/lib/builder/u8strgrow.c b/vendor/librune/lib/builder/u8strgrow.c
new file mode 100644
index 0000000..022b216
--- /dev/null
+++ b/vendor/librune/lib/builder/u8strgrow.c
@@ -0,0 +1,41 @@
+#include <stdlib.h>
+
+#include "builder.h"
+
+#include "internal/common.h"
+
+static size_t nextpow2(size_t);
+
+struct u8str *
+u8strgrow(struct u8str *b, size_t n)
+{
+ if (n > b->cap) {
+ b->cap = nextpow2(n);
+ if (!(b->p = realloc(b->p, b->cap)))
+ return nullptr;
+ }
+ return b;
+}
+
+size_t
+nextpow2(size_t x)
+{
+#if defined(__has_builtin) && __has_builtin(__builtin_clzl)
+ x = x <= 1 ? 1 : 1 << (64 - __builtin_clzl(x - 1));
+#else
+ if (x) {
+ x--;
+ x |= x >> 1;
+ x |= x >> 2;
+ x |= x >> 4;
+ x |= x >> 8;
+ if (sizeof(size_t) >= 4)
+ x |= x >> 16;
+ if (sizeof(size_t) >= 8)
+ x |= x >> 32;
+ }
+ x++;
+#endif
+
+ return x;
+}