diff --git a/c/unpack.c b/c/unpack.c index 8be0b92..4334974 100644 --- a/c/unpack.c +++ b/c/unpack.c @@ -44,6 +44,7 @@ struct template_context; typedef struct template_context template_context; static void template_init(template_context* ctx); +static void template_destroy(template_context* ctx); static msgpack_object template_data(template_context* ctx); @@ -215,6 +216,7 @@ bool msgpack_unpacker_init(msgpack_unpacker* mpac, size_t initial_buffer_size) void msgpack_unpacker_destroy(msgpack_unpacker* mpac) { msgpack_zone_free(mpac->z); + template_destroy(mpac->ctx); free(mpac->ctx); decl_count(mpac->buffer); } @@ -368,6 +370,7 @@ msgpack_unpack_return msgpack_unpack(const char* data, size_t len, size_t* off, msgpack_zone* z, msgpack_object* result) { + msgpack_unpack_return ret = MSGPACK_UNPACK_SUCCESS; template_context ctx; template_init(&ctx); @@ -377,23 +380,28 @@ msgpack_unpack(const char* data, size_t len, size_t* off, size_t noff = 0; if(off != NULL) { noff = *off; } - int ret = template_execute(&ctx, data, len, &noff); - if(ret < 0) { - return MSGPACK_UNPACK_PARSE_ERROR; + int e = template_execute(&ctx, data, len, &noff); + if(e < 0) { + ret = MSGPACK_UNPACK_PARSE_ERROR; + goto out; } if(off != NULL) { *off = noff; } - if(ret == 0) { - return MSGPACK_UNPACK_CONTINUE; + if(e == 0) { + ret = MSGPACK_UNPACK_CONTINUE; + goto out; } *result = template_data(&ctx); if(noff < len) { - return MSGPACK_UNPACK_EXTRA_BYTES; + ret = MSGPACK_UNPACK_EXTRA_BYTES; + goto out; } - return MSGPACK_UNPACK_SUCCESS; +out: + template_destroy(&ctx); + return ret; } diff --git a/cpp/msgpack/object.hpp b/cpp/msgpack/object.hpp index ed2e290..3b42a8e 100644 --- a/cpp/msgpack/object.hpp +++ b/cpp/msgpack/object.hpp @@ -87,9 +87,15 @@ struct object { template void convert(T* v) const; - object(); - object(msgpack_object obj); operator msgpack_object(); + object(msgpack_object obj); + + object(); + object(bool v); + object(uint64_t v); + object(int64_t v); + object(double v); + object(const char* ptr, size_t size); private: struct implicit_type; @@ -184,7 +190,46 @@ inline bool operator!=(const object x, const object y) { return !(x == y); } -inline object::object() { } +inline object::object() +{ + type = type::NIL; +} + +inline object::object(bool v) +{ + type = type::BOOLEAN; + via.boolean = v; +} + +inline object::object(uint64_t v) +{ + type = type::POSITIVE_INTEGER; + via.u64 = v; +} + +inline object::object(int64_t v) +{ + if(v >= 0) { + type = type::POSITIVE_INTEGER; + via.u64 = v; + } else { + type = type::NEGATIVE_INTEGER; + via.i64 = v; + } +} + +inline object::object(double v) +{ + type = type::DOUBLE; + via.dec = v; +} + +inline object::object(const char* ptr, size_t size) +{ + type = type::RAW; + via.raw.size = size; + via.raw.ptr = ptr; +} inline object::object(msgpack_object obj) { @@ -200,7 +245,6 @@ inline object::operator msgpack_object() return obj; } - inline object::implicit_type object::convert() const { return implicit_type(*this); diff --git a/msgpack/unpack_define.h b/msgpack/unpack_define.h index e61f73d..cb02a3b 100644 --- a/msgpack/unpack_define.h +++ b/msgpack/unpack_define.h @@ -19,6 +19,7 @@ #define MSGPACK_UNPACK_DEFINE_H__ #include "msgpack/sysdep.h" +#include #include #include #include @@ -28,8 +29,8 @@ extern "C" { #endif -#ifndef MSGPACK_MAX_STACK_SIZE -#define MSGPACK_MAX_STACK_SIZE 16 +#ifndef MSGPACK_EMBED_STACK_SIZE +#define MSGPACK_EMBED_STACK_SIZE 1 #endif diff --git a/msgpack/unpack_template.h b/msgpack/unpack_template.h index 3f871cd..72f8e59 100644 --- a/msgpack/unpack_template.h +++ b/msgpack/unpack_template.h @@ -58,7 +58,9 @@ msgpack_unpack_struct_decl(_context) { unsigned int cs; unsigned int trail; unsigned int top; - msgpack_unpack_struct(_stack) stack[MSGPACK_MAX_STACK_SIZE]; + msgpack_unpack_struct(_stack)* stack; + unsigned int stack_size; + msgpack_unpack_struct(_stack) embed_stack[MSGPACK_EMBED_STACK_SIZE]; }; @@ -67,9 +69,18 @@ msgpack_unpack_func(void, _init)(msgpack_unpack_struct(_context)* ctx) ctx->cs = CS_HEADER; ctx->trail = 0; ctx->top = 0; + ctx->stack = ctx->embed_stack; + ctx->stack_size = MSGPACK_EMBED_STACK_SIZE; ctx->stack[0].obj = msgpack_unpack_callback(_root)(&ctx->user); } +msgpack_unpack_func(void, _destroy)(msgpack_unpack_struct(_context)* ctx) +{ + if(ctx->stack_size != MSGPACK_EMBED_STACK_SIZE) { + free(ctx->stack); + } +} + msgpack_unpack_func(msgpack_unpack_object, _data)(msgpack_unpack_struct(_context)* ctx) { return (ctx)->stack[0].obj; @@ -119,12 +130,28 @@ msgpack_unpack_func(int, _execute)(msgpack_unpack_struct(_context)* ctx, const c #define start_container(func, count_, ct_) \ if(msgpack_unpack_callback(func)(user, count_, &stack[top].obj) < 0) { goto _failed; } \ if((count_) == 0) { obj = stack[top].obj; goto _push; } \ - if(top >= MSGPACK_MAX_STACK_SIZE) { goto _failed; } \ stack[top].ct = ct_; \ stack[top].count = count_; \ + ++top; \ /*printf("container %d count %d stack %d\n",stack[top].obj,count_,top);*/ \ /*printf("stack push %d\n", top);*/ \ - ++top; \ + if(top >= ctx->stack_size) { \ + if(ctx->stack_size == MSGPACK_EMBED_STACK_SIZE) { \ + size_t csize = sizeof(msgpack_unpack_struct(_stack)) * MSGPACK_EMBED_STACK_SIZE; \ + size_t nsize = csize * 2; \ + msgpack_unpack_struct(_stack)* tmp = (msgpack_unpack_struct(_stack)*)malloc(nsize); \ + if(tmp == NULL) { goto _failed; } \ + memcpy(tmp, ctx->stack, csize); \ + ctx->stack = tmp; \ + ctx->stack_size = MSGPACK_EMBED_STACK_SIZE * 2; \ + } else { \ + size_t nsize = sizeof(msgpack_unpack_struct(_stack)) * ctx->stack_size * 2; \ + msgpack_unpack_struct(_stack)* tmp = (msgpack_unpack_struct(_stack)*)realloc(ctx->stack, nsize); \ + if(tmp == NULL) { goto _failed; } \ + ctx->stack = tmp; \ + ctx->stack_size *= 2; \ + } \ + } \ goto _header_again #define NEXT_CS(p) \ diff --git a/perl/unpack.c b/perl/unpack.c index 7a4f422..c520e02 100644 --- a/perl/unpack.c +++ b/perl/unpack.c @@ -53,6 +53,7 @@ struct template_context; typedef struct template_context msgpack_unpack_t; static void template_init(msgpack_unpack_t* u); +static void template_destroy(msgpack_unpack_t* u); static SV* template_data(msgpack_unpack_t* u); @@ -132,6 +133,7 @@ SV* _msgpack_unpack(SV* data, int limit) { size_t from = 0; STRLEN dlen; const char * dptr = SvPV_const(data, dlen); + SV* obj; template_init(&mp); mp.user = u; @@ -140,6 +142,9 @@ SV* _msgpack_unpack(SV* data, int limit) { ret = template_execute(&mp, dptr, (size_t)dlen, &from); mp.user.source = &PL_sv_undef; + obj = template_data(&mp); + template_destroy(&mp); + if(ret < 0) { Perl_croak(aTHX_ "parse error."); } else if(ret == 0) { @@ -148,7 +153,7 @@ SV* _msgpack_unpack(SV* data, int limit) { if(from < dlen) { Perl_croak(aTHX_ "extra bytes."); } - return template_data(&mp); + return obj; } } @@ -311,6 +316,7 @@ XS(xs_unpacker_destroy) { } UNPACKER(ST(0), mp); + template_destroy(mp); Safefree(mp); XSRETURN(0);