/* * Copyright 2023 Oleg Borodin */ #include #include #include #include #include #include #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); }