Skip to content

Commit

Permalink
Merge pull request #231 from silicon-heaven/better-chainpack-parser
Browse files Browse the repository at this point in the history
Add support for NULL chainpack serialization buffer #202
  • Loading branch information
fvacek authored Jan 14, 2023
2 parents 7460e7b + 0861387 commit 6f2abd2
Show file tree
Hide file tree
Showing 5 changed files with 183 additions and 168 deletions.
129 changes: 49 additions & 80 deletions libshvchainpack/c/ccpcp.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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;
Expand All @@ -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)
Expand All @@ -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 ================================
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -425,3 +393,4 @@ size_t ccpcp_decimal_to_string(char *buff, size_t buff_len, int64_t mantisa, int
return mantisa_str_len;
}


12 changes: 7 additions & 5 deletions libshvchainpack/c/ccpcp.h
Original file line number Diff line number Diff line change
Expand Up @@ -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 ============================
Expand Down
8 changes: 7 additions & 1 deletion libshvchainpack/c/ccpcp_convert.c
Original file line number Diff line number Diff line change
@@ -1,8 +1,15 @@
#include "cchainpack.h"
#include "ccpon.h"

#include <assert.h>

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;
Expand Down Expand Up @@ -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
Expand Down
50 changes: 10 additions & 40 deletions libshvchainpack/c/ccpon.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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)
Expand All @@ -578,20 +560,16 @@ 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)
{
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)
Expand All @@ -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)
Expand All @@ -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)
Expand All @@ -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)
Expand Down
Loading

0 comments on commit 6f2abd2

Please sign in to comment.