static int get_bsd_value( sdb_read_ctx_t *ctx, double *value) { bsd_data_t data; if( bsd_read(& ctx->bsd_ctx, & data, ctx->bytes, ctx->nbytes) < ctx->nbytes) return 0; // read error, bad type if( data.type == BSD_INT) { *value = data.content.i; } else if( data.type == BSD_DOUBLE) { *value = data.content.d; } else { return 0; // bad type. } return 1; }
void bsd_dump( bsd_ctx_t *ctx, FILE *output, const uint8_t *buffer, int length) { const uint8_t *begin = buffer; const uint8_t *end = buffer + length; fputs("Byte\tOpcode\tContext\tType\tValue\tAdditional bytes\tAdditional info\n", output); while( buffer < end || ctx->stacksize > 0) { bsd_data_t x; struct bsd_stackframe_t *f = topframe( ctx); // we need context in which the value is decoded, so we catch now rather than after the read bs_ctxid_t ctxid = getctxid( f); int r = bsd_read( ctx, &x, buffer, length); if( 0 == r && BSD_ERROR == x.kind) { fprintf( output, "Error %d at byte %td.\n", x.content.error, buffer - begin); break; } else if( r < 0) { fprintf( output, "Error: %d bytes missing.\n", r); break; } else { int opcode_len = 0; fprintf( output, "%td\t", buffer - begin); if( r == 0) fputs( "N/A\tN/A\t", output); else { switch( ctxid) { case BS_CTXID_CHUNKED: opcode_len = 2; break; case BS_CTXID_FLOAT: case BS_CTXID_INT32: opcode_len = 4; break; case BS_CTXID_DOUBLE: opcode_len = 8; break; default: opcode_len = 1; break; } hexdump( output, buffer, opcode_len); fputc('\t', output); switch( ctxid) { #define CASE(x) case BS_CTXID_##x: fputs( #x"\t", output); break CASE(GLOBAL); CASE(UNSIGNED_OR_STRING); CASE(NUMBER); CASE(INT32); CASE(FLOAT); CASE(DOUBLE); CASE(LIST_OR_MAP); default: printf("%d\t", ctxid); break; #undef CASE } } switch( x.kind) { #define CASE(x) case BSD_##x: fputs( #x"\t", output) CASE(CLOSE); fputs( "N/A\t", output); break; CASE(NULL); fputs( "N/A\t", output); break; CASE(INT); fprintf( output, "%" PRId64 "\t", x.content.i); break; CASE(BOOL); fputs( x.content.boolean ? "true\t" : "false\t", output); break; CASE(DOUBLE); fprintf( output, "%f\t", x.content.d); break; CASE(STRING); fprintf( output, "length: %zu\t", x.content.string.length); break; CASE(CHUNKED_STRING); fputs( "N/A\t", output); break; CASE(CHUNK); fprintf( output, "length: %zu\t", x.content.chunk.length); break; CASE(LIST); fprintf( output, "length: %zu, ctx: %d\t", x.content.length, topframe( ctx)->ctxid); break; CASE(ZLIST); fprintf( output, "ctx: %d\t", topframe( ctx)->ctxid); break; CASE(MAP); fprintf( output, "length: %zu, ctx: %d\t", x.content.length, topframe( ctx)->ctxid); break; CASE(ZMAP); fprintf( output, "ctx: %d\t", topframe( ctx)->ctxid); break; CASE(OBJECT); if( NULL == x.content.classdef->classname) fprintf( output, "class: %d\t", x.content.classdef->classid); else fprintf( output, "class: %s\t", x.content.classdef->classname); break; CASE(CLASSDEF); if( NULL == x.content.classdef->classname) fprintf( output, "class: %d\t", x.content.classdef->classid); else fprintf( output, "class: %s\t", x.content.classdef->classname); break; default: fprintf(output, "%d\tN/A\t", x.kind); #undef CASE } int additional = r - opcode_len; if( 0 < additional && additional <= 10) hexdump( output, buffer+opcode_len, additional); else if( additional > 10) { hexdump( output, buffer+opcode_len, 3); fputs( "...", output); hexdump( output, buffer+r-3, 3); } else fputs( "N/A", output); fputs( "\t", output); // additional infos if( BSD_KOBJFIELD == x._internalContext && x.fieldname != NULL) { fprintf( output, "field: %s\t", x.fieldname); } else { fputs( "N/A\t", output); } fputs( "\n", output); } buffer += r; length -= r; } }