Files
cworker/jparser.c
2023-08-14 23:30:54 +02:00

151 lines
4.0 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(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) {
switch (pos) {
// POS 0
case 0:{
if (type != JLEXTOK_BLOCKB) {
log_error("wrong block token: %s", token);
return -1;
}
pos++;
break;
}
// POS 1
case 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_SPACE)
continue;
if (type != JLEXTOK_SEPAR) {
log_error("wrong delimeter token: %s", token);
return -1;
}
pos++;
break;
}
// POS 3
case 3:{
if (type == JLEXTOK_SPACE)
continue;
if (type != JLEXTOK_WORD && type != JLEXTOK_NUMB) {
log_error("wrong delimeter token: %s", token);
return -1;
}
char* val = strcopy(token);
jkval_t* kv = &(parser->kvalarr[parser->kvalsize]);
kv->key = key;
if (type == JLEXTOK_NUMB) {
kv->type = JVALTYPE_NUM;
char* eptr = NULL;
kv->num = (int64_t)strtol(val, &eptr, 10);;
free(val);
} else {
kv->type = JVALTYPE_STR;
kv->str = val;
}
free(key);
parser->kvalsize++;
pos++;
break;
}
// POS 4
case 4:{
if (type == JLEXTOK_SPACE)
continue;
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);
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]);
if (strcmp(kv->key, key) == 0) {
if (kv->type == JVALTYPE_STR) {
*(char**)(ref) = strcopy(kv->str);
} else if (kv->type == JVALTYPE_NUM) {
*(int*)(ref) = kv->num;
}
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);
}