updated vector to video version, will probably break a lot

This commit is contained in:
herbglitch 2024-08-27 03:23:29 -06:00
parent c1e60a6d2f
commit 93dc0fa053
12 changed files with 461 additions and 97 deletions

View file

@ -17,19 +17,27 @@ extern "C" {
extern int32_t arc_errno;
#ifdef ARC_DEBUG
#include <stdio.h>
//this is handy to override for if they user is doing terminal output and wants to change where logs are sent
extern FILE *arc_errno_log_file;
#ifndef ARC_DEBUG_LOG_STREAM_OVERRIDE
//this functin will be called on start, handy to set the log file to stdout if it is not overrided
void __attribute__ ((constructor)) ARC_Errno_SetDefaultStream(void);
#endif // !ARC_DEBUG_LOG_STREAM_OVERRIDE
#endif // !ARC_DEBUG
#ifdef __cplusplus
}
#endif
#ifdef ARC_DEBUG
# include <stdio.h>
# define ARC_DEBUG_LOG(ERR, STR, ...) printf("[ERROR %d] " STR "\n", ERR, __VA_ARGS__)
# define ARC_DEBUG_ERR(STR) printf("[ERROR %d] " STR "\n", arc_errno)
#define ARC_DEBUG_LOG_ERROR(STR) fprintf(arc_errno_log_file, "[ERROR %d] " STR "\n", arc_errno)
#define ARC_DEBUG_LOG_ERROR_WITH_VARIABLES(STR, ...) fprintf(arc_errno_log_file, "[ERROR %d] " STR "\n", arc_errno, __VA_ARGS__)
#else
# define ARC_DEBUG_LOG(ERR, STR, ...)
# define ARC_DEBUG_ERR(STR)
#endif
#define ARC_DEBUG_LOG_ERROR(STR)
#define ARC_DEBUG_LOG_ERROR_WITH_VARIABLES(STR, ...)
#endif // !ARC_DEBUG
#define ARC_ERR_CHECK(FUNC) FUNC; if(arc_errno){ ARC_DEBUG_LOG(arc_errno, "%s", #FUNC); return; }
#endif //ARC_STD_ERRNO_H_
#endif // !ARC_STD_ERRNO_H_

31
include/arc/std/lexer.h Normal file
View file

@ -0,0 +1,31 @@
#ifndef ARC_STD_LEXER_H_
#define ARC_STD_LEXER_H_
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief a lexer type
*/
typedef struct ARC_Lexer ARC_Lexer;
/**
* @brief
*
* @param[out] lexer
*/
void ARC_Lexer_Create(ARC_Lexer **lexer);
/**
* @brief
*
* @param[in] lexer ARC_Lexer to free
*/
void ARC_Lexer_Destroy(ARC_Lexer *lexer);
#ifdef __cplusplus
}
#endif
#endif // !ARC_STD_LEXER_H_

0
include/arc/std/parser.h Normal file
View file

View file

