Last active
December 2, 2017 19:52
-
-
Save leok7v/604c0b85fac5c1511c95b6c855b238fb to your computer and use it in GitHub Desktop.
simplest C++ heap and stack array I can think of
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#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; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
This is a good way (a bit too over complicated) to do it in C.
https://github.com/rxi/vec