summaryrefslogtreecommitdiff
path: root/lib/std/strsplit.myr
blob: af34838ba37b644a41591869b67e17d59d9bea1e (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
use "alloc"
use "chartype"
use "die"
use "extremum"
use "option"
use "slpush"
use "strfind"
use "strstrip"
use "types"
use "utf"

pkg std =
	const strsplit	: (s : byte[:], delim : byte[:] -> byte[:][:])
	const bstrsplit	: (sp : byte[:][:], s : byte[:], delim : byte[:] -> byte[:][:])
	const strtok	: (s : byte[:] -> byte[:][:])
	const bstrtok	: (sp : byte[:][:], s : byte[:] -> byte[:][:])
;;

extern const put	: (fmt : byte[:], args : ... -> size)

const strsplit = {s, delim
	var sp

	sp = [][:]
	-> dostrsplit(&sp, s, delim, true)
}

const bstrsplit = {sp, s, delim
	-> dostrsplit(&sp, s, delim, false)
}

const dostrsplit : (sp : byte[:][:]#, s : byte[:], delim : byte[:], grow : bool -> byte[:][:]) = {sp : byte[:][:]#, s, delim, grow
	var last
	var idx

	last = 0
	idx = 0

	if s.len == 0
		-> sp#[:idx]
	;;

	while true
		match strfind(s, delim)
		| `Some i:
			if grow
				slpush(sp, s[:i])
			elif idx < sp#.len - 1
				sp#[idx] = s[:i]
			else
				goto donesplit
			;;
			s = s[i + delim.len:]
			idx++
		| `None:
			goto donesplit
		;;
	;;
:donesplit
	if grow
		slpush(sp, s)
	else
		sp#[idx] = s
	;;
	idx++
	-> sp#[:idx]
}

const strtok = {s
	var toks
	toks = [][:]

	-> dostrtok(&toks, s, true)
}

const bstrtok = {toks, s
	-> dostrtok(&toks, s, false)
}

const dostrtok = {toks, s, grow
	var i, j
	var idx

	i = 0
	idx = 0
	while i != s.len
		while isspace(std.decode(s[i:])) && i < s.len
			i++
		;;
		j = i
		while !std.isspace(std.decode(s[j:])) && j < s.len
			j++
		;;
		if i != j
			if grow
				slpush(toks, s[i:j])
			elif idx < toks#.len - 1
				toks#[idx] = s[i:j]
			else
				toks#[idx] = strrstrip(s[i:])
				idx++
				break
			;;
			idx++
		;;
		i = j
	;;
	-> toks#[:idx]
}