179 lines
4.7 KiB
C
179 lines
4.7 KiB
C
/*
|
|
* Copyright 2023 Oleg Borodin <borodin@unix7.org>
|
|
*/
|
|
|
|
#include <stdbool.h>
|
|
#include <string.h>
|
|
#include <stdlib.h>
|
|
#include <stdio.h>
|
|
#include <ctype.h>
|
|
|
|
#include <cfparser.h>
|
|
#include <logger.h>
|
|
|
|
|
|
#define INIT_BSIZE 64
|
|
|
|
|
|
static char* strcopy(char* src) {
|
|
size_t srcsize = strlen(src) + 1;
|
|
char* dst = malloc(srcsize);
|
|
|
|
memset(dst, '\0', srcsize);
|
|
strcpy(dst, src);
|
|
return dst;
|
|
}
|
|
|
|
#if 0
|
|
static char* strconcat(char** str, int num) {
|
|
size_t tsize = 0;
|
|
size_t size[num];
|
|
|
|
for (int i = 0; i < num; i++) {
|
|
size[i] = 0;
|
|
if (str[i] != NULL) {
|
|
size[i] = strlen(str[i]);
|
|
tsize += size[i];
|
|
}
|
|
}
|
|
tsize++;
|
|
char* dst = malloc(tsize);
|
|
|
|
memset(dst, '\0', tsize);
|
|
int pos = 0;
|
|
|
|
for (int i = 0; i < num; i++) {
|
|
if (str[i] != NULL) {
|
|
strcpy(&dst[pos], str[i]);
|
|
pos += size[i];
|
|
}
|
|
}
|
|
return dst;
|
|
}
|
|
#endif
|
|
|
|
|
|
void cfparser_init(cfparser_t * parser, cflexer_t * lexer) {
|
|
parser->lexer = lexer;
|
|
parser->kvalarr = malloc(sizeof(cfkval_t) * INIT_BSIZE);
|
|
parser->kvalcapa = INIT_BSIZE;
|
|
parser->kvalsize = 0;
|
|
}
|
|
|
|
int cfparser_bind(cfparser_t * parser, int type, char* key, void* ref) {
|
|
for (int i = 0; i < parser->kvalsize; i++) {
|
|
if (strcmp(key, parser->kvalarr[i].key) == 0) {
|
|
char* key = parser->kvalarr[i].key;
|
|
char* val = parser->kvalarr[i].val;
|
|
switch (type) {
|
|
case CFVALTYPE_STR: {
|
|
*(char**)(ref) = strcopy(val);
|
|
break;
|
|
}
|
|
case CFVALTYPE_INT: {
|
|
for (size_t i = 0; i < strlen(val); i++) {
|
|
if (isdigit(val[i]) == 0 && val[i] != '-' ) {
|
|
log_error("wrong integer value: %s = %s", key, val);
|
|
return -1;
|
|
}
|
|
}
|
|
char* eptr = NULL;
|
|
*(int64_t*)(ref) = (int64_t)strtol(val, &eptr, 10);
|
|
break;
|
|
}
|
|
case CFVALTYPE_BOOL:{
|
|
*(bool*)(ref) = false;
|
|
if (strcmp(val, "true") == 0) {
|
|
*(bool*)(ref) = true;
|
|
} else if (strcmp(val, "false") == 0) {
|
|
*(bool*)(ref) = false;
|
|
} else {
|
|
log_error("wrong boolean key value: %s = %s", key, val);
|
|
}
|
|
break;
|
|
}
|
|
|
|
}
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
#define MAX_TOKEN_SIZE 1024
|
|
|
|
|
|
int cfparser_parse(cfparser_t * parser) {
|
|
cflexer_t* lex = parser->lexer;
|
|
|
|
char token[MAX_TOKEN_SIZE];
|
|
int type = 0;
|
|
int pos = 0;
|
|
|
|
char* key;
|
|
//char* val;
|
|
|
|
while ((type = cflexer_gettoken(lex, token)) != CFLEXTOK_END) {
|
|
switch (pos) {
|
|
// POS 0
|
|
case 0:{
|
|
if (type == CFLEXTOK_SPACE) continue;
|
|
if (type == CFLEXTOK_COMM) continue;
|
|
if (type == CFLEXTOK_NEXT) continue;
|
|
if (type == CFLEXTOK_WORD) {
|
|
key = strcopy(token);
|
|
pos++;
|
|
} else {
|
|
return -1;
|
|
}
|
|
break;
|
|
}
|
|
// POS 1
|
|
case 1:{
|
|
if (type == CFLEXTOK_SPACE) continue;
|
|
if (type == CFLEXTOK_SEPAR) {
|
|
pos++;
|
|
} else {
|
|
return -1;
|
|
}
|
|
break;
|
|
}
|
|
// POS 2
|
|
case 2:{
|
|
if (type == CFLEXTOK_SPACE) continue;
|
|
if (type == CFLEXTOK_WORD) {
|
|
char* val = strcopy(token);
|
|
if (parser->kvalsize >= parser->kvalcapa) {
|
|
// TODO
|
|
}
|
|
parser->kvalarr[parser->kvalsize].key = key;
|
|
parser->kvalarr[parser->kvalsize].val = val;
|
|
parser->kvalsize++;
|
|
pos++;
|
|
} else {
|
|
return -1;
|
|
}
|
|
break;
|
|
}
|
|
case 3:{
|
|
if (type == CFLEXTOK_SPACE) continue;
|
|
if (type == CFLEXTOK_COMM) continue;
|
|
if (type == CFLEXTOK_NEXT) {
|
|
pos = 0;
|
|
} else {
|
|
return -1;
|
|
}
|
|
break;
|
|
}
|
|
default:{
|
|
return -1;
|
|
}
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
|
|
void cfparser_destroy(cfparser_t * parser) {
|
|
free(parser->kvalarr);
|
|
}
|