basic chemical (config) working, still needs more testing

This commit is contained in:
herbglitch 2025-03-09 06:03:38 -06:00
parent 0e83921632
commit 3fbccd9752
4 changed files with 420 additions and 96 deletions

View file

@ -87,7 +87,6 @@ void ARC_Chemical_SetGroupWithCStr(ARC_Chemical *chemical, const char *groupName
* @brief get a value from a given keyname
*
* @note name may be prefaced with <group>:: to specify group
* @note this function uses ARC_Chemical_GetWithCStr so it shares error messages with that function
*
* @param[in] chemical ARC_Chemical to get value from
* @param[in] element name of a variable that has been read in
@ -100,6 +99,7 @@ void *ARC_Chemical_Get(ARC_Chemical *chemical, ARC_String *element);
* @brief get a value from a given keyname
*
* @note name may be prefaced with <group>:: to specify group
* @note this function uses ARC_Chemical_Get so it shares error messages with that function
*
* @param[in] chemical ARC_Chemical to get value from
* @param[in] element name of a variable that has been read in
@ -128,6 +128,75 @@ void ARC_Chemical_UnloadFromString(ARC_Chemical *chemical, ARC_String **string);
*/
void ARC_Chemical_UnloadFromFile(ARC_Chemical *chemical, ARC_String *data);
#define ARC_CHEMICAL_DEFAULT_GROUP " "
#define ARC_CHEMICAL_GROUP_TAG_NAME "group"
#define ARC_CHEMICAL_GROUP_SEPARATOR "::"
//the grouping is based on the ascii table, but the ids are sequential to make finding tokens quicker (look at the lexer continious for more explanation)
#define ARC_CHEMICAL_TAB 0x01
#define ARC_CHEMICAL_NEWLINE 0x02
#define ARC_CHEMICAL_SPACE 0x03
#define ARC_CHEMICAL_BANG 0x04
#define ARC_CHEMICAL_QUOTE 0x05
#define ARC_CHEMICAL_HASH 0x06
#define ARC_CHEMICAL_DOLLAR 0x07
#define ARC_CHEMICAL_PERCENT 0x08
#define ARC_CHEMICAL_AMPERSAND 0x09
#define ARC_CHEMICAL_SINGLE_QUOTE 0x0A
#define ARC_CHEMICAL_OPEN_PAREN 0x0B
#define ARC_CHEMICAL_CLOSE_PAREN 0x0C
#define ARC_CHEMICAL_ASTERISK 0x0D
#define ARC_CHEMICAL_PLUS 0x0E
#define ARC_CHEMICAL_COMMA 0x0F
#define ARC_CHEMICAL_MINUS 0x10
#define ARC_CHEMICAL_PERIOD 0x11
#define ARC_CHEMICAL_SLASH 0x12
#define ARC_CHEMICAL_NUMBER 0x13
#define ARC_CHEMICAL_COLON 0x14
#define ARC_CHEMICAL_SEMICOLON 0x15
#define ARC_CHEMICAL_LESS_THAN 0x16
#define ARC_CHEMICAL_GREATER_THAN 0x17
#define ARC_CHEMICAL_EQUAL 0x18
#define ARC_CHEMICAL_QUESTION_MARK 0x19
#define ARC_CHEMICAL_AT 0x1A
#define ARC_CHEMICAL_ALPHA_UPPER_CHAR 0x1B
#define ARC_CHEMICAL_OPEN_BRACKET 0x1C
#define ARC_CHEMICAL_BACKSLASH 0x1D
#define ARC_CHEMICAL_CLOSE_BRACKET 0x1E
#define ARC_CHEMICAL_CARET 0x1F
#define ARC_CHEMICAL_UNDERSCORE 0x20
#define ARC_CHEMICAL_GRAVE 0x21
#define ARC_CHEMICAL_ALPHA_LOWER_CHAR 0x22
#define ARC_CHEMICAL_OPEN_CURLY_BRACE 0x23
#define ARC_CHEMICAL_VERTICAL_LINE 0x24
#define ARC_CHEMICAL_CLOSE_CURLY_BRACE 0x25
#define ARC_CHEMICAL_TILDE 0x26
#define ARC_CHEMICAL_LANGUAGE 0x27
#define ARC_CHEMICAL_GROUP 0x28
#define ARC_CHEMICAL_GROUP_NAME 0x29
#define ARC_CHEMICAL_GROUP_ARGS 0x2A
#define ARC_CHEMICAL_VARIABLE_LINES 0x2B
#define ARC_CHEMICAL_VARIABLE_LINE 0x2C
#define ARC_CHEMICAL_ALLOW_SPACE 0x2D
#define ARC_CHEMICAL_TYPE 0x2E
#define ARC_CHEMICAL_VALUE 0x2F
#define ARC_CHEMICAL_NESTED_VALUE 0x30
#define ARC_CHEMICAL_VALUE_ARGS 0x31
#define ARC_CHEMICAL_VARIABLE 0x32
#define ARC_CHEMICAL_VARIABLE_NAME 0x33
#define ARC_CHEMICAL_VARIABLE_CHAR 0x34
#define ARC_CHEMICAL_STRING 0x35
#define ARC_CHEMICAL_STRING_CHARS 0x36
#define ARC_CHEMICAL_STRING_CHAR 0x37
#define ARC_CHEMICAL_ESCAPE_CHAR 0x38
#define ARC_CHEMICAL_WHITESPACE 0x39
#define ARC_CHEMICAL_NUMBER_TAG 0x3A
#ifdef __cplusplus
}
#endif

