all repos — mgba @ 19758d711528b15a255b353d1ef740d516b8685e

mGBA Game Boy Advance Emulator

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}