diff --git a/cpp/src/msgpack/unpack.h b/cpp/src/msgpack/unpack.h index e17d0d85..1f43ab75 100644 --- a/cpp/src/msgpack/unpack.h +++ b/cpp/src/msgpack/unpack.h @@ -20,6 +20,15 @@ #include "msgpack/zone.h" #include "msgpack/object.h" +#include + +#ifndef MSGPACK_UNPACKER_INIT_BUFFER_SIZE +#define MSGPACK_UNPACKER_INIT_BUFFER_SIZE (64*1024) +#endif + +#ifndef MSGPACK_UNPACKER_RESERVE_SIZE +#define MSGPACK_UNPACKER_RESERVE_SIZE (32*1024) +#endif #ifdef __cplusplus extern "C" { @@ -37,6 +46,10 @@ typedef struct msgpack_unpacker { void* ctx; } msgpack_unpacker; +typedef struct msgpack_unpacked { + msgpack_zone* zone; + msgpack_object data; +} msgpack_unpacked; bool msgpack_unpacker_init(msgpack_unpacker* mpac, size_t initial_buffer_size); void msgpack_unpacker_destroy(msgpack_unpacker* mpac); @@ -49,6 +62,13 @@ static inline char* msgpack_unpacker_buffer(msgpack_unpacker* mpac); static inline size_t msgpack_unpacker_buffer_capacity(const msgpack_unpacker* mpac); static inline void msgpack_unpacker_buffer_consumed(msgpack_unpacker* mpac, size_t size); +bool msgpack_unpacker_next(msgpack_unpacker* mpac, msgpack_unpacked* pac); + +static inline void msgpack_unpacked_init(msgpack_unpacked* result); +static inline void msgpack_unpacked_destroy(msgpack_unpacked* result); + +static inline msgpack_zone* msgpack_unpacked_release_zone(msgpack_unpacked* result); + int msgpack_unpacker_execute(msgpack_unpacker* mpac); @@ -63,6 +83,9 @@ void msgpack_unpacker_reset(msgpack_unpacker* mpac); static inline size_t msgpack_unpacker_message_size(const msgpack_unpacker* mpac); +bool msgpack_unpack_next(msgpack_unpacked* result, + const char* data, size_t len, size_t* off); + typedef enum { MSGPACK_UNPACK_SUCCESS = 2, @@ -73,7 +96,7 @@ typedef enum { msgpack_unpack_return msgpack_unpack(const char* data, size_t len, size_t* off, - msgpack_zone* z, msgpack_object* result); + msgpack_zone* result_zone, msgpack_object* result); static inline size_t msgpack_unpacker_parsed_size(const msgpack_unpacker* mpac); @@ -115,6 +138,31 @@ size_t msgpack_unpacker_parsed_size(const msgpack_unpacker* mpac) } +void msgpack_unpacked_init(msgpack_unpacked* result) +{ + memset(result, 0, sizeof(msgpack_unpacked)); +} + +void msgpack_unpacked_destroy(msgpack_unpacked* result) +{ + if(result->zone != NULL) { + msgpack_zone_free(result->zone); + result->zone = NULL; + memset(&result->data, 0, sizeof(msgpack_object)); + } +} + +msgpack_zone* msgpack_unpacked_release_zone(msgpack_unpacked* result) +{ + if(result->zone != NULL) { + msgpack_zone* z = result->zone; + result->zone = NULL; + return z; + } + return NULL; +} + + #ifdef __cplusplus } #endif diff --git a/cpp/src/msgpack/unpack.hpp b/cpp/src/msgpack/unpack.hpp index e1617efb..7b45017a 100644 --- a/cpp/src/msgpack/unpack.hpp +++ b/cpp/src/msgpack/unpack.hpp @@ -24,8 +24,9 @@ #include #include +// backward compatibility #ifndef MSGPACK_UNPACKER_DEFAULT_INITIAL_BUFFER_SIZE -#define MSGPACK_UNPACKER_DEFAULT_INITIAL_BUFFER_SIZE (32*1024) +#define MSGPACK_UNPACKER_DEFAULT_INITIAL_BUFFER_SIZE MSGPACK_UNPACKER_INIT_BUFFER_SIZE #endif namespace msgpack { @@ -64,12 +65,12 @@ private: class unpacker : public msgpack_unpacker { public: - unpacker(size_t init_buffer_size = MSGPACK_UNPACKER_DEFAULT_INITIAL_BUFFER_SIZE); + unpacker(size_t init_buffer_size = MSGPACK_UNPACKER_INIT_BUFFER_SIZE); ~unpacker(); public: /*! 1. reserve buffer. at least `size' bytes of capacity will be ready */ - void reserve_buffer(size_t size); + void reserve_buffer(size_t size = MSGPACK_UNPACKER_RESERVE_SIZE); /*! 2. read data to the buffer() up to buffer_capacity() bytes */ char* buffer(); diff --git a/cpp/src/unpack.c b/cpp/src/unpack.c index 4a425264..0c21780b 100644 --- a/cpp/src/unpack.c +++ b/cpp/src/unpack.c @@ -363,20 +363,46 @@ void msgpack_unpacker_reset(msgpack_unpacker* mpac) mpac->parsed = 0; } +bool msgpack_unpacker_next(msgpack_unpacker* mpac, msgpack_unpacked* result) +{ + if(result->zone != NULL) { + msgpack_zone_free(result->zone); + } + + int ret = msgpack_unpacker_execute(mpac); + + if(ret <= 0) { + result->zone = NULL; + memset(&result->data, 0, sizeof(msgpack_object)); + return false; + } + + result->zone = msgpack_unpacker_release_zone(mpac); + result->data = msgpack_unpacker_data(mpac); + msgpack_unpacker_reset(mpac); + + return true; +} + msgpack_unpack_return msgpack_unpack(const char* data, size_t len, size_t* off, - msgpack_zone* z, msgpack_object* result) + msgpack_zone* result_zone, msgpack_object* result) { + size_t noff = 0; + if(off != NULL) { noff = *off; } + + if(len <= noff) { + // FIXME + return MSGPACK_UNPACK_CONTINUE; + } + template_context ctx; template_init(&ctx); - ctx.user.z = z; + ctx.user.z = result_zone; ctx.user.referenced = false; - size_t noff = 0; - if(off != NULL) { noff = *off; } - int e = template_execute(&ctx, data, len, &noff); if(e < 0) { return MSGPACK_UNPACK_PARSE_ERROR; @@ -397,3 +423,37 @@ msgpack_unpack(const char* data, size_t len, size_t* off, return MSGPACK_UNPACK_SUCCESS; } +bool msgpack_unpack_next(msgpack_unpacked* result, + const char* data, size_t len, size_t* off) +{ + msgpack_unpacked_destroy(result); + + size_t noff = 0; + if(off != NULL) { noff = *off; } + + if(len <= noff) { + return false; + } + + msgpack_zone* z = msgpack_zone_new(MSGPACK_ZONE_CHUNK_SIZE); + + template_context ctx; + template_init(&ctx); + + ctx.user.z = z; + ctx.user.referenced = false; + + int e = template_execute(&ctx, data, len, &noff); + if(e <= 0) { + msgpack_zone_free(z); + return false; + } + + if(off != NULL) { *off = noff; } + + result->zone = z; + result->data = template_data(&ctx); + + return true; +} + diff --git a/cpp/src/zone.c b/cpp/src/zone.c index 85de765a..8cc8b0de 100644 --- a/cpp/src/zone.c +++ b/cpp/src/zone.c @@ -214,6 +214,7 @@ msgpack_zone* msgpack_zone_new(size_t chunk_size) void msgpack_zone_free(msgpack_zone* zone) { + if(zone == NULL) { return; } msgpack_zone_destroy(zone); free(zone); }