libcx/src/include/cx/collections/vec.hpp

147 lines
3.5 KiB
C++

#ifndef _H_LIBCX_COLLECTIONS_VEC
#define _H_LIBCX_COLLECTIONS_VEC
#include <cx/result.hpp>
#include <cx/option.hpp>
#include <stdint.h>
#include <cx/stddef.hpp>
template <typename T>
class Vec {
private:
T* items = nullptr;
size_t count = 0;
size_t capacity = 0;
public:
Vec() {
this->reserve(16);
}
~Vec() = default;
Option<T*> nth(const size_t n) {
if (this->count <= n) {
return Option<T*>();
}
return Option<T*>(&this->items[n]);
}
Option<const T*> nth(const size_t n) const {
if (this->count <= n) {
return Option<const T*>();
}
return Option<const T*>(&this->items[n]);
}
Option<T> pop() {
if (this->count == 0) {
return Option<T>();
}
T&& popped = stl::move(this->items[--this->count]);
return Option<T>(static_cast<T&&>(popped));
}
void push(const T& val) {
if (this->capacity <= this->count) {
this->reserve(this->capacity * 2);
}
// printf("myello!!!!!\n");
this->items[this->count++] = stl::move(val);
}
void push(T&& val) {
if (this->capacity <= this->count) {
this->reserve(this->capacity * 2);
}
// printf("myello\n");
this->items[this->count++] = val;
}
Result<void, const char*> reserve(size_t new_cap) {
if (new_cap <= this->capacity) {
return Result<void, const char*>::err("New capacity is lower than current capacity");
}
T* new_data = (T*)(::operator new(sizeof(T) * new_cap));
for (size_t i = 0; i < this->count; ++i) {
new_data[i] = stl::move(this->items[i]);
}
for (size_t i = 0; i < this->count; ++i) {
this->items[i].~T();
}
::operator delete(this->items);
this->capacity = new_cap;
this->items = new_data;
return Result<void, const char*>::ok();
}
void clear() {
for (size_t i = 0; i < this->count; i++) {
this->items[i].~T();
}
::operator delete(this->items);
this->capacity = 0;
this->count = 0;
}
T* to_ptr() {
// Special case for cstr
// makes items[count] a null value so the cstr is valid
// TODO: Maybe make Vec::to_ptr only do this when T is char
if (this->count >= this->capacity) {
this->reserve(this->capacity * 2);
}
this->items[this->count] = (T)NULL;
return this->items;
}
static Vec<T> from_ptr(const T* ptr, size_t len) {
Vec<T> vec = Vec();
for (size_t i = 0; i < len; i++) {
vec.push(ptr[i]);
}
return vec;
}
size_t len() {
return this->count;
}
// IMPL: Clone
Vec clone() {
Vec nv = Vec();
nv = *this;
// nv.items = new T(*this->items);
// nv.count = this->count;
// nv.capacity = this->capacity;
return nv;
}
// IMPL: Buffer
uint8_t const* buf_get_raw_ptr() {
return (uint8_t const*)this->items;
}
// IMPL: Buffer
size_t buf_get_size() {
return this->count;
}
// IMPL: Buffer
void buf_push_byte(uint8_t byte) {
this->push(byte);
}
// IMPL: Buffer
void buf_append_bytes(uint8_t const* byte_ptr, size_t byte_count) {
for (size_t i = 0; i < byte_count; i++) {
this->buf_push_byte(byte_ptr[i]);
}
}
};
#endif // _H_LIBCX_COLLECTIONS_VEC