summaryrefslogtreecommitdiff
path: root/std/queue.zc
diff options
context:
space:
mode:
authorZuhaitz Méndez Fernández de Aránguiz <zuhaitz@debian>2026-01-23 01:54:51 +0000
committerZuhaitz Méndez Fernández de Aránguiz <zuhaitz@debian>2026-01-23 01:54:51 +0000
commit98623f2fdd63232edf0ebab1b9680cf4e33e6f10 (patch)
tree46e05b4953ea873bc5e52339a333f7911fc22867 /std/queue.zc
parent8cb7089b2eb09d40d9497cea40d088d94676a8c6 (diff)
More docs, and a few improvements for the standard library
Diffstat (limited to 'std/queue.zc')
-rw-r--r--std/queue.zc93
1 files changed, 66 insertions, 27 deletions
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;
}
}