From 2174c1bd9bd5b343430afddcd4c1f5218b07c4e7 Mon Sep 17 00:00:00 2001 From: hyung-hwan Date: Sat, 6 Jun 2020 18:53:09 +0000 Subject: [PATCH] enhanced mio_json_instcb_t to accept a position with a parent container --- mio/bin/t03.c | 60 +++++++++++++++++++++++++------ mio/lib/json.c | 89 +++++++++++++++++++++++++++------------------- mio/lib/mio-json.h | 2 ++ 3 files changed, 104 insertions(+), 47 deletions(-) diff --git a/mio/bin/t03.c b/mio/bin/t03.c index c21154e..636b7c0 100644 --- a/mio/bin/t03.c +++ b/mio/bin/t03.c @@ -30,56 +30,93 @@ #include #include -static int on_json_inst (mio_json_t* json, mio_json_inst_t inst, mio_oow_t level, const mio_oocs_t* str, void* ctx) +static int on_json_inst (mio_json_t* json, mio_json_inst_t inst, mio_oow_t level, mio_oow_t index, const mio_oocs_t* str, void* ctx) { mio_t* mio = mio_json_getmio(json); mio_oow_t i; + switch (inst) { case MIO_JSON_INST_START_ARRAY: - /* for (i = 0; i < level; i++) mio_logbfmt (mio, MIO_LOG_STDOUT, "\t"); */ + if (level > 0) + { + if (index > 0) mio_logbfmt (mio, MIO_LOG_STDOUT, ",\n"); + for (i = 0; i < level; i++) mio_logbfmt (mio, MIO_LOG_STDOUT, "\t"); + } mio_logbfmt (mio, MIO_LOG_STDOUT, "[\n"); break; case MIO_JSON_INST_END_ARRAY: + mio_logbfmt (mio, MIO_LOG_STDOUT, "\n"); for (i = 0; i < level; i++) mio_logbfmt (mio, MIO_LOG_STDOUT, "\t"); - mio_logbfmt (mio, MIO_LOG_STDOUT, "]\n"); + mio_logbfmt (mio, MIO_LOG_STDOUT, "]"); break; case MIO_JSON_INST_START_DIC: - /*for (i = 0; i < level; i++) mio_logbfmt (mio, MIO_LOG_STDOUT, "\t"); */ + if (level > 0) + { + if (index > 0) mio_logbfmt (mio, MIO_LOG_STDOUT, ",\n"); + for (i = 0; i < level; i++) mio_logbfmt (mio, MIO_LOG_STDOUT, "\t"); + } mio_logbfmt (mio, MIO_LOG_STDOUT, "{\n"); break; case MIO_JSON_INST_END_DIC: + mio_logbfmt (mio, MIO_LOG_STDOUT, "\n"); for (i = 0; i < level; i++) mio_logbfmt (mio, MIO_LOG_STDOUT, "\t"); - mio_logbfmt (mio, MIO_LOG_STDOUT, "}\n"); + mio_logbfmt (mio, MIO_LOG_STDOUT, "}"); break; case MIO_JSON_INST_KEY: - for (i = 0; i < level; i++) mio_logbfmt (mio, MIO_LOG_STDOUT, "\t"); + if (index > 0) mio_logbfmt (mio, MIO_LOG_STDOUT, ",\n"); + for (i = 0; i < level; i++) mio_logbfmt (mio, MIO_LOG_STDOUT, "\t"); mio_logbfmt (mio, MIO_LOG_STDOUT, "%.*js: ", str->len, str->ptr); break; case MIO_JSON_INST_NIL: - mio_logbfmt (mio, MIO_LOG_STDOUT, "null\n"); + if (level > 0) + { + if (index > 0) mio_logbfmt (mio, MIO_LOG_STDOUT, ",\n"); + for (i = 0; i < level; i++) mio_logbfmt (mio, MIO_LOG_STDOUT, "\t"); + } + mio_logbfmt (mio, MIO_LOG_STDOUT, "null"); break; case MIO_JSON_INST_TRUE: - mio_logbfmt (mio, MIO_LOG_STDOUT, "true\n"); + if (level > 0) + { + if (index > 0) mio_logbfmt (mio, MIO_LOG_STDOUT, ",\n"); + for (i = 0; i < level; i++) mio_logbfmt (mio, MIO_LOG_STDOUT, "\t"); + } + mio_logbfmt (mio, MIO_LOG_STDOUT, "true"); break; case MIO_JSON_INST_FALSE: - mio_logbfmt (mio, MIO_LOG_STDOUT, "false\n"); + if (level > 0) + { + if (index > 0) mio_logbfmt (mio, MIO_LOG_STDOUT, ",\n"); + for (i = 0; i < level; i++) mio_logbfmt (mio, MIO_LOG_STDOUT, "\t"); + } + mio_logbfmt (mio, MIO_LOG_STDOUT, "false"); break; case MIO_JSON_INST_NUMBER: - mio_logbfmt (mio, MIO_LOG_STDOUT, "%.*js\n", str->len, str->ptr); + if (level > 0) + { + if (index > 0) mio_logbfmt (mio, MIO_LOG_STDOUT, ",\n"); + for (i = 0; i < level; i++) mio_logbfmt (mio, MIO_LOG_STDOUT, "\t"); + } + mio_logbfmt (mio, MIO_LOG_STDOUT, "%.*js", str->len, str->ptr); break; case MIO_JSON_INST_STRING: - mio_logbfmt (mio, MIO_LOG_STDOUT, "\"%.*js\"\n", str->len, str->ptr); /* TODO: escaping */ + if (level > 0) + { + if (index > 0) mio_logbfmt (mio, MIO_LOG_STDOUT, ",\n"); + for (i = 0; i < level; i++) mio_logbfmt (mio, MIO_LOG_STDOUT, "\t"); + } + mio_logbfmt (mio, MIO_LOG_STDOUT, "\"%.*js\"", str->len, str->ptr); /* TODO: escaping */ break; default: @@ -135,6 +172,7 @@ int main (int argc, char* argv[]) if (rem > 0) memcpy (buf, &buf[size - rem], rem); } +mio_logbfmt (mio, MIO_LOG_STDOUT, "\n"); mio_json_close (json); } diff --git a/mio/lib/json.c b/mio/lib/json.c index 8dadb59..2b9d6cd 100644 --- a/mio/lib/json.c +++ b/mio/lib/json.c @@ -108,6 +108,7 @@ static int push_read_state (mio_json_t* json, mio_json_state_t state) ss->state = state; ss->level = json->state_stack->level; /* copy from the parent */ + ss->index = 0; ss->next = json->state_stack; json->state_stack = ss; @@ -144,18 +145,53 @@ static void pop_all_read_states (mio_json_t* json) static int invoke_data_inst (mio_json_t* json, mio_json_inst_t inst) { - if (json->state_stack->state == MIO_JSON_STATE_IN_DIC && json->state_stack->u.id.state == 1) - { - if (inst != MIO_JSON_INST_STRING) - { - mio_seterrbfmt (json->mio, MIO_EINVAL, "dictionary key not a string - %.*js", json->tok.len, json->tok.ptr); - return -1; - } + mio_json_state_node_t* ss; + int is_dic_val = 0; - inst = MIO_JSON_INST_KEY; + ss = json->state_stack; + + if (ss->state == MIO_JSON_STATE_IN_DIC) + { + if (ss->u.id.state == 1) /* got colon */ + { + /* this is called after the reader has seen a colon. + * the data item must be used as a key */ + + if (inst != MIO_JSON_INST_STRING) + { + mio_seterrbfmt (json->mio, MIO_EINVAL, "dictionary key not a string - %.*js", json->tok.len, json->tok.ptr); + return -1; + } + + inst = MIO_JSON_INST_KEY; + } + else + { + /* if this variable is non-zero, level is set to 0 regardless of actual level */ + is_dic_val = 1; + } } - return json->instcb(json, inst, json->state_stack->level, &json->tok, json->rctx); + switch (inst) + { + case MIO_JSON_INST_START_ARRAY: + if (push_read_state(json, MIO_JSON_STATE_IN_ARRAY) <= -1) return -1; + json->state_stack->u.ia.got_value = 0; + json->state_stack->level++; + if (ss->state != MIO_JSON_STATE_IN_DIC || ss->u.id.state == 1) ss->index++; + return json->instcb(json, inst, (is_dic_val? 0: json->state_stack->level - 1), ss->index - 1, MIO_NULL, json->rctx); + + case MIO_JSON_INST_START_DIC: + if (push_read_state(json, MIO_JSON_STATE_IN_DIC) <= -1) return -1; + json->state_stack->u.id.state = 0; + json->state_stack->level++; + if (ss->state != MIO_JSON_STATE_IN_DIC || ss->u.id.state == 1) ss->index++; + return json->instcb(json, inst, (is_dic_val? 0: json->state_stack->level - 1), ss->index - 1, MIO_NULL, json->rctx); + + default: + if (ss->state != MIO_JSON_STATE_IN_DIC || ss->u.id.state == 1) ss->index++; + return json->instcb(json, inst, (is_dic_val? 0: json->state_stack->level), ss->index - 1, &json->tok, json->rctx); + } } static int handle_string_value_char (mio_json_t* json, mio_ooci_t c) @@ -331,21 +367,14 @@ static int handle_word_value_char (mio_json_t* json, mio_ooci_t c) static int handle_start_char (mio_json_t* json, mio_ooci_t c) { -printf ("HANDLE START CHAR [%c]\n", c); if (c == '[') { - if (push_read_state(json, MIO_JSON_STATE_IN_ARRAY) <= -1) return -1; - json->state_stack->u.ia.got_value = 0; - if (json->instcb(json, MIO_JSON_INST_START_ARRAY, json->state_stack->level, MIO_NULL, json->rctx) <= -1) return -1; - json->state_stack->level++; + if (invoke_data_inst(json, MIO_JSON_INST_START_ARRAY) <= -1) return -1; return 1; } else if (c == '{') { - if (push_read_state(json, MIO_JSON_STATE_IN_DIC) <= -1) return -1; - json->state_stack->u.id.state = 0; - if (json->instcb(json, MIO_JSON_INST_START_DIC, json->state_stack->level, MIO_NULL, json->rctx) <= -1) return -1; - json->state_stack->level++; + if (invoke_data_inst(json, MIO_JSON_INST_START_DIC) <= -1) return -1; return 1; } #if 0 @@ -367,7 +396,7 @@ static int handle_char_in_array (mio_json_t* json, mio_ooci_t c) { if (c == ']') { - if (json->instcb(json, MIO_JSON_INST_END_ARRAY, json->state_stack->level - 1, MIO_NULL, json->rctx) <= -1) return -1; + if (json->instcb(json, MIO_JSON_INST_END_ARRAY, json->state_stack->level - 1, json->state_stack->index, MIO_NULL, json->rctx) <= -1) return -1; pop_read_state (json); return 1; } @@ -417,18 +446,12 @@ static int handle_char_in_array (mio_json_t* json, mio_ooci_t c) } else if (c == '[') { - if (push_read_state(json, MIO_JSON_STATE_IN_ARRAY) <= -1) return -1; - json->state_stack->u.ia.got_value = 0; - if (json->instcb(json, MIO_JSON_INST_START_ARRAY, json->state_stack->level, MIO_NULL, json->rctx) <= -1) return -1; - json->state_stack->level++; + if (invoke_data_inst(json, MIO_JSON_INST_START_ARRAY) <= -1) return -1; return 1; } else if (c == '{') { - if (push_read_state(json, MIO_JSON_STATE_IN_DIC) <= -1) return -1; - json->state_stack->u.id.state = 0; - if (json->instcb(json, MIO_JSON_INST_START_DIC, json->state_stack->level, MIO_NULL, json->rctx) <= -1) return -1; - json->state_stack->level++; + if (invoke_data_inst(json, MIO_JSON_INST_START_DIC) <= -1) return -1; return 1; } else @@ -443,7 +466,7 @@ static int handle_char_in_dic (mio_json_t* json, mio_ooci_t c) { if (c == '}') { - if (json->instcb(json, MIO_JSON_INST_END_DIC, json->state_stack->level - 1, MIO_NULL, json->rctx) <= -1) return -1; + if (json->instcb(json, MIO_JSON_INST_END_DIC, json->state_stack->level - 1, json->state_stack->index, MIO_NULL, json->rctx) <= -1) return -1; pop_read_state (json); return 1; } @@ -508,18 +531,12 @@ static int handle_char_in_dic (mio_json_t* json, mio_ooci_t c) } else if (c == '[') { - if (push_read_state(json, MIO_JSON_STATE_IN_ARRAY) <= -1) return -1; - json->state_stack->u.ia.got_value = 0; - json->state_stack->level++; - if (json->instcb(json, MIO_JSON_INST_START_ARRAY, json->state_stack->level, MIO_NULL, json->rctx) <= -1) return -1; + if (invoke_data_inst(json, MIO_JSON_INST_START_ARRAY) <= -1) return -1; return 1; } else if (c == '{') { - if (push_read_state(json, MIO_JSON_STATE_IN_DIC) <= -1) return -1; - json->state_stack->u.id.state = 0; - json->state_stack->level++; - if (json->instcb(json, MIO_JSON_INST_START_DIC, json->state_stack->level, MIO_NULL, json->rctx) <= -1) return -1; + if (invoke_data_inst(json, MIO_JSON_INST_START_DIC) <= -1) return -1; return 1; } else diff --git a/mio/lib/mio-json.h b/mio/lib/mio-json.h index 2ff3d56..a8a6e4f 100644 --- a/mio/lib/mio-json.h +++ b/mio/lib/mio-json.h @@ -70,6 +70,7 @@ typedef int (*mio_json_instcb_t) ( mio_json_t* json, mio_json_inst_t inst, mio_oow_t level, + mio_oow_t index, const mio_oocs_t* str, void* ctx ); @@ -80,6 +81,7 @@ struct mio_json_state_node_t { mio_json_state_t state; mio_oow_t level; + mio_oow_t index; union { struct