ref: 690ab7aa8e6c56a4ae8a2bd5bce58d1df681234e
dir: /lib/std/strsplit.myr/
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] }