diff options
| author | gingerBill <gingerBill@users.noreply.github.com> | 2020-07-10 08:25:24 +0100 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2020-07-10 08:25:24 +0100 |
| commit | f65fa0e4a6201fa7a67c5b0013f460b902550a57 (patch) | |
| tree | ab244a8e82a81e2bf8c87df72a2555e80a4c6a15 /core/strings | |
| parent | 65b9dbe13f2749c943c21e7880356b6e6efcfc8b (diff) | |
| parent | e3d1d1d85c68b6ebc999cae648e55c692e1258d2 (diff) | |
Merge pull request #339 from dotbmp/master
"core:path" Path library and "core:strings" `split` Utilities
Diffstat (limited to 'core/strings')
| -rw-r--r-- | core/strings/strings.odin | 150 |
1 files changed, 150 insertions, 0 deletions
diff --git a/core/strings/strings.odin b/core/strings/strings.odin index b6af8dc53..32fbcbd20 100644 --- a/core/strings/strings.odin +++ b/core/strings/strings.odin @@ -641,6 +641,7 @@ trim_space :: proc(s: string) -> string { return trim_right_space(trim_left_space(s)); } + trim_left_null :: proc(s: string) -> string { return trim_left_proc(s, is_null); } @@ -653,6 +654,155 @@ trim_null :: proc(s: string) -> string { return trim_right_null(trim_left_null(s)); } + +// returns a slice of sub-strings into `s` +// `allocator` is used only for the slice +// `skip_empty=true` does not return zero-length substrings +split :: proc{split_single, split_multi}; + +split_single :: proc(s, substr: string, skip_empty := false, allocator := context.temp_allocator) -> []string #no_bounds_check { + if s == "" || substr == "" do return nil; + + sublen := len(substr); + shared := len(s) - sublen; + + if shared <= 0 { + return nil; + } + + // number, index, last + n, i, l := 0, 0, 0; + + // count results + first_pass: for i <= shared { + if s[i:i+sublen] == substr { + if !skip_empty || i - l > 0 { + n += 1; + } + + i += sublen; + l = i; + } else { + _, skip := utf8.decode_rune_in_string(s[i:]); + i += skip; + } + } + + if !skip_empty || len(s) - l > 0 { + n += 1; + } + + if n < 1 { + // no results + return nil; + } + + buf := make([]string, n, allocator); + + n, i, l = 0, 0, 0; + + // slice results + second_pass: for i <= shared { + if s[i:i+sublen] == substr { + if !skip_empty || i - l > 0 { + buf[n] = s[l:i]; + n += 1; + } + + i += sublen; + l = i; + } else { + _, skip := utf8.decode_rune_in_string(s[i:]); + i += skip; + } + } + + if !skip_empty || len(s) - l > 0 { + buf[n] = s[l:]; + } + + return buf; +} + +split_multi :: proc(s: string, substrs: []string, skip_empty := false, allocator := context.temp_allocator) -> []string #no_bounds_check { + if s == "" || len(substrs) <= 0 { + return nil; + } + + sublen := len(substrs[0]); + + for substr in substrs[1:] { + sublen = min(sublen, len(substr)); + } + + shared := len(s) - sublen; + + if shared <= 0 { + return nil; + } + + // number, index, last + n, i, l := 0, 0, 0; + + // count results + first_pass: for i <= shared { + for substr in substrs { + if s[i:i+sublen] == substr { + if !skip_empty || i - l > 0 { + n += 1; + } + + i += sublen; + l = i; + + continue first_pass; + } + } + + _, skip := utf8.decode_rune_in_string(s[i:]); + i += skip; + } + + if !skip_empty || len(s) - l > 0 { + n += 1; + } + + if n < 1 { + // no results + return nil; + } + + buf := make([]string, n, allocator); + + n, i, l = 0, 0, 0; + + // slice results + second_pass: for i <= shared { + for substr in substrs { + if s[i:i+sublen] == substr { + if !skip_empty || i - l > 0 { + buf[n] = s[l:i]; + n += 1; + } + + i += sublen; + l = i; + + continue second_pass; + } + } + + _, skip := utf8.decode_rune_in_string(s[i:]); + i += skip; + } + + if !skip_empty || len(s) - l > 0 { + buf[n] = s[l:]; + } + + return buf; +} + // scrub scruvs invalid utf-8 characters and replaces them with the replacement string // Adjacent invalid bytes are only replaced once scrub :: proc(s: string, replacement: string, allocator := context.allocator) -> string { |