From 08613876c0d2da11cfd92032492f0b841f7b912c Mon Sep 17 00:00:00 2001 From: Fanda Vacek Date: Fri, 6 Jan 2023 19:28:58 +0100 Subject: [PATCH] Add support for NULL chainpack serialization buffer #202 To measure buffer size needed to pack use ccpcp_pack_context_dry_run_init() Packed size can be found in ccpcp_pack_context::bytes_written field For example see: test_dry_run_int() in test_ccpcp.c --- libshvchainpack/c/ccpcp.c | 129 +++++++++-------------- libshvchainpack/c/ccpcp.h | 12 ++- libshvchainpack/c/ccpcp_convert.c | 8 +- libshvchainpack/c/ccpon.c | 50 ++------- libshvchainpack/c/tests/test_ccpcp.c | 152 +++++++++++++++++++-------- 5 files changed, 183 insertions(+), 168 deletions(-) diff --git a/libshvchainpack/c/ccpcp.c b/libshvchainpack/c/ccpcp.c index e9efbb34e..ffb7198cf 100644 --- a/libshvchainpack/c/ccpcp.c +++ b/libshvchainpack/c/ccpcp.c @@ -17,7 +17,38 @@ const char *ccpcp_error_string(int err_no) } } -size_t ccpcp_pack_make_space(ccpcp_pack_context* pack_context, size_t size_hint) +//=========================== PACK ============================ +void ccpcp_pack_context_init (ccpcp_pack_context* pack_context, void *data, size_t length, ccpcp_pack_overflow_handler poh) +{ + pack_context->start = pack_context->current = (char*)data; + pack_context->end = pack_context->start + length; + pack_context->err_no = 0; + pack_context->handle_pack_overflow = poh; + pack_context->err_no = CCPCP_RC_OK; + pack_context->cpon_options.indent = NULL; + pack_context->cpon_options.json_output = 0; + pack_context->nest_count = 0; + pack_context->custom_context = NULL; + pack_context->bytes_written = 0; +} + +void ccpcp_pack_context_dry_run_init(ccpcp_pack_context *pack_context) +{ + ccpcp_pack_context_init(pack_context, NULL, 0, NULL); +} + +static bool is_dry_run(ccpcp_pack_context* pack_context) +{ + return pack_context->handle_pack_overflow == NULL + && pack_context->start == NULL + && pack_context->end == NULL + && pack_context->current == NULL; +} + +// try to make size_hint bytes space in pack_context +// returns number of bytes available in pack_context buffer, can be < size_hint, but always > 0 +// returns 0 if fails +static size_t ccpcp_pack_make_space(ccpcp_pack_context* pack_context, size_t size_hint) { if(pack_context->err_no != CCPCP_RC_OK) return 0; @@ -37,7 +68,8 @@ size_t ccpcp_pack_make_space(ccpcp_pack_context* pack_context, size_t size_hint) return free_space; } -char* ccpcp_pack_reserve_space(ccpcp_pack_context* pack_context, size_t more) +//alocate more bytes, move current after allocated bytec +static char* ccpcp_pack_reserve_space(ccpcp_pack_context* pack_context, size_t more) { if(pack_context->err_no != CCPCP_RC_OK) return NULL; @@ -51,22 +83,31 @@ char* ccpcp_pack_reserve_space(ccpcp_pack_context* pack_context, size_t more) return p; } -void ccpcp_pack_copy_byte(ccpcp_pack_context *pack_context, uint8_t b) +size_t ccpcp_pack_copy_byte(ccpcp_pack_context *pack_context, uint8_t b) { + pack_context->bytes_written += 1; + if(is_dry_run(pack_context)) + return 1; + char *p = ccpcp_pack_reserve_space(pack_context, 1); if(!p) - return; + return 0; *p = (char)b; + return 1; } -void ccpcp_pack_copy_bytes(ccpcp_pack_context *pack_context, const void *str, size_t len) +size_t ccpcp_pack_copy_bytes(ccpcp_pack_context *pack_context, const void *str, size_t len) { + pack_context->bytes_written += len; + if(is_dry_run(pack_context)) + return len; + size_t copied = 0; while (pack_context->err_no == CCPCP_RC_OK && copied < len) { size_t buff_size = ccpcp_pack_make_space(pack_context, len); if(buff_size == 0) { pack_context->err_no = CCPCP_RC_BUFFER_OVERFLOW; - return; + return 0; } size_t rest = len - copied; if(rest > buff_size) @@ -75,6 +116,7 @@ void ccpcp_pack_copy_bytes(ccpcp_pack_context *pack_context, const void *str, si copied += rest; pack_context->current += rest; } + return copied; } //================================ UNPACK ================================ @@ -237,80 +279,6 @@ const char *ccpcp_unpack_peek_byte(ccpcp_unpack_context *unpack_context) return p; } -/* -bool ccpcp_item_is_string_unfinished(ccpcp_unpack_context *unpack_context) -{ - bool is_string_concat = false; - ccpcp_container_state *parent_state = ccpcp_unpack_context_parent_container_state(unpack_context); - if(parent_state != NULL) { - if(unpack_context->item.type == CCPCP_ITEM_STRING) { - ccpcp_string *it = &(unpack_context->item.as.String); - if(it->chunk_cnt > 1) { - // multichunk string - // this can happen, when parsed string is greater than unpack_context buffer - // or escape sequence is encountered - // concatenate it with previous chunk - is_string_concat = true; - } - } - } - return is_string_concat; -} - -bool ccpcp_item_is_list_item(ccpcp_unpack_context *unpack_context) -{ - ccpcp_container_state *parent_state = ccpcp_unpack_context_parent_container_state(unpack_context); - if(parent_state != NULL) { - bool is_string_concat = 0; - if(unpack_context->item.type == CCPCP_ITEM_STRING) { - ccpcp_string *it = &(unpack_context->item.as.String); - if(it->chunk_cnt > 1) { - // multichunk string - // this can happen, when parsed string is greater than unpack_context buffer - // or escape sequence is encountered - // concatenate it with previous chunk - is_string_concat = 1; - } - } - if(!is_string_concat && unpack_context->item.type != CCPCP_ITEM_CONTAINER_END) { - switch(parent_state->container_type) { - case CCPCP_ITEM_LIST: - //case CCPCP_ITEM_ARRAY: - if(!meta_just_closed) - ccpon_pack_field_delim(out_ctx, parent_state->item_count == 1); - break; - case CCPCP_ITEM_MAP: - case CCPCP_ITEM_IMAP: - case CCPCP_ITEM_META: { - bool is_key = (parent_state->item_count % 2); - if(is_key) { - if(!meta_just_closed) - ccpon_pack_field_delim(out_ctx, parent_state->item_count == 1); - } - else { - // delimite value - ccpon_pack_key_val_delim(out_ctx); - } - break; - } - default: - break; - } - } - } -} - -bool ccpcp_item_is_map_key(ccpcp_unpack_context *unpack_context) -{ - -} - -bool ccpcp_item_is_map_val(ccpcp_unpack_context *unpack_context) -{ - -} -*/ - double ccpcp_exponentional_to_double(int64_t const mantisa, const int exponent, const int base) { double d = (double)mantisa; @@ -425,3 +393,4 @@ size_t ccpcp_decimal_to_string(char *buff, size_t buff_len, int64_t mantisa, int return mantisa_str_len; } + diff --git a/libshvchainpack/c/ccpcp.h b/libshvchainpack/c/ccpcp.h index a909742a3..60e9caa64 100644 --- a/libshvchainpack/c/ccpcp.h +++ b/libshvchainpack/c/ccpcp.h @@ -49,17 +49,19 @@ typedef struct ccpcp_pack_context { ccpcp_pack_overflow_handler handle_pack_overflow; void *custom_context; ccpcp_cpon_pack_options cpon_options; + size_t bytes_written; } ccpcp_pack_context; -void ccpcp_pack_context_init(ccpcp_pack_context* pack_context, void *data, size_t length, ccpcp_pack_overflow_handler hpo); +void ccpcp_pack_context_init(ccpcp_pack_context* pack_context, void *data, size_t length, ccpcp_pack_overflow_handler poh); +void ccpcp_pack_context_dry_run_init(ccpcp_pack_context* pack_context); // try to make size_hint bytes space in pack_context // returns number of bytes available in pack_context buffer, can be < size_hint, but always > 0 // returns 0 if fails -size_t ccpcp_pack_make_space(ccpcp_pack_context* pack_context, size_t size_hint); -char *ccpcp_pack_reserve_space(ccpcp_pack_context* pack_context, size_t more); -void ccpcp_pack_copy_byte (ccpcp_pack_context* pack_context, uint8_t b); -void ccpcp_pack_copy_bytes (ccpcp_pack_context* pack_context, const void *str, size_t len); +//size_t ccpcp_pack_make_space(ccpcp_pack_context* pack_context, size_t size_hint); +//char *ccpcp_pack_reserve_space(ccpcp_pack_context* pack_context, size_t more); +size_t ccpcp_pack_copy_byte(ccpcp_pack_context* pack_context, uint8_t b); +size_t ccpcp_pack_copy_bytes(ccpcp_pack_context* pack_context, const void *str, size_t len); //void ccpcp_pack_copy_bytes_cpon_string_escaped (ccpcp_pack_context* pack_context, const void *str, size_t len); //=========================== UNPACK ============================ diff --git a/libshvchainpack/c/ccpcp_convert.c b/libshvchainpack/c/ccpcp_convert.c index 312b74897..949f2c9d8 100644 --- a/libshvchainpack/c/ccpcp_convert.c +++ b/libshvchainpack/c/ccpcp_convert.c @@ -1,8 +1,15 @@ #include "cchainpack.h" #include "ccpon.h" +#include + void ccpcp_convert(ccpcp_unpack_context* in_ctx, ccpcp_pack_format in_format, ccpcp_pack_context* out_ctx, ccpcp_pack_format out_format) { + if(!in_ctx->container_stack) { + // ccpcp_convert() cannot worj without input context container state set + in_ctx->err_no = CCPCP_RC_LOGICAL_ERROR; + return; + } bool o_cpon_input = (in_format == CCPCP_Cpon); bool o_chainpack_output = (out_format == CCPCP_ChainPack); //int prev_item = CCPCP_ITEM_INVALID; @@ -240,7 +247,6 @@ void ccpcp_convert(ccpcp_unpack_context* in_ctx, ccpcp_pack_format in_format, cc break; } } - //prev_item = in_ctx->item.type; { ccpcp_container_state *top_state = ccpcp_unpack_context_top_container_state(in_ctx); // take just one object from stream diff --git a/libshvchainpack/c/ccpon.c b/libshvchainpack/c/ccpon.c index d8569a5b8..d300167d8 100644 --- a/libshvchainpack/c/ccpon.c +++ b/libshvchainpack/c/ccpon.c @@ -338,19 +338,6 @@ static void *memcpy(void *dst, const void *src, size_t n) #endif //============================ P A C K ================================= -void ccpcp_pack_context_init (ccpcp_pack_context* pack_context, void *data, size_t length, ccpcp_pack_overflow_handler hpo) -{ - pack_context->start = pack_context->current = (char*)data; - pack_context->end = pack_context->start + length; - pack_context->err_no = 0; - pack_context->handle_pack_overflow = hpo; - pack_context->err_no = CCPCP_RC_OK; - pack_context->cpon_options.indent = NULL; - pack_context->cpon_options.json_output = 0; - pack_context->nest_count = 0; - pack_context->custom_context = NULL; -} - void ccpon_pack_copy_str(ccpcp_pack_context *pack_context, const char *str) { size_t len = strlen(str); @@ -449,10 +436,7 @@ void ccpon_pack_double(ccpcp_pack_context* pack_context, double d) pack_context->err_no = CCPCP_RC_LOGICAL_ERROR; return; } - char *p = ccpcp_pack_reserve_space(pack_context, n); - if(p) { - memcpy(p, str, n); - } + ccpcp_pack_copy_bytes(pack_context, str, n); } void ccpon_pack_date_time(ccpcp_pack_context *pack_context, int64_t epoch_msecs, int min_from_utc) @@ -566,10 +550,8 @@ void ccpon_pack_list_begin(ccpcp_pack_context *pack_context) if (pack_context->err_no) return; - char *p = ccpcp_pack_reserve_space(pack_context, 1); - if(p) - *p = CCPON_C_LIST_BEGIN; - start_block(pack_context); + if(ccpcp_pack_copy_byte(pack_context, CCPON_C_LIST_BEGIN) > 0) + start_block(pack_context); } void ccpon_pack_list_end(ccpcp_pack_context *pack_context, bool is_oneliner) @@ -578,9 +560,7 @@ void ccpon_pack_list_end(ccpcp_pack_context *pack_context, bool is_oneliner) return; end_block(pack_context, is_oneliner); - char *p = ccpcp_pack_reserve_space(pack_context, 1); - if(p) - *p = CCPON_C_LIST_END; + ccpcp_pack_copy_byte(pack_context, CCPON_C_LIST_END); } void ccpon_pack_map_begin(ccpcp_pack_context *pack_context) @@ -588,10 +568,8 @@ void ccpon_pack_map_begin(ccpcp_pack_context *pack_context) if (pack_context->err_no) return; - char *p = ccpcp_pack_reserve_space(pack_context, 1); - if(p) - *p = CCPON_C_MAP_BEGIN; - start_block(pack_context); + if(ccpcp_pack_copy_byte(pack_context, CCPON_C_MAP_BEGIN)) + start_block(pack_context); } void ccpon_pack_map_end(ccpcp_pack_context *pack_context, bool is_oneliner) @@ -600,10 +578,7 @@ void ccpon_pack_map_end(ccpcp_pack_context *pack_context, bool is_oneliner) return; end_block(pack_context, is_oneliner); - char *p = ccpcp_pack_reserve_space(pack_context, 1); - if(p) { - *p = CCPON_C_MAP_END; - } + ccpcp_pack_copy_byte(pack_context, CCPON_C_MAP_END); } void ccpon_pack_imap_begin(ccpcp_pack_context* pack_context) @@ -625,10 +600,8 @@ void ccpon_pack_meta_begin(ccpcp_pack_context *pack_context) if (pack_context->err_no) return; - char *p = ccpcp_pack_reserve_space(pack_context, 1); - if(p) - *p = CCPON_C_META_BEGIN; - start_block(pack_context); + if(ccpcp_pack_copy_byte(pack_context, CCPON_C_META_BEGIN) > 0) + start_block(pack_context); } void ccpon_pack_meta_end(ccpcp_pack_context *pack_context, bool is_oneliner) @@ -637,10 +610,7 @@ void ccpon_pack_meta_end(ccpcp_pack_context *pack_context, bool is_oneliner) return; end_block(pack_context, is_oneliner); - char *p = ccpcp_pack_reserve_space(pack_context, 1); - if(p) { - *p = CCPON_C_META_END; - } + ccpcp_pack_copy_byte(pack_context, CCPON_C_META_END); } static char* copy_data_escaped(ccpcp_pack_context* pack_context, const void* str, size_t len) diff --git a/libshvchainpack/c/tests/test_ccpcp.c b/libshvchainpack/c/tests/test_ccpcp.c index 902c128e7..76840b036 100644 --- a/libshvchainpack/c/tests/test_ccpcp.c +++ b/libshvchainpack/c/tests/test_ccpcp.c @@ -12,7 +12,7 @@ #include #include -static bool o_silent = true; +static bool o_verbose = false; static void binary_dump(const char *buff, ssize_t len) { @@ -98,7 +98,7 @@ void test_pack_decimal(int mantisa, int exponent, const char *res) ccpcp_pack_context_init(&ctx, buff, BUFFLEN, NULL); ccpon_pack_decimal(&ctx, mantisa, exponent); *ctx.current = '\0'; - if(!o_silent) { + if(o_verbose) { printf("pack decimal mantisa %d, exponent %d have: '%s' expected: '%s'\n", mantisa, exponent, buff, res); } if(strcmp(buff, res)) { @@ -229,16 +229,15 @@ int64_t datetime_str_to_msec_utc(const char *str) assert(false); } ccpcp_date_time *dt = &ctx.item.as.DateTime; - printf("datetime str: '%s' have: %ld msec + %d utc min offset\n" , str , dt->msecs_since_epoch, dt->minutes_from_utc); + if(o_verbose) + printf("datetime str: '%s' have: %ld msec + %d utc min offset\n" , str , dt->msecs_since_epoch, dt->minutes_from_utc); return dt->msecs_since_epoch; } static void test_cpon_helper(const char *cpon, const char *ref_cpon, bool compare_chainpack, bool compare_cpon) { - - - if(!o_silent) - printf("-------------------------------------------------\n"); + if(o_verbose) + printf("---------------- test cpon ---------------------\n"); static const size_t STATE_CNT = 100; ccpcp_container_state states[STATE_CNT]; @@ -251,7 +250,7 @@ static void test_cpon_helper(const char *cpon, const char *ref_cpon, bool compar char out_buff1[1024]; ccpcp_pack_context out_ctx; - if(!o_silent) + if(o_verbose) printf("Cpon: %s\n", in_buff); ccpcp_container_stack_init(&stack, states, STATE_CNT, NULL); @@ -262,7 +261,7 @@ static void test_cpon_helper(const char *cpon, const char *ref_cpon, bool compar // printf("BREAK\n"); ccpcp_convert(&in_ctx, CCPCP_Cpon, &out_ctx, CCPCP_Cpon); *out_ctx.current = 0; - if(!o_silent) + if(o_verbose) printf("1. Cpon->Cpon: %s\n", out_ctx.start); //printf("DDD in err: %d out err: %d\n", in_ctx.err_no, out_ctx.err_no); assert(in_ctx.err_no == CCPCP_RC_OK && out_ctx.err_no == CCPCP_RC_OK); @@ -273,16 +272,11 @@ static void test_cpon_helper(const char *cpon, const char *ref_cpon, bool compar ccpcp_pack_context_init(&out_ctx, out_buff2, sizeof (out_buff2), NULL); ccpcp_convert(&in_ctx, CCPCP_Cpon, &out_ctx, CCPCP_ChainPack); - if(o_silent) { + if(o_verbose) { printf("%s -> len: %ld data: ", cpon, out_ctx.current - out_ctx.start); binary_dump(out_ctx.start, out_ctx.current - out_ctx.start); printf("\n"); } - else { - printf("2. Cpon->CPack len: %ld data: ", out_ctx.current - out_ctx.start); - binary_dump(out_ctx.start, out_ctx.current - out_ctx.start); - printf("\n"); - } assert(in_ctx.err_no == CCPCP_RC_OK && out_ctx.err_no == CCPCP_RC_OK); ccpcp_container_stack_init(&stack, states, STATE_CNT, NULL); @@ -290,7 +284,7 @@ static void test_cpon_helper(const char *cpon, const char *ref_cpon, bool compar ccpcp_pack_context_init(&out_ctx, out_buff1, sizeof (out_buff1), NULL); ccpcp_convert(&in_ctx, CCPCP_ChainPack, &out_ctx, CCPCP_ChainPack); - if(!o_silent) { + if(o_verbose) { printf("3. CPack->CPack len: %ld data: ", out_ctx.current - out_ctx.start); binary_dump(out_ctx.start, out_ctx.current - out_ctx.start); printf("\n"); @@ -308,7 +302,7 @@ static void test_cpon_helper(const char *cpon, const char *ref_cpon, bool compar ccpcp_convert(&in_ctx, CCPCP_ChainPack, &out_ctx, CCPCP_Cpon); *out_ctx.current = 0; - if(!o_silent) + if(o_verbose) printf("4. CPack->Cpon: %s\n", out_ctx.start); assert(in_ctx.err_no == CCPCP_RC_OK && out_ctx.err_no == CCPCP_RC_OK); @@ -333,46 +327,107 @@ static void test_cpon2(const char *cpon, const char *ref_cpon) { test_cpon_helper(cpon, ref_cpon, false, true); } -/* -static void test_cpon3(const char *cpon, const char *ref_cpon) + +static void test_dry_run_cpon(const char *cpon) { - test_cpon_helper(cpon, ref_cpon, true, false); + if(o_verbose) + printf("---------------- test dry run cpon ---------------------\n"); + + size_t dry_run_size; + { + static const size_t STATE_CNT = 100; + ccpcp_container_state states[STATE_CNT]; + ccpcp_container_stack stack; + ccpcp_container_stack_init(&stack, states, STATE_CNT, NULL); + + const char *in_buff = cpon; + ccpcp_unpack_context in_ctx; + ccpcp_pack_context out_ctx; + ccpcp_unpack_context_init(&in_ctx, in_buff, strlen(in_buff), NULL, &stack); + ccpcp_pack_context_dry_run_init(&out_ctx); + ccpcp_convert(&in_ctx, CCPCP_Cpon, &out_ctx, CCPCP_ChainPack); + assert(in_ctx.err_no == CCPCP_RC_OK); + dry_run_size = out_ctx.bytes_written; + } + size_t packed_size; + { + static const size_t STATE_CNT = 100; + ccpcp_container_state states[STATE_CNT]; + ccpcp_container_stack stack; + ccpcp_container_stack_init(&stack, states, STATE_CNT, NULL); + + const char *in_buff = cpon; + ccpcp_unpack_context in_ctx; + ccpcp_pack_context out_ctx; + char out_buff[1024]; + ccpcp_unpack_context_init(&in_ctx, in_buff, strlen(in_buff), NULL, &stack); + ccpcp_pack_context_init(&out_ctx, out_buff, sizeof (out_buff), NULL); + ccpcp_convert(&in_ctx, CCPCP_Cpon, &out_ctx, CCPCP_ChainPack); + packed_size = out_ctx.current - out_ctx.start; + *out_ctx.current = 0; + //printf("%s\n", out_ctx.start); + } + if(o_verbose) + printf("%s - dry: %zu, real: %zu\n", cpon, dry_run_size, packed_size); + assert(dry_run_size == packed_size); } -*/ -#define INIT_OUT_BUFF() \ - char out_buff1[1024]; \ - ccpcp_pack_context out_ctx; \ - ccpcp_pack_context_init(&out_ctx, out_buff1, sizeof (out_buff1), NULL); \ -#define INIT_OUT_BUFFS() \ +static void test_dry_run_int(int n) +{ + if(o_verbose) + printf("---------------- test dry run int ---------------------\n"); + + size_t dry_run_size; + { + ccpcp_pack_context out_ctx; + ccpcp_pack_context_dry_run_init(&out_ctx); + cchainpack_pack_int(&out_ctx, n); + dry_run_size = out_ctx.bytes_written; + } + size_t packed_size; + { + ccpcp_pack_context out_ctx; + char out_buff[1024]; + ccpcp_pack_context_init(&out_ctx, out_buff, sizeof (out_buff), NULL); + cchainpack_pack_int(&out_ctx, n); + packed_size = out_ctx.current - out_ctx.start; + } + if(o_verbose) + printf("%d - dry: %zu, real: %zu\n", n, dry_run_size, packed_size); + assert(dry_run_size == packed_size); +} + +#define INIT_OUT_CONTEXT() \ char out_buff1[1024]; \ ccpcp_pack_context out_ctx; \ ccpcp_pack_context_init(&out_ctx, out_buff1, sizeof (out_buff1), NULL); \ - char out_buff2[1024]; void test_vals() { printf("------------- NULL \n"); { - INIT_OUT_BUFFS(); + INIT_OUT_CONTEXT(); ccpon_pack_null(&out_ctx); *out_ctx.current = 0; + char out_buff2[1024]; snprintf(out_buff2, sizeof (out_buff2), "null"); test_cpon((const char *)out_ctx.start, out_buff2); } printf("------------- BOOL \n"); for (unsigned n = 0; n < 2; ++n) { - INIT_OUT_BUFFS(); + INIT_OUT_CONTEXT(); ccpon_pack_boolean(&out_ctx, n); *out_ctx.current = 0; + char out_buff2[1024]; snprintf(out_buff2, sizeof (out_buff2), n? "true": "false"); test_cpon((const char *)out_ctx.start, out_buff2); } printf("------------- tiny uint \n"); for (unsigned n = 0; n < 64; ++n) { - INIT_OUT_BUFFS(); + INIT_OUT_CONTEXT(); ccpon_pack_uint(&out_ctx, n); *out_ctx.current = 0; + char out_buff2[1024]; snprintf(out_buff2, sizeof (out_buff2), "%du", n); test_cpon((const char *)out_ctx.start, out_buff2); } @@ -386,9 +441,10 @@ void test_vals() shift_n = max_shift_n; int64_t n = ((int64_t)1) << shift_n; uint64_t un = (uint64_t)n; - INIT_OUT_BUFFS(); + INIT_OUT_CONTEXT(); ccpon_pack_uint(&out_ctx, un); *out_ctx.current = 0; + char out_buff2[1024]; snprintf(out_buff2, sizeof (out_buff2), "%lluu", (unsigned long long)un); test_cpon((const char *)out_ctx.start, out_buff2); } @@ -398,17 +454,19 @@ void test_vals() n = ~n; // cpon parser can handle only int64_t numbers n /= 2; - INIT_OUT_BUFFS(); + INIT_OUT_CONTEXT(); ccpon_pack_uint(&out_ctx, n); *out_ctx.current = 0; + char out_buff2[1024]; snprintf(out_buff2, sizeof (out_buff2), "%lluu", (unsigned long long)n); test_cpon((const char *)out_ctx.start, out_buff2); } printf("------------- tiny int \n"); for (int n = 0; n < 64; ++n) { - INIT_OUT_BUFFS(); + INIT_OUT_CONTEXT(); ccpon_pack_int(&out_ctx, n); *out_ctx.current = 0; + char out_buff2[1024]; snprintf(out_buff2, sizeof (out_buff2), "%i", n); test_cpon((const char *)out_ctx.start, out_buff2); } @@ -421,9 +479,10 @@ void test_vals() if(shift_n >= max_shift_n) shift_n = max_shift_n; int64_t n = sig * ((int64_t)1 << shift_n); - INIT_OUT_BUFFS(); + INIT_OUT_CONTEXT(); ccpon_pack_int(&out_ctx, n); *out_ctx.current = 0; + char out_buff2[1024]; snprintf(out_buff2, sizeof (out_buff2), "%lli", (long long)n); test_cpon((const char *)out_ctx.start, out_buff2); } @@ -431,9 +490,10 @@ void test_vals() } for (int i = 0; i < 2; i++) { int64_t n = i? INT64_MAX: INT64_MIN + 1; - INIT_OUT_BUFFS(); + INIT_OUT_CONTEXT(); ccpon_pack_int(&out_ctx, n); *out_ctx.current = 0; + char out_buff2[1024]; snprintf(out_buff2, sizeof (out_buff2), "%lli", (long long)n); test_cpon((const char *)out_ctx.start, out_buff2); } @@ -444,7 +504,7 @@ void test_vals() int exp_max = 16; int step = 1; for (int exp = exp_min; exp <= exp_max; exp += step) { - INIT_OUT_BUFF(); + INIT_OUT_CONTEXT(); ccpon_pack_decimal(&out_ctx, mant, exp); *out_ctx.current = 0; test_cpon((const char *)out_ctx.start, NULL); @@ -457,7 +517,7 @@ void test_vals() double n_min = -1000000.; double step = (n_max - n_min) / 100.1; for (double n = n_min; n < n_max; n += step) { - INIT_OUT_BUFF(); + INIT_OUT_CONTEXT(); cchainpack_pack_double(&out_ctx, n); assert(out_ctx.current - out_ctx.start == sizeof(double) + 1); ccpcp_unpack_context in_ctx; @@ -473,8 +533,9 @@ void test_vals() double step = -1.23456789e10; //qDebug() << n_min << " - " << n_max << ": " << step << " === " << (n_max / step / 10); for (double n = n_min; n < n_max / -step / 10; n *= step) { - INIT_OUT_BUFF(); - printf("%g\n", n); + INIT_OUT_CONTEXT(); + if(o_verbose) + printf("%g\n", n); cchainpack_pack_double(&out_ctx, n); ccpcp_unpack_context in_ctx; ccpcp_unpack_context_init(&in_ctx, out_buff1, sizeof(out_buff1), NULL, NULL); @@ -503,7 +564,7 @@ void test_vals() }; for (size_t i = 0; i < sizeof (cpons) / sizeof(char*); i+=2) { const char *cpon = cpons[i]; - INIT_OUT_BUFF(); + INIT_OUT_CONTEXT(); test_cpon(cpon, cpons[i+1]); } } @@ -519,7 +580,7 @@ void test_vals() }; for (size_t i = 0; i < sizeof (cpons) / sizeof(char*); i+=2) { const char *cpon = cpons[i]; - INIT_OUT_BUFF(); + INIT_OUT_CONTEXT(); ccpon_pack_string_terminated(&out_ctx, cpon); *out_ctx.current = 0; test_cpon2(out_ctx.start, cpons[i+1]); @@ -530,6 +591,7 @@ void test_vals() void test_cpons() { const char* cpons[] = { + "[]", NULL, "null", NULL, //"@", "null", "0.", NULL, @@ -577,6 +639,7 @@ void test_cpons() size_t cpons_cnt = sizeof (cpons) / sizeof (char*); for(size_t i = 0; i < cpons_cnt; i += 2) { test_cpon(cpons[i], cpons[i+1]); + test_dry_run_cpon(cpons[i]); } } @@ -584,7 +647,7 @@ int main(int argc, const char * argv[]) { for (int i = 0; i < argc; ++i) { if(!strcmp(argv[i], "-v")) { - o_silent = false; + o_verbose = true; } } @@ -675,6 +738,11 @@ int main(int argc, const char * argv[]) test_cpons(); + test_dry_run_int(1); + test_dry_run_int(128); + test_dry_run_int(1234); + test_dry_run_int(-12345); + test_pack_decimal(0, 0, "0."); test_pack_decimal(83, 1, "830."); test_pack_decimal(83, 0, "83.");