summaryrefslogtreecommitdiff
path: root/vendors/ini.c
diff options
context:
space:
mode:
Diffstat (limited to 'vendors/ini.c')
-rw-r--r--vendors/ini.c277
1 files changed, 0 insertions, 277 deletions
diff --git a/vendors/ini.c b/vendors/ini.c
deleted file mode 100644
index d6f5b75..0000000
--- a/vendors/ini.c
+++ /dev/null
@@ -1,277 +0,0 @@
-/**
- * Copyright (c) 2016 rxi
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <ctype.h>
-
-#include "ini.h"
-
-struct ini_t {
- char *data;
- char *end;
-};
-
-
-/* Case insensitive string compare */
-static int strcmpci(const char *a, const char *b) {
- for (;;) {
- int d = tolower(*a) - tolower(*b);
- if (d != 0 || !*a) {
- return d;
- }
- a++, b++;
- }
-}
-
-/* Returns the next string in the split data */
-static char* next(ini_t *ini, char *p) {
- p += strlen(p);
- while (p < ini->end && *p == '\0') {
- p++;
- }
- return p;
-}
-
-static void trim_back(ini_t *ini, char *p) {
- while (p >= ini->data && (*p == ' ' || *p == '\t' || *p == '\r')) {
- *p-- = '\0';
- }
-}
-
-static char* discard_line(ini_t *ini, char *p) {
- while (p < ini->end && *p != '\n') {
- *p++ = '\0';
- }
- return p;
-}
-
-
-static char *unescape_quoted_value(ini_t *ini, char *p) {
- /* Use `q` as write-head and `p` as read-head, `p` is always ahead of `q`
- * as escape sequences are always larger than their resultant data */
- char *q = p;
- p++;
- while (p < ini->end && *p != '"' && *p != '\r' && *p != '\n') {
- if (*p == '\\') {
- /* Handle escaped char */
- p++;
- switch (*p) {
- default : *q = *p; break;
- case 'r' : *q = '\r'; break;
- case 'n' : *q = '\n'; break;
- case 't' : *q = '\t'; break;
- case '\r' :
- case '\n' :
- case '\0' : goto end;
- }
-
- } else {
- /* Handle normal char */
- *q = *p;
- }
- q++, p++;
- }
-end:
- return q;
-}
-
-
-/* Splits data in place into strings containing section-headers, keys and
- * values using one or more '\0' as a delimiter. Unescapes quoted values */
-static void split_data(ini_t *ini) {
- char *value_start, *line_start;
- char *p = ini->data;
-
- while (p < ini->end) {
- switch (*p) {
- case '\r':
- case '\n':
- case '\t':
- case ' ':
- *p = '\0';
- /* Fall through */
-
- case '\0':
- p++;
- break;
-
- case '[':
- p += strcspn(p, "]\n");
- *p = '\0';
- break;
-
- case ';':
- p = discard_line(ini, p);
- break;
-
- default:
- line_start = p;
- p += strcspn(p, "=\n");
-
- /* Is line missing a '='? */
- if (*p != '=') {
- p = discard_line(ini, line_start);
- break;
- }
- trim_back(ini, p - 1);
-
- /* Replace '=' and whitespace after it with '\0' */
- do {
- *p++ = '\0';
- } while (*p == ' ' || *p == '\r' || *p == '\t');
-
- /* Is a value after '=' missing? */
- if (*p == '\n' || *p == '\0') {
- p = discard_line(ini, line_start);
- break;
- }
-
- if (*p == '"') {
- /* Handle quoted string value */
- value_start = p;
- p = unescape_quoted_value(ini, p);
-
- /* Was the string empty? */
- if (p == value_start) {
- p = discard_line(ini, line_start);
- break;
- }
-
- /* Discard the rest of the line after the string value */
- p = discard_line(ini, p);
-
- } else {
- /* Handle normal value */
- p += strcspn(p, "\n");
- trim_back(ini, p - 1);
- }
- break;
- }
- }
-}
-
-
-
-ini_t* ini_load(const char *filename) {
- ini_t *ini = NULL;
- FILE *fp = NULL;
- int n, sz;
-
- /* Init ini struct */
- ini = malloc(sizeof(*ini));
- if (!ini) {
- goto fail;
- }
- memset(ini, 0, sizeof(*ini));
-
- /* Open file */
- fp = fopen(filename, "rb");
- if (!fp) {
- goto fail;
- }
-
- /* Get file size */
- fseek(fp, 0, SEEK_END);
- sz = ftell(fp);
- rewind(fp);
-
- /* Load file content into memory, null terminate, init end var */
- ini->data = malloc(sz + 1);
- if (!ini->data) {
- goto fail;
- }
- ini->data[sz] = '\0';
- ini->end = ini->data + sz;
- n = fread(ini->data, 1, sz, fp);
- if (n != sz) {
- goto fail;
- }
-
- /* Prepare data */
- split_data(ini);
-
- /* Clean up and return */
- fclose(fp);
- return ini;
-
-fail:
- if (fp) fclose(fp);
- if (ini) ini_free(ini);
- return NULL;
-}
-
-
-void ini_free(ini_t *ini) {
- if (ini->data) free(ini->data);
- free(ini);
-}
-
-
-const char* ini_get(ini_t *ini, const char *section, const char *key) {
- char *current_section = "";
- char *val;
- char *p = ini->data;
-
- if (*p == '\0') {
- p = next(ini, p);
- }
-
- while (p < ini->end) {
- if (*p == '[') {
- /* Handle section */
- current_section = p + 1;
-
- } else {
- /* Handle key */
- val = next(ini, p);
- if (!section || !strcmpci(section, current_section)) {
- if (!strcmpci(p, key)) {
- return val;
- }
- }
- p = val;
- }
-
- p = next(ini, p);
- }
-
- return NULL;
-}
-
-
-int ini_sget(
- ini_t *ini, const char *section, const char *key,
- const char *scanfmt, void *dst
-) {
- const char *val = ini_get(ini, section, key);
- if (!val) {
- return 0;
- }
- if (scanfmt) {
- sscanf(val, scanfmt, dst);
- } else {
- *((const char**) dst) = val;
- }
- return 1;
-}