aboutsummaryrefslogtreecommitdiff
path: root/vendor/librune/lib/builder/u8strgrow.c
blob: 253fcfce7dabaacaf4fea43f40c4df827b0b781b (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
#include <stdlib.h>

#include "builder.h"

#include "internal/common.h"

static size_t nextpow2(size_t);

struct u8buf *
u8strgrow(struct u8buf *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;
}