diff --git a/core/containers/queue.h b/core/containers/queue.h new file mode 100644 index 0000000..b7f82a0 --- /dev/null +++ b/core/containers/queue.h @@ -0,0 +1,229 @@ +#ifndef QUEUE_H +#define QUEUE_H + +#include "core/error_macros.h" + +#include "vector.h" + +template +class Queue +{ +public: + void enqueue(const T &job); + T dequeue(); + const T &peek() const; + + bool is_empty() const; + bool is_full() const; + + int size() const; + int capacity() const; + void ensure_capacity(const int capacity); + void resize(const int s); + + void pack(); + + Queue(); + Queue(int prealloc); + Queue(int prealloc, int grow_by); + ~Queue(); + +private: + T* _data; + int _head; + int _tail; + + int _capacity; + int _grow_size; +}; + +template +void Queue::pack() +{ + if (_head == _tail) + { + _head = 0; + _tail = 0; + return; + } + + if (_head == 0 && _tail == _capacity) + { + resize(_capacity + _grow_size); + return; + } + + int j = 0; + + for (int i = _head; i < _tail; ++i) + { + _data[j++] = _data[i]; + } + + _head = 0; + _tail = j; + +} + +template +void Queue::enqueue(const T &job) +{ + if (_tail == _capacity) + { + pack(); + } + + _data[_tail++] = job; +} + +template +T Queue::dequeue() +{ + CRASH_COND(is_empty()); + + return _data[_head++]; +} + +template +const T &Queue::peek() const +{ + CRASH_COND(is_empty()); + + return _data[_head]; +} + +template +bool Queue::is_empty() const +{ + return _head == _tail; +} + +template +bool Queue::is_full() const +{ + return (_head == 0) && (_tail == _capacity); +} + +template +int Queue::size() const +{ + return _tail - _head; +} + +template +int Queue::capacity() const +{ + return _capacity; +} + +template +void Queue::ensure_capacity(const int capacity) +{ + if (_capacity < capacity) + { + resize(capacity); + } +} + +template +void Queue::resize(const int s) +{ + if (s == 0 && _data) + { + delete[] _data; + + _data = nullptr; + + _capacity = s; + + return; + } + + if (!_data) + { + _data = new T[s]; + _capacity = s; + return; + } + + if (is_empty()) + { + delete[] _data; + + _data = new T[s]; + + _capacity = s; + + return; + } + + if (!is_full()) + { + pack(); + } + + T* nd = new T[s]; + + int to = s > _tail ? _tail : s; + + for (int i = 0; i < to; ++i) + { + nd[i] = _data[i]; + } + + delete[] _data; + _data = nd; + _capacity = s; +} + +template +Queue::Queue() +{ + _data = nullptr; + + _head = 0; + _tail = 0; + + _capacity = 20; + _grow_size = 10; + resize(_capacity); +} + +template +Queue::Queue(int prealloc) +{ + _data = nullptr; + + _head = 0; + _tail = 0; + + _capacity = prealloc; + _grow_size = 10; + resize(_capacity); +} + +template +Queue::Queue(int prealloc, int grow_by) +{ + _data = nullptr; + + _head = 0; + _tail = 0; + + _capacity = prealloc; + _grow_size = grow_by; + resize(_capacity); +} + +template +Queue::~Queue() +{ + if (_data) + { + delete[] _data; + + _data = nullptr; + } +} + +#endif diff --git a/core/containers/vector.h b/core/containers/vector.h new file mode 100644 index 0000000..2c33ad0 --- /dev/null +++ b/core/containers/vector.h @@ -0,0 +1,227 @@ +#ifndef VECTOR_H +#define VECTOR_H + +#include "core/error_macros.h" + +template +class Vector { + +public: + void push_back(const T &element); + void pop_back(); + void remove(const int index); + void remove_keep_order(const int index); + void erase(const T &element); + void clear(); + bool empty() const; + T get(const int index); + const T &get(const int index) const; + void set(const int index, const T &value); + + int size() const; + int capacity() const; + void ensure_capacity(const int capacity); + void resize(const int s); + void append_array(const Vector &other); + int find(const T &val) const; + + int *dataw(); + const int *data() const; + + const T &operator[](const int index) const; + T &operator[](const int index); + + Vector(); + Vector(int prealloc); + Vector(int prealloc, int grow_by); + ~Vector(); + +private: + T *_data; + int _actual_size; + int _size; + int _grow_by; +}; + +template +void Vector::push_back(const T &element) { + ensure_capacity(_size + 1); + + _data[_size++] = element; +} + +template +void Vector::pop_back() { + if (_size == 0) { + return; + } + + --_size; +} + +template +void Vector::remove(const int index) { + _data[index] = _data[_size - 1]; + + --_size; +} + +template +void Vector::remove_keep_order(const int index) { + --_size; + + for (int i = index; i < _size; ++i) { + _data[i] = _data[i + 1]; + } +} + +template +void Vector::erase(const T &element) { + int index = find(element); + + if (index != -1) { + remove(index); + } +} + +template +void Vector::clear() { + _size = 0; +} + +template +bool Vector::empty() const { + return _size == 0; +} + +template +T Vector::get(const int index) { + return _data[index]; +} + +template +const T &Vector::get(const int index) const { + return _data[index]; +} + +template +void Vector::set(const int index, const T &value) { + _data[index] = value; +} + +template +int Vector::size() const { + return _size; +} + +template +int Vector::capacity() const { + return _actual_size; +} + +template +void Vector::ensure_capacity(const int capacity) { + if (capacity <= _actual_size) { + return; + } + + int tsize = capacity + _grow_by; + + T *nd = new T[tsize]; + + if (_data) { + for (int i = 0; i < _size; ++i) { + nd[i] = _data[i]; + } + + delete[] _data; + } + + _data = nd; + _actual_size = tsize; +} + +template +void Vector::resize(const int s) { + ensure_capacity(s); + + _size = s; +} + +template +void Vector::append_array(const Vector &other) { + ensure_capacity(_size + other._size); + + for (int i = 0; i < other._size; ++i) { + _data[_size++] = other._data[i]; + } +} + +template +int Vector::find(const T &val) const { + for (int i = 0; i < _size; ++i) { + if (_data[i] == val) { + return i; + } + } + + return -1; +} + +template +int *Vector::dataw() { + return _data; +} + +template +const int *Vector::data() const { + return _data; +} + +template +const T &Vector::operator[](const int index) const { + return _data[index]; +} + +template +T &Vector::operator[](const int index) { + return _data[index]; +} + +template +Vector::Vector() { + _data = nullptr; + _actual_size = 0; + _size = 0; + _grow_by = 100; +} + +template +Vector::Vector(int prealloc) { + _data = nullptr; + _actual_size = 0; + _size = 0; + _grow_by = 100; + + ensure_capacity(prealloc); +} + +template +Vector::Vector(int prealloc, int grow_by) { + _data = nullptr; + _actual_size = 0; + _size = 0; + _grow_by = grow_by; + + ensure_capacity(prealloc); +} + +template +Vector::~Vector() { + if (_data) { + delete[] _data; + _data = nullptr; + } +} + +#endif \ No newline at end of file diff --git a/core/string.cpp b/core/string.cpp new file mode 100644 index 0000000..7c6d074 --- /dev/null +++ b/core/string.cpp @@ -0,0 +1,637 @@ +#include "string.h" + +#include "error_macros.h" +#include +#include +#include + +void String::push_back(const char element) { + ensure_capacity(_size + 1); + + _data[_size++] = element; + _data[_size] = '\0'; +} + +void String::pop_back() { + if (_size == 0) { + return; + } + + --_size; + + _data[_size] = '\0'; +} + +void String::remove(const int index) { + _data[index] = _data[_size - 1]; + + --_size; + + _data[_size] = '\0'; +} + +void String::erase(const char element) { + int index = find(element); + + if (index != -1) { + remove(index); + } +} + +void String::clear() { + _size = 0; +} + +bool String::empty() const { + return _size == 0; +} + +char String::get(const int index) { + return _data[index]; +} + +const char String::get(const int index) const { + return _data[index]; +} + +void String::set(const int index, const char value) { + _data[index] = value; +} + +int String::size() const { + return _size; +} + +int String::capacity() const { + return _actual_size; +} + +void String::ensure_capacity(const int capacity) { + if (capacity < _actual_size) { + return; + } + + int tsize = capacity + _grow_by; + + char *nd = new char[tsize]; + + if (_data) { + for (int i = 0; i < _size; ++i) { + nd[i] = _data[i]; + } + + delete[] _data; + } + + _data = nd; + _actual_size = tsize; +} + +void String::resize(const int s) { + ensure_capacity(s + 1); // +1 for the null terminator + + _size = s; + + _data[_size] = '\0'; +} + +int String::find(const char val) const { + for (int i = 0; i < _size; ++i) { + if (_data[i] == val) { + return i; + } + } + + return -1; +} + +void String::get_substr(char *into_buf, const int start_index, const int len) { + ERR_FAIL_INDEX(start_index + len - 1, _size); + + int j = 0; + for (int i = start_index; i < start_index + len; ++i) { + into_buf[j++] = _data[i]; + } +} + +void String::get_substr_nt(char *into_buf, const int start_index, const int len) { + ERR_FAIL_INDEX(start_index + len - 1, _size); + + int j = 0; + for (int i = start_index; i < start_index + len; ++i) { + into_buf[j++] = _data[i]; + } + + into_buf[len + 1] = '\0'; +} + +uint8_t String::read_uint8_bytes_at(int &index, bool advance_index) { + ERR_FAIL_INDEX_V(index, _size, 0); + + if (advance_index) { + return static_cast(_data[index++]); + } else { + return static_cast(_data[index]); + } +} +uint16_t String::read_uint16_bytes_at(int &index, bool advance_index) { + ERR_FAIL_INDEX_V(index + 1, _size, 0); + + char carr[3]; + char* p = carr; + + //printf("%u %u\n", static_cast(p[0]), static_cast(p[1])); + + get_substr_nt(p, index, 2); + + const uint16_t *vp = static_cast((void *)p); + + if (advance_index) { + index += 2; + } + + return *vp; +} +uint32_t String::read_uint32_bytes_at(int &index, bool advance_index) { + ERR_FAIL_INDEX_V(index + 3, _size, 0); + + char carr[5]; + char* p = carr; + + get_substr_nt(p, index, 4); + + const uint32_t *vp = static_cast((void *)p); + + if (advance_index) { + index += 4; + } + + return *vp; +} +uint64_t String::read_uint64_bytes_at(int &index, bool advance_index) { + ERR_FAIL_INDEX_V(index + 7, _size, 0); + + char carr[9]; + char* p = carr; + + get_substr_nt(p, index, 8); + + const uint64_t *vp = static_cast((void *)p); + + if (advance_index) { + index += 8; + } + + return *vp; +} + +int8_t String::read_int8_bytes_at(int &index, bool advance_index) { + ERR_FAIL_INDEX_V(index, _size, 0); + + if (advance_index) { + return static_cast(_data[index++]); + } else { + return static_cast(_data[index]); + } +} +int16_t String::read_int16_bytes_at(int &index, bool advance_index) { + ERR_FAIL_INDEX_V(index + 1, _size, 0); + + char carr[3]; + char* p = carr; + + //printf("%u %u\n", static_cast(p[0]), static_cast(p[1])); + + get_substr_nt(p, index, 2); + + const int16_t *vp = static_cast((void *)p); + + if (advance_index) { + index += 2; + } + + return *vp; +} +int32_t String::read_int32_bytes_at(int &index, bool advance_index) { + ERR_FAIL_INDEX_V(index + 3, _size, 0); + + char carr[5]; + char* p = carr; + + get_substr_nt(p, index, 4); + + const int32_t *vp = static_cast((void *)p); + + if (advance_index) { + index += 4; + } + + return *vp; +} +int64_t String::read_int64_bytes_at(int &index, bool advance_index) { + ERR_FAIL_INDEX_V(index + 7, _size, 0); + + char carr[9]; + char* p = carr; + + get_substr_nt(p, index, 8); + + const int64_t *vp = static_cast((void *)p); + + if (advance_index) { + index += 8; + } + + return *vp; +} + +void String::append_uint8_bytes(const uint8_t val) { + ensure_capacity(_size + 1); + + _data[_size++] = val; + _data[_size] = '\0'; +} +void String::append_uint16_bytes(const uint16_t val) { + ensure_capacity(_size + 2); + + const char *vp = static_cast((void *)&val); + + //printf("a %u %u\n", static_cast(vp[0]), static_cast(vp[1])); + + memcpy(&_data[_size], vp, 2); + + _size += 2; + + _data[_size] = '\0'; +} +void String::append_uint32_bytes(const uint32_t val) { + ensure_capacity(_size + 4); + + const char *vp = static_cast((void *)&val); + + memcpy(&_data[_size], vp, 4); + + _size += 4; + + _data[_size] = '\0'; +} +void String::append_uint64_bytes(const uint64_t val) { + ensure_capacity(_size + 8); + + const char *vp = static_cast((void *)&val); + + memcpy(&_data[_size], vp, 8); + + _size += 8; + + _data[_size] = '\0'; +} + +void String::append_int8_bytes(const int8_t val) { + ensure_capacity(_size + 1); + + _data[_size++] = val; + _data[_size] = '\0'; +} +void String::append_int16_bytes(const int16_t val) { + ensure_capacity(_size + 2); + + const char *vp = static_cast((void *)&val); + + //printf("a %u %u\n", static_cast(vp[0]), static_cast(vp[1])); + + memcpy(&_data[_size], vp, 2); + + _size += 2; + + _data[_size] = '\0'; +} +void String::append_int32_bytes(const int32_t val) { + ensure_capacity(_size + 4); + + const char *vp = static_cast((void *)&val); + + memcpy(&_data[_size], vp, 4); + + _size += 4; + + _data[_size] = '\0'; +} +void String::append_int64_bytes(const int64_t val) { + ensure_capacity(_size + 8); + + const char *vp = static_cast((void *)&val); + + memcpy(&_data[_size], vp, 8); + + _size += 8; + + _data[_size] = '\0'; +} + +float String::read_float_bytes_at(int &index, bool advance_index) { + ERR_FAIL_INDEX_V(index + 3, _size, 0); + + char carr[5]; + char* p = carr; + + get_substr_nt(p, index, 4); + + const float *vp = static_cast((void *)p); + + if (advance_index) { + index += 4; + } + + return *vp; +} +void String::append_float_bytes(const float val) { + ensure_capacity(_size + 4); + + const char *vp = static_cast((void *)&val); + + memcpy(&_data[_size], vp, 4); + + _size += 4; + + _data[_size] = '\0'; +} + +double String::read_double_bytes_at(int &index, bool advance_index) { + ERR_FAIL_INDEX_V(index + 7, _size, 0); + + char carr[9]; + char* p = carr; + + get_substr_nt(p, index, 8); + + const double *vp = static_cast((void *)p); + + if (advance_index) { + index += 8; + } + + return *vp; +} +void String::append_double_bytes(const double val) { + ensure_capacity(_size + 8); + + const char *vp = static_cast((void *)&val); + + memcpy(&_data[_size], vp, 8); + + _size += 8; + + _data[_size] = '\0'; +} + +void String::append_str(const char* str) { + if (str == nullptr) { + return; + } + + int i = 0; + + while (str[i] != '\0') { + push_back(str[i++]); + } +} + +void String::append_str(const String &other) { + ensure_capacity(_size + other._size + 1); // +1 for the null terminator + + for (int i = 0; i < other._size; ++i) { + _data[_size++] = other._data[i]; + } + + _data[_size] = '\0'; +} + +float String::to_float() { + return atof(c_str()); +} + +double String::to_double() { + return atof(c_str()); +} + +int String::to_int() { + return atoi(c_str()); +} + +uint32_t String::to_uint() { + return static_cast(atoll(c_str())); +} + +char *String::c_str() { + return _data; +} + +const char *String::c_str() const { + return _data; +} + +char *String::dataw() { + return _data; +} + +const char *String::data() const { + return _data; +} + +const char String::operator[](const int index) const { + return _data[index]; +} + +char String::operator[](const int index) { + return _data[index]; +} + +String &String::operator+=(const String &b) { + ensure_capacity(_size + b._size + 1); // +1 for the null terminator + + for (int i = 0; i < b._size; ++i) { + _data[_size++] = b._data[i]; + } + + return *this; +} + +String &String::operator+=(const char chr) { + push_back(chr); + + return *this; +} + +String &String::operator+=(const char *p_c_str) { + int i = 0; + while (p_c_str[i] != '\0') { + push_back(p_c_str[i]); + ++i; + } + + return *this; +} + +String operator+(String lhs, const String &rhs) { + lhs += rhs; + + return lhs; +} + +String operator+(String lhs, const char *rhs) { + lhs += rhs; + + return lhs; +} + +String operator+(String lhs, const char rhs) { + lhs += rhs; + + return lhs; +} + +bool operator==(const String &a, const String &b) { + if (a._size != b._size) { + return false; + } + + for (int i = 0; i < a._size; ++i) { + if (a[i] != b[i]) { + return false; + } + } + + return true; +} + +bool operator!=(const String &a, const String &b) { + return !(a == b); +} + +bool operator==(const String &a, const char *b) { + int i = 0; + while (b[i] != '\0' && i < a._size) { + if (a[i] != b[i]) { + return false; + } + + ++i; + } + + if (i != a._size) { + return false; + } + + return true; +} + +bool operator!=(const String &a, const char *b) { + return !(a == b); +} + +bool operator==(const char *b, const String &a) { + int i = 0; + while (b[i] != '\0' && i < a._size) { + if (a[i] != b[i]) { + return false; + } + + ++i; + } + + if (i != a._size) { + return false; + } + + return true; +} + +bool operator!=(const char *b, const String &a) { + return !(a == b); +} + +String::String() { + _data = nullptr; + _actual_size = 0; + _size = 0; + _grow_by = 100; + + ensure_capacity(100); + + _data[0] = '\0'; +} + +String::String(const String &other) { + _data = nullptr; + _actual_size = 0; + _size = 0; + _grow_by = 100; + + //+1 for the null terminator in case its needed + ensure_capacity(other.size() + 1); + + for (int i = 0; i < other._size; ++i) { + _data[i] = other._data[i]; + } + + _data[other._size] = '\0'; +} + +String::String(const String &other, int grow_by) { + _data = nullptr; + _actual_size = 0; + _size = 0; + _grow_by = grow_by; + + //+1 for the null terminator in case its needed + ensure_capacity(other.size() + 1); + + for (int i = 0; i < other._size; ++i) { + _data[i] = other._data[i]; + } + + _data[_size] = '\0'; +} + +String::String(const char* p_c_str) { + _data = nullptr; + _actual_size = 0; + _size = 0; + _grow_by = 100; + + operator+=(p_c_str); +} + +String::String(const char* p_c_str, const int grow_by) { + _data = nullptr; + _actual_size = 0; + _size = 0; + _grow_by = grow_by; + + operator+=(p_c_str); +} + +String::String(int prealloc) { + _data = nullptr; + _actual_size = 0; + _size = 0; + _grow_by = 100; + + ensure_capacity(prealloc); +} + +String::String(int prealloc, int grow_by) { + _data = nullptr; + _actual_size = 0; + _size = 0; + _grow_by = grow_by; + + ensure_capacity(prealloc); +} + +String::~String() { + if (_data) { + delete[] _data; + } +} diff --git a/core/string.h b/core/string.h new file mode 100644 index 0000000..386e96e --- /dev/null +++ b/core/string.h @@ -0,0 +1,101 @@ +#ifndef STRING_H +#define STRING_H + +#include + +class String { +public: + void push_back(const char element); + void pop_back(); + void remove(const int index); + void erase(const char element); + void clear(); + bool empty() const; + char get(const int index); + const char get(const int index) const; + void set(const int index, const char value); + + int size() const; + int capacity() const; + void ensure_capacity(const int capacity); + void resize(const int s); + int find(const char val) const; + void get_substr(char *into_buf, const int start_index, const int len); + void get_substr_nt(char *into_buf, const int start_index, const int len); + + uint8_t read_uint8_bytes_at(int &index, bool advance_index = true); + uint16_t read_uint16_bytes_at(int &index, bool advance_index = true); + uint32_t read_uint32_bytes_at(int &index, bool advance_index = true); + uint64_t read_uint64_bytes_at(int &index, bool advance_index = true); + + int8_t read_int8_bytes_at(int &index, bool advance_index = true); + int16_t read_int16_bytes_at(int &index, bool advance_index = true); + int32_t read_int32_bytes_at(int &index, bool advance_index = true); + int64_t read_int64_bytes_at(int &index, bool advance_index = true); + + void append_uint8_bytes(const uint8_t val); + void append_uint16_bytes(const uint16_t val); + void append_uint32_bytes(const uint32_t val); + void append_uint64_bytes(const uint64_t val); + + void append_int8_bytes(const int8_t val); + void append_int16_bytes(const int16_t val); + void append_int32_bytes(const int32_t val); + void append_int64_bytes(const int64_t val); + + float read_float_bytes_at(int &index, bool advance_index = true); + void append_float_bytes(const float val); + double read_double_bytes_at(int &index, bool advance_index = true); + void append_double_bytes(const double val); + + void append_str(const char* str); + void append_str(const String &other); + + float to_float(); + double to_double(); + int to_int(); + uint32_t to_uint(); + + char *c_str(); + const char *c_str() const; + + char *dataw(); + const char *data() const; + + const char operator[](const int index) const; + char operator[](const int index); + + String &operator+=(const String &b); + String &operator+=(const char chr); + String &operator+=(const char *p_c_str); + + friend String operator+(String lhs, const String &rhs); + friend String operator+(String lhs, const char *rhs); + friend String operator+(String lhs, const char rhs); + + friend bool operator==(const String &a, const String &b); + friend bool operator!=(const String &a, const String &b); + + friend bool operator==(const String &a, const char *b); + friend bool operator!=(const String &a, const char *b); + + friend bool operator==(const char *b, const String &a); + friend bool operator!=(const char *b, const String &a); + + String(); + String(const String &other); + String(const String &other, const int grow_by); + String(const char* p_c_str); + String(const char* p_c_str, const int grow_by); + String(const int prealloc); + String(const int prealloc, const int grow_by); + ~String(); + +private: + char *_data; + int _actual_size; + int _size; + int _grow_by; +}; + +#endif