1     type Char
2         def is_whitespace = case self of
3             ' ' | '\n' | '\r' -> true
4             else -> false
5     
6     type String
7         def chars = Slice ptr length
8         def is_empty = length == 0
9         def is_not_empty = length <> 0
10    
11        def try_index_of (s : String) =
12            let last @param = false
13    
14            if length < s.length then
15                return None
16    
17            let (from, to, diff) = if last
18                                   then (length - s.length, 0, -1)
19                                   else (0, length - s.length, 1)
20            let mut i = from
21            repeat
22                let mut result = true
23                for j = 0 until s.length do
24                    if s[j] <> self[i + j] then
25                        result = false
26                        break
27    
28                when
29                    result -> return Some i
30                    i == to -> return None
31                    else -> i += diff
32    
33        def index_of (s : String) = try_index_of s |> unwrap
34        def try_last_index_of (s : String) = try_index_of s
35                                                          last = true
36        def last_index_of (s : String) = try_last_index_of s |> unwrap
37        def try_index_of (c : Char) =
38            for i = 0 until length do
39                if self[i] == c then return Some i
40    
41            None
42    
43        def index_of (c : Char) = try_index_of c |> unwrap
44    
45        def try_last_index_of (c : Char) =
46            for i = length - 1 downto 0 do
47                if self[i] == c then return Some i
48    
49            None
50    
51        def try_last_index_of (chars : Slice<Char> @vararg) =
52            for i = length - 1 downto 0 do
53                for c in chars do
54                    if self[i] == c then return Some i
55    
56            None
57    
58        def last_index_of (c : Char) = try_last_index_of c |> unwrap
59    
60        def contains (s : String) = try_index_of s |> is_some
61        def contains (c : Char) = try_index_of c |> is_some
62    
63        def starts_with (s : String) =
64            if length < s.length then false
65            else
66                for i = 0 until s.length do
67                    if self[i] <> s[i] then return false
68    
69                true
70    
71        def starts_with (c : Char) = self[0] == c
72    
73        def ends_with (s : String) =
74            if length < s.length then false
75            else
76                let offset = length - s.length
77                for i = 0 until s.length do
78                    if self[i + offset] <> s[i] then return false
79    
80                true
81    
82        def ends_with (c : Char) = self[length - 1] == c
83        def last = self[length - 1]
84    
85        def drop (x : u32) =
86            assert x <= length
87            String (ptr + x) (length - x)
88    
89        def drop_last (x : u32) =
90            assert x <= length
91            String ptr (length - x)
92    
93        def take (x : u32) =
94            assert x <= length
95            String ptr x
96    
97        def trim_start =
98            if length == 0 then
99                return self
100   
101           let mut start = 0
102           let end = length - 1
103           while self[start].is_whitespace && start < end do
104               start += 1
105   
106           let count = end - start + 1
107           String (ptr + start) count
108   
109       def trim_end =
110           if length == 0 then
111               return self
112   
113           let mut end = length - 1
114           while self[end].is_whitespace && end > 0 do
115               end -= 1
116   
117           String ptr (end + 1)
118   
119       def trim =
120           if length == 0 then
121               return self
122   
123           let mut start = 0
124           let mut end = length - 1
125           while self[start].is_whitespace && start < end do
126               start += 1
127   
128           while self[end].is_whitespace && end > start do
129               end -= 1
130   
131           let count = end - start + 1
132           String (ptr + start) count
133   
134       def split_at (index : u32) =
135           let before = substring 0 index
136           let after = substring (index + 1) length
137           (before, after)
138   
139       def split (s : String) =
140           let list = List<String>.new
141           let mut start = 0
142           let mut index = 0
143           let mut pattern_index = 0
144   
145           for i = 0 until length do
146               if self[i] == s[pattern_index] then
147                   pattern_index += 1
148                   if pattern_index == s.length then
149                       let t = if i > start + pattern_index
150                               then substring start (i - pattern_index + 1)
151                               else ""
152                       list.add t
153                       start = i + 1
154                       pattern_index = 0
155   
156           substring start length |> list.add
157   
158           list
159   
160       def count (f : Char -> bool) =
161           let mut count = 0
162           for i = 0 until length do
163               if f self[i] then
164                   count += 1
165   
166           count
167   
168       def split (c : Char) =
169           let list = List<String>.new
170           let mut start = 0
171           for i = 0 until length do
172               if self[i] == c then
173                   let s = substring start i
174                   list.add s
175                   start = i + 1
176   
177           if length - start > 0 then
178               let last = substring start length
179               list.add last
180   
181           list
182   
183       def split_first (c : Char) =
184           for i = 0 until length do
185               if self[i] == c then
186                   return substring 0 i
187   
188           fail
189   
190       def lines = split '\n'
191   
192       def with_index =
193           let list = List<(u32, Char)>.new
194           for i = 0 until length do
195               list.add (i, self[i])
196   
197           list
198   
199       def as_bytes =
200           Slice ptr = ptr as Ptr<u8>
201                 size = length * String.bytes_per_char
202   
203       def replace (from : Char) (to : Char) =
204           let sb = StringBuilder.new
205           for char in chars do
206               let c = if char == from then to else char
207               sb.append c
208   
209           sb.create
210