| 1 | module builtin |
| 2 | |
| 3 | // String: This is a minimal implementation of the "string" builtin until the WASM backend |
| 4 | // is able to compile the original builtin implementation |
| 5 | |
| 6 | pub struct string { |
| 7 | pub: |
| 8 | str &u8 |
| 9 | len int |
| 10 | } |
| 11 | |
| 12 | // Concatenation operator: var += str / str + str |
| 13 | // Note: This will alloc a new string with the content of these two strings |
| 14 | pub fn (s string) + (other string) string { |
| 15 | if s.len == 0 { |
| 16 | return other |
| 17 | } |
| 18 | if other.len == 0 { |
| 19 | return s |
| 20 | } |
| 21 | total_len := s.len + other.len |
| 22 | result_ptr := unsafe { malloc(total_len) } |
| 23 | if result_ptr == 0 { |
| 24 | panic('string.+: malloc failed') |
| 25 | } |
| 26 | unsafe { |
| 27 | vmemcpy(result_ptr, s.str, s.len) |
| 28 | vmemcpy(result_ptr + s.len, other.str, other.len) |
| 29 | } |
| 30 | return string{ |
| 31 | str: result_ptr |
| 32 | len: total_len |
| 33 | } |
| 34 | } |
| 35 | |
| 36 | // Equality comparison: checks if two strings are identical |
| 37 | pub fn (s string) == (other string) bool { |
| 38 | if s.len != other.len { |
| 39 | return false |
| 40 | } |
| 41 | |
| 42 | for i in 0 .. s.len { |
| 43 | if s[i] != other[i] { |
| 44 | return false |
| 45 | } |
| 46 | } |
| 47 | |
| 48 | return true |
| 49 | } |
| 50 | |
| 51 | // Less-than comparison: lexicographically compares two strings |
| 52 | pub fn (s string) < (other string) bool { |
| 53 | // Taken from the C Backend |
| 54 | for i in 0 .. s.len { |
| 55 | if i >= other.len || s[i] > other[i] { |
| 56 | return false |
| 57 | } else if s[i] < other[i] { |
| 58 | return true |
| 59 | } |
| 60 | } |
| 61 | if s.len < other.len { |
| 62 | return true |
| 63 | } |
| 64 | return false |
| 65 | } |
| 66 | |
| 67 | // at returns the byte at index `idx`. |
| 68 | // Example: assert 'ABC'.at(1) == u8(`B`) |
| 69 | // NOTE: Adapted from C built-in, modified for WASM |
| 70 | pub fn (s string) at(idx int) u8 { |
| 71 | $if !no_bounds_checking { |
| 72 | if idx < 0 || idx >= s.len { |
| 73 | panic('string index out of range') |
| 74 | } |
| 75 | } |
| 76 | return unsafe { s.str[idx] } |
| 77 | } |
| 78 | |
| 79 | // Convert C string to V string |
| 80 | pub fn cstring_to_vstring(ptr &u8) string { |
| 81 | if ptr == 0 { |
| 82 | return '' |
| 83 | } |
| 84 | |
| 85 | mut len := 0 |
| 86 | unsafe { |
| 87 | for ptr[len] != 0 { |
| 88 | len++ |
| 89 | } |
| 90 | } |
| 91 | unsafe { |
| 92 | return string{ |
| 93 | str: ptr |
| 94 | len: len |
| 95 | } |
| 96 | } |
| 97 | } |
| 98 | |