Skip to content

Instantly share code, notes, and snippets.

@leok7v
Last active December 2, 2017 19:52
Show Gist options
  • Save leok7v/604c0b85fac5c1511c95b6c855b238fb to your computer and use it in GitHub Desktop.
Save leok7v/604c0b85fac5c1511c95b6c855b238fb to your computer and use it in GitHub Desktop.
simplest C++ heap and stack array I can think of
#include <memory.h>
#include <stdio.h>
#include <stdlib.h>
#define null ((void*)0)
#define mem_alloc malloc
#define mem_realloc realloc
#define mem_free free
#define assertion(e, fmt, ...) if (!(e)) { printf("assertion failed: %s ", #e); printf(fmt, __VA_ARGS__); __debugbreak(); }
#define assert(e) assertion(e, "");
// All array classes only supports pointers, atomic types and constructor-less plain data objects "t".
// By design: no copy constructor, not assignable, no shrinkig, double capacity realloc for heap.
// Arrays are "heavy" - absence of copy constructor and assign operator ensure
// that arrays are not passed by value as function parameters by mistake.
template <typename t>
struct heap_array {
heap_array() : array((t*)null), count(0), capacity(0) {}
~heap_array() { mem_free(array); }
t& operator[](int i) { assertion(0 <= i && i < count, "%d out of range [0..%d]", i, count); return array[i]; }
bool add(const t &e) { // returns true if added, false if out of memory
if (count == capacity) {
const int c = capacity == 0 ? 16 : capacity + capacity;
t* a = (t*)mem_realloc(array, c * sizeof(t));
if (a == null) { return false; }
array = a;
capacity = c;
}
array[count++] = e;
return true;
}
int indexof(const t &e) {
for (int i = 0; i < count; i++) { if (memcmp(&array[i], &e, sizeof(t)) == 0) { return i; } }
return -1;
}
void remove_at_index(int i) {
assertion(0 <= i && i < count, "%d out of range [0..%d]", i, count);
if (i < count - 1) { memcpy(&array[i], &array[i + 1], (count - 1 - i) * sizeof(t)); }
count--;
}
bool remove(const t &e) {
const int i = indexof(e);
if (i >= 0) { remove_at_index(i); }
return i >= 0;
}
int size() const { return count; }
private:
heap_array(const heap_array&) : array((t*)null), count(0), capacity(0) { assertion(false, "not implemented"); }
const heap_array& operator=(const heap_array&) { assertion(false, "not implemented"); return this; }
t* array;
int count;
int capacity;
};
template <typename t, int n>
struct stack_array {
stack_array() : count(0) { assertion(n > 0, "array size cannot be less then 1"); }
~stack_array() { }
t& operator[](int i) { assertion(0 <= i && i < count, "%d out of range [0..%d]", i, count); return array[i]; }
bool add(const t &e) { // returns true if added, false if array overflows
if (count == n) {
return false;
} else {
array[count++] = e;
return true;
}
}
int indexof(const t &e) {
for (int i = 0; i < count; i++) { if (memcmp(&array[i], &e, sizeof(t)) == 0) { return i; } }
return -1;
}
void remove_at_index(int i) {
assertion(0 <= i && i < count, "%d out of range [0..%d]", i, count);
if (i < count - 1) { memcpy(&array[i], &array[i + 1], (count - 1 - i) * sizeof(t)); }
count--;
}
bool remove(const t &e) {
const int i = indexof(e);
if (i >= 0) { remove_at_index(i); }
return i >= 0;
}
int size() const { return count; }
private:
stack_array(const stack_array&) : array((t*)null), count(0) { assertion(false, "not implemented"); }
const stack_array& operator=(const stack_array&) { assertion(false, "not implemented"); return this; }
t array[n];
int count;
};
template <typename t, int n>
struct array {
array() {}
t& operator[](int i) { assertion(0 <= i && i < size(), "%d out of range [0..%d]", i, size()); return i < n ? a[i] : b[i]; }
bool add(const t &e) { // returns true if added, false if array overflows
return size() < n ? a.add(e) : b.add(e);
}
int indexof(const t &e) {
const int i = a.indexof(e);
if (i >= 0) { return i; }
const int j = b.indexof(e);
return j < 0 ? j : j + n;
}
void remove_at_index(int i) {
if (size() <= n) {
a.remove_at_index(i);
} else if (i < n) {
a.remove_at_index(i);
a.add(b[0]);
b.remove_at_index(0);
} else {
b.remove_at_index(i - n);
}
}
bool remove(const t &e) {
const int i = indexof(e);
if (i >= 0) { remove_at_index(i); }
return i >= 0;
}
int size() const { return a.size() + b.size(); }
private:
array(const array&) { assertion(false, "not implemented"); }
const array& operator=(const array&) { assertion(false, "not implemented"); return this; }
stack_array<t,n> a;
heap_array<t> b;
};
int main(int argc, char* argv[]) {
{
const int n = 32;
stack_array<int, n> a;
for (int i = 0; i < n; i++) { assert(a.add(i)); }
assert(a.size() == n);
for (int i = 0; i < n; i++) { assert(a.indexof(i) == i); }
assert(!a.add(n));
assert(a.size() == n);
while (a.size() > 0) { int k = a.size(); a.remove_at_index(k / 2); assert(a.size() == k - 1); }
for (int i = 0; i < n; i++) { assert(a.add(i)); }
while (a.size() > 0) { int k = a.size(); a.remove(a[k / 2]); assert(a.size() == k - 1); }
}
for (int n = 32; n < 128; n += 32) {
heap_array<int> a;
for (int i = 0; i < n; i++) { assert(a.add(i)); }
assert(a.size() == n);
for (int i = 0; i < n; i++) { assert(a.indexof(i) == i); }
assert(a.add(n));
assert(a.size() == n + 1);
while (a.size() > 0) { int k = a.size(); a.remove_at_index(k / 2); assert(a.size() == k - 1); }
for (int i = 0; i < n; i++) { assert(a.add(i)); }
while (a.size() > 0) { int k = a.size(); a.remove(a[k / 2]); assert(a.size() == k - 1); }
}
{
const int n = 32;
array<int, n> a;
for (int i = 0; i < n; i++) { assert(a.add(i)); }
assert(a.size() == n);
for (int i = 0; i < n; i++) { assert(a.indexof(i) == i); }
for (int i = 0; i < n; i++) {
assert(a.add(n + i + 1));
assert(a.size() == n + i + 1);
}
while (a.size() > 0) { int k = a.size(); a.remove_at_index(k / 2); assert(a.size() == k - 1); }
for (int i = 0; i < n; i++) { assert(a.add(i)); }
while (a.size() > 0) { int k = a.size(); a.remove(a[k / 2]); assert(a.size() == k - 1); }
// Lines below must result in compile error:
// array<int, n> b = a;
// array<int, n> c(a);
// array<int, n> d; d = a;
}
{
typedef struct point_s { int x; int y; } point_t;
const int n = 32;
array<point_t, n> a;
for (int i = 0; i < n; i++) { point_t pt = {i, i}; assert(a.add(pt)); assert(a[i].x == pt.x && a[i].y == pt.y); }
assert(a.size() == n);
point_t absent = {n + 1, n + 1};
assert(a.indexof(absent) == -1);
for (int i = 0; i < n; i++) { point_t pt = {i, i}; assert(a.indexof(pt) == i); }
for (int i = 0; i < n; i++) {
point_t pt = {n + i + 1, n + i + 1};
assert(a.add(pt));
assert(a.size() == n + i + 1);
}
while (a.size() > 0) { int k = a.size(); a.remove_at_index(k / 2); assert(a.size() == k - 1); }
for (int i = 0; i < n; i++) { point_t pt = {i, i}; assert(a.add(pt)); assert(a[i].x == pt.x && a[i].y == pt.y); }
while (a.size() > 0) { int k = a.size(); a.remove(a[k / 2]); assert(a.size() == k - 1); }
}
return 0;
}
@leok7v
Copy link
Author

leok7v commented Dec 2, 2017

This is a good way (a bit too over complicated) to do it in C.
https://github.com/rxi/vec

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment