/* * 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(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) { //printf("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 && type != JLEXTOK_NUMB) { log_error("Wrong value token: %s", token); return -1; } char* val = strcopy(token); jkval_t* kv = &(parser->kvalarr[parser->kvalsize]); kv->key = strcopy(key); log_debug("parser added key %s", kv->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_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_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); }