first
This commit is contained in:
commit
db1adbb838
35 changed files with 4408 additions and 0 deletions
417
src/std/config.c
Normal file
417
src/std/config.c
Normal file
|
|
@ -0,0 +1,417 @@
|
|||
#include "arc/std/config.h"
|
||||
|
||||
#include "arc/std/errno.h"
|
||||
#include "arc/std/io.h"
|
||||
#include <stdio.h>
|
||||
#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 {
|
||||
ARC_ConfigKey *key;
|
||||
|
||||
void *data;
|
||||
} ARC_ConfigTypeTemplate;
|
||||
|
||||
typedef struct ARC_DeleteUserData {
|
||||
ARC_Config *config;
|
||||
|
||||
const char* data;
|
||||
ARC_StringSubstr *subdata;
|
||||
} ARC_DeleteUserData;
|
||||
|
||||
int32_t ARC_Config_KeyComp(void *key1, size_t *key1size, void *key2, size_t *key2size){
|
||||
if(*key1size - *key2size){ return -1; }
|
||||
return strncmp((const char *)key1, (const char *)key2, *key1size);
|
||||
}
|
||||
|
||||
int32_t ARC_ConfigKey_Add(ARC_Config *config, char *type, ARC_ConfigKeyRead keyRead, ARC_ConfigKeyDelete keyDelete){
|
||||
ARC_ConfigKey *temp = (ARC_ConfigKey *)malloc(sizeof(ARC_ConfigKey));
|
||||
temp->Read = keyRead;
|
||||
temp->Delete = keyDelete;
|
||||
return ARC_Hashtable_Add(config->keys, (void *)type, strlen(type), (void *)temp);
|
||||
}
|
||||
|
||||
int32_t ARC_ConfigKey_Destroy(ARC_HashtableNode *node, void *userdata){
|
||||
if(!node->data){ return ARC_ERRNO_NULL; }
|
||||
free((ARC_ConfigKey *)node->data);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int32_t ARC_ConfigGroup_Create(ARC_Config *config, const char *name){
|
||||
ARC_Hashtable *data;
|
||||
ARC_Hashtable_Create(&data, ARC_GROUP_DATA_BUCKET_SIZE, NULL, ARC_Config_KeyComp);
|
||||
|
||||
char *group = (char *) malloc(sizeof(char) * strlen(name));
|
||||
strncpy(group, name, strlen(name));
|
||||
|
||||
return ARC_Hashtable_Add(config->groups, (void *)group, strlen(name), (void *)data);
|
||||
}
|
||||
|
||||
int32_t ARC_ConfigGroupNode_Destroy(ARC_HashtableNode *node, void *userdata){
|
||||
free((char *)node->key);
|
||||
|
||||
ARC_ConfigTypeTemplate *temp = (ARC_ConfigTypeTemplate *)node->data;
|
||||
if(temp->key){
|
||||
ARC_DeleteUserData *deldata = (ARC_DeleteUserData *)userdata;
|
||||
temp->key->Delete(deldata->config, deldata->data, deldata->subdata, temp->data);
|
||||
}
|
||||
|
||||
free(temp);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int32_t ARC_ConfigGroup_Destroy(ARC_HashtableNode *group, void *userdata){
|
||||
free((char *)group->key);
|
||||
return ARC_Hashtable_Destroy((ARC_Hashtable *)group->data, ARC_ConfigGroupNode_Destroy, userdata);
|
||||
}
|
||||
|
||||
int32_t ARC_Config_Create(ARC_Config **config, ARC_ConfigKey_AddFunc keysAdd){
|
||||
*config = (ARC_Config *) malloc(sizeof(ARC_Config));
|
||||
(*config)->currgroup = NULL;
|
||||
|
||||
ARC_Hashtable *groups;
|
||||
ARC_Hashtable_Create(&groups, ARC_GROUP_BUCKET_SIZE, NULL, ARC_Config_KeyComp);
|
||||
(*config)->groups = groups;
|
||||
ARC_ConfigGroup_Create(*config, "");
|
||||
|
||||
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
|
||||
|
||||
if(keysAdd){ keysAdd(*config); }
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int32_t ARC_Config_Destroy(ARC_Config *config){
|
||||
ARC_DeleteUserData deldata = { .config = config, .data = NULL, .subdata = NULL };
|
||||
int32_t err = ARC_Hashtable_Destroy(config->groups, ARC_ConfigGroup_Destroy, (void *)&deldata);
|
||||
if(err){ return err; }
|
||||
|
||||
err = ARC_Hashtable_Destroy(config->keys, ARC_ConfigKey_Destroy, NULL);
|
||||
if(err){ return err; }
|
||||
|
||||
free(config);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int32_t ARC_Config_Get(ARC_Config *config, char *keyname, void **value){
|
||||
uint64_t len = 0;
|
||||
ARC_ConfigTypeTemplate *temp;
|
||||
|
||||
int32_t err = ARC_String_Find(keyname, (char *)"::", &len);
|
||||
if(err){ return err; }
|
||||
|
||||
if(len != ~((uint64_t)0)){
|
||||
char group[len + 1];
|
||||
strncpy(group, keyname, len);
|
||||
group[len] = '\0';
|
||||
|
||||
ARC_Hashtable *currgroup = config->currgroup;
|
||||
err = ARC_Config_SetGroup(config, group);
|
||||
if(err){ return err; }
|
||||
|
||||
char *namestr = (len + 2) + keyname;
|
||||
char name[strlen(namestr)];
|
||||
strcpy(name, namestr);
|
||||
|
||||
err = ARC_Hashtable_Get(config->currgroup, (void *)name, strlen(name), (void **)&temp);
|
||||
if(err){ return err; }
|
||||
|
||||
config->currgroup = currgroup;
|
||||
*value = temp->data;
|
||||
return 0;
|
||||
}
|
||||
|
||||
err = ARC_Hashtable_Get(config->currgroup, (void *)keyname, strlen(keyname), (void **)&temp);
|
||||
if(err){ return err; }
|
||||
|
||||
*value = temp->data;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int32_t ARC_Config_Remove(ARC_Config *config, const char *keyname, const char* data, ARC_StringSubstr *subdata){
|
||||
ARC_DeleteUserData deldata = { .config = config, .data = data, .subdata = subdata };
|
||||
printf("data: %s\n\n", data);
|
||||
return ARC_Hashtable_Remove(config->currgroup, (void *)keyname, strlen(keyname), ARC_ConfigGroupNode_Destroy, (void *)&deldata);
|
||||
}
|
||||
|
||||
int32_t ARC_Config_SetGroup(ARC_Config *config, char *groupstr){
|
||||
int err = ARC_Hashtable_Get(config->groups, groupstr, strlen(groupstr), (void **)&(config->currgroup));
|
||||
if(err && err != ARC_ERRNO_NULL){ return err; }
|
||||
|
||||
if(!(config->currgroup)){
|
||||
err = ARC_ConfigGroup_Create(config, groupstr);
|
||||
if(err){ return err; }
|
||||
|
||||
err = ARC_Hashtable_Get(config->groups, groupstr, strlen(groupstr), (void **)&(config->currgroup));
|
||||
if(err){ return err; }
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void ARC_ConfigPath_Create(char *data, ARC_StringSubstr *subpath, char **path){
|
||||
if(*(data + subpath->index) == '~'){
|
||||
*path = (char *) malloc(sizeof(char) * (subpath->length + strlen(ARC_HOME_PATH) + 1));
|
||||
strcpy(*path, ARC_HOME_PATH);
|
||||
strncpy((*path) + strlen(ARC_HOME_PATH) - 1, data + subpath->index, subpath->length);
|
||||
(*path)[subpath->length + strlen(ARC_HOME_PATH)] = '\0';
|
||||
return;
|
||||
}
|
||||
|
||||
*path = (char *) malloc(sizeof(char) * (subpath->length + 1));
|
||||
strncpy(*path, data + subpath->index, subpath->length);
|
||||
(*path)[subpath->length] = '\0';
|
||||
}
|
||||
|
||||
void ARC_ConfigPath_Destroy(char *url){
|
||||
free(url);
|
||||
}
|
||||
|
||||
int32_t ARC_Config_Recurse(ARC_Config *config, char *data, uint64_t *size, char *groupstr, ARC_StringSubstr *subkey, uint8_t *command);
|
||||
|
||||
int32_t ARC_ConfigKey_Command(ARC_Config *config, char *data, uint64_t *size, ARC_StringSubstr *subkey){
|
||||
ARC_StringSubstr subcommand = { subkey->index + 1, 0 };
|
||||
int32_t err = ARC_String_Find(data + subcommand.index, " ", &(subcommand.length));
|
||||
if(err){ return err; }
|
||||
if(subcommand.length == ~((uint64_t)0)){ return ARC_ERRNO_DATA; }
|
||||
subkey->index += subcommand.length + 1;
|
||||
|
||||
ARC_StringSubstr_StripEnds(data, NULL, &subcommand);
|
||||
if(strncmp("load", data + subcommand.index, strlen("load")) && strncmp("unload", data + subcommand.index, strlen("unload"))){ return ARC_ERRNO_DATA; }
|
||||
|
||||
ARC_StringSubstr subpath = { subkey->index, 0 };
|
||||
err = ARC_String_Find(data + subpath.index, (char *)"\"", &(subpath.index));
|
||||
if(err){ return err; }
|
||||
if(subpath.length == ~((uint64_t)0)){ return ARC_ERRNO_DATA; }
|
||||
subkey->index += subpath.length + 2; //we want to skip over the first \" that is why it is 2 not 1
|
||||
|
||||
subpath = (ARC_StringSubstr) { subkey->index, 0 };
|
||||
err = ARC_String_Find(data + subpath.index, (char *)"\"", &(subpath.length));
|
||||
if(err){ return err; }
|
||||
if(subpath.length == ~((uint64_t)0)){ return ARC_ERRNO_DATA; }
|
||||
subkey->index += subpath.length + 1;
|
||||
|
||||
char *path;
|
||||
ARC_ConfigPath_Create(data, &subpath, &path);
|
||||
|
||||
if (!strncmp( "load", data + subcommand.index, strlen( "load"))){ err = ARC_Config_FileIO(config, path, ARC_CONFIG_FILE_IO_LOAD ); }
|
||||
else if(!strncmp("unload", data + subcommand.index, strlen("unload"))){ err = ARC_Config_FileIO(config, path, ARC_CONFIG_FILE_IO_UNLOAD); }
|
||||
else { return ARC_ERRNO_DATA; }
|
||||
|
||||
ARC_ConfigPath_Destroy(path);
|
||||
return err;
|
||||
}
|
||||
|
||||
int32_t ARC_ConfigKey_Comment(ARC_Config *config, char *data, uint64_t *size, ARC_StringSubstr *subkey){
|
||||
uint64_t commentlen = 0;
|
||||
if(data[subkey->index + 1] == '*'){
|
||||
int32_t err = ARC_String_Find(data + subkey->index, (char *)"*/", &commentlen);
|
||||
if(err){ return err; }
|
||||
|
||||
subkey->index += commentlen + 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int32_t err = ARC_String_Find(data + subkey->index, (char *)"\n", &commentlen);
|
||||
if(err){ return err; }
|
||||
|
||||
subkey->index += commentlen + 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int32_t ARC_ConfigKey_Group(ARC_Config *config, char *data, uint64_t *size, ARC_StringSubstr *subkey, uint8_t *command){
|
||||
ARC_StringSubstr subgroup = { subkey->index, 0 };
|
||||
int32_t err = ARC_String_Find(data + subgroup.index, "{", &(subgroup.length));
|
||||
if(err){ return err; }
|
||||
if(subgroup.length == ~((uint64_t)0)){ return ARC_ERRNO_DATA; }
|
||||
subkey->index += subgroup.length + 1;
|
||||
|
||||
ARC_StringSubstr_StripEnds(data, NULL, &subgroup);
|
||||
|
||||
char groupstr[subgroup.length + 1];
|
||||
strncpy(groupstr, data + subgroup.index, subgroup.length);
|
||||
groupstr[subgroup.length] = '\0';
|
||||
|
||||
return ARC_Config_Recurse(config, data, size, groupstr, subkey, command);
|
||||
}
|
||||
|
||||
int32_t ARC_ConfigKey_Load(ARC_Config *config, char *data, uint64_t *size, char *keyname, ARC_StringSubstr *subkey){
|
||||
ARC_ConfigKey *key;
|
||||
int32_t err = ARC_Hashtable_Get(config->keys, (void *)keyname, strlen(keyname), (void **)&key);
|
||||
if(err){ return err; }
|
||||
|
||||
ARC_StringSubstr subname = { subkey->index, 0 };
|
||||
err = ARC_String_Find(data + subname.index, (char *)"=", &(subname.length));
|
||||
if(err){ return err; }
|
||||
if(subname.length == ~((uint64_t)0)){ return ARC_ERRNO_DATA; }
|
||||
subkey->index += subname.length + 1;
|
||||
|
||||
ARC_StringSubstr_StripEnds(data, NULL, &subname);
|
||||
|
||||
ARC_StringSubstr subvalue = { subkey->index, 0 };
|
||||
err = ARC_String_Find(data + subvalue.index, (char *)";", &(subvalue.length));
|
||||
if(err){ return err; }
|
||||
if(subvalue.length == ~((uint64_t)0)){ return ARC_ERRNO_DATA; }
|
||||
subkey->index += subvalue.length + 1;
|
||||
|
||||
ARC_StringSubstr_StripEnds(data, NULL, &subvalue);
|
||||
ARC_ConfigTypeTemplate *templateVal = NULL;
|
||||
|
||||
char *name = malloc(sizeof(char) * subname.length + 1);
|
||||
strncpy(name, data + subname.index, sizeof(char) * subname.length);
|
||||
name[subname.length] = '\0';
|
||||
|
||||
templateVal = (ARC_ConfigTypeTemplate *) malloc(sizeof(ARC_ConfigTypeTemplate));
|
||||
templateVal->key = NULL;
|
||||
templateVal->data = ARC_Config_GetReference(config, data, &subvalue);
|
||||
|
||||
if(!templateVal->data){
|
||||
err = key->Read(config, data, &subvalue, &(templateVal->data));
|
||||
if(err){ return err; }
|
||||
templateVal->key = key;
|
||||
}
|
||||
|
||||
return ARC_Hashtable_Add(config->currgroup, (void *)name, strlen(name), (void *)templateVal);
|
||||
}
|
||||
|
||||
int32_t ARC_ConfigKey_Unload(ARC_Config *config, char *data, uint64_t *size, char *keyname, ARC_StringSubstr *subkey){
|
||||
ARC_StringSubstr subname = { subkey->index, 0 };
|
||||
int32_t err = ARC_String_Find(data + subname.index, (char *)"=", &(subname.length));
|
||||
if(err){ return err; }
|
||||
if(subname.length == ~((uint64_t)0)){ return ARC_ERRNO_DATA; }
|
||||
subkey->index += subname.length + 1;
|
||||
|
||||
ARC_StringSubstr_StripEnds(data, NULL, &subname);
|
||||
char name[subname.length + 1];
|
||||
strncpy(name, data + subname.index, subname.length);
|
||||
name[subname.length] = '\0';
|
||||
|
||||
subname = (ARC_StringSubstr){ subkey->index, 0 };
|
||||
err = ARC_String_Find(data + subname.index, (char *)";", &(subname.length));
|
||||
if(err){ return err; }
|
||||
if(subname.length == ~((uint64_t)0)){ return ARC_ERRNO_DATA; }
|
||||
subkey->index += subname.length + 1;
|
||||
|
||||
return ARC_Config_Remove(config, name, data, &subname);
|
||||
}
|
||||
|
||||
int32_t ARC_Config_Recurse(ARC_Config *config, char *data, uint64_t *size, char *groupstr, ARC_StringSubstr *subkey, uint8_t *command){
|
||||
int32_t err = ARC_Config_SetGroup(config, groupstr);
|
||||
if(err){ return err; }
|
||||
ARC_Hashtable *group = config->currgroup;
|
||||
|
||||
while(subkey->index < *size){
|
||||
if(data[subkey->index] == ' ' || data[subkey->index] == '\n' || data[subkey->index] == '\t' || data[subkey->index] == '\r'){
|
||||
subkey->index++;
|
||||
continue;
|
||||
}
|
||||
|
||||
if(data[subkey->index] == '}'){
|
||||
config->currgroup = NULL;
|
||||
subkey->index++;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if(data[subkey->index] == '#'){
|
||||
err = ARC_ConfigKey_Command(config, data, size, subkey);
|
||||
if(err){ return err; }
|
||||
continue;
|
||||
}
|
||||
|
||||
if(data[subkey->index] == '/'){
|
||||
err = ARC_ConfigKey_Comment(config, data, size, subkey);
|
||||
if(err){ return err; }
|
||||
continue;
|
||||
}
|
||||
|
||||
err = ARC_String_Find(data + subkey->index, (char *)" ", &(subkey->length));
|
||||
if(err){ return err; }
|
||||
if(subkey->length == ~((uint64_t)0)){ return 0; }
|
||||
|
||||
if(!(config->currgroup)){
|
||||
config->currgroup = group;
|
||||
}
|
||||
|
||||
char keyname[subkey->length + 1];
|
||||
strncpy(keyname, data + subkey->index, subkey->length);
|
||||
keyname[subkey->length] = '\0';
|
||||
subkey->index += subkey->length + 1;
|
||||
|
||||
if(subkey->length == strlen("group") && !strcmp(keyname, "group")){
|
||||
err = ARC_ConfigKey_Group(config, data, size, subkey, command);
|
||||
if(err){ return err; }
|
||||
continue;
|
||||
}
|
||||
|
||||
if(*command == ARC_CONFIG_FILE_IO_LOAD){
|
||||
err = ARC_ConfigKey_Load(config, data, size, keyname, subkey);
|
||||
if(err){ return err; }
|
||||
continue;
|
||||
}
|
||||
|
||||
if(*command == ARC_CONFIG_FILE_IO_UNLOAD){
|
||||
err = ARC_ConfigKey_Unload(config, data, size, keyname, subkey);
|
||||
if(err){ return err;}
|
||||
continue;
|
||||
}
|
||||
|
||||
return ARC_ERRNO_DATA;
|
||||
}
|
||||
|
||||
config->currgroup = group;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int32_t ARC_Config_FileIO(ARC_Config *config, const char *pathstr, uint8_t command){
|
||||
char *path, *data;
|
||||
uint64_t size;
|
||||
ARC_StringSubstr subpath = { 0, strlen(pathstr) };
|
||||
ARC_ConfigPath_Create((char *)pathstr, &subpath, &path);
|
||||
|
||||
int32_t err = ARC_IO_FileToStr(path, &data, &size);
|
||||
if(err){
|
||||
ARC_DEBUG_LOG(err, "ARC_IO_FileToStr(%s, &data, &size);\n", path);
|
||||
ARC_ConfigPath_Destroy(path);
|
||||
return err;
|
||||
}
|
||||
|
||||
ARC_ConfigPath_Destroy(path);
|
||||
|
||||
ARC_StringSubstr subkey = { 0, 0 };
|
||||
err = ARC_Config_Recurse(config, data, &size, "", &subkey, &command);
|
||||
if(err){ return err; }
|
||||
|
||||
free(data);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void *ARC_Config_GetReference(ARC_Config *config, char *data, ARC_StringSubstr *subdata){
|
||||
if(ARC_String_Alpha(data + subdata->index, 1) && *(data + subdata->index) != ':'){ return NULL; }
|
||||
|
||||
char refname[subdata->length + 1];
|
||||
strncpy(refname, data + subdata->index, subdata->length);
|
||||
refname[subdata->length] = 0;
|
||||
|
||||
void *value;
|
||||
int32_t err = ARC_Config_Get(config, refname, &value);
|
||||
return (err)? NULL : value;
|
||||
}
|
||||
116
src/std/defaults/config.c
Normal file
116
src/std/defaults/config.c
Normal file
|
|
@ -0,0 +1,116 @@
|
|||
#ifdef ARC_DEFAULT_CONFIG
|
||||
|
||||
#include "arc/std/defaults/config.h"
|
||||
|
||||
#include "arc/std/config.h"
|
||||
#include "arc/std/errno.h"
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
int32_t ARC_Defaults_ConfigKey_Create(ARC_Config *config){
|
||||
ARC_ConfigKey_Add(config, "uint8_t" , ARC_ConfigKey_Read_Uint8_t , ARC_ConfigKey_Delete_Uint8_t );
|
||||
ARC_ConfigKey_Add(config, "int8_t" , ARC_ConfigKey_Read_Int8_t , ARC_ConfigKey_Delete_Int8_t );
|
||||
// ARC_ConfigKey_Add(config, "char" , ARC_ConfigKey_Read_Char , ARC_ConfigKey_Delete_Char );
|
||||
ARC_ConfigKey_Add(config, "uint16_t", ARC_ConfigKey_Read_Uint16_t, ARC_ConfigKey_Delete_Uint16_t);
|
||||
ARC_ConfigKey_Add(config, "int16_t" , ARC_ConfigKey_Read_Int16_t , ARC_ConfigKey_Delete_Int16_t );
|
||||
ARC_ConfigKey_Add(config, "uint32_t", ARC_ConfigKey_Read_Uint32_t, ARC_ConfigKey_Delete_Uint32_t);
|
||||
ARC_ConfigKey_Add(config, "int32_t" , ARC_ConfigKey_Read_Int32_t , ARC_ConfigKey_Delete_Int32_t );
|
||||
ARC_ConfigKey_Add(config, "int" , ARC_ConfigKey_Read_Int , ARC_ConfigKey_Delete_Int );
|
||||
ARC_ConfigKey_Add(config, "uint64_t", ARC_ConfigKey_Read_Uint64_t, ARC_ConfigKey_Delete_Uint64_t);
|
||||
ARC_ConfigKey_Add(config, "int64_t" , ARC_ConfigKey_Read_Int64_t , ARC_ConfigKey_Delete_Int64_t );
|
||||
ARC_ConfigKey_Add(config, "long" , ARC_ConfigKey_Read_Long , ARC_ConfigKey_Delete_Long );
|
||||
ARC_ConfigKey_Add(config, "string" , ARC_ConfigKey_Read_String , ARC_ConfigKey_Delete_String );
|
||||
return 0;
|
||||
}
|
||||
|
||||
int32_t ARC_ConfigKey_Read_Uint8_t(ARC_Config* config, const char *data, ARC_StringSubstr *subdata, void **value){
|
||||
*value = (uint8_t *) malloc(sizeof(uint8_t));
|
||||
*((uint8_t *)(*value)) = (uint8_t) ARC_String_ToUint64_t(data, subdata);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int32_t ARC_ConfigKey_Read_Int8_t(ARC_Config* config, const char *data, ARC_StringSubstr *subdata, void **value){
|
||||
*value = (int8_t *) malloc(sizeof(int8_t));
|
||||
*((int8_t *)(*value)) = (int8_t) ARC_String_ToUint64_t(data, subdata);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int32_t ARC_ConfigKey_Read_Char(ARC_Config* config, const char *data, ARC_StringSubstr *subdata, void **value){
|
||||
*value = (char *) malloc(sizeof(char));
|
||||
*((char *)(* value)) = (char) *(data + subdata->index);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int32_t ARC_ConfigKey_Read_Uint16_t(ARC_Config* config, const char *data, ARC_StringSubstr *subdata, void **value){
|
||||
*value = (uint16_t *) malloc(sizeof(uint16_t));
|
||||
*((uint16_t *)(*value)) = (uint16_t) ARC_String_ToUint64_t(data, subdata);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int32_t ARC_ConfigKey_Read_Int16_t(ARC_Config* config, const char *data, ARC_StringSubstr *subdata, void **value){
|
||||
*value = (int16_t *) malloc(sizeof(int16_t));
|
||||
*((int16_t *)(*value)) = (int16_t) ARC_String_ToUint64_t(data, subdata);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int32_t ARC_ConfigKey_Read_Uint32_t(ARC_Config* config, const char *data, ARC_StringSubstr *subdata, void **value){
|
||||
*value = (uint32_t *) malloc(sizeof(uint32_t));
|
||||
*((uint32_t *)(*value)) = (uint32_t) ARC_String_ToUint64_t(data, subdata);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int32_t ARC_ConfigKey_Read_Int32_t(ARC_Config* config, const char *data, ARC_StringSubstr *subdata, void **value){
|
||||
*value = (int32_t *) malloc(sizeof(int32_t));
|
||||
*((int32_t *)(*value)) = (int32_t) ARC_String_ToUint64_t(data, subdata);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int32_t ARC_ConfigKey_Read_Int(ARC_Config* config, const char *data, ARC_StringSubstr *subdata, void **value){
|
||||
*value = (int *) malloc(sizeof(int));
|
||||
*((int *)(*value)) = (int) ARC_String_ToUint64_t(data, subdata);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int32_t ARC_ConfigKey_Read_Uint64_t(ARC_Config* config, const char *data, ARC_StringSubstr *subdata, void **value){
|
||||
*value = (uint64_t *) malloc(sizeof(uint64_t));
|
||||
*((uint64_t *)(*value)) = ARC_String_ToUint64_t(data, subdata);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int32_t ARC_ConfigKey_Read_Int64_t(ARC_Config* config, const char *data, ARC_StringSubstr *subdata, void **value){
|
||||
*value = (int64_t *) malloc(sizeof(int64_t));
|
||||
*((int64_t *)(*value)) = (int64_t) ARC_String_ToUint64_t(data, subdata);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int32_t ARC_ConfigKey_Read_Long(ARC_Config* config, const char *data, ARC_StringSubstr *subdata, void **value){
|
||||
*value = (long *) malloc(sizeof(long));
|
||||
*((long *)(*value)) = (long) ARC_String_ToUint64_t(data, subdata);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int32_t ARC_ConfigKey_Read_String(ARC_Config* config, const char *data, ARC_StringSubstr *subdata, void **value){
|
||||
ARC_StringSubstr_StripWhitespaceEnds((char *)data, subdata);
|
||||
if(data[subdata->index] != '"' || data[subdata->index + subdata->length] != '"'){ return ARC_ERRNO_DATA; }
|
||||
ARC_StringSubstr_StripEnds((char *)data, (char *)"\"", subdata);
|
||||
*value = (char *) malloc(sizeof(char) * (subdata->length + 1));
|
||||
strncpy((char *)(*value), data + subdata->index, subdata->length);
|
||||
((char *)(*value))[subdata->length] = '\0';
|
||||
return 0;
|
||||
}
|
||||
|
||||
int32_t ARC_ConfigKey_Delete_Uint8_t (ARC_Config* config, const char* data, ARC_StringSubstr *subdata, void *value){ if((uint8_t *)value){ free((uint8_t *)value); } return 0; }
|
||||
int32_t ARC_ConfigKey_Delete_Int8_t (ARC_Config* config, const char* data, ARC_StringSubstr *subdata, void *value){ if((int8_t *)value){ free((int8_t *)value); } return 0; }
|
||||
int32_t ARC_ConfigKey_Delete_Char (ARC_Config* config, const char* data, ARC_StringSubstr *subdata, void *value){ if((char *)value){ free((char *)value); } return 0; }
|
||||
int32_t ARC_ConfigKey_Delete_Uint16_t(ARC_Config* config, const char* data, ARC_StringSubstr *subdata, void *value){ if((uint16_t *)value){ free((uint16_t *)value); } return 0; }
|
||||
int32_t ARC_ConfigKey_Delete_Int16_t (ARC_Config* config, const char* data, ARC_StringSubstr *subdata, void *value){ if((int16_t *)value){ free((int16_t *)value); } return 0; }
|
||||
int32_t ARC_ConfigKey_Delete_Uint32_t(ARC_Config* config, const char* data, ARC_StringSubstr *subdata, void *value){ if((uint32_t *)value){ free((uint32_t *)value); } return 0; }
|
||||
int32_t ARC_ConfigKey_Delete_Int32_t (ARC_Config* config, const char* data, ARC_StringSubstr *subdata, void *value){ if((int32_t *)value){ free((int32_t *)value); } return 0; }
|
||||
int32_t ARC_ConfigKey_Delete_Int (ARC_Config* config, const char* data, ARC_StringSubstr *subdata, void *value){ if((int *)value){ free((int *)value); } return 0; }
|
||||
int32_t ARC_ConfigKey_Delete_Uint64_t(ARC_Config* config, const char* data, ARC_StringSubstr *subdata, void *value){ if((uint64_t *)value){ free((uint64_t *)value); } return 0; }
|
||||
int32_t ARC_ConfigKey_Delete_Int64_t (ARC_Config* config, const char* data, ARC_StringSubstr *subdata, void *value){ if((int64_t *)value){ free((int64_t *)value); } return 0; }
|
||||
int32_t ARC_ConfigKey_Delete_Long (ARC_Config* config, const char* data, ARC_StringSubstr *subdata, void *value){ if((long *)value){ free((long *)value); } return 0; }
|
||||
int32_t ARC_ConfigKey_Delete_String (ARC_Config* config, const char* data, ARC_StringSubstr *subdata, void *value){ if((char *)value){ free((char *)value); } return 0; }
|
||||
|
||||
#endif //ARC_DEFAULT_CONFIG
|
||||
68
src/std/handler.c
Normal file
68
src/std/handler.c
Normal file
|
|
@ -0,0 +1,68 @@
|
|||
#include "arc/std/handler.h"
|
||||
|
||||
#include "arc/std/errno.h"
|
||||
#include "arc/std/vector.h"
|
||||
#include <stdlib.h>
|
||||
|
||||
struct ARC_Handler {
|
||||
ARC_Vector *data;
|
||||
ARC_Vector *trash;
|
||||
};
|
||||
|
||||
void ARC_Handler_Create(ARC_Handler **handler){
|
||||
*handler = (ARC_Handler *) malloc(sizeof(ARC_Handler));
|
||||
ARC_Vector_Create(&((*handler)->data), sizeof(void *));
|
||||
ARC_Vector_Create(&((*handler)->trash), sizeof(void *));
|
||||
}
|
||||
|
||||
void ARC_Handler_Destroy(ARC_Handler *handler, ARC_Handler_CleanDataFn cleanfn){
|
||||
ARC_Handler_Clear(handler);
|
||||
ARC_Handler_Clean(handler, cleanfn);
|
||||
|
||||
ARC_Vector_Destroy(handler->data);
|
||||
ARC_Vector_Destroy(handler->trash);
|
||||
|
||||
free(handler);
|
||||
}
|
||||
|
||||
void ARC_Handler_Add(ARC_Handler *handler, void *data){
|
||||
ARC_Vector_Add(handler->data, data);
|
||||
}
|
||||
|
||||
int8_t ARC_Handler_RemoveCompareFn(void *a, void *b){ return a == b; }
|
||||
|
||||
void ARC_Handler_Remove(ARC_Handler *handler, void *data){
|
||||
ARC_Vector_Remove(handler->data, data, ARC_Handler_RemoveCompareFn);
|
||||
ARC_Vector_Add(handler->trash, data);
|
||||
}
|
||||
|
||||
void ARC_Handler_RemoveIndex(ARC_Handler *handler, uint32_t *index){
|
||||
void *data = ARC_Vector_Get(handler->data, index);
|
||||
ARC_Vector_RemoveIndex(handler->data, index);
|
||||
ARC_Vector_Add(handler->trash, data);
|
||||
}
|
||||
|
||||
void ARC_Handler_Iterate(ARC_Handler *handler, ARC_Handler_DataFn datafn){
|
||||
for(uint32_t i = 0; i < *ARC_Vector_Size(handler->data); i++){
|
||||
datafn(ARC_Vector_Get(handler->data, &i));
|
||||
}
|
||||
}
|
||||
|
||||
void ARC_Handler_Clear(ARC_Handler *handler){
|
||||
while(*ARC_Vector_Size(handler->data)){
|
||||
ARC_Handler_Remove(handler, 0);
|
||||
}
|
||||
}
|
||||
|
||||
void ARC_Handler_Clean(ARC_Handler *handler, ARC_Handler_CleanDataFn cleanfn){
|
||||
uint32_t i = 0;
|
||||
while(*ARC_Vector_Size(handler->trash)){
|
||||
void *data = ARC_Vector_Get(handler->trash, &i);
|
||||
cleanfn(data);
|
||||
ARC_Vector_RemoveIndex(handler->trash, &i);
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t *ARC_Handler_Size(ARC_Handler *handler){
|
||||
return ARC_Vector_Size(handler->data);
|
||||
}
|
||||
167
src/std/hashtable.c
Normal file
167
src/std/hashtable.c
Normal file
|
|
@ -0,0 +1,167 @@
|
|||
#include "arc/std/hashtable.h"
|
||||
|
||||
#include "arc/std/errno.h"
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
|
||||
struct ARC_Hashtable {
|
||||
uint32_t size;
|
||||
ARC_HashtableNode **nodes;
|
||||
ARC_Hashtable_Hash hash;
|
||||
ARC_Hashtable_KeyCompare compare;
|
||||
};
|
||||
|
||||
int32_t CRC32(void *key, size_t *keysize, uint32_t *hashval){
|
||||
*hashval = 0xffffffff;
|
||||
|
||||
for(size_t i = 0; i < *keysize; i++){
|
||||
uint8_t value = *(((uint8_t *)key) + i);
|
||||
for(uint8_t j = 0; j < 8; j++){
|
||||
uint8_t flag = (uint8_t)((value ^ *hashval) & 1);
|
||||
*hashval >>= 1;
|
||||
if(flag){ *hashval ^= 0xEDB888320; }
|
||||
value >>= 1;
|
||||
}
|
||||
}
|
||||
|
||||
*hashval = ~*hashval;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int32_t ARC_Default_Key_Compare(void *key1, size_t *key1size, void *key2, size_t *key2size){
|
||||
return key1 - key2;
|
||||
}
|
||||
|
||||
void ARC_HashtableNode_Create(ARC_HashtableNode **node, void *key, size_t *keysize, void *data){
|
||||
*node = (ARC_HashtableNode *) malloc(sizeof(ARC_HashtableNode));
|
||||
(*node)->key = key;
|
||||
(*node)->keysize = *keysize;
|
||||
(*node)->data = data;
|
||||
(*node)->node = NULL;
|
||||
}
|
||||
|
||||
int32_t ARC_HashtableNode_Destroy(ARC_HashtableNode *node, ARC_HashtableNode_DestroyExternal external, void *userdata){
|
||||
if(node == NULL){ return 0; }
|
||||
ARC_HashtableNode_Destroy(node->node, external, userdata);
|
||||
|
||||
if(external){
|
||||
int32_t err = external(node, userdata);
|
||||
if(err){ return err; }
|
||||
}
|
||||
|
||||
free(node);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void ARC_Hashtable_Create(ARC_Hashtable **htable, uint32_t bucketsize, ARC_Hashtable_Hash hash, ARC_Hashtable_KeyCompare compare){
|
||||
*htable = (ARC_Hashtable *) malloc(sizeof(ARC_Hashtable));
|
||||
(*htable)->size = bucketsize;
|
||||
(*htable)->nodes = (ARC_HashtableNode **) calloc(bucketsize, sizeof(ARC_HashtableNode *));
|
||||
(*htable)->hash = (hash)? hash : CRC32;
|
||||
(*htable)->compare = (compare)? compare : ARC_Default_Key_Compare;
|
||||
}
|
||||
|
||||
int32_t ARC_Hashtable_Destroy(ARC_Hashtable *htable, ARC_HashtableNode_DestroyExternal external, void *userdata){
|
||||
for(uint32_t i = 0; i < htable->size; i++){
|
||||
if(htable->nodes[i]){
|
||||
int32_t err = ARC_HashtableNode_Destroy(htable->nodes[i], external, userdata);
|
||||
if(err){ return err; }
|
||||
}
|
||||
}
|
||||
|
||||
free(htable->nodes);
|
||||
free(htable);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int32_t ARC_Hashtable_Add(ARC_Hashtable *htable, void *key, size_t keysize, void *data){
|
||||
uint32_t size = 0;
|
||||
int32_t err = htable->hash(key, &keysize, &size);
|
||||
if(err){ return err; }
|
||||
|
||||
ARC_HashtableNode *bucket = htable->nodes[size % htable->size];
|
||||
if(!bucket){
|
||||
ARC_HashtableNode_Create(&bucket, key, &keysize, data);
|
||||
htable->nodes[size % htable->size] = bucket;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if(!htable->compare(bucket->key, &bucket->keysize, key, &keysize)){ return ARC_ERRNO_EXISTS; }
|
||||
|
||||
while(bucket->node){
|
||||
if(!htable->compare(bucket->node->key, &bucket->node->keysize, key, &keysize)){ return ARC_ERRNO_EXISTS; }
|
||||
bucket = bucket->node;
|
||||
}
|
||||
|
||||
ARC_HashtableNode_Create(&(bucket->node), key, &keysize, data);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int32_t ARC_Hashtable_Get(ARC_Hashtable *htable, void *key, size_t keysize, void **data){
|
||||
uint32_t size = 0;
|
||||
int32_t err = htable->hash(key, &keysize, &size);
|
||||
if(err){ return err; }
|
||||
|
||||
ARC_HashtableNode *bucket = htable->nodes[size % htable->size];
|
||||
if(!bucket){
|
||||
*data = NULL;
|
||||
return ARC_ERRNO_NULL;
|
||||
}
|
||||
|
||||
if(!htable->compare(bucket->key, &bucket->keysize, key, &keysize)){
|
||||
*data = bucket->data;
|
||||
return 0;
|
||||
}
|
||||
|
||||
while(bucket->node){
|
||||
if(!htable->compare(bucket->node->key, &bucket->node->keysize, key, &keysize)){
|
||||
*data = bucket->node->data;
|
||||
return 0;
|
||||
}
|
||||
bucket = bucket->node;
|
||||
}
|
||||
|
||||
return ARC_ERRNO_NULL;
|
||||
}
|
||||
|
||||
int32_t ARC_Hashtable_Remove(ARC_Hashtable *htable, void *key, size_t keysize, ARC_HashtableNode_DestroyExternal external, void *userdata){
|
||||
uint32_t size = 0;
|
||||
int32_t err = htable->hash(key, &keysize, &size);
|
||||
if(err){ return err; }
|
||||
|
||||
ARC_HashtableNode *bucket = htable->nodes[size % htable->size];
|
||||
if(!bucket){ return ARC_ERRNO_NULL; }
|
||||
|
||||
if(!htable->compare(bucket->key, &bucket->keysize, key, &keysize)){
|
||||
ARC_HashtableNode *temp = bucket;
|
||||
htable->nodes[size % htable->size] = bucket->node;
|
||||
|
||||
if(external){
|
||||
err = external(temp, userdata);
|
||||
if(err){ return err; }
|
||||
}
|
||||
|
||||
free(temp);
|
||||
return 0;
|
||||
}
|
||||
|
||||
while(bucket->node){
|
||||
if(!htable->compare(bucket->node->key, &bucket->node->keysize, key, &keysize)){
|
||||
ARC_HashtableNode *temp = bucket->node;
|
||||
bucket->node = bucket->node->node;
|
||||
|
||||
if(external){
|
||||
err = external(temp, userdata);
|
||||
if(err){ return err; }
|
||||
}
|
||||
|
||||
free(temp);
|
||||
return 0;
|
||||
}
|
||||
|
||||
bucket = bucket->node;
|
||||
}
|
||||
|
||||
return ARC_ERRNO_NULL;
|
||||
}
|
||||
28
src/std/io.c
Normal file
28
src/std/io.c
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
#include "arc/std/io.h"
|
||||
|
||||
#include "arc/std/errno.h"
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
int32_t ARC_IO_FileToStr(const char *path, char **data, uint64_t *size){
|
||||
FILE *file = fopen(path, "rb");
|
||||
if(!file){ return ARC_ERRNO_NULL; }
|
||||
|
||||
fseek(file, 0L, SEEK_END);
|
||||
*size = ftell(file);
|
||||
rewind(file);
|
||||
|
||||
*data = (char *) calloc(1, *size + 1);
|
||||
if(!*data){
|
||||
fclose(file);
|
||||
return ARC_ERRNO_NULL;
|
||||
}
|
||||
|
||||
if(1 != fread(*data, *size, 1, file)){
|
||||
fclose(file);
|
||||
return ARC_ERRNO_COPY;
|
||||
}
|
||||
|
||||
fclose(file);
|
||||
return 0;
|
||||
}
|
||||
115
src/std/string.c
Normal file
115
src/std/string.c
Normal file
|
|
@ -0,0 +1,115 @@
|
|||
#include "arc/std/string.h"
|
||||
|
||||
#include "arc/std/errno.h"
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
uint8_t ARC_String_Alpha(char *val, uint64_t length){
|
||||
for(; length; length--){
|
||||
if(val[length - 1] >= 'a' && val[length - 1] <= 'z'){ continue; }
|
||||
if(val[length - 1] >= 'A' && val[length - 1] <= 'Z'){ continue; }
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint64_t ARC_String_ToUint64_t(const char *data, ARC_StringSubstr *substr){
|
||||
char temp[substr->length + 1];
|
||||
strncpy(temp, data + substr->index, substr->length);
|
||||
temp[substr->length] = '\0';
|
||||
|
||||
return (uint64_t) strtoul(temp, NULL, 10);
|
||||
}
|
||||
|
||||
int32_t ARC_String_Find(char *data, char *substr, uint64_t *index){
|
||||
if(!data || !substr){ return ARC_ERRNO_NULL; }
|
||||
|
||||
uint64_t max = strlen(data);
|
||||
uint64_t sub = strlen(substr);
|
||||
if(!max || !sub || sub > max){ return ARC_ERRNO_DATA; }
|
||||
|
||||
max -= sub - 1;
|
||||
for(uint64_t i = 0; max; i++, max--){
|
||||
if(!strncmp(data + i, substr, sub)){
|
||||
*index = i;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
*index = ~((uint64_t)0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int32_t ARC_String_FindBack(char *data, char *substr, uint64_t *index){
|
||||
if(!data || !substr){ return ARC_ERRNO_NULL; }
|
||||
|
||||
uint64_t max = strlen(data);
|
||||
uint64_t sub = strlen(substr);
|
||||
if(!max || !sub || sub > max){ return ARC_ERRNO_DATA; }
|
||||
|
||||
max -= sub - 1;
|
||||
for(; max; max--){
|
||||
if(!strncmp(data + (max - 1), substr, sub)){
|
||||
*index = max;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
*index = ~((uint64_t)0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int32_t ARC_StringSubstr_StripEnds(char *data, char *substr, ARC_StringSubstr *subdata){
|
||||
if(!subdata){ return ARC_ERRNO_NULL; }
|
||||
if(!substr){ substr = (char *)" "; }
|
||||
|
||||
subdata->length = (subdata->length)? subdata->length : strlen(data);
|
||||
uint64_t max = subdata->length;
|
||||
uint64_t sub = strlen(substr);
|
||||
if(!max || !sub || sub > max){ return ARC_ERRNO_DATA; }
|
||||
|
||||
max -= sub - 1;
|
||||
for(; max; max--){
|
||||
if(strncmp(data + subdata->index + (max - 1), substr, sub)){
|
||||
subdata->length = max;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
max = subdata->length - (sub - 1);
|
||||
for(uint64_t i = 0; max; i++, max--){
|
||||
if(strncmp(data + subdata->index + i, substr, sub)){
|
||||
subdata->index += i;
|
||||
subdata->length -= i;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int32_t ARC_StringSubstr_StripWhitespaceEnds(char *data, ARC_StringSubstr *subdata){
|
||||
if(!subdata){ return ARC_ERRNO_NULL; }
|
||||
|
||||
subdata->length = (subdata->length)? subdata->length : strlen(data);
|
||||
uint64_t max = subdata->length;
|
||||
if(!max){ return ARC_ERRNO_DATA; }
|
||||
|
||||
for(; max; max--){
|
||||
if(data[subdata->index + (max - 1)] != ' ' && data[subdata->index + (max - 1)] != '\n' && data[subdata->index + (max - 1)] != '\t' && data[subdata->index + (max - 1)] != '\r'){
|
||||
subdata->length = max;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
max = subdata->length;
|
||||
for(uint64_t i = 0; max; i++, max--){
|
||||
if(data[subdata->index + i] != ' ' && data[subdata->index + i] != '\n' && data[subdata->index + i] != '\t' && data[subdata->index + i] != '\r'){
|
||||
subdata->index += i;
|
||||
subdata->length -= i;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
109
src/std/vector.c
Normal file
109
src/std/vector.c
Normal file
|
|
@ -0,0 +1,109 @@
|
|||
#include "arc/std/vector.h"
|
||||
|
||||
#include "arc/std/errno.h"
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
|
||||
struct ARC_Vector {
|
||||
uint32_t *currentSize, *capacity;
|
||||
uint32_t *dataSize;
|
||||
void *data;
|
||||
};
|
||||
|
||||
void ARC_Vector_Create(ARC_Vector **vector, uint32_t dataSize){
|
||||
*vector = (ARC_Vector *) malloc(sizeof(ARC_Vector));
|
||||
(*vector)->currentSize = (uint32_t *) malloc(sizeof(uint32_t));
|
||||
(*vector)->capacity = (uint32_t *) malloc(sizeof(uint32_t));
|
||||
(*vector)->dataSize = (uint32_t *) malloc(sizeof(uint32_t));
|
||||
(*vector)->data = (void *) malloc(dataSize);
|
||||
|
||||
*((*vector)->currentSize) = 0;
|
||||
*((*vector)->capacity) = 1;
|
||||
*((*vector)->dataSize) = dataSize;
|
||||
}
|
||||
|
||||
void ARC_Vector_Destroy(ARC_Vector *vector){
|
||||
free(vector->currentSize);
|
||||
free(vector->capacity);
|
||||
free(vector->data);
|
||||
free(vector->dataSize);
|
||||
free(vector);
|
||||
}
|
||||
|
||||
void ARC_Vector_Add(ARC_Vector *vector, void *data){
|
||||
if(*(vector->currentSize) == ~((uint32_t)0)){
|
||||
arc_errno = ARC_ERRNO_OVERFLOW;
|
||||
return;
|
||||
}
|
||||
|
||||
if(*(vector->currentSize) == *(vector->capacity)){
|
||||
*(vector->capacity) <<= 1;
|
||||
|
||||
vector->data = (void *) realloc(vector->data, *(vector->dataSize) * *(vector->capacity));
|
||||
}
|
||||
|
||||
memcpy(vector->data + (*(vector->currentSize) * *(vector->dataSize)), data, *(vector->dataSize));
|
||||
++*(vector->currentSize);
|
||||
}
|
||||
|
||||
void ARC_Vector_Remove(ARC_Vector *vector, void *data, ARC_Vector_CompareDataFn compare){
|
||||
if(!*(vector->currentSize)){
|
||||
arc_errno = ARC_ERRNO_DATA;
|
||||
return;
|
||||
}
|
||||
|
||||
--*(vector->currentSize);
|
||||
|
||||
if(*(vector->currentSize) != *(vector->capacity) >> 1){
|
||||
for(uint32_t i = 0; i <= *(vector->currentSize); i++){
|
||||
if(!compare(data, vector->data + (i * *(vector->dataSize)))){
|
||||
memcpy(vector->data + (i * *(vector->dataSize)), vector->data + ((i + 1) * *(vector->dataSize)), *(vector->currentSize - i) * *(vector->dataSize));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
arc_errno = ARC_ERRNO_DATA;
|
||||
return;
|
||||
}
|
||||
|
||||
*(vector->capacity) >>= 1;
|
||||
void *temp = (void *) malloc(*(vector->dataSize) * *(vector->capacity));
|
||||
|
||||
for(uint32_t i = 0; i <= *(vector->currentSize); i++){
|
||||
if(compare(data, vector->data + (i * *(vector->dataSize)))){
|
||||
memcpy(temp, vector->data, i * *(vector->dataSize));
|
||||
memcpy(temp + (i * *(vector->dataSize)), vector->data + ((i + 1) * *(vector->dataSize)), *(vector->currentSize - i) * *(vector->dataSize));
|
||||
free(vector->data);
|
||||
vector->data = temp;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
arc_errno = ARC_ERRNO_DATA;
|
||||
}
|
||||
|
||||
void ARC_Vector_RemoveIndex(ARC_Vector *vector, uint32_t *index){
|
||||
if(!*(vector->currentSize) || *index >= *(vector->currentSize)){
|
||||
arc_errno = ARC_ERRNO_DATA;
|
||||
return;
|
||||
}
|
||||
|
||||
--*(vector->currentSize);
|
||||
if(*(vector->currentSize) != *(vector->capacity) >> 1){
|
||||
memcpy(vector->data + (*index * *(vector->dataSize)), vector->data + ((*index + 1) * *(vector->dataSize)), *(vector->currentSize - *index) * *(vector->dataSize));
|
||||
return;
|
||||
}
|
||||
|
||||
*(vector->capacity) >>= 1;
|
||||
void **temp = (void **) malloc(sizeof(void *) * (*(vector->capacity)));
|
||||
memcpy(temp, vector->data, *index * *(vector->dataSize));
|
||||
memcpy(temp + (*index * *(vector->dataSize)), vector->data + ((*index + 1) * *(vector->dataSize)), *(vector->currentSize - *index) * *(vector->dataSize));
|
||||
|
||||
free(vector->data);
|
||||
vector->data = temp;
|
||||
}
|
||||
|
||||
uint32_t *ARC_Vector_Size(ARC_Vector *vector){ return vector->currentSize; }
|
||||
|
||||
void *ARC_Vector_Get(ARC_Vector *vector, uint32_t *index){ return (void *)(uint8_t (*)[*(vector->dataSize)]) vector->data + (*index * *(vector->dataSize)); }
|
||||
Loading…
Add table
Add a link
Reference in a new issue