2022-10-27 15:16:54 -06:00
|
|
|
#include "arc/std/config.h"
|
|
|
|
|
|
|
|
|
|
#include "arc/std/errno.h"
|
2023-01-17 01:59:08 -07:00
|
|
|
#include "arc/std/hashtable.h"
|
2022-10-27 15:16:54 -06:00
|
|
|
#include "arc/std/io.h"
|
2023-01-17 01:59:08 -07:00
|
|
|
#include "arc/std/string.h"
|
2022-10-27 15:16:54 -06:00
|
|
|
#include <stdio.h>
|
2023-01-17 01:59:08 -07:00
|
|
|
#include <stdint.h>
|
2022-10-27 15:16:54 -06:00
|
|
|
#include <stdlib.h>
|
|
|
|
|
#include <stddef.h>
|
|
|
|
|
#include <string.h>
|
|
|
|
|
|
|
|
|
|
struct ARC_Config {
|
|
|
|
|
ARC_Hashtable *currgroup;
|
|
|
|
|
|
|
|
|
|
ARC_Hashtable *groups;
|
|
|
|
|
ARC_Hashtable *keys;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
typedef struct ARC_ConfigKey {
|
|
|
|
|
ARC_ConfigKeyRead Read;
|
|
|
|
|
ARC_ConfigKeyDelete Delete;
|
|
|
|
|
} ARC_ConfigKey;
|
|
|
|
|
|
|
|
|
|
typedef struct ARC_ConfigTypeTemplate {
|
2023-01-17 01:59:08 -07:00
|
|
|
ARC_ConfigKeyDelete Delete;
|
2022-10-27 15:16:54 -06:00
|
|
|
|
|
|
|
|
void *data;
|
|
|
|
|
} ARC_ConfigTypeTemplate;
|
|
|
|
|
|
2023-01-20 22:38:29 -07:00
|
|
|
typedef struct ARC_ConfigDeleteKeyArgs {
|
|
|
|
|
ARC_Config *config;
|
|
|
|
|
ARC_String *string;
|
|
|
|
|
} ARC_ConfigDeleteKeyArgs;
|
|
|
|
|
|
2023-01-17 01:59:08 -07:00
|
|
|
int8_t ARC_Config_KeyComp(void *key1, size_t *key1size, void *key2, size_t *key2size);
|
2022-10-27 15:16:54 -06:00
|
|
|
|
2023-01-17 01:59:08 -07:00
|
|
|
void ARC_Config_CreateGroup(ARC_Config *config, ARC_String *name);
|
|
|
|
|
void ARC_Config_DestroyGroup(ARC_HashtableNode *group, void *userdata);
|
2022-10-27 15:16:54 -06:00
|
|
|
|
2023-01-17 01:59:08 -07:00
|
|
|
void ARC_Config_DestroyGroupNode(ARC_HashtableNode *node , void *userdata);
|
2022-10-27 15:16:54 -06:00
|
|
|
|
2023-01-17 01:59:08 -07:00
|
|
|
void ARC_Config_RemoveKey(ARC_HashtableNode *node, void *userdata);
|
2022-10-27 15:16:54 -06:00
|
|
|
|
2023-01-17 01:59:08 -07:00
|
|
|
void ARC_Config_AddKey(ARC_Config *config, ARC_String *type, ARC_ConfigKeyRead keyRead, ARC_ConfigKeyDelete keyDelete){
|
|
|
|
|
ARC_ConfigKey *newKey = (ARC_ConfigKey *)malloc(sizeof(ARC_ConfigKey));
|
|
|
|
|
newKey->Read = keyRead;
|
|
|
|
|
newKey->Delete = keyDelete;
|
2022-10-27 15:16:54 -06:00
|
|
|
|
2023-01-17 01:59:08 -07:00
|
|
|
char *typeval = (char *)malloc(sizeof(char) * type->length);
|
|
|
|
|
strncpy(typeval, type->data, type->length);
|
|
|
|
|
ARC_Hashtable_Add(config->keys, (void *)typeval, type->length, newKey);
|
2022-10-27 15:16:54 -06:00
|
|
|
}
|
|
|
|
|
|
2023-01-17 01:59:08 -07:00
|
|
|
void ARC_Config_AddKeyCString(ARC_Config *config, const char *type, uint64_t length, ARC_ConfigKeyRead keyRead, ARC_ConfigKeyDelete keyDelete){
|
|
|
|
|
ARC_ConfigKey *newKey = (ARC_ConfigKey *)malloc(sizeof(ARC_ConfigKey));
|
|
|
|
|
newKey->Read = keyRead;
|
|
|
|
|
newKey->Delete = keyDelete;
|
2022-10-27 15:16:54 -06:00
|
|
|
|
2023-01-17 01:59:08 -07:00
|
|
|
char *typeval = (char *)malloc(sizeof(char) * length);
|
|
|
|
|
strncpy(typeval, type, length);
|
|
|
|
|
ARC_Hashtable_Add(config->keys, (void *)typeval, length, newKey);
|
2022-10-27 15:16:54 -06:00
|
|
|
}
|
|
|
|
|
|
2023-01-17 01:59:08 -07:00
|
|
|
void ARC_Config_Create(ARC_Config **config){
|
|
|
|
|
*config = (ARC_Config *)malloc(sizeof(ARC_Config));
|
2022-10-27 15:16:54 -06:00
|
|
|
(*config)->currgroup = NULL;
|
|
|
|
|
|
|
|
|
|
ARC_Hashtable *groups;
|
|
|
|
|
ARC_Hashtable_Create(&groups, ARC_GROUP_BUCKET_SIZE, NULL, ARC_Config_KeyComp);
|
|
|
|
|
(*config)->groups = groups;
|
2023-01-17 01:59:08 -07:00
|
|
|
ARC_Config_CreateGroup(*config, NULL);
|
2022-10-27 15:16:54 -06:00
|
|
|
|
|
|
|
|
ARC_Hashtable *keys;
|
|
|
|
|
ARC_Hashtable_Create(&keys, ARC_KEY_BUCKET_SIZE, NULL, ARC_Config_KeyComp);
|
|
|
|
|
(*config)->keys = keys;
|
|
|
|
|
|
|
|
|
|
#ifdef ARC_DEFAULT_CONFIG
|
|
|
|
|
ARC_Defaults_ConfigKey_Create(*config);
|
|
|
|
|
#endif
|
2023-01-17 01:59:08 -07:00
|
|
|
}
|
2022-10-27 15:16:54 -06:00
|
|
|
|
2023-01-17 01:59:08 -07:00
|
|
|
void ARC_Config_Destroy(ARC_Config *config){
|
2023-01-20 22:38:29 -07:00
|
|
|
ARC_ConfigDeleteKeyArgs keyArgs = {
|
|
|
|
|
.config = config,
|
|
|
|
|
.string = NULL,
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
ARC_Hashtable_Destroy(config->groups, ARC_Config_DestroyGroup, (void *)&keyArgs);
|
|
|
|
|
ARC_Hashtable_Destroy(config->keys , ARC_Config_RemoveKey , NULL );
|
2023-01-17 01:59:08 -07:00
|
|
|
free(config);
|
2022-10-27 15:16:54 -06:00
|
|
|
}
|
|
|
|
|
|
2023-01-20 22:38:29 -07:00
|
|
|
//TODO: fix NULL group
|
2023-01-17 01:59:08 -07:00
|
|
|
void ARC_Config_SetGroup(ARC_Config *config, ARC_String *groupname){
|
2023-01-20 22:38:29 -07:00
|
|
|
if(!config){
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2023-01-17 01:59:08 -07:00
|
|
|
if(groupname == NULL){
|
|
|
|
|
ARC_Hashtable_Get(config->groups, (void *)" ", 1, (void **)&(config->currgroup));
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ARC_Hashtable_Get(config->groups, (void *)groupname->data, groupname->length, (void **)&(config->currgroup));
|
|
|
|
|
if(arc_errno && arc_errno != ARC_ERRNO_NULL){
|
|
|
|
|
return;
|
|
|
|
|
}
|
2022-10-27 15:16:54 -06:00
|
|
|
|
2023-01-17 01:59:08 -07:00
|
|
|
if(config->currgroup){
|
|
|
|
|
return;
|
|
|
|
|
}
|
2022-10-27 15:16:54 -06:00
|
|
|
|
2023-01-17 01:59:08 -07:00
|
|
|
ARC_Config_CreateGroup(config, groupname);
|
|
|
|
|
if(arc_errno){
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ARC_Hashtable_Get(config->groups, (void *)groupname->data, groupname->length, (void **)&(config->currgroup));
|
2022-10-27 15:16:54 -06:00
|
|
|
}
|
|
|
|
|
|
2023-01-17 01:59:08 -07:00
|
|
|
void ARC_Config_Get(ARC_Config *config, ARC_String *keyname, void **value){
|
2023-01-21 16:58:10 -07:00
|
|
|
ARC_ConfigTypeTemplate *temp = NULL;
|
2022-10-27 15:16:54 -06:00
|
|
|
|
2023-01-20 22:38:29 -07:00
|
|
|
uint64_t length = ARC_String_FindCString(keyname, "::", 2);
|
2023-01-17 01:59:08 -07:00
|
|
|
if(arc_errno){
|
|
|
|
|
//TODO: Debug info here
|
2023-01-21 16:58:10 -07:00
|
|
|
ARC_DEBUG_ERR("in ARC_Config_Get(config, keyname, value); length threw error");
|
2023-01-17 01:59:08 -07:00
|
|
|
*value = NULL;
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if(length != ~((uint64_t)0)){
|
2023-01-20 22:38:29 -07:00
|
|
|
length--;
|
|
|
|
|
ARC_String *group = NULL;
|
|
|
|
|
|
|
|
|
|
if(length != 0){
|
|
|
|
|
ARC_String_CopySubstring(&group, keyname, 0, length);
|
|
|
|
|
}
|
2022-10-27 15:16:54 -06:00
|
|
|
|
|
|
|
|
ARC_Hashtable *currgroup = config->currgroup;
|
2023-01-17 01:59:08 -07:00
|
|
|
ARC_Config_SetGroup(config, group);
|
|
|
|
|
if(arc_errno){
|
2023-01-21 16:58:10 -07:00
|
|
|
ARC_DEBUG_ERR("in ARC_Config_Get(config, keyname, value); setting group threw error");
|
2023-01-17 01:59:08 -07:00
|
|
|
ARC_String_Destroy(group);
|
|
|
|
|
*value = NULL;
|
|
|
|
|
return;
|
|
|
|
|
}
|
2022-10-27 15:16:54 -06:00
|
|
|
|
2023-01-17 01:59:08 -07:00
|
|
|
ARC_String *name;
|
|
|
|
|
ARC_String_CopySubstring(&name, keyname, length + 2, keyname->length - (length + 2));
|
|
|
|
|
ARC_Hashtable_Get(config->currgroup, (void *)name->data, name->length, (void **)&temp);
|
2023-01-20 22:38:29 -07:00
|
|
|
ARC_String_Destroy(name);
|
2022-10-27 15:16:54 -06:00
|
|
|
|
|
|
|
|
config->currgroup = currgroup;
|
2023-01-20 22:38:29 -07:00
|
|
|
if(group){
|
|
|
|
|
ARC_String_Destroy(group);
|
|
|
|
|
}
|
2023-02-23 00:07:18 -07:00
|
|
|
|
|
|
|
|
if(temp == NULL){
|
|
|
|
|
*value = NULL;
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2022-10-27 15:16:54 -06:00
|
|
|
*value = temp->data;
|
2023-01-17 01:59:08 -07:00
|
|
|
return;
|
2022-10-27 15:16:54 -06:00
|
|
|
}
|
|
|
|
|
|
2023-01-20 22:38:29 -07:00
|
|
|
if(!keyname){
|
|
|
|
|
*value = NULL;
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2023-01-17 01:59:08 -07:00
|
|
|
ARC_Hashtable_Get(config->currgroup, (void *)keyname->data, keyname->length, (void **)&temp);
|
|
|
|
|
if(arc_errno || temp == NULL){
|
|
|
|
|
*value = NULL;
|
|
|
|
|
return;
|
|
|
|
|
}
|
2022-10-27 15:16:54 -06:00
|
|
|
|
|
|
|
|
*value = temp->data;
|
|
|
|
|
}
|
|
|
|
|
|
2023-01-17 01:59:08 -07:00
|
|
|
void ARC_Config_Recurse(ARC_Config *config, ARC_String **data, ARC_String *groupstr, uint8_t *command);
|
2022-10-27 15:16:54 -06:00
|
|
|
|
2023-01-17 01:59:08 -07:00
|
|
|
void ARC_Config_SetKeyGroup(ARC_Config *config, ARC_String **data, uint8_t *command){
|
|
|
|
|
uint64_t index = ARC_String_FindCString(*data, " ", 1);
|
|
|
|
|
uint64_t nextIndex = ARC_String_FindCString(*data, "{", 1);
|
|
|
|
|
if(index == ~(uint64_t)0 || nextIndex == ~(uint64_t)0){
|
|
|
|
|
arc_errno = ARC_ERRNO_DATA;
|
2022-10-27 15:16:54 -06:00
|
|
|
}
|
|
|
|
|
|
2023-01-17 01:59:08 -07:00
|
|
|
if(arc_errno){
|
2022-10-27 15:16:54 -06:00
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2023-01-17 01:59:08 -07:00
|
|
|
ARC_String *name, *temp;
|
2023-01-20 22:38:29 -07:00
|
|
|
ARC_String_CopySubstring(&temp, *data, index, nextIndex - index - 1);
|
2023-01-17 01:59:08 -07:00
|
|
|
ARC_String_StripEndsWhitespace(temp, &name);
|
|
|
|
|
ARC_String_Destroy(temp);
|
2022-10-27 15:16:54 -06:00
|
|
|
|
2023-01-17 01:59:08 -07:00
|
|
|
temp = *data;
|
2023-01-20 22:38:29 -07:00
|
|
|
ARC_String_CopySubstring(data, temp, nextIndex + 1, (*data)->length - (nextIndex + 1));
|
2023-01-17 01:59:08 -07:00
|
|
|
ARC_String_Destroy(temp);
|
2022-10-27 15:16:54 -06:00
|
|
|
|
2023-01-17 01:59:08 -07:00
|
|
|
ARC_Config_Recurse(config, data, name, command);
|
|
|
|
|
ARC_String_Destroy(name);
|
|
|
|
|
}
|
2022-10-27 15:16:54 -06:00
|
|
|
|
2023-01-17 01:59:08 -07:00
|
|
|
void ARC_Config_LoadFromKey(ARC_Config *config, ARC_String *keyType, ARC_String *name, ARC_String *value){
|
|
|
|
|
ARC_ConfigKey *key;
|
|
|
|
|
ARC_Hashtable_Get(config->keys, keyType->data, keyType->length, (void **)&key);
|
|
|
|
|
if(key == NULL){
|
|
|
|
|
arc_errno = ARC_ERRNO_DATA;
|
2023-04-04 16:29:37 -06:00
|
|
|
ARC_DEBUG_LOG(arc_errno, "in ARC_Config_LoadFromKey(config, string, value); no matching key: %s", keyType->data);
|
2023-01-17 01:59:08 -07:00
|
|
|
}
|
2022-10-27 15:16:54 -06:00
|
|
|
|
2023-01-17 01:59:08 -07:00
|
|
|
if(arc_errno){
|
|
|
|
|
return;
|
|
|
|
|
}
|
2022-10-27 15:16:54 -06:00
|
|
|
|
2023-01-17 01:59:08 -07:00
|
|
|
ARC_ConfigTypeTemplate *templateVal = (ARC_ConfigTypeTemplate *) malloc(sizeof(ARC_ConfigTypeTemplate));
|
|
|
|
|
templateVal->Delete = NULL;
|
2023-01-17 02:57:57 -07:00
|
|
|
templateVal->data = NULL;
|
2022-10-27 15:16:54 -06:00
|
|
|
|
2023-01-17 01:59:08 -07:00
|
|
|
uint8_t reference = key->Read(config, value, &(templateVal->data));
|
|
|
|
|
if(!reference){
|
|
|
|
|
templateVal->Delete = key->Delete;
|
|
|
|
|
}
|
2022-10-27 15:16:54 -06:00
|
|
|
|
2023-01-17 01:59:08 -07:00
|
|
|
if(arc_errno){
|
|
|
|
|
return;
|
2022-10-27 15:16:54 -06:00
|
|
|
}
|
|
|
|
|
|
2023-01-20 22:38:29 -07:00
|
|
|
char *nameval = (char *)malloc(sizeof(char) * name->length + 1);
|
2023-01-17 01:59:08 -07:00
|
|
|
strncpy(nameval, name->data, name->length);
|
2023-01-20 22:38:29 -07:00
|
|
|
nameval[name->length] = '\0';
|
2023-01-17 01:59:08 -07:00
|
|
|
ARC_Hashtable_Add(config->currgroup, nameval, name->length, (void *)templateVal);
|
|
|
|
|
}
|
2022-10-27 15:16:54 -06:00
|
|
|
|
2023-01-20 22:38:29 -07:00
|
|
|
void ARC_Config_UnloadFromKey(ARC_Config *config, ARC_String *keyType, ARC_String *name, ARC_String *value){
|
|
|
|
|
ARC_ConfigDeleteKeyArgs keyArgs = {
|
|
|
|
|
.config = config,
|
|
|
|
|
.string = value,
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
ARC_Hashtable_Remove(config->currgroup, name->data, name->length, ARC_Config_DestroyGroupNode, &keyArgs);
|
2022-10-27 15:16:54 -06:00
|
|
|
}
|
|
|
|
|
|
2023-01-17 01:59:08 -07:00
|
|
|
void ARC_Config_GetNameAndValue(ARC_String *data, ARC_String **name, ARC_String **value){
|
|
|
|
|
uint64_t index = ARC_String_FindCString(data, "=", 1);
|
|
|
|
|
if(arc_errno || index == ~(uint64_t)0){
|
|
|
|
|
*name = NULL;
|
|
|
|
|
*value = NULL;
|
|
|
|
|
return;
|
|
|
|
|
}
|
2022-10-27 15:16:54 -06:00
|
|
|
|
2023-01-17 01:59:08 -07:00
|
|
|
ARC_String_CopySubstring(name, data, 0, index - 1);
|
|
|
|
|
index++;
|
2022-10-27 15:16:54 -06:00
|
|
|
|
2023-01-17 01:59:08 -07:00
|
|
|
ARC_String *dataTemp = *name;
|
|
|
|
|
ARC_String_StripEndsWhitespace(dataTemp, name);
|
|
|
|
|
ARC_String_Destroy(dataTemp);
|
2022-10-27 15:16:54 -06:00
|
|
|
|
2023-01-20 22:38:29 -07:00
|
|
|
ARC_String_CopySubstring(&dataTemp, data, index, data->length - index);
|
|
|
|
|
ARC_String_StripEndsWhitespace(dataTemp, value);
|
|
|
|
|
ARC_String_Destroy(dataTemp);
|
2022-10-27 15:16:54 -06:00
|
|
|
}
|
|
|
|
|
|
2023-01-17 01:59:08 -07:00
|
|
|
void ARC_Config_Recurse(ARC_Config *config, ARC_String **data, ARC_String *groupstr, uint8_t *command){
|
|
|
|
|
ARC_Config_SetGroup(config, groupstr);
|
|
|
|
|
if(arc_errno){
|
|
|
|
|
return;
|
2022-10-27 15:16:54 -06:00
|
|
|
}
|
|
|
|
|
|
2023-01-17 01:59:08 -07:00
|
|
|
ARC_Hashtable *group = config->currgroup;
|
2022-10-27 15:16:54 -06:00
|
|
|
|
2023-01-17 01:59:08 -07:00
|
|
|
while(*data && (*data)->length){
|
|
|
|
|
ARC_String *dataTemp = *data;
|
|
|
|
|
ARC_String_StripEndsWhitespace(dataTemp, data);
|
|
|
|
|
ARC_String_Destroy(dataTemp);
|
2022-10-27 15:16:54 -06:00
|
|
|
|
2023-01-17 01:59:08 -07:00
|
|
|
// break out of current group
|
|
|
|
|
if((*data)->data[0] == '}'){
|
|
|
|
|
config->currgroup = NULL;
|
2022-10-27 15:16:54 -06:00
|
|
|
|
2023-01-17 01:59:08 -07:00
|
|
|
dataTemp = *data;
|
|
|
|
|
ARC_String_CopySubstring(data, dataTemp, 1, dataTemp->length - 1);
|
|
|
|
|
ARC_String_Destroy(dataTemp);
|
|
|
|
|
return;
|
2022-10-27 15:16:54 -06:00
|
|
|
}
|
|
|
|
|
|
2023-01-17 01:59:08 -07:00
|
|
|
// set group
|
|
|
|
|
if(!(config->currgroup)){
|
|
|
|
|
config->currgroup = group;
|
2022-10-27 15:16:54 -06:00
|
|
|
}
|
|
|
|
|
|
2023-01-17 01:59:08 -07:00
|
|
|
// get keys type
|
|
|
|
|
uint64_t index = ARC_String_FindCString(*data, " ", 1);
|
|
|
|
|
if(arc_errno || index == ~(uint64_t)0){
|
|
|
|
|
return;
|
2022-10-27 15:16:54 -06:00
|
|
|
}
|
|
|
|
|
|
2023-01-17 01:59:08 -07:00
|
|
|
ARC_String *keyType, *keyTypeTemp;
|
|
|
|
|
ARC_String_CopySubstring(&keyTypeTemp, *data, 0, index);
|
|
|
|
|
ARC_String_StripEndsWhitespace(keyTypeTemp, &keyType);
|
|
|
|
|
ARC_String_Destroy(keyTypeTemp);
|
|
|
|
|
|
|
|
|
|
if(ARC_String_EqualsCString(keyType, "group", 5)){
|
|
|
|
|
ARC_Config_SetKeyGroup(config, data, command);
|
2023-01-17 02:57:57 -07:00
|
|
|
ARC_String_Destroy(keyType);
|
2023-01-20 22:38:29 -07:00
|
|
|
config->currgroup = group;
|
2023-01-17 01:59:08 -07:00
|
|
|
if(arc_errno){
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2022-10-27 15:16:54 -06:00
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
2023-01-17 01:59:08 -07:00
|
|
|
// get and copy up to the ;
|
|
|
|
|
ARC_String *nameAndValue;
|
|
|
|
|
uint64_t nextIndex = ARC_String_FindCString(*data, ";", 1);
|
|
|
|
|
if(nextIndex == ~(uint64_t)0){
|
|
|
|
|
arc_errno = ARC_ERRNO_DATA;
|
|
|
|
|
}
|
2022-10-27 15:16:54 -06:00
|
|
|
|
2023-01-17 01:59:08 -07:00
|
|
|
if(arc_errno){
|
|
|
|
|
ARC_String_Destroy(keyType);
|
|
|
|
|
return;
|
2022-10-27 15:16:54 -06:00
|
|
|
}
|
|
|
|
|
|
2023-01-17 01:59:08 -07:00
|
|
|
ARC_String_CopySubstring(&nameAndValue, *data, index, nextIndex - (index + 1));
|
|
|
|
|
if(arc_errno){
|
|
|
|
|
ARC_String_Destroy(keyType);
|
|
|
|
|
return;
|
|
|
|
|
}
|
2022-10-27 15:16:54 -06:00
|
|
|
|
2023-01-17 01:59:08 -07:00
|
|
|
// remove up to the ; from data string
|
|
|
|
|
dataTemp = *data;
|
|
|
|
|
ARC_String_CopySubstring(data, dataTemp, nextIndex, (*data)->length - nextIndex);
|
|
|
|
|
ARC_String_Destroy(dataTemp);
|
|
|
|
|
if(arc_errno){
|
|
|
|
|
ARC_String_Destroy(keyType);
|
|
|
|
|
ARC_String_Destroy(nameAndValue);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// get name and value of string
|
|
|
|
|
ARC_String *name, *value;
|
|
|
|
|
ARC_Config_GetNameAndValue(nameAndValue, &name, &value);
|
|
|
|
|
ARC_String_Destroy(nameAndValue);
|
|
|
|
|
if(arc_errno){
|
|
|
|
|
ARC_String_Destroy(keyType);
|
|
|
|
|
return;
|
2022-10-27 15:16:54 -06:00
|
|
|
}
|
|
|
|
|
|
2023-01-17 01:59:08 -07:00
|
|
|
// load from key
|
2022-10-27 15:16:54 -06:00
|
|
|
if(*command == ARC_CONFIG_FILE_IO_LOAD){
|
2023-01-17 01:59:08 -07:00
|
|
|
ARC_Config_LoadFromKey(config, keyType, name, value);
|
2023-01-17 02:57:57 -07:00
|
|
|
|
|
|
|
|
ARC_String_Destroy(keyType);
|
|
|
|
|
ARC_String_Destroy(name );
|
|
|
|
|
ARC_String_Destroy(value );
|
|
|
|
|
|
2023-01-17 01:59:08 -07:00
|
|
|
if(arc_errno){
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2022-10-27 15:16:54 -06:00
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
2023-01-17 01:59:08 -07:00
|
|
|
// unload from key
|
2022-10-27 15:16:54 -06:00
|
|
|
if(*command == ARC_CONFIG_FILE_IO_UNLOAD){
|
2023-01-20 22:38:29 -07:00
|
|
|
ARC_Config_UnloadFromKey(config, keyType, name, value);
|
2023-01-17 02:57:57 -07:00
|
|
|
|
|
|
|
|
ARC_String_Destroy(keyType);
|
|
|
|
|
ARC_String_Destroy(name );
|
|
|
|
|
ARC_String_Destroy(value );
|
|
|
|
|
|
2023-01-17 01:59:08 -07:00
|
|
|
if(arc_errno){
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2022-10-27 15:16:54 -06:00
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
2023-01-17 01:59:08 -07:00
|
|
|
// config file wasn't loaded correctly
|
|
|
|
|
ARC_String_Destroy(keyType);
|
|
|
|
|
ARC_String_Destroy(name );
|
|
|
|
|
ARC_String_Destroy(value );
|
|
|
|
|
arc_errno = ARC_ERRNO_DATA;
|
|
|
|
|
return;
|
2022-10-27 15:16:54 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
config->currgroup = group;
|
|
|
|
|
}
|
|
|
|
|
|
2023-01-17 01:59:08 -07:00
|
|
|
void ARC_Config_StripComment(ARC_String *original, ARC_String **stripped, ARC_String *lineStart, ARC_String *lineEnd){
|
2023-01-20 22:38:29 -07:00
|
|
|
ARC_String *current = NULL;
|
2023-01-17 01:59:08 -07:00
|
|
|
ARC_String_Copy(¤t, original);
|
|
|
|
|
|
2023-01-20 22:38:29 -07:00
|
|
|
uint64_t index = ARC_String_Find(original, lineStart);
|
2023-01-17 01:59:08 -07:00
|
|
|
while(index != ~(uint64_t)0){
|
2023-01-20 22:38:29 -07:00
|
|
|
ARC_String *commentString;
|
|
|
|
|
ARC_String_CopySubstring(&commentString, current, index + lineStart->length, current->length - (index + lineStart->length));
|
2023-01-17 01:59:08 -07:00
|
|
|
|
2023-01-20 22:38:29 -07:00
|
|
|
uint64_t endIndex = ARC_String_Find(commentString, lineEnd);
|
|
|
|
|
ARC_String_Destroy(commentString);
|
2023-01-17 01:59:08 -07:00
|
|
|
if(endIndex == ~(uint64_t)0){
|
|
|
|
|
ARC_DEBUG_ERR("ARC_Config_RemoveComments(original, commentRemoved); No newline found when stripping single line comment");
|
|
|
|
|
arc_errno = ARC_ERRNO_DATA;
|
2023-01-17 02:57:57 -07:00
|
|
|
ARC_String_Destroy(current);
|
2023-01-17 01:59:08 -07:00
|
|
|
*stripped = NULL;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ARC_String *currentTemp = current;
|
2023-01-20 22:38:29 -07:00
|
|
|
ARC_String_RemoveSection(¤t, currentTemp, index, endIndex + lineStart->length + lineEnd->length);
|
2023-01-17 01:59:08 -07:00
|
|
|
ARC_String_Destroy(currentTemp);
|
|
|
|
|
|
|
|
|
|
index = ARC_String_Find(current, lineStart);
|
2022-10-27 15:16:54 -06:00
|
|
|
}
|
|
|
|
|
|
2023-01-17 01:59:08 -07:00
|
|
|
*stripped = current;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void ARC_Config_RemoveComments(ARC_String *original, ARC_String **commentRemoved){
|
|
|
|
|
ARC_String *lineStart, *lineEnd;
|
2022-10-27 15:16:54 -06:00
|
|
|
|
2023-01-17 01:59:08 -07:00
|
|
|
//Single Line Comment
|
|
|
|
|
ARC_String_Create(&lineStart, "//", 2);
|
|
|
|
|
ARC_String_Create(&lineEnd , "\n", 1);
|
|
|
|
|
|
|
|
|
|
ARC_String *singleLineStripped;
|
|
|
|
|
ARC_Config_StripComment(original, &singleLineStripped, lineStart, lineEnd);
|
|
|
|
|
|
|
|
|
|
ARC_String_Destroy(lineStart);
|
|
|
|
|
ARC_String_Destroy(lineEnd );
|
|
|
|
|
|
|
|
|
|
if(arc_errno){
|
|
|
|
|
commentRemoved = NULL;
|
|
|
|
|
return;
|
|
|
|
|
}
|
2022-10-27 15:16:54 -06:00
|
|
|
|
2023-01-17 01:59:08 -07:00
|
|
|
//Multi Line Comment
|
|
|
|
|
ARC_String_Create(&lineStart, "/*", 2);
|
|
|
|
|
ARC_String_Create(&lineEnd , "*/", 2);
|
|
|
|
|
|
|
|
|
|
ARC_Config_StripComment(singleLineStripped, commentRemoved, lineStart, lineEnd);
|
|
|
|
|
ARC_String_Destroy(singleLineStripped);
|
|
|
|
|
|
|
|
|
|
ARC_String_Destroy(lineStart);
|
|
|
|
|
ARC_String_Destroy(lineEnd );
|
2022-10-27 15:16:54 -06:00
|
|
|
}
|
|
|
|
|
|
2023-01-17 01:59:08 -07:00
|
|
|
void ARC_Config_RunCommand(ARC_Config *config, ARC_String *command){
|
|
|
|
|
ARC_String *space;
|
|
|
|
|
ARC_String_Create(&space, " " , 1);
|
|
|
|
|
|
|
|
|
|
uint64_t index = ARC_String_Find(command, space);
|
|
|
|
|
if(index == ~(uint64_t)0){
|
|
|
|
|
arc_errno = ARC_ERRNO_DATA;
|
|
|
|
|
ARC_String_Destroy(space);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ARC_String *commandOpt;
|
|
|
|
|
ARC_String_CopySubstring(&commandOpt, command, 0, index);
|
|
|
|
|
|
|
|
|
|
ARC_String *commandArgTemp, *commandArg;
|
|
|
|
|
ARC_String_CopySubstring(&commandArgTemp, command, index + space->length, command->length - (index + space->length));
|
|
|
|
|
ARC_String_StripWhitespace(commandArgTemp, &commandArg);
|
|
|
|
|
ARC_String_Destroy(commandArgTemp);
|
2022-10-27 15:16:54 -06:00
|
|
|
|
2023-01-17 01:59:08 -07:00
|
|
|
if(ARC_String_EqualsCString(command, "load", 4)){
|
|
|
|
|
ARC_Config_FileIO(config, commandArg, ARC_CONFIG_FILE_IO_LOAD);
|
|
|
|
|
}
|
|
|
|
|
else if(ARC_String_EqualsCString(command, "unload", 6)){
|
|
|
|
|
ARC_Config_FileIO(config, commandArg, ARC_CONFIG_FILE_IO_UNLOAD);
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
arc_errno = ARC_ERRNO_DATA;
|
|
|
|
|
}
|
2022-10-27 15:16:54 -06:00
|
|
|
|
2023-01-17 01:59:08 -07:00
|
|
|
ARC_String_Destroy(commandOpt);
|
|
|
|
|
ARC_String_Destroy(commandArg);
|
|
|
|
|
ARC_String_Destroy(space );
|
2022-10-27 15:16:54 -06:00
|
|
|
}
|
2023-01-17 01:59:08 -07:00
|
|
|
|
|
|
|
|
void ARC_Config_RemoveAndRunCommands(ARC_Config *config, ARC_String *original, ARC_String **commandRemoved){
|
|
|
|
|
ARC_String *current;
|
|
|
|
|
ARC_String_Copy(¤t, original);
|
|
|
|
|
|
|
|
|
|
ARC_String *lineStart, *lineEnd;
|
|
|
|
|
ARC_String_Create(&lineStart, "#" , 1);
|
|
|
|
|
ARC_String_Create(&lineEnd , "\n", 1);
|
|
|
|
|
|
|
|
|
|
uint64_t index = ARC_String_Find(current, lineStart);
|
|
|
|
|
|
|
|
|
|
while(index != ~(uint64_t)0){
|
|
|
|
|
uint64_t endIndex = ARC_String_Find(current, lineEnd);
|
|
|
|
|
if(endIndex == ~(uint64_t)0){
|
|
|
|
|
arc_errno = ARC_ERRNO_DATA;
|
|
|
|
|
ARC_String_Destroy(current );
|
|
|
|
|
ARC_String_Destroy(lineStart);
|
|
|
|
|
ARC_String_Destroy(lineEnd );
|
|
|
|
|
*commandRemoved = NULL;
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ARC_String *command;
|
|
|
|
|
ARC_String_CopySubstring(&command, current, index + lineStart->length, endIndex - (index + lineStart->length));
|
|
|
|
|
ARC_Config_RunCommand(config, command);
|
|
|
|
|
|
|
|
|
|
ARC_String *currentTemp = current;
|
|
|
|
|
ARC_String_RemoveSubstring(¤t, currentTemp, command);
|
|
|
|
|
ARC_String_Destroy(command);
|
|
|
|
|
ARC_String_Destroy(currentTemp);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ARC_String_Destroy(lineStart);
|
|
|
|
|
ARC_String_Destroy(lineEnd );
|
|
|
|
|
|
|
|
|
|
*commandRemoved = current;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void ARC_Config_FileIO(ARC_Config *config, ARC_String *path, uint8_t command){
|
|
|
|
|
ARC_String *data;
|
|
|
|
|
ARC_IO_FileToStr(path, &data);
|
|
|
|
|
if(arc_errno){
|
|
|
|
|
ARC_DEBUG_LOG(arc_errno, "ARC_IO_FileToStr(%s, &data, &size);\n", path->data);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2023-01-20 22:38:29 -07:00
|
|
|
char *tempData = (char *)malloc(sizeof(char) * (data->length + 1));
|
2023-01-17 02:57:57 -07:00
|
|
|
strncpy(tempData, data->data, data->length);
|
|
|
|
|
tempData[data->length] = '\n';
|
|
|
|
|
|
|
|
|
|
ARC_String *temp = data;
|
|
|
|
|
ARC_String_Create(&temp, tempData, data->length + 1);
|
|
|
|
|
free(tempData);
|
2023-01-17 01:59:08 -07:00
|
|
|
ARC_String_Destroy(data);
|
|
|
|
|
|
2023-01-17 02:57:57 -07:00
|
|
|
ARC_Config_RemoveComments(temp, &data);
|
|
|
|
|
ARC_String_Destroy(temp);
|
|
|
|
|
|
|
|
|
|
temp = data;
|
|
|
|
|
ARC_Config_RemoveAndRunCommands(config, temp, &data);
|
|
|
|
|
ARC_String_Destroy(temp);
|
2023-01-17 01:59:08 -07:00
|
|
|
|
2023-01-17 02:57:57 -07:00
|
|
|
temp = data;
|
|
|
|
|
ARC_String_StripEndsWhitespace(temp, &data);
|
|
|
|
|
ARC_String_Destroy(temp);
|
|
|
|
|
|
|
|
|
|
ARC_Config_Recurse(config, &data, NULL, &command);
|
|
|
|
|
if(data){
|
|
|
|
|
ARC_String_Destroy(data);
|
2023-01-17 01:59:08 -07:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int8_t ARC_Config_KeyComp(void *key1, size_t *key1size, void *key2, size_t *key2size){
|
2023-01-17 02:57:57 -07:00
|
|
|
if(*key1size - *key2size){
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
|
2023-01-17 01:59:08 -07:00
|
|
|
return strncmp((const char *)key1, (const char *)key2, *key1size);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void ARC_Config_CreateGroup(ARC_Config *config, ARC_String *name){
|
|
|
|
|
ARC_Hashtable *data;
|
|
|
|
|
ARC_Hashtable_Create(&data, ARC_GROUP_DATA_BUCKET_SIZE, NULL, ARC_Config_KeyComp);
|
|
|
|
|
|
|
|
|
|
if(name){
|
|
|
|
|
char *nameval = (char *)malloc(sizeof(char) * name->length);
|
|
|
|
|
strncpy(nameval, name->data, name->length);
|
|
|
|
|
ARC_Hashtable_Add(config->groups, nameval, name->length, (void *)data);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
char *emptyGroup = (char *)malloc(sizeof(char));
|
|
|
|
|
emptyGroup[0] = ' ';
|
|
|
|
|
ARC_Hashtable_Add(config->groups, emptyGroup, 1, (void *)data);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void ARC_Config_DestroyGroup(ARC_HashtableNode *group, void *userdata){
|
|
|
|
|
free((char *)group->key);
|
|
|
|
|
return ARC_Hashtable_Destroy((ARC_Hashtable *)group->data, ARC_Config_DestroyGroupNode, userdata);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void ARC_Config_DestroyGroupNode(ARC_HashtableNode *node, void *userdata){
|
|
|
|
|
free((char *)node->key);
|
|
|
|
|
|
|
|
|
|
ARC_ConfigTypeTemplate *temp = (ARC_ConfigTypeTemplate *)node->data;
|
|
|
|
|
if(temp->Delete && temp->data && userdata){
|
2023-01-20 22:38:29 -07:00
|
|
|
ARC_ConfigDeleteKeyArgs *args = (ARC_ConfigDeleteKeyArgs *)userdata;
|
2023-01-17 01:59:08 -07:00
|
|
|
|
2023-01-20 22:38:29 -07:00
|
|
|
temp->Delete(args->config, args->string, temp->data);
|
2023-01-17 01:59:08 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
free(temp);
|
|
|
|
|
node->data = NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void ARC_Config_RemoveKey(ARC_HashtableNode *node, void *userdata){
|
|
|
|
|
free((char *)node->key);
|
|
|
|
|
|
|
|
|
|
if(!node->data){
|
|
|
|
|
arc_errno = ARC_ERRNO_NULL;
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
free((ARC_ConfigKey *)node->data);
|
|
|
|
|
}
|