c and c++: rewritten and integrated

This commit is contained in:
frsyuki 2009-02-22 15:14:21 +09:00
parent 761b398083
commit 11abec1093
44 changed files with 1035 additions and 1124 deletions

View File

@ -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.

View File

@ -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
View File

@ -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.

View File

@ -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"

View File

@ -1 +0,0 @@
FURUHASHI Sadayuki <frsyuki _at_ users.sourceforge.jp>

View File

@ -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.

View File

0
c/NEWS
View File

View File

@ -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.

View File

@ -1,3 +0,0 @@
#!/bin/sh
NO_NEST=1
. ../bootstrap

View File

@ -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])

View File

@ -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;
}

View File

@ -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

View File

@ -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);
}

View File

@ -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;
}

View File

@ -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
View File

@ -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);
}

View File

@ -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

View File

@ -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])

View File

@ -1 +0,0 @@
FURUHASHI Sadayuki <frsyuki _at_ users.sourceforge.jp>

View File

@ -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.

View File

View File

@ -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

View File

View File

@ -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.

View File

@ -1,3 +0,0 @@
#!/bin/sh
NO_NEST=1
. ../bootstrap

View File

@ -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])

View File

@ -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.

View File

@ -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.

View File

@ -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.

View File

@ -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.

View File

@ -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.

View File

@ -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.

View File

@ -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.

View File

@ -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.

View File

@ -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

View File

@ -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");
}
}

View File

@ -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

View File

@ -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

View File

@ -10,6 +10,7 @@
class Server {
public:
Server(int sock) : m_sock(sock) { }
~Server() { }
typedef std::auto_ptr<msgpack::zone> auto_zone;

View File

@ -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;

View File

@ -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

View File

@ -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/

View File

@ -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};