Skip to content

Instantly share code, notes, and snippets.

@kotlinsyntax
Created June 7, 2024 17:56
Show Gist options
  • Save kotlinsyntax/305da9f71c21e6d3b707d982ae8c3342 to your computer and use it in GitHub Desktop.
Save kotlinsyntax/305da9f71c21e6d3b707d982ae8c3342 to your computer and use it in GitHub Desktop.
//
// Created by kotlinsyntax on 6/7/2024.
//
#ifndef ARRAY_HPP
#define ARRAY_HPP
#include <cstdarg>
#include <cstdio>
#include <cstring>
#include <functional>
#include <memory>
template <typename T>
class Array {
std::size_t size;
std::size_t capacity;
T* data;
void resize() {
capacity *= 2;
data = static_cast<T*>(std::realloc(data, capacity * sizeof(T)));
if (!data) {
fprintf(stderr, "Failed to allocate memory while resizing array!");
throw std::bad_alloc();
}
}
public:
explicit Array(const int initialCapacity = 1)
: size(0), capacity(initialCapacity),
data(static_cast<T*>(std::malloc(capacity * sizeof(T))))
{
if (!data) {
fprintf(stderr, "Failed to allocate memory during array creation!");
throw std::bad_alloc();
}
}
~Array() {
for (std::size_t i = 0; i < size; ++i) {
data[i].~T(); // destruct elements before freeing mem
}
std::free(data);
}
void add(const T& value) {
if (size == capacity) {
resize();
}
new (data + size) T(value);
++size;
}
void clear() {
if (size == 0) return;
for (std::size_t i = 0; i < size; ++i) {
remove(i);
}
}
void addAll(const std::initializer_list<T>& values) {
for (const T& value : values) {
add(value);
}
}
void remove(const std::size_t index) {
if (index >= size) {
throw std::out_of_range("Index out of bounds!");
}
(data + index)->~T();
for (std::size_t i = index; i < size - 1; ++i) {
data[i] = data[i + 1];
}
--size;
}
void forEach(const std::function<void(const T&)>& lambda) const {
for (std::size_t i = 0; i < size; ++i) {
lambda(*(data + i));
}
}
template<typename U>
Array<U> map(const std::function<U(const T&)>& mapper) {
Array<U> result;
for (std::size_t i = 0; i < size; ++i) {
result.add(mapper(at(i)));
}
return result;
}
Array filter(const std::function<bool(const T&)>& predicate) const {
Array result;
for (std::size_t i = 0; i < size; ++i) {
if (predicate(*(data + i))) {
result.add(*(data + i));
}
}
return result;
}
T& at(const std::size_t index) {
if (index >= size) {
throw std::out_of_range("Tried to access index out of array bounds!");
}
return *(data + index);
}
[[nodiscard]] std::size_t length() const {
return size;
}
T& operator[](const std::size_t index) {
return at(index);
}
};
#endif //ARRAY_HPP
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment