length := fn(ptr: ^u8): uint { len := 0 loop if *(ptr + len) == 0 return len else len += 1 } split_once := fn(haystack: ^u8, needle: @Any()): ?^u8 { T := @TypeOf(needle) if T == ^u8 { if *needle == 0 return null loop if *haystack == 0 return null else { if *haystack == *needle { h := haystack n := needle loop { n += 1 h += 1 if *n == 0 { return haystack } else if *h == 0 | *h != *n { break } } } haystack += 1 } } else if T == u8 { loop if *haystack == needle return haystack else if *haystack == 0 return null else haystack += 1 } } SplitIter := fn($T: type): type { return struct { str: ^u8, needle: T, done: bool iter := fn(self: ^Self): ?^u8 { if self.done | *self.str == 0 { return null } next := split_once(self.str, self.needle) if next == null { self.done = true return self.str } s := self.str if T == ^u8 { self.str = next + length(self.needle) } else if T == u8 { self.str = next + 1 } return s } } } split := fn(iter: ^u8, needle: @Any()): SplitIter(@TypeOf(needle)) { return .( iter, needle, false ) } main := fn(): void { full_path := "acs:/path/to/a/file\0" splt := split(full_path, "path\0") a := splt.iter() splt2 := split(full_path, '/') b := splt2.iter() }