aboutsummaryrefslogtreecommitdiff
path: root/core/strings
diff options
context:
space:
mode:
authorLaytan Laats <laytanlaats@hotmail.com>2024-09-03 21:10:15 +0200
committerLaytan Laats <laytanlaats@hotmail.com>2024-09-03 21:13:35 +0200
commit597ba796b7340aeca0aa25ac7d7f52ca2411294a (patch)
tree343dc52bdffeaf85c1c2102777d92cfeeb07d6b1 /core/strings
parent0e6109e171d24b3bb17289219ae3b482c24f2460 (diff)
strings: add `substring`, `substring_to` and `substring_from`
Diffstat (limited to 'core/strings')
-rw-r--r--core/strings/strings.odin103
1 files changed, 103 insertions, 0 deletions
diff --git a/core/strings/strings.odin b/core/strings/strings.odin
index 216d7ad79..b94384bd8 100644
--- a/core/strings/strings.odin
+++ b/core/strings/strings.odin
@@ -3316,3 +3316,106 @@ levenshtein_distance :: proc(a, b: string, allocator := context.allocator, loc :
return costs[n], nil
}
+
+@(private)
+internal_substring :: proc(s: string, rune_start: int, rune_end: int) -> (sub: string, ok: bool) {
+ sub = s
+ ok = true
+
+ rune_i: int
+
+ if rune_start > 0 {
+ ok = false
+ for _, i in sub {
+ if rune_start == rune_i {
+ ok = true
+ sub = sub[i:]
+ break
+ }
+ rune_i += 1
+ }
+ if !ok { return }
+ }
+
+ if rune_end >= rune_start {
+ ok = false
+ for _, i in sub {
+ if rune_end == rune_i {
+ ok = true
+ sub = sub[:i]
+ break
+ }
+ rune_i += 1
+ }
+
+ if rune_end == rune_i {
+ ok = true
+ }
+ }
+
+ return
+}
+
+/*
+Returns a substring of `s` that starts at rune index `rune_start` and goes up to `rune_end`.
+
+Think of it as slicing `s[rune_start:rune_end]` but rune-wise.
+
+Inputs:
+- s: the string to substring
+- rune_start: the start (inclusive) rune
+- rune_end: the end (exclusive) rune
+
+Returns:
+- sub: the substring
+- ok: whether the rune indexes where in bounds of the original string
+*/
+substring :: proc(s: string, rune_start: int, rune_end: int) -> (sub: string, ok: bool) {
+ if rune_start < 0 || rune_end < 0 || rune_end < rune_start {
+ return
+ }
+
+ return internal_substring(s, rune_start, rune_end)
+}
+
+/*
+Returns a substring of `s` that starts at rune index `rune_start` and goes up to the end of the string.
+
+Think of it as slicing `s[rune_start:]` but rune-wise.
+
+Inputs:
+- s: the string to substring
+- rune_start: the start (inclusive) rune
+
+Returns:
+- sub: the substring
+- ok: whether the rune indexes where in bounds of the original string
+*/
+substring_from :: proc(s: string, rune_start: int) -> (sub: string, ok: bool) {
+ if rune_start < 0 {
+ return
+ }
+
+ return internal_substring(s, rune_start, -1)
+}
+
+/*
+Returns a substring of `s` that goes up to rune index `rune_end`.
+
+Think of it as slicing `s[:rune_end]` but rune-wise.
+
+Inputs:
+- s: the string to substring
+- rune_end: the end (exclusive) rune
+
+Returns:
+- sub: the substring
+- ok: whether the rune indexes where in bounds of the original string
+*/
+substring_to :: proc(s: string, rune_end: int) -> (sub: string, ok: bool) {
+ if rune_end < 0 {
+ return
+ }
+
+ return internal_substring(s, -1, rune_end)
+}