basic chemical (config) working, still needs more testing
This commit is contained in:
parent
0e83921632
commit
3fbccd9752
4 changed files with 420 additions and 96 deletions
|
|
@ -87,7 +87,6 @@ void ARC_Chemical_SetGroupWithCStr(ARC_Chemical *chemical, const char *groupName
|
||||||
* @brief get a value from a given keyname
|
* @brief get a value from a given keyname
|
||||||
*
|
*
|
||||||
* @note name may be prefaced with <group>:: to specify group
|
* @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] chemical ARC_Chemical to get value from
|
||||||
* @param[in] element name of a variable that has been read in
|
* @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
|
* @brief get a value from a given keyname
|
||||||
*
|
*
|
||||||
* @note name may be prefaced with <group>:: to specify group
|
* @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] chemical ARC_Chemical to get value from
|
||||||
* @param[in] element name of a variable that has been read in
|
* @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);
|
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
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
|
||||||
|
|
@ -23,73 +23,6 @@ typedef struct ARC_ChemicalTypeData {
|
||||||
ARC_ChemicalType_DestroyFn destroyFn;
|
ARC_ChemicalType_DestroyFn destroyFn;
|
||||||
} ARC_ChemicalTypeData;
|
} 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){
|
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_TAB , '\t'));
|
||||||
ARC_Lexer_RegisterTokenRule(lexer, ARC_LexerTokenRule_CreateAndReturnMatchCharRule(ARC_CHEMICAL_NEWLINE, '\n'));
|
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;
|
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
|
//private function to check hashtable keys used by chemical
|
||||||
ARC_Bool ARC_Chemical_HashtableKeyCompareFn(void *key1, void *key2){
|
ARC_Bool ARC_Chemical_HashtableKeyCompareFn(void *key1, void *key2){
|
||||||
return (ARC_Bool)strcmp((const char *)key1, (const char *)key2) == 0;
|
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);
|
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){
|
void ARC_Chemical_Create(ARC_Chemical **chemical){
|
||||||
*chemical = (ARC_Chemical *)malloc(sizeof(ARC_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){
|
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
|
//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->groups);
|
||||||
ARC_Hashtable_Destroy(chemical->types);
|
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
|
//copy the string into a cstring for long term storage
|
||||||
char *typeNameCopy = malloc(sizeof(char) * strlen(typeNameCStr));
|
uint64_t typeNameCopyLength = strlen(typeNameCStr) + 1;
|
||||||
strcpy(typeNameCopy, typeNameCStr);
|
char *typeNameCopy = (char *)malloc(sizeof(char) * typeNameCopyLength);
|
||||||
|
strncpy(typeNameCopy, typeNameCStr, typeNameCopyLength);
|
||||||
|
typeNameCopy[strlen(typeNameCStr)] = '\0';
|
||||||
|
|
||||||
//copy the type for long term storage
|
//copy the type for long term storage
|
||||||
ARC_ChemicalType *typeCopy = (ARC_ChemicalType *)malloc(sizeof(ARC_ChemicalType));
|
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){
|
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){
|
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
|
//get the return value
|
||||||
return ARC_Hashtable_Get(chemical->currentGroup, (void *)element);
|
void *returnValue = ARC_Chemical_Get(chemical, elementString);
|
||||||
|
|
||||||
|
//cleanup
|
||||||
|
ARC_String_Destroy(elementString);
|
||||||
|
|
||||||
|
return returnValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ARC_Chemical_LoadFromString(ARC_Chemical *chemical, ARC_String **string){
|
void ARC_Chemical_LoadFromString(ARC_Chemical *chemical, ARC_String **string){
|
||||||
|
|
|
||||||
|
|
@ -88,10 +88,6 @@ void ARC_String_CopySubstring(ARC_String **substring, ARC_String *original, uint
|
||||||
}
|
}
|
||||||
|
|
||||||
char data[length];
|
char data[length];
|
||||||
for(uint32_t i = 0; i < length; i++){
|
|
||||||
data[i] = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
strncpy(data, original->data + start, length);
|
strncpy(data, original->data + start, length);
|
||||||
|
|
||||||
ARC_String_Create(substring, data, length);
|
ARC_String_Create(substring, data, length);
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,65 @@
|
||||||
#include "../test.h"
|
#include "../test.h"
|
||||||
#include "arc/std/errno.h"
|
#include "arc/std/errno.h"
|
||||||
#include "arc/std/chemical.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_TEST(Chemical_BasicTest){
|
||||||
ARC_Chemical *chemical;
|
ARC_Chemical *chemical;
|
||||||
|
|
@ -10,11 +67,21 @@ ARC_TEST(Chemical_BasicTest){
|
||||||
|
|
||||||
ARC_CHECK(arc_errno == 0);
|
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";
|
char *tempCString = "tests/res/std/chemical/first.chemical";
|
||||||
ARC_String *tempString;
|
ARC_String *tempString;
|
||||||
ARC_String_CreateWithStrlen(&tempString, tempCString);
|
ARC_String_CreateWithStrlen(&tempString, tempCString);
|
||||||
ARC_Chemical_LoadFromFile(chemical, tempString);
|
ARC_Chemical_LoadFromFile(chemical, tempString);
|
||||||
|
|
||||||
|
int32_t testVal = *(int32_t *)ARC_Chemical_GetWithCStr(chemical, "test::test");
|
||||||
|
ARC_CHECK(testVal == 5);
|
||||||
|
|
||||||
//cleanup
|
//cleanup
|
||||||
|
ARC_String_Destroy(tempString);
|
||||||
ARC_Chemical_Destroy(chemical);
|
ARC_Chemical_Destroy(chemical);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue