From 7c726ee1da92804b87d58388b686aac401eab69f Mon Sep 17 00:00:00 2001 From: hyung-hwan Date: Sat, 30 May 2020 06:57:37 +0000 Subject: [PATCH] enhanced json code --- mio/bin/Makefile.am | 6 ++++ mio/bin/Makefile.in | 43 +++++++++++++++++++++++--- mio/lib/json.c | 74 +++++++++++++++++++++++++++++++++------------ mio/lib/mio-json.h | 43 +++++++++++++++++++++----- 4 files changed, 136 insertions(+), 30 deletions(-) diff --git a/mio/bin/Makefile.am b/mio/bin/Makefile.am index 01f96ae..9c852be 100644 --- a/mio/bin/Makefile.am +++ b/mio/bin/Makefile.am @@ -34,3 +34,9 @@ mio_t02_SOURCES = t02.c mio_t02_CPPFLAGS = $(CPPFLAGS_LIB_COMMON) mio_t02_LDFLAGS = $(LDFLAGS_LIB_COMMON) mio_t02_LDADD = $(LIBADD_LIB_COMMON) -lmio $(SSL_LIBS) $(SOCKET_LIBS) $(SENDFILE_LIBS) + +bin_PROGRAMS += mio-t03 +mio_t03_SOURCES = t03.c +mio_t03_CPPFLAGS = $(CPPFLAGS_LIB_COMMON) +mio_t03_LDFLAGS = $(LDFLAGS_LIB_COMMON) +mio_t03_LDADD = $(LIBADD_LIB_COMMON) -lmio $(SSL_LIBS) $(SOCKET_LIBS) $(SENDFILE_LIBS) diff --git a/mio/bin/Makefile.in b/mio/bin/Makefile.in index 6830e16..dd8c4ea 100644 --- a/mio/bin/Makefile.in +++ b/mio/bin/Makefile.in @@ -88,7 +88,8 @@ PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ -bin_PROGRAMS = mio-execd$(EXEEXT) mio-t01$(EXEEXT) mio-t02$(EXEEXT) +bin_PROGRAMS = mio-execd$(EXEEXT) mio-t01$(EXEEXT) mio-t02$(EXEEXT) \ + mio-t03$(EXEEXT) subdir = bin ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/ax_check_sign.m4 \ @@ -133,6 +134,13 @@ mio_t02_DEPENDENCIES = $(am__DEPENDENCIES_2) $(am__DEPENDENCIES_1) \ mio_t02_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(mio_t02_LDFLAGS) $(LDFLAGS) -o $@ +am_mio_t03_OBJECTS = mio_t03-t03.$(OBJEXT) +mio_t03_OBJECTS = $(am_mio_t03_OBJECTS) +mio_t03_DEPENDENCIES = $(am__DEPENDENCIES_2) $(am__DEPENDENCIES_1) \ + $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) +mio_t03_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ + $(mio_t03_LDFLAGS) $(LDFLAGS) -o $@ AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) am__v_P_0 = false @@ -149,7 +157,8 @@ DEFAULT_INCLUDES = depcomp = $(SHELL) $(top_srcdir)/ac/depcomp am__maybe_remake_depfiles = depfiles am__depfiles_remade = ./$(DEPDIR)/mio_execd-execd.Po \ - ./$(DEPDIR)/mio_t01-t01.Po ./$(DEPDIR)/mio_t02-t02.Po + ./$(DEPDIR)/mio_t01-t01.Po ./$(DEPDIR)/mio_t02-t02.Po \ + ./$(DEPDIR)/mio_t03-t03.Po am__mv = mv -f COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) @@ -169,9 +178,10 @@ AM_V_CCLD = $(am__v_CCLD_@AM_V@) am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) am__v_CCLD_0 = @echo " CCLD " $@; am__v_CCLD_1 = -SOURCES = $(mio_execd_SOURCES) $(mio_t01_SOURCES) $(mio_t02_SOURCES) +SOURCES = $(mio_execd_SOURCES) $(mio_t01_SOURCES) $(mio_t02_SOURCES) \ + $(mio_t03_SOURCES) DIST_SOURCES = $(mio_execd_SOURCES) $(mio_t01_SOURCES) \ - $(mio_t02_SOURCES) + $(mio_t02_SOURCES) $(mio_t03_SOURCES) am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ @@ -373,6 +383,10 @@ mio_t02_SOURCES = t02.c mio_t02_CPPFLAGS = $(CPPFLAGS_LIB_COMMON) mio_t02_LDFLAGS = $(LDFLAGS_LIB_COMMON) mio_t02_LDADD = $(LIBADD_LIB_COMMON) -lmio $(SSL_LIBS) $(SOCKET_LIBS) $(SENDFILE_LIBS) +mio_t03_SOURCES = t03.c +mio_t03_CPPFLAGS = $(CPPFLAGS_LIB_COMMON) +mio_t03_LDFLAGS = $(LDFLAGS_LIB_COMMON) +mio_t03_LDADD = $(LIBADD_LIB_COMMON) -lmio $(SSL_LIBS) $(SOCKET_LIBS) $(SENDFILE_LIBS) all: all-am .SUFFIXES: @@ -468,6 +482,10 @@ mio-t02$(EXEEXT): $(mio_t02_OBJECTS) $(mio_t02_DEPENDENCIES) $(EXTRA_mio_t02_DEP @rm -f mio-t02$(EXEEXT) $(AM_V_CCLD)$(mio_t02_LINK) $(mio_t02_OBJECTS) $(mio_t02_LDADD) $(LIBS) +mio-t03$(EXEEXT): $(mio_t03_OBJECTS) $(mio_t03_DEPENDENCIES) $(EXTRA_mio_t03_DEPENDENCIES) + @rm -f mio-t03$(EXEEXT) + $(AM_V_CCLD)$(mio_t03_LINK) $(mio_t03_OBJECTS) $(mio_t03_LDADD) $(LIBS) + mostlyclean-compile: -rm -f *.$(OBJEXT) @@ -477,6 +495,7 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mio_execd-execd.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mio_t01-t01.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mio_t02-t02.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mio_t03-t03.Po@am__quote@ # am--include-marker $(am__depfiles_remade): @$(MKDIR_P) $(@D) @@ -550,6 +569,20 @@ mio_t02-t02.obj: t02.c @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(mio_t02_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o mio_t02-t02.obj `if test -f 't02.c'; then $(CYGPATH_W) 't02.c'; else $(CYGPATH_W) '$(srcdir)/t02.c'; fi` +mio_t03-t03.o: t03.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(mio_t03_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT mio_t03-t03.o -MD -MP -MF $(DEPDIR)/mio_t03-t03.Tpo -c -o mio_t03-t03.o `test -f 't03.c' || echo '$(srcdir)/'`t03.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/mio_t03-t03.Tpo $(DEPDIR)/mio_t03-t03.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='t03.c' object='mio_t03-t03.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(mio_t03_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o mio_t03-t03.o `test -f 't03.c' || echo '$(srcdir)/'`t03.c + +mio_t03-t03.obj: t03.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(mio_t03_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT mio_t03-t03.obj -MD -MP -MF $(DEPDIR)/mio_t03-t03.Tpo -c -o mio_t03-t03.obj `if test -f 't03.c'; then $(CYGPATH_W) 't03.c'; else $(CYGPATH_W) '$(srcdir)/t03.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/mio_t03-t03.Tpo $(DEPDIR)/mio_t03-t03.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='t03.c' object='mio_t03-t03.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(mio_t03_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o mio_t03-t03.obj `if test -f 't03.c'; then $(CYGPATH_W) 't03.c'; else $(CYGPATH_W) '$(srcdir)/t03.c'; fi` + mostlyclean-libtool: -rm -f *.lo @@ -686,6 +719,7 @@ distclean: distclean-am -rm -f ./$(DEPDIR)/mio_execd-execd.Po -rm -f ./$(DEPDIR)/mio_t01-t01.Po -rm -f ./$(DEPDIR)/mio_t02-t02.Po + -rm -f ./$(DEPDIR)/mio_t03-t03.Po -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ distclean-tags @@ -734,6 +768,7 @@ maintainer-clean: maintainer-clean-am -rm -f ./$(DEPDIR)/mio_execd-execd.Po -rm -f ./$(DEPDIR)/mio_t01-t01.Po -rm -f ./$(DEPDIR)/mio_t02-t02.Po + -rm -f ./$(DEPDIR)/mio_t03-t03.Po -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic diff --git a/mio/lib/json.c b/mio/lib/json.c index 4d2182f..9401951 100644 --- a/mio/lib/json.c +++ b/mio/lib/json.c @@ -109,6 +109,7 @@ static int push_state (mio_json_t* json, mio_json_state_t state) if (MIO_UNLIKELY(!ss)) return -1; ss->state = state; + ss->level = json->state_stack->level; /* copy from the parent */ ss->next = json->state_stack; json->state_stack = ss; @@ -156,10 +157,7 @@ static int invoke_data_inst (mio_json_t* json, mio_json_inst_t inst) inst = MIO_JSON_INST_KEY; } -///// XXXXX -///// if (json->instcb(json, inst, &json->tok) <= -1) return -1; -///// - return 0; + return json->instcb(json, inst, json->state_stack->level, &json->tok); } static int handle_string_value_char (mio_json_t* json, mio_ooci_t c) @@ -242,6 +240,7 @@ static int handle_string_value_char (mio_json_t* json, mio_ooci_t c) } else if (c == 'u') { + /* TOOD: handle UTF-16 surrogate pair U+1D11E -> \uD834\uDD1E*/ json->state_stack->u.sv.escaped = 4; json->state_stack->u.sv.digit_count = 0; json->state_stack->u.sv.acc = 0; @@ -439,25 +438,31 @@ 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_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, MIO_NULL) <= -1) return -1; + if (json->instcb(json, MIO_JSON_INST_START_ARRAY, json->state_stack->level, MIO_NULL) <= -1) return -1; + json->state_stack->level++; return 1; } else if (c == '{') { if (push_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, MIO_NULL) <= -1) return -1; + if (json->instcb(json, MIO_JSON_INST_START_DIC, json->state_stack->level, MIO_NULL) <= -1) return -1; + json->state_stack->level++; return 1; } +#if 0 +/* this check is not needed for screening in feed_json_data() */ else if (mio_is_ooch_space(c)) { /* do nothing */ return 1; } +#endif else { mio_seterrbfmt (json->mio, MIO_EINVAL, "not starting with [ or { - %jc", (mio_ooch_t)c); @@ -469,7 +474,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, MIO_NULL) <= -1) return -1; + if (json->instcb(json, MIO_JSON_INST_END_ARRAY, json->state_stack->level - 1, MIO_NULL) <= -1) return -1; pop_state (json); return 1; } @@ -527,14 +532,16 @@ static int handle_char_in_array (mio_json_t* json, mio_ooci_t c) { if (push_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, MIO_NULL) <= -1) return -1; + if (json->instcb(json, MIO_JSON_INST_START_ARRAY, json->state_stack->level, MIO_NULL) <= -1) return -1; + json->state_stack->level++; return 1; } else if (c == '{') { if (push_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, MIO_NULL) <= -1) return -1; + if (json->instcb(json, MIO_JSON_INST_START_DIC, json->state_stack->level, MIO_NULL) <= -1) return -1; + json->state_stack->level++; return 1; } else @@ -549,7 +556,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, MIO_NULL) <= -1) return -1; + if (json->instcb(json, MIO_JSON_INST_END_DIC, json->state_stack->level - 1, MIO_NULL) <= -1) return -1; pop_state (json); return 1; } @@ -622,14 +629,16 @@ static int handle_char_in_dic (mio_json_t* json, mio_ooci_t c) { if (push_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, MIO_NULL) <= -1) return -1; + json->state_stack->level++; + if (json->instcb(json, MIO_JSON_INST_START_ARRAY, json->state_stack->level, MIO_NULL) <= -1) return -1; return 1; } else if (c == '{') { if (push_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, MIO_NULL) <= -1) return -1; + json->state_stack->level++; + if (json->instcb(json, MIO_JSON_INST_START_DIC, json->state_stack->level, MIO_NULL) <= -1) return -1; return 1; } else @@ -704,10 +713,11 @@ start_over: /* ========================================================================= */ -static int feed_json_data (mio_json_t* json, const mio_bch_t* data, mio_oow_t len, mio_oow_t* xlen) +static int feed_json_data (mio_json_t* json, const mio_bch_t* data, mio_oow_t len, mio_oow_t* xlen, int stop_if_ever_completed) { const mio_bch_t* ptr; const mio_bch_t* end; + int ever_completed = 0; ptr = data; end = ptr + len; @@ -715,12 +725,14 @@ static int feed_json_data (mio_json_t* json, const mio_bch_t* data, mio_oow_t le while (ptr < end) { mio_ooci_t c; + const mio_bch_t* optr; #if defined(MIO_OOCH_IS_UCH) mio_ooch_t uc; mio_oow_t bcslen; mio_oow_t n; + optr = ptr; bcslen = end - ptr; n = json->mio->_cmgr->bctouc(ptr, bcslen, &uc); if (n == 0) @@ -739,15 +751,24 @@ static int feed_json_data (mio_json_t* json, const mio_bch_t* data, mio_oow_t le ptr += n; c = uc; #else + optr = ptr; c = *ptr++; #endif + if (json->state_stack->state == MIO_JSON_STATE_START && mio_is_ooch_space(c)) continue; /* skip white space */ + if (stop_if_ever_completed && ever_completed) + { + *xlen = optr - data; + return 2; + } + /* handle a signle character */ if (handle_char(json, c) <= -1) goto oops; + if (json->state_stack->state == MIO_JSON_STATE_START) ever_completed = 1; } *xlen = ptr - data; - return 1; + return (stop_if_ever_completed && ever_completed)? 2: 1; oops: /* TODO: compute the number of processed bytes so far and return it via a parameter??? */ @@ -785,12 +806,17 @@ void mio_json_close (mio_json_t* json) mio_freemem (json->mio, json); } +static int do_nothing_on_inst (mio_json_t* json, mio_json_inst_t inst, mio_oow_t level, const mio_oocs_t* str) +{ + return 0; +} int mio_json_init (mio_json_t* json, mio_t* mio) { MIO_MEMSET (json, 0, MIO_SIZEOF(*json)); json->mio = mio; + json->instcb = do_nothing_on_inst; json->state_top.state = MIO_JSON_STATE_START; json->state_top.next = MIO_NULL; json->state_stack = &json->state_top; @@ -809,20 +835,24 @@ void mio_json_fini (mio_json_t* json) } /* ========================================================================= */ +void mio_json_setinstcb (mio_json_t* json, mio_json_instcb_t instcb) +{ + json->instcb = instcb; +} + mio_json_state_t mio_json_getstate (mio_json_t* json) { return json->state_stack->state; } -void mio_json_reset (mio_json_t* json) +void mio_json_resetstates (mio_json_t* json) { - /* TODO: reset XXXXXXXXXXXXXXXXXXXXXXXXXXXxxxxx */ pop_all_states (json); MIO_ASSERT (json->mio, json->state_stack == &json->state_top); json->state_stack->state = MIO_JSON_STATE_START; } -int mio_json_feed (mio_json_t* json, const void* ptr, mio_oow_t len, mio_oow_t* xlen) +int mio_json_feed (mio_json_t* json, const void* ptr, mio_oow_t len, mio_oow_t* rem, int stop_if_ever_completed) { int x; mio_oow_t total, ylen; @@ -832,13 +862,19 @@ int mio_json_feed (mio_json_t* json, const void* ptr, mio_oow_t len, mio_oow_t* total = 0; while (total < len) { - x = feed_json_data(json, &buf[total], len - total, &ylen); + x = feed_json_data(json, &buf[total], len - total, &ylen, stop_if_ever_completed); if (x <= -1) return -1; total += ylen; if (x == 0) break; /* incomplete sequence encountered */ + + if (stop_if_ever_completed && x >= 2) + { + *rem = len - total; + return 1; + } } - *xlen = total; + *rem = len - total; return 0; } diff --git a/mio/lib/mio-json.h b/mio/lib/mio-json.h index c930bc2..4a117c0 100644 --- a/mio/lib/mio-json.h +++ b/mio/lib/mio-json.h @@ -71,6 +71,7 @@ typedef enum mio_json_inst_t mio_json_inst_t; typedef int (*mio_json_instcb_t) ( mio_json_t* json, mio_json_inst_t inst, + mio_oow_t level, const mio_oocs_t* str ); @@ -79,6 +80,7 @@ typedef struct mio_json_state_node_t mio_json_state_node_t; struct mio_json_state_node_t { mio_json_state_t state; + mio_oow_t level; union { struct @@ -151,19 +153,46 @@ MIO_EXPORT void mio_json_fini ( mio_json_t* json ); -MIO_EXPORT void mio_json_reset ( - mio_json_t* json +#if defined(MIO_HAVE_INLINE) +static MIO_INLINE mio_t* mio_json_getmio (mio_json_t* json) { return json->mio; } +#else +# define mio_json_getmio(json) (((mio_json_t*)(json))->mio) +#endif + +MIO_EXPORT void mio_json_setinstcb ( + mio_json_t* json, + mio_json_instcb_t instcb ); + +MIO_EXPORT mio_json_state_t mio_json_getstate ( + mio_json_t* json +); + +MIO_EXPORT void mio_json_resetstates ( + mio_json_t* json +); + +/** + * The mio_json_feed() function processes the raw data. + * + * If stop_if_ever_complted is 0, it returns 0 on success. If the value pointed to by + * rem is greater 0 after the call, processing is not complete and more feeding is + * required. Incomplete feeding may be caused by incomplete byte sequences or incomplete + * json object. + * + * If stop_if_ever_completed is non-zero, it returns 0 upon incomplet byte sequence or + * incomplete json object. It returns 1 if it sees the first complete json object. It stores + * the size of remaning raw data in the memory pointed to by rem. + * + * The function returns -1 upon failure. + */ MIO_EXPORT int mio_json_feed ( mio_json_t* json, const void* ptr, mio_oow_t len, - mio_oow_t* xlen -); - -MIO_EXPORT mio_json_state_t mio_json_getstate ( - mio_json_t* json + mio_oow_t* rem, + int stop_if_ever_completed );