src/util/configuration.c (view raw)
1#include "configuration.h"
2
3#include "util/vfs.h"
4
5#include "third-party/inih/ini.h"
6
7#include <float.h>
8
9static void _tableDeinit(void* table) {
10 TableDeinit(table);
11 free(table);
12}
13
14static void _sectionDeinit(void* string) {
15 free(string);
16}
17
18static int _iniRead(void* configuration, const char* section, const char* key, const char* value) {
19 if (section && !section[0]) {
20 section = 0;
21 }
22 ConfigurationSetValue(configuration, section, key, value);
23 return 1;
24}
25
26static void _keyHandler(const char* key, void* value, void* user) {
27 fprintf(user, "%s=%s\n", key, (const char*) value);
28}
29
30static void _sectionHandler(const char* key, void* section, void* user) {
31 fprintf(user, "[%s]\n", key);
32 HashTableEnumerate(section, _keyHandler, user);
33 fprintf(user, "\n");
34}
35
36void ConfigurationInit(struct Configuration* configuration) {
37 HashTableInit(&configuration->sections, 0, _tableDeinit);
38 HashTableInit(&configuration->root, 0, _sectionDeinit);
39}
40
41void ConfigurationDeinit(struct Configuration* configuration) {
42 HashTableDeinit(&configuration->sections);
43 HashTableDeinit(&configuration->root);
44}
45
46void ConfigurationSetValue(struct Configuration* configuration, const char* section, const char* key, const char* value) {
47 struct Table* currentSection = &configuration->root;
48 if (section) {
49 currentSection = HashTableLookup(&configuration->sections, section);
50 if (!currentSection && value) {
51 currentSection = malloc(sizeof(*currentSection));
52 HashTableInit(currentSection, 0, _sectionDeinit);
53 HashTableInsert(&configuration->sections, section, currentSection);
54 }
55 }
56 if (value) {
57 HashTableInsert(currentSection, key, strdup(value));
58 } else {
59 HashTableRemove(currentSection, key);
60 }
61}
62
63void ConfigurationSetIntValue(struct Configuration* configuration, const char* section, const char* key, int value) {
64 char charValue[12];
65 sprintf(charValue, "%i", value);
66 ConfigurationSetValue(configuration, section, key, charValue);
67}
68
69void ConfigurationSetUIntValue(struct Configuration* configuration, const char* section, const char* key, unsigned value) {
70 char charValue[12];
71 sprintf(charValue, "%u", value);
72 ConfigurationSetValue(configuration, section, key, charValue);
73}
74
75void ConfigurationSetFloatValue(struct Configuration* configuration, const char* section, const char* key, float value) {
76 char charValue[FLT_DIG + 7];
77 sprintf(charValue, "%.*g", FLT_DIG, value);
78 ConfigurationSetValue(configuration, section, key, charValue);
79}
80
81const char* ConfigurationGetValue(const struct Configuration* configuration, const char* section, const char* key) {
82 const struct Table* currentSection = &configuration->root;
83 if (section) {
84 currentSection = HashTableLookup(&configuration->sections, section);
85 if (!currentSection) {
86 return 0;
87 }
88 }
89 return HashTableLookup(currentSection, key);
90}
91
92bool ConfigurationRead(struct Configuration* configuration, const char* path) {
93 HashTableClear(&configuration->root);
94 HashTableClear(&configuration->sections);
95 return ini_parse(path, _iniRead, configuration) == 0;
96}
97
98bool ConfigurationWrite(const struct Configuration* configuration, const char* path) {
99 FILE* file = fopen(path, "w");
100 if (!file) {
101 return false;
102 }
103 HashTableEnumerate(&configuration->root, _keyHandler, file);
104 HashTableEnumerate(&configuration->sections, _sectionHandler, file);
105 fclose(file);
106 return true;
107}
108
109bool ConfigurationWriteSection(const struct Configuration* configuration, const char* path, const char* section) {
110 const struct Table* currentSection = &configuration->root;
111 FILE* file = fopen(path, "w");
112 if (!file) {
113 return false;
114 }
115 if (section) {
116 currentSection = HashTableLookup(&configuration->sections, section);
117 fprintf(file, "[%s]\n", section);
118 }
119 if (currentSection) {
120 HashTableEnumerate(currentSection, _sectionHandler, file);
121 }
122 fclose(file);
123 return true;
124}