VitaShell/config.c

302 lines
6.3 KiB
C
Raw Permalink Normal View History

/*
2017-10-13 10:42:36 +00:00
VitaShell
2017-12-30 10:43:37 +00:00
Copyright (C) 2015-2018, TheFloW
2017-10-13 10:42:36 +00:00
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
2017-10-13 10:42:36 +00:00
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
2017-10-13 10:42:36 +00:00
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "main.h"
2016-09-14 09:33:52 +00:00
#include "file.h"
#include "config.h"
2017-02-12 15:27:43 +00:00
static void trim(char *str) {
2017-10-13 10:42:36 +00:00
int len = strlen(str);
int i;
for (i = len - 1; i >= 0; i--) {
if (str[i] == 0x20 || str[i] == '\t') {
str[i] = 0;
} else {
break;
}
}
}
2017-02-12 15:27:43 +00:00
static int GetLine(char *buf, int size, char *str) {
2017-10-13 10:42:36 +00:00
uint8_t ch = 0;
int n = 0;
int i = 0;
uint8_t *s = (uint8_t *)str;
while (1) {
if (i >= size)
break;
ch = ((uint8_t *)buf)[i];
if (ch < 0x20 && ch != '\t') {
if (n != 0) {
i++;
break;
}
} else {
*str++ = ch;
n++;
}
2017-10-13 10:42:36 +00:00
i++;
}
2017-10-13 10:42:36 +00:00
trim((char *)s);
2017-10-13 10:42:36 +00:00
return i;
}
2017-02-12 15:27:43 +00:00
static int getDecimal(const char *str) {
2017-10-13 10:42:36 +00:00
return strtol(str, NULL, 0);
}
2017-02-12 15:27:43 +00:00
static int getHexdecimal(const char *str) {
2017-10-13 10:42:36 +00:00
return strtoul(str, NULL, 16);
}
2017-02-12 15:27:43 +00:00
static int getBoolean(const char *str) {
2018-01-03 21:37:11 +00:00
if (strcasecmp(str, "false") == 0 ||
strcasecmp(str, "off") == 0 ||
strcasecmp(str, "no") == 0)
2017-10-13 10:42:36 +00:00
return 0;
2018-01-03 21:37:11 +00:00
if (strcasecmp(str, "true") == 0 ||
strcasecmp(str, "on") == 0 ||
strcasecmp(str, "yes") == 0)
2017-10-13 10:42:36 +00:00
return 1;
2017-10-13 10:42:36 +00:00
return -1;
}
2017-02-12 15:27:43 +00:00
static char *getString(const char *str) {
2017-10-13 10:42:36 +00:00
if (str[0] != '"')
return NULL;
2017-10-13 10:42:36 +00:00
char *p = strchr(str + 1, '"');
if (!p)
return NULL;
2017-10-13 10:42:36 +00:00
int len = p - (str + 1);
2017-10-13 10:42:36 +00:00
char *out = malloc(len + 1);
strncpy(out, str + 1, len);
out[len] = '\0';
2017-10-13 10:42:36 +00:00
int i;
for (i = 0; i < len; i++) {
if (out[i] == '\\')
out[i] = '\n';
}
2017-10-13 10:42:36 +00:00
return out;
}
2017-02-12 15:27:43 +00:00
static int readEntry(const char *line, ConfigEntry *entries, int n_entries) {
2017-10-13 10:42:36 +00:00
// Trim at beginning
while (*line == ' ' || *line == '\t')
line++;
2017-10-13 10:42:36 +00:00
// Ignore comments #1
if (line[0] == '#') {
// debugPrintf("IGNORE %s\n", line);
return 0;
}
2017-10-13 10:42:36 +00:00
// Ignore comments #2
char *p = strchr(line, '#');
if (p) {
// debugPrintf("IGNORE %s\n", p);
*p = '\0';
}
2017-10-13 10:42:36 +00:00
// Get token
p = strchr(line, '=');
if (!p)
return -1;
2017-10-13 10:42:36 +00:00
// Name of entry
char name[MAX_CONFIG_NAME_LENGTH];
int len = p - line;
if (len > MAX_CONFIG_NAME_LENGTH - 1)
2018-01-03 21:37:11 +00:00
len = MAX_CONFIG_NAME_LENGTH - 1;
2017-10-13 10:42:36 +00:00
strncpy(name, line, len);
name[len] = '\0';
2017-10-13 10:42:36 +00:00
trim(name);
2016-10-31 19:31:44 +00:00
2017-10-13 10:42:36 +00:00
// debugPrintf("NAME: %s\n", name);
2017-03-13 20:45:04 +00:00
2017-10-13 10:42:36 +00:00
// String of entry
char *string = p + 1;
2016-10-31 19:31:44 +00:00
2017-10-13 10:42:36 +00:00
// Trim at beginning
while (*string == ' ' || *string == '\t')
string++;
2016-10-31 19:31:44 +00:00
2017-10-13 10:42:36 +00:00
// Trim at end
trim(string);
2016-10-31 19:31:44 +00:00
2017-10-13 10:42:36 +00:00
// debugPrintf("STRING: %s\n", string);
int i;
for (i = 0; i < n_entries; i++) {
if (strcasecmp(name, entries[i].name) == 0) {
switch (entries[i].type) {
2016-10-31 19:31:44 +00:00
case CONFIG_TYPE_DECIMAL:
2017-10-13 10:42:36 +00:00
*(uint32_t *)entries[i].value = getDecimal(string);
// debugPrintf("VALUE DECIMAL: %d\n", *(uint32_t *)entries[i].value);
break;
2016-10-31 19:31:44 +00:00
case CONFIG_TYPE_HEXDECIMAL:
2017-10-13 10:42:36 +00:00
*(uint32_t *)entries[i].value = getHexdecimal(string);
// debugPrintf("VALUE HEXDECIMAL: 0x%X\n", *(uint32_t *)entries[i].value);
break;
case CONFIG_TYPE_BOOLEAN:
*(uint32_t *)entries[i].value = getBoolean(string);
// debugPrintf("VALUE BOOLEAN: %d\n", *(uint32_t *)entries[i].value);
break;
2016-10-31 19:31:44 +00:00
case CONFIG_TYPE_STRING:
2017-10-13 10:42:36 +00:00
{
char *value = getString(string);
if (value) {
*(uint32_t *)entries[i].value = (uint32_t)value;
// debugPrintf("VALUE STRING: %s\n", *(uint32_t *)entries[i].value);
}
break;
}
}
break;
2016-10-31 19:31:44 +00:00
}
2017-10-13 10:42:36 +00:00
}
return 1;
}
2016-10-31 19:31:44 +00:00
2017-10-13 10:42:36 +00:00
int readConfigBuffer(void *buffer, int size, ConfigEntry *entries, int n_entries) {
int res = 0;
char line[MAX_CONFIG_LINE_LENGTH];
char *p = buffer;
// Skip UTF-8 bom
uint32_t bom = 0xBFBBEF;
if (memcmp(p, &bom, 3) == 0) {
p += 3;
size -= 3;
}
do {
memset(line, 0, sizeof(line));
res = GetLine(p, size, line);
if (res > 0) {
readEntry(line, entries, n_entries);
size -= res;
p += res;
}
} while (res > 0);
2016-10-31 19:31:44 +00:00
2017-10-13 10:42:36 +00:00
return 0;
}
2016-10-31 19:31:44 +00:00
2017-10-13 10:42:36 +00:00
int readConfig(const char *path, ConfigEntry *entries, int n_entries) {
void *buffer = NULL;
int size = allocateReadFile(path, &buffer);
2018-08-27 15:51:18 +00:00
if (size < 0)
2017-10-13 10:42:36 +00:00
return size;
readConfigBuffer(buffer, size, entries, n_entries);
free(buffer);
return 0;
}
static int writeEntry(SceUID fd, ConfigEntry *entry) {
if (!entry->value)
return -1;
int result;
if ((result = sceIoWrite(fd, entry->name, strlen(entry->name))) < 0)
return result;
if ((result = sceIoWrite(fd, " = ", 3)) < 0)
return result;
char *val;
char buffer[33];
switch (entry->type) {
case CONFIG_TYPE_BOOLEAN:
val = *(uint32_t *)entry->value != 0 ? "true" : "false";
result = sceIoWrite(fd, val, strlen(val));
break;
case CONFIG_TYPE_DECIMAL:
itoa(*(int *)entry->value, buffer, 10);
result = sceIoWrite(fd, buffer, strlen(buffer));
break;
case CONFIG_TYPE_HEXDECIMAL:
itoa(*(int *)entry->value, buffer, 16);
result = sceIoWrite(fd, buffer, strlen(buffer));
break;
case CONFIG_TYPE_STRING:
val = *(char **)entry->value;
sceIoWrite(fd, "\"", 1);
result = sceIoWrite(fd, val, strlen(val));
sceIoWrite(fd, "\"", 1);
break;
default:
return 1;
}
if (result < 0)
return result;
if ((sceIoWrite(fd, "\n", 1)) < 0)
return result;
return 0;
2016-10-31 19:31:44 +00:00
}
2017-02-12 15:27:43 +00:00
int writeConfig(const char *path, ConfigEntry *entries, int n_entries) {
2017-10-13 10:42:36 +00:00
SceUID fd = sceIoOpen(path, SCE_O_WRONLY | SCE_O_CREAT | SCE_O_TRUNC, 0777);
if (fd < 0)
return fd;
int i;
for (i = 0; i < n_entries; i++) {
int result = writeEntry(fd, entries+i);
if (result != 0) {
return result;
2016-10-31 19:31:44 +00:00
}
2017-10-13 10:42:36 +00:00
}
2016-10-31 19:31:44 +00:00
2017-10-13 10:42:36 +00:00
sceIoClose(fd);
2016-10-31 19:31:44 +00:00
2017-10-13 10:42:36 +00:00
return 0;
}