diff options
| author | Jeroen van Rijn <Kelimion@users.noreply.github.com> | 2024-09-03 22:47:56 +0200 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2024-09-03 22:47:56 +0200 |
| commit | 645207b8b07cd2d8b58f46f0a4748ac0a0d0e3d5 (patch) | |
| tree | 481a55b91545c0b133ef4ba05954a09c234adc89 /core/strings | |
| parent | 6bbc165121f94d2ad5c6ebba676c5b8137661a05 (diff) | |
| parent | 597ba796b7340aeca0aa25ac7d7f52ca2411294a (diff) | |
Merge pull request #4192 from laytan/strings-substring-rune-wise
strings: add `substring`, `substring_to` and `substring_from`
Diffstat (limited to 'core/strings')
| -rw-r--r-- | core/strings/strings.odin | 103 |
1 files changed, 103 insertions, 0 deletions
diff --git a/core/strings/strings.odin b/core/strings/strings.odin index dfe881ccd..b69c4a0e0 100644 --- a/core/strings/strings.odin +++ b/core/strings/strings.odin @@ -3327,3 +3327,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) +} |