@ -5,6 +5,7 @@
extern "C" {
#endif
#include "arc/std/bool.h"
#include <stdint.h>
/**
@ -13,68 +14,86 @@ extern "C" {
typedef struct ARC_Vector ARC_Vector;
/**
* @brief data comparison function ptr
* @brief a callback that allows the user to define a way to check the data stored in a vector for a match
*
* @param a first data struct
* @param b second data struct
* @param[in] dataA the first data to check
* @param[in] dataB the second data to check
*
* @return 0 when a == b, TODO: return and ARC_Bool
* @return ARC_True when dataA == dataB, and ARC_False otherwise
*/
typedef int32_t (* ARC_Vector_CompareDataFn)(void *a, void *b);
typedef ARC_Bool (* ARC_Vector_CompareDataFn)(void *dataA, void *dataB);
/**
* @brief creates ARC_Vector type
* @brief creates an ARC_Vector which is an "expandable" array
*
* @param vector ARC_Vector to initialize
* @note for this basic implementation, the array will double in size every time the capacity is hit
* @note the array will also half in size when the array is only half filled
*
* @param[out] vector ARC_Vector to initialize
* @param[in] compareDataFn a callback that checks if data stored in the array matches,
* if set to NULL and ARC_Vector_Remove is called, the pointer addresses will be compared
*/
void ARC_Vector_Create(ARC_Vector **vector);
void ARC_Vector_Create(ARC_Vector **vector, ARC_Vector_CompareDataFn *compareDataFn);
/**
* @brief destroyes ARC_Vector type
* @brief destroys an ARC_Vector
*
* @note this will not free the items stored in the vector
* @note please make sure to clear and free the children before destroying an ARC_Vector
*
* @param[in] vector ARC_Vector to free
*/
void ARC_Vector_Destroy(ARC_Vector *vector);
/**
* @brief adds value to vector
* @brief adds an item to an ARC_Vector
*
* @param vector ARC_Vector to add to
* @param data data that is being added
* @note this will error if you add more than 4,294,967,295 items (the max value of an unsigned int 32)
*
* @param[in] vector ARC_Vector to add to
* @param[in] data data that is being added
*/
void ARC_Vector_Add(ARC_Vector *vector, void *data);
/**
* @brief remove from ARC_Vector
* @brief removes an item from a matching item in an ARC_Vector
*
* @param vector ARC_Vector to remove from
* @param data data that is being removed
* @param compare comparison callback to get check if data should be removed
* @note this function uses the ARC_Vector_CompareDataFn that the ARC_Vector was created with
* @note this function will not throw an error if there is no match
*
* @param[in] vector ARC_Vector to remove from
* @param[in] data matching data to remove
*/
void ARC_Vector_Remove(ARC_Vector *vector, void *data, ARC_Vector_CompareDataFn compare);
void ARC_Vector_Remove(ARC_Vector *vector, void *data);
/**
* @brief remove from ARC_Vector
* @brief removes an item from an ARC_Vector at an index
*
* @param vector ARC_Vector to remove from
* @param index index of data that is being removed
* @note this function will error if trying to remove an index that is outside the bounds of the ARC_Vector
*
* @param[in] vector ARC_Vector to remove from
* @param[in] index position of data to remove
*/
void ARC_Vector_RemoveIndex(ARC_Vector *vector, uint32_t index);
/**
* @brief gets size of vector
* @brief gets the current size of an ARC_Vector as an unsigned 32 bit integer
*
* @param vector ARC_Vector to get size from
* @param[in] vector ARC_Vector to get current size from
*
* @return the pointer of the vectors size, TODO: don't pass as a pointer
* @return the current size as a unsigned 32 bit integer
*/
uint32_t ARC_Vector_Size(ARC_Vector *vector);
uint32_t ARC_Vector_GetSize(ARC_Vector *vector);
/**
* @brief gets data from ARC_Vector at position index
* @brief gets an item from an ARC_Vector at a position index
*
* @param vector ARC_Vector to get data from
* @param index position of data in ARC_Vector
* @note this function will error if trying to get an index that is outside the bounds of the ARC_Vector
*
* @return pointer to data on success, NULL on fail
* @param[in] vector ARC_Vector to get data from
* @param[in] index position of data to get
*
* @return a void * item, or NULL on error
*/
void *ARC_Vector_Get(ARC_Vector *vector, uint32_t index);
@ -82,4 +101,4 @@ void *ARC_Vector_Get(ARC_Vector *vector, uint32_t index);
}
#endif
#endif //ARC_STD_VECTOR_H_
#endif // !ARC_STD_VECTOR_H_

View file

@ -1,3 +1,16 @@
#include "arc/std/errno.h"
#include <stdint.h>
int32_t arc_errno = 0;
#if ARC_DEBUG
#include <stdio.h>
FILE *arc_errno_log_file = NULL;
#ifndef ARC_DEBUG_LOG_STREAM_OVERRIDE
void ARC_Errno_SetDefaultStream(void){
arc_errno_log_file = stdout;
}
#endif
#endif

