~sircmpwn/hare

hare/strings/cstrings.ha -rw-r--r-- 1.5 KiB
1c326effDrew DeVault fnmatch: remove export on internal function 21 hours ago
                                                                                
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
use encoding::utf8;
use types;
use rt;

let emptybuf: [1]u8 = [0];

// A C-compatible empty string. Empty Hare strings have a null pointer instead
// of containing only '\0', so a special string is needed for this case.
export let c_empty: *const char = &emptybuf: *[*]u8: *const char;

// Computes the length of a NUL-terminated C string, in octets, in O(n). The
// computed length does not include the NUL terminator.
export fn cstrlen(cstr: *const char) size = {
	const ptr = cstr: *[*]u8;
	let ln = 0z;
	for (ptr[ln] != 0; ln += 1) void;
	return ln;
};

// Converts a C string to a Hare string in O(n), and does not check if it's
// valid UTF-8.
export fn fromc_unsafe(cstr: *const char) const str = {
	const l = cstrlen(cstr);
	const s = types::string {
		data = cstr: *[*]u8,
		length = l,
		capacity = l,
	};
	return *(&s: *const str);
};

// Converts a C string to a Hare string in O(n). If the string is not valid
// UTF-8, abort.
export fn fromc(cstr: *const char) const str = {
	let s = fromc_unsafe(cstr);
	assert(utf8::valid(s));
	return s;
};

// Converts a Hare string to a C string. The result is allocated, the caller
// must free it when they're done.
export fn to_c(s: const str) *char = {
	let ptr = rt::malloc(len(s) + 1): nullable *[*]u8;
	let ptr = match (ptr) {
	case null =>
		abort("Out of memory");
	case p: *[*]u8 =>
		yield p;
	};
	match ((&s: *types::string).data) {
	case null => void;
	case data: *[*]u8 =>
		yield rt::memcpy(ptr, data, len(s));
	};
	ptr[len(s)] = 0;
	return ptr: *char;
};