-
Notifications
You must be signed in to change notification settings - Fork 8
/
vector.oc
154 lines (128 loc) · 3.73 KB
/
vector.oc
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
//! A dynamic list of objects
import std::mem
//* A dynamic list of objects
struct Vector<T> {
data: &T
size: u32
capacity: u32
}
def Vector::new(capacity: u32 = 16): &Vector<T> {
let list = mem::alloc<Vector<T>>()
list.capacity = capacity
list.data = mem::alloc<T>(capacity)
list.size = 0
return list
}
//* Resizes the vector to a new capacity
def Vector::resize(&this, new_capacity: u32) {
if .capacity >= new_capacity then return
.data = mem::realloc<T>(.data , .capacity, new_capacity)
.capacity = new_capacity
}
[operator "+="]
//* Pushes an element to the end of the vector
def Vector::push(&this, value: T) {
if .size == .capacity {
.resize(.capacity * 2)
}
.data[.size] = value
.size += 1
}
//* Pushes an element to the front of the vector
//* This is an O(n) operation
def Vector::push_front(&this, value: T) {
if .size == .capacity {
.resize(.capacity * 2)
}
for let i = .size; i > 0; i -= 1 {
.data[i] = .data[i - 1]
}
.data[0] = value
.size += 1
}
//* Pops an element from the end of the vector and returns it
def Vector::pop(&this): T {
assert .size > 0, "Empty vector in Vector::pop"
.size -= 1
return .data[.size]
}
//* Pops an element from the end of the vector without checking if it's empty
def Vector::unchecked_pop(&this): T {
.size -= 1
return .data[.size]
}
//* Pops an element from the given index and returns it - O(n)
def Vector::pop_at(&this, i: u32): T {
assert .size > 0, "Empty vector in Vector::pop_at"
assert i < .size, "Out of bounds in Vector::pop_at"
let val = .data[i]
for let j = i; j < .size - 1; j += 1 {
.data[j] = .data[j + 1]
}
.size -= 1
return val
}
[operator "+="]
//* Appends the contents of another vector to this one
def Vector::extend(&this, other: &Vector<T>) {
for val in other.iter() {
.push(val)
}
}
//* Returns the last element of the vector
def Vector::back(&this, i: u32 = 0): T {
assert .size > 0, "Empty vector in Vector::back"
assert i < .size, "Out of bounds in Vector::back"
return .data[.size - i - 1]
}
//* Returns a pointer to the last element of the vector
def Vector::back_ptr(&this, i: u32 = 0): &T {
assert .size > 0, "Empty vector in Vector::back"
assert i < .size, "Out of bounds in Vector::back"
return &.data[.size - i - 1]
}
//* Returns a pointer to the last element of the vector
def Vector::at_ptr(&this, i: u32 = 0): &T {
assert i < .size, "Out of bounds in Vector::at"
return &.data[i]
}
[operator "[]"]
//* Returns the element at the given index
def Vector::at(&this, i: u32): T {
assert i < .size, "Out of bounds in Vector::at"
return .data[i]
}
[operator "[]="]
//* Returns the element at the given index
def Vector::set(&this, i: u32, val: T) {
assert i < .size, "Out of bounds in Vector::set"
.data[i] = val
}
//* Returns the element at the given index without checking if it's out of bounds
def Vector::unchecked_at(&this, i: u32): T => .data[i]
//* Clears the vector
//* This does not free the memory
def Vector::clear(&this) {
.size = 0
}
def Vector::is_empty(&this): bool => .size == 0
def Vector::iter(&this): Iterator<T> => Iterator<T>::make(this)
def Vector::free(&this) {
mem::free(.data)
mem::free(this)
}
//* Iterator for the vector
struct Iterator<T> {
vec: &Vector<T>
index: u32
}
def Iterator::make(vec: &Vector<T>): Iterator<T> => Iterator<T>(vec, 0)
def Iterator::has_value(&this): bool => .index < .vec.size
def Iterator::next(&this) {
assert .index < .vec.size, "Out of bounds in Iterator::next"
.index += 1
}
def Iterator::cur(&this): T {
assert .index < .vec.size, "Out of bounds in Iterator::current"
return .vec.data[.index]
}