src/util/configuration.c (view raw)
1/* Copyright (c) 2013-2014 Jeffrey Pfau
2 *
3 * This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6#include "configuration.h"
7
8#include "util/formatting.h"
9#include "util/string.h"
10#include "util/vfs.h"
11
12#include "third-party/inih/ini.h"
13
14#include <float.h>
15
16static void _tableDeinit(void* table) {
17 TableDeinit(table);
18 free(table);
19}
20
21static void _sectionDeinit(void* string) {
22 free(string);
23}
24
25static int _iniRead(void* configuration, const char* section, const char* key, const char* value) {
26 if (section && !section[0]) {
27 section = 0;
28 }
29 ConfigurationSetValue(configuration, section, key, value);
30 return 1;
31}
32
33static void _keyHandler(const char* key, void* value, void* user) {
34 fprintf(user, "%s=%s\n", key, (const char*) value);
35}
36
37static void _sectionHandler(const char* key, void* section, void* user) {
38 fprintf(user, "[%s]\n", key);
39 HashTableEnumerate(section, _keyHandler, user);
40 fprintf(user, "\n");
41}
42
43void ConfigurationInit(struct Configuration* configuration) {
44 HashTableInit(&configuration->sections, 0, _tableDeinit);
45 HashTableInit(&configuration->root, 0, _sectionDeinit);
46}
47
48void ConfigurationDeinit(struct Configuration* configuration) {
49 HashTableDeinit(&configuration->sections);
50 HashTableDeinit(&configuration->root);
51}
52
53void ConfigurationSetValue(struct Configuration* configuration, const char* section, const char* key, const char* value) {
54 struct Table* currentSection = &configuration->root;
55 if (section) {
56 currentSection = HashTableLookup(&configuration->sections, section);
57 if (!currentSection) {
58 if (value) {
59 currentSection = malloc(sizeof(*currentSection));
60 HashTableInit(currentSection, 0, _sectionDeinit);
61 HashTableInsert(&configuration->sections, section, currentSection);
62 } else {
63 return;
64 }
65 }
66 }
67 if (value) {
68 HashTableInsert(currentSection, key, strdup(value));
69 } else {
70 HashTableRemove(currentSection, key);
71 }
72}
73
74void ConfigurationSetIntValue(struct Configuration* configuration, const char* section, const char* key, int value) {
75 char charValue[12];
76 sprintf(charValue, "%i", value);
77 ConfigurationSetValue(configuration, section, key, charValue);
78}
79
80void ConfigurationSetUIntValue(struct Configuration* configuration, const char* section, const char* key, unsigned value) {
81 char charValue[12];
82 sprintf(charValue, "%u", value);
83 ConfigurationSetValue(configuration, section, key, charValue);
84}
85
86void ConfigurationSetFloatValue(struct Configuration* configuration, const char* section, const char* key, float value) {
87 char charValue[16];
88 ftostr_u(charValue, sizeof(charValue), value);
89 ConfigurationSetValue(configuration, section, key, charValue);
90}
91
92void ConfigurationClearValue(struct Configuration* configuration, const char* section, const char* key) {
93 struct Table* currentSection = &configuration->root;
94 if (section) {
95 currentSection = HashTableLookup(&configuration->sections, section);
96 if (!currentSection) {
97 return;
98 }
99 }
100 HashTableRemove(currentSection, key);
101}
102
103bool ConfigurationHasSection(const struct Configuration* configuration, const char* section) {
104 return HashTableLookup(&configuration->sections, section);
105}
106
107const char* ConfigurationGetValue(const struct Configuration* configuration, const char* section, const char* key) {
108 const struct Table* currentSection = &configuration->root;
109 if (section) {
110 currentSection = HashTableLookup(&configuration->sections, section);
111 if (!currentSection) {
112 return 0;
113 }
114 }
115 return HashTableLookup(currentSection, key);
116}
117
118bool ConfigurationRead(struct Configuration* configuration, const char* path) {
119 HashTableClear(&configuration->root);
120 HashTableClear(&configuration->sections);
121 return ini_parse(path, _iniRead, configuration) == 0;
122}
123
124bool ConfigurationWrite(const struct Configuration* configuration, const char* path) {
125 FILE* file = fopen(path, "w");
126 if (!file) {
127 return false;
128 }
129 HashTableEnumerate(&configuration->root, _keyHandler, file);
130 HashTableEnumerate(&configuration->sections, _sectionHandler, file);
131 fclose(file);
132 return true;
133}
134
135bool ConfigurationWriteSection(const struct Configuration* configuration, const char* path, const char* section) {
136 const struct Table* currentSection = &configuration->root;
137 FILE* file = fopen(path, "w");
138 if (!file) {
139 return false;
140 }
141 if (section) {
142 currentSection = HashTableLookup(&configuration->sections, section);
143 fprintf(file, "[%s]\n", section);
144 }
145 if (currentSection) {
146 HashTableEnumerate(currentSection, _sectionHandler, file);
147 }
148 fclose(file);
149 return true;
150}