| 1 | module strings |
| 2 | |
| 3 | // import rand |
| 4 | // random returns a random string with `n` characters |
| 5 | /* |
| 6 | pub fn random(n int) string { |
| 7 | buf := vmalloc(n) |
| 8 | for i in 0..n { |
| 9 | buf[i] = rand.next() |
| 10 | } |
| 11 | return tos(buf) |
| 12 | } |
| 13 | */ |
| 14 | |
| 15 | // find_between_pair_byte returns the string found between the pair of marks defined |
| 16 | // by `start` and `end`. |
| 17 | // As opposed to the `find_between`, `all_after*`, `all_before*` methods defined on the |
| 18 | // `string` type, this function can extract content between *nested* marks in `input`. |
| 19 | // If `start` and `end` marks are nested in `input`, the characters |
| 20 | // between the *outermost* mark pair is returned. It is expected that `start` and `end` |
| 21 | // marks are *balanced*, meaning that the amount of `start` marks equal the |
| 22 | // amount of `end` marks in the `input`. An empty string is returned otherwise. |
| 23 | // Using two identical marks as `start` and `end` results in undefined output behavior. |
| 24 | // find_between_pair_byte is the fastest in the find_between_pair_* family of functions. |
| 25 | // Example: assert strings.find_between_pair_u8('(V) (NOT V)',`(`,`)`) == 'V' |
| 26 | // Example: assert strings.find_between_pair_u8('s {X{Y}} s',`{`,`}`) == 'X{Y}' |
| 27 | pub fn find_between_pair_u8(input string, start u8, end u8) string { |
| 28 | mut marks := 0 |
| 29 | mut start_index := -1 |
| 30 | for i, b in input { |
| 31 | if b == start { |
| 32 | if start_index == -1 { |
| 33 | start_index = i + 1 |
| 34 | } |
| 35 | marks++ |
| 36 | continue |
| 37 | } |
| 38 | if start_index > 0 { |
| 39 | if b == end { |
| 40 | marks-- |
| 41 | if marks == 0 { |
| 42 | return input[start_index..i] |
| 43 | } |
| 44 | } |
| 45 | } |
| 46 | } |
| 47 | return '' |
| 48 | } |
| 49 | |
| 50 | // find_between_pair_rune returns the string found between the pair of marks defined by `start` and `end`. |
| 51 | // As opposed to the `find_between`, `all_after*`, `all_before*` methods defined on the |
| 52 | // `string` type, this function can extract content between *nested* marks in `input`. |
| 53 | // If `start` and `end` marks are nested in `input`, the characters |
| 54 | // between the *outermost* mark pair is returned. It is expected that `start` and `end` |
| 55 | // marks are *balanced*, meaning that the amount of `start` marks equal the |
| 56 | // amount of `end` marks in the `input`. An empty string is returned otherwise. |
| 57 | // Using two identical marks as `start` and `end` results in undefined output behavior. |
| 58 | // find_between_pair_rune is inbetween the fastest and slowest in the find_between_pair_* family of functions. |
| 59 | // Example: assert strings.find_between_pair_rune('(V) (NOT V)',`(`,`)`) == 'V' |
| 60 | // Example: assert strings.find_between_pair_rune('s {X{Y}} s',`{`,`}`) == 'X{Y}' |
| 61 | pub fn find_between_pair_rune(input string, start rune, end rune) string { |
| 62 | mut marks := 0 |
| 63 | mut start_index := -1 |
| 64 | runes := input.runes() |
| 65 | for i, r in runes { |
| 66 | if r == start { |
| 67 | if start_index == -1 { |
| 68 | start_index = i + 1 |
| 69 | } |
| 70 | marks++ |
| 71 | continue |
| 72 | } |
| 73 | if start_index > 0 { |
| 74 | if r == end { |
| 75 | marks-- |
| 76 | if marks == 0 { |
| 77 | return runes[start_index..i].string() |
| 78 | } |
| 79 | } |
| 80 | } |
| 81 | } |
| 82 | return '' |
| 83 | } |
| 84 | |
| 85 | // find_between_pair_string returns the string found between the pair of marks defined by `start` and `end`. |
| 86 | // As opposed to the `find_between`, `all_after*`, `all_before*` methods defined on the |
| 87 | // `string` type, this function can extract content between *nested* marks in `input`. |
| 88 | // If `start` and `end` marks are nested in `input`, the characters |
| 89 | // between the *outermost* mark pair is returned. It is expected that `start` and `end` |
| 90 | // marks are *balanced*, meaning that the amount of `start` marks equal the |
| 91 | // amount of `end` marks in the `input`. An empty string is returned otherwise. |
| 92 | // Using two identical marks as `start` and `end` results in undefined output behavior. |
| 93 | // find_between_pair_string is the slowest in the find_between_pair_* function family. |
| 94 | // Example: assert strings.find_between_pair_string('/*V*/ /*NOT V*/','/*','*/') == 'V' |
| 95 | // Example: assert strings.find_between_pair_string('s {{X{{Y}}}} s','{{','}}') == 'X{{Y}}' |
| 96 | pub fn find_between_pair_string(input string, start string, end string) string { |
| 97 | mut start_index := -1 |
| 98 | mut marks := 0 |
| 99 | start_runes := start.runes() |
| 100 | end_runes := end.runes() |
| 101 | runes := input.runes() |
| 102 | mut i := 0 |
| 103 | for ; i < runes.len; i++ { |
| 104 | start_slice := runes#[i..i + start_runes.len] |
| 105 | if start_slice == start_runes { |
| 106 | i = i + start_runes.len - 1 |
| 107 | if start_index < 0 { |
| 108 | start_index = i + 1 |
| 109 | } |
| 110 | marks++ |
| 111 | continue |
| 112 | } |
| 113 | if start_index > 0 { |
| 114 | end_slice := runes#[i..i + end_runes.len] |
| 115 | if end_slice == end_runes { |
| 116 | marks-- |
| 117 | if marks == 0 { |
| 118 | return runes[start_index..i].string() |
| 119 | } |
| 120 | i = i + end_runes.len - 1 |
| 121 | continue |
| 122 | } |
| 123 | } |
| 124 | } |
| 125 | return '' |
| 126 | } |
| 127 | |
| 128 | // split_capital returns an array containing the contents of `s` split by capital letters. |
| 129 | // Example: assert strings.split_capital('XYZ') == ['X', 'Y', 'Z'] |
| 130 | // Example: assert strings.split_capital('XYStar') == ['X', 'Y', 'Star'] |
| 131 | pub fn split_capital(s string) []string { |
| 132 | mut res := []string{} |
| 133 | mut word_start := 0 |
| 134 | for idx, c in s { |
| 135 | if c.is_capital() { |
| 136 | if word_start != idx { |
| 137 | res << s#[word_start..idx] |
| 138 | } |
| 139 | word_start = idx |
| 140 | continue |
| 141 | } |
| 142 | } |
| 143 | if word_start != s.len { |
| 144 | res << s#[word_start..] |
| 145 | } |
| 146 | return res |
| 147 | } |
| 148 | |