aboutsummaryrefslogtreecommitdiff
path: root/vendor/libc/string.odin
blob: b8115ea8831772c353fa555058a3c598a8f9abd1 (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
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
package odin_libc

import "base:intrinsics"

import "core:c"
import "core:strings"
import "core:mem"
import "core:bytes"

// NOTE: already defined by Odin.
// void *memcpy(void *, const void *, size_t);
// void *memset(void *, int, size_t);

@(require, linkage="strong", link_name="memcmp")
memcmp :: proc "c" (lhs: [^]byte, rhs: [^]byte, count: uint) -> i32 {
	icount := int(count)
	assert_contextless(icount >= 0)
	return i32(mem.compare(lhs[:icount], rhs[:icount]))
}

@(require, linkage="strong", link_name="strlen")
strlen :: proc "c" (str: cstring) -> c.ulong {
	return c.ulong(len(str))
}

@(require, linkage="strong", link_name="strchr")
strchr :: proc "c" (str: cstring, ch: i32) -> cstring {
	bch  := u8(ch)
	sstr := string(str)
	if bch == 0 {
		return cstring(raw_data(sstr)[len(sstr):])
	}

	idx := strings.index_byte(sstr, bch)
	if idx < 0 {
		return nil
	}

	return cstring(raw_data(sstr)[idx:])
}

@(require, linkage="strong", link_name="strrchr")
strrchr :: proc "c" (str: cstring, ch: i32) -> cstring {
	bch  := u8(ch)
	sstr := string(str)
	if bch == 0 {
		return cstring(raw_data(sstr)[len(sstr):])
	}

	idx := strings.last_index_byte(sstr, bch)
	if idx < 0 {
		return nil
	}

	return cstring(raw_data(sstr)[idx:])
}

@(require, linkage="strong", link_name="strncpy")
strncpy :: proc "c" (dst: [^]byte, src: cstring, count: uint) -> cstring {
	icount := int(count)
	assert_contextless(icount >= 0)
	cnt := min(len(src), icount)
	intrinsics.mem_copy_non_overlapping(dst, rawptr(src), cnt)
	intrinsics.mem_zero(dst, icount-cnt)
	return cstring(dst)
}

@(require, linkage="strong", link_name="strcpy")
strcpy :: proc "c" (dst: [^]byte, src: cstring) -> cstring {
	intrinsics.mem_copy_non_overlapping(dst, rawptr(src), len(src)+1)
	return cstring(dst)
}

@(require, linkage="strong", link_name="strcspn")
strcspn :: proc "c" (dst: cstring, src: cstring) -> uint {
	context = g_ctx
	sdst := string(dst)
	idx := strings.index_any(sdst, string(src))
	if idx == -1 {
		return len(sdst)
	}
	return uint(idx)
}

@(require, linkage="strong", link_name="strncmp")
strncmp :: proc "c" (lhs: cstring, rhs: cstring, count: uint) -> i32 {
	icount := int(count)
	assert_contextless(icount >= 0)
	lhss := strings.string_from_null_terminated_ptr(([^]byte)(lhs), icount)
	rhss := strings.string_from_null_terminated_ptr(([^]byte)(rhs), icount)
	return i32(strings.compare(lhss, rhss))
}

@(require, linkage="strong", link_name="strcmp")
strcmp :: proc "c" (lhs: cstring, rhs: cstring) -> i32 {
	return i32(strings.compare(string(lhs), string(rhs)))
}

@(require, linkage="strong", link_name="strstr")
strstr :: proc "c" (str: cstring, substr: cstring) -> cstring {
	if substr == "" {
		return str
	}

	idx := strings.index(string(str), string(substr))
	if idx < 0 {
		return nil
	}

	return cstring(([^]byte)(str)[idx:])
}

@(require, linkage="strong", link_name="memchr")
memchr :: proc "c" (str: [^]byte, c: i32, n: uint) -> [^]byte {
	idx := bytes.index_byte(str[:n], u8(c))
	if idx < 0 {
		return nil
	}

	return str[idx:]
}