diff options
Diffstat (limited to 'std')
| -rw-r--r-- | std/io.zc | 22 | ||||
| -rw-r--r-- | std/queue.zc | 93 | ||||
| -rw-r--r-- | std/string.zc | 72 |
3 files changed, 159 insertions, 28 deletions
@@ -1,5 +1,6 @@ import "./core.zc" +import "./string.zc" raw { char* format(const char* fmt, ...) { @@ -34,8 +35,29 @@ raw { { return fgetc((FILE*)stream); } + + char* _z_format_alloc(const char* fmt, va_list args) { + int len = vsnprintf(NULL, 0, fmt, args); + if (len < 0) return NULL; + char* buffer = malloc(len + 1); + if (!buffer) return NULL; + vsnprintf(buffer, len + 1, fmt, args); + return buffer; + } + + char* format_s_raw(char* fmt, ...) { + va_list args; + va_start(args, fmt); + char* ret = _z_format_alloc(fmt, args); + va_end(args); + return ret; + } } +extern fn format_s_raw(fmt: char*, ...) -> char*; + +// TODO: add format function. We will need to do a few updates... +// like adding support for varargs in Zen C functions. fn readln() -> char* { diff --git a/std/queue.zc b/std/queue.zc index 3e99eba..0b00ee2 100644 --- a/std/queue.zc +++ b/std/queue.zc @@ -3,13 +3,15 @@ import "./mem.zc" struct Queue<T> { data: T*; - len: usize; cap: usize; + head: usize; + tail: usize; + count: usize; } impl Queue<T> { fn new() -> Queue<T> { - return Queue<T>{data: NULL, len: 0, cap: 0}; + return Queue<T>{data: NULL, cap: 0, head: 0, tail: 0, count: 0}; } fn free(self) { @@ -17,54 +19,91 @@ impl Queue<T> { free(self.data); self.data = NULL; } - self.len = 0; + self.cap = 0; + self.head = 0; + self.tail = 0; + self.count = 0; + } + + fn _grow(self) { + var new_cap = (self.cap == 0) ? 8 : self.cap * 2; + var new_data = malloc(sizeof(T) * new_cap); + + if (self.count > 0) { + if (self.tail > self.head) { + memcpy(new_data, self.data + self.head, sizeof(T) * self.count); + } else { + var first_part = self.cap - self.head; + var second_part = self.tail; + memcpy(new_data, self.data + self.head, sizeof(T) * first_part); + memcpy(new_data + first_part, self.data, sizeof(T) * second_part); + } + } + + if (self.data) free(self.data); + self.data = new_data; + self.cap = new_cap; + self.head = 0; + self.tail = self.count; } fn clone(self) -> Queue<T> { var new_queue = Queue<T>::new(); - new_queue.len = self.len; + new_queue.data = malloc(sizeof(T) * self.cap); new_queue.cap = self.cap; - new_queue.data = malloc(sizeof(T) * new_queue.cap); - memcpy(new_queue.data, self.data, sizeof(T) * new_queue.len); + new_queue.head = 0; + new_queue.tail = self.count; + new_queue.count = self.count; + + if (self.count > 0) { + if (self.tail > self.head) { + memcpy(new_queue.data, self.data + self.head, sizeof(T) * self.count); + } + else { + var first_part = self.cap - self.head; + var second_part = self.tail; + memcpy(new_queue.data, self.data + self.head, sizeof(T) * first_part); + memcpy(new_queue.data + first_part, self.data, sizeof(T) * second_part); + } + } + return new_queue; } fn push(self, value: T) { - if (!self.data) { - self.cap = 8; - self.data = malloc(sizeof(T) * self.cap); + if (self.count == self.cap) { + self._grow(); } - if (self.len == self.cap) { - self.cap = self.cap * 2; - self.data = realloc(self.data, sizeof(T) * self.cap); - } - self.data[self.len] = value; - self.len = self.len + 1; + + self.data[self.tail] = value; + self.tail = (self.tail + 1) % self.cap; + self.count = self.count + 1; } fn pop(self) -> Option<T> { - if (self.len > 0) { - var value = self.data[0]; - self.len = self.len - 1; - - // Shifts the data in the queue "forward" - memcpy(self.data, self.data + 1, sizeof(T) * self.len); - - return Option<T>::Some(value); + if (self.count == 0) { + return Option<T>::None(); } - return Option<T>::None(); + + var value = self.data[self.head]; + self.head = (self.head + 1) % self.cap; + self.count = self.count - 1; + + return Option<T>::Some(value); } fn length(self) -> usize { - return self.len; + return self.count; } fn clear(self) { - self.len = 0; + self.head = 0; + self.tail = 0; + self.count = 0; } fn is_empty(self) -> bool { - return self.len == 0; + return self.count == 0; } } diff --git a/std/string.zc b/std/string.zc index 3f96053..a7dd6ce 100644 --- a/std/string.zc +++ b/std/string.zc @@ -31,7 +31,6 @@ impl String { return String::new(s); } - // Fixed: 'self' implies pointer in generated C fn c_str(self) -> char* { return self.vec.data; } @@ -245,4 +244,75 @@ impl String { return parts; } + + fn trim(self) -> String { + var start: usize = 0; + var len = self.length(); + var end = len; + + // Find start + while (start < len) { + var c = self.vec.get(start); + if (c != ' ' && c != '\t' && c != '\n' && c != '\r') { + break; + } + start = start + 1; + } + + if (start == len) { + return String::new(""); + } + + // Find end + while (end > start) { + var c = self.vec.get(end - 1); + if (c != ' ' && c != '\t' && c != '\n' && c != '\r') { + break; + } + end = end - 1; + } + + return self.substring(start, end - start); + } + + fn replace(self, target: char*, replacement: char*) -> String { + var t_len = strlen(target); + if (t_len == 0) return self.substring(0, self.length()); // clone + + + var s_len = self.length(); + var result = String::new(""); + + var i: usize = 0; + while (i < s_len) { + // Check if match + if (i + t_len <= s_len) { + var is_match = true; + // Manual strncmp against vec data + for (var k: usize = 0; k < t_len; k = k + 1) { + if (self.vec.get(i + k) != target[k]) { + is_match = false; + break; + } + } + + if (is_match) { + var r_str = String::new(replacement); + result.append(&r_str); + i = i + t_len; + continue; + } + } + + // Append single char + var v = Vec<char>::new(); + v.push(self.vec.get(i)); + v.push(0); + var ch_s = String::new(v.data); + result.append(&ch_s); + v.free(); + i = i + 1; + } + return result; + } }
\ No newline at end of file |