View file

@ -23,73 +23,6 @@ typedef struct ARC_ChemicalTypeData {
ARC_ChemicalType_DestroyFn destroyFn;
} ARC_ChemicalTypeData;
static const char *ARC_CHEMICAL_DEFAULT_GROUP = " ";
//the grouping is based on the ascii table, but the ids are sequential to make finding tokens quicker (look at the lexer continious for more explanation)
static const uint32_t ARC_CHEMICAL_TAB = 0x01;
static const uint32_t ARC_CHEMICAL_NEWLINE = 0x02;
static const uint32_t ARC_CHEMICAL_SPACE = 0x03;
static const uint32_t ARC_CHEMICAL_BANG = 0x04;
static const uint32_t ARC_CHEMICAL_QUOTE = 0x05;
static const uint32_t ARC_CHEMICAL_HASH = 0x06;
static const uint32_t ARC_CHEMICAL_DOLLAR = 0x07;
static const uint32_t ARC_CHEMICAL_PERCENT = 0x08;
static const uint32_t ARC_CHEMICAL_AMPERSAND = 0x09;
static const uint32_t ARC_CHEMICAL_SINGLE_QUOTE = 0x0A;
static const uint32_t ARC_CHEMICAL_OPEN_PAREN = 0x0B;
static const uint32_t ARC_CHEMICAL_CLOSE_PAREN = 0x0C;
static const uint32_t ARC_CHEMICAL_ASTERISK = 0x0D;
static const uint32_t ARC_CHEMICAL_PLUS = 0x0E;
static const uint32_t ARC_CHEMICAL_COMMA = 0x0F;
static const uint32_t ARC_CHEMICAL_MINUS = 0x10;
static const uint32_t ARC_CHEMICAL_PERIOD = 0x11;
static const uint32_t ARC_CHEMICAL_SLASH = 0x12;
static const uint32_t ARC_CHEMICAL_NUMBER = 0x13;
static const uint32_t ARC_CHEMICAL_COLON = 0x14;
static const uint32_t ARC_CHEMICAL_SEMICOLON = 0x15;
static const uint32_t ARC_CHEMICAL_LESS_THAN = 0x16;
static const uint32_t ARC_CHEMICAL_GREATER_THAN = 0x17;
static const uint32_t ARC_CHEMICAL_EQUAL = 0x18;
static const uint32_t ARC_CHEMICAL_QUESTION_MARK = 0x19;
static const uint32_t ARC_CHEMICAL_AT = 0x1A;
static const uint32_t ARC_CHEMICAL_ALPHA_UPPER_CHAR = 0x1B;
static const uint32_t ARC_CHEMICAL_OPEN_BRACKET = 0x1C;
static const uint32_t ARC_CHEMICAL_BACKSLASH = 0x1D;
static const uint32_t ARC_CHEMICAL_CLOSE_BRACKET = 0x1E;
static const uint32_t ARC_CHEMICAL_CARET = 0x1F;
static const uint32_t ARC_CHEMICAL_UNDERSCORE = 0x20;
static const uint32_t ARC_CHEMICAL_GRAVE = 0x21;
static const uint32_t ARC_CHEMICAL_ALPHA_LOWER_CHAR = 0x22;
static const uint32_t ARC_CHEMICAL_OPEN_CURLY_BRACE = 0x23;
static const uint32_t ARC_CHEMICAL_VERTICAL_LINE = 0x24;
static const uint32_t ARC_CHEMICAL_CLOSE_CURLY_BRACE = 0x25;
static const uint32_t ARC_CHEMICAL_TILDE = 0x26;
static const uint32_t ARC_CHEMICAL_LANGUAGE = 0x27;
static const uint32_t ARC_CHEMICAL_GROUP = 0x28;
static const uint32_t ARC_CHEMICAL_GROUP_NAME = 0x29;
static const uint32_t ARC_CHEMICAL_GROUP_ARGS = 0x2A;
static const uint32_t ARC_CHEMICAL_VARIABLE_LINES = 0x2B;
static const uint32_t ARC_CHEMICAL_VARIABLE_LINE = 0x2C;
static const uint32_t ARC_CHEMICAL_ALLOW_SPACE = 0x2D;
static const uint32_t ARC_CHEMICAL_TYPE = 0x2E;
static const uint32_t ARC_CHEMICAL_VALUE = 0x2F;
static const uint32_t ARC_CHEMICAL_NESTED_VALUE = 0x30;
static const uint32_t ARC_CHEMICAL_VALUE_ARGS = 0x31;
static const uint32_t ARC_CHEMICAL_VARIABLE = 0x32;
static const uint32_t ARC_CHEMICAL_VARIABLE_NAME = 0x33;
static const uint32_t ARC_CHEMICAL_VARIABLE_CHAR = 0x34;
static const uint32_t ARC_CHEMICAL_STRING = 0x35;
static const uint32_t ARC_CHEMICAL_STRING_CHARS = 0x36;
static const uint32_t ARC_CHEMICAL_STRING_CHAR = 0x37;
static const uint32_t ARC_CHEMICAL_ESCAPE_CHAR = 0x38;
static const uint32_t ARC_CHEMICAL_WHITESPACE = 0x39;
static const uint32_t ARC_CHEMICAL_NUMBER_TAG = 0x3A;
void ARC_Chemical_InitLexerRulesFn(ARC_Lexer *lexer){
ARC_Lexer_RegisterTokenRule(lexer, ARC_LexerTokenRule_CreateAndReturnMatchCharRule(ARC_CHEMICAL_TAB , '\t'));
ARC_Lexer_RegisterTokenRule(lexer, ARC_LexerTokenRule_CreateAndReturnMatchCharRule(ARC_CHEMICAL_NEWLINE, '\n'));
@ -325,23 +258,6 @@ uint32_t ARC_Chemical_GetStringIdFn(ARC_String *string){
return ~(uint32_t)0;
}
void ARC_ChemicalData_CreateFn(void **data, ARC_ParserTagToken *parsedData, void *userData){
printf("HERE??\n");
*data = NULL;
if(parsedData == NULL || userData == NULL){
printf("Parsed Data was NULL\n");
//TODO: error here?
*data = NULL;
return;
}
}
void ARC_ChemicalData_DestroyFn(void *data, ARC_Bool clear, void *userData){
return;
}
//private function to check hashtable keys used by chemical
ARC_Bool ARC_Chemical_HashtableKeyCompareFn(void *key1, void *key2){
return (ARC_Bool)strcmp((const char *)key1, (const char *)key2) == 0;
@ -368,6 +284,234 @@ void ARC_Chemical_GroupDataHashtableDestroyKeyValueFn(void *key, void *value){
free(typeData);
}
//<variableLine> -> <whitespace> <type> <whitespace> <variable> <whitespace> EQUAL <whitespace> <value> <whitespace> SEMICOLON
void ARC_ChemicalData_RunVariableLineTag(ARC_ParserTagToken *tagToken, ARC_Chemical *chemical){
//skip whitespace and check for group name
ARC_ParserTagToken *childTagToken = (ARC_ParserTagToken *)ARC_Vector_Get(tagToken->tagTokens, 1);
//get the type
ARC_String *typeString;
ARC_String_Create(&typeString, NULL, 0);
ARC_ParserData_HelperRecurseStringAdd(&typeString, childTagToken);
//check if type exists in the types hashtable
ARC_ChemicalType *type = (ARC_ChemicalType *)ARC_Hashtable_Get(chemical->types, typeString->data);
if(type == NULL){
//throw an error and return
arc_errno = ARC_ERRNO_DATA;
ARC_DEBUG_LOG_ERROR_WITH_VARIABLES("ARC_ChemicalData_RunVariableLineTag(tagToken, chemical), type \"%s\" was not registered to chemical", typeString->data);
ARC_String_Destroy(typeString);
return;
}
//cleanup
ARC_String_Destroy(typeString);
//get the variable
childTagToken = (ARC_ParserTagToken *)ARC_Vector_Get(tagToken->tagTokens, 3);
ARC_String *variableString;
ARC_String_Create(&variableString, NULL, 0);
ARC_ParserData_HelperRecurseStringAdd(&variableString, childTagToken);
//check to see if the current variable is already in the current group hashtable
ARC_ChemicalTypeData *typeData = (ARC_ChemicalTypeData *)ARC_Hashtable_Get(chemical->currentGroup, variableString->data);
if(typeData != NULL){
//there is already a value so throw an error and return
arc_errno = ARC_ERRNO_DATA;
ARC_DEBUG_LOG_ERROR_WITH_VARIABLES("ARC_ChemicalData_RunVariableLineTag(tagToken, chemical), variable \"%s\" already registered to the current group", variableString->data);
ARC_String_Destroy(variableString);
return;
}
//copy the string into a cstring that will be stored in the hashtable
char *elementVariableCStr = malloc(sizeof(char) * (variableString->length + 1));
strncpy(elementVariableCStr, variableString->data, variableString->length);
elementVariableCStr[variableString->length] = '\0';
ARC_String_Destroy(variableString);
//get <value>
childTagToken = (ARC_ParserTagToken *)ARC_Vector_Get(tagToken->tagTokens, 7);
//check if <value> is a reference
ARC_String *valueString;
ARC_String_Create(&valueString, NULL, 0);
ARC_ParserData_HelperRecurseStringAdd(&valueString, childTagToken);
void *value = ARC_Hashtable_Get(chemical->currentGroup, valueString);
ARC_String_Destroy(valueString);
//create where to store either the reference or type data
typeData = (ARC_ChemicalTypeData *)malloc(sizeof(ARC_ChemicalTypeData));
if(value != NULL){
//point to the already stored data
typeData->data = value;
typeData->destroyFn = NULL;
//add to the current group hashtable
ARC_Hashtable_Add(chemical->currentGroup, (void *)elementVariableCStr, (void *)typeData);
return;
}
//passed the parsed value into the copy type function and set the destroy function
type->copyFn(&(typeData->data), childTagToken, chemical);
typeData->destroyFn = type->destroyFn;
//add to the current group hashtable
ARC_Hashtable_Add(chemical->currentGroup, (void *)elementVariableCStr, (void *)typeData);
}
//<variableLines> -> <variableLine> <whitespace> <variableLines> | <variableLine>
void ARC_ChemicalData_RunVariableLinesTag(ARC_ParserTagToken *tagToken, ARC_Chemical *chemical){
//loop through the tags either going to the next line or the next body
for(uint32_t index = 0; index < ARC_Vector_GetSize(tagToken->tagTokens); index++){
ARC_ParserTagToken *childTagToken = (ARC_ParserTagToken *)ARC_Vector_Get(tagToken->tagTokens, index);
switch(childTagToken->id){
//recuse to run the next line
case ARC_CHEMICAL_VARIABLE_LINES:
ARC_ChemicalData_RunVariableLinesTag(childTagToken, chemical);
if(arc_errno != 0){
ARC_DEBUG_LOG_ERROR("ARC_ChemicalData_RunVariableLinesTag(tagToken, chemical), chemical errored when trying to used parsed data for variable lines");
return;
}
continue;
//recurse into a variable line tag
case ARC_CHEMICAL_VARIABLE_LINE:
ARC_ChemicalData_RunVariableLineTag(childTagToken, chemical);
if(arc_errno != 0){
ARC_DEBUG_LOG_ERROR("ARC_ChemicalData_RunVariableLinesTag(tagToken, chemical), chemical errored when trying to used parsed data for variable line");
return;
}
continue;
//this is for whitespace and any oddities
default:
continue;
}
}
}
//<group> -> <whitespace> <groupName> <whitespace> <variable> <whitespace> OPEN_CURLY_BRACE <groupArgs> <whitespace> CLOSE_CURLY_BRACE
void ARC_ChemicalData_RunGroupTag(ARC_ParserTagToken *tagToken, ARC_Chemical *chemical){
//skip whitespace and check for group name
ARC_ParserTagToken *childTagToken = (ARC_ParserTagToken *)ARC_Vector_Get(tagToken->tagTokens, 1);
/* ~ <groupName> ~ */
//get the group name and check if it is named "group"
//NOTE: this check may be usedful in the future if there is different functionality for group like tag names
ARC_String *groupName;
ARC_String_Create(&groupName, NULL, 0);
ARC_ParserData_HelperRecurseStringAdd(&groupName, childTagToken);
if(ARC_String_EqualsCStringWithStrlen(groupName, ARC_CHEMICAL_GROUP_TAG_NAME) == ARC_False){
//throw an error and return
arc_errno = ARC_ERRNO_DATA;
ARC_DEBUG_LOG_ERROR_WITH_VARIABLES("ARC_ChemicalData_RunGroupTag(tagToken, chemical), chemical contained keyword \"%s\" instead of using the correct keyword: \"%s\" ", groupName->data, ARC_CHEMICAL_GROUP_TAG_NAME);
ARC_String_Destroy(groupName);
return;
}
//cleanup
ARC_String_Destroy(groupName);
/* ~ <variable> ~ */
//get the group's variable name
childTagToken = (ARC_ParserTagToken *)ARC_Vector_Get(tagToken->tagTokens, 3);
ARC_String *groupVariable;
ARC_String_Create(&groupVariable, NULL, 0);
ARC_ParserData_HelperRecurseStringAdd(&groupVariable, childTagToken);
//get the needed hashtable or create it from the groups hashtable
ARC_Hashtable *groupHashtable = ARC_Hashtable_Get(chemical->groups, (void *)groupVariable->data);
if(groupHashtable == NULL){
//copy the string into a cstring that will be stored in the hashtable
char *groupVariableCStr = malloc(sizeof(char) * (groupVariable->length + 1));
strncpy(groupVariableCStr, groupVariable->data, groupVariable->length);
groupVariableCStr[groupVariable->length] = '\0';
//create the hashtable with the given group name key
ARC_Hashtable_KeyCompareFn keyCompareFn = ARC_Chemical_HashtableKeyCompareFn;
ARC_Hashtable_DestroyKeyValueFn groupDataDestroyKeyValueFn = ARC_Chemical_GroupDataHashtableDestroyKeyValueFn;
ARC_Hashtable_Create(&groupHashtable, NULL, &keyCompareFn, &groupDataDestroyKeyValueFn);
ARC_Hashtable_Add(chemical->groups, (void *)groupVariableCStr, (void *)groupHashtable);
}
//cleanup
ARC_String_Destroy(groupVariable);
//set the current group to the group just created or found
chemical->currentGroup = groupHashtable;
/* ~ <groupArgs> ~ */
childTagToken = (ARC_ParserTagToken *)ARC_Vector_Get(tagToken->tagTokens, 6);
//<groupArgs> -> <whitespace> <variableLines> | LAMBDA
if(childTagToken->token == NULL && ARC_Vector_GetSize(childTagToken->tagTokens) == 2){
ARC_ParserTagToken *variableLines = (ARC_ParserTagToken *)ARC_Vector_Get(childTagToken->tagTokens, 1);
ARC_ChemicalData_RunVariableLinesTag(variableLines, chemical);
//log error if it happens, but as setting the group back is the last thing we shouldn't return
if(arc_errno != 0){
ARC_DEBUG_LOG_ERROR("ARC_ChemicalData_RunGroupTag(tagToken, chemical), chemical errored when trying to used parsed data for variable lines");
}
}
/* ~ reset current group ~ */
chemical->currentGroup = ARC_Hashtable_Get(chemical->groups, (void *)ARC_CHEMICAL_DEFAULT_GROUP);
}
//<language> -> <group> <language> | <variableLines> <language> | <whitespace>
void ARC_ChemicalData_RunLanguageTag(ARC_ParserTagToken *tagToken, ARC_Chemical *chemical){
//loop through the tags either going to the next language, group, or variable lines
for(uint32_t index = 0; index < ARC_Vector_GetSize(tagToken->tagTokens); index++){
ARC_ParserTagToken *childTagToken = (ARC_ParserTagToken *)ARC_Vector_Get(tagToken->tagTokens, index);
switch(childTagToken->id){
//recuse to run the next line
case ARC_CHEMICAL_LANGUAGE:
ARC_ChemicalData_RunLanguageTag(childTagToken, chemical);
continue;
//recurse into a group tag
case ARC_CHEMICAL_GROUP:
ARC_ChemicalData_RunGroupTag(childTagToken, chemical);
if(arc_errno != 0){
ARC_DEBUG_LOG_ERROR("ARC_ChemicalData_RunLanguageTag(tagToken, chemical), chemical errored when trying to used parsed data for a group");
return;
}
continue;
//recurse through variable lines
case ARC_CHEMICAL_VARIABLE_LINES:
ARC_ChemicalData_RunVariableLinesTag(childTagToken, chemical);
ARC_ChemicalData_RunGroupTag(childTagToken, chemical);
if(arc_errno != 0){
ARC_DEBUG_LOG_ERROR("ARC_ChemicalData_RunLanguageTag(tagToken, chemical), chemical errored when trying to used parsed data for variable lines");
return;
}
continue;
//this is for whitespace and any oddities
default:
continue;
}
}
}
void ARC_ChemicalData_CreateFn(void **data, ARC_ParserTagToken *parsedData, void *userData){
*data = NULL;
if(parsedData == NULL || userData == NULL){
//TODO: error here?
*data = NULL;
return;
}
ARC_ChemicalData_RunLanguageTag(parsedData, (ARC_Chemical *)userData);
}
void ARC_ChemicalData_DestroyFn(void *data, ARC_Bool clear, void *userData){
return;
}
void ARC_Chemical_Create(ARC_Chemical **chemical){
*chemical = (ARC_Chemical *)malloc(sizeof(ARC_Chemical));
@ -438,6 +582,7 @@ void ARC_Chemical_Create(ARC_Chemical **chemical){
}
void ARC_Chemical_Destroy(ARC_Chemical *chemical){
ARC_Parser_Destroy(chemical->parser);
//NOTE: chemical->currentGroup does not need to be freed as it is stored in chemical->groups
ARC_Hashtable_Destroy(chemical->groups);
ARC_Hashtable_Destroy(chemical->types);
@ -457,8 +602,10 @@ void ARC_Chemical_RegisterTypeWithCStr(ARC_Chemical *chemical, const char *typeN
}
//copy the string into a cstring for long term storage
char *typeNameCopy = malloc(sizeof(char) * strlen(typeNameCStr));
strcpy(typeNameCopy, typeNameCStr);
uint64_t typeNameCopyLength = strlen(typeNameCStr) + 1;
char *typeNameCopy = (char *)malloc(sizeof(char) * typeNameCopyLength);
strncpy(typeNameCopy, typeNameCStr, typeNameCopyLength);
typeNameCopy[strlen(typeNameCStr)] = '\0';
//copy the type for long term storage
ARC_ChemicalType *typeCopy = (ARC_ChemicalType *)malloc(sizeof(ARC_ChemicalType));
@ -488,14 +635,59 @@ void ARC_Chemical_SetGroupWithCStr(ARC_Chemical *chemical, const char *groupName
}
void *ARC_Chemical_Get(ARC_Chemical *chemical, ARC_String *element){
return ARC_Chemical_GetWithCStr(chemical, element->data);
//check if the group separator exists
uint64_t startSeparatorIndex = ARC_String_FindCStringWithStrlen(element, ARC_CHEMICAL_GROUP_SEPARATOR);
if(startSeparatorIndex == ~(uint64_t)0){
//use empty group
chemical->currentGroup = ARC_Hashtable_Get(chemical->groups, (void *)ARC_CHEMICAL_DEFAULT_GROUP);
//get the typeData and pass back the data without the cleanup function
ARC_ChemicalTypeData *typeData = (ARC_ChemicalTypeData *)ARC_Hashtable_Get(chemical->currentGroup, (void *)element->data);
if(typeData == NULL){
return NULL;
}
return typeData->data;
}
//get the group
startSeparatorIndex--;
ARC_String *groupString;
ARC_String_CopySubstring(&groupString, element, 0, startSeparatorIndex);
//set the group
chemical->currentGroup = ARC_Hashtable_Get(chemical->groups, (void *)groupString->data);
//cleanup
ARC_String_Destroy(groupString);
//get the element
ARC_String *elementString;
startSeparatorIndex += strlen(ARC_CHEMICAL_GROUP_SEPARATOR);
ARC_String_CopySubstring(&elementString, element, startSeparatorIndex, element->length - startSeparatorIndex);
//this will either return the value or NULL
ARC_ChemicalTypeData *typeData = (ARC_ChemicalTypeData *)ARC_Hashtable_Get(chemical->currentGroup, (void *)elementString->data);
ARC_String_Destroy(elementString);
if(typeData == NULL){
return NULL;
}
return typeData->data;
}
void *ARC_Chemical_GetWithCStr(ARC_Chemical *chemical, const char *element){
//TODO: set the parent group
//create and copy into ARC_String
ARC_String *elementString;
ARC_String_CreateWithStrlen(&elementString, (char *)element);
//this will either return the value or NULL
return ARC_Hashtable_Get(chemical->currentGroup, (void *)element);
//get the return value
void *returnValue = ARC_Chemical_Get(chemical, elementString);
//cleanup
ARC_String_Destroy(elementString);
return returnValue;
}
void ARC_Chemical_LoadFromString(ARC_Chemical *chemical, ARC_String **string){

View file

@ -88,10 +88,6 @@ void ARC_String_CopySubstring(ARC_String **substring, ARC_String *original, uint
}
char data[length];
for(uint32_t i = 0; i < length; i++){
data[i] = 0;
}
strncpy(data, original->data + start, length);
ARC_String_Create(substring, data, length);

View file

@ -1,8 +1,65 @@
#include "../test.h"
#include "arc/std/errno.h"
#include "arc/std/chemical.h"
//#include <stdlib.h>
#include "arc/std/parser.h"
#include "arc/std/parser/helpers.h"
#include <stdlib.h>
static const char *testType = "int32";
void TEST_ChemicalType_CopyInt32Fn(void **type, ARC_ParserTagToken *parsedData, ARC_Chemical *chemical){
ARC_String *int32String;
ARC_String_Create(&int32String, NULL, 0);
ARC_ParserData_HelperRecurseStringAdd(&int32String, parsedData);
//set the max character size 2,147,483,647 (10 characters) or -2,147,483,648 (11 characters)
uint32_t maxInt32Size = 10;
if(int32String->data[0] == '-'){
maxInt32Size++;
}
//if the string is bigger than the possible size return NULL and error
if(int32String->length > maxInt32Size){
arc_errno = ARC_ERRNO_DATA;
ARC_DEBUG_LOG_ERROR_WITH_VARIABLES("TEST_ChemicalType_CopyInt32Fn(type, parsedData, chemical), size \"%s\" was bigger or smaller than the max 2,147,483,647 or min -2,147,483,648", int32String->data);
*type = NULL;
ARC_String_Destroy(int32String);
return;
}
if(int32String->length == maxInt32Size){
char maxint32CStr[10] = "2147483647";
//offset starting index and last number if there is a negative
uint8_t stringIndex = 0;
if(int32String->data[0] == '-'){
stringIndex++;
maxint32CStr[9]++;
}
for(uint8_t index = 0; index < 10; index++, stringIndex++){
if(int32String->data[stringIndex] > maxint32CStr[index]){
arc_errno = ARC_ERRNO_DATA;
ARC_DEBUG_LOG_ERROR_WITH_VARIABLES("TEST_ChemicalType_CopyInt32Fn(type, parsedData, chemical), size \"%s\" was bigger or smaller than the max 2,147,483,647 or min -2,147,483,648", int32String->data);
*type = NULL;
ARC_String_Destroy(int32String);
return;
}
}
}
//copy the int32_t
*type = malloc(sizeof(int32_t));
*(int32_t *)(*type) = (int32_t)ARC_String_ToInt64_t(int32String);
//cleanup
ARC_String_Destroy(int32String);
}
void TEST_ChemicalType_DestroyInt32Fn(void *type){
free((int32_t *)type);
}
ARC_TEST(Chemical_BasicTest){
ARC_Chemical *chemical;
@ -10,11 +67,21 @@ ARC_TEST(Chemical_BasicTest){
ARC_CHECK(arc_errno == 0);
ARC_ChemicalType int32Type = {
TEST_ChemicalType_CopyInt32Fn,
TEST_ChemicalType_DestroyInt32Fn
};
ARC_Chemical_RegisterTypeWithCStr(chemical, testType, int32Type);
char *tempCString = "tests/res/std/chemical/first.chemical";
ARC_String *tempString;
ARC_String_CreateWithStrlen(&tempString, tempCString);
ARC_Chemical_LoadFromFile(chemical, tempString);
int32_t testVal = *(int32_t *)ARC_Chemical_GetWithCStr(chemical, "test::test");
ARC_CHECK(testVal == 5);
//cleanup
ARC_String_Destroy(tempString);
ARC_Chemical_Destroy(chemical);
}