summaryrefslogtreecommitdiff
path: root/src/runtime/c/gu/str.c
blob: 073781b232b0a730c129e3c537d49ecbfd8a1f8a (plain)
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
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
#include <gu/assert.h>
#include <gu/str.h>
#include <string.h>
#include <wchar.h>
#include <stdio.h>
#include <stdlib.h>

const char gu_empty_str[] = "";
const char* const gu_null_str = NULL;

char* 
gu_new_str(size_t size, GuPool* pool)
{
	char* str = gu_new_n(char, size + 1, pool);
	memset(str, '\0', size + 1);
	return str;
}

char*
gu_strdup(const char* cstr, GuPool* pool)
{
	int len = strlen(cstr);
	char* str = gu_new_str(len, pool);
	memcpy(str, cstr, len);
	return str;
}

bool
gu_str_eq(GuStr s1, GuStr s2)
{
	return (strcmp(s1, s2)) == 0;
}

static bool
gu_str_is_equal(GuEquality* self, const void* p1, const void* p2)
{
	(void) self;
	const GuStr* sp1 = p1;
	const GuStr* sp2 = p2;
	return gu_str_eq(*sp1, *sp2);
}

static GuHash
gu_str_hasher_hash(GuHasher* self, const void* p)
{
	(void) self;
	GuHash h = 0;
	const GuStr* sp = p;
	for (const char* s = *sp; *s != '\0'; s++) {
		h = 101 * h + (unsigned char) *s;
	}
	return h;
}

GuHasher gu_str_hasher[1] = {
	{
		.eq = { .is_equal = gu_str_is_equal },
		.hash = gu_str_hasher_hash
	}
};

GU_DEFINE_TYPE(GuStr, repr, _);

char* 
gu_vasprintf(const char* fmt, va_list args, GuPool* pool)
{
	va_list args2;
	va_copy(args2, args);
	int len = vsnprintf(NULL, 0, fmt, args2);
	gu_assert_msg(len >= 0, "Invalid format string: \"%s\"", fmt);
	va_end(args2);
	char* str = gu_new_str(len, pool);
	vsnprintf(str, len + 1, fmt, args);
	return str;
}

char* 
gu_asprintf(GuPool* pool, const char* fmt, ...)
{
	va_list args;
	va_start(args, fmt);
	char* str = gu_vasprintf(fmt, args, pool);
	va_end(args);
	return str;
}