0
src/std/lexer.c Normal file
View file

0
src/std/parser.c Normal file
View file

View file

@ -1,103 +1,129 @@
#include "arc/std/vector.h"
#include "arc/std/bool.h"
#include "arc/std/errno.h"
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#include <stdlib.h>
struct ARC_Vector {
uint32_t currentSize, capacity;
uint32_t currentCapacity;
uint32_t currentSize;
void **data;
ARC_Vector_CompareDataFn compareDataFn;
};
void ARC_Vector_Create(ARC_Vector **vector){
//this is a private function used as the default check for removing data from a given pointer
ARC_Bool ARC_Vector_CompareDataDefaultFn(void *dataA, void *dataB){
if(dataA == dataB){
return ARC_True;
}
return ARC_False;
}
void ARC_Vector_Create(ARC_Vector **vector, ARC_Vector_CompareDataFn *compareDataFn){
//create the vector
*vector = (ARC_Vector *)malloc(sizeof(ARC_Vector));
(*vector)->currentSize = 0;
(*vector)->capacity = 1;
//initialize all the values stored in the vector
(*vector)->data = (void **)malloc(sizeof(void *));
(*vector)->currentCapacity = 1;
(*vector)->currentSize = 0;
//set a default for compareDataFn, then override it if it is passed in through parameters
(*vector)->compareDataFn = ARC_Vector_CompareDataDefaultFn;
if(compareDataFn != NULL){
(*vector)->compareDataFn = *compareDataFn;
}
}
void ARC_Vector_Destroy(ARC_Vector *vector){
//free everything stored in the vector
free(vector->data);
//free the vector
free(vector);
}
void ARC_Vector_Add(ARC_Vector *vector, void *data){
//check to see if the current size is the same as a max uint32_t and if so it will overflow so throw an error
if(vector->currentSize == ~((uint32_t)0)){
arc_errno = ARC_ERRNO_OVERFLOW;
ARC_DEBUG_LOG_ERROR("ARC_Vector_Add(vector, data), vector at max capacity tried adding another value");
return;
}
if(vector->currentSize == vector->capacity){
if(!vector->capacity){
++vector->capacity;
}
vector->capacity <<= 1;
//check if we are at the max of the current capacity
if(vector->currentSize == vector->currentCapacity){
//increase the current capacity by double
vector->currentCapacity <<= 1;
vector->data = (void *)realloc(vector->data, sizeof(void *) * vector->capacity);
//if for some reason the capacity is 0, we should set it to one so we do not error on realloc
if(vector->currentCapacity != 0){
vector->currentCapacity++;
}
//resize the vectors array and copy the contents at the same time
vector->data = (void **)realloc(vector->data, sizeof(void *) * vector->currentCapacity);
}
//add to the vectors array and increase its current size
vector->data[vector->currentSize] = data;
++(vector->currentSize);
vector->currentSize++;
}
//this function removes the redundant checking currentSize and index that would happen if ARC_Vector_Remove called ARC_Vector_RemoveIndex
void ARC_Vector_RemoveIndexNoCheck(ARC_Vector *vector, uint32_t index);
void ARC_Vector_Remove(ARC_Vector *vector, void *data){
//iterate through every item to check to see if it exists
for(uint32_t index = 0; index < vector->currentSize; index++){
//keep the code cleaner by pulling the current index data into a temp variable
void *dataB = vector->data[index];
void ARC_Vector_Remove(ARC_Vector *vector, void *data, ARC_Vector_CompareDataFn compare){
if(!vector->currentSize){
arc_errno = ARC_ERRNO_DATA;
return;
}
for(uint32_t i = 0; i < vector->currentSize; i++){
if(!compare(data, vector->data[i])){
ARC_Vector_RemoveIndexNoCheck(vector, i);
return;
//check if the data matches, and if so remove by index
if(vector->compareDataFn(data, dataB) == ARC_True){
ARC_Vector_RemoveIndex(vector, index);
}
}
//no matching data found in compare function
arc_errno = ARC_ERRNO_DATA;
}
void ARC_Vector_RemoveIndex(ARC_Vector *vector, uint32_t index){
if(!vector->currentSize || index >= vector->currentSize){
//check to make sure the given index is in bounds of the vector
if(index >= vector->currentSize){
arc_errno = ARC_ERRNO_DATA;
ARC_DEBUG_LOG_ERROR("ARC_Vector_Add(vector, data), vector at max capacity tried adding another value");
return;
}
ARC_Vector_RemoveIndexNoCheck(vector, index);
//we will be using index to iterate as we will not use it again, so we can skip the first part of the for loop
for(; index + 1 < vector->currentSize; index++){
//override the data from index to the end by shifting it back one
vector->data[index] = vector->data[index + 1];
}
void ARC_Vector_RemoveIndexNoCheck(ARC_Vector *vector, uint32_t index){
for(uint32_t i = index; i <= vector->currentSize; i++){
if(i + 1 >= vector->currentSize - 1){
break;
}
vector->data[i] = vector->data[i + 1];
}
//we have removed the item so we can decrease the current size
vector->currentSize--;
--vector->currentSize;
if(vector->currentSize != vector->capacity >> 1){
//if the current size is half the current capacity or the current capacity is at the smallest limit, we do not need to do anything else
if(vector->currentSize != vector->currentCapacity >> 1 || vector->currentCapacity == 1){
return;
}
vector->capacity >>= 1;
if(vector->capacity <= 0){
vector->capacity = 1;
//half the capacity and copy it into a smaller array
vector->currentCapacity >>= 1;
vector->data = (void **)realloc(vector->data, sizeof(void *) * vector->currentCapacity);
}
vector->data = (void *)realloc(vector->data, sizeof(void *) * vector->capacity);
}
uint32_t ARC_Vector_Size(ARC_Vector *vector){
uint32_t ARC_Vector_GetSize(ARC_Vector *vector){
return vector->currentSize;
}
void *ARC_Vector_Get(ARC_Vector *vector, uint32_t index){
//check to make sure the given index is in bounds of the vector
if(index >= vector->currentSize){
arc_errno = ARC_ERRNO_DATA;
ARC_DEBUG_LOG_ERROR_WITH_VARIABLES("ARC_Vector_Get(vector, %u), null value as the index was out of bounds", index);
return NULL;
}

48
temp.txt Normal file
View file

@ -0,0 +1,48 @@
<configLanguage> -> <configLanguageBody> EOF
<configLanguageBody> -> <configPreDefines> <configComment> <configGroup> <configFunction> <configFunctionCall> <configVariableLine> <configLanguageBody> | LAMBDA
<configPreDefines> -> <preDefines> | LAMBDA
<configComment> -> <comment> | LAMBDA
<configGroup> -> <group> | LAMBDA
<configFunction> -> <function> | LAMBDA
<configFunctionCall> -> <functionCall> | LAMBDA
<configVariableLine> -> <variableLine> | LAMBDA
<preDefines> -> HASH <preDefineRule>
<preDefineRule> -> <preDefineInclude> | <preDefineExclude>
<comment> -> <commentSingleLine> | <commentMultiLine>
<commentSingleLine> -> SLASH SLASH <commentContents> | NEWLINE
<commentMultiLine> -> SLASH ASTERISK <commentContents> ASTERISK SLASH
<commentContents> -> STRING <commentContents> | LAMBDA
<group> -> <groupName> LEFT_CURLY_BRACE <configLanguage> RIGHT_CURLY_BRACE
<groupRef> -> <parameter> COLON COLON <parameter>
<function> -> <parameter> LEFT_PAREN <parameterList> RIGHT_PAREN LEFT_CURLY_BRACE <configLanguage> RIGHT_CURLY_BRACE
<parameterList> -> <type> <parameter> <parameterListItem> | LAMBDA
<parameterListItem> -> COMMA <type> <parameter> <parameterListItem> | LAMBDA
<variableLine> -> <variableCreate> <variable> EQUALS <variableData> SEMICOLON
<variableCreate> -> <type> | LAMBDA
<variableData> -> <equation> | <variableOption>
<equation> -> <equationFormula> | <encapsulation>
<equationFormula> -> <equationData> SYMBOL <equationData>
<equationData> -> LEFT_PAREN <equation> RIGHT_PAREN | <data>
<variableOption> -> <data> | <dataList>
<data> -> <variable> | <value>
<dataList> -> LEFT_CURLY_BRACE <variableData> <dataListItem> RIGHT_CURLY_BRACE SEMICOLON
<dataListItem> -> COMMA <variableData> <dataListItem> | LAMBDA
<functionCall> -> <functionName> LEFT_PAREN <valueList> <RIGHT_PAREN> SEMICOLON
<valueList> -> <value> <valueListItem>
<valueListItem> -> COMMA <value> <valueListItem>
<groupName> -> <variable>
<functionName> -> <variable>
<type> -> <variable>
<value> -> <variable> | NUM
<variable> -> CHAR <variableName>
<variableName> -> <charOrNum> <variableName> | LAMBDA
<charOrNum> -> CHAR | NUM

153
tests/src/vector.c Normal file
View file

@ -0,0 +1,153 @@
#include "../test.h"
#include "arc/std/bool.h"
#include "arc/std/errno.h"
#include "arc/std/vector.h"
#include <stdint.h>
ARC_Bool TEST_Vector_CompareDataFn(void *dataA, void *dataB){
if(*(int32_t *)dataA == *(int32_t *)dataB){
return ARC_True;
}
return ARC_False;
}
ARC_TEST(Vector_Add_RemoveIndex_Get){
ARC_Vector *vector;
ARC_Vector_Create(&vector, NULL);
int32_t val0 = 0;
int32_t val1 = 1;
int32_t val2 = 2;
int32_t val3 = 3;
int32_t val4 = 4;
ARC_Vector_Add(vector, &val0);
ARC_Vector_Add(vector, &val1);
ARC_Vector_Add(vector, &val2);
ARC_Vector_Add(vector, &val3);
ARC_Vector_Add(vector, &val4);
ARC_CHECK(0 == *(int32_t *)ARC_Vector_Get(vector, 0));
ARC_CHECK(1 == *(int32_t *)ARC_Vector_Get(vector, 1));
ARC_CHECK(2 == *(int32_t *)ARC_Vector_Get(vector, 2));
ARC_CHECK(3 == *(int32_t *)ARC_Vector_Get(vector, 3));
ARC_CHECK(4 == *(int32_t *)ARC_Vector_Get(vector, 4));
ARC_Vector_RemoveIndex(vector, 0);
ARC_CHECK(1 == *(int32_t *)ARC_Vector_Get(vector, 0));
ARC_CHECK(2 == *(int32_t *)ARC_Vector_Get(vector, 1));
ARC_CHECK(3 == *(int32_t *)ARC_Vector_Get(vector, 2));
ARC_CHECK(4 == *(int32_t *)ARC_Vector_Get(vector, 3));
ARC_Vector_RemoveIndex(vector, 3);
ARC_CHECK(1 == *(int32_t *)ARC_Vector_Get(vector, 0));
ARC_CHECK(2 == *(int32_t *)ARC_Vector_Get(vector, 1));
ARC_CHECK(3 == *(int32_t *)ARC_Vector_Get(vector, 2));
ARC_Vector_RemoveIndex(vector, 1);
ARC_CHECK(1 == *(int32_t *)ARC_Vector_Get(vector, 0));
ARC_CHECK(3 == *(int32_t *)ARC_Vector_Get(vector, 1));
ARC_Vector_RemoveIndex(vector, 1);
ARC_CHECK(1 == *(int32_t *)ARC_Vector_Get(vector, 0));
ARC_Vector_RemoveIndex(vector, 0);
ARC_Vector_Destroy(vector);
}
ARC_TEST(Vector_Add_Remove_Get){
ARC_Vector *vector;
ARC_Vector_CompareDataFn testCompareDataFn = TEST_Vector_CompareDataFn;
ARC_Vector_Create(&vector, &testCompareDataFn);
int32_t val0 = 0;
int32_t val1 = 1;
int32_t val2 = 2;
int32_t val3 = 3;
int32_t val4 = 4;
ARC_Vector_Add(vector, &val0);
ARC_Vector_Add(vector, &val1);
ARC_Vector_Add(vector, &val2);
ARC_Vector_Add(vector, &val3);
ARC_Vector_Add(vector, &val4);
ARC_CHECK(0 == *(int32_t *)ARC_Vector_Get(vector, 0));
ARC_CHECK(1 == *(int32_t *)ARC_Vector_Get(vector, 1));
ARC_CHECK(2 == *(int32_t *)ARC_Vector_Get(vector, 2));
ARC_CHECK(3 == *(int32_t *)ARC_Vector_Get(vector, 3));
ARC_CHECK(4 == *(int32_t *)ARC_Vector_Get(vector, 4));
ARC_Vector_Remove(vector, &val0);
ARC_CHECK(1 == *(int32_t *)ARC_Vector_Get(vector, 0));
ARC_CHECK(2 == *(int32_t *)ARC_Vector_Get(vector, 1));
ARC_CHECK(3 == *(int32_t *)ARC_Vector_Get(vector, 2));
ARC_CHECK(4 == *(int32_t *)ARC_Vector_Get(vector, 3));
ARC_Vector_Remove(vector, &val4);
ARC_CHECK(1 == *(int32_t *)ARC_Vector_Get(vector, 0));
ARC_CHECK(2 == *(int32_t *)ARC_Vector_Get(vector, 1));
ARC_CHECK(3 == *(int32_t *)ARC_Vector_Get(vector, 2));
ARC_Vector_Remove(vector, &val2);
ARC_CHECK(1 == *(int32_t *)ARC_Vector_Get(vector, 0));
ARC_CHECK(3 == *(int32_t *)ARC_Vector_Get(vector, 1));
ARC_Vector_Remove(vector, &val1);
ARC_CHECK(3 == *(int32_t *)ARC_Vector_Get(vector, 0));
ARC_Vector_Remove(vector, &val3);
ARC_Vector_Destroy(vector);
}
ARC_TEST(Vector_Add_RemoveIndex_GetSize){
ARC_Vector *vector;
ARC_Vector_Create(&vector, NULL);
int32_t val0 = 0;
int32_t val1 = 1;
int32_t val2 = 2;
int32_t val3 = 3;
int32_t val4 = 4;
ARC_Vector_Add(vector, &val0);
ARC_Vector_Add(vector, &val1);
ARC_Vector_Add(vector, &val2);
ARC_Vector_Add(vector, &val3);
ARC_Vector_Add(vector, &val4);
ARC_CHECK(5 == ARC_Vector_GetSize(vector));
ARC_Vector_RemoveIndex(vector, 0);
ARC_CHECK(4 == ARC_Vector_GetSize(vector));
ARC_Vector_RemoveIndex(vector, 0);
ARC_CHECK(3 == ARC_Vector_GetSize(vector));
ARC_Vector_RemoveIndex(vector, 0);
ARC_CHECK(2 == ARC_Vector_GetSize(vector));
ARC_Vector_RemoveIndex(vector, 0);
ARC_CHECK(1 == ARC_Vector_GetSize(vector));
ARC_Vector_RemoveIndex(vector, 0);
ARC_CHECK(0 == ARC_Vector_GetSize(vector));
ARC_Vector_Destroy(vector);
}
ARC_TEST(Vector_Add_RemoveIndex_Get_Try_Out_Of_Bounds){
ARC_Vector *vector;
ARC_Vector_Create(&vector, NULL);
int32_t val0 = 0;
ARC_Vector_Add(vector, &val0);
ARC_CHECK(NULL == ARC_Vector_Get(vector, 1));
arc_errno = 0;
ARC_Vector_RemoveIndex(vector, 0);
ARC_Vector_Destroy(vector);
}

22
tests/test.c Normal file
View file

@ -0,0 +1,22 @@
#include "test.h"
#include "arc/std/errno.h"
#include <stdio.h>
#include <stdlib.h>
uint32_t *temp_arc_test_num_checks_run__ARC_TEST__ = NULL;
uint32_t *temp_arc_test_num_checks_passed__ARC_TEST__ = NULL;
void ARC_Test_SetErrnoStream(void){
arc_errno_log_file = fopen("tests/test_error_out.txt", "w");
}
void ARC_Test_UnsetErrnoStream(void){
fclose(arc_errno_log_file);
}
#ifndef ARC_TEST_NO_MAIN
int main(void){
return 0;
}
#endif

44
tests/test.h Normal file
View file

@ -0,0 +1,44 @@
#ifndef ARC_TEST_H_
#define ARC_TEST_H_
#ifdef __cplusplus
extern "C" {
#endif
#include <stdint.h>
#include <stdio.h>
extern uint32_t *temp_arc_test_num_checks_run__ARC_TEST__;
extern uint32_t *temp_arc_test_num_checks_passed__ARC_TEST__;
void ARC_Test_SetErrnoStream(void) __attribute__ ((constructor));
void ARC_Test_UnsetErrnoStream(void) __attribute__ ((destructor));
#define ARC_TEST_START_MESSAGE(MESSAGE) void ARC_TEST_START_MESSAGE__ ## MESSAGE(void) __attribute__ ((constructor));\
uint32_t arc_test_num_checks_run__ARC_TEST__ ## MESSAGE = 0;\
uint32_t arc_test_num_checks_passed__ARC_TEST__ ## MESSAGE = 0;\
void ARC_TEST_START_MESSAGE__ ## MESSAGE(void){\
printf("[ARC TEST] Running: %s\n", #MESSAGE);\
temp_arc_test_num_checks_run__ARC_TEST__ = &arc_test_num_checks_run__ARC_TEST__ ## MESSAGE; \
temp_arc_test_num_checks_passed__ARC_TEST__ = &arc_test_num_checks_passed__ARC_TEST__ ## MESSAGE; \
}
#define ARC_TEST_END_MESSAGE(MESSAGE) void ARC_TEST_END_MESSAGE__ ## MESSAGE(void) __attribute__ ((destructor));\
void ARC_TEST_END_MESSAGE__ ## MESSAGE(void){\
printf("[ARC TEST] RUN: %4u, PASSED: %4u, FAILED: %4u, Completed: %s\n", arc_test_num_checks_run__ARC_TEST__ ## MESSAGE, arc_test_num_checks_passed__ARC_TEST__ ## MESSAGE, arc_test_num_checks_run__ARC_TEST__ ## MESSAGE - arc_test_num_checks_passed__ARC_TEST__ ## MESSAGE, #MESSAGE);\
}
#define ARC_TEST(MESSAGE) ARC_TEST_START_MESSAGE(MESSAGE) ARC_TEST_END_MESSAGE(MESSAGE) void ARC_TEST__ ## MESSAGE(void) __attribute__ ((constructor)); void ARC_TEST__ ## MESSAGE (void)
#define ARC_CHECK(TEST)\
if(temp_arc_test_num_checks_run__ARC_TEST__ == NULL || temp_arc_test_num_checks_passed__ARC_TEST__ == NULL){ return; }\
printf(" %4u) ", *temp_arc_test_num_checks_run__ARC_TEST__);\
++*temp_arc_test_num_checks_run__ARC_TEST__;\
if(TEST){ printf("PASS\t\n"); ++*temp_arc_test_num_checks_passed__ARC_TEST__; }\
else { printf("FAIL\t%s\n", #TEST); }
#ifdef __cplusplus
}
#endif
#endif // !ARC_TEST_H_