import "./core.zc" import "./vec.zc" import "./option.zc" struct String { vec: Vec; } impl String { fn new(s: char*) -> String { var len = strlen(s); var v = Vec::new(); // Manual copy for now for (var i = 0; i < len; i = i + 1) { v.push(s[i]); } v.push(0); // Extract fields to transfer ownership var d = v.data; var l = v.len; var c = v.cap; // Forget the local vector so it doesn't free the memory v.forget(); return String { vec: Vec { data: d, len: l, cap: c } }; } fn from(s: char*) -> String { return String::new(s); } // Fixed: 'self' implies pointer in generated C fn c_str(self) -> char* { return self.vec.data; } fn destroy(self) { self.vec.free(); } fn forget(self) { self.vec.forget(); } fn append(self, other: String*) { // Remove null terminator before appending if (self.vec.len > 0) { self.vec.len = self.vec.len - 1; } var other_len = (*other).vec.len; for (var i = 0; i < other_len; i = i + 1) { self.vec.push((*other).vec.get(i)); } } fn add(self, other: String*) -> String { var new_s = String::from(self.c_str()); new_s.append(other); var d = new_s.vec.data; var l = new_s.vec.len; var c = new_s.vec.cap; new_s.forget(); return String { vec: Vec { data: d, len: l, cap: c } }; } fn eq(self, other: String*) -> bool { return strcmp(self.c_str(), (*other).c_str()) == 0; } fn length(self) -> usize { if (self.vec.len == 0) { return 0; } return self.vec.len - 1; } fn substring(self, start: usize, len: usize) -> String { if (start + len > self.length()) { panic("substring out of bounds"); } var v = Vec::new(); for (var i: usize = 0; i < len; i = i + 1) { v.push(self.vec.get(start + i)); } v.push(0); var d = v.data; var l = v.len; var c = v.cap; v.forget(); return String { vec: Vec { data: d, len: l, cap: c } }; } fn find(self, target: char) -> Option { var len = self.length(); for (var i: usize = 0; i < len; i = i + 1) { if (self.vec.get(i) == target) { return Option::Some(i); } } return Option::None(); } fn print(self) { printf("%s", self.c_str()); fflush(stdout); } fn println(self) { printf("%s\n", self.c_str()); } fn is_empty(self) -> bool { return self.length() == 0; } fn contains(self, target: char) -> bool { return self.find(target).is_some(); } fn starts_with(self, prefix: char*) -> bool { var plen = strlen(prefix); if plen > self.length() { return false; } return strncmp(self.c_str(), prefix, plen) == 0; } fn ends_with(self, suffix: char*) -> bool { var slen = strlen(suffix); var len = self.length(); if slen > len { return false; } var offset = (int)(len - slen); return strcmp(self.c_str() + offset, suffix) == 0; } fn free(self) { self.vec.free(); } }