all repos — mgba @ f836a67863e66499c812c8d963d37ff56ad10638

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