all repos — mgba @ 0ba9d1e247209c37a04321d30867c7bbac3ba4bf

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
 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}