summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--c/unpack.c22
-rw-r--r--cpp/msgpack/object.hpp52
-rw-r--r--msgpack/unpack_define.h5
-rw-r--r--msgpack/unpack_template.h33
-rw-r--r--perl/unpack.c8
5 files changed, 103 insertions, 17 deletions
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 <typename T>
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 <stdlib.h>
#include <string.h>
#include <assert.h>
#include <stdio.h>
@@ -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);