c and c++: rewritten and integrated

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

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