diff options
| author | Jeroen van Rijn <Kelimion@users.noreply.github.com> | 2021-08-02 18:09:59 +0200 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2021-08-02 18:09:59 +0200 |
| commit | c0f746a251e5bc433acec710aa1824b2220f4da1 (patch) | |
| tree | 8ca05f0425be235564f261e4ac2d33fb5775158c | |
| parent | ccbdf086ff1d160cec707f5fe5560509afeda495 (diff) | |
| parent | d260ca6738f1122d2e1767038afb148442dbdb7b (diff) | |
Merge pull request #1065 from Kelimion/string_cut
Add `strings.cut`, which returns a substring.
| -rw-r--r-- | core/strings/strings.odin | 34 |
1 files changed, 34 insertions, 0 deletions
diff --git a/core/strings/strings.odin b/core/strings/strings.odin index e81b41222..6d135fc75 100644 --- a/core/strings/strings.odin +++ b/core/strings/strings.odin @@ -165,6 +165,40 @@ concatenate :: proc(a: []string, allocator := context.allocator) -> string { return string(b); } +/* + `rune_offset` and `rune_length` are in runes, not bytes. + If `rune_length` <= 0, then it'll return the remainder of the string starting with `rune_offset`. +*/ +cut :: proc(s: string, rune_offset := int(0), rune_length := int(0), allocator := context.allocator) -> (res: string) { + s := s; rune_length := rune_length; + l := utf8.rune_count_in_string(s); + + if rune_offset >= l { return ""; } + if rune_offset == 0 && rune_length <= 0 { + return clone(s, allocator); + } + if rune_length == 0 { rune_length = l; } + + bytes_needed := min(rune_length * 4, len(s)); + buf := make([]u8, bytes_needed, allocator); + + byte_offset := 0; + for i := 0; i < l; i += 1 { + _, w := utf8.decode_rune_in_string(s); + if i >= rune_offset { + for j := 0; j < w; j += 1 { + buf[byte_offset+j] = s[j]; + } + byte_offset += w; + } + if rune_length > 0 { + if i == rune_offset + rune_length - 1 { break; } + } + s = s[w:]; + } + return string(buf[:byte_offset]); +} + @private _split :: proc(s_, sep: string, sep_save, n_: int, allocator := context.allocator) -> []string { s, n := s_, n_; |