summaryrefslogtreecommitdiff
path: root/c
diff options
context:
space:
mode:
Diffstat (limited to 'c')
-rw-r--r--c/AUTHORS1
-rw-r--r--c/COPYING14
-rw-r--r--c/ChangeLog0
-rw-r--r--c/NEWS0
-rw-r--r--c/README21
-rwxr-xr-xc/bootstrap3
-rw-r--r--c/configure.in16
-rw-r--r--c/object.c213
-rw-r--r--c/object.h25
-rw-r--r--c/pack.h87
-rw-r--r--c/unpack.c378
-rw-r--r--c/unpack.h109
-rw-r--r--c/zone.c251
-rw-r--r--c/zone.h49
14 files changed, 741 insertions, 426 deletions
diff --git a/c/AUTHORS b/c/AUTHORS
deleted file mode 100644
index ababacb..0000000
--- a/c/AUTHORS
+++ /dev/null
@@ -1 +0,0 @@
-FURUHASHI Sadayuki <frsyuki _at_ users.sourceforge.jp>
diff --git a/c/COPYING b/c/COPYING
deleted file mode 100644
index 6f5f220..0000000
--- a/c/COPYING
+++ /dev/null
@@ -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.
-
diff --git a/c/ChangeLog b/c/ChangeLog
deleted file mode 100644
index e69de29..0000000
--- a/c/ChangeLog
+++ /dev/null
diff --git a/c/NEWS b/c/NEWS
deleted file mode 100644
index e69de29..0000000
--- a/c/NEWS
+++ /dev/null
diff --git a/c/README b/c/README
deleted file mode 100644
index 76dc221..0000000
--- a/c/README
+++ /dev/null
@@ -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.
-
-
diff --git a/c/bootstrap b/c/bootstrap
deleted file mode 100755
index 7e61b82..0000000
--- a/c/bootstrap
+++ /dev/null
@@ -1,3 +0,0 @@
-#!/bin/sh
-NO_NEST=1
-. ../bootstrap
diff --git a/c/configure.in b/c/configure.in
deleted file mode 100644
index 47eb8aa..0000000
--- a/c/configure.in
+++ /dev/null
@@ -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])
-
diff --git a/c/object.c b/c/object.c
index 6376438..871153d 100644
--- a/c/object.c
+++ b/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)
-{
- 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;
-}
-
-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;
-}
-
-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;
-}
-
-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;
-}
-
-static inline msgpack_object msgpack_unpack_raw(unpack_user* u, const char* b, const char* p, unsigned int l)
+void msgpack_object_print(FILE* out, msgpack_object o)
{
- msgpack_object o;
- o.type = MSGPACK_OBJECT_RAW;
- o.via.raw.ptr = p;
- o.via.raw.size = l;
- u->referenced = true;
- return o;
-}
-
-#include "msgpack/unpack_template.h"
-
-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;
-
- 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;
+ switch(o.type) {
+ case MSGPACK_OBJECT_NIL:
+ fprintf(out, "nil");
+ break;
+
+ case MSGPACK_OBJECT_BOOLEAN:
+ fprintf(out, (o.via.boolean ? "true" : "false"));
+ break;
+
+ case MSGPACK_OBJECT_POSITIVE_INTEGER:
+ fprintf(out, "%"PRIu64, o.via.u64);
+ break;
+
+ case MSGPACK_OBJECT_NEGATIVE_INTEGER:
+ fprintf(out, "%"PRIi64, o.via.i64);
+ break;
+
+ case MSGPACK_OBJECT_DOUBLE:
+ fprintf(out, "%f", o.via.dec);
+ break;
+
+ case MSGPACK_OBJECT_RAW:
+ fprintf(out, "\"");
+ fwrite(o.via.raw.ptr, o.via.raw.size, 1, out);
+ fprintf(out, "\"");
+ break;
+
+ 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
+
+ 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;
}
-
diff --git a/c/object.h b/c/object.h
index b590ebe..7c603b3 100644
--- a/c/object.h
+++ b/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
diff --git a/c/pack.h b/c/pack.h
index a510eff..46de722 100644
--- a/c/pack.h
+++ b/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);
}
diff --git a/c/unpack.c b/c/unpack.c
index 03c67be..e06d97c 100644
--- a/c/unpack.c
+++ b/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 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(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_map(msgpack_unpack_t* x, unsigned int n)
-{ return x->callback.unpack_map(x->data, n); }
+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_item(msgpack_unpack_t* x, void** c, void* k, void* v)
-{ x->callback.unpack_map_item(x->data, *c, k, v); }
+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_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)
+{
+ *(volatile unsigned int*)buf = 1;
+}
+
+static inline void decl_count(void* buf)
+{
+ //if(--*(unsigned int*)buf == 0) {
+ if(__sync_sub_and_fetch((unsigned int*)buf, 1) == 0) {
+ free(buf);
+ }
+}
+
+static inline void incr_count(void* buf)
+{
+ //++*(unsigned int*)buf;
+ __sync_add_and_fetch((unsigned int*)buf, 1);
+}
+
+static inline unsigned int get_count(void* buf)
+{
+ return *(volatile unsigned int*)buf;
+}
+
+
+
+bool msgpack_unpacker_init(msgpack_unpacker* mpac, size_t initial_buffer_size)
{
- 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;
+ 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_unpack_free(msgpack_unpack_t* ctx)
+void msgpack_unpacker_destroy(msgpack_unpacker* mpac)
{
- free((struct template_context*)ctx);
+ msgpack_zone_free(mpac->z);
+ free(mpac->ctx);
+ decl_count(mpac->buf);
}
-void* msgpack_unpack_data(msgpack_unpack_t* ctx)
+
+msgpack_unpacker* msgpack_unpacker_new(size_t initial_buffer_size)
{
- return template_func_data((struct template_context*)ctx);
+ 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_unpack_reset(msgpack_unpack_t* ctx)
+void msgpack_unpacker_free(msgpack_unpacker* mpac)
{
- msgpack_unpack_t x = ((struct template_context*)ctx)->user;
- template_func_init((struct template_context*)ctx);
- ((struct template_context*)ctx)->user = x;
+ msgpack_unpacker_destroy(mpac);
+ free(mpac);
}
-int msgpack_unpack_execute(msgpack_unpack_t* ctx,
- const char* data, size_t len, size_t* off)
+
+bool msgpack_unpacker_expand_buffer(msgpack_unpacker* mpac, size_t size)
{
- return template_func_execute(
- (struct template_context*)ctx,
- data, len, off);
+ 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;
+}
diff --git a/c/unpack.h b/c/unpack.h
index 4977f51..ab202a1 100644
--- a/c/unpack.h
+++ b/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 {
- 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);
-
-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);
+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;
+
+
+bool msgpack_unpacker_init(msgpack_unpacker* mpac, size_t initial_buffer_size);
+void msgpack_unpacker_destroy(msgpack_unpacker* mpac);
+
+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
diff --git a/c/zone.c b/c/zone.c
index ccd702d..e891c82 100644
--- a/c/zone.c
+++ b/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)
+{
+ // glibcは72バイト以下のmallocが高速
+ const size_t nfirst = (sizeof(msgpack_zone_chunk) < 72/2) ?
+ 72 / sizeof(msgpack_zone_chunk) : 8;
+
+ msgpack_zone_chunk* array = (msgpack_zone_chunk*)malloc(
+ sizeof(msgpack_zone_chunk) * nfirst);
+ if(!array) {
+ return false;
+ }
+
+ 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;
+}
+
+static inline void destroy_chunk_array(msgpack_zone_chunk_array* ca)
{
- return calloc(1, sizeof(msgpack_zone));
+ msgpack_zone_chunk* chunk = ca->array;
+ for(; chunk != ca->tail+1; ++chunk) {
+ free(chunk->alloc);
+ }
+ free(ca->array);
}
-void msgpack_zone_free(msgpack_zone* z)
+void* msgpack_zone_malloc(msgpack_zone* zone, size_t size)
{
- if(z->array) {
- size_t i;
- for(i=0; i <= z->ntail; ++i) {
- free(z->array[i].alloc);
+ 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;
}
+
+ ca->array = chunk;
+ ca->end = chunk + nnext;
+ chunk = ca->tail = chunk + nused;
+ }
+
+ size_t sz = zone->chunk_size;
+
+ while(sz < size) {
+ sz *= 2;
+ }
+
+ char* ptr = (char*)malloc(sz);
+ if(!ptr) {
+ return NULL;
}
- free(z);
+
+ chunk->free = sz - size;
+ chunk->ptr = ptr + size;
+ chunk->alloc = ptr;
+
+ return ptr;
}
-void* msgpack_zone_malloc(msgpack_zone* z, size_t size)
+static inline void init_finalizer_array(msgpack_zone_finalizer_array* fa)
{
- 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; }
-
- size_t sz = 2048; /* FIXME chunk_size */
- while(sz < size) { sz *= 2; }
- char* p = (char*)malloc(sz);
- if(!p) {
- free(array);
- return NULL;
+ 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;
}
- z->array = array;
- z->usable = n - 1;
- array[0].free = sz - size;
- array[0].ptr = p + size;
- array[0].alloc = p;
- return p;
+ fa->array = fin;
+ fa->end = fin + nnext;
+ fin = fa->tail = fin + 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;
+ 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;
}
- 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;
+ 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;
}
- size_t sz = 2048; /* FIXME chunk_size */
- while(sz < size) { sz *= 2; }
- char* p = (char*)malloc(sz);
- if(!p) { return NULL; }
+ if(!msgpack_zone_init(zone, chunk_size)) {
+ free(zone);
+ return NULL;
+ }
+
+ return zone;
+}
- ++z->ntail;
- z->array[z->ntail].free = sz - size;
- z->array[z->ntail].ptr = p + size;
- z->array[z->ntail].alloc = p;
- return p;
+void msgpack_zone_free(msgpack_zone* zone)
+{
+ msgpack_zone_destroy(zone);
+ free(zone);
}
diff --git a/c/zone.h b/c/zone.h
index ff6ca62..3dc9f52 100644
--- a/c/zone.h
+++ b/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