267 lines
8.5 KiB
C
267 lines
8.5 KiB
C
/*
|
|
* Copyright 2023 Oleg Borodin <borodin@unix7.org>
|
|
*/
|
|
|
|
#include <stdbool.h>
|
|
#include <string.h>
|
|
#include <stdlib.h>
|
|
#include <stdio.h>
|
|
|
|
#include <logger.h>
|
|
#include <jparser.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;
|
|
}
|
|
|
|
void jparser_init(jparser_t * parser, jlexer_t * lexer) {
|
|
parser->lexer = lexer;
|
|
parser->kvalarr = malloc(sizeof(jkval_t) * INIT_BSIZE);
|
|
parser->kvalcapa = INIT_BSIZE;
|
|
parser->kvalsize = 0;
|
|
}
|
|
|
|
#define MAX_TOKEN_SIZE 1024
|
|
|
|
int jparser_parse_array(jparser_t * parser, char* arrname) {
|
|
jlexer_t* lex = parser->lexer;
|
|
|
|
char token[MAX_TOKEN_SIZE];
|
|
int type = 0;
|
|
|
|
int pos = 0;
|
|
|
|
|
|
while ((type = jlexer_gettoken(lex, token)) != JLEXTOK_END) {
|
|
log_debug("pos %d tok 0x%02x: %s\n", pos, type, token);
|
|
|
|
if (type == JLEXTOK_ARRE) {
|
|
return 1;
|
|
}
|
|
|
|
|
|
}
|
|
return 1;
|
|
|
|
}
|
|
|
|
int jparser_parse(jparser_t * parser) {
|
|
jlexer_t* lex = parser->lexer;
|
|
char token[MAX_TOKEN_SIZE];
|
|
int type = 0;
|
|
|
|
int pos = 0;
|
|
char* key = "";
|
|
|
|
while ((type = jlexer_gettoken(lex, token)) != JLEXTOK_END) {
|
|
log_debug("pos %d tok 0x%02x: %s\n", pos, type, token);
|
|
switch (pos) {
|
|
// POS 0
|
|
case 0:{
|
|
if (type == JLEXTOK_END) {
|
|
log_error("End token received in position %d", pos);
|
|
return -1;
|
|
}
|
|
if (type != JLEXTOK_BLOCKB) {
|
|
log_error("Wrong block token: %s", token);
|
|
return -1;
|
|
}
|
|
pos++;
|
|
break;
|
|
}
|
|
// POS 1
|
|
case 1:{
|
|
if (type == JLEXTOK_END) {
|
|
log_error("End token received in position %d", pos);
|
|
//return -1;
|
|
}
|
|
if (type == JLEXTOK_SPACE)
|
|
continue;
|
|
if (type == JLEXTOK_NEXT)
|
|
continue;
|
|
if (type == JLEXTOK_BLOCKE)
|
|
return 0;
|
|
if (type != JLEXTOK_WORD) {
|
|
log_error("Wrong word token: %s", token);
|
|
return -1;
|
|
}
|
|
key = strcopy(token);
|
|
pos++;
|
|
break;
|
|
}
|
|
// POS 2
|
|
case 2:{
|
|
if (type == JLEXTOK_END) {
|
|
log_error("End token received in position %d", pos);
|
|
return -1;
|
|
}
|
|
if (type == JLEXTOK_SPACE)
|
|
continue;
|
|
if (type != JLEXTOK_SEPAR) {
|
|
log_error("Wrong delimeter token: %s", token);
|
|
return -1;
|
|
}
|
|
pos++;
|
|
break;
|
|
}
|
|
// POS 3
|
|
case 3:{
|
|
if (type == JLEXTOK_END) {
|
|
log_error("End token received in position %d", pos);
|
|
return -1;
|
|
}
|
|
if (type == JLEXTOK_SPACE)
|
|
continue;
|
|
if (type == JLEXTOK_BLOCKB) {
|
|
pos = 1;
|
|
continue;
|
|
}
|
|
if (type == JLEXTOK_WORD) {
|
|
char* val = strcopy(token);
|
|
jkval_t* kv = &(parser->kvalarr[parser->kvalsize]);
|
|
kv->key = strcopy(key);
|
|
//log_debug("Parser added key %s", kv->key);
|
|
kv->type = JVALTYPE_STR;
|
|
kv->str = val;
|
|
free(key);
|
|
parser->kvalsize++;
|
|
pos++;
|
|
break;
|
|
}
|
|
if (type == JLEXTOK_INTEG) {
|
|
char* val = strcopy(token);
|
|
jkval_t* kv = &(parser->kvalarr[parser->kvalsize]);
|
|
kv->key = strcopy(key);
|
|
kv->type = JVALTYPE_INTEG;
|
|
char* eptr = NULL;
|
|
kv->integ = (int64_t)strtol(val, &eptr, 10);;
|
|
free(val);
|
|
free(key);
|
|
log_debug("Parser added integer key %s = %d", kv->key, kv->integ);
|
|
parser->kvalsize++;
|
|
pos++;
|
|
break;
|
|
}
|
|
if (type == JLEXTOK_FLOAT) {
|
|
char* val = strcopy(token);
|
|
jkval_t* kv = &(parser->kvalarr[parser->kvalsize]);
|
|
kv->key = strcopy(key);
|
|
kv->type = JVALTYPE_FLOAT;
|
|
char* eptr = NULL;
|
|
kv->numb = (double)strtod(val, &eptr);
|
|
log_debug("Parser added float key %s = %f", kv->key, kv->numb);
|
|
free(val);
|
|
free(key);
|
|
parser->kvalsize++;
|
|
pos++;
|
|
break;
|
|
}
|
|
|
|
if (type == JLEXTOK_RAWSTR) {
|
|
char* val = strcopy(token);
|
|
bool isbool = false;
|
|
bool bval = false;
|
|
if (strcmp(val, "true") == 0) {
|
|
isbool = true;
|
|
bval = true;
|
|
}
|
|
if (strcmp(val, "false") == 0) {
|
|
isbool = true;
|
|
bval = false;
|
|
}
|
|
if (isbool) {
|
|
jkval_t* kv = &(parser->kvalarr[parser->kvalsize]);
|
|
kv->key = strcopy(key);
|
|
log_debug("Parser added bool key %s = %d", kv->key, bval);
|
|
kv->type = JVALTYPE_BOOL;
|
|
kv->flag = bval;
|
|
free(key);
|
|
parser->kvalsize++;
|
|
pos++;
|
|
break;
|
|
}
|
|
}
|
|
if (type == JLEXTOK_ARRB) {
|
|
jkval_t* kv = &(parser->kvalarr[parser->kvalsize]);
|
|
kv->key = strcopy(key);
|
|
log_debug("Parser added array key %s", kv->key);
|
|
if (jparser_parse_array(parser, kv->key) < 0) {
|
|
log_error("Wrong array: %s", key);
|
|
return -1;
|
|
}
|
|
pos++;
|
|
break;
|
|
}
|
|
log_error("Wrong value token: %s", token);
|
|
return -1;
|
|
|
|
}
|
|
// POS 4
|
|
case 4:{
|
|
if (type == JLEXTOK_END) {
|
|
log_error("End token received in position %d", pos);
|
|
return -1;
|
|
}
|
|
if (type == JLEXTOK_SPACE) {
|
|
continue;
|
|
} else if (type == JLEXTOK_BLOCKE) {
|
|
//log_debug("Block ended: %s", token);
|
|
return 0;
|
|
} else if (type != JLEXTOK_NEXT && type != JLEXTOK_BLOCKE) {
|
|
log_error("Wrong next token: %s", token);
|
|
return -1;
|
|
}
|
|
pos = 1;
|
|
break;
|
|
}
|
|
default:{
|
|
log_error("Wrong parser stage: %s", token);
|
|
if (type == JLEXTOK_END) {
|
|
log_error("End token received in position %d", pos);
|
|
return -1;
|
|
}
|
|
return -1;
|
|
}
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
int jparser_bind(jparser_t* parser, int type, char* key, void* ref) {
|
|
for (int i = 0; i < parser->kvalsize; i++) {
|
|
jkval_t* kv = &(parser->kvalarr[i]);
|
|
|
|
//log_debug("Find equal keys: kv->key = %s, key = %s", kv->key, key);
|
|
if (strcmp(kv->key, key) == 0) {
|
|
if (kv->type == JVALTYPE_STR) {
|
|
*(char**)(ref) = strcopy(kv->str);
|
|
} else if (kv->type == JVALTYPE_INTEG) {
|
|
*(int64_t*)(ref) = kv->integ;
|
|
} else if (kv->type == JVALTYPE_FLOAT) {
|
|
*(double*)(ref) = kv->numb;
|
|
} else if (kv->type == JVALTYPE_BOOL) {
|
|
*(bool*)(ref) = kv->flag;
|
|
}
|
|
return 0;
|
|
}
|
|
}
|
|
return -1;
|
|
}
|
|
|
|
void jparser_destroy(jparser_t * parser) {
|
|
for (int i = 0; i < parser->kvalsize; i++) {
|
|
if (parser->kvalarr[i].type == JVALTYPE_STR) {
|
|
free(parser->kvalarr[i].str);
|
|
}
|
|
}
|
|
free(parser->kvalarr);
|
|
}
|