Files
CgeConf/Conf.c
T
blankhex bb5e4eeaa9
CI / build-and-analyze (push) Failing after 43s
Initial commit
2026-09-22 19:00:03 +03:00

189 lines
4.1 KiB
C

#include "CgeConf.h"
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#define MAX_LINE 4096
typedef struct StrView {
char *data;
size_t size;
} StrView;
typedef struct MemCtx {
const char *buffer;
size_t size;
size_t pos;
} MemCtx;
static int memRead(void *ctx, void *buffer, size_t size, size_t *actual) {
MemCtx *mem = (MemCtx *)ctx;
size_t remaining = mem->size - mem->pos;
if (size > remaining)
size = remaining;
memcpy(buffer, mem->buffer + mem->pos, size);
mem->pos += size;
*actual = size;
return 1;
}
static int fileRead(void *ctx, void *buffer, size_t size, size_t *actual) {
*actual = fread(buffer, 1, size, (FILE *)ctx);
return 1;
}
static void trimLeft(StrView *view) {
for (; view->size && isspace(*view->data); ++view->data, --view->size);
}
static void trimRight(StrView *view) {
char *last = view->data + view->size;
for (; last > view->data && isspace(*(last - 1)); last--, view->size--);
}
static void trim(StrView *view) {
trimLeft(view);
trimRight(view);
}
static size_t firstIndex(StrView *view, char symbol) {
char *current, *end;
current = view->data;
end = view->data + view->size;
for (; current < end; ++current) {
if (*current == symbol)
return current - view->data;
}
return -1;
}
static int split(StrView *view, StrView *prefix, char delim) {
size_t position;
if ((position = firstIndex(view, delim)) == -1)
return 0;
prefix->data = view->data;
prefix->size = position;
view->data += position;
view->size -= position;
return 1;
}
static void parseLine(StrView *view, CgeConfCb callback, void *user) {
StrView key;
trim(view);
if (!view->size || *view->data == '#' || *view->data == ';')
return;
if (*view->data == '[' && *(view->data + view->size - 1) == ']') {
view->size -= 2;
view->data += 1;
trim(view);
view->data[view->size] = 0;
callback(CGE_CONF_SECTION, NULL, view->data, user);
} else if (split(view, &key, '=')) {
trimRight(&key);
view->data++, view->size--;
trimLeft(view);
if (view->size > 1 && *view->data == '"' &&
*(view->data + view->size - 1) == '"') {
view->size -= 2;
view->data += 1;
}
key.data[key.size] = 0;
view->data[view->size] = 0;
callback(CGE_CONF_KEYVALUE, key.data, view->data, user);
}
}
static int readSymbol(CgeConfIO *io) {
unsigned char symbol;
size_t actual;
if (!io->read(io->ctx, &symbol, 1, &actual) || !actual)
return -1;
return (int)symbol;
}
static size_t readLine(CgeConfIO *io, char *buffer, size_t size) {
int symbol;
size_t counter = 0;
while ((symbol = readSymbol(io)) != -1) {
if (counter && symbol == '\n')
break;
else if (symbol == '\n')
continue;
if (symbol == '\r')
continue;
if (counter >= size - 1)
return -1;
buffer[counter++] = symbol;
}
buffer[counter] = 0;
return counter;
}
int CgeConfFromString(const char *str, CgeConfCb callback, void *user) {
return CgeConfFromMemory(str, strlen(str), callback, user);
}
int CgeConfFromMemory(const char *buffer, size_t size, CgeConfCb callback,
void *user) {
CgeConfIO io;
MemCtx mem;
mem.buffer = buffer;
mem.size = size;
mem.pos = 0;
io.read = memRead;
io.ctx = &mem;
return CgeConfFromCb(&io, callback, user);
}
int CgeConfFromFile(const char *path, CgeConfCb callback, void *user) {
CgeConfIO io;
FILE *file;
int ret;
file = fopen(path, "rb");
if (!file)
return 0;
io.read = fileRead;
io.ctx = file;
ret = CgeConfFromCb(&io, callback, user);
fclose(file);
return ret;
}
int CgeConfFromCb(CgeConfIO *io, CgeConfCb callback, void *user) {
char buffer[MAX_LINE];
StrView view;
while ((view.size = readLine(io, buffer, MAX_LINE))) {
if (view.size == -1)
return 0;
view.data = buffer;
parseLine(&view, callback, user);
}
return 1;
}