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 && value) {
57 currentSection = malloc(sizeof(*currentSection));
58 HashTableInit(currentSection, 0, _sectionDeinit);
59 HashTableInsert(&configuration->sections, section, currentSection);
60 }
61 }
62 if (value) {
63 HashTableInsert(currentSection, key, strdup(value));
64 } else {
65 HashTableRemove(currentSection, key);
66 }
67}
68
69void ConfigurationSetIntValue(struct Configuration* configuration, const char* section, const char* key, int value) {
70 char charValue[12];
71 sprintf(charValue, "%i", value);
72 ConfigurationSetValue(configuration, section, key, charValue);
73}
74
75void ConfigurationSetUIntValue(struct Configuration* configuration, const char* section, const char* key, unsigned value) {
76 char charValue[12];
77 sprintf(charValue, "%u", value);
78 ConfigurationSetValue(configuration, section, key, charValue);
79}
80
81void ConfigurationSetFloatValue(struct Configuration* configuration, const char* section, const char* key, float value) {
82 char charValue[16];
83 ftostr_u(charValue, sizeof(charValue), value);
84 ConfigurationSetValue(configuration, section, key, charValue);
85}
86
87void ConfigurationClearValue(struct Configuration* configuration, const char* section, const char* key) {
88 struct Table* currentSection = &configuration->root;
89 if (section) {
90 currentSection = HashTableLookup(&configuration->sections, section);
91 if (!currentSection) {
92 return;
93 }
94 }
95 HashTableRemove(currentSection, key);
96}
97
98const char* ConfigurationGetValue(const struct Configuration* configuration, const char* section, const char* key) {
99 const struct Table* currentSection = &configuration->root;
100 if (section) {
101 currentSection = HashTableLookup(&configuration->sections, section);
102 if (!currentSection) {
103 return 0;
104 }
105 }
106 return HashTableLookup(currentSection, key);
107}
108
109bool ConfigurationRead(struct Configuration* configuration, const char* path) {
110 HashTableClear(&configuration->root);
111 HashTableClear(&configuration->sections);
112 return ini_parse(path, _iniRead, configuration) == 0;
113}
114
115bool ConfigurationWrite(const struct Configuration* configuration, const char* path) {
116 FILE* file = fopen(path, "w");
117 if (!file) {
118 return false;
119 }
120 HashTableEnumerate(&configuration->root, _keyHandler, file);
121 HashTableEnumerate(&configuration->sections, _sectionHandler, file);
122 fclose(file);
123 return true;
124}
125
126bool ConfigurationWriteSection(const struct Configuration* configuration, const char* path, const char* section) {
127 const struct Table* currentSection = &configuration->root;
128 FILE* file = fopen(path, "w");
129 if (!file) {
130 return false;
131 }
132 if (section) {
133 currentSection = HashTableLookup(&configuration->sections, section);
134 fprintf(file, "[%s]\n", section);
135 }
136 if (currentSection) {
137 HashTableEnumerate(currentSection, _sectionHandler, file);
138 }
139 fclose(file);
140 return true;
141}