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