aboutsummaryrefslogtreecommitdiff
path: root/core/strings
diff options
context:
space:
mode:
authorgingerBill <bill@gingerbill.org>2020-11-12 14:17:41 +0000
committergingerBill <bill@gingerbill.org>2020-11-12 14:17:41 +0000
commit78b6948ff2e5fed0ef3e279b23686d1ac6c4d797 (patch)
tree1b496aab8d3063a05dde9c8b57afd5b35415475d /core/strings
parenta6c5c203abdeee683558543fdfe39ece59e17c9c (diff)
Reorganize package strings
Diffstat (limited to 'core/strings')
-rw-r--r--core/strings/conversion.odin254
-rw-r--r--core/strings/strings.odin255
2 files changed, 254 insertions, 255 deletions
diff --git a/core/strings/conversion.odin b/core/strings/conversion.odin
new file mode 100644
index 000000000..44f501246
--- /dev/null
+++ b/core/strings/conversion.odin
@@ -0,0 +1,254 @@
+package strings
+
+to_valid_utf8 :: proc(s, replacement: string, allocator := context.allocator) -> string {
+ if len(s) == 0 {
+ return "";
+ }
+
+ b := make_builder_len_cap(0, 0, allocator);
+
+ s := s;
+ for c, i in s {
+ if c != utf8.RUNE_ERROR {
+ continue;
+ }
+
+ _, w := utf8.decode_rune_in_string(s[i:]);
+ if w == 1 {
+ grow_builder(&b, len(s) + len(replacement));
+ write_string(&b, s[:i]);
+ s = s[i:];
+ break;
+ }
+ }
+
+ if builder_cap(b) == 0 {
+ return clone(s, allocator);
+ }
+
+ invalid := false;
+
+ for i := 0; i < len(s); /**/ {
+ c := s[i];
+ if c < utf8.RUNE_SELF {
+ i += 1;
+ invalid = false;
+ write_byte(&b, c);
+ continue;
+ }
+
+ _, w := utf8.decode_rune_in_string(s[i:]);
+ if w == 1 {
+ i += 1;
+ if !invalid {
+ invalid = true;
+ write_string(&b, replacement);
+ }
+ continue;
+ }
+ invalid = false;
+ write_string(&b, s[i:][:w]);
+ i += w;
+ }
+ return to_string(b);
+}
+
+to_lower :: proc(s: string, allocator := context.allocator) -> string {
+ b := make_builder(0, len(s), allocator);
+ for r in s {
+ write_rune(&b, unicode.to_lower(r));
+ }
+ return to_string(b);
+}
+to_upper :: proc(s: string, allocator := context.allocator) -> string {
+ b := make_builder(0, len(s), allocator);
+ for r in s {
+ write_rune(&b, unicode.to_upper(r));
+ }
+ return to_string(b);
+}
+
+
+
+
+is_delimiter :: proc(c: rune) -> bool {
+ return c == '-' || c == '_' || is_space(c);
+}
+
+is_separator :: proc(r: rune) -> bool {
+ if r <= 0x7f {
+ switch r {
+ case '0'..'9': return false;
+ case 'a'..'z': return false;
+ case 'A'..'Z': return false;
+ case '_': return false;
+ }
+ return true;
+ }
+
+ // TODO(bill): unicode categories
+ // if unicode.is_letter(r) || unicode.is_digit(r) {
+ // return false;
+ // }
+
+ return unicode.is_space(r);
+}
+
+
+string_case_iterator :: proc(b: ^Builder, s: string, callback: proc(b: ^Builder, prev, curr, next: rune)) {
+ prev, curr: rune;
+ for next in s {
+ if curr == 0 {
+ prev = curr;
+ curr = next;
+ continue;
+ }
+
+ callback(b, prev, curr, next);
+
+ prev = curr;
+ curr = next;
+ }
+
+ if len(s) > 0 {
+ callback(b, prev, curr, 0);
+ }
+}
+
+
+to_lower_camel_case :: to_camel_case;
+to_camel_case :: proc(s: string, allocator := context.allocator) -> string {
+ s := s;
+ s = trim_space(s);
+ b := make_builder(0, len(s), allocator);
+
+ string_case_iterator(&b, s, proc(b: ^Builder, prev, curr, next: rune) {
+ if !is_delimiter(curr) {
+ if is_delimiter(prev) {
+ write_rune(b, unicode.to_upper(curr));
+ } else if unicode.is_lower(prev) {
+ write_rune(b, curr);
+ } else {
+ write_rune(b, unicode.to_lower(curr));
+ }
+ }
+ });
+
+ return to_string(b);
+}
+
+to_upper_camel_case :: to_pascal_case;
+to_pascal_case :: proc(s: string, allocator := context.allocator) -> string {
+ s := s;
+ s = trim_space(s);
+ b := make_builder(0, len(s), allocator);
+
+ string_case_iterator(&b, s, proc(b: ^Builder, prev, curr, next: rune) {
+ if !is_delimiter(curr) {
+ if is_delimiter(prev) || prev == 0 {
+ write_rune(b, unicode.to_upper(curr));
+ } else if unicode.is_lower(prev) {
+ write_rune(b, curr);
+ } else {
+ write_rune(b, unicode.to_lower(curr));
+ }
+ }
+ });
+
+ return to_string(b);
+}
+
+to_delimiter_case :: proc(s: string, delimiter: rune, all_upper_case: bool, allocator := context.allocator) -> string {
+ s := s;
+ s = trim_space(s);
+ b := make_builder(0, len(s), allocator);
+
+ adjust_case := unicode.to_upper if all_upper_case else unicode.to_lower;
+
+ prev, curr: rune;
+
+ for next in s {
+ if is_delimiter(curr) {
+ if !is_delimiter(prev) {
+ write_rune(&b, delimiter);
+ }
+ } else if unicode.is_upper(curr) {
+ if unicode.is_lower(prev) || (unicode.is_upper(prev) && unicode.is_lower(next)) {
+ write_rune(&b, delimiter);
+ }
+ write_rune(&b, adjust_case(curr));
+ } else if curr != 0 {
+ write_rune(&b, adjust_case(curr));
+ }
+
+ prev = curr;
+ curr = next;
+ }
+
+ if len(s) > 0 {
+ if unicode.is_upper(curr) && unicode.is_lower(prev) && prev != 0 {
+ write_rune(&b, delimiter);
+ }
+ write_rune(&b, adjust_case(curr));
+ }
+
+ return to_string(b);
+}
+
+
+to_snake_case :: proc(s: string, allocator := context.allocator) -> string {
+ return to_delimiter_case(s, '_', false, allocator);
+}
+
+to_screaming_snake_case :: to_upper_snake_case;
+to_upper_snake_case :: proc(s: string, allocator := context.allocator) -> string {
+ return to_delimiter_case(s, '_', true, allocator);
+}
+
+to_kebab_case :: proc(s: string, allocator := context.allocator) -> string {
+ return to_delimiter_case(s, '-', false, allocator);
+}
+
+to_upper_case :: proc(s: string, allocator := context.allocator) -> string {
+ return to_delimiter_case(s, '-', true, allocator);
+}
+
+to_ada_case :: proc(s: string, allocator := context.allocator) -> string {
+ delimiter :: '_';
+
+ s := s;
+ s = trim_space(s);
+ b := make_builder(0, len(s), allocator);
+
+ prev, curr: rune;
+
+ for next in s {
+ if is_delimiter(curr) {
+ if !is_delimiter(prev) {
+ write_rune(&b, delimiter);
+ }
+ } else if unicode.is_upper(curr) {
+ if unicode.is_lower(prev) || (unicode.is_upper(prev) && unicode.is_lower(next)) {
+ write_rune(&b, delimiter);
+ }
+ write_rune(&b, unicode.to_upper(curr));
+ } else if curr != 0 {
+ write_rune(&b, unicode.to_lower(curr));
+ }
+
+ prev = curr;
+ curr = next;
+ }
+
+ if len(s) > 0 {
+ if unicode.is_upper(curr) && unicode.is_lower(prev) && prev != 0 {
+ write_rune(&b, delimiter);
+ write_rune(&b, unicode.to_upper(curr));
+ } else {
+ write_rune(&b, unicode.to_lower(curr));
+ }
+ }
+
+ return to_string(b);
+}
+
diff --git a/core/strings/strings.odin b/core/strings/strings.odin
index c706f5940..47620ed54 100644
--- a/core/strings/strings.odin
+++ b/core/strings/strings.odin
@@ -787,207 +787,6 @@ scrub :: proc(s: string, replacement: string, allocator := context.allocator) ->
}
-to_lower :: proc(s: string, allocator := context.allocator) -> string {
- b := make_builder(0, len(s), allocator);
- for r in s {
- write_rune(&b, unicode.to_lower(r));
- }
- return to_string(b);
-}
-to_upper :: proc(s: string, allocator := context.allocator) -> string {
- b := make_builder(0, len(s), allocator);
- for r in s {
- write_rune(&b, unicode.to_upper(r));
- }
- return to_string(b);
-}
-
-
-
-
-is_delimiter :: proc(c: rune) -> bool {
- return c == '-' || c == '_' || is_space(c);
-}
-
-is_separator :: proc(r: rune) -> bool {
- if r <= 0x7f {
- switch r {
- case '0'..'9': return false;
- case 'a'..'z': return false;
- case 'A'..'Z': return false;
- case '_': return false;
- }
- return true;
- }
-
- // TODO(bill): unicode categories
- // if unicode.is_letter(r) || unicode.is_digit(r) {
- // return false;
- // }
-
- return unicode.is_space(r);
-}
-
-
-string_case_iterator :: proc(b: ^Builder, s: string, callback: proc(b: ^Builder, prev, curr, next: rune)) {
- prev, curr: rune;
- for next in s {
- if curr == 0 {
- prev = curr;
- curr = next;
- continue;
- }
-
- callback(b, prev, curr, next);
-
- prev = curr;
- curr = next;
- }
-
- if len(s) > 0 {
- callback(b, prev, curr, 0);
- }
-}
-
-
-to_lower_camel_case :: to_camel_case;
-to_camel_case :: proc(s: string, allocator := context.allocator) -> string {
- s := s;
- s = trim_space(s);
- b := make_builder(0, len(s), allocator);
-
- string_case_iterator(&b, s, proc(b: ^Builder, prev, curr, next: rune) {
- if !is_delimiter(curr) {
- if is_delimiter(prev) {
- write_rune(b, unicode.to_upper(curr));
- } else if unicode.is_lower(prev) {
- write_rune(b, curr);
- } else {
- write_rune(b, unicode.to_lower(curr));
- }
- }
- });
-
- return to_string(b);
-}
-
-to_upper_camel_case :: to_pascal_case;
-to_pascal_case :: proc(s: string, allocator := context.allocator) -> string {
- s := s;
- s = trim_space(s);
- b := make_builder(0, len(s), allocator);
-
- string_case_iterator(&b, s, proc(b: ^Builder, prev, curr, next: rune) {
- if !is_delimiter(curr) {
- if is_delimiter(prev) || prev == 0 {
- write_rune(b, unicode.to_upper(curr));
- } else if unicode.is_lower(prev) {
- write_rune(b, curr);
- } else {
- write_rune(b, unicode.to_lower(curr));
- }
- }
- });
-
- return to_string(b);
-}
-
-to_delimiter_case :: proc(s: string, delimiter: rune, all_upper_case: bool, allocator := context.allocator) -> string {
- s := s;
- s = trim_space(s);
- b := make_builder(0, len(s), allocator);
-
- adjust_case := unicode.to_upper if all_upper_case else unicode.to_lower;
-
- prev, curr: rune;
-
- for next in s {
- if is_delimiter(curr) {
- if !is_delimiter(prev) {
- write_rune(&b, delimiter);
- }
- } else if unicode.is_upper(curr) {
- if unicode.is_lower(prev) || (unicode.is_upper(prev) && unicode.is_lower(next)) {
- write_rune(&b, delimiter);
- }
- write_rune(&b, adjust_case(curr));
- } else if curr != 0 {
- write_rune(&b, adjust_case(curr));
- }
-
- prev = curr;
- curr = next;
- }
-
- if len(s) > 0 {
- if unicode.is_upper(curr) && unicode.is_lower(prev) && prev != 0 {
- write_rune(&b, delimiter);
- }
- write_rune(&b, adjust_case(curr));
- }
-
- return to_string(b);
-}
-
-
-to_snake_case :: proc(s: string, allocator := context.allocator) -> string {
- return to_delimiter_case(s, '_', false, allocator);
-}
-
-to_screaming_snake_case :: to_upper_snake_case;
-to_upper_snake_case :: proc(s: string, allocator := context.allocator) -> string {
- return to_delimiter_case(s, '_', true, allocator);
-}
-
-to_kebab_case :: proc(s: string, allocator := context.allocator) -> string {
- return to_delimiter_case(s, '-', false, allocator);
-}
-
-to_upper_case :: proc(s: string, allocator := context.allocator) -> string {
- return to_delimiter_case(s, '-', true, allocator);
-}
-
-to_ada_case :: proc(s: string, allocator := context.allocator) -> string {
- delimiter :: '_';
-
- s := s;
- s = trim_space(s);
- b := make_builder(0, len(s), allocator);
-
- prev, curr: rune;
-
- for next in s {
- if is_delimiter(curr) {
- if !is_delimiter(prev) {
- write_rune(&b, delimiter);
- }
- } else if unicode.is_upper(curr) {
- if unicode.is_lower(prev) || (unicode.is_upper(prev) && unicode.is_lower(next)) {
- write_rune(&b, delimiter);
- }
- write_rune(&b, unicode.to_upper(curr));
- } else if curr != 0 {
- write_rune(&b, unicode.to_lower(curr));
- }
-
- prev = curr;
- curr = next;
- }
-
- if len(s) > 0 {
- if unicode.is_upper(curr) && unicode.is_lower(prev) && prev != 0 {
- write_rune(&b, delimiter);
- write_rune(&b, unicode.to_upper(curr));
- } else {
- write_rune(&b, unicode.to_lower(curr));
- }
- }
-
- return to_string(b);
-}
-
-
-
reverse :: proc(s: string, allocator := context.allocator) -> string {
str := s;
n := len(str);
@@ -1120,60 +919,6 @@ right_justify :: proc(str: string, length: int, pad: string, allocator := contex
-to_valid_utf8 :: proc(s, replacement: string, allocator := context.allocator) -> string {
- if len(s) == 0 {
- return "";
- }
-
- b := make_builder_len_cap(0, 0, allocator);
-
- s := s;
- for c, i in s {
- if c != utf8.RUNE_ERROR {
- continue;
- }
-
- _, w := utf8.decode_rune_in_string(s[i:]);
- if w == 1 {
- grow_builder(&b, len(s) + len(replacement));
- write_string(&b, s[:i]);
- s = s[i:];
- break;
- }
- }
-
- if builder_cap(b) == 0 {
- return clone(s, allocator);
- }
-
- invalid := false;
-
- for i := 0; i < len(s); /**/ {
- c := s[i];
- if c < utf8.RUNE_SELF {
- i += 1;
- invalid = false;
- write_byte(&b, c);
- continue;
- }
-
- _, w := utf8.decode_rune_in_string(s[i:]);
- if w == 1 {
- i += 1;
- if !invalid {
- invalid = true;
- write_string(&b, replacement);
- }
- continue;
- }
- invalid = false;
- write_string(&b, s[i:][:w]);
- i += w;
- }
- return to_string(b);
-}
-
-
@private
write_pad_string :: proc(b: ^Builder, pad: string, pad_len, remains: int) {