mirror of
https://github.com/krgamestudios/Toy.git
synced 2026-04-15 14:54:07 +10:00
Reworking structures for easy testing, read more
I was reworking bits of the containers to address issue #131, then realized that the table's tests depended on a specific initial size. I'm too buggered to finish it tonight, so I'll fix it tomorrow.
This commit is contained in:
@@ -11,3 +11,22 @@ typedef struct Toy_Array { //32 | 64 BITNESS
|
||||
} Toy_Array; //8 | 8
|
||||
|
||||
TOY_API Toy_Array* Toy_resizeArray(Toy_Array* array, unsigned int capacity);
|
||||
|
||||
//some useful sizes, could be swapped out as needed
|
||||
#ifndef TOY_ARRAY_INITIAL_CAPACITY
|
||||
#define TOY_ARRAY_INITIAL_CAPACITY 8
|
||||
#endif
|
||||
|
||||
#ifndef TOY_ARRAY_EXPANSION_RATE
|
||||
#define TOY_ARRAY_EXPANSION_RATE 2
|
||||
#endif
|
||||
|
||||
//quick allocate
|
||||
#ifndef TOY_ARRAY_ALLOCATE
|
||||
#define TOY_ARRAY_ALLOCATE() Toy_resizeArray(NULL, TOY_ARRAY_INITIAL_CAPACITY)
|
||||
#endif
|
||||
|
||||
//one line to expand the array
|
||||
#ifndef TOY_ARRAY_EXPAND
|
||||
#define TOY_ARRAY_EXPAND(array) (array = (array != NULL && (array)->count + 1 > (array)->capacity ? Toy_resizeArray(array, (array)-> capacity * TOY_ARRAY_EXPANSION_RATE) : array))
|
||||
#endif
|
||||
|
||||
@@ -20,13 +20,27 @@ TOY_API Toy_Bucket* Toy_allocateBucket(unsigned int capacity);
|
||||
TOY_API void* Toy_partitionBucket(Toy_Bucket** bucketHandle, unsigned int amount);
|
||||
TOY_API void Toy_freeBucket(Toy_Bucket** bucketHandle);
|
||||
|
||||
//some useful bucket sizes, could be swapped or ifdef'd as needed
|
||||
//some useful sizes, could be swapped out as needed
|
||||
#ifndef TOY_BUCKET_TINY
|
||||
#define TOY_BUCKET_TINY (1024 * 2)
|
||||
#endif
|
||||
|
||||
#ifndef TOY_BUCKET_SMALL
|
||||
#define TOY_BUCKET_SMALL (1024 * 4)
|
||||
#endif
|
||||
|
||||
#ifndef TOY_BUCKET_MEDIUM
|
||||
#define TOY_BUCKET_MEDIUM (1024 * 8)
|
||||
#endif
|
||||
|
||||
#ifndef TOY_BUCKET_LARGE
|
||||
#define TOY_BUCKET_LARGE (1024 * 16)
|
||||
#endif
|
||||
|
||||
#ifndef TOY_BUCKET_HUGE
|
||||
#define TOY_BUCKET_HUGE (1024 * 32)
|
||||
#endif
|
||||
|
||||
//sizeof(Toy_Bucket) is added internally, so reverse it here
|
||||
#ifndef TOY_BUCKET_IDEAL
|
||||
#define TOY_BUCKET_IDEAL (TOY_BUCKET_HUGE - sizeof(Toy_Bucket))
|
||||
|
||||
#endif
|
||||
|
||||
@@ -4,18 +4,15 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
//a good chunk of space - 'count' actually tracks the number of values
|
||||
#define MIN_CAPACITY 64
|
||||
|
||||
Toy_Stack* Toy_allocateStack() {
|
||||
Toy_Stack* stack = malloc(MIN_CAPACITY * sizeof(Toy_Value) + sizeof(Toy_Stack));
|
||||
Toy_Stack* stack = malloc(TOY_STACK_INITIAL_CAPACITY * sizeof(Toy_Value) + sizeof(Toy_Stack));
|
||||
|
||||
if (stack == NULL) {
|
||||
fprintf(stderr, TOY_CC_ERROR "ERROR: Failed to allocate a 'Toy_Stack' of %d capacity (%d space in memory)\n" TOY_CC_RESET, MIN_CAPACITY, (int)(MIN_CAPACITY * sizeof(Toy_Value) + sizeof(Toy_Stack)));
|
||||
fprintf(stderr, TOY_CC_ERROR "ERROR: Failed to allocate a 'Toy_Stack' of %d capacity (%d space in memory)\n" TOY_CC_RESET, TOY_STACK_INITIAL_CAPACITY, (int)(TOY_STACK_INITIAL_CAPACITY * sizeof(Toy_Value) + sizeof(Toy_Stack)));
|
||||
exit(1);
|
||||
}
|
||||
|
||||
stack->capacity = MIN_CAPACITY;
|
||||
stack->capacity = TOY_STACK_INITIAL_CAPACITY;
|
||||
stack->count = 0;
|
||||
|
||||
return stack;
|
||||
@@ -30,8 +27,8 @@ void Toy_freeStack(Toy_Stack* stack) {
|
||||
}
|
||||
|
||||
void Toy_pushStack(Toy_Stack** stackHandle, Toy_Value value) {
|
||||
//don't go overboard - limit to 1mb of capacity used
|
||||
if ((*stackHandle)->count >= 1024 * 1024 / sizeof(Toy_Value)) {
|
||||
//don't go overboard
|
||||
if ((*stackHandle)->count >= TOY_STACK_OVERFLOW) {
|
||||
fprintf(stderr, TOY_CC_ERROR "ERROR: Stack overflow\n" TOY_CC_RESET);
|
||||
exit(-1);
|
||||
}
|
||||
@@ -39,7 +36,7 @@ void Toy_pushStack(Toy_Stack** stackHandle, Toy_Value value) {
|
||||
//expand the capacity if needed
|
||||
if ((*stackHandle)->count + 1 > (*stackHandle)->capacity) {
|
||||
while ((*stackHandle)->count + 1 > (*stackHandle)->capacity) {
|
||||
(*stackHandle)->capacity = (*stackHandle)->capacity < MIN_CAPACITY ? MIN_CAPACITY : (*stackHandle)->capacity * 2;
|
||||
(*stackHandle)->capacity = (*stackHandle)->capacity < TOY_STACK_INITIAL_CAPACITY ? TOY_STACK_INITIAL_CAPACITY : (*stackHandle)->capacity * TOY_STACK_EXPANSION_RATE;
|
||||
}
|
||||
|
||||
unsigned int newCapacity = (*stackHandle)->capacity;
|
||||
@@ -72,7 +69,7 @@ Toy_Value Toy_popStack(Toy_Stack** stackHandle) {
|
||||
}
|
||||
|
||||
//shrink if possible
|
||||
if ((*stackHandle)->count > MIN_CAPACITY && (*stackHandle)->count < (*stackHandle)->capacity / 4) {
|
||||
if ((*stackHandle)->count > TOY_STACK_INITIAL_CAPACITY && (*stackHandle)->count < (*stackHandle)->capacity * TOY_STACK_CONTRACTION_RATE) {
|
||||
(*stackHandle)->capacity /= 2;
|
||||
unsigned int newCapacity = (*stackHandle)->capacity;
|
||||
|
||||
|
||||
@@ -16,3 +16,20 @@ TOY_API void Toy_pushStack(Toy_Stack** stackHandle, Toy_Value value);
|
||||
TOY_API Toy_Value Toy_peekStack(Toy_Stack** stackHandle);
|
||||
TOY_API Toy_Value Toy_popStack(Toy_Stack** stackHandle);
|
||||
|
||||
//some useful sizes, could be swapped out as needed
|
||||
#ifndef TOY_STACK_INITIAL_CAPACITY
|
||||
#define TOY_STACK_INITIAL_CAPACITY 8
|
||||
#endif
|
||||
|
||||
#ifndef TOY_STACK_EXPANSION_RATE
|
||||
#define TOY_STACK_EXPANSION_RATE 2
|
||||
#endif
|
||||
|
||||
#ifndef TOY_STACK_CONTRACTION_RATE
|
||||
#define TOY_STACK_CONTRACTION_RATE (1 / 4)
|
||||
#endif
|
||||
|
||||
//prevent an infinite expansion, limited to 1MB
|
||||
#ifndef TOY_STACK_OVERFLOW
|
||||
#define TOY_STACK_OVERFLOW (1024 * 1024 / sizeof(Toy_Value))
|
||||
#endif
|
||||
|
||||
@@ -6,9 +6,6 @@
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
//'count' actually tracks the number of values
|
||||
#define MIN_CAPACITY 16
|
||||
|
||||
//utils
|
||||
static void probeAndInsert(Toy_Table** tableHandle, Toy_Value key, Toy_Value value) {
|
||||
//make the entry
|
||||
@@ -88,7 +85,7 @@ Toy_Table* Toy_private_adjustTableCapacity(Toy_Table* oldTable, unsigned int new
|
||||
}
|
||||
|
||||
Toy_Table* Toy_allocateTable() {
|
||||
return Toy_private_adjustTableCapacity(NULL, MIN_CAPACITY);
|
||||
return Toy_private_adjustTableCapacity(NULL, TOY_TABLE_INITIAL_CAPACITY);
|
||||
}
|
||||
|
||||
void Toy_freeTable(Toy_Table* table) {
|
||||
@@ -103,8 +100,8 @@ void Toy_insertTable(Toy_Table** tableHandle, Toy_Value key, Toy_Value value) {
|
||||
}
|
||||
|
||||
//expand the capacity
|
||||
if ((*tableHandle)->count > (*tableHandle)->capacity * 0.8) {
|
||||
(*tableHandle) = Toy_private_adjustTableCapacity((*tableHandle), (*tableHandle)->capacity * 2);
|
||||
if ((*tableHandle)->count > (*tableHandle)->capacity * TOY_TABLE_EXPANSION_THRESHOLD) {
|
||||
(*tableHandle) = Toy_private_adjustTableCapacity((*tableHandle), (*tableHandle)->capacity * TOY_TABLE_EXPANSION_RATE);
|
||||
}
|
||||
|
||||
probeAndInsert(tableHandle, key, value);
|
||||
|
||||
@@ -27,3 +27,17 @@ TOY_API void Toy_removeTable(Toy_Table** tableHandle, Toy_Value key);
|
||||
|
||||
//NOTE: exposed to skip unnecessary allocations within Toy_Scope
|
||||
TOY_API Toy_Table* Toy_private_adjustTableCapacity(Toy_Table* oldTable, unsigned int newCapacity);
|
||||
|
||||
//some useful sizes, could be swapped out as needed
|
||||
#ifndef TOY_TABLE_INITIAL_CAPACITY
|
||||
#define TOY_TABLE_INITIAL_CAPACITY 8
|
||||
#endif
|
||||
|
||||
#ifndef TOY_TABLE_EXPANSION_RATE
|
||||
#define TOY_TABLE_EXPANSION_RATE 2
|
||||
#endif
|
||||
|
||||
//expand when the contents passes a certain percentage of the capacity
|
||||
#ifndef TOY_TABLE_EXPANSION_THRESHOLD
|
||||
#define TOY_TABLE_EXPANSION_THRESHOLD 0.8
|
||||
#endif
|
||||
|
||||
@@ -21,7 +21,7 @@ int test_scope_allocation() {
|
||||
if (scope == NULL ||
|
||||
scope->next != NULL ||
|
||||
scope->table == NULL ||
|
||||
scope->table->capacity != 16 ||
|
||||
scope->table->capacity != 8 ||
|
||||
scope->refCount != 1 ||
|
||||
|
||||
false)
|
||||
@@ -54,27 +54,27 @@ int test_scope_allocation() {
|
||||
scope == NULL ||
|
||||
scope->next == NULL ||
|
||||
scope->table == NULL ||
|
||||
scope->table->capacity != 16 ||
|
||||
scope->table->capacity != 8 ||
|
||||
scope->refCount != 1 ||
|
||||
|
||||
scope->next->next == NULL ||
|
||||
scope->next->table == NULL ||
|
||||
scope->next->table->capacity != 16 ||
|
||||
scope->next->table->capacity != 8 ||
|
||||
scope->next->refCount != 2 ||
|
||||
|
||||
scope->next->next->next == NULL ||
|
||||
scope->next->next->table == NULL ||
|
||||
scope->next->next->table->capacity != 16 ||
|
||||
scope->next->next->table->capacity != 8 ||
|
||||
scope->next->next->refCount != 3 ||
|
||||
|
||||
scope->next->next->next->next == NULL ||
|
||||
scope->next->next->next->table == NULL ||
|
||||
scope->next->next->next->table->capacity != 16 ||
|
||||
scope->next->next->next->table->capacity != 8 ||
|
||||
scope->next->next->next->refCount != 4 ||
|
||||
|
||||
scope->next->next->next->next->next != NULL ||
|
||||
scope->next->next->next->next->table == NULL ||
|
||||
scope->next->next->next->next->table->capacity != 16 ||
|
||||
scope->next->next->next->next->table->capacity != 8 ||
|
||||
scope->next->next->next->next->refCount != 5 || //refCount includes all ancestors
|
||||
|
||||
false)
|
||||
@@ -115,17 +115,17 @@ int test_scope_allocation() {
|
||||
scope == NULL ||
|
||||
scope->next == NULL ||
|
||||
scope->table == NULL ||
|
||||
scope->table->capacity != 16 ||
|
||||
scope->table->capacity != 8 ||
|
||||
scope->refCount != 1 ||
|
||||
|
||||
scope->next->next == NULL ||
|
||||
scope->next->table == NULL ||
|
||||
scope->next->table->capacity != 16 ||
|
||||
scope->next->table->capacity != 8 ||
|
||||
scope->next->refCount != 2 ||
|
||||
|
||||
scope->next->next->next != NULL ||
|
||||
scope->next->next->table == NULL ||
|
||||
scope->next->next->table->capacity != 16 ||
|
||||
scope->next->next->table->capacity != 8 ||
|
||||
scope->next->next->refCount != 3 ||
|
||||
|
||||
false)
|
||||
@@ -160,19 +160,19 @@ int test_scope_allocation() {
|
||||
scopeBase == NULL ||
|
||||
scopeBase->next != NULL ||
|
||||
scopeBase->table == NULL ||
|
||||
scopeBase->table->capacity != 16 ||
|
||||
scopeBase->table->capacity != 8 ||
|
||||
scopeBase->refCount != 3 ||
|
||||
|
||||
scopeA == NULL ||
|
||||
scopeA->next != scopeBase ||
|
||||
scopeA->table == NULL ||
|
||||
scopeA->table->capacity != 16 ||
|
||||
scopeA->table->capacity != 8 ||
|
||||
scopeA->refCount != 1 ||
|
||||
|
||||
scopeB == NULL ||
|
||||
scopeB->next != scopeBase ||
|
||||
scopeB->table == NULL ||
|
||||
scopeB->table->capacity != 16 ||
|
||||
scopeB->table->capacity != 8 ||
|
||||
scopeB->refCount != 1 ||
|
||||
|
||||
scopeA->next != scopeB->next || //double check
|
||||
@@ -212,20 +212,20 @@ int test_scope_allocation() {
|
||||
scopeA == NULL ||
|
||||
scopeA->next != NULL ||
|
||||
scopeA->table == NULL ||
|
||||
scopeA->table->capacity != 16 ||
|
||||
scopeA->table->capacity != 8 ||
|
||||
scopeA->refCount != 2 ||
|
||||
|
||||
//scopeB still exists in memory until scopeC is popped
|
||||
scopeB == NULL ||
|
||||
scopeB->next != scopeA ||
|
||||
scopeB->table == NULL ||
|
||||
scopeB->table->capacity != 16 ||
|
||||
scopeB->table->capacity != 8 ||
|
||||
scopeB->refCount != 1 ||
|
||||
|
||||
scopeC == NULL ||
|
||||
scopeC->next != scopeB ||
|
||||
scopeC->table == NULL ||
|
||||
scopeC->table->capacity != 16 ||
|
||||
scopeC->table->capacity != 8 ||
|
||||
scopeC->refCount != 1 ||
|
||||
|
||||
false)
|
||||
@@ -259,19 +259,19 @@ int test_scope_allocation() {
|
||||
scopeA == NULL ||
|
||||
scopeA->next != NULL ||
|
||||
scopeA->table == NULL ||
|
||||
scopeA->table->capacity != 16 ||
|
||||
scopeA->table->capacity != 8 ||
|
||||
scopeA->refCount != 3 ||
|
||||
|
||||
scopeB == NULL ||
|
||||
scopeB->next != scopeA ||
|
||||
scopeB->table == NULL ||
|
||||
scopeB->table->capacity != 16 ||
|
||||
scopeB->table->capacity != 8 ||
|
||||
scopeB->refCount != 1 ||
|
||||
|
||||
scopeB == NULL ||
|
||||
scopeB->next != scopeA ||
|
||||
scopeB->table == NULL ||
|
||||
scopeB->table->capacity != 16 ||
|
||||
scopeB->table->capacity != 8 ||
|
||||
scopeB->refCount != 1 ||
|
||||
|
||||
scopeB == scopeCopy ||
|
||||
@@ -335,7 +335,7 @@ int test_scope_elements() {
|
||||
if (scope == NULL ||
|
||||
scope->next != NULL ||
|
||||
scope->table == NULL ||
|
||||
scope->table->capacity != 16 ||
|
||||
scope->table->capacity != 8 ||
|
||||
scope->refCount != 1 ||
|
||||
|
||||
TOY_VALUE_IS_INTEGER(result) != true ||
|
||||
@@ -360,7 +360,7 @@ int test_scope_elements() {
|
||||
if (scope == NULL ||
|
||||
scope->next != NULL ||
|
||||
scope->table == NULL ||
|
||||
scope->table->capacity != 16 ||
|
||||
scope->table->capacity != 8 ||
|
||||
scope->refCount != 1 ||
|
||||
|
||||
TOY_VALUE_IS_FLOAT(resultTwo) != true ||
|
||||
|
||||
@@ -11,7 +11,7 @@ int test_stack_basics() {
|
||||
//check if it worked
|
||||
if (
|
||||
stack == NULL ||
|
||||
stack->capacity != 64 ||
|
||||
stack->capacity != 8 ||
|
||||
stack->count != 0)
|
||||
{
|
||||
fprintf(stderr, TOY_CC_ERROR "ERROR: failed to allocate Toy_Stack\n" TOY_CC_RESET);
|
||||
@@ -32,7 +32,7 @@ int test_stack_basics() {
|
||||
Toy_pushStack(&stack, TOY_VALUE_FROM_INTEGER(420));
|
||||
if (
|
||||
stack == NULL ||
|
||||
stack->capacity != 64 ||
|
||||
stack->capacity != 8 ||
|
||||
stack->count != 3)
|
||||
{
|
||||
fprintf(stderr, TOY_CC_ERROR "ERROR: failed to push Toy_Stack\n" TOY_CC_RESET);
|
||||
@@ -55,7 +55,7 @@ int test_stack_basics() {
|
||||
Toy_Value top2 = Toy_popStack(&stack);
|
||||
if (
|
||||
stack == NULL ||
|
||||
stack->capacity != 64 ||
|
||||
stack->capacity != 8 ||
|
||||
stack->count != 2 ||
|
||||
TOY_VALUE_IS_INTEGER(top2) != true ||
|
||||
TOY_VALUE_AS_INTEGER(top2) != 420)
|
||||
|
||||
@@ -36,7 +36,7 @@ int test_table_simple_insert_lookup_and_remove() {
|
||||
//insert
|
||||
Toy_insertTable(&table, key, value);
|
||||
if (table == NULL ||
|
||||
table->capacity != 16 ||
|
||||
table->capacity != 8 ||
|
||||
table->count != 1)
|
||||
{
|
||||
fprintf(stderr, TOY_CC_ERROR "ERROR: Failed to insert into a table\n" TOY_CC_RESET);
|
||||
@@ -49,7 +49,7 @@ int test_table_simple_insert_lookup_and_remove() {
|
||||
|
||||
//check lookup
|
||||
if (table == NULL ||
|
||||
table->capacity != 16 ||
|
||||
table->capacity != 8 ||
|
||||
table->count != 1 ||
|
||||
TOY_VALUE_AS_INTEGER(result) != 42)
|
||||
{
|
||||
@@ -63,7 +63,7 @@ int test_table_simple_insert_lookup_and_remove() {
|
||||
|
||||
//check remove
|
||||
if (table == NULL ||
|
||||
table->capacity != 16 ||
|
||||
table->capacity != 8 ||
|
||||
table->count != 0)
|
||||
{
|
||||
fprintf(stderr, TOY_CC_ERROR "ERROR: Failed to remove from a table\n" TOY_CC_RESET);
|
||||
@@ -97,7 +97,7 @@ int test_table_contents_no_expansion() {
|
||||
|
||||
//check the state
|
||||
if (table == NULL ||
|
||||
table->capacity != 16 ||
|
||||
table->capacity != 8 ||
|
||||
table->count != 1 ||
|
||||
|
||||
TEST_ENTRY_STATE(7, 1, 42, 0)
|
||||
@@ -124,7 +124,7 @@ int test_table_contents_no_expansion() {
|
||||
|
||||
//check the state
|
||||
if (table == NULL ||
|
||||
table->capacity != 16 ||
|
||||
table->capacity != 8 ||
|
||||
table->count != 3 ||
|
||||
|
||||
TEST_ENTRY_STATE(7, 1, 42, 0) ||
|
||||
@@ -154,7 +154,7 @@ int test_table_contents_no_expansion() {
|
||||
|
||||
//check the state
|
||||
if (table == NULL ||
|
||||
table->capacity != 16 ||
|
||||
table->capacity != 8 ||
|
||||
table->count != 4 ||
|
||||
|
||||
TEST_ENTRY_STATE(7, 1, 42, 0) ||
|
||||
@@ -184,7 +184,7 @@ int test_table_contents_no_expansion() {
|
||||
|
||||
//check the state
|
||||
if (table == NULL ||
|
||||
table->capacity != 16 ||
|
||||
table->capacity != 8 ||
|
||||
table->count != 3 ||
|
||||
|
||||
TEST_ENTRY_STATE(15, 17, 42, 0) ||
|
||||
@@ -216,7 +216,7 @@ int test_table_contents_no_expansion() {
|
||||
|
||||
//check the state
|
||||
if (table == NULL ||
|
||||
table->capacity != 16 ||
|
||||
table->capacity != 8 ||
|
||||
table->count != 3 ||
|
||||
|
||||
TOY_VALUE_IS_INTEGER(result) != true ||
|
||||
@@ -245,7 +245,7 @@ int test_table_contents_no_expansion() {
|
||||
|
||||
//check the state
|
||||
if (table == NULL ||
|
||||
table->capacity != 16 ||
|
||||
table->capacity != 8 ||
|
||||
table->count != 4 ||
|
||||
|
||||
TEST_ENTRY_STATE(15, 17, 42, 0) ||
|
||||
@@ -279,7 +279,7 @@ int test_table_contents_no_expansion() {
|
||||
|
||||
//check the state
|
||||
if (table == NULL ||
|
||||
table->capacity != 16 ||
|
||||
table->capacity != 8 ||
|
||||
table->count != 3 ||
|
||||
|
||||
TEST_ENTRY_STATE(15, 17, 42, 0) ||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
https://www.programiz.com/c-programming/online-compiler/
|
||||
//https://www.programiz.com/c-programming/online-compiler/
|
||||
#include <stdio.h>
|
||||
|
||||
static unsigned int hashUInt(unsigned int x) {
|
||||
@@ -11,7 +11,7 @@ static unsigned int hashUInt(unsigned int x) {
|
||||
int main() {
|
||||
//print the index/hash pairs
|
||||
for (unsigned int i = 0; i < 100; i++) {
|
||||
printf("{%u:%u}\n", i, hashUInt(i) % 16);
|
||||
printf("{%u:%u}\n", i, hashUInt(i));
|
||||
}
|
||||
|
||||
return 0;
|
||||
@@ -1,4 +1,4 @@
|
||||
https://www.programiz.com/c-programming/online-compiler/
|
||||
//https://www.programiz.com/c-programming/online-compiler/
|
||||
#include <stdio.h>
|
||||
|
||||
static unsigned int hashUInt(unsigned int x) {
|
||||
Reference in New Issue
Block a user