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