@@ -0,0 +1,188 @@
|
||||
#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;
|
||||
}
|
||||
Reference in New Issue
Block a user