From 527f48fe8011c190e2c5f2e4d43aca77252b1770 Mon Sep 17 00:00:00 2001 From: hyung-hwan Date: Mon, 23 Apr 2018 14:30:00 +0000 Subject: [PATCH] added to handle a character literal --- lib/hcl-json.h | 4 +- lib/json.c | 227 ++++++++++++++++++++++++++++++++++++++++--------- lib/main-c.c | 5 +- lib/main-j.c | 25 +++++- lib/main-s.c | 5 +- 5 files changed, 221 insertions(+), 45 deletions(-) diff --git a/lib/hcl-json.h b/lib/hcl-json.h index 5b121d9..825168e 100644 --- a/lib/hcl-json.h +++ b/lib/hcl-json.h @@ -58,7 +58,8 @@ enum hcl_json_state_t HCL_JSON_STATE_IN_WORD_VALUE, HCL_JSON_STATE_IN_NUMERIC_VALUE, - HCL_JSON_STATE_IN_QUOTED_VALUE + HCL_JSON_STATE_IN_STRING_VALUE, + HCL_JSON_STATE_IN_CHARACTER_VALUE }; typedef enum hcl_json_state_t hcl_json_state_t; @@ -73,6 +74,7 @@ enum hcl_json_inst_t HCL_JSON_INST_KEY, + HCL_JSON_INST_CHARACTER, /* there is no such element as character in real JSON */ HCL_JSON_INST_STRING, HCL_JSON_INST_NUMBER, HCL_JSON_INST_NIL, diff --git a/lib/json.c b/lib/json.c index 1b9f23a..f4bddb8 100644 --- a/lib/json.c +++ b/lib/json.c @@ -61,7 +61,13 @@ struct hcl_json_state_node_t int escaped; int digit_count; hcl_ooch_t acc; - } qv; + } sv; + struct + { + int escaped; + int digit_count; + hcl_ooch_t acc; + } cv; struct { int dotted; @@ -272,64 +278,88 @@ static int invoke_data_inst (hcl_json_t* json, hcl_json_inst_t inst) return 0; } -static int handle_quoted_value_char (hcl_json_t* json, hcl_ooci_t c) +static int handle_string_value_char (hcl_json_t* json, hcl_ooci_t c) { - if (json->state_stack->u.qv.escaped >= 2) + int ret = 1; + + + if (json->state_stack->u.sv.escaped == 3) + { + if (c >= '0' && c <= '7') + { + json->state_stack->u.sv.acc = json->state_stack->u.sv.acc * 8 + c - '0'; + json->state_stack->u.sv.digit_count++; + if (json->state_stack->u.sv.digit_count >= json->state_stack->u.sv.escaped) goto add_sv_acc; + } + else + { + ret = 0; + goto add_sv_acc; + } + } + else if (json->state_stack->u.sv.escaped >= 2) { if (c >= '0' && c <= '9') { - json->state_stack->u.qv.acc = json->state_stack->u.qv.acc * 16 + c - '0'; - json->state_stack->u.qv.digit_count++; - if (json->state_stack->u.qv.digit_count >= json->state_stack->u.qv.escaped) goto add_qv_acc; + json->state_stack->u.sv.acc = json->state_stack->u.sv.acc * 16 + c - '0'; + json->state_stack->u.sv.digit_count++; + if (json->state_stack->u.sv.digit_count >= json->state_stack->u.sv.escaped) goto add_sv_acc; } else if (c >= 'a' && c <= 'f') { - json->state_stack->u.qv.acc = json->state_stack->u.qv.acc * 16 + c - 'a' + 10; - json->state_stack->u.qv.digit_count++; - if (json->state_stack->u.qv.digit_count >= json->state_stack->u.qv.escaped) goto add_qv_acc; + json->state_stack->u.sv.acc = json->state_stack->u.sv.acc * 16 + c - 'a' + 10; + json->state_stack->u.sv.digit_count++; + if (json->state_stack->u.sv.digit_count >= json->state_stack->u.sv.escaped) goto add_sv_acc; } else if (c >= 'A' && c <= 'F') { - json->state_stack->u.qv.acc = json->state_stack->u.qv.acc * 16 + c - 'A' + 10; - json->state_stack->u.qv.digit_count++; - if (json->state_stack->u.qv.digit_count >= json->state_stack->u.qv.escaped) goto add_qv_acc; + json->state_stack->u.sv.acc = json->state_stack->u.sv.acc * 16 + c - 'A' + 10; + json->state_stack->u.sv.digit_count++; + if (json->state_stack->u.sv.digit_count >= json->state_stack->u.sv.escaped) goto add_sv_acc; } else { - add_qv_acc: - if (add_char_to_token(json, json->state_stack->u.qv.acc) <= -1) return -1; - json->state_stack->u.qv.escaped = 0; + ret = 0; + add_sv_acc: + if (add_char_to_token(json, json->state_stack->u.sv.acc) <= -1) return -1; + json->state_stack->u.sv.escaped = 0; } } - else if (json->state_stack->u.qv.escaped == 1) + else if (json->state_stack->u.sv.escaped == 1) { - if (c == 'x') + if (c >= '0' && c <= '8') { - json->state_stack->u.qv.escaped = 2; - json->state_stack->u.qv.digit_count = 0; - json->state_stack->u.qv.acc = 0; + json->state_stack->u.sv.escaped = 3; + json->state_stack->u.sv.digit_count = 0; + json->state_stack->u.sv.acc = c - '0'; + } + else if (c == 'x') + { + json->state_stack->u.sv.escaped = 2; + json->state_stack->u.sv.digit_count = 0; + json->state_stack->u.sv.acc = 0; } else if (c == 'u') { - json->state_stack->u.qv.escaped = 4; - json->state_stack->u.qv.digit_count = 0; - json->state_stack->u.qv.acc = 0; + json->state_stack->u.sv.escaped = 4; + json->state_stack->u.sv.digit_count = 0; + json->state_stack->u.sv.acc = 0; } else if (c == 'U') { - json->state_stack->u.qv.escaped = 8; - json->state_stack->u.qv.digit_count = 0; - json->state_stack->u.qv.acc = 0; + json->state_stack->u.sv.escaped = 8; + json->state_stack->u.sv.digit_count = 0; + json->state_stack->u.sv.acc = 0; } else { - json->state_stack->u.qv.escaped = 0; + json->state_stack->u.sv.escaped = 0; if (add_char_to_token(json, unescape(c)) <= -1) return -1; } } else if (c == '\\') { - json->state_stack->u.qv.escaped = 1; + json->state_stack->u.sv.escaped = 1; } else if (c == '\"') { @@ -341,7 +371,114 @@ static int handle_quoted_value_char (hcl_json_t* json, hcl_ooci_t c) if (add_char_to_token(json, c) <= -1) return -1; } - return 1; + return ret; +} + +static int handle_character_value_char (hcl_json_t* json, hcl_ooci_t c) +{ + /* The real JSON dones't support character literal. this is HCL's own extension. */ + int ret = 1; + + if (json->state_stack->u.cv.escaped == 3) + { + if (c >= '0' && c <= '7') + { + json->state_stack->u.cv.acc = json->state_stack->u.cv.acc * 8 + c - '0'; + json->state_stack->u.cv.digit_count++; + if (json->state_stack->u.cv.digit_count >= json->state_stack->u.cv.escaped) goto add_cv_acc; + } + else + { + ret = 0; + goto add_cv_acc; + } + } + if (json->state_stack->u.cv.escaped >= 2) + { + if (c >= '0' && c <= '9') + { + json->state_stack->u.cv.acc = json->state_stack->u.cv.acc * 16 + c - '0'; + json->state_stack->u.cv.digit_count++; + if (json->state_stack->u.cv.digit_count >= json->state_stack->u.cv.escaped) goto add_cv_acc; + } + else if (c >= 'a' && c <= 'f') + { + json->state_stack->u.cv.acc = json->state_stack->u.cv.acc * 16 + c - 'a' + 10; + json->state_stack->u.cv.digit_count++; + if (json->state_stack->u.cv.digit_count >= json->state_stack->u.cv.escaped) goto add_cv_acc; + } + else if (c >= 'A' && c <= 'F') + { + json->state_stack->u.cv.acc = json->state_stack->u.cv.acc * 16 + c - 'A' + 10; + json->state_stack->u.cv.digit_count++; + if (json->state_stack->u.cv.digit_count >= json->state_stack->u.cv.escaped) goto add_cv_acc; + } + else + { + ret = 0; + add_cv_acc: + if (add_char_to_token(json, json->state_stack->u.cv.acc) <= -1) return -1; + json->state_stack->u.cv.escaped = 0; + } + } + else if (json->state_stack->u.cv.escaped == 1) + { + if (c >= '0' && c <= '8') + { + json->state_stack->u.cv.escaped = 3; + json->state_stack->u.cv.digit_count = 0; + json->state_stack->u.cv.acc = c - '0'; + } + else if (c == 'x') + { + json->state_stack->u.cv.escaped = 2; + json->state_stack->u.cv.digit_count = 0; + json->state_stack->u.cv.acc = 0; + } + else if (c == 'u') + { + json->state_stack->u.cv.escaped = 4; + json->state_stack->u.cv.digit_count = 0; + json->state_stack->u.cv.acc = 0; + } + else if (c == 'U') + { + json->state_stack->u.cv.escaped = 8; + json->state_stack->u.cv.digit_count = 0; + json->state_stack->u.cv.acc = 0; + } + else + { + json->state_stack->u.cv.escaped = 0; + if (add_char_to_token(json, unescape(c)) <= -1) return -1; + } + } + else if (c == '\\') + { + json->state_stack->u.cv.escaped = 1; + } + else if (c == '\'') + { + pop_state (json); + + if (json->tok.len < 1) + { + hcl_json_seterrbfmt (json, HCL_EINVAL, "no character in a character literal"); + return -1; + } + if (invoke_data_inst(json, HCL_JSON_INST_CHARACTER) <= -1) return -1; + } + else + { + if (add_char_to_token(json, c) <= -1) return -1; + } + + if (json->tok.len >= 1) + { + hcl_json_seterrbfmt (json, HCL_EINVAL, "too many characters in a character literal - %.*js", json->tok.len, json->tok.ptr); + return -1; + } + return ret; } static int handle_numeric_value_char (hcl_json_t* json, hcl_ooci_t c) @@ -388,7 +525,7 @@ static int handle_word_value_char (hcl_json_t* json, hcl_ooci_t c) else if (hcl_comp_oochars_bcstr(json->tok.ptr, json->tok.len, "false") == 0) inst = HCL_JSON_INST_FALSE; else { - hcl_json_seterrbfmt (json, HCL_EINVAL, "invalue word value - %.*js", json->tok.len, json->tok.ptr); + hcl_json_seterrbfmt (json, HCL_EINVAL, "invalid word value - %.*js", json->tok.len, json->tok.ptr); return -1; } @@ -459,12 +596,17 @@ static int handle_char_in_array (hcl_json_t* json, hcl_ooci_t c) if (c == '\"') { - if (push_state(json, HCL_JSON_STATE_IN_QUOTED_VALUE) <= -1) return -1; + if (push_state(json, HCL_JSON_STATE_IN_STRING_VALUE) <= -1) return -1; clear_token (json); return 1; } - /* TOOD: else if (c == '\'') HCL character - * else if (c == '#') HCL radixed number + else if (c == '\'') + { + if (push_state(json, HCL_JSON_STATE_IN_CHARACTER_VALUE) <= -1) return -1; + clear_token (json); + return 1; + } + /* TOOD: else if (c == '#') HCL radixed number */ else if (is_digitchar(c) || c == '+' || c == '-') { @@ -549,12 +691,17 @@ static int handle_char_in_dic (hcl_json_t* json, hcl_ooci_t c) if (c == '\"') { - if (push_state(json, HCL_JSON_STATE_IN_QUOTED_VALUE) <= -1) return -1; + if (push_state(json, HCL_JSON_STATE_IN_STRING_VALUE) <= -1) return -1; clear_token (json); return 1; } - /* TOOD: else if (c == '\'') HCL character - * else if (c == '#') HCL radixed number + else if (c == '\'') + { + if (push_state(json, HCL_JSON_STATE_IN_CHARACTER_VALUE) <= -1) return -1; + clear_token (json); + return 1; + } + /* TOOD: else if (c == '#') HCL radixed number */ else if (is_digitchar(c) || c == '+' || c == '-') { @@ -630,8 +777,12 @@ start_over: x = handle_word_value_char(json, c); break; - case HCL_JSON_STATE_IN_QUOTED_VALUE: - x = handle_quoted_value_char(json, c); + case HCL_JSON_STATE_IN_STRING_VALUE: + x = handle_string_value_char(json, c); + break; + + case HCL_JSON_STATE_IN_CHARACTER_VALUE: + x = handle_character_value_char(json, c); break; case HCL_JSON_STATE_IN_NUMERIC_VALUE: diff --git a/lib/main-c.c b/lib/main-c.c index bd061bc..57a8f9a 100644 --- a/lib/main-c.c +++ b/lib/main-c.c @@ -290,7 +290,10 @@ static void log_write (hcl_client_t* client, unsigned int mask, const hcl_ooch_t else if (n <= -1) { /* conversion error */ - break; + if (bcslen <= 0) break; + if (write_log(client, logfd, buf, bcslen) <= -1) break; + msgidx += ucslen; + len -= ucslen; } } #else diff --git a/lib/main-j.c b/lib/main-j.c index f9776cf..3f235a7 100644 --- a/lib/main-j.c +++ b/lib/main-j.c @@ -21,6 +21,8 @@ struct json_xtn_t hcl_bch_t buf[4096]; hcl_oow_t len; } logbuf; + + int depth; }; /* ========================================================================= */ @@ -88,7 +90,6 @@ static int write_log (hcl_json_t* json, int fd, const hcl_bch_t* ptr, hcl_oow_t { json_xtn_t* xtn; - xtn = hcl_json_getxtn(json); while (len > 0) @@ -240,7 +241,10 @@ static void log_write (hcl_json_t* json, unsigned int mask, const hcl_ooch_t* ms else if (n <= -1) { /* conversion error */ - break; + if (bcslen <= 0) break; + if (write_log(json, logfd, buf, bcslen) <= -1) break; + msgidx += ucslen; + len -= ucslen; } } #else @@ -257,18 +261,26 @@ static void log_write (hcl_json_t* json, unsigned int mask, const hcl_ooch_t* ms static int instcb (hcl_json_t* json, hcl_json_inst_t it, const hcl_oocs_t* str) { + json_xtn_t* json_xtn; + + json_xtn = hcl_json_getxtn(json); + switch (it) { case HCL_JSON_INST_START_ARRAY: + json_xtn->depth++; hcl_json_logbfmt (json, HCL_LOG_INFO | HCL_LOG_APP, "[\n"); break; case HCL_JSON_INST_END_ARRAY: + json_xtn->depth--; hcl_json_logbfmt (json, HCL_LOG_INFO | HCL_LOG_APP, "]\n"); break; case HCL_JSON_INST_START_DIC: + json_xtn->depth++; hcl_json_logbfmt (json, HCL_LOG_INFO | HCL_LOG_APP, "{\n"); break; case HCL_JSON_INST_END_DIC: + json_xtn->depth--; hcl_json_logbfmt (json, HCL_LOG_INFO | HCL_LOG_APP, "}\n"); break; @@ -276,6 +288,7 @@ static int instcb (hcl_json_t* json, hcl_json_inst_t it, const hcl_oocs_t* str) hcl_json_logbfmt (json, HCL_LOG_INFO | HCL_LOG_APP, "%.*js: ", str->len, str->ptr); break; + case HCL_JSON_INST_CHARACTER: case HCL_JSON_INST_STRING: case HCL_JSON_INST_NUMBER: case HCL_JSON_INST_TRUE: @@ -307,11 +320,15 @@ int main (int argc, char* argv[]) json_xtn = hcl_json_getxtn(json); json_xtn->logmask = HCL_LOG_ALL_LEVELS | HCL_LOG_ALL_TYPES; - p = "[ \"ab\\xab\\uC88B\\uC544\\uC6A9c\", \"kaden\", \"iron\", true, { \"null\": \"abc\", \"123\": \"AA20AA\", \"10\": -0.123 } ]"; + p = "[ \"ab\\xab\\uC88B\\uC544\\uC6A9c\", \"kaden\", \"iron\", true, { \"null\": \"a\\1bc\", \"123\": \"AA20AA\", \"10\": -0.123, \"way\": '\\uC88B' } ]"; if (hcl_json_feed(json, p, strlen(p), &xlen) <= -1) + { + hcl_json_logbfmt (json, HCL_LOG_FATAL | HCL_LOG_APP, "ERROR: unable to process - %js\n", hcl_json_geterrmsg(json)); + } + else if (json_xtn->depth != 0) { - hcl_json_logbfmt (json, HCL_LOG_FATAL | HCL_LOG_APP, "ERROR: %js\n", hcl_json_geterrmsg(json)); + hcl_json_logbfmt (json, HCL_LOG_FATAL | HCL_LOG_APP, "ERROR: incomplete input\n"); } hcl_json_close (json); diff --git a/lib/main-s.c b/lib/main-s.c index 75e2873..d95f1c2 100644 --- a/lib/main-s.c +++ b/lib/main-s.c @@ -291,7 +291,10 @@ static void log_write (hcl_server_t* server, hcl_oow_t wid, unsigned int mask, c else if (n <= -1) { /* conversion error */ - break; + if (bcslen <= 0) break; + if (write_log(server, logfd, buf, bcslen) <= -1) break; + msgidx += ucslen; + len -= ucslen; } } #else