From 0b539bbba2229c6b64b57f75a4e85fb20beee4b7 Mon Sep 17 00:00:00 2001 From: YuQing <384681@qq.com> Date: Sat, 4 Jun 2022 12:41:07 +0800 Subject: [PATCH] json decode supports memory pool for persistency --- HISTORY | 2 +- src/json_parser.c | 50 ++++++++++++++++++++++++++++-------- src/json_parser.h | 41 ++++++++++++++++++++++++----- src/tests/test_json_parser.c | 46 ++++++++++++++++++++++++--------- 4 files changed, 109 insertions(+), 30 deletions(-) diff --git a/HISTORY b/HISTORY index 9b2d04c..e4e837c 100644 --- a/HISTORY +++ b/HISTORY @@ -1,5 +1,5 @@ -Version 1.58 2022-05-29 +Version 1.58 2022-06-04 * add function conn_pool_connect_server_ex1 to support service name * add function conn_pool_get_connection_ex to support service name * add function iniGetCharValueEx diff --git a/src/json_parser.c b/src/json_parser.c index f5369eb..c123fe5 100644 --- a/src/json_parser.c +++ b/src/json_parser.c @@ -126,7 +126,7 @@ static int next_json_element(fc_json_context_t *context) int unicode; int i; - dest = context->element.str; + dest = context->decode.element.str; quote_ch = *context->p; if (quote_ch == '\"' || quote_ch == '\'') { context->p++; @@ -224,7 +224,7 @@ static int next_json_element(fc_json_context_t *context) } *dest = '\0'; - context->element.len = dest - context->element.str; + context->decode.element.len = dest - context->decode.element.str; return 0; } @@ -288,8 +288,8 @@ static int prepare_json_parse(fc_json_context_t *context, } } - context->element.str = context->output.buff; - context->element.len = 0; + context->decode.element.str = context->output.buff; + context->decode.element.len = 0; context->str = input->str; context->p = input->str + 1; context->end = input->str + input->len - 1; @@ -392,6 +392,18 @@ int fc_encode_json_map_ex(fc_json_context_t *context, return 0; } +#define JSON_DECODE_COPY_STRING(ctx, input, dest, src) \ + do { \ + if ((context->error_no=fast_mpool_alloc_string_ex2( \ + &ctx->decode.mpool, dest, src)) != 0) \ + { \ + set_parse_error(input->str, ctx->p, EXPECT_STR_LEN, \ + "out of memory", &ctx->error_info, ctx->error_size); \ + return NULL; \ + } \ + } while (0) + + const fc_json_array_t *fc_decode_json_array(fc_json_context_t *context, const string_t *input) { @@ -445,8 +457,14 @@ const fc_json_array_t *fc_decode_json_array(fc_json_context_t return NULL; } - context->jarray.elements[context->jarray.count++] = context->element; - context->element.str += context->element.len + 1; + if (context->decode.use_mpool) { + JSON_DECODE_COPY_STRING(context, input, context->jarray.elements + + context->jarray.count++, &context->decode.element); + } else { + context->jarray.elements[context->jarray.count++] = + context->decode.element; + } + context->decode.element.str += context->decode.element.len + 1; } return &context->jarray; @@ -496,8 +514,8 @@ const fc_json_map_t *fc_decode_json_map(fc_json_context_t } context->p++; //skip colon - kv_pair.key = context->element; - context->element.str += context->element.len + 1; + kv_pair.key = context->decode.element; + context->decode.element.str += context->decode.element.len + 1; while (context->p < context->end && JSON_SPACE(*context->p)) { context->p++; @@ -520,8 +538,8 @@ const fc_json_map_t *fc_decode_json_map(fc_json_context_t } } - kv_pair.value = context->element; - context->element.str += context->element.len + 1; + kv_pair.value = context->decode.element; + context->decode.element.str += context->decode.element.len + 1; if ((context->error_no=check_alloc_array(context, (fc_common_array_t *) @@ -529,7 +547,17 @@ const fc_json_map_t *fc_decode_json_map(fc_json_context_t { return NULL; } - context->jmap.elements[context->jmap.count++] = kv_pair; + + if (context->decode.use_mpool) { + key_value_pair_t *dest; + dest = context->jmap.elements + context->jmap.count++; + JSON_DECODE_COPY_STRING(context, input, + &dest->key, &kv_pair.key); + JSON_DECODE_COPY_STRING(context, input, + &dest->value, &kv_pair.value); + } else { + context->jmap.elements[context->jmap.count++] = kv_pair; + } } return &context->jmap; diff --git a/src/json_parser.h b/src/json_parser.h index 9290bd6..64ab7e4 100644 --- a/src/json_parser.h +++ b/src/json_parser.h @@ -24,6 +24,7 @@ #include #include "common_define.h" #include "shared_func.h" +#include "fast_mpool.h" #define FC_JSON_TYPE_STRING 1 #define FC_JSON_TYPE_ARRAY 2 @@ -44,8 +45,12 @@ DEFINE_ARRAY_STRUCT(string_t, fc_json_array_t); DEFINE_ARRAY_STRUCT(key_value_pair_t, fc_json_map_t); typedef struct { - BufferInfo output; //for json encode - string_t element; //string allocator use output buffer + BufferInfo output; //for json encode/decode + struct { + struct fast_mpool_man mpool; + string_t element; //string allocator use output buffer + bool use_mpool; + } decode; int init_buff_size; int error_no; int error_size; @@ -119,11 +124,15 @@ extern "C" { } static inline int fc_init_json_context_ex(fc_json_context_t *ctx, - const int init_buff_size, char *error_info, const int error_size) + const bool decode_use_mpool, const int alloc_size_once, + const int init_buff_size, char *error_info, + const int error_size) { + const int discard_size = 0; + ctx->output.buff = NULL; ctx->output.alloc_size = ctx->output.length = 0; - FC_SET_STRING_NULL(ctx->element); + FC_SET_STRING_NULL(ctx->decode.element); if (init_buff_size > 0) { ctx->init_buff_size = init_buff_size; } else { @@ -134,13 +143,30 @@ extern "C" { ctx->error_no = 0; fc_set_json_error_buffer(ctx, error_info, error_size); - return 0; + ctx->decode.use_mpool = decode_use_mpool; + if (decode_use_mpool) { + return fast_mpool_init(&ctx->decode.mpool, + alloc_size_once, discard_size); + } else { + return 0; + } } static inline int fc_init_json_context(fc_json_context_t *ctx) { + const bool decode_use_mpool = false; + const int alloc_size_once = 0; const int init_buff_size = 0; - return fc_init_json_context_ex(ctx, init_buff_size, NULL, 0); + + return fc_init_json_context_ex(ctx, decode_use_mpool, + alloc_size_once, init_buff_size, NULL, 0); + } + + static inline void fc_reset_json_context(fc_json_context_t *ctx) + { + if (ctx->decode.use_mpool) { + fast_mpool_reset(&ctx->decode.mpool); + } } static inline void fc_destroy_json_context(fc_json_context_t *ctx) @@ -148,6 +174,9 @@ extern "C" { fc_free_buffer(&ctx->output); fc_free_json_array(&ctx->jarray); fc_free_json_map(&ctx->jmap); + if (ctx->decode.use_mpool) { + fast_mpool_destroy(&ctx->decode.mpool); + } } static inline int fc_json_parser_get_error_no(fc_json_context_t *ctx) diff --git a/src/tests/test_json_parser.c b/src/tests/test_json_parser.c index cca7fe1..4c79bb6 100644 --- a/src/tests/test_json_parser.c +++ b/src/tests/test_json_parser.c @@ -28,12 +28,16 @@ int main(int argc, char *argv[]) { + const bool decode_use_mpool = false; + const int alloc_size_once = 1024; + const int init_buff_size = 1024; int result; int json_type; fc_json_context_t json_ctx; char error_info[256]; string_t input; - BufferInfo output; + BufferInfo buffer; + const BufferInfo *output; if (argc < 2) { fprintf(stderr, "Usage: %s \n", @@ -43,12 +47,13 @@ int main(int argc, char *argv[]) log_init(); - if ((result=fc_init_json_context_ex(&json_ctx, 1024, - error_info, sizeof(error_info))) != 0) + if ((result=fc_init_json_context_ex(&json_ctx, decode_use_mpool, + alloc_size_once, init_buff_size, error_info, + sizeof(error_info))) != 0) { return result; } - memset(&output, 0, sizeof(output)); + memset(&buffer, 0, sizeof(buffer)); input.str = argv[1]; input.len = strlen(input.str); @@ -61,14 +66,23 @@ int main(int argc, char *argv[]) return fc_json_parser_get_error_no(&json_ctx); } - if ((result=fc_encode_json_array_ex(&json_ctx, array->elements, - array->count, &output)) != 0) - { + if (decode_use_mpool) { + output = fc_encode_json_array(&json_ctx, + array->elements, array->count); + result = fc_json_parser_get_error_no(&json_ctx); + } else { + output = &buffer; + result = fc_encode_json_array_ex(&json_ctx, + array->elements, array->count, &buffer); + } + + if (result != 0) { fprintf(stderr, "encode json array fail, %s\n", error_info); return result; } - printf("%.*s\n", output.length, output.buff); + printf("%.*s\n", output->length, output->buff); + fc_free_buffer(&buffer); } else if (json_type == FC_JSON_TYPE_MAP) { const fc_json_map_t *map; @@ -77,14 +91,22 @@ int main(int argc, char *argv[]) return fc_json_parser_get_error_no(&json_ctx); } - if ((result=fc_encode_json_map_ex(&json_ctx, map->elements, - map->count, &output)) != 0) - { + if (decode_use_mpool) { + output = fc_encode_json_map(&json_ctx, + map->elements, map->count); + result = fc_json_parser_get_error_no(&json_ctx); + } else { + output = &buffer; + result = fc_encode_json_map_ex(&json_ctx, + map->elements, map->count, &buffer); + } + if (result != 0) { fprintf(stderr, "encode json map fail, %s\n", error_info); return result; } - printf("%.*s\n", output.length, output.buff); + printf("%.*s\n", output->length, output->buff); + fc_free_buffer(&buffer); } else { fprintf(stderr, "string\n"); }