mirror of
https://github.com/hmaxnl/netex.git
synced 2025-01-18 07:24:21 +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 <json-c/json_object.h>
|
||||
#include <json-c/json_tokener.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#include "config.h"
|
||||
#include "netex.h"
|
||||
#include "strutil.h"
|
||||
|
||||
#define SEPARATOR_CHAR '.'
|
||||
#define DELIM_CHAR '.'
|
||||
|
||||
|
||||
int config_set(CONFIGURATION* config, const char* key, const char* value)
|
||||
const char* config_to_formatted_json_string(const CONFIGURATION* config)
|
||||
{
|
||||
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;
|
||||
}
|
||||
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)
|
||||
return -1;
|
||||
if (config->json == NULL)
|
||||
config->json = json_object_new_object();
|
||||
json_object* temp_obj = NULL;
|
||||
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)
|
||||
{
|
||||
json_object* value_object = json_object_new_string(value);
|
||||
if (json_object_object_add(current_obj, splitted_key->delimited[i], value_object) != 0)
|
||||
ERROR("Failed to set value '%s'", value);
|
||||
if (json_object_object_add(current_obj, splitted_key->delimited[i], json_value_object) != 0)
|
||||
ERROR("Failed to set value to JSON!");
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -53,15 +187,44 @@ int config_set(CONFIGURATION* config, const char* key, const char* value)
|
|||
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)
|
||||
return NULL;
|
||||
SPLIT_STR* splitted = splstr(key, SEPARATOR_CHAR);
|
||||
SPLIT_STR* splitted = splstr(key, DELIM_CHAR);
|
||||
if (splitted == NULL || splitted->count == 0)
|
||||
return NULL;
|
||||
json_object* tmp_json = config->json;
|
||||
char* found_value = NULL;
|
||||
for (int i = 0; i != splitted->count; i++)
|
||||
{
|
||||
json_object* current_json_object = json_object_new_object();
|
||||
|
@ -73,13 +236,6 @@ char* config_get(const CONFIGURATION* config, const char* key)
|
|||
return NULL;
|
||||
}
|
||||
}
|
||||
if (tmp_json != NULL)
|
||||
found_value = strdup(json_object_get_string(tmp_json));
|
||||
strsplfree(splitted);
|
||||
return found_value;
|
||||
}
|
||||
|
||||
char* config_get_default(const char* key, const char* default_value)
|
||||
{
|
||||
return "";
|
||||
return tmp_json;
|
||||
}
|
|
@ -5,10 +5,29 @@
|
|||
typedef struct config_container
|
||||
{
|
||||
json_object* json;
|
||||
int has_allocations : 1;
|
||||
} CONFIGURATION;
|
||||
|
||||
int config_set(CONFIGURATION* config, const char* key, const char* value);
|
||||
char* config_get(const CONFIGURATION* config, const char* key);
|
||||
const char* config_to_formatted_json_string(const CONFIGURATION* config);
|
||||
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
|
||||
|
|
|
@ -14,6 +14,6 @@ struct netex_configuration
|
|||
};
|
||||
|
||||
int save_config(void);
|
||||
int load_config(void);
|
||||
int load_config_storage(void);
|
||||
|
||||
#endif //STORAGE_H
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
void netex_init(void)
|
||||
{
|
||||
// Config
|
||||
const int config_loaded = load_config();
|
||||
const int config_loaded = load_config_storage();
|
||||
if (config_loaded != 0)
|
||||
{
|
||||
ERROR("Failed to load config! Shutting down...");
|
||||
|
|
|
@ -41,7 +41,7 @@ int save_config(void)
|
|||
}
|
||||
return 0;
|
||||
}
|
||||
int load_config(void)
|
||||
int load_config_storage(void)
|
||||
{
|
||||
struct stat config_stat;
|
||||
if (lstat(CONFIG_FILE_NAME, &config_stat) == -1)
|
||||
|
@ -92,7 +92,7 @@ struct netex_configuration* get_configuration()
|
|||
{
|
||||
if (loaded_configuration == NULL)
|
||||
{
|
||||
const int load_result = load_config();
|
||||
const int load_result = load_config_storage();
|
||||
if (load_result != 0)
|
||||
WARN("Failed to get configuration!");
|
||||
}
|
||||
|
|
|
@ -20,6 +20,7 @@ SPLIT_STR* splstr(const char* str, const char delimiter)
|
|||
{
|
||||
const int error = errno;
|
||||
ERROR("Failed to allocate memory, error code: %i", error);
|
||||
free(dup);
|
||||
return NULL;
|
||||
}
|
||||
if (delim_occ != 0)
|
||||
|
@ -31,6 +32,7 @@ SPLIT_STR* splstr(const char* str, const char delimiter)
|
|||
const int error = errno;
|
||||
ERROR("Allocation failed, error code: %i", error);
|
||||
free(splitted);
|
||||
free(dup);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
@ -50,7 +52,7 @@ SPLIT_STR* splstr(const char* str, const char delimiter)
|
|||
|
||||
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);
|
||||
}
|
||||
|
||||
|
|
|
@ -1,25 +1,19 @@
|
|||
#include <stdio.h>
|
||||
|
||||
#include "netex.h"
|
||||
#include "config.h"
|
||||
|
||||
#define CONFIG_PATH "srv_config.json"
|
||||
|
||||
int srv_setup(void);
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
CONFIGURATION configuration;
|
||||
config_set(&configuration, "Server.Connection.Port", "6920");
|
||||
config_set(&configuration, "Server.Connection.IP", "localhost");
|
||||
config_set(&configuration, "Global.Project.Name", "NetEx");
|
||||
config_set(&configuration, "Global.Project.Lang", "C");
|
||||
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");*/
|
||||
const CONFIGURATION* srv_config = config_load_from_path(CONFIG_PATH);
|
||||
int remove_result = config_remove(srv_config, "Connection.CertPath");
|
||||
config_set_string(srv_config, "Connection.CertPath", "cert.pem");
|
||||
config_save_to_path(srv_config, CONFIG_PATH);
|
||||
config_clear(srv_config);
|
||||
|
||||
netex_init();
|
||||
PRINT_LINE("Hello, server!");
|
||||
|
|
Loading…
Reference in New Issue
Block a user