147 lines
3.5 KiB
C++
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
|