all repos — mgba @ 1e71f62a3c031325809005c9f1c720ccd30d0df5

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