mirror of
https://github.com/msgpack/msgpack-c.git
synced 2025-03-18 12:34:15 +01:00
c and c++: rewritten and integrated
This commit is contained in:
parent
761b398083
commit
11abec1093
2
COPYING
2
COPYING
@ -1,4 +1,4 @@
|
||||
Copyright (C) 2008 FURUHASHI Sadayuki
|
||||
Copyright (C) 2008-2009 FURUHASHI Sadayuki
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
|
@ -1,4 +1,9 @@
|
||||
if ENABLE_CXX
|
||||
export ERB
|
||||
SUBDIRS = c cpp
|
||||
else
|
||||
SUBDIRS = c
|
||||
endif
|
||||
|
||||
nobase_include_HEADERS = \
|
||||
msgpack/pack_define.h \
|
||||
|
2
README
2
README
@ -54,7 +54,7 @@ Binary-based efficient data interchange format.
|
||||
|
||||
|
||||
|
||||
Copyright (C) 2008 FURUHASHI Sadayuki
|
||||
Copyright (C) 2008-2009 FURUHASHI Sadayuki
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
|
@ -31,10 +31,10 @@ if test x"$1" = x"--help"; then
|
||||
fi
|
||||
|
||||
|
||||
if [ -z "$NO_NEST" ];then
|
||||
cd c && ./bootstrap $@; cd ..
|
||||
cd cpp && ./bootstrap $@; cd ..
|
||||
fi
|
||||
#if [ -z "$NO_NEST" ];then
|
||||
# cd c && ./bootstrap $@; cd ..
|
||||
# cd cpp && ./bootstrap $@; cd ..
|
||||
#fi
|
||||
|
||||
|
||||
ACLOCAL="aclocal"
|
||||
|
14
c/COPYING
14
c/COPYING
@ -1,14 +0,0 @@
|
||||
Copyright (C) 2008-2009 FURUHASHI Sadayuki
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
|
21
c/README
21
c/README
@ -1,21 +0,0 @@
|
||||
MessagePack for C
|
||||
-----------------
|
||||
MessagePack is a binary-based efficient data interchange format.
|
||||
|
||||
|
||||
|
||||
Copyright (C) 2008-2009 FURUHASHI Sadayuki
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
|
||||
|
@ -1,3 +0,0 @@
|
||||
#!/bin/sh
|
||||
NO_NEST=1
|
||||
. ../bootstrap
|
@ -1,16 +0,0 @@
|
||||
AC_INIT(unpack.c)
|
||||
AM_INIT_AUTOMAKE(msgpackc, 0.1.0)
|
||||
AC_CONFIG_HEADER(config.h)
|
||||
|
||||
AC_SUBST(CFLAGS)
|
||||
if test "" = "$CFLAGS"; then
|
||||
CFLAGS="-g -O4"
|
||||
fi
|
||||
|
||||
AC_PROG_CC
|
||||
AC_PROG_LIBTOOL
|
||||
|
||||
CFLAGS="-O4 -Wall $CFLAGS -I.."
|
||||
|
||||
AC_OUTPUT([Makefile])
|
||||
|
199
c/object.c
199
c/object.c
@ -15,153 +15,78 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
#include "msgpack/unpack.h"
|
||||
#include "msgpack/unpack_define.h"
|
||||
#include "msgpack/object.h"
|
||||
#include <stdio.h>
|
||||
#include <inttypes.h>
|
||||
|
||||
typedef struct {
|
||||
msgpack_zone* z;
|
||||
bool referenced;
|
||||
bool failed;
|
||||
} unpack_user;
|
||||
|
||||
#define msgpack_unpack_struct(name) \
|
||||
struct msgpack_unpacker ## name
|
||||
|
||||
#define msgpack_unpack_func(ret, name) \
|
||||
ret msgpack_unpacker ## name
|
||||
|
||||
#define msgpack_unpack_callback(name) \
|
||||
msgpack_unpack ## name
|
||||
|
||||
#define msgpack_unpack_object msgpack_object
|
||||
|
||||
#define msgpack_unpack_user unpack_user
|
||||
|
||||
|
||||
struct msgpack_unpacker_context;
|
||||
|
||||
static void msgpack_unpacker_init(struct msgpack_unpacker_context* ctx);
|
||||
|
||||
static msgpack_object msgpack_unpacker_data(struct msgpack_unpacker_context* ctx);
|
||||
|
||||
static int msgpack_unpacker_execute(struct msgpack_unpacker_context* ctx,
|
||||
const char* data, size_t len, size_t* off);
|
||||
|
||||
static inline msgpack_object msgpack_unpack_init(unpack_user* u)
|
||||
{ msgpack_object o; return o; }
|
||||
|
||||
static inline msgpack_object msgpack_unpack_uint8(unpack_user* u, uint8_t d)
|
||||
{ msgpack_object o; o.type = MSGPACK_OBJECT_POSITIVE_INTEGER; o.via.u64 = d; return o; }
|
||||
|
||||
static inline msgpack_object msgpack_unpack_uint16(unpack_user* u, uint16_t d)
|
||||
{ msgpack_object o; o.type = MSGPACK_OBJECT_POSITIVE_INTEGER; o.via.u64 = d; return o; }
|
||||
|
||||
static inline msgpack_object msgpack_unpack_uint32(unpack_user* u, uint32_t d)
|
||||
{ msgpack_object o; o.type = MSGPACK_OBJECT_POSITIVE_INTEGER; o.via.u64 = d; return o; }
|
||||
|
||||
static inline msgpack_object msgpack_unpack_uint64(unpack_user* u, uint64_t d)
|
||||
{ msgpack_object o; o.type = MSGPACK_OBJECT_POSITIVE_INTEGER; o.via.u64 = d; return o; }
|
||||
|
||||
static inline msgpack_object msgpack_unpack_int8(unpack_user* u, int8_t d)
|
||||
{ if(d >= 0) { msgpack_object o; o.type = MSGPACK_OBJECT_POSITIVE_INTEGER; o.via.u64 = d; return o; }
|
||||
else { msgpack_object o; o.type = MSGPACK_OBJECT_NEGATIVE_INTEGER; o.via.i64 = d; return o; } }
|
||||
|
||||
static inline msgpack_object msgpack_unpack_int16(unpack_user* u, int16_t d)
|
||||
{ if(d >= 0) { msgpack_object o; o.type = MSGPACK_OBJECT_POSITIVE_INTEGER; o.via.u64 = d; return o; }
|
||||
else { msgpack_object o; o.type = MSGPACK_OBJECT_NEGATIVE_INTEGER; o.via.i64 = d; return o; } }
|
||||
|
||||
static inline msgpack_object msgpack_unpack_int32(unpack_user* u, int32_t d)
|
||||
{ if(d >= 0) { msgpack_object o; o.type = MSGPACK_OBJECT_POSITIVE_INTEGER; o.via.u64 = d; return o; }
|
||||
else { msgpack_object o; o.type = MSGPACK_OBJECT_NEGATIVE_INTEGER; o.via.i64 = d; return o; } }
|
||||
|
||||
static inline msgpack_object msgpack_unpack_int64(unpack_user* u, int64_t d)
|
||||
{ if(d >= 0) { msgpack_object o; o.type = MSGPACK_OBJECT_POSITIVE_INTEGER; o.via.u64 = d; return o; }
|
||||
else { msgpack_object o; o.type = MSGPACK_OBJECT_NEGATIVE_INTEGER; o.via.i64 = d; return o; } }
|
||||
|
||||
static inline msgpack_object msgpack_unpack_float(unpack_user* u, float d)
|
||||
{ msgpack_object o; o.type = MSGPACK_OBJECT_DOUBLE; o.via.dec = d; return o; }
|
||||
|
||||
static inline msgpack_object msgpack_unpack_double(unpack_user* u, double d)
|
||||
{ msgpack_object o; o.type = MSGPACK_OBJECT_DOUBLE; o.via.dec = d; return o; }
|
||||
|
||||
static inline msgpack_object msgpack_unpack_nil(unpack_user* u)
|
||||
{ msgpack_object o; o.type = MSGPACK_OBJECT_NIL; return o; }
|
||||
|
||||
static inline msgpack_object msgpack_unpack_true(unpack_user* u)
|
||||
{ msgpack_object o; o.type = MSGPACK_OBJECT_BOOLEAN; o.via.boolean = true; return o; }
|
||||
|
||||
static inline msgpack_object msgpack_unpack_false(unpack_user* u)
|
||||
{ msgpack_object o; o.type = MSGPACK_OBJECT_BOOLEAN; o.via.boolean = false; return o; }
|
||||
|
||||
static inline msgpack_object msgpack_unpack_array(unpack_user* u, unsigned int n)
|
||||
void msgpack_object_print(FILE* out, msgpack_object o)
|
||||
{
|
||||
msgpack_object o;
|
||||
o.type = MSGPACK_OBJECT_ARRAY;
|
||||
o.via.array.size = 0;
|
||||
o.via.array.ptr = msgpack_zone_malloc(u->z, n*sizeof(msgpack_object));
|
||||
if(o.via.array.ptr == NULL) { u->failed = true; }
|
||||
return o;
|
||||
}
|
||||
switch(o.type) {
|
||||
case MSGPACK_OBJECT_NIL:
|
||||
fprintf(out, "nil");
|
||||
break;
|
||||
|
||||
static inline void msgpack_unpack_array_item(unpack_user* u, msgpack_object* c, msgpack_object o)
|
||||
{
|
||||
if(u->failed) { return; }
|
||||
c->via.array.ptr[ c->via.array.size++ ] = o;
|
||||
}
|
||||
case MSGPACK_OBJECT_BOOLEAN:
|
||||
fprintf(out, (o.via.boolean ? "true" : "false"));
|
||||
break;
|
||||
|
||||
static inline msgpack_object msgpack_unpack_map(unpack_user* u, unsigned int n)
|
||||
{
|
||||
msgpack_object o;
|
||||
o.type = MSGPACK_OBJECT_MAP;
|
||||
o.via.map.size = 0;
|
||||
o.via.map.ptr = msgpack_zone_malloc(u->z, n*sizeof(msgpack_object_kv));
|
||||
if(o.via.map.ptr == NULL) { u->failed = true; }
|
||||
return o;
|
||||
}
|
||||
case MSGPACK_OBJECT_POSITIVE_INTEGER:
|
||||
fprintf(out, "%"PRIu64, o.via.u64);
|
||||
break;
|
||||
|
||||
static inline void msgpack_unpack_map_item(unpack_user* u, msgpack_object* c, msgpack_object k, msgpack_object v)
|
||||
{
|
||||
if(u->failed) { return; }
|
||||
c->via.map.ptr[c->via.map.size].key = k;
|
||||
c->via.map.ptr[c->via.map.size].val = v;
|
||||
++c->via.map.size;
|
||||
}
|
||||
case MSGPACK_OBJECT_NEGATIVE_INTEGER:
|
||||
fprintf(out, "%"PRIi64, o.via.i64);
|
||||
break;
|
||||
|
||||
static inline msgpack_object msgpack_unpack_raw(unpack_user* u, const char* b, const char* p, unsigned int l)
|
||||
{
|
||||
msgpack_object o;
|
||||
o.type = MSGPACK_OBJECT_RAW;
|
||||
o.via.raw.ptr = p;
|
||||
o.via.raw.size = l;
|
||||
u->referenced = true;
|
||||
return o;
|
||||
}
|
||||
case MSGPACK_OBJECT_DOUBLE:
|
||||
fprintf(out, "%f", o.via.dec);
|
||||
break;
|
||||
|
||||
#include "msgpack/unpack_template.h"
|
||||
case MSGPACK_OBJECT_RAW:
|
||||
fprintf(out, "\"");
|
||||
fwrite(o.via.raw.ptr, o.via.raw.size, 1, out);
|
||||
fprintf(out, "\"");
|
||||
break;
|
||||
|
||||
msgpack_object_unpack_return
|
||||
msgpack_object_unpack(const char* data, size_t len, size_t* off,
|
||||
msgpack_zone* z, msgpack_object* result)
|
||||
{
|
||||
struct msgpack_unpacker_context ctx;
|
||||
msgpack_unpacker_init(&ctx);
|
||||
unpack_user u = {z, false, false};
|
||||
ctx.user = u;
|
||||
case MSGPACK_OBJECT_ARRAY:
|
||||
fprintf(out, "[");
|
||||
if(o.via.array.size != 0) {
|
||||
msgpack_object* p = o.via.array.ptr;
|
||||
msgpack_object_print(out, *p);
|
||||
++p;
|
||||
msgpack_object* const pend = o.via.array.ptr + o.via.array.size;
|
||||
for(; p < pend; ++p) {
|
||||
fprintf(out, ", ");
|
||||
msgpack_object_print(out, *p);
|
||||
}
|
||||
}
|
||||
fprintf(out, "]");
|
||||
break;
|
||||
// FIXME loop optimiziation
|
||||
|
||||
size_t noff = (off ? *off : 0);
|
||||
int ret = msgpack_unpacker_execute(&ctx, data, len, &noff);
|
||||
if(ret < 0 || ctx.user.failed) {
|
||||
return MSGPACK_OBJECT_PARSE_ERROR;
|
||||
} else if(ret == 0) {
|
||||
return MSGPACK_OBJECT_INSUFFICIENT_BYTES;
|
||||
case MSGPACK_OBJECT_MAP:
|
||||
fprintf(out, "{");
|
||||
if(o.via.map.size != 0) {
|
||||
msgpack_object_kv* p = o.via.map.ptr;
|
||||
msgpack_object_print(out, p->key);
|
||||
fprintf(out, "=>");
|
||||
msgpack_object_print(out, p->val);
|
||||
++p;
|
||||
msgpack_object_kv* const pend = o.via.map.ptr + o.via.map.size;
|
||||
for(; p < pend; ++p) {
|
||||
fprintf(out, ", ");
|
||||
msgpack_object_print(out, p->key);
|
||||
fprintf(out, "=>");
|
||||
msgpack_object_print(out, p->val);
|
||||
}
|
||||
}
|
||||
fprintf(out, "}");
|
||||
break;
|
||||
// FIXME loop optimiziation
|
||||
|
||||
default:
|
||||
// FIXME
|
||||
fprintf(out, "#<UNKNOWN %hu %"PRIu64">", o.type, o.via.u64);
|
||||
}
|
||||
*result = msgpack_unpacker_data(&ctx);
|
||||
if(off) { *off = noff; }
|
||||
if(ret == 0) {
|
||||
return MSGPACK_OBJECT_EXTRA_BYTES;
|
||||
}
|
||||
return MSGPACK_OBJECT_PARSE_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
|
23
c/object.h
23
c/object.h
@ -22,6 +22,7 @@
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
@ -39,18 +40,18 @@ typedef enum {
|
||||
MSGPACK_OBJECT_MAP = 0x08,
|
||||
} msgpack_object_type;
|
||||
|
||||
struct _msgpack_object;
|
||||
|
||||
struct _msgpack_object_kv;
|
||||
struct msgpack_object;
|
||||
struct msgpack_object_kv;
|
||||
|
||||
typedef struct {
|
||||
uint32_t size;
|
||||
struct _msgpack_object* ptr;
|
||||
struct msgpack_object* ptr;
|
||||
} msgpack_object_array;
|
||||
|
||||
typedef struct {
|
||||
uint32_t size;
|
||||
struct _msgpack_object_kv* ptr;
|
||||
struct msgpack_object_kv* ptr;
|
||||
} msgpack_object_map;
|
||||
|
||||
typedef struct {
|
||||
@ -68,26 +69,18 @@ typedef union {
|
||||
msgpack_object_raw raw;
|
||||
} msgpack_object_union;
|
||||
|
||||
typedef struct _msgpack_object {
|
||||
typedef struct msgpack_object {
|
||||
msgpack_object_type type;
|
||||
msgpack_object_union via;
|
||||
} msgpack_object;
|
||||
|
||||
typedef struct _msgpack_object_kv {
|
||||
typedef struct msgpack_object_kv {
|
||||
msgpack_object key;
|
||||
msgpack_object val;
|
||||
} msgpack_object_kv;
|
||||
|
||||
typedef enum {
|
||||
MSGPACK_OBJECT_PARSE_SUCCESS = 0,
|
||||
MSGPACK_OBJECT_EXTRA_BYTES = 1,
|
||||
MSGPACK_OBJECT_INSUFFICIENT_BYTES = -1,
|
||||
MSGPACK_OBJECT_PARSE_ERROR = -2,
|
||||
} msgpack_object_unpack_return;
|
||||
|
||||
msgpack_object_unpack_return
|
||||
msgpack_object_unpack(const char* data, size_t len, size_t* off,
|
||||
msgpack_zone* z, msgpack_object* result);
|
||||
void msgpack_object_print(FILE* out, msgpack_object o);
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
87
c/pack.h
87
c/pack.h
@ -28,50 +28,49 @@ extern "C" {
|
||||
#endif
|
||||
|
||||
|
||||
typedef int (*msgpack_pack_write_t)(void* data, const char* buf, unsigned int len);
|
||||
typedef int (*msgpack_packer_write)(void* data, const char* buf, unsigned int len);
|
||||
|
||||
typedef struct {
|
||||
typedef struct msgpack_packer {
|
||||
void* data;
|
||||
msgpack_pack_write_t callback;
|
||||
} msgpack_pack_t;
|
||||
msgpack_packer_write callback;
|
||||
} msgpack_packer;
|
||||
|
||||
static void msgpack_pack_init(msgpack_pack_t* ctx, void* data, msgpack_pack_write_t callback);
|
||||
static void msgpack_packer_init(msgpack_packer* pk, void* data, msgpack_packer_write callback);
|
||||
|
||||
static msgpack_pack_t* msgpack_pack_new(void* data, msgpack_pack_write_t callback);
|
||||
static msgpack_packer* msgpack_packer_new(void* data, msgpack_packer_write callback);
|
||||
static void msgpack_packer_free(msgpack_packer* pk);
|
||||
|
||||
static void msgpack_pack_free(msgpack_pack_t* ctx);
|
||||
static int msgpack_pack_short(msgpack_packer* pk, short d);
|
||||
static int msgpack_pack_int(msgpack_packer* pk, int d);
|
||||
static int msgpack_pack_long(msgpack_packer* pk, long d);
|
||||
static int msgpack_pack_long_long(msgpack_packer* pk, long long d);
|
||||
static int msgpack_pack_unsigned_short(msgpack_packer* pk, unsigned short d);
|
||||
static int msgpack_pack_unsigned_int(msgpack_packer* pk, unsigned int d);
|
||||
static int msgpack_pack_unsigned_long(msgpack_packer* pk, unsigned long d);
|
||||
static int msgpack_pack_unsigned_long_long(msgpack_packer* pk, unsigned long long d);
|
||||
|
||||
static int msgpack_pack_short(msgpack_pack_t* ctx, short d);
|
||||
static int msgpack_pack_int(msgpack_pack_t* ctx, int d);
|
||||
static int msgpack_pack_long(msgpack_pack_t* ctx, long d);
|
||||
static int msgpack_pack_long_long(msgpack_pack_t* ctx, long long d);
|
||||
static int msgpack_pack_unsigned_short(msgpack_pack_t* ctx, unsigned short d);
|
||||
static int msgpack_pack_unsigned_int(msgpack_pack_t* ctx, unsigned int d);
|
||||
static int msgpack_pack_unsigned_long(msgpack_pack_t* ctx, unsigned long d);
|
||||
static int msgpack_pack_unsigned_long_long(msgpack_pack_t* ctx, unsigned long long d);
|
||||
static int msgpack_pack_uint8(msgpack_packer* pk, uint8_t d);
|
||||
static int msgpack_pack_uint16(msgpack_packer* pk, uint16_t d);
|
||||
static int msgpack_pack_uint32(msgpack_packer* pk, uint32_t d);
|
||||
static int msgpack_pack_uint64(msgpack_packer* pk, uint64_t d);
|
||||
static int msgpack_pack_int8(msgpack_packer* pk, int8_t d);
|
||||
static int msgpack_pack_int16(msgpack_packer* pk, int16_t d);
|
||||
static int msgpack_pack_int32(msgpack_packer* pk, int32_t d);
|
||||
static int msgpack_pack_int64(msgpack_packer* pk, int64_t d);
|
||||
|
||||
static int msgpack_pack_uint8(msgpack_pack_t* ctx, uint8_t d);
|
||||
static int msgpack_pack_uint16(msgpack_pack_t* ctx, uint16_t d);
|
||||
static int msgpack_pack_uint32(msgpack_pack_t* ctx, uint32_t d);
|
||||
static int msgpack_pack_uint64(msgpack_pack_t* ctx, uint64_t d);
|
||||
static int msgpack_pack_int8(msgpack_pack_t* ctx, int8_t d);
|
||||
static int msgpack_pack_int16(msgpack_pack_t* ctx, int16_t d);
|
||||
static int msgpack_pack_int32(msgpack_pack_t* ctx, int32_t d);
|
||||
static int msgpack_pack_int64(msgpack_pack_t* ctx, int64_t d);
|
||||
static int msgpack_pack_float(msgpack_packer* pk, float d);
|
||||
static int msgpack_pack_double(msgpack_packer* pk, double d);
|
||||
|
||||
static int msgpack_pack_float(msgpack_pack_t* ctx, float d);
|
||||
static int msgpack_pack_double(msgpack_pack_t* ctx, double d);
|
||||
static int msgpack_pack_nil(msgpack_packer* pk);
|
||||
static int msgpack_pack_true(msgpack_packer* pk);
|
||||
static int msgpack_pack_false(msgpack_packer* pk);
|
||||
|
||||
static int msgpack_pack_nil(msgpack_pack_t* ctx);
|
||||
static int msgpack_pack_true(msgpack_pack_t* ctx);
|
||||
static int msgpack_pack_false(msgpack_pack_t* ctx);
|
||||
static int msgpack_pack_array(msgpack_packer* pk, unsigned int n);
|
||||
|
||||
static int msgpack_pack_array(msgpack_pack_t* ctx, unsigned int n);
|
||||
static int msgpack_pack_map(msgpack_packer* pk, unsigned int n);
|
||||
|
||||
static int msgpack_pack_map(msgpack_pack_t* ctx, unsigned int n);
|
||||
|
||||
static int msgpack_pack_raw(msgpack_pack_t* ctx, size_t l);
|
||||
static int msgpack_pack_raw_body(msgpack_pack_t* ctx, const void* b, size_t l);
|
||||
static int msgpack_pack_raw(msgpack_packer* pk, size_t l);
|
||||
static int msgpack_pack_raw_body(msgpack_packer* pk, const void* b, size_t l);
|
||||
|
||||
|
||||
|
||||
@ -81,30 +80,30 @@ static int msgpack_pack_raw_body(msgpack_pack_t* ctx, const void* b, size_t l);
|
||||
#define msgpack_pack_inline_func_cint(name) \
|
||||
inline int msgpack_pack ## name
|
||||
|
||||
#define msgpack_pack_user msgpack_pack_t*
|
||||
#define msgpack_pack_user msgpack_packer*
|
||||
|
||||
#define msgpack_pack_append_buffer(user, buf, len) \
|
||||
return (*(user)->callback)((user)->data, (const char*)buf, len)
|
||||
|
||||
#include "msgpack/pack_template.h"
|
||||
|
||||
inline void msgpack_pack_init(msgpack_pack_t* ctx, void* data, msgpack_pack_write_t callback)
|
||||
inline void msgpack_packer_init(msgpack_packer* pk, void* data, msgpack_packer_write callback)
|
||||
{
|
||||
ctx->data = data;
|
||||
ctx->callback = callback;
|
||||
pk->data = data;
|
||||
pk->callback = callback;
|
||||
}
|
||||
|
||||
inline msgpack_pack_t* msgpack_pack_new(void* data, msgpack_pack_write_t callback)
|
||||
inline msgpack_packer* msgpack_packer_new(void* data, msgpack_packer_write callback)
|
||||
{
|
||||
msgpack_pack_t* ctx = (msgpack_pack_t*)calloc(1, sizeof(msgpack_pack_t));
|
||||
if(!ctx) { return NULL; }
|
||||
msgpack_pack_init(ctx, data, callback);
|
||||
return ctx;
|
||||
msgpack_packer* pk = (msgpack_packer*)calloc(1, sizeof(msgpack_packer));
|
||||
if(!pk) { return NULL; }
|
||||
msgpack_packer_init(pk, data, callback);
|
||||
return pk;
|
||||
}
|
||||
|
||||
inline void msgpack_pack_free(msgpack_pack_t* ctx)
|
||||
inline void msgpack_packer_free(msgpack_packer* pk)
|
||||
{
|
||||
free(ctx);
|
||||
free(pk);
|
||||
}
|
||||
|
||||
|
||||
|
384
c/unpack.c
384
c/unpack.c
@ -20,125 +20,371 @@
|
||||
#include <stdlib.h>
|
||||
|
||||
|
||||
typedef struct {
|
||||
msgpack_zone* z;
|
||||
bool* referenced;
|
||||
} unpack_user;
|
||||
|
||||
|
||||
#define msgpack_unpack_struct(name) \
|
||||
struct template ## name
|
||||
|
||||
#define msgpack_unpack_func(ret, name) \
|
||||
ret template_func ## name
|
||||
ret template ## name
|
||||
|
||||
#define msgpack_unpack_callback(name) \
|
||||
template_callback ## name
|
||||
|
||||
#define msgpack_unpack_object void*
|
||||
#define msgpack_unpack_object msgpack_object
|
||||
|
||||
#define msgpack_unpack_user msgpack_unpack_t
|
||||
#define msgpack_unpack_user unpack_user
|
||||
|
||||
|
||||
struct template_context;
|
||||
typedef struct template_context template_context;
|
||||
|
||||
static void template_func_init(struct template_context* ctx);
|
||||
static void template_init(template_context* ctx);
|
||||
|
||||
static void* template_func_data(struct template_context* ctx);
|
||||
static msgpack_object template_data(template_context* ctx);
|
||||
|
||||
static int template_func_execute(struct template_context* ctx,
|
||||
static int template_execute(template_context* ctx,
|
||||
const char* data, size_t len, size_t* off);
|
||||
|
||||
|
||||
static inline void* template_callback_init(msgpack_unpack_t* x)
|
||||
{ return NULL; }
|
||||
static inline msgpack_object template_callback_root(unpack_user* u)
|
||||
{ msgpack_object o; return o; }
|
||||
|
||||
static inline void* template_callback_uint8(msgpack_unpack_t* x, uint8_t d)
|
||||
{ return x->callback.unpack_uint8(x->data, d); }
|
||||
static inline int template_callback_uint8(unpack_user* u, uint8_t d, msgpack_object* o)
|
||||
{ o->type = MSGPACK_OBJECT_POSITIVE_INTEGER; o->via.u64 = d; return 0; }
|
||||
|
||||
static inline void* template_callback_uint16(msgpack_unpack_t* x, uint16_t d)
|
||||
{ return x->callback.unpack_uint16(x->data, d); }
|
||||
static inline int template_callback_uint16(unpack_user* u, uint16_t d, msgpack_object* o)
|
||||
{ o->type = MSGPACK_OBJECT_POSITIVE_INTEGER; o->via.u64 = d; return 0; }
|
||||
|
||||
static inline void* template_callback_uint32(msgpack_unpack_t* x, uint32_t d)
|
||||
{ return x->callback.unpack_uint32(x->data, d); }
|
||||
static inline int template_callback_uint32(unpack_user* u, uint32_t d, msgpack_object* o)
|
||||
{ o->type = MSGPACK_OBJECT_POSITIVE_INTEGER; o->via.u64 = d; return 0; }
|
||||
|
||||
static inline void* template_callback_uint64(msgpack_unpack_t* x, uint64_t d)
|
||||
{ return x->callback.unpack_uint64(x->data, d); }
|
||||
static inline int template_callback_uint64(unpack_user* u, uint64_t d, msgpack_object* o)
|
||||
{ o->type = MSGPACK_OBJECT_POSITIVE_INTEGER; o->via.u64 = d; return 0; }
|
||||
|
||||
static inline void* template_callback_int8(msgpack_unpack_t* x, int8_t d)
|
||||
{ return x->callback.unpack_int8(x->data, d); }
|
||||
static inline int template_callback_int8(unpack_user* u, int8_t d, msgpack_object* o)
|
||||
{ if(d >= 0) { o->type = MSGPACK_OBJECT_POSITIVE_INTEGER; o->via.u64 = d; return 0; }
|
||||
else { o->type = MSGPACK_OBJECT_NEGATIVE_INTEGER; o->via.i64 = d; return 0; } }
|
||||
|
||||
static inline void* template_callback_int16(msgpack_unpack_t* x, int16_t d)
|
||||
{ return x->callback.unpack_int16(x->data, d); }
|
||||
static inline int template_callback_int16(unpack_user* u, int16_t d, msgpack_object* o)
|
||||
{ if(d >= 0) { o->type = MSGPACK_OBJECT_POSITIVE_INTEGER; o->via.u64 = d; return 0; }
|
||||
else { o->type = MSGPACK_OBJECT_NEGATIVE_INTEGER; o->via.i64 = d; return 0; } }
|
||||
|
||||
static inline void* template_callback_int32(msgpack_unpack_t* x, int32_t d)
|
||||
{ return x->callback.unpack_int32(x->data, d); }
|
||||
static inline int template_callback_int32(unpack_user* u, int32_t d, msgpack_object* o)
|
||||
{ if(d >= 0) { o->type = MSGPACK_OBJECT_POSITIVE_INTEGER; o->via.u64 = d; return 0; }
|
||||
else { o->type = MSGPACK_OBJECT_NEGATIVE_INTEGER; o->via.i64 = d; return 0; } }
|
||||
|
||||
static inline void* template_callback_int64(msgpack_unpack_t* x, int64_t d)
|
||||
{ return x->callback.unpack_int64(x->data, d); }
|
||||
static inline int template_callback_int64(unpack_user* u, int64_t d, msgpack_object* o)
|
||||
{ if(d >= 0) { o->type = MSGPACK_OBJECT_POSITIVE_INTEGER; o->via.u64 = d; return 0; }
|
||||
else { o->type = MSGPACK_OBJECT_NEGATIVE_INTEGER; o->via.i64 = d; return 0; } }
|
||||
|
||||
static inline void* template_callback_float(msgpack_unpack_t* x, float d)
|
||||
{ return x->callback.unpack_float(x->data, d); }
|
||||
static inline int template_callback_float(unpack_user* u, float d, msgpack_object* o)
|
||||
{ o->type = MSGPACK_OBJECT_DOUBLE; o->via.dec = d; return 0; }
|
||||
|
||||
static inline void* template_callback_double(msgpack_unpack_t* x, double d)
|
||||
{ return x->callback.unpack_double(x->data, d); }
|
||||
static inline int template_callback_double(unpack_user* u, double d, msgpack_object* o)
|
||||
{ o->type = MSGPACK_OBJECT_DOUBLE; o->via.dec = d; return 0; }
|
||||
|
||||
static inline void* template_callback_nil(msgpack_unpack_t* x)
|
||||
{ return x->callback.unpack_nil(x->data); }
|
||||
static inline int template_callback_nil(unpack_user* u, msgpack_object* o)
|
||||
{ o->type = MSGPACK_OBJECT_NIL; return 0; }
|
||||
|
||||
static inline void* template_callback_true(msgpack_unpack_t* x)
|
||||
{ return x->callback.unpack_true(x->data); }
|
||||
static inline int template_callback_true(unpack_user* u, msgpack_object* o)
|
||||
{ o->type = MSGPACK_OBJECT_BOOLEAN; o->via.boolean = true; return 0; }
|
||||
|
||||
static inline void* template_callback_false(msgpack_unpack_t* x)
|
||||
{ return x->callback.unpack_false(x->data); }
|
||||
static inline int template_callback_false(unpack_user* u, msgpack_object* o)
|
||||
{ o->type = MSGPACK_OBJECT_BOOLEAN; o->via.boolean = false; return 0; }
|
||||
|
||||
static inline void* template_callback_array(msgpack_unpack_t* x, unsigned int n)
|
||||
{ return x->callback.unpack_array(x->data, n); }
|
||||
static inline int template_callback_array(unpack_user* u, unsigned int n, msgpack_object* o)
|
||||
{
|
||||
o->type = MSGPACK_OBJECT_ARRAY;
|
||||
o->via.array.size = 0;
|
||||
o->via.array.ptr = msgpack_zone_malloc(u->z, n*sizeof(msgpack_object));
|
||||
if(o->via.array.ptr == NULL) { return -1; }
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline void template_callback_array_item(msgpack_unpack_t* x, void** c, void* o)
|
||||
{ x->callback.unpack_array_item(x->data, *c, o); }
|
||||
static inline int template_callback_array_item(unpack_user* u, msgpack_object* c, msgpack_object o)
|
||||
{ c->via.array.ptr[c->via.array.size++] = o; return 0; }
|
||||
|
||||
static inline void* template_callback_map(msgpack_unpack_t* x, unsigned int n)
|
||||
{ return x->callback.unpack_map(x->data, n); }
|
||||
static inline int template_callback_map(unpack_user* u, unsigned int n, msgpack_object* o)
|
||||
{
|
||||
o->type = MSGPACK_OBJECT_MAP;
|
||||
o->via.map.size = 0;
|
||||
o->via.map.ptr = (msgpack_object_kv*)msgpack_zone_malloc(u->z, n*sizeof(msgpack_object_kv));
|
||||
if(o->via.map.ptr == NULL) { return -1; }
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline void template_callback_map_item(msgpack_unpack_t* x, void** c, void* k, void* v)
|
||||
{ x->callback.unpack_map_item(x->data, *c, k, v); }
|
||||
|
||||
static inline void* template_callback_raw(msgpack_unpack_t* x, const char* b, const char* p, unsigned int l)
|
||||
{ return x->callback.unpack_raw(x->data, b, p, l); }
|
||||
static inline int template_callback_map_item(unpack_user* u, msgpack_object* c, msgpack_object k, msgpack_object v)
|
||||
{
|
||||
c->via.map.ptr[c->via.map.size].key = k;
|
||||
c->via.map.ptr[c->via.map.size].val = v;
|
||||
++c->via.map.size;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int template_callback_raw(unpack_user* u, const char* b, const char* p, unsigned int l, msgpack_object* o)
|
||||
{
|
||||
o->type = MSGPACK_OBJECT_RAW;
|
||||
o->via.raw.ptr = p;
|
||||
o->via.raw.size = l;
|
||||
*u->referenced = true;
|
||||
return 0;
|
||||
}
|
||||
|
||||
#include "msgpack/unpack_template.h"
|
||||
|
||||
|
||||
msgpack_unpack_t* msgpack_unpack_new(void* data, msgpack_unpack_callback* callback)
|
||||
#define CTX_CAST(m) ((template_context*)(m))
|
||||
|
||||
|
||||
static const size_t COUNTER_SIZE = sizeof(unsigned int);
|
||||
|
||||
static inline void init_count(void* buf)
|
||||
{
|
||||
struct template_context* ctx;
|
||||
ctx = (struct template_context*)calloc(1, sizeof(struct template_context));
|
||||
if(ctx == NULL) { return NULL; }
|
||||
template_func_init(ctx);
|
||||
((msgpack_unpack_t*)ctx)->data = data;
|
||||
((msgpack_unpack_t*)ctx)->callback = *callback;
|
||||
return (msgpack_unpack_t*)ctx;
|
||||
*(volatile unsigned int*)buf = 1;
|
||||
}
|
||||
|
||||
void msgpack_unpack_free(msgpack_unpack_t* ctx)
|
||||
static inline void decl_count(void* buf)
|
||||
{
|
||||
free((struct template_context*)ctx);
|
||||
//if(--*(unsigned int*)buf == 0) {
|
||||
if(__sync_sub_and_fetch((unsigned int*)buf, 1) == 0) {
|
||||
free(buf);
|
||||
}
|
||||
}
|
||||
|
||||
void* msgpack_unpack_data(msgpack_unpack_t* ctx)
|
||||
static inline void incr_count(void* buf)
|
||||
{
|
||||
return template_func_data((struct template_context*)ctx);
|
||||
//++*(unsigned int*)buf;
|
||||
__sync_add_and_fetch((unsigned int*)buf, 1);
|
||||
}
|
||||
|
||||
void msgpack_unpack_reset(msgpack_unpack_t* ctx)
|
||||
static inline unsigned int get_count(void* buf)
|
||||
{
|
||||
msgpack_unpack_t x = ((struct template_context*)ctx)->user;
|
||||
template_func_init((struct template_context*)ctx);
|
||||
((struct template_context*)ctx)->user = x;
|
||||
}
|
||||
|
||||
int msgpack_unpack_execute(msgpack_unpack_t* ctx,
|
||||
const char* data, size_t len, size_t* off)
|
||||
{
|
||||
return template_func_execute(
|
||||
(struct template_context*)ctx,
|
||||
data, len, off);
|
||||
return *(volatile unsigned int*)buf;
|
||||
}
|
||||
|
||||
|
||||
|
||||
bool msgpack_unpacker_init(msgpack_unpacker* mpac, size_t initial_buffer_size)
|
||||
{
|
||||
if(initial_buffer_size < COUNTER_SIZE) {
|
||||
initial_buffer_size = COUNTER_SIZE;
|
||||
}
|
||||
|
||||
char* buf = (char*)malloc(initial_buffer_size);
|
||||
if(buf == NULL) {
|
||||
return false;
|
||||
}
|
||||
|
||||
void* ctx = malloc(sizeof(template_context));
|
||||
if(ctx == NULL) {
|
||||
free(buf);
|
||||
return false;
|
||||
}
|
||||
|
||||
msgpack_zone* z = msgpack_zone_new(MSGPACK_ZONE_CHUNK_SIZE);
|
||||
if(z == NULL) {
|
||||
free(ctx);
|
||||
free(buf);
|
||||
return false;
|
||||
}
|
||||
|
||||
mpac->buf = buf;
|
||||
mpac->used = COUNTER_SIZE;
|
||||
mpac->free = initial_buffer_size - mpac->used;
|
||||
mpac->off = COUNTER_SIZE;
|
||||
mpac->initial_buffer_size = initial_buffer_size;
|
||||
mpac->z = z;
|
||||
mpac->referenced = false;
|
||||
mpac->ctx = ctx;
|
||||
|
||||
init_count(mpac->buf);
|
||||
|
||||
template_init(CTX_CAST(mpac->ctx));
|
||||
CTX_CAST(mpac->ctx)->user.z = mpac->z;
|
||||
CTX_CAST(mpac->ctx)->user.referenced = &mpac->referenced;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void msgpack_unpacker_destroy(msgpack_unpacker* mpac)
|
||||
{
|
||||
msgpack_zone_free(mpac->z);
|
||||
free(mpac->ctx);
|
||||
decl_count(mpac->buf);
|
||||
}
|
||||
|
||||
|
||||
msgpack_unpacker* msgpack_unpacker_new(size_t initial_buffer_size)
|
||||
{
|
||||
msgpack_unpacker* mpac = (msgpack_unpacker*)malloc(sizeof(msgpack_unpacker));
|
||||
if(mpac == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if(!msgpack_unpacker_init(mpac, initial_buffer_size)) {
|
||||
free(mpac);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return mpac;
|
||||
}
|
||||
|
||||
void msgpack_unpacker_free(msgpack_unpacker* mpac)
|
||||
{
|
||||
msgpack_unpacker_destroy(mpac);
|
||||
free(mpac);
|
||||
}
|
||||
|
||||
|
||||
bool msgpack_unpacker_expand_buffer(msgpack_unpacker* mpac, size_t size)
|
||||
{
|
||||
if(mpac->used == mpac->off && get_count(mpac->buf) == 1 && !mpac->referenced) {
|
||||
// rewind buffer
|
||||
mpac->free += mpac->used - COUNTER_SIZE;
|
||||
mpac->used = COUNTER_SIZE;
|
||||
mpac->off = COUNTER_SIZE;
|
||||
|
||||
if(mpac->free >= size) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
if(mpac->off == COUNTER_SIZE) {
|
||||
size_t next_size = (mpac->used + mpac->free) * 2; // include COUNTER_SIZE
|
||||
while(next_size < size + mpac->used) {
|
||||
next_size *= 2;
|
||||
}
|
||||
|
||||
char* tmp = (char*)realloc(mpac->buf, next_size);
|
||||
if(tmp == NULL) {
|
||||
return false;
|
||||
}
|
||||
|
||||
mpac->buf = tmp;
|
||||
mpac->free = next_size - mpac->used;
|
||||
|
||||
} else {
|
||||
size_t next_size = mpac->initial_buffer_size; // include COUNTER_SIZE
|
||||
size_t not_parsed = mpac->used - mpac->off;
|
||||
while(next_size < size + not_parsed + COUNTER_SIZE) {
|
||||
next_size *= 2;
|
||||
}
|
||||
|
||||
char* tmp = (char*)malloc(next_size);
|
||||
if(tmp == NULL) {
|
||||
return false;
|
||||
}
|
||||
|
||||
init_count(tmp);
|
||||
|
||||
if(mpac->referenced) {
|
||||
if(!msgpack_zone_push_finalizer(mpac->z, decl_count, mpac->buf)) {
|
||||
free(tmp);
|
||||
return false;
|
||||
}
|
||||
mpac->referenced = false;
|
||||
} else {
|
||||
decl_count(mpac->buf);
|
||||
}
|
||||
|
||||
memcpy(tmp+COUNTER_SIZE, mpac->buf+mpac->off, not_parsed);
|
||||
|
||||
mpac->buf = tmp;
|
||||
mpac->used = not_parsed + COUNTER_SIZE;
|
||||
mpac->free = next_size - mpac->used;
|
||||
mpac->off = COUNTER_SIZE;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
int msgpack_unpacker_execute(msgpack_unpacker* mpac)
|
||||
{
|
||||
return template_execute(CTX_CAST(mpac->ctx),
|
||||
mpac->buf, mpac->used, &mpac->off);
|
||||
}
|
||||
|
||||
msgpack_object msgpack_unpacker_data(msgpack_unpacker* mpac)
|
||||
{
|
||||
return template_data(CTX_CAST(mpac->ctx));
|
||||
}
|
||||
|
||||
msgpack_zone* msgpack_unpacker_release_zone(msgpack_unpacker* mpac)
|
||||
{
|
||||
if(!msgpack_unpacker_flush_zone(mpac)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
msgpack_zone* z = msgpack_zone_new(MSGPACK_ZONE_CHUNK_SIZE);
|
||||
if(z == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
msgpack_zone* old = mpac->z;
|
||||
mpac->z = z;
|
||||
|
||||
return old;
|
||||
}
|
||||
|
||||
bool msgpack_unpacker_flush_zone(msgpack_unpacker* mpac)
|
||||
{
|
||||
if(mpac->referenced) {
|
||||
if(!msgpack_zone_push_finalizer(mpac->z, decl_count, mpac->buf)) {
|
||||
return false;
|
||||
}
|
||||
mpac->referenced = false;
|
||||
|
||||
incr_count(mpac->buf);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void msgpack_unpacker_reset(msgpack_unpacker* mpac)
|
||||
{
|
||||
msgpack_zone* z = mpac->z;
|
||||
template_init(CTX_CAST(mpac->ctx));
|
||||
CTX_CAST(mpac->ctx)->user.z = z;
|
||||
CTX_CAST(mpac->ctx)->user.referenced = &mpac->referenced;
|
||||
}
|
||||
|
||||
|
||||
msgpack_unpack_return
|
||||
msgpack_unpack(const char* data, size_t len, size_t* off,
|
||||
msgpack_zone* z, msgpack_object* result)
|
||||
{
|
||||
template_context ctx;
|
||||
template_init(&ctx);
|
||||
|
||||
bool referenced = false;
|
||||
ctx.user.z = z;
|
||||
ctx.user.referenced = &referenced;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
if(off != NULL) { *off = noff; }
|
||||
|
||||
if(ret == 0) {
|
||||
return MSGPACK_UNPACK_CONTINUE;
|
||||
}
|
||||
|
||||
*result = template_data(&ctx);
|
||||
|
||||
if(noff < len) {
|
||||
return MSGPACK_UNPACK_EXTRA_BYTES;
|
||||
}
|
||||
|
||||
return MSGPACK_UNPACK_SUCCESS;
|
||||
}
|
||||
|
||||
|
103
c/unpack.h
103
c/unpack.h
@ -15,9 +15,11 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
#ifndef MSGPACK_UNPACK_H__
|
||||
#define MSGPACK_UNPACK_H__
|
||||
#ifndef msgpack_unpacker_H__
|
||||
#define msgpack_unpacker_H__
|
||||
|
||||
#include "msgpack/zone.h"
|
||||
#include "msgpack/object.h"
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
|
||||
@ -26,39 +28,76 @@ extern "C" {
|
||||
#endif
|
||||
|
||||
|
||||
typedef struct {
|
||||
void* (*unpack_uint8)(void* data, uint8_t d);
|
||||
void* (*unpack_uint16)(void* data, uint16_t d);
|
||||
void* (*unpack_uint32)(void* data, uint32_t d);
|
||||
void* (*unpack_uint64)(void* data, uint64_t d);
|
||||
void* (*unpack_int8)(void* data, int8_t d);
|
||||
void* (*unpack_int16)(void* data, int16_t d);
|
||||
void* (*unpack_int32)(void* data, int32_t d);
|
||||
void* (*unpack_int64)(void* data, int64_t d);
|
||||
void* (*unpack_float)(void* data, float d);
|
||||
void* (*unpack_double)(void* data, double d);
|
||||
void* (*unpack_nil)(void* data);
|
||||
void* (*unpack_true)(void* data);
|
||||
void* (*unpack_false)(void* data);
|
||||
void* (*unpack_array)(void* data, unsigned int n);
|
||||
void (*unpack_array_item)(void* data, void* c, void* o);
|
||||
void* (*unpack_map)(void* data, unsigned int n);
|
||||
void (*unpack_map_item)(void* data, void* c, void* k, void* v);
|
||||
void* (*unpack_raw)(void* data, const char* b, const char* p, unsigned int l);
|
||||
} msgpack_unpack_callback;
|
||||
typedef struct msgpack_unpacker {
|
||||
char* buf;
|
||||
size_t used;
|
||||
size_t free;
|
||||
size_t off;
|
||||
msgpack_zone* z;
|
||||
bool referenced;
|
||||
size_t initial_buffer_size;
|
||||
void* ctx;
|
||||
} msgpack_unpacker;
|
||||
|
||||
typedef struct {
|
||||
void* data;
|
||||
msgpack_unpack_callback callback;
|
||||
} msgpack_unpack_t;
|
||||
|
||||
msgpack_unpack_t* msgpack_unpack_new(void* data, msgpack_unpack_callback* callback);
|
||||
void msgpack_unpack_free(msgpack_unpack_t* ctx);
|
||||
bool msgpack_unpacker_init(msgpack_unpacker* mpac, size_t initial_buffer_size);
|
||||
void msgpack_unpacker_destroy(msgpack_unpacker* mpac);
|
||||
|
||||
int msgpack_unpack_execute(msgpack_unpack_t* ctx,
|
||||
const char* data, size_t len, size_t* off);
|
||||
void* msgpack_unpack_data(msgpack_unpack_t* ctx);
|
||||
void msgpack_unpack_reset(msgpack_unpack_t* ctx);
|
||||
msgpack_unpacker* msgpack_unpacker_new(size_t initial_buffer_size);
|
||||
void msgpack_unpacker_free(msgpack_unpacker* mpac);
|
||||
|
||||
static inline bool msgpack_unpacker_reserve_buffer(msgpack_unpacker* mpac, size_t size);
|
||||
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);
|
||||
|
||||
|
||||
int msgpack_unpacker_execute(msgpack_unpacker* mpac);
|
||||
|
||||
msgpack_object msgpack_unpacker_data(msgpack_unpacker* mpac);
|
||||
|
||||
msgpack_zone* msgpack_unpacker_release_zone(msgpack_unpacker* mpac);
|
||||
|
||||
void msgpack_unpacker_reset(msgpack_unpacker* mpac);
|
||||
|
||||
|
||||
typedef enum {
|
||||
MSGPACK_UNPACK_SUCCESS = 2,
|
||||
MSGPACK_UNPACK_EXTRA_BYTES = 1,
|
||||
MSGPACK_UNPACK_CONTINUE = 0,
|
||||
MSGPACK_UNPACK_PARSE_ERROR = -1,
|
||||
} msgpack_unpack_return;
|
||||
|
||||
msgpack_unpack_return
|
||||
msgpack_unpack(const char* data, size_t len, size_t* off,
|
||||
msgpack_zone* z, msgpack_object* result);
|
||||
|
||||
|
||||
bool msgpack_unpacker_flush_zone(msgpack_unpacker* mpac);
|
||||
|
||||
bool msgpack_unpacker_expand_buffer(msgpack_unpacker* mpac, size_t size);
|
||||
|
||||
bool msgpack_unpacker_reserve_buffer(msgpack_unpacker* mpac, size_t size)
|
||||
{
|
||||
if(mpac->free >= size) { return true; }
|
||||
return msgpack_unpacker_expand_buffer(mpac, size);
|
||||
}
|
||||
|
||||
char* msgpack_unpacker_buffer(msgpack_unpacker* mpac)
|
||||
{
|
||||
return mpac->buf + mpac->used;
|
||||
}
|
||||
|
||||
size_t msgpack_unpacker_buffer_capacity(const msgpack_unpacker* mpac)
|
||||
{
|
||||
return mpac->free;
|
||||
}
|
||||
|
||||
void msgpack_unpacker_buffer_consumed(msgpack_unpacker* mpac, size_t size)
|
||||
{
|
||||
mpac->used += size;
|
||||
mpac->free -= size;
|
||||
}
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
253
c/zone.c
253
c/zone.c
@ -19,85 +19,214 @@
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
typedef struct {
|
||||
size_t free;
|
||||
void* ptr;
|
||||
void* alloc;
|
||||
} msgpack_zone_chunk;
|
||||
|
||||
struct _msgpack_zone {
|
||||
msgpack_zone_chunk* array;
|
||||
size_t ntail;
|
||||
size_t usable;
|
||||
};
|
||||
|
||||
msgpack_zone* msgpack_zone_new()
|
||||
static inline bool init_chunk_array(msgpack_zone_chunk_array* ca, size_t chunk_size)
|
||||
{
|
||||
return calloc(1, sizeof(msgpack_zone));
|
||||
}
|
||||
// glibcは72バイト以下のmallocが高速
|
||||
const size_t nfirst = (sizeof(msgpack_zone_chunk) < 72/2) ?
|
||||
72 / sizeof(msgpack_zone_chunk) : 8;
|
||||
|
||||
void msgpack_zone_free(msgpack_zone* z)
|
||||
{
|
||||
if(z->array) {
|
||||
size_t i;
|
||||
for(i=0; i <= z->ntail; ++i) {
|
||||
free(z->array[i].alloc);
|
||||
}
|
||||
msgpack_zone_chunk* array = (msgpack_zone_chunk*)malloc(
|
||||
sizeof(msgpack_zone_chunk) * nfirst);
|
||||
if(!array) {
|
||||
return false;
|
||||
}
|
||||
free(z);
|
||||
|
||||
const size_t sz = chunk_size;
|
||||
|
||||
char* ptr = (char*)malloc(sz);
|
||||
if(!ptr) {
|
||||
free(array);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ca->tail = array;
|
||||
ca->end = array + nfirst;
|
||||
ca->array = array;
|
||||
|
||||
array[0].free = sz;
|
||||
array[0].ptr = ptr;
|
||||
array[0].alloc = ptr;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
void* msgpack_zone_malloc(msgpack_zone* z, size_t size)
|
||||
static inline void destroy_chunk_array(msgpack_zone_chunk_array* ca)
|
||||
{
|
||||
if(!z->array) {
|
||||
const size_t n = (sizeof(msgpack_zone_chunk) < 72/2) ?
|
||||
72 / sizeof(msgpack_zone_chunk) : 8;
|
||||
msgpack_zone_chunk* array =
|
||||
(msgpack_zone_chunk*)malloc(sizeof(msgpack_zone_chunk) * n);
|
||||
if(!array) { return NULL; }
|
||||
msgpack_zone_chunk* chunk = ca->array;
|
||||
for(; chunk != ca->tail+1; ++chunk) {
|
||||
free(chunk->alloc);
|
||||
}
|
||||
free(ca->array);
|
||||
}
|
||||
|
||||
size_t sz = 2048; /* FIXME chunk_size */
|
||||
while(sz < size) { sz *= 2; }
|
||||
char* p = (char*)malloc(sz);
|
||||
if(!p) {
|
||||
free(array);
|
||||
void* msgpack_zone_malloc(msgpack_zone* zone, size_t size)
|
||||
{
|
||||
msgpack_zone_chunk_array* const ca = &zone->chunk_array;
|
||||
|
||||
msgpack_zone_chunk* chunk = ca->tail;
|
||||
|
||||
if(chunk->free > size) {
|
||||
// chunkに空き容量がある
|
||||
// 空き容量を消費して返す
|
||||
|
||||
char* ptr = chunk->ptr;
|
||||
|
||||
chunk->ptr += size;
|
||||
chunk->free -= size;
|
||||
|
||||
return ptr;
|
||||
}
|
||||
|
||||
chunk = ++ca->tail;
|
||||
|
||||
if(chunk == ca->end) {
|
||||
// ca->arrayに空きがない
|
||||
// ca->arrayを拡張する
|
||||
|
||||
const size_t nused = ca->end - ca->array;
|
||||
const size_t nnext = (ca->end - ca->array) * 2;
|
||||
|
||||
chunk = (msgpack_zone_chunk*)realloc(ca->array,
|
||||
sizeof(msgpack_zone_chunk) * nnext);
|
||||
if(!chunk) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
z->array = array;
|
||||
z->usable = n - 1;
|
||||
array[0].free = sz - size;
|
||||
array[0].ptr = p + size;
|
||||
array[0].alloc = p;
|
||||
return p;
|
||||
ca->array = chunk;
|
||||
ca->end = chunk + nnext;
|
||||
chunk = ca->tail = chunk + nused;
|
||||
}
|
||||
|
||||
if(z->array[z->ntail].free > size) {
|
||||
char* p = (char*)z->array[z->ntail].ptr;
|
||||
z->array[z->ntail].ptr = p + size;
|
||||
z->array[z->ntail].free -= size;
|
||||
return p;
|
||||
size_t sz = zone->chunk_size;
|
||||
|
||||
while(sz < size) {
|
||||
sz *= 2;
|
||||
}
|
||||
|
||||
if(z->usable <= z->ntail) {
|
||||
const size_t n = (z->usable + 1) * 2;
|
||||
msgpack_zone_chunk* tmp =
|
||||
(msgpack_zone_chunk*)realloc(z->array, sizeof(msgpack_zone_chunk) * n);
|
||||
if(!tmp) { return NULL; }
|
||||
z->array = tmp;
|
||||
z->usable = n - 1;
|
||||
char* ptr = (char*)malloc(sz);
|
||||
if(!ptr) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
size_t sz = 2048; /* FIXME chunk_size */
|
||||
while(sz < size) { sz *= 2; }
|
||||
char* p = (char*)malloc(sz);
|
||||
if(!p) { return NULL; }
|
||||
chunk->free = sz - size;
|
||||
chunk->ptr = ptr + size;
|
||||
chunk->alloc = ptr;
|
||||
|
||||
++z->ntail;
|
||||
z->array[z->ntail].free = sz - size;
|
||||
z->array[z->ntail].ptr = p + size;
|
||||
z->array[z->ntail].alloc = p;
|
||||
return p;
|
||||
return ptr;
|
||||
}
|
||||
|
||||
|
||||
static inline void init_finalizer_array(msgpack_zone_finalizer_array* fa)
|
||||
{
|
||||
fa->tail = NULL;
|
||||
fa->end = NULL;
|
||||
fa->array = NULL;
|
||||
}
|
||||
|
||||
static inline void destroy_finalizer_array(msgpack_zone_finalizer_array* fa)
|
||||
{
|
||||
// 逆順に呼び出し
|
||||
msgpack_zone_finalizer* fin = fa->tail;
|
||||
for(; fin != fa->array; --fin) {
|
||||
(*(fin-1)->func)((fin-1)->data);
|
||||
}
|
||||
free(fa->array);
|
||||
}
|
||||
|
||||
bool msgpack_zone_push_finalizer(msgpack_zone* zone,
|
||||
void (*func)(void* data), void* data)
|
||||
{
|
||||
msgpack_zone_finalizer_array* const fa = &zone->finalizer_array;
|
||||
|
||||
msgpack_zone_finalizer* fin = fa->tail;
|
||||
|
||||
if(fin == fa->end) {
|
||||
// fa->arrayに空きがない
|
||||
// fa->arrayを拡張する
|
||||
|
||||
size_t nnext;
|
||||
const size_t nused = fa->end - fa->array;
|
||||
|
||||
if(nused == 0) {
|
||||
// 初回の呼び出し:fa->tail == fa->end == fa->array == NULL
|
||||
|
||||
// glibcは72バイト以下のmallocが高速
|
||||
nnext = (sizeof(msgpack_zone_finalizer) < 72/2) ?
|
||||
72 / sizeof(msgpack_zone_finalizer) : 8;
|
||||
|
||||
} else {
|
||||
nnext = (fa->end - fa->array) * 2;
|
||||
}
|
||||
|
||||
fin = (msgpack_zone_finalizer*)realloc(fa->array,
|
||||
sizeof(msgpack_zone_finalizer) * nnext);
|
||||
if(!fin) {
|
||||
return false;
|
||||
}
|
||||
|
||||
fa->array = fin;
|
||||
fa->end = fin + nnext;
|
||||
fin = fa->tail = fin + nused;
|
||||
}
|
||||
|
||||
fin->func = func;
|
||||
fin->data = data;
|
||||
|
||||
++fa->tail;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool msgpack_zone_is_empty(msgpack_zone* zone)
|
||||
{
|
||||
msgpack_zone_chunk_array* const ca = &zone->chunk_array;
|
||||
msgpack_zone_finalizer_array* const fa = &zone->finalizer_array;
|
||||
return ca->array[0].ptr == ca->array[0].alloc &&
|
||||
ca->tail == ca->array &&
|
||||
fa->tail == fa->array;
|
||||
}
|
||||
|
||||
|
||||
bool msgpack_zone_init(msgpack_zone* zone, size_t chunk_size)
|
||||
{
|
||||
zone->chunk_size = chunk_size;
|
||||
|
||||
if(!init_chunk_array(&zone->chunk_array, chunk_size)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
init_finalizer_array(&zone->finalizer_array);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void msgpack_zone_destroy(msgpack_zone* zone)
|
||||
{
|
||||
destroy_finalizer_array(&zone->finalizer_array);
|
||||
destroy_chunk_array(&zone->chunk_array);
|
||||
}
|
||||
|
||||
|
||||
msgpack_zone* msgpack_zone_new(size_t chunk_size)
|
||||
{
|
||||
msgpack_zone* zone = (msgpack_zone*)malloc(sizeof(msgpack_zone));
|
||||
if(zone == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if(!msgpack_zone_init(zone, chunk_size)) {
|
||||
free(zone);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return zone;
|
||||
}
|
||||
|
||||
void msgpack_zone_free(msgpack_zone* zone)
|
||||
{
|
||||
msgpack_zone_destroy(zone);
|
||||
free(zone);
|
||||
}
|
||||
|
||||
|
49
c/zone.h
49
c/zone.h
@ -19,19 +19,58 @@
|
||||
#define MSGPACK_ZONE_H__
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
|
||||
struct _msgpack_zone;
|
||||
typedef struct _msgpack_zone msgpack_zone;
|
||||
typedef struct msgpack_zone_chunk {
|
||||
size_t free;
|
||||
char* ptr;
|
||||
void* alloc;
|
||||
} msgpack_zone_chunk;
|
||||
|
||||
msgpack_zone* msgpack_zone_new();
|
||||
void msgpack_zone_free(msgpack_zone* z);
|
||||
typedef struct msgpack_zone_finalizer {
|
||||
void (*func)(void* data);
|
||||
void* data;
|
||||
} msgpack_zone_finalizer;
|
||||
|
||||
void* msgpack_zone_malloc(msgpack_zone* z, size_t size);
|
||||
typedef struct msgpack_zone_chunk_array {
|
||||
msgpack_zone_chunk* tail;
|
||||
msgpack_zone_chunk* end;
|
||||
msgpack_zone_chunk* array;
|
||||
} msgpack_zone_chunk_array;
|
||||
|
||||
typedef struct msgpack_zone_finalizer_array {
|
||||
msgpack_zone_finalizer* tail;
|
||||
msgpack_zone_finalizer* end;
|
||||
msgpack_zone_finalizer* array;
|
||||
} msgpack_zone_finalizer_array;
|
||||
|
||||
typedef struct msgpack_zone {
|
||||
msgpack_zone_chunk_array chunk_array;
|
||||
msgpack_zone_finalizer_array finalizer_array;
|
||||
size_t chunk_size;
|
||||
} msgpack_zone;
|
||||
|
||||
#ifndef MSGPACK_ZONE_CHUNK_SIZE
|
||||
#define MSGPACK_ZONE_CHUNK_SIZE 2048
|
||||
#endif
|
||||
|
||||
bool msgpack_zone_init(msgpack_zone* zone, size_t chunk_size);
|
||||
void msgpack_zone_destroy(msgpack_zone* zone);
|
||||
|
||||
msgpack_zone* msgpack_zone_new(size_t chunk_size);
|
||||
void msgpack_zone_free(msgpack_zone* zone);
|
||||
|
||||
void* msgpack_zone_malloc(msgpack_zone* zone, size_t size);
|
||||
|
||||
bool msgpack_zone_push_finalizer(msgpack_zone* zone,
|
||||
void (*func)(void* data), void* data);
|
||||
|
||||
bool msgpack_zone_is_empty(msgpack_zone* zone);
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
38
configure.in
38
configure.in
@ -2,8 +2,42 @@ AC_INIT(msgpack/unpack_template.h)
|
||||
AM_INIT_AUTOMAKE(msgpack, 0.3.0)
|
||||
AC_CONFIG_HEADER(config.h)
|
||||
|
||||
AC_SUBST(CFLAGS)
|
||||
if test "" = "$CFLAGS"; then
|
||||
CFLAGS="-g -O4"
|
||||
fi
|
||||
|
||||
AC_PROG_CC
|
||||
|
||||
CFLAGS="-O4 -Wall $CFLAGS -I.."
|
||||
|
||||
|
||||
AC_MSG_CHECKING([if c++ api is enabled])
|
||||
AC_ARG_ENABLE(cxx,
|
||||
AS_HELP_STRING([--disable-cxx],
|
||||
[don't build c++ api.]) )
|
||||
AC_MSG_RESULT($enable_cxx)
|
||||
if test "$enable_cxx" != "no"; then
|
||||
AC_SUBST(CXXFLAGS)
|
||||
if test "" = "$CXXFLAGS"; then
|
||||
CXXFLAGS="-g -O4"
|
||||
fi
|
||||
|
||||
AC_CHECK_PROG(ERB, erb, erb)
|
||||
if test "x$ERB" = x; then
|
||||
AC_MSG_ERROR([cannot find erb. Ruby is needed to build.])
|
||||
fi
|
||||
fi
|
||||
|
||||
# FIXME
|
||||
AC_PROG_CXX
|
||||
|
||||
CXXFLAGS="-O4 -Wall $CXXFLAGS -I.."
|
||||
|
||||
|
||||
AM_CONDITIONAL(ENABLE_CXX, test "$enable_cxx" != "no")
|
||||
|
||||
AC_PROG_LIBTOOL
|
||||
|
||||
AC_CONFIG_SUBDIRS([c cpp])
|
||||
AC_OUTPUT([Makefile])
|
||||
AC_OUTPUT([Makefile c/Makefile cpp/Makefile])
|
||||
|
||||
|
@ -1 +0,0 @@
|
||||
FURUHASHI Sadayuki <frsyuki _at_ users.sourceforge.jp>
|
14
cpp/COPYING
14
cpp/COPYING
@ -1,14 +0,0 @@
|
||||
Copyright (C) 2008-2009 FURUHASHI Sadayuki
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
|
@ -1,9 +1,7 @@
|
||||
lib_LTLIBRARIES = libmsgpack.la
|
||||
|
||||
libmsgpack_la_SOURCES = \
|
||||
object.cpp \
|
||||
unpack.cpp \
|
||||
zone.cpp
|
||||
object.cpp
|
||||
|
||||
nobase_include_HEADERS = \
|
||||
msgpack.hpp \
|
||||
@ -28,7 +26,6 @@ noinst_HEADERS = \
|
||||
# FIXME
|
||||
object.lo: msgpack/type/tuple.hpp
|
||||
unpack.lo: msgpack/type/tuple.hpp msgpack/zone.hpp
|
||||
zone.lo: msgpack/type/tuple.hpp msgpack/zone.hpp
|
||||
|
||||
msgpack/type/tuple.hpp: msgpack/type/tuple.hpp.erb
|
||||
$(ERB) $< > $@.tmp
|
||||
@ -42,6 +39,8 @@ MOSTLYCLEANFILES = \
|
||||
msgpack/type/tuple.hpp \
|
||||
msgpack/zone.hpp
|
||||
|
||||
libmsgpack_la_LIBADD = -L../c -lmsgpackc
|
||||
|
||||
# -version-info CURRENT:REVISION:AGE
|
||||
libmsgpack_la_LDFLAGS = -version-info 1:0:0
|
||||
|
||||
|
21
cpp/README
21
cpp/README
@ -1,21 +0,0 @@
|
||||
MessagePack for C++
|
||||
-------------------
|
||||
MessagePack is a binary-based efficient data interchange format.
|
||||
|
||||
|
||||
|
||||
Copyright (C) 2008-2009 FURUHASHI Sadayuki
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
|
||||
|
@ -1,3 +0,0 @@
|
||||
#!/bin/sh
|
||||
NO_NEST=1
|
||||
. ../bootstrap
|
@ -1,23 +0,0 @@
|
||||
AC_INIT(object.cpp)
|
||||
AM_INIT_AUTOMAKE(msgpack, 0.1.0)
|
||||
AC_CONFIG_HEADER(config.h)
|
||||
|
||||
AC_SUBST(CXXFLAGS)
|
||||
if test "" = "$CXXFLAGS"; then
|
||||
CXXFLAGS="-g -O4"
|
||||
fi
|
||||
|
||||
AC_PROG_CXX
|
||||
AC_PROG_LIBTOOL
|
||||
|
||||
AC_CHECK_PROG(ERB, erb, erb)
|
||||
if test "x$ERB" = x; then
|
||||
AC_MSG_ERROR([cannot find erb. Ruby is needed to build.])
|
||||
fi
|
||||
|
||||
AC_CHECK_LIB(stdc++, main)
|
||||
|
||||
CXXFLAGS="-O4 -Wall $CXXFLAGS -I.."
|
||||
|
||||
AC_OUTPUT([Makefile])
|
||||
|
@ -1,7 +1,7 @@
|
||||
//
|
||||
// MessagePack for C++ static resolution routine
|
||||
//
|
||||
// Copyright (C) 2008 FURUHASHI Sadayuki
|
||||
// Copyright (C) 2008-2009 FURUHASHI Sadayuki
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
|
@ -1,7 +1,7 @@
|
||||
//
|
||||
// MessagePack for C++ static resolution routine
|
||||
//
|
||||
// Copyright (C) 2008 FURUHASHI Sadayuki
|
||||
// Copyright (C) 2008-2009 FURUHASHI Sadayuki
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
|
@ -1,7 +1,7 @@
|
||||
//
|
||||
// MessagePack for C++ static resolution routine
|
||||
//
|
||||
// Copyright (C) 2008 FURUHASHI Sadayuki
|
||||
// Copyright (C) 2008-2009 FURUHASHI Sadayuki
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
|
@ -1,7 +1,7 @@
|
||||
//
|
||||
// MessagePack for C++ static resolution routine
|
||||
//
|
||||
// Copyright (C) 2008 FURUHASHI Sadayuki
|
||||
// Copyright (C) 2008-2009 FURUHASHI Sadayuki
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
|
@ -1,7 +1,7 @@
|
||||
//
|
||||
// MessagePack for C++ static resolution routine
|
||||
//
|
||||
// Copyright (C) 2008 FURUHASHI Sadayuki
|
||||
// Copyright (C) 2008-2009 FURUHASHI Sadayuki
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
|
@ -1,7 +1,7 @@
|
||||
//
|
||||
// MessagePack for C++ static resolution routine
|
||||
//
|
||||
// Copyright (C) 2008 FURUHASHI Sadayuki
|
||||
// Copyright (C) 2008-2009 FURUHASHI Sadayuki
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
|
@ -1,7 +1,7 @@
|
||||
//
|
||||
// MessagePack for C++ static resolution routine
|
||||
//
|
||||
// Copyright (C) 2008 FURUHASHI Sadayuki
|
||||
// Copyright (C) 2008-2009 FURUHASHI Sadayuki
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
|
@ -1,7 +1,7 @@
|
||||
//
|
||||
// MessagePack for C++ static resolution routine
|
||||
//
|
||||
// Copyright (C) 2008 FURUHASHI Sadayuki
|
||||
// Copyright (C) 2008-2009 FURUHASHI Sadayuki
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
|
369
cpp/unpack.cpp
369
cpp/unpack.cpp
@ -1,369 +0,0 @@
|
||||
//
|
||||
// MessagePack for C++ deserializing routine
|
||||
//
|
||||
// Copyright (C) 2008-2009 FURUHASHI Sadayuki
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
//
|
||||
#include "msgpack/unpack.hpp"
|
||||
#include "msgpack/unpack_define.h"
|
||||
#include <stdlib.h>
|
||||
|
||||
namespace msgpack {
|
||||
|
||||
|
||||
//namespace {
|
||||
struct unpack_user {
|
||||
zone* z;
|
||||
bool referenced;
|
||||
};
|
||||
//} // noname namespace
|
||||
|
||||
|
||||
#define msgpack_unpack_struct(name) \
|
||||
struct msgpack_unpacker ## name
|
||||
|
||||
#define msgpack_unpack_func(ret, name) \
|
||||
ret msgpack_unpacker ## name
|
||||
|
||||
#define msgpack_unpack_callback(name) \
|
||||
msgpack_unpack ## name
|
||||
|
||||
#define msgpack_unpack_object object
|
||||
|
||||
#define msgpack_unpack_user unpack_user
|
||||
|
||||
|
||||
struct msgpack_unpacker_context;
|
||||
|
||||
static void msgpack_unpacker_init(struct msgpack_unpacker_context* ctx);
|
||||
|
||||
static object msgpack_unpacker_data(struct msgpack_unpacker_context* ctx);
|
||||
|
||||
static int msgpack_unpacker_execute(struct msgpack_unpacker_context* ctx,
|
||||
const char* data, size_t len, size_t* off);
|
||||
|
||||
|
||||
static inline object msgpack_unpack_init(unpack_user* u)
|
||||
{ return object(); }
|
||||
|
||||
static inline object msgpack_unpack_uint8(unpack_user* u, uint8_t d)
|
||||
{ object o; o.type = type::POSITIVE_INTEGER; o.via.u64 = d; return o; }
|
||||
|
||||
static inline object msgpack_unpack_uint16(unpack_user* u, uint16_t d)
|
||||
{ object o; o.type = type::POSITIVE_INTEGER; o.via.u64 = d; return o; }
|
||||
|
||||
static inline object msgpack_unpack_uint32(unpack_user* u, uint32_t d)
|
||||
{ object o; o.type = type::POSITIVE_INTEGER; o.via.u64 = d; return o; }
|
||||
|
||||
static inline object msgpack_unpack_uint64(unpack_user* u, uint64_t d)
|
||||
{ object o; o.type = type::POSITIVE_INTEGER; o.via.u64 = d; return o; }
|
||||
|
||||
static inline object msgpack_unpack_int8(unpack_user* u, int8_t d)
|
||||
{ if(d >= 0) { object o; o.type = type::POSITIVE_INTEGER; o.via.u64 = d; return o; }
|
||||
else { object o; o.type = type::NEGATIVE_INTEGER; o.via.i64 = d; return o; } }
|
||||
|
||||
static inline object msgpack_unpack_int16(unpack_user* u, int16_t d)
|
||||
{ if(d >= 0) { object o; o.type = type::POSITIVE_INTEGER; o.via.u64 = d; return o; }
|
||||
else { object o; o.type = type::NEGATIVE_INTEGER; o.via.i64 = d; return o; } }
|
||||
|
||||
static inline object msgpack_unpack_int32(unpack_user* u, int32_t d)
|
||||
{ if(d >= 0) { object o; o.type = type::POSITIVE_INTEGER; o.via.u64 = d; return o; }
|
||||
else { object o; o.type = type::NEGATIVE_INTEGER; o.via.i64 = d; return o; } }
|
||||
|
||||
static inline object msgpack_unpack_int64(unpack_user* u, int64_t d)
|
||||
{ if(d >= 0) { object o; o.type = type::POSITIVE_INTEGER; o.via.u64 = d; return o; }
|
||||
else { object o; o.type = type::NEGATIVE_INTEGER; o.via.i64 = d; return o; } }
|
||||
|
||||
static inline object msgpack_unpack_float(unpack_user* u, float d)
|
||||
{ object o; o.type = type::DOUBLE; o.via.dec = d; return o; }
|
||||
|
||||
static inline object msgpack_unpack_double(unpack_user* u, double d)
|
||||
{ object o; o.type = type::DOUBLE; o.via.dec = d; return o; }
|
||||
|
||||
static inline object msgpack_unpack_nil(unpack_user* u)
|
||||
{ object o; o.type = type::NIL; return o; }
|
||||
|
||||
static inline object msgpack_unpack_true(unpack_user* u)
|
||||
{ object o; o.type = type::BOOLEAN; o.via.boolean = true; return o; }
|
||||
|
||||
static inline object msgpack_unpack_false(unpack_user* u)
|
||||
{ object o; o.type = type::BOOLEAN; o.via.boolean = false; return o; }
|
||||
|
||||
static inline object msgpack_unpack_array(unpack_user* u, unsigned int n)
|
||||
{
|
||||
object o;
|
||||
o.type = type::ARRAY;
|
||||
o.via.array.size = 0;
|
||||
o.via.array.ptr = (object*)u->z->malloc(n*sizeof(object));
|
||||
return o;
|
||||
}
|
||||
|
||||
static inline void msgpack_unpack_array_item(unpack_user* u, object* c, object o)
|
||||
{ c->via.array.ptr[c->via.array.size++] = o; }
|
||||
|
||||
static inline object msgpack_unpack_map(unpack_user* u, unsigned int n)
|
||||
{
|
||||
object o;
|
||||
o.type = type::MAP;
|
||||
o.via.map.size = 0;
|
||||
o.via.map.ptr = (object_kv*)u->z->malloc(n*sizeof(object_kv));
|
||||
return o;
|
||||
}
|
||||
|
||||
static inline void msgpack_unpack_map_item(unpack_user* u, object* c, object k, object v)
|
||||
{
|
||||
c->via.map.ptr[c->via.map.size].key = k;
|
||||
c->via.map.ptr[c->via.map.size].val = v;
|
||||
++c->via.map.size;
|
||||
}
|
||||
|
||||
static inline object msgpack_unpack_raw(unpack_user* u, const char* b, const char* p, unsigned int l)
|
||||
{
|
||||
object o;
|
||||
o.type = type::RAW;
|
||||
o.via.raw.ptr = p;
|
||||
o.via.raw.size = l;
|
||||
u->referenced = true;
|
||||
return o;
|
||||
}
|
||||
|
||||
#include "msgpack/unpack_template.h"
|
||||
|
||||
|
||||
namespace {
|
||||
struct context {
|
||||
context()
|
||||
{
|
||||
msgpack_unpacker_init(&m_ctx);
|
||||
unpack_user u = {NULL, false};
|
||||
m_ctx.user = u;
|
||||
}
|
||||
|
||||
~context() { }
|
||||
|
||||
int execute(const char* data, size_t len, size_t* off)
|
||||
{
|
||||
return msgpack_unpacker_execute(&m_ctx, data, len, off);
|
||||
}
|
||||
|
||||
object data()
|
||||
{
|
||||
return msgpack_unpacker_data(&m_ctx);
|
||||
}
|
||||
|
||||
void reset()
|
||||
{
|
||||
zone* z = m_ctx.user.z;
|
||||
msgpack_unpacker_init(&m_ctx);
|
||||
unpack_user u = {z, false};
|
||||
m_ctx.user = u;
|
||||
}
|
||||
|
||||
void set_zone(zone* z)
|
||||
{
|
||||
m_ctx.user.z = z;
|
||||
}
|
||||
|
||||
bool is_referenced() const
|
||||
{
|
||||
return m_ctx.user.referenced;
|
||||
}
|
||||
|
||||
private:
|
||||
msgpack_unpacker_context m_ctx;
|
||||
zone* m_zone;
|
||||
|
||||
private:
|
||||
context(const context&);
|
||||
};
|
||||
|
||||
static inline context* as_ctx(void* m)
|
||||
{
|
||||
return reinterpret_cast<context*>(m);
|
||||
}
|
||||
|
||||
|
||||
static const size_t COUNTER_SIZE = sizeof(unsigned int);
|
||||
|
||||
static inline void init_count(void* buffer)
|
||||
{
|
||||
*(volatile unsigned int*)buffer = 1;
|
||||
}
|
||||
|
||||
static inline void decl_count(void* buffer)
|
||||
{
|
||||
//if(--*(unsigned int*)buffer == 0) {
|
||||
if(__sync_sub_and_fetch((unsigned int*)buffer, 1) == 0) {
|
||||
free(buffer);
|
||||
}
|
||||
}
|
||||
|
||||
static inline void incr_count(void* buffer)
|
||||
{
|
||||
//++*(unsigned int*)buffer;
|
||||
__sync_add_and_fetch((unsigned int*)buffer, 1);
|
||||
}
|
||||
|
||||
static inline unsigned int get_count(void* buffer)
|
||||
{
|
||||
return *(volatile unsigned int*)buffer;
|
||||
}
|
||||
|
||||
} // noname namespace
|
||||
|
||||
|
||||
unpacker::unpacker(size_t initial_buffer_size) :
|
||||
m_buffer(NULL),
|
||||
m_used(0),
|
||||
m_free(0),
|
||||
m_off(0),
|
||||
m_zone(new zone()),
|
||||
m_ctx(new context()),
|
||||
m_initial_buffer_size(initial_buffer_size)
|
||||
{
|
||||
if(m_initial_buffer_size < COUNTER_SIZE) {
|
||||
m_initial_buffer_size = COUNTER_SIZE;
|
||||
}
|
||||
|
||||
as_ctx(m_ctx)->set_zone(m_zone.get());
|
||||
|
||||
m_buffer = (char*)::malloc(m_initial_buffer_size);
|
||||
if(!m_buffer) { throw std::bad_alloc(); }
|
||||
init_count(m_buffer);
|
||||
|
||||
m_used = COUNTER_SIZE;
|
||||
m_free = m_initial_buffer_size - m_used;
|
||||
m_off = COUNTER_SIZE;
|
||||
}
|
||||
|
||||
|
||||
unpacker::~unpacker()
|
||||
{
|
||||
delete as_ctx(m_ctx);
|
||||
decl_count(m_buffer);
|
||||
}
|
||||
|
||||
void unpacker::expand_buffer(size_t len)
|
||||
{
|
||||
if(m_used == m_off && get_count(m_buffer) == 1 &&
|
||||
!as_ctx(m_ctx)->is_referenced()) {
|
||||
// rewind buffer
|
||||
m_free += m_used - COUNTER_SIZE;
|
||||
m_used = COUNTER_SIZE;
|
||||
m_off = COUNTER_SIZE;
|
||||
if(m_free >= len) { return; }
|
||||
}
|
||||
|
||||
if(m_off == COUNTER_SIZE) {
|
||||
size_t next_size = (m_used + m_free) * 2;
|
||||
while(next_size < len + m_used) { next_size *= 2; }
|
||||
|
||||
char* tmp = (char*)::realloc(m_buffer, next_size);
|
||||
if(!tmp) { throw std::bad_alloc(); }
|
||||
|
||||
m_buffer = tmp;
|
||||
m_free = next_size - m_used;
|
||||
|
||||
} else {
|
||||
size_t next_size = m_initial_buffer_size; // include COUNTER_SIZE
|
||||
size_t not_parsed = m_used - m_off;
|
||||
while(next_size < len + not_parsed + COUNTER_SIZE) { next_size *= 2; }
|
||||
|
||||
char* tmp = (char*)::malloc(next_size);
|
||||
if(!tmp) { throw std::bad_alloc(); }
|
||||
init_count(tmp);
|
||||
|
||||
try {
|
||||
m_zone->push_finalizer(decl_count, m_buffer);
|
||||
} catch (...) { free(tmp); throw; }
|
||||
|
||||
memcpy(tmp+COUNTER_SIZE, m_buffer+m_off, not_parsed);
|
||||
|
||||
m_buffer = tmp;
|
||||
m_used = not_parsed + COUNTER_SIZE;
|
||||
m_free = next_size - m_used;
|
||||
m_off = COUNTER_SIZE;
|
||||
}
|
||||
}
|
||||
|
||||
bool unpacker::execute()
|
||||
{
|
||||
int ret = as_ctx(m_ctx)->execute(m_buffer, m_used, &m_off);
|
||||
if(ret < 0) {
|
||||
throw unpack_error("parse error");
|
||||
} else if(ret == 0) {
|
||||
return false;
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
zone* unpacker::release_zone()
|
||||
{
|
||||
m_zone->push_finalizer(decl_count, m_buffer);
|
||||
incr_count(m_buffer);
|
||||
|
||||
//std::auto_ptr<zone> old(new zone());
|
||||
//m_zone.swap(old);
|
||||
zone* n = new zone();
|
||||
std::auto_ptr<zone> old(m_zone.release());
|
||||
m_zone.reset(n);
|
||||
|
||||
as_ctx(m_ctx)->set_zone(m_zone.get());
|
||||
|
||||
return old.release();
|
||||
}
|
||||
|
||||
object unpacker::data()
|
||||
{
|
||||
return as_ctx(m_ctx)->data();
|
||||
}
|
||||
|
||||
void unpacker::reset()
|
||||
{
|
||||
//if(!m_zone->empty()) { delete release_zone(); }
|
||||
as_ctx(m_ctx)->reset();
|
||||
}
|
||||
|
||||
|
||||
object unpacker::unpack(const char* data, size_t len, zone& z, size_t* off)
|
||||
{
|
||||
context ctx;
|
||||
ctx.set_zone(&z);
|
||||
if(off) {
|
||||
size_t noff = *off;
|
||||
int ret = ctx.execute(data, len, &noff);
|
||||
if(ret < 0) {
|
||||
throw unpack_error("parse error");
|
||||
} else if(ret == 0) {
|
||||
throw unpack_error("insufficient bytes");
|
||||
}
|
||||
*off = noff;
|
||||
} else {
|
||||
size_t noff = 0;
|
||||
int ret = ctx.execute(data, len, &noff);
|
||||
if(ret < 0) {
|
||||
throw unpack_error("parse error");
|
||||
} else if(ret == 0) {
|
||||
throw unpack_error("insufficient bytes");
|
||||
} else if(noff < len) {
|
||||
throw unpack_error("extra bytes");
|
||||
}
|
||||
}
|
||||
return ctx.data();
|
||||
}
|
||||
|
||||
|
||||
} // namespace msgpack
|
||||
|
171
cpp/unpack.hpp
171
cpp/unpack.hpp
@ -18,6 +18,7 @@
|
||||
#ifndef MSGPACK_UNPACK_HPP__
|
||||
#define MSGPACK_UNPACK_HPP__
|
||||
|
||||
#include "msgpack/unpack.h"
|
||||
#include "msgpack/object.hpp"
|
||||
#include "msgpack/zone.hpp"
|
||||
#include <memory>
|
||||
@ -36,21 +37,21 @@ struct unpack_error : public std::runtime_error {
|
||||
};
|
||||
|
||||
|
||||
class unpacker {
|
||||
class unpacker : public msgpack_unpacker {
|
||||
public:
|
||||
unpacker(size_t initial_buffer_size = MSGPACK_UNPACKER_DEFAULT_INITIAL_BUFFER_SIZE);
|
||||
~unpacker();
|
||||
|
||||
public:
|
||||
/*! 1. reserve buffer. at least `len' bytes of capacity will be ready */
|
||||
void reserve_buffer(size_t len);
|
||||
/*! 1. reserve buffer. at least `size' bytes of capacity will be ready */
|
||||
void reserve_buffer(size_t size);
|
||||
|
||||
/*! 2. read data to the buffer() up to buffer_capacity() bytes */
|
||||
char* buffer();
|
||||
size_t buffer_capacity() const;
|
||||
|
||||
/*! 3. specify the number of bytes actually copied */
|
||||
void buffer_consumed(size_t len);
|
||||
void buffer_consumed(size_t size);
|
||||
|
||||
/*! 4. repeat execute() until it retunrs false */
|
||||
bool execute();
|
||||
@ -114,71 +115,157 @@ public:
|
||||
size_t nonparsed_size() const;
|
||||
|
||||
/*! skip specified size of non-parsed buffer, leaving the buffer */
|
||||
// Note that the `len' argument must be smaller than nonparsed_size()
|
||||
void skip_nonparsed_buffer(size_t len);
|
||||
// Note that the `size' argument must be smaller than nonparsed_size()
|
||||
void skip_nonparsed_buffer(size_t size);
|
||||
|
||||
/*! remove unparsed buffer from unpacker */
|
||||
// Note that reset() leaves non-parsed buffer.
|
||||
void remove_nonparsed_buffer();
|
||||
|
||||
private:
|
||||
char* m_buffer;
|
||||
size_t m_used;
|
||||
size_t m_free;
|
||||
size_t m_off;
|
||||
|
||||
std::auto_ptr<zone> m_zone;
|
||||
|
||||
void* m_ctx;
|
||||
|
||||
size_t m_initial_buffer_size;
|
||||
|
||||
private:
|
||||
void expand_buffer(size_t len);
|
||||
|
||||
private:
|
||||
unpacker(const unpacker&);
|
||||
|
||||
public:
|
||||
static object unpack(const char* data, size_t len, zone& z, size_t* off = NULL);
|
||||
};
|
||||
|
||||
|
||||
inline void unpacker::reserve_buffer(size_t len)
|
||||
typedef enum {
|
||||
MSGPACK_UNPACK_SUCCESS = 2,
|
||||
MSGPACK_UNPACK_EXTRA_BYTES = 1,
|
||||
MSGPACK_UNPACK_CONTINUE = 0,
|
||||
MSGPACK_UNPACK_PARSE_ERROR = -1,
|
||||
} unpack_return;
|
||||
|
||||
static unpack_return unpack(const char* data, size_t len, size_t* off,
|
||||
zone* z, object* result);
|
||||
|
||||
|
||||
// obsolete
|
||||
static object unpack(const char* data, size_t len, zone& z, size_t* off = NULL);
|
||||
|
||||
|
||||
inline unpacker::unpacker(size_t initial_buffer_size)
|
||||
{
|
||||
if(m_free >= len) { return; }
|
||||
expand_buffer(len);
|
||||
if(!msgpack_unpacker_init(this, initial_buffer_size)) {
|
||||
throw std::bad_alloc();
|
||||
}
|
||||
}
|
||||
|
||||
inline unpacker::~unpacker()
|
||||
{
|
||||
msgpack_unpacker_destroy(this);
|
||||
}
|
||||
|
||||
inline void unpacker::reserve_buffer(size_t size)
|
||||
{
|
||||
if(!msgpack_unpacker_reserve_buffer(this, size)) {
|
||||
throw std::bad_alloc();
|
||||
}
|
||||
}
|
||||
|
||||
inline char* unpacker::buffer()
|
||||
{ return m_buffer + m_used; }
|
||||
{
|
||||
return msgpack_unpacker_buffer(this);
|
||||
}
|
||||
|
||||
inline size_t unpacker::buffer_capacity() const
|
||||
{ return m_free; }
|
||||
|
||||
inline void unpacker::buffer_consumed(size_t len)
|
||||
{
|
||||
m_used += len;
|
||||
m_free -= len;
|
||||
return msgpack_unpacker_buffer_capacity(this);
|
||||
}
|
||||
|
||||
inline void unpacker::buffer_consumed(size_t size)
|
||||
{
|
||||
return msgpack_unpacker_buffer_consumed(this, size);
|
||||
}
|
||||
|
||||
|
||||
inline bool unpacker::execute()
|
||||
{
|
||||
int ret = msgpack_unpacker_execute(this);
|
||||
if(ret < 0) {
|
||||
throw unpack_error("parse error");
|
||||
} else if(ret == 0) {
|
||||
return false;
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
inline object unpacker::data()
|
||||
{
|
||||
msgpack_object obj = msgpack_unpacker_data(this);
|
||||
return *reinterpret_cast<object*>(&obj);
|
||||
}
|
||||
|
||||
inline zone* unpacker::release_zone()
|
||||
{
|
||||
if(!msgpack_unpacker_flush_zone(this)) {
|
||||
throw std::bad_alloc();
|
||||
}
|
||||
|
||||
zone* r = new zone();
|
||||
|
||||
msgpack_zone old = *this->z;
|
||||
*this->z = *z;
|
||||
*z = old;
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
inline void unpacker::reset()
|
||||
{
|
||||
msgpack_unpacker_reset(this);
|
||||
}
|
||||
|
||||
|
||||
inline char* unpacker::nonparsed_buffer()
|
||||
{ return m_buffer + m_off; }
|
||||
{
|
||||
return buf + off;
|
||||
}
|
||||
|
||||
inline size_t unpacker::nonparsed_size() const
|
||||
{ return m_used - m_off; }
|
||||
{
|
||||
return used - off;
|
||||
}
|
||||
|
||||
inline void unpacker::skip_nonparsed_buffer(size_t len)
|
||||
{ m_off += len; }
|
||||
inline void unpacker::skip_nonparsed_buffer(size_t size)
|
||||
{
|
||||
off += size;
|
||||
}
|
||||
|
||||
inline void unpacker::remove_nonparsed_buffer()
|
||||
{ m_used = m_off; }
|
||||
|
||||
|
||||
inline object unpack(const char* data, size_t len, zone& z, size_t* off = NULL)
|
||||
{
|
||||
return unpacker::unpack(data, len, z, off);
|
||||
used = off;
|
||||
}
|
||||
|
||||
|
||||
inline unpack_return unpack(const char* data, size_t len, size_t* off,
|
||||
zone* z, object* result)
|
||||
{
|
||||
return (unpack_return)msgpack_unpack(data, len, off,
|
||||
z, reinterpret_cast<msgpack_object*>(result));
|
||||
}
|
||||
|
||||
inline object unpack(const char* data, size_t len, zone& z, size_t* off)
|
||||
{
|
||||
object result;
|
||||
|
||||
switch( msgpack::unpack(data, len, off, &z, &result) ) {
|
||||
case MSGPACK_UNPACK_SUCCESS:
|
||||
return result;
|
||||
|
||||
case MSGPACK_UNPACK_EXTRA_BYTES:
|
||||
if(off) {
|
||||
return result;
|
||||
} else {
|
||||
throw unpack_error("extra bytes");
|
||||
}
|
||||
|
||||
case MSGPACK_UNPACK_CONTINUE:
|
||||
throw unpack_error("insufficient bytes");
|
||||
|
||||
case MSGPACK_UNPACK_PARSE_ERROR:
|
||||
default:
|
||||
throw unpack_error("parse error");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
100
cpp/zone.cpp
100
cpp/zone.cpp
@ -1,100 +0,0 @@
|
||||
//
|
||||
// MessagePack for C++ memory pool
|
||||
//
|
||||
// Copyright (C) 2008-2009 FURUHASHI Sadayuki
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
//
|
||||
#include "msgpack/zone.hpp"
|
||||
#include <algorithm>
|
||||
|
||||
namespace msgpack {
|
||||
|
||||
|
||||
zone::zone(size_t chunk_size) :
|
||||
m_chunk_size(chunk_size)
|
||||
{
|
||||
chunk dummy = {0, NULL, NULL};
|
||||
m_chunk_array.push_back(dummy);
|
||||
}
|
||||
|
||||
zone::~zone()
|
||||
{
|
||||
clear();
|
||||
}
|
||||
|
||||
namespace {
|
||||
template <typename Private>
|
||||
struct zone_finalize {
|
||||
void operator() (Private& f) {
|
||||
(*f.func)(f.obj);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Private>
|
||||
struct zone_free {
|
||||
void operator() (Private& c) {
|
||||
::free(c.alloc);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
void zone::clear()
|
||||
{
|
||||
std::for_each(m_finalizers.rbegin(), m_finalizers.rend(),
|
||||
zone_finalize<finalizer>());
|
||||
m_finalizers.clear();
|
||||
|
||||
std::for_each(m_chunk_array.begin(), m_chunk_array.end(),
|
||||
zone_free<chunk>());
|
||||
m_chunk_array.resize(1);
|
||||
m_chunk_array[0].ptr = NULL;
|
||||
m_chunk_array[0].free = 0;
|
||||
}
|
||||
|
||||
bool zone::empty() const
|
||||
{
|
||||
return m_chunk_array.back().alloc == NULL &&
|
||||
m_finalizers.empty();
|
||||
}
|
||||
|
||||
void* zone::malloc(size_t size)
|
||||
{
|
||||
if(m_chunk_array.back().free > size) {
|
||||
char* p = (char*)m_chunk_array.back().ptr;
|
||||
m_chunk_array.back().ptr = p + size;
|
||||
m_chunk_array.back().free -= size;
|
||||
return p;
|
||||
}
|
||||
|
||||
size_t sz = m_chunk_size;
|
||||
while(sz < size) { sz *= 2; }
|
||||
|
||||
chunk dummy = {0, NULL, NULL};
|
||||
m_chunk_array.push_back(dummy);
|
||||
|
||||
char* p = (char*)::malloc(sz);
|
||||
if(!p) {
|
||||
m_chunk_array.pop_back();
|
||||
throw std::bad_alloc();
|
||||
}
|
||||
|
||||
m_chunk_array.back().free = sz - size;
|
||||
m_chunk_array.back().ptr = p + size;
|
||||
m_chunk_array.back().alloc = p;
|
||||
return p;
|
||||
}
|
||||
|
||||
|
||||
} // namespace msgpack
|
||||
|
@ -19,17 +19,15 @@
|
||||
#define MSGPACK_ZONE_HPP__
|
||||
|
||||
#include "msgpack/object.hpp"
|
||||
#include "msgpack/zone.h"
|
||||
#include <cstdlib>
|
||||
#include <vector>
|
||||
|
||||
#ifndef MSGPACK_ZONE_CHUNK_SIZE
|
||||
#define MSGPACK_ZONE_CHUNK_SIZE 2048
|
||||
#endif
|
||||
<% GENERATION_LIMIT = 15 %>
|
||||
namespace msgpack {
|
||||
|
||||
|
||||
class zone {
|
||||
class zone : public msgpack_zone {
|
||||
public:
|
||||
zone(size_t chunk_size = MSGPACK_ZONE_CHUNK_SIZE);
|
||||
~zone();
|
||||
@ -37,11 +35,7 @@ public:
|
||||
public:
|
||||
void* malloc(size_t size);
|
||||
|
||||
void push_finalizer(void (*func)(void*), void* obj);
|
||||
|
||||
void clear();
|
||||
|
||||
bool empty() const;
|
||||
void push_finalizer(void (*func)(void*), void* data);
|
||||
|
||||
<%0.upto(GENERATION_LIMIT) {|i|%>
|
||||
template <typename T<%1.upto(i) {|j|%>, typename A<%=j%><%}%>>
|
||||
@ -49,35 +43,39 @@ public:
|
||||
<%}%>
|
||||
|
||||
private:
|
||||
struct chunk {
|
||||
size_t free;
|
||||
void* ptr;
|
||||
void* alloc;
|
||||
};
|
||||
|
||||
std::vector<chunk> m_chunk_array;
|
||||
|
||||
struct finalizer {
|
||||
void (*func)(void*);
|
||||
void* obj;
|
||||
};
|
||||
|
||||
std::vector<finalizer> m_finalizers;
|
||||
|
||||
template <typename T>
|
||||
static void object_destructor(void* obj);
|
||||
|
||||
size_t m_chunk_size;
|
||||
|
||||
private:
|
||||
zone(const zone&);
|
||||
};
|
||||
|
||||
|
||||
inline void zone::push_finalizer(void (*func)(void*), void* obj)
|
||||
|
||||
inline zone::zone(size_t chunk_size)
|
||||
{
|
||||
finalizer f = {func, obj};
|
||||
m_finalizers.push_back(f);
|
||||
msgpack_zone_init(this, chunk_size);
|
||||
}
|
||||
|
||||
inline zone::~zone()
|
||||
{
|
||||
msgpack_zone_destroy(this);
|
||||
}
|
||||
|
||||
inline void* zone::malloc(size_t size)
|
||||
{
|
||||
void* ptr = msgpack_zone_malloc(this, size);
|
||||
if(!ptr) {
|
||||
throw std::bad_alloc();
|
||||
}
|
||||
return ptr;
|
||||
}
|
||||
|
||||
inline void zone::push_finalizer(void (*func)(void*), void* data)
|
||||
{
|
||||
if(!msgpack_zone_push_finalizer(this, func, data)) {
|
||||
throw std::bad_alloc();
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
@ -93,7 +91,7 @@ T* zone::allocate(<%=(1..i).map{|j|"A#{j} a#{j}"}.join(', ')%>)
|
||||
void* x = malloc(sizeof(T));
|
||||
push_finalizer(&zone::object_destructor<T>, x);
|
||||
try { return new (x) T(<%=(1..i).map{|j|"a#{j}"}.join(', ')%>); }
|
||||
catch (...) { m_finalizers.pop_back(); throw; }
|
||||
catch (...) { --finalizer_array.tail; throw; }
|
||||
}
|
||||
<%}%>
|
||||
|
||||
@ -101,3 +99,4 @@ T* zone::allocate(<%=(1..i).map{|j|"A#{j} a#{j}"}.join(', ')%>)
|
||||
|
||||
#endif /* msgpack/zone.hpp */
|
||||
|
||||
// vim: ft=cpp ts=4 sw=4 softtabstop=4 noexpandtab smarttab
|
||||
|
@ -10,6 +10,7 @@
|
||||
class Server {
|
||||
public:
|
||||
Server(int sock) : m_sock(sock) { }
|
||||
|
||||
~Server() { }
|
||||
|
||||
typedef std::auto_ptr<msgpack::zone> auto_zone;
|
||||
|
@ -49,7 +49,7 @@ msgpack_unpack_struct_decl(_stack) {
|
||||
};
|
||||
|
||||
msgpack_unpack_struct_decl(_context) {
|
||||
msgpack_unpack_user user; // must be first
|
||||
msgpack_unpack_user user;
|
||||
unsigned int cs;
|
||||
unsigned int trail;
|
||||
unsigned int top;
|
||||
@ -63,12 +63,12 @@ msgpack_unpack_func(void, _init)(msgpack_unpack_struct(_context)* ctx)
|
||||
ctx->cs = CS_HEADER;
|
||||
ctx->trail = 0;
|
||||
ctx->top = 0;
|
||||
ctx->stack[0].obj = msgpack_unpack_callback(_init)(&ctx->user);
|
||||
ctx->stack[0].obj = msgpack_unpack_callback(_root)(&ctx->user);
|
||||
}
|
||||
|
||||
msgpack_unpack_func(msgpack_unpack_object, _data)(msgpack_unpack_struct(_context)* unpacker)
|
||||
msgpack_unpack_func(msgpack_unpack_object, _data)(msgpack_unpack_struct(_context)* ctx)
|
||||
{
|
||||
return (unpacker)->stack[0].obj;
|
||||
return (ctx)->stack[0].obj;
|
||||
}
|
||||
|
||||
|
||||
@ -92,16 +92,14 @@ msgpack_unpack_func(int, _execute)(msgpack_unpack_struct(_context)* ctx, const c
|
||||
int ret;
|
||||
|
||||
#define push_simple_value(func) \
|
||||
obj = msgpack_unpack_callback(func)(user); \
|
||||
/*printf("obj %d\n",obj);*/ \
|
||||
if(msgpack_unpack_callback(func)(user, &obj) < 0) { goto _failed; } \
|
||||
goto _push
|
||||
#define push_fixed_value(func, arg) \
|
||||
obj = msgpack_unpack_callback(func)(user, arg); \
|
||||
/*printf("obj %d\n",obj);*/ \
|
||||
if(msgpack_unpack_callback(func)(user, arg, &obj) < 0) { goto _failed; } \
|
||||
goto _push
|
||||
#define push_variable_value(func, base, pos, len) \
|
||||
obj = msgpack_unpack_callback(func)(user, (const char*)base, (const char*)pos, len); \
|
||||
/*printf("obj %d\n",obj);*/ \
|
||||
if(msgpack_unpack_callback(func)(user, \
|
||||
(const char*)base, (const char*)pos, len, &obj) < 0) { goto _failed; } \
|
||||
goto _push
|
||||
|
||||
#define again_fixed_trail(_cs, trail_len) \
|
||||
@ -115,7 +113,7 @@ msgpack_unpack_func(int, _execute)(msgpack_unpack_struct(_context)* ctx, const c
|
||||
goto _fixed_trail_again
|
||||
|
||||
#define start_container(func, count_, ct_) \
|
||||
stack[top].obj = msgpack_unpack_callback(func)(user, count_); \
|
||||
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_; \
|
||||
@ -264,11 +262,13 @@ msgpack_unpack_func(int, _execute)(msgpack_unpack_struct(_context)* ctx, const c
|
||||
case CS_ARRAY_16:
|
||||
start_container(_array, (uint16_t)PTR_CAST_16(n), CT_ARRAY_ITEM);
|
||||
case CS_ARRAY_32:
|
||||
/* FIXME security guard */
|
||||
start_container(_array, (uint32_t)PTR_CAST_32(n), CT_ARRAY_ITEM);
|
||||
|
||||
case CS_MAP_16:
|
||||
start_container(_map, (uint16_t)PTR_CAST_16(n), CT_MAP_KEY);
|
||||
case CS_MAP_32:
|
||||
/* FIXME security guard */
|
||||
start_container(_map, (uint32_t)PTR_CAST_32(n), CT_MAP_KEY);
|
||||
|
||||
default:
|
||||
@ -281,7 +281,7 @@ _push:
|
||||
c = &stack[top-1];
|
||||
switch(c->ct) {
|
||||
case CT_ARRAY_ITEM:
|
||||
msgpack_unpack_callback(_array_item)(user, &c->obj, obj);
|
||||
if(msgpack_unpack_callback(_array_item)(user, &c->obj, obj) < 0) { goto _failed; }
|
||||
if(--c->count == 0) {
|
||||
obj = c->obj;
|
||||
--top;
|
||||
@ -294,7 +294,7 @@ _push:
|
||||
c->ct = CT_MAP_VALUE;
|
||||
goto _header_again;
|
||||
case CT_MAP_VALUE:
|
||||
msgpack_unpack_callback(_map_item)(user, &c->obj, c->map_key, obj);
|
||||
if(msgpack_unpack_callback(_map_item)(user, &c->obj, c->map_key, obj) < 0) { goto _failed; }
|
||||
if(--c->count == 0) {
|
||||
obj = c->obj;
|
||||
--top;
|
||||
|
@ -24,6 +24,6 @@
|
||||
|
||||
== Copyright
|
||||
|
||||
Author:: frsyuki <frsyuki@>
|
||||
Copyright:: Copyright (c) 2009 frsyuki
|
||||
Author:: frsyuki <frsyuki@users.sourceforge.jp>
|
||||
Copyright:: Copyright (c) 2008-2009 frsyuki
|
||||
License:: Apache License, Version 2.0
|
||||
|
@ -1,5 +1,7 @@
|
||||
#!/bin/sh
|
||||
|
||||
mkdir -p gem/ext
|
||||
mkdir -p gem/msgpack
|
||||
cp extconf.rb gem/ext/
|
||||
cp pack.c gem/ext/
|
||||
cp pack.h gem/ext/
|
||||
|
134
ruby/unpack.c
134
ruby/unpack.c
@ -21,99 +21,99 @@
|
||||
|
||||
typedef struct {
|
||||
int finished;
|
||||
VALUE origstr;
|
||||
} msgpack_unpack_context;
|
||||
VALUE source;
|
||||
} unpack_user;
|
||||
|
||||
|
||||
#define msgpack_unpack_struct(name) \
|
||||
struct msgpack_unpacker ## name
|
||||
struct template ## name
|
||||
|
||||
#define msgpack_unpack_func(ret, name) \
|
||||
ret msgpack_unpacker ## name
|
||||
ret template ## name
|
||||
|
||||
#define msgpack_unpack_callback(name) \
|
||||
template_callback ## name
|
||||
|
||||
#define msgpack_unpack_object VALUE
|
||||
|
||||
#define msgpack_unpack_user msgpack_unpack_context
|
||||
#define msgpack_unpack_user unpack_user
|
||||
|
||||
|
||||
struct msgpack_unpacker_context;
|
||||
typedef struct msgpack_unpacker_context msgpack_unpacker;
|
||||
struct template_context;
|
||||
typedef struct template_context msgpack_unpack_t;
|
||||
|
||||
static void msgpack_unpacker_init(msgpack_unpacker* ctx);
|
||||
static void template_init(msgpack_unpack_t* u);
|
||||
|
||||
static VALUE msgpack_unpacker_data(msgpack_unpacker* ctx);
|
||||
static VALUE template_data(msgpack_unpack_t* u);
|
||||
|
||||
static int msgpack_unpacker_execute(msgpack_unpacker* ctx,
|
||||
static int template_execute(msgpack_unpack_t* u,
|
||||
const char* data, size_t len, size_t* off);
|
||||
|
||||
|
||||
static inline VALUE template_callback_init(msgpack_unpack_context* x)
|
||||
static inline VALUE template_callback_root(unpack_user* u)
|
||||
{ return Qnil; }
|
||||
|
||||
static inline VALUE template_callback_uint8(msgpack_unpack_context* x, uint8_t d)
|
||||
{ return INT2FIX(d); }
|
||||
static inline int template_callback_uint8(unpack_user* u, uint8_t d, VALUE* o)
|
||||
{ *o = INT2FIX(d); return 0; }
|
||||
|
||||
static inline VALUE template_callback_uint16(msgpack_unpack_context* x, uint16_t d)
|
||||
{ return INT2FIX(d); }
|
||||
static inline int template_callback_uint16(unpack_user* u, uint16_t d, VALUE* o)
|
||||
{ *o = INT2FIX(d); return 0; }
|
||||
|
||||
static inline VALUE template_callback_uint32(msgpack_unpack_context* x, uint32_t d)
|
||||
{ return UINT2NUM(d); }
|
||||
static inline int template_callback_uint32(unpack_user* u, uint32_t d, VALUE* o)
|
||||
{ *o = UINT2NUM(d); return 0; }
|
||||
|
||||
static inline VALUE template_callback_uint64(msgpack_unpack_context* x, uint64_t d)
|
||||
{ return rb_ull2inum(d); }
|
||||
static inline int template_callback_uint64(unpack_user* u, uint64_t d, VALUE* o)
|
||||
{ *o = rb_ull2inum(d); return 0; }
|
||||
|
||||
static inline VALUE template_callback_int8(msgpack_unpack_context* x, int8_t d)
|
||||
{ return INT2FIX((long)d); }
|
||||
static inline int template_callback_int8(unpack_user* u, int8_t d, VALUE* o)
|
||||
{ *o = INT2FIX((long)d); return 0; }
|
||||
|
||||
static inline VALUE template_callback_int16(msgpack_unpack_context* x, int16_t d)
|
||||
{ return INT2FIX((long)d); }
|
||||
static inline int template_callback_int16(unpack_user* u, int16_t d, VALUE* o)
|
||||
{ *o = INT2FIX((long)d); return 0; }
|
||||
|
||||
static inline VALUE template_callback_int32(msgpack_unpack_context* x, int32_t d)
|
||||
{ return INT2NUM((long)d); }
|
||||
static inline int template_callback_int32(unpack_user* u, int32_t d, VALUE* o)
|
||||
{ *o = INT2NUM((long)d); return 0; }
|
||||
|
||||
static inline VALUE template_callback_int64(msgpack_unpack_context* x, int64_t d)
|
||||
{ return rb_ll2inum(d); }
|
||||
static inline int template_callback_int64(unpack_user* u, int64_t d, VALUE* o)
|
||||
{ *o = rb_ll2inum(d); return 0; }
|
||||
|
||||
static inline VALUE template_callback_float(msgpack_unpack_context* x, float d)
|
||||
{ return rb_float_new(d); }
|
||||
static inline int template_callback_float(unpack_user* u, float d, VALUE* o)
|
||||
{ *o = rb_float_new(d); return 0; }
|
||||
|
||||
static inline VALUE template_callback_double(msgpack_unpack_context* x, double d)
|
||||
{ return rb_float_new(d); }
|
||||
static inline int template_callback_double(unpack_user* u, double d, VALUE* o)
|
||||
{ *o = rb_float_new(d); return 0; }
|
||||
|
||||
static inline VALUE template_callback_nil(msgpack_unpack_context* x)
|
||||
{ return Qnil; }
|
||||
static inline int template_callback_nil(unpack_user* u, VALUE* o)
|
||||
{ *o = Qnil; return 0; }
|
||||
|
||||
static inline VALUE template_callback_true(msgpack_unpack_context* x)
|
||||
{ return Qtrue; }
|
||||
static inline int template_callback_true(unpack_user* u, VALUE* o)
|
||||
{ *o = Qtrue; return 0; }
|
||||
|
||||
static inline VALUE template_callback_false(msgpack_unpack_context* x)
|
||||
{ return Qfalse; }
|
||||
static inline int template_callback_false(unpack_user* u, VALUE* o)
|
||||
{ *o = Qfalse; return 0;}
|
||||
|
||||
static inline VALUE template_callback_array(msgpack_unpack_context* x, unsigned int n)
|
||||
{ return rb_ary_new2(n); }
|
||||
static inline int template_callback_array(unpack_user* u, unsigned int n, VALUE* o)
|
||||
{ *o = rb_ary_new2(n); return 0; }
|
||||
|
||||
static inline void template_callback_array_item(msgpack_unpack_context* x, VALUE* c, VALUE o)
|
||||
{ rb_ary_push(*c, o); } // FIXME set value directry RARRAY_PTR(obj)[RARRAY_LEN(obj)++]
|
||||
static inline int template_callback_array_item(unpack_user* u, VALUE* c, VALUE o)
|
||||
{ rb_ary_push(*c, o); return 0; } // FIXME set value directry RARRAY_PTR(obj)[RARRAY_LEN(obj)++]
|
||||
|
||||
static inline VALUE template_callback_map(msgpack_unpack_context* x, unsigned int n)
|
||||
{ return rb_hash_new(); }
|
||||
static inline int template_callback_map(unpack_user* u, unsigned int n, VALUE* o)
|
||||
{ *o = rb_hash_new(); return 0; }
|
||||
|
||||
static inline void template_callback_map_item(msgpack_unpack_context* x, VALUE* c, VALUE k, VALUE v)
|
||||
{ rb_hash_aset(*c, k, v); }
|
||||
static inline int template_callback_map_item(unpack_user* u, VALUE* c, VALUE k, VALUE v)
|
||||
{ rb_hash_aset(*c, k, v); return 0; }
|
||||
|
||||
static inline VALUE template_callback_raw(msgpack_unpack_context* x, const char* b, const char* p, unsigned int l)
|
||||
{ return l == 0 ? rb_str_new(0,0) : rb_str_substr(x->origstr, p - b, l); }
|
||||
static inline int template_callback_raw(unpack_user* u, const char* b, const char* p, unsigned int l, VALUE* o)
|
||||
{ *o = (l == 0) ? rb_str_new(0,0) : rb_str_substr(u->source, p - b, l); return 0; }
|
||||
|
||||
|
||||
#include "msgpack/unpack_template.h"
|
||||
|
||||
|
||||
#define UNPACKER(from, name) \
|
||||
msgpack_unpacker *name = NULL; \
|
||||
Data_Get_Struct(from, msgpack_unpacker, name); \
|
||||
msgpack_unpack_t *name = NULL; \
|
||||
Data_Get_Struct(from, msgpack_unpack_t, name); \
|
||||
if(name == NULL) { \
|
||||
rb_raise(rb_eArgError, "NULL found for " # name " when shouldn't be."); \
|
||||
}
|
||||
@ -132,7 +132,7 @@ static void MessagePack_Unpacker_free(void* data)
|
||||
if(data) { free(data); }
|
||||
}
|
||||
|
||||
static void MessagePack_Unpacker_mark(msgpack_unpacker *mp)
|
||||
static void MessagePack_Unpacker_mark(msgpack_unpack_t *mp)
|
||||
{
|
||||
unsigned int i;
|
||||
for(i=0; i < mp->top; ++i) {
|
||||
@ -144,7 +144,7 @@ static void MessagePack_Unpacker_mark(msgpack_unpacker *mp)
|
||||
static VALUE MessagePack_Unpacker_alloc(VALUE klass)
|
||||
{
|
||||
VALUE obj;
|
||||
msgpack_unpacker* mp = ALLOC_N(msgpack_unpacker, 1);
|
||||
msgpack_unpack_t* mp = ALLOC_N(msgpack_unpack_t, 1);
|
||||
obj = Data_Wrap_Struct(klass, MessagePack_Unpacker_mark,
|
||||
MessagePack_Unpacker_free, mp);
|
||||
return obj;
|
||||
@ -153,9 +153,9 @@ static VALUE MessagePack_Unpacker_alloc(VALUE klass)
|
||||
static VALUE MessagePack_Unpacker_reset(VALUE self)
|
||||
{
|
||||
UNPACKER(self, mp);
|
||||
msgpack_unpacker_init(mp);
|
||||
msgpack_unpack_context ctx = {0, Qnil};
|
||||
mp->user = ctx;
|
||||
template_init(mp);
|
||||
unpack_user u = {0, Qnil};
|
||||
mp->user = u;
|
||||
return self;
|
||||
}
|
||||
|
||||
@ -180,9 +180,9 @@ static VALUE MessagePack_Unpacker_execute_impl(VALUE args)
|
||||
rb_raise(eUnpackError, "offset is bigger than data buffer size.");
|
||||
}
|
||||
|
||||
mp->user.origstr = data;
|
||||
ret = msgpack_unpacker_execute(mp, dptr, (size_t)dlen, &from);
|
||||
mp->user.origstr = Qnil;
|
||||
mp->user.source = data;
|
||||
ret = template_execute(mp, dptr, (size_t)dlen, &from);
|
||||
mp->user.source = Qnil;
|
||||
|
||||
if(ret < 0) {
|
||||
rb_raise(eUnpackError, "parse error.");
|
||||
@ -235,13 +235,13 @@ static VALUE MessagePack_Unpacker_finished_p(VALUE self)
|
||||
static VALUE MessagePack_Unpacker_data(VALUE self)
|
||||
{
|
||||
UNPACKER(self, mp);
|
||||
return msgpack_unpacker_data(mp);
|
||||
return template_data(mp);
|
||||
}
|
||||
|
||||
|
||||
static VALUE MessagePack_unpack_impl(VALUE args)
|
||||
{
|
||||
msgpack_unpacker* mp = (msgpack_unpacker*)((VALUE*)args)[0];
|
||||
msgpack_unpack_t* mp = (msgpack_unpack_t*)((VALUE*)args)[0];
|
||||
VALUE data = ((VALUE*)args)[1];
|
||||
|
||||
size_t from = 0;
|
||||
@ -249,9 +249,9 @@ static VALUE MessagePack_unpack_impl(VALUE args)
|
||||
long dlen = FIX2LONG(((VALUE*)args)[2]);
|
||||
int ret;
|
||||
|
||||
mp->user.origstr = data;
|
||||
ret = msgpack_unpacker_execute(mp, dptr, (size_t)dlen, &from);
|
||||
mp->user.origstr = Qnil;
|
||||
mp->user.source = data;
|
||||
ret = template_execute(mp, dptr, (size_t)dlen, &from);
|
||||
mp->user.source = Qnil;
|
||||
|
||||
if(ret < 0) {
|
||||
rb_raise(eUnpackError, "parse error.");
|
||||
@ -261,7 +261,7 @@ static VALUE MessagePack_unpack_impl(VALUE args)
|
||||
if(from < dlen) {
|
||||
rb_raise(eUnpackError, "extra bytes.");
|
||||
}
|
||||
return msgpack_unpacker_data(mp);
|
||||
return template_data(mp);
|
||||
}
|
||||
}
|
||||
|
||||
@ -278,10 +278,10 @@ static VALUE MessagePack_unpack_rescue(VALUE args)
|
||||
static VALUE MessagePack_unpack_limit(VALUE self, VALUE data, VALUE limit)
|
||||
{
|
||||
CHECK_STRING_TYPE(data);
|
||||
msgpack_unpacker mp;
|
||||
msgpack_unpacker_init(&mp);
|
||||
msgpack_unpack_context ctx = {0, Qnil};
|
||||
mp.user = ctx;
|
||||
msgpack_unpack_t mp;
|
||||
template_init(&mp);
|
||||
unpack_user u = {0, Qnil};
|
||||
mp.user = u;
|
||||
|
||||
rb_gc_disable();
|
||||
VALUE args[3] = {(VALUE)&mp, data, limit};
|
||||
|
Loading…
x
Reference in New Issue
Block a user