diff --git a/core/slice/slice.odin b/core/slice/slice.odin index b8fb29ab3..440cf643f 100644 --- a/core/slice/slice.odin +++ b/core/slice/slice.odin @@ -170,6 +170,21 @@ simple_equal :: proc(a, b: $T/[]$E) -> bool where intrinsics.type_is_simple_comp return mem.compare_ptrs(raw_data(a), raw_data(b), len(a)*size_of(E)) == 0 } +/* + return the prefix length common between slices `a` and `b`. + + slice.prefix_length([]u8{1, 2, 3, 4}, []u8{1}) -> 1 + slice.prefix_length([]u8{1, 2, 3, 4}, []u8{1, 2, 3}) -> 3 + slice.prefix_length([]u8{1, 2, 3, 4}, []u8{2, 3, 4}) -> 0 +*/ +prefix_length :: proc(a, b: $T/[]$E) -> (n: int) where intrinsics.type_is_comparable(E) { + _len := builtin.min(len(a), len(b)) + + #no_bounds_check for n < _len && a[n] == b[n] { + n += 1 + } + return +} has_prefix :: proc(array: $T/[]$E, needle: E) -> bool where intrinsics.type_is_comparable(E) { n := len(needle) diff --git a/core/strings/strings.odin b/core/strings/strings.odin index 2429b451d..678cc94cd 100644 --- a/core/strings/strings.odin +++ b/core/strings/strings.odin @@ -215,6 +215,29 @@ equal_fold :: proc(u, v: string) -> bool { return s == t } +/* + return the prefix length common between strings `a` and `b`. + + strings.prefix_length("testing", "test") -> 4 + strings.prefix_length("testing", "te") -> 2 + strings.prefix_length("telephone", "te") -> 2 + strings.prefix_length("testing", "est") -> 0 +*/ +prefix_length :: proc(a, b: string) -> (n: int) { + _len := min(len(a), len(b)) + idx := 0 + + #no_bounds_check for idx < _len && a[idx] == b[idx] { + idx += 1 + + if a[idx] & 128 != 128 { + // new codepoint or end of multi-byte codepoint, update match length + n = idx + } + } + return +} + /* return true when the string `prefix` is contained at the start of the string `s`