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
86const char* ConfigurationGetValue(const struct Configuration* configuration, const char* section, const char* key) {
87 const struct Table* currentSection = &configuration->root;
88 if (section) {
89 currentSection = HashTableLookup(&configuration->sections, section);
90 if (!currentSection) {
91 return 0;
92 }
93 }
94 return HashTableLookup(currentSection, key);
95}
96
97bool ConfigurationRead(struct Configuration* configuration, const char* path) {
98 HashTableClear(&configuration->root);
99 HashTableClear(&configuration->sections);
100 return ini_parse(path, _iniRead, configuration) == 0;
101}
102
103bool ConfigurationWrite(const struct Configuration* configuration, const char* path) {
104 FILE* file = fopen(path, "w");
105 if (!file) {
106 return false;
107 }
108 HashTableEnumerate(&configuration->root, _keyHandler, file);
109 HashTableEnumerate(&configuration->sections, _sectionHandler, file);
110 fclose(file);
111 return true;
112}
113
114bool ConfigurationWriteSection(const struct Configuration* configuration, const char* path, const char* section) {
115 const struct Table* currentSection = &configuration->root;
116 FILE* file = fopen(path, "w");
117 if (!file) {
118 return false;
119 }
120 if (section) {
121 currentSection = HashTableLookup(&configuration->sections, section);
122 fprintf(file, "[%s]\n", section);
123 }
124 if (currentSection) {
125 HashTableEnumerate(currentSection, _sectionHandler, file);
126 }
127 fclose(file);
128 return true;
129}