all repos — mgba @ 4bd35550455e74a870a52c611d8e39d4dde20015

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