mirror of
https://github.com/hmaxnl/netex.git
synced 2025-01-18 15:34:20 +01:00
Implemented simple config system (loading/writing to file in JSON format)
This commit is contained in:
parent
334df8f9f0
commit
71326e34b2
|
@ -1,25 +1,160 @@
|
||||||
|
#include <errno.h>
|
||||||
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <json-c/json_object.h>
|
#include <json-c/json_tokener.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
#include "netex.h"
|
#include "netex.h"
|
||||||
#include "strutil.h"
|
#include "strutil.h"
|
||||||
|
|
||||||
#define SEPARATOR_CHAR '.'
|
#define DELIM_CHAR '.'
|
||||||
|
|
||||||
|
const char* config_to_formatted_json_string(const CONFIGURATION* config)
|
||||||
int config_set(CONFIGURATION* config, const char* key, const char* value)
|
|
||||||
{
|
{
|
||||||
if (config == NULL)
|
if (config == NULL)
|
||||||
|
return NULL;
|
||||||
|
return json_object_to_json_string_ext(config->json, JSON_C_TO_STRING_PRETTY | JSON_C_TO_STRING_SPACED);
|
||||||
|
}
|
||||||
|
CONFIGURATION* config_create(void)
|
||||||
|
{
|
||||||
|
CONFIGURATION* config_obj = malloc(sizeof(CONFIGURATION));
|
||||||
|
config_obj->json = json_object_new_object();
|
||||||
|
return config_obj;
|
||||||
|
}
|
||||||
|
int config_clear(const CONFIGURATION* config)
|
||||||
|
{
|
||||||
|
if (config == NULL)
|
||||||
|
return -1;
|
||||||
|
if (config->json != NULL)
|
||||||
|
json_object_put(config->json);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
CONFIGURATION* config_load_from_path(const char* path)
|
||||||
|
{
|
||||||
|
if (path == NULL)
|
||||||
|
return NULL;
|
||||||
|
struct stat con_file_stat;
|
||||||
|
if (lstat(path, &con_file_stat) == -1)
|
||||||
{
|
{
|
||||||
WARN("Parameter 'config' is NULL!");
|
const int error = errno;
|
||||||
|
WARN("Failed to get stat from file '%s'. Error code: %i", path, error);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
const long int file_size = con_file_stat.st_size;
|
||||||
|
if (file_size <= 0)
|
||||||
|
{
|
||||||
|
//TODO: Empty file?
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
FILE* config_file = fopen(path, "r");
|
||||||
|
if (config_file == NULL)
|
||||||
|
{
|
||||||
|
WARN("Failed to load file '%s'", path);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
void* config_mem = malloc(file_size);
|
||||||
|
if (config_mem == NULL)
|
||||||
|
{
|
||||||
|
const int error = errno;
|
||||||
|
WARN("Failed to allocate %ld bytes, error: %i", file_size, error);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
const size_t total_read = fread(config_mem, file_size, file_size, config_file);
|
||||||
|
fclose(config_file);
|
||||||
|
if (total_read != 1)
|
||||||
|
{
|
||||||
|
free(config_mem);
|
||||||
|
WARN("Failed to load read file!");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
json_object* tokenized = json_tokener_parse(config_mem);
|
||||||
|
free(config_mem);
|
||||||
|
if (tokenized == NULL)
|
||||||
|
{
|
||||||
|
WARN("Failed to tokenize JSON!");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
CONFIGURATION* config_obj = malloc(sizeof(CONFIGURATION));
|
||||||
|
if (config_obj == NULL)
|
||||||
|
{
|
||||||
|
WARN("Failed to allocate memory!");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
config_obj->json = tokenized;
|
||||||
|
return config_obj;
|
||||||
|
}
|
||||||
|
|
||||||
|
int config_save_to_path(const CONFIGURATION* config, const char* path)
|
||||||
|
{
|
||||||
|
if (config == NULL || path == NULL)
|
||||||
|
return -1;
|
||||||
|
FILE* config_file = fopen(path, "w");
|
||||||
|
if (config_file == NULL)
|
||||||
|
{
|
||||||
|
const int error = errno;
|
||||||
|
WARN("Failed to open file: '%s' Error code: %i", path, error);
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
const char* json_str = json_object_to_json_string_ext(config->json, JSON_C_TO_STRING_PRETTY | JSON_C_TO_STRING_SPACED);
|
||||||
|
if (json_str == NULL)
|
||||||
|
{
|
||||||
|
WARN("Failed to convert JSON obj to string.");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
SPLIT_STR* splitted_key = splstr(key, SEPARATOR_CHAR);
|
const size_t json_str_len = strlen(json_str);
|
||||||
|
const int write_result = fwrite(json_str, 1, json_str_len, config_file);
|
||||||
|
fclose(config_file);
|
||||||
|
if (write_result <= 0)
|
||||||
|
{
|
||||||
|
const int wr_error = errno;
|
||||||
|
WARN("Error occured while writing file '%s' to disk, error code: %i", path, wr_error);
|
||||||
|
return wr_error;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
int config_remove(const CONFIGURATION* config, const char* key)
|
||||||
|
{
|
||||||
|
if (key == NULL)
|
||||||
|
return -1;
|
||||||
|
json_object* to_remove = config_get_json(config, key);
|
||||||
|
if (json_object_put(to_remove) != 1)
|
||||||
|
{
|
||||||
|
WARN("Failed to remove item from JSON");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
int config_set_string(const CONFIGURATION* config, const char* key, const char* str_value)
|
||||||
|
{
|
||||||
|
if (str_value == NULL)
|
||||||
|
return -1;
|
||||||
|
json_object* str_json_value = json_object_new_string(str_value);
|
||||||
|
return config_set_json(config, key, str_json_value);
|
||||||
|
}
|
||||||
|
int config_set_int(const CONFIGURATION* config, const char* key, const size_t int_value)
|
||||||
|
{
|
||||||
|
json_object* int_value_json = json_object_new_int64(int_value);
|
||||||
|
return config_set_json(config, key, int_value_json);
|
||||||
|
}
|
||||||
|
int config_set_uint(const CONFIGURATION* config, const char* key, const uint64_t int_value)
|
||||||
|
{
|
||||||
|
json_object* int_value_json = json_object_new_uint64(int_value);
|
||||||
|
return config_set_json(config, key, int_value_json);
|
||||||
|
}
|
||||||
|
int config_set_double(const CONFIGURATION* config, const char* key, const double double_value)
|
||||||
|
{
|
||||||
|
json_object* double_value_json = json_object_new_double(double_value);
|
||||||
|
return config_set_json(config, key, double_value_json);
|
||||||
|
}
|
||||||
|
|
||||||
|
int config_set_json(const CONFIGURATION* config, const char* key, json_object* json_value_object)
|
||||||
|
{
|
||||||
|
if ((config == NULL || json_value_object == NULL) || config->json == NULL)
|
||||||
|
return -1;
|
||||||
|
SPLIT_STR* splitted_key = splstr(key, DELIM_CHAR);
|
||||||
if (splitted_key == NULL || splitted_key->count == 0)
|
if (splitted_key == NULL || splitted_key->count == 0)
|
||||||
return -1;
|
return -1;
|
||||||
if (config->json == NULL)
|
|
||||||
config->json = json_object_new_object();
|
|
||||||
json_object* temp_obj = NULL;
|
json_object* temp_obj = NULL;
|
||||||
for (int i = 0; i != splitted_key->count; i++)
|
for (int i = 0; i != splitted_key->count; i++)
|
||||||
{
|
{
|
||||||
|
@ -35,9 +170,8 @@ int config_set(CONFIGURATION* config, const char* key, const char* value)
|
||||||
|
|
||||||
if (i == splitted_key->count - 1) // Last key (set value)
|
if (i == splitted_key->count - 1) // Last key (set value)
|
||||||
{
|
{
|
||||||
json_object* value_object = json_object_new_string(value);
|
if (json_object_object_add(current_obj, splitted_key->delimited[i], json_value_object) != 0)
|
||||||
if (json_object_object_add(current_obj, splitted_key->delimited[i], value_object) != 0)
|
ERROR("Failed to set value to JSON!");
|
||||||
ERROR("Failed to set value '%s'", value);
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -53,15 +187,44 @@ int config_set(CONFIGURATION* config, const char* key, const char* value)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
char* config_get(const CONFIGURATION* config, const char* key)
|
char* config_get_string(const CONFIGURATION* config, const char* key)
|
||||||
|
{
|
||||||
|
json_object* json_string_obj = config_get_json(config, key);
|
||||||
|
if (json_string_obj == NULL)
|
||||||
|
return NULL;
|
||||||
|
// Duplicate the string, if the json object is free'd (using json_object_put()) the returned string is still there and can be used further in the application.
|
||||||
|
return strdup(json_object_get_string(json_string_obj));
|
||||||
|
}
|
||||||
|
int64_t config_get_int(const CONFIGURATION* config, const char* key)
|
||||||
|
{
|
||||||
|
const json_object* json_int_obj = config_get_json(config, key);
|
||||||
|
if (json_int_obj == NULL)
|
||||||
|
return 0;
|
||||||
|
return json_object_get_int64(json_int_obj);
|
||||||
|
}
|
||||||
|
uint64_t config_get_uint(const CONFIGURATION* config, const char* key)
|
||||||
|
{
|
||||||
|
const json_object* json_int_obj = config_get_json(config, key);
|
||||||
|
if (json_int_obj == NULL)
|
||||||
|
return 0;
|
||||||
|
return json_object_get_uint64(json_int_obj);
|
||||||
|
}
|
||||||
|
double config_get_double(const CONFIGURATION* config, const char* key)
|
||||||
|
{
|
||||||
|
const json_object* json_double_obj = config_get_json(config, key);
|
||||||
|
if (json_double_obj == NULL)
|
||||||
|
return 0;
|
||||||
|
return json_object_get_double(json_double_obj);
|
||||||
|
}
|
||||||
|
|
||||||
|
json_object* config_get_json(const CONFIGURATION* config, const char* key)
|
||||||
{
|
{
|
||||||
if (config == NULL || config->json == NULL)
|
if (config == NULL || config->json == NULL)
|
||||||
return NULL;
|
return NULL;
|
||||||
SPLIT_STR* splitted = splstr(key, SEPARATOR_CHAR);
|
SPLIT_STR* splitted = splstr(key, DELIM_CHAR);
|
||||||
if (splitted == NULL || splitted->count == 0)
|
if (splitted == NULL || splitted->count == 0)
|
||||||
return NULL;
|
return NULL;
|
||||||
json_object* tmp_json = config->json;
|
json_object* tmp_json = config->json;
|
||||||
char* found_value = NULL;
|
|
||||||
for (int i = 0; i != splitted->count; i++)
|
for (int i = 0; i != splitted->count; i++)
|
||||||
{
|
{
|
||||||
json_object* current_json_object = json_object_new_object();
|
json_object* current_json_object = json_object_new_object();
|
||||||
|
@ -73,13 +236,6 @@ char* config_get(const CONFIGURATION* config, const char* key)
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (tmp_json != NULL)
|
|
||||||
found_value = strdup(json_object_get_string(tmp_json));
|
|
||||||
strsplfree(splitted);
|
strsplfree(splitted);
|
||||||
return found_value;
|
return tmp_json;
|
||||||
}
|
|
||||||
|
|
||||||
char* config_get_default(const char* key, const char* default_value)
|
|
||||||
{
|
|
||||||
return "";
|
|
||||||
}
|
}
|
|
@ -5,10 +5,29 @@
|
||||||
typedef struct config_container
|
typedef struct config_container
|
||||||
{
|
{
|
||||||
json_object* json;
|
json_object* json;
|
||||||
int has_allocations : 1;
|
|
||||||
} CONFIGURATION;
|
} CONFIGURATION;
|
||||||
|
|
||||||
int config_set(CONFIGURATION* config, const char* key, const char* value);
|
const char* config_to_formatted_json_string(const CONFIGURATION* config);
|
||||||
char* config_get(const CONFIGURATION* config, const char* key);
|
CONFIGURATION* config_create(void);
|
||||||
|
int config_clear(const CONFIGURATION* config);
|
||||||
|
|
||||||
|
CONFIGURATION* config_load_from_path(const char* path);
|
||||||
|
int config_save_to_path(const CONFIGURATION* config, const char* path);
|
||||||
|
int config_remove(const CONFIGURATION* config, const char* key);
|
||||||
|
|
||||||
|
int config_set_json(const CONFIGURATION* config, const char* key, json_object* json_value_object);
|
||||||
|
|
||||||
|
int config_set_string(const CONFIGURATION* config, const char* key, const char* str_value);
|
||||||
|
int config_set_int(const CONFIGURATION* config, const char* key, size_t int_value);
|
||||||
|
int config_set_uint(const CONFIGURATION* config, const char* key, uint64_t int_value);
|
||||||
|
int config_set_double(const CONFIGURATION* config, const char* key, double double_value);
|
||||||
|
|
||||||
|
json_object* config_get_json(const CONFIGURATION* config, const char* key);
|
||||||
|
|
||||||
|
// The returning value need to be free'd with the 'free()' function!
|
||||||
|
char* config_get_string(const CONFIGURATION* config, const char* key);
|
||||||
|
int64_t config_get_int(const CONFIGURATION* config, const char* key);
|
||||||
|
uint64_t config_get_uint(const CONFIGURATION* config, const char* key);
|
||||||
|
double config_get_double(const CONFIGURATION* config, const char* key);
|
||||||
|
|
||||||
#endif //CONFIG_H
|
#endif //CONFIG_H
|
||||||
|
|
|
@ -14,6 +14,6 @@ struct netex_configuration
|
||||||
};
|
};
|
||||||
|
|
||||||
int save_config(void);
|
int save_config(void);
|
||||||
int load_config(void);
|
int load_config_storage(void);
|
||||||
|
|
||||||
#endif //STORAGE_H
|
#endif //STORAGE_H
|
||||||
|
|
|
@ -8,7 +8,7 @@
|
||||||
void netex_init(void)
|
void netex_init(void)
|
||||||
{
|
{
|
||||||
// Config
|
// Config
|
||||||
const int config_loaded = load_config();
|
const int config_loaded = load_config_storage();
|
||||||
if (config_loaded != 0)
|
if (config_loaded != 0)
|
||||||
{
|
{
|
||||||
ERROR("Failed to load config! Shutting down...");
|
ERROR("Failed to load config! Shutting down...");
|
||||||
|
|
|
@ -41,7 +41,7 @@ int save_config(void)
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
int load_config(void)
|
int load_config_storage(void)
|
||||||
{
|
{
|
||||||
struct stat config_stat;
|
struct stat config_stat;
|
||||||
if (lstat(CONFIG_FILE_NAME, &config_stat) == -1)
|
if (lstat(CONFIG_FILE_NAME, &config_stat) == -1)
|
||||||
|
@ -92,7 +92,7 @@ struct netex_configuration* get_configuration()
|
||||||
{
|
{
|
||||||
if (loaded_configuration == NULL)
|
if (loaded_configuration == NULL)
|
||||||
{
|
{
|
||||||
const int load_result = load_config();
|
const int load_result = load_config_storage();
|
||||||
if (load_result != 0)
|
if (load_result != 0)
|
||||||
WARN("Failed to get configuration!");
|
WARN("Failed to get configuration!");
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,6 +20,7 @@ SPLIT_STR* splstr(const char* str, const char delimiter)
|
||||||
{
|
{
|
||||||
const int error = errno;
|
const int error = errno;
|
||||||
ERROR("Failed to allocate memory, error code: %i", error);
|
ERROR("Failed to allocate memory, error code: %i", error);
|
||||||
|
free(dup);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
if (delim_occ != 0)
|
if (delim_occ != 0)
|
||||||
|
@ -31,6 +32,7 @@ SPLIT_STR* splstr(const char* str, const char delimiter)
|
||||||
const int error = errno;
|
const int error = errno;
|
||||||
ERROR("Allocation failed, error code: %i", error);
|
ERROR("Allocation failed, error code: %i", error);
|
||||||
free(splitted);
|
free(splitted);
|
||||||
|
free(dup);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -50,7 +52,7 @@ SPLIT_STR* splstr(const char* str, const char delimiter)
|
||||||
|
|
||||||
void strsplfree(SPLIT_STR* str)
|
void strsplfree(SPLIT_STR* str)
|
||||||
{
|
{
|
||||||
free(str->delimited);
|
free(*str->delimited); // Free the allocated array and not the ptr pointing to the array!
|
||||||
free(str);
|
free(str);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,25 +1,19 @@
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|
||||||
#include "netex.h"
|
#include "netex.h"
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
|
|
||||||
|
#define CONFIG_PATH "srv_config.json"
|
||||||
|
|
||||||
int srv_setup(void);
|
int srv_setup(void);
|
||||||
|
|
||||||
int main(int argc, char *argv[])
|
int main(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
CONFIGURATION configuration;
|
const CONFIGURATION* srv_config = config_load_from_path(CONFIG_PATH);
|
||||||
config_set(&configuration, "Server.Connection.Port", "6920");
|
int remove_result = config_remove(srv_config, "Connection.CertPath");
|
||||||
config_set(&configuration, "Server.Connection.IP", "localhost");
|
config_set_string(srv_config, "Connection.CertPath", "cert.pem");
|
||||||
config_set(&configuration, "Global.Project.Name", "NetEx");
|
config_save_to_path(srv_config, CONFIG_PATH);
|
||||||
config_set(&configuration, "Global.Project.Lang", "C");
|
config_clear(srv_config);
|
||||||
config_set(&configuration, "Global.Project.OS", "Linux");
|
|
||||||
config_set(&configuration, "Server.Connection.db", "SQLite");
|
|
||||||
PRINT_LINE("JSON:\n%s", json_object_to_json_string_ext(configuration.json, JSON_C_TO_STRING_SPACED | JSON_C_TO_STRING_PRETTY));
|
|
||||||
|
|
||||||
char* proj_name = config_get(&configuration,"Global.Project.Name");
|
|
||||||
PRINT_LINE("Project name: %s", proj_name);
|
|
||||||
|
|
||||||
/*config_set("Server.Test", "Test value for server config");
|
|
||||||
config_set("Server.port", "6920");*/
|
|
||||||
|
|
||||||
netex_init();
|
netex_init();
|
||||||
PRINT_LINE("Hello, server!");
|
PRINT_LINE("Hello, server!");
|
||||||
|
|
Loading…
Reference in New Issue
Block a user