mirror of
https://github.com/krgamestudios/Toy.git
synced 2026-04-15 14:54:07 +10:00
Prepped for #160, fixed a stack-shrink bug
This commit is contained in:
@@ -21,26 +21,6 @@ TOY_API Toy_Array* Toy_resizeArray(Toy_Array* array, unsigned int capacity);
|
|||||||
#define TOY_ARRAY_EXPANSION_RATE 2
|
#define TOY_ARRAY_EXPANSION_RATE 2
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
//quick allocate
|
|
||||||
#ifndef TOY_ARRAY_ALLOCATE
|
|
||||||
#define TOY_ARRAY_ALLOCATE() Toy_resizeArray(NULL, TOY_ARRAY_INITIAL_CAPACITY)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
//quick free
|
|
||||||
#ifndef TOY_ARRAY_FREE
|
|
||||||
#define TOY_ARRAY_FREE(array) (array = Toy_resizeArray(array, 0))
|
|
||||||
#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
|
|
||||||
|
|
||||||
//quick push back
|
|
||||||
#ifndef TOY_ARRAY_PUSHBACK
|
|
||||||
#define TOY_ARRAY_PUSHBACK(array, value) (TOY_ARRAY_EXPAND(array), (array)->data[(array)->count++] = (value))
|
|
||||||
#endif
|
|
||||||
|
|
||||||
//TODO: array.getLength()
|
//TODO: array.getLength()
|
||||||
//TODO: array.pushFront(x)
|
//TODO: array.pushFront(x)
|
||||||
//TODO: array.pushBack(x)
|
//TODO: array.pushBack(x)
|
||||||
|
|||||||
@@ -31,7 +31,7 @@ void Toy_freeStack(Toy_Stack* stack) {
|
|||||||
|
|
||||||
void Toy_pushStack(Toy_Stack** stackHandle, Toy_Value value) {
|
void Toy_pushStack(Toy_Stack** stackHandle, Toy_Value value) {
|
||||||
//don't go overboard
|
//don't go overboard
|
||||||
if ((*stackHandle)->count >= TOY_STACK_OVERFLOW) {
|
if ((*stackHandle)->count >= TOY_STACK_OVERFLOW_THRESHOLD) {
|
||||||
fprintf(stderr, TOY_CC_ERROR "ERROR: Stack overflow\n" TOY_CC_RESET);
|
fprintf(stderr, TOY_CC_ERROR "ERROR: Stack overflow\n" TOY_CC_RESET);
|
||||||
exit(-1);
|
exit(-1);
|
||||||
}
|
}
|
||||||
@@ -72,9 +72,9 @@ Toy_Value Toy_popStack(Toy_Stack** stackHandle) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
//shrink if possible
|
//shrink if possible
|
||||||
if ((*stackHandle)->count > TOY_STACK_INITIAL_CAPACITY && (*stackHandle)->count < (*stackHandle)->capacity * TOY_STACK_CONTRACTION_THRESHOLD) {
|
if ((*stackHandle)->capacity > TOY_STACK_INITIAL_CAPACITY && (*stackHandle)->count <= (*stackHandle)->capacity / TOY_STACK_CONTRACTION_THRESHOLD) {
|
||||||
(*stackHandle)->capacity /= 2;
|
(*stackHandle)->capacity /= TOY_STACK_CONTRACTION_THRESHOLD;
|
||||||
unsigned int newCapacity = (*stackHandle)->capacity;
|
unsigned int newCapacity = (*stackHandle)->capacity; //cache for the msg
|
||||||
|
|
||||||
(*stackHandle) = realloc((*stackHandle), (*stackHandle)->capacity * sizeof(Toy_Value) + sizeof(Toy_Stack));
|
(*stackHandle) = realloc((*stackHandle), (*stackHandle)->capacity * sizeof(Toy_Value) + sizeof(Toy_Stack));
|
||||||
|
|
||||||
|
|||||||
@@ -26,10 +26,10 @@ TOY_API Toy_Value Toy_popStack(Toy_Stack** stackHandle);
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef TOY_STACK_CONTRACTION_THRESHOLD
|
#ifndef TOY_STACK_CONTRACTION_THRESHOLD
|
||||||
#define TOY_STACK_CONTRACTION_THRESHOLD (1 / 4)
|
#define TOY_STACK_CONTRACTION_THRESHOLD 4 // this integer means 'shrink when count drops below one-forth of capacity'
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
//prevent an infinite expansion, limited to 1MB
|
//prevent an infinite expansion, limited to 1MB
|
||||||
#ifndef TOY_STACK_OVERFLOW
|
#ifndef TOY_STACK_OVERFLOW_THRESHOLD
|
||||||
#define TOY_STACK_OVERFLOW (1024 * 1024 / sizeof(Toy_Value))
|
#define TOY_STACK_OVERFLOW_THRESHOLD (1024 * 1024 / sizeof(Toy_Value) - sizeof(Toy_Stack))
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -107,7 +107,7 @@ void Toy_insertTable(Toy_Table** tableHandle, Toy_Value key, Toy_Value value) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
//expand the capacity
|
//expand the capacity
|
||||||
if ((*tableHandle)->count > (*tableHandle)->capacity * TOY_TABLE_EXPANSION_THRESHOLD) {
|
if ((*tableHandle)->count >= (*tableHandle)->capacity * TOY_TABLE_EXPANSION_THRESHOLD) {
|
||||||
(*tableHandle) = Toy_private_adjustTableCapacity((*tableHandle), (*tableHandle)->capacity * TOY_TABLE_EXPANSION_RATE);
|
(*tableHandle) = Toy_private_adjustTableCapacity((*tableHandle), (*tableHandle)->capacity * TOY_TABLE_EXPANSION_RATE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -38,7 +38,7 @@ TOY_API Toy_Table* Toy_private_adjustTableCapacity(Toy_Table* oldTable, unsigned
|
|||||||
#define TOY_TABLE_EXPANSION_RATE 2
|
#define TOY_TABLE_EXPANSION_RATE 2
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
//expand when the contents passes a certain percentage of the capacity
|
//expand when the contents passes a certain percentage (80%) of the capacity
|
||||||
#ifndef TOY_TABLE_EXPANSION_THRESHOLD
|
#ifndef TOY_TABLE_EXPANSION_THRESHOLD
|
||||||
#define TOY_TABLE_EXPANSION_THRESHOLD 0.8
|
#define TOY_TABLE_EXPANSION_THRESHOLD 0.8f
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -139,7 +139,7 @@ void Toy_freeValue(Toy_Value value) {
|
|||||||
Toy_freeValue(ptr->data[i]);
|
Toy_freeValue(ptr->data[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
TOY_ARRAY_FREE(ptr);
|
Toy_resizeArray(ptr, 0);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -6,30 +6,30 @@
|
|||||||
int test_array(void) {
|
int test_array(void) {
|
||||||
//test allocation and free
|
//test allocation and free
|
||||||
{
|
{
|
||||||
Toy_Array* array = TOY_ARRAY_ALLOCATE();
|
Toy_Array* array = Toy_resizeArray(NULL, TOY_ARRAY_INITIAL_CAPACITY);
|
||||||
TOY_ARRAY_FREE(array);
|
array = Toy_resizeArray(array, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
//test initial data
|
//test initial data
|
||||||
{
|
{
|
||||||
Toy_Array* array = TOY_ARRAY_ALLOCATE();
|
Toy_Array* array = Toy_resizeArray(NULL, TOY_ARRAY_INITIAL_CAPACITY);
|
||||||
|
|
||||||
//check you can access the memory
|
//check you can access the memory
|
||||||
array->data[1] = TOY_VALUE_FROM_INTEGER(42);
|
array->data[1] = TOY_VALUE_FROM_INTEGER(42);
|
||||||
|
|
||||||
TOY_ARRAY_FREE(array);
|
array = Toy_resizeArray(array, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
//test multiple arrays (no overlaps or conflicts)
|
//test multiple arrays (no overlaps or conflicts)
|
||||||
{
|
{
|
||||||
Toy_Array* array1 = TOY_ARRAY_ALLOCATE();
|
Toy_Array* array1 = Toy_resizeArray(NULL, TOY_ARRAY_INITIAL_CAPACITY);
|
||||||
Toy_Array* array2 = TOY_ARRAY_ALLOCATE();
|
Toy_Array* array2 = Toy_resizeArray(NULL, TOY_ARRAY_INITIAL_CAPACITY);
|
||||||
|
|
||||||
array1->data[1] = TOY_VALUE_FROM_INTEGER(42);
|
array1->data[1] = TOY_VALUE_FROM_INTEGER(42);
|
||||||
array2->data[1] = TOY_VALUE_FROM_INTEGER(42);
|
array2->data[1] = TOY_VALUE_FROM_INTEGER(42);
|
||||||
|
|
||||||
TOY_ARRAY_FREE(array1);
|
Toy_resizeArray(array1, 0);
|
||||||
TOY_ARRAY_FREE(array2);
|
Toy_resizeArray(array2, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|||||||
@@ -83,11 +83,11 @@ int test_stack_basics(void) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
int test_stack_stress(void) {
|
int test_stack_stress(void) {
|
||||||
//stress the stack's contents
|
//stress the stack
|
||||||
{
|
{
|
||||||
Toy_Stack* stack = Toy_allocateStack();
|
Toy_Stack* stack = Toy_allocateStack();
|
||||||
|
|
||||||
//allocate 500 values
|
//push 500 values
|
||||||
for (int i = 0; i < 500; i++) {
|
for (int i = 0; i < 500; i++) {
|
||||||
Toy_pushStack(&stack, TOY_VALUE_FROM_INTEGER(i));
|
Toy_pushStack(&stack, TOY_VALUE_FROM_INTEGER(i));
|
||||||
}
|
}
|
||||||
@@ -98,11 +98,28 @@ int test_stack_stress(void) {
|
|||||||
stack->capacity != 512 ||
|
stack->capacity != 512 ||
|
||||||
stack->count != 500)
|
stack->count != 500)
|
||||||
{
|
{
|
||||||
fprintf(stderr, TOY_CC_ERROR "ERROR: failed to stress the Toy_Stack\n" TOY_CC_RESET);
|
fprintf(stderr, TOY_CC_ERROR "ERROR: failed to stress push the Toy_Stack\n" TOY_CC_RESET);
|
||||||
Toy_freeStack(stack);
|
Toy_freeStack(stack);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//pop each value
|
||||||
|
while(stack->count > 0) {
|
||||||
|
Toy_popStack(&stack); //ignore the results
|
||||||
|
}
|
||||||
|
|
||||||
|
//check if it worked
|
||||||
|
if (
|
||||||
|
stack == NULL ||
|
||||||
|
stack->capacity != TOY_STACK_INITIAL_CAPACITY || //reset to initial capacity
|
||||||
|
stack->count != 0)
|
||||||
|
{
|
||||||
|
fprintf(stderr, TOY_CC_ERROR "ERROR: failed to stress pop the Toy_Stack\n" TOY_CC_RESET);
|
||||||
|
Toy_freeStack(stack);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
//cleanup
|
||||||
Toy_freeStack(stack);
|
Toy_freeStack(stack);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -9,6 +9,10 @@
|
|||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
|
//util macros
|
||||||
|
#define TOY_ARRAY_EXPAND(array) (array = (array != NULL && (array)->count + 1 > (array)->capacity ? Toy_resizeArray(array, (array)->capacity * TOY_ARRAY_EXPANSION_RATE) : array))
|
||||||
|
#define TOY_ARRAY_PUSHBACK(array, value) (TOY_ARRAY_EXPAND(array), (array)->data[(array)->count++] = (value))
|
||||||
|
|
||||||
int test_value_creation(void) {
|
int test_value_creation(void) {
|
||||||
//test for the correct size
|
//test for the correct size
|
||||||
{
|
{
|
||||||
@@ -68,7 +72,7 @@ int test_value_creation(void) {
|
|||||||
//test creating arrays
|
//test creating arrays
|
||||||
{
|
{
|
||||||
//setup
|
//setup
|
||||||
Toy_Array* array = TOY_ARRAY_ALLOCATE();
|
Toy_Array* array = Toy_resizeArray(NULL, TOY_ARRAY_INITIAL_CAPACITY);
|
||||||
TOY_ARRAY_PUSHBACK(array, TOY_VALUE_FROM_INTEGER(42));
|
TOY_ARRAY_PUSHBACK(array, TOY_VALUE_FROM_INTEGER(42));
|
||||||
TOY_ARRAY_PUSHBACK(array, TOY_VALUE_FROM_INTEGER(69));
|
TOY_ARRAY_PUSHBACK(array, TOY_VALUE_FROM_INTEGER(69));
|
||||||
TOY_ARRAY_PUSHBACK(array, TOY_VALUE_FROM_INTEGER(8891));
|
TOY_ARRAY_PUSHBACK(array, TOY_VALUE_FROM_INTEGER(8891));
|
||||||
@@ -84,12 +88,12 @@ int test_value_creation(void) {
|
|||||||
)
|
)
|
||||||
{
|
{
|
||||||
fprintf(stderr, TOY_CC_ERROR "ERROR: 'array' value failed\n" TOY_CC_RESET);
|
fprintf(stderr, TOY_CC_ERROR "ERROR: 'array' value failed\n" TOY_CC_RESET);
|
||||||
TOY_ARRAY_FREE(array);
|
Toy_resizeArray(array, 0);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
//cleanup
|
//cleanup
|
||||||
TOY_ARRAY_FREE(array);
|
Toy_resizeArray(array, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
@@ -139,7 +143,7 @@ int test_value_copying(void) {
|
|||||||
//test copy arrays
|
//test copy arrays
|
||||||
{
|
{
|
||||||
//setup
|
//setup
|
||||||
Toy_Array* array = TOY_ARRAY_ALLOCATE();
|
Toy_Array* array = Toy_resizeArray(NULL, TOY_ARRAY_INITIAL_CAPACITY);
|
||||||
TOY_ARRAY_PUSHBACK(array, TOY_VALUE_FROM_INTEGER(42));
|
TOY_ARRAY_PUSHBACK(array, TOY_VALUE_FROM_INTEGER(42));
|
||||||
TOY_ARRAY_PUSHBACK(array, TOY_VALUE_FROM_INTEGER(69));
|
TOY_ARRAY_PUSHBACK(array, TOY_VALUE_FROM_INTEGER(69));
|
||||||
TOY_ARRAY_PUSHBACK(array, TOY_VALUE_FROM_INTEGER(8891));
|
TOY_ARRAY_PUSHBACK(array, TOY_VALUE_FROM_INTEGER(8891));
|
||||||
@@ -186,7 +190,7 @@ int test_value_hashing(void) {
|
|||||||
//skip float
|
//skip float
|
||||||
Toy_Value s = TOY_VALUE_FROM_STRING(Toy_createString(&bucket, "Hello world"));
|
Toy_Value s = TOY_VALUE_FROM_STRING(Toy_createString(&bucket, "Hello world"));
|
||||||
|
|
||||||
Toy_Array* array = TOY_ARRAY_ALLOCATE();
|
Toy_Array* array = Toy_resizeArray(NULL, TOY_ARRAY_INITIAL_CAPACITY);
|
||||||
TOY_ARRAY_PUSHBACK(array, TOY_VALUE_FROM_INTEGER(42));
|
TOY_ARRAY_PUSHBACK(array, TOY_VALUE_FROM_INTEGER(42));
|
||||||
TOY_ARRAY_PUSHBACK(array, TOY_VALUE_FROM_INTEGER(69));
|
TOY_ARRAY_PUSHBACK(array, TOY_VALUE_FROM_INTEGER(69));
|
||||||
TOY_ARRAY_PUSHBACK(array, TOY_VALUE_FROM_INTEGER(8891));
|
TOY_ARRAY_PUSHBACK(array, TOY_VALUE_FROM_INTEGER(8891));
|
||||||
@@ -202,13 +206,13 @@ int test_value_hashing(void) {
|
|||||||
)
|
)
|
||||||
{
|
{
|
||||||
fprintf(stderr, TOY_CC_ERROR "ERROR: Unexpected hash of a value\n" TOY_CC_RESET);
|
fprintf(stderr, TOY_CC_ERROR "ERROR: Unexpected hash of a value\n" TOY_CC_RESET);
|
||||||
TOY_ARRAY_FREE(array);
|
Toy_resizeArray(array, 0);
|
||||||
Toy_freeBucket(&bucket);
|
Toy_freeBucket(&bucket);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
//cleanup
|
//cleanup
|
||||||
TOY_ARRAY_FREE(array);
|
Toy_resizeArray(array, 0);
|
||||||
Toy_freeBucket(&bucket);
|
Toy_freeBucket(&bucket);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -259,14 +263,14 @@ int test_value_equality(void) {
|
|||||||
//again with arrays
|
//again with arrays
|
||||||
{
|
{
|
||||||
//setup
|
//setup
|
||||||
Toy_Array* array1 = TOY_ARRAY_ALLOCATE();
|
Toy_Array* array1 = Toy_resizeArray(NULL, TOY_ARRAY_INITIAL_CAPACITY);
|
||||||
TOY_ARRAY_PUSHBACK(array1, TOY_VALUE_FROM_INTEGER(42));
|
TOY_ARRAY_PUSHBACK(array1, TOY_VALUE_FROM_INTEGER(42));
|
||||||
TOY_ARRAY_PUSHBACK(array1, TOY_VALUE_FROM_INTEGER(69));
|
TOY_ARRAY_PUSHBACK(array1, TOY_VALUE_FROM_INTEGER(69));
|
||||||
TOY_ARRAY_PUSHBACK(array1, TOY_VALUE_FROM_INTEGER(8891));
|
TOY_ARRAY_PUSHBACK(array1, TOY_VALUE_FROM_INTEGER(8891));
|
||||||
|
|
||||||
Toy_Value value1 = TOY_VALUE_FROM_ARRAY(array1);
|
Toy_Value value1 = TOY_VALUE_FROM_ARRAY(array1);
|
||||||
|
|
||||||
Toy_Array* array2 = TOY_ARRAY_ALLOCATE();
|
Toy_Array* array2 = Toy_resizeArray(NULL, TOY_ARRAY_INITIAL_CAPACITY);
|
||||||
TOY_ARRAY_PUSHBACK(array2, TOY_VALUE_FROM_INTEGER(42));
|
TOY_ARRAY_PUSHBACK(array2, TOY_VALUE_FROM_INTEGER(42));
|
||||||
TOY_ARRAY_PUSHBACK(array2, TOY_VALUE_FROM_INTEGER(69));
|
TOY_ARRAY_PUSHBACK(array2, TOY_VALUE_FROM_INTEGER(69));
|
||||||
TOY_ARRAY_PUSHBACK(array2, TOY_VALUE_FROM_INTEGER(8891));
|
TOY_ARRAY_PUSHBACK(array2, TOY_VALUE_FROM_INTEGER(8891));
|
||||||
@@ -512,7 +516,7 @@ int test_value_stringify(void) {
|
|||||||
Toy_Bucket* bucket = Toy_allocateBucket(TOY_BUCKET_SMALL);
|
Toy_Bucket* bucket = Toy_allocateBucket(TOY_BUCKET_SMALL);
|
||||||
|
|
||||||
//setup
|
//setup
|
||||||
Toy_Array* array = TOY_ARRAY_ALLOCATE();
|
Toy_Array* array = Toy_resizeArray(NULL, TOY_ARRAY_INITIAL_CAPACITY);
|
||||||
TOY_ARRAY_PUSHBACK(array, TOY_VALUE_FROM_INTEGER(42));
|
TOY_ARRAY_PUSHBACK(array, TOY_VALUE_FROM_INTEGER(42));
|
||||||
TOY_ARRAY_PUSHBACK(array, TOY_VALUE_FROM_INTEGER(69));
|
TOY_ARRAY_PUSHBACK(array, TOY_VALUE_FROM_INTEGER(69));
|
||||||
TOY_ARRAY_PUSHBACK(array, TOY_VALUE_FROM_INTEGER(8891));
|
TOY_ARRAY_PUSHBACK(array, TOY_VALUE_FROM_INTEGER(8891));
|
||||||
@@ -525,14 +529,14 @@ int test_value_stringify(void) {
|
|||||||
{
|
{
|
||||||
fprintf(stderr, TOY_CC_ERROR "ERROR: stringify array '[42,69,8891]' failed\n" TOY_CC_RESET);
|
fprintf(stderr, TOY_CC_ERROR "ERROR: stringify array '[42,69,8891]' failed\n" TOY_CC_RESET);
|
||||||
free(buffer);
|
free(buffer);
|
||||||
TOY_ARRAY_FREE(array);
|
array = Toy_resizeArray(array, 0);
|
||||||
Toy_freeBucket(&bucket);
|
Toy_freeBucket(&bucket);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
//cleanup
|
//cleanup
|
||||||
free(buffer);
|
free(buffer);
|
||||||
TOY_ARRAY_FREE(array);
|
Toy_resizeArray(array, 0);
|
||||||
Toy_freeBucket(&bucket);
|
Toy_freeBucket(&bucket);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user