mirror of
https://github.com/msgpack/msgpack-c.git
synced 2025-10-13 14:45:38 +02:00
c and c++: rewritten and integrated
This commit is contained in:
@@ -1 +0,0 @@
|
||||
FURUHASHI Sadayuki <frsyuki _at_ users.sourceforge.jp>
|
14
cpp/COPYING
14
cpp/COPYING
@@ -1,14 +0,0 @@
|
||||
Copyright (C) 2008-2009 FURUHASHI Sadayuki
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
|
@@ -1,9 +1,7 @@
|
||||
lib_LTLIBRARIES = libmsgpack.la
|
||||
|
||||
libmsgpack_la_SOURCES = \
|
||||
object.cpp \
|
||||
unpack.cpp \
|
||||
zone.cpp
|
||||
object.cpp
|
||||
|
||||
nobase_include_HEADERS = \
|
||||
msgpack.hpp \
|
||||
@@ -28,7 +26,6 @@ noinst_HEADERS = \
|
||||
# FIXME
|
||||
object.lo: msgpack/type/tuple.hpp
|
||||
unpack.lo: msgpack/type/tuple.hpp msgpack/zone.hpp
|
||||
zone.lo: msgpack/type/tuple.hpp msgpack/zone.hpp
|
||||
|
||||
msgpack/type/tuple.hpp: msgpack/type/tuple.hpp.erb
|
||||
$(ERB) $< > $@.tmp
|
||||
@@ -42,6 +39,8 @@ MOSTLYCLEANFILES = \
|
||||
msgpack/type/tuple.hpp \
|
||||
msgpack/zone.hpp
|
||||
|
||||
libmsgpack_la_LIBADD = -L../c -lmsgpackc
|
||||
|
||||
# -version-info CURRENT:REVISION:AGE
|
||||
libmsgpack_la_LDFLAGS = -version-info 1:0:0
|
||||
|
||||
|
21
cpp/README
21
cpp/README
@@ -1,21 +0,0 @@
|
||||
MessagePack for C++
|
||||
-------------------
|
||||
MessagePack is a binary-based efficient data interchange format.
|
||||
|
||||
|
||||
|
||||
Copyright (C) 2008-2009 FURUHASHI Sadayuki
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
|
||||
|
@@ -1,3 +0,0 @@
|
||||
#!/bin/sh
|
||||
NO_NEST=1
|
||||
. ../bootstrap
|
@@ -1,23 +0,0 @@
|
||||
AC_INIT(object.cpp)
|
||||
AM_INIT_AUTOMAKE(msgpack, 0.1.0)
|
||||
AC_CONFIG_HEADER(config.h)
|
||||
|
||||
AC_SUBST(CXXFLAGS)
|
||||
if test "" = "$CXXFLAGS"; then
|
||||
CXXFLAGS="-g -O4"
|
||||
fi
|
||||
|
||||
AC_PROG_CXX
|
||||
AC_PROG_LIBTOOL
|
||||
|
||||
AC_CHECK_PROG(ERB, erb, erb)
|
||||
if test "x$ERB" = x; then
|
||||
AC_MSG_ERROR([cannot find erb. Ruby is needed to build.])
|
||||
fi
|
||||
|
||||
AC_CHECK_LIB(stdc++, main)
|
||||
|
||||
CXXFLAGS="-O4 -Wall $CXXFLAGS -I.."
|
||||
|
||||
AC_OUTPUT([Makefile])
|
||||
|
@@ -1,7 +1,7 @@
|
||||
//
|
||||
// MessagePack for C++ static resolution routine
|
||||
//
|
||||
// Copyright (C) 2008 FURUHASHI Sadayuki
|
||||
// Copyright (C) 2008-2009 FURUHASHI Sadayuki
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
|
@@ -1,7 +1,7 @@
|
||||
//
|
||||
// MessagePack for C++ static resolution routine
|
||||
//
|
||||
// Copyright (C) 2008 FURUHASHI Sadayuki
|
||||
// Copyright (C) 2008-2009 FURUHASHI Sadayuki
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
|
@@ -1,7 +1,7 @@
|
||||
//
|
||||
// MessagePack for C++ static resolution routine
|
||||
//
|
||||
// Copyright (C) 2008 FURUHASHI Sadayuki
|
||||
// Copyright (C) 2008-2009 FURUHASHI Sadayuki
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
|
@@ -1,7 +1,7 @@
|
||||
//
|
||||
// MessagePack for C++ static resolution routine
|
||||
//
|
||||
// Copyright (C) 2008 FURUHASHI Sadayuki
|
||||
// Copyright (C) 2008-2009 FURUHASHI Sadayuki
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
|
@@ -1,7 +1,7 @@
|
||||
//
|
||||
// MessagePack for C++ static resolution routine
|
||||
//
|
||||
// Copyright (C) 2008 FURUHASHI Sadayuki
|
||||
// Copyright (C) 2008-2009 FURUHASHI Sadayuki
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
|
@@ -1,7 +1,7 @@
|
||||
//
|
||||
// MessagePack for C++ static resolution routine
|
||||
//
|
||||
// Copyright (C) 2008 FURUHASHI Sadayuki
|
||||
// Copyright (C) 2008-2009 FURUHASHI Sadayuki
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
|
@@ -1,7 +1,7 @@
|
||||
//
|
||||
// MessagePack for C++ static resolution routine
|
||||
//
|
||||
// Copyright (C) 2008 FURUHASHI Sadayuki
|
||||
// Copyright (C) 2008-2009 FURUHASHI Sadayuki
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
|
@@ -1,7 +1,7 @@
|
||||
//
|
||||
// MessagePack for C++ static resolution routine
|
||||
//
|
||||
// Copyright (C) 2008 FURUHASHI Sadayuki
|
||||
// Copyright (C) 2008-2009 FURUHASHI Sadayuki
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
|
369
cpp/unpack.cpp
369
cpp/unpack.cpp
@@ -1,369 +0,0 @@
|
||||
//
|
||||
// MessagePack for C++ deserializing routine
|
||||
//
|
||||
// Copyright (C) 2008-2009 FURUHASHI Sadayuki
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
//
|
||||
#include "msgpack/unpack.hpp"
|
||||
#include "msgpack/unpack_define.h"
|
||||
#include <stdlib.h>
|
||||
|
||||
namespace msgpack {
|
||||
|
||||
|
||||
//namespace {
|
||||
struct unpack_user {
|
||||
zone* z;
|
||||
bool referenced;
|
||||
};
|
||||
//} // noname namespace
|
||||
|
||||
|
||||
#define msgpack_unpack_struct(name) \
|
||||
struct msgpack_unpacker ## name
|
||||
|
||||
#define msgpack_unpack_func(ret, name) \
|
||||
ret msgpack_unpacker ## name
|
||||
|
||||
#define msgpack_unpack_callback(name) \
|
||||
msgpack_unpack ## name
|
||||
|
||||
#define msgpack_unpack_object object
|
||||
|
||||
#define msgpack_unpack_user unpack_user
|
||||
|
||||
|
||||
struct msgpack_unpacker_context;
|
||||
|
||||
static void msgpack_unpacker_init(struct msgpack_unpacker_context* ctx);
|
||||
|
||||
static object msgpack_unpacker_data(struct msgpack_unpacker_context* ctx);
|
||||
|
||||
static int msgpack_unpacker_execute(struct msgpack_unpacker_context* ctx,
|
||||
const char* data, size_t len, size_t* off);
|
||||
|
||||
|
||||
static inline object msgpack_unpack_init(unpack_user* u)
|
||||
{ return object(); }
|
||||
|
||||
static inline object msgpack_unpack_uint8(unpack_user* u, uint8_t d)
|
||||
{ object o; o.type = type::POSITIVE_INTEGER; o.via.u64 = d; return o; }
|
||||
|
||||
static inline object msgpack_unpack_uint16(unpack_user* u, uint16_t d)
|
||||
{ object o; o.type = type::POSITIVE_INTEGER; o.via.u64 = d; return o; }
|
||||
|
||||
static inline object msgpack_unpack_uint32(unpack_user* u, uint32_t d)
|
||||
{ object o; o.type = type::POSITIVE_INTEGER; o.via.u64 = d; return o; }
|
||||
|
||||
static inline object msgpack_unpack_uint64(unpack_user* u, uint64_t d)
|
||||
{ object o; o.type = type::POSITIVE_INTEGER; o.via.u64 = d; return o; }
|
||||
|
||||
static inline object msgpack_unpack_int8(unpack_user* u, int8_t d)
|
||||
{ if(d >= 0) { object o; o.type = type::POSITIVE_INTEGER; o.via.u64 = d; return o; }
|
||||
else { object o; o.type = type::NEGATIVE_INTEGER; o.via.i64 = d; return o; } }
|
||||
|
||||
static inline object msgpack_unpack_int16(unpack_user* u, int16_t d)
|
||||
{ if(d >= 0) { object o; o.type = type::POSITIVE_INTEGER; o.via.u64 = d; return o; }
|
||||
else { object o; o.type = type::NEGATIVE_INTEGER; o.via.i64 = d; return o; } }
|
||||
|
||||
static inline object msgpack_unpack_int32(unpack_user* u, int32_t d)
|
||||
{ if(d >= 0) { object o; o.type = type::POSITIVE_INTEGER; o.via.u64 = d; return o; }
|
||||
else { object o; o.type = type::NEGATIVE_INTEGER; o.via.i64 = d; return o; } }
|
||||
|
||||
static inline object msgpack_unpack_int64(unpack_user* u, int64_t d)
|
||||
{ if(d >= 0) { object o; o.type = type::POSITIVE_INTEGER; o.via.u64 = d; return o; }
|
||||
else { object o; o.type = type::NEGATIVE_INTEGER; o.via.i64 = d; return o; } }
|
||||
|
||||
static inline object msgpack_unpack_float(unpack_user* u, float d)
|
||||
{ object o; o.type = type::DOUBLE; o.via.dec = d; return o; }
|
||||
|
||||
static inline object msgpack_unpack_double(unpack_user* u, double d)
|
||||
{ object o; o.type = type::DOUBLE; o.via.dec = d; return o; }
|
||||
|
||||
static inline object msgpack_unpack_nil(unpack_user* u)
|
||||
{ object o; o.type = type::NIL; return o; }
|
||||
|
||||
static inline object msgpack_unpack_true(unpack_user* u)
|
||||
{ object o; o.type = type::BOOLEAN; o.via.boolean = true; return o; }
|
||||
|
||||
static inline object msgpack_unpack_false(unpack_user* u)
|
||||
{ object o; o.type = type::BOOLEAN; o.via.boolean = false; return o; }
|
||||
|
||||
static inline object msgpack_unpack_array(unpack_user* u, unsigned int n)
|
||||
{
|
||||
object o;
|
||||
o.type = type::ARRAY;
|
||||
o.via.array.size = 0;
|
||||
o.via.array.ptr = (object*)u->z->malloc(n*sizeof(object));
|
||||
return o;
|
||||
}
|
||||
|
||||
static inline void msgpack_unpack_array_item(unpack_user* u, object* c, object o)
|
||||
{ c->via.array.ptr[c->via.array.size++] = o; }
|
||||
|
||||
static inline object msgpack_unpack_map(unpack_user* u, unsigned int n)
|
||||
{
|
||||
object o;
|
||||
o.type = type::MAP;
|
||||
o.via.map.size = 0;
|
||||
o.via.map.ptr = (object_kv*)u->z->malloc(n*sizeof(object_kv));
|
||||
return o;
|
||||
}
|
||||
|
||||
static inline void msgpack_unpack_map_item(unpack_user* u, object* c, object k, object v)
|
||||
{
|
||||
c->via.map.ptr[c->via.map.size].key = k;
|
||||
c->via.map.ptr[c->via.map.size].val = v;
|
||||
++c->via.map.size;
|
||||
}
|
||||
|
||||
static inline object msgpack_unpack_raw(unpack_user* u, const char* b, const char* p, unsigned int l)
|
||||
{
|
||||
object o;
|
||||
o.type = type::RAW;
|
||||
o.via.raw.ptr = p;
|
||||
o.via.raw.size = l;
|
||||
u->referenced = true;
|
||||
return o;
|
||||
}
|
||||
|
||||
#include "msgpack/unpack_template.h"
|
||||
|
||||
|
||||
namespace {
|
||||
struct context {
|
||||
context()
|
||||
{
|
||||
msgpack_unpacker_init(&m_ctx);
|
||||
unpack_user u = {NULL, false};
|
||||
m_ctx.user = u;
|
||||
}
|
||||
|
||||
~context() { }
|
||||
|
||||
int execute(const char* data, size_t len, size_t* off)
|
||||
{
|
||||
return msgpack_unpacker_execute(&m_ctx, data, len, off);
|
||||
}
|
||||
|
||||
object data()
|
||||
{
|
||||
return msgpack_unpacker_data(&m_ctx);
|
||||
}
|
||||
|
||||
void reset()
|
||||
{
|
||||
zone* z = m_ctx.user.z;
|
||||
msgpack_unpacker_init(&m_ctx);
|
||||
unpack_user u = {z, false};
|
||||
m_ctx.user = u;
|
||||
}
|
||||
|
||||
void set_zone(zone* z)
|
||||
{
|
||||
m_ctx.user.z = z;
|
||||
}
|
||||
|
||||
bool is_referenced() const
|
||||
{
|
||||
return m_ctx.user.referenced;
|
||||
}
|
||||
|
||||
private:
|
||||
msgpack_unpacker_context m_ctx;
|
||||
zone* m_zone;
|
||||
|
||||
private:
|
||||
context(const context&);
|
||||
};
|
||||
|
||||
static inline context* as_ctx(void* m)
|
||||
{
|
||||
return reinterpret_cast<context*>(m);
|
||||
}
|
||||
|
||||
|
||||
static const size_t COUNTER_SIZE = sizeof(unsigned int);
|
||||
|
||||
static inline void init_count(void* buffer)
|
||||
{
|
||||
*(volatile unsigned int*)buffer = 1;
|
||||
}
|
||||
|
||||
static inline void decl_count(void* buffer)
|
||||
{
|
||||
//if(--*(unsigned int*)buffer == 0) {
|
||||
if(__sync_sub_and_fetch((unsigned int*)buffer, 1) == 0) {
|
||||
free(buffer);
|
||||
}
|
||||
}
|
||||
|
||||
static inline void incr_count(void* buffer)
|
||||
{
|
||||
//++*(unsigned int*)buffer;
|
||||
__sync_add_and_fetch((unsigned int*)buffer, 1);
|
||||
}
|
||||
|
||||
static inline unsigned int get_count(void* buffer)
|
||||
{
|
||||
return *(volatile unsigned int*)buffer;
|
||||
}
|
||||
|
||||
} // noname namespace
|
||||
|
||||
|
||||
unpacker::unpacker(size_t initial_buffer_size) :
|
||||
m_buffer(NULL),
|
||||
m_used(0),
|
||||
m_free(0),
|
||||
m_off(0),
|
||||
m_zone(new zone()),
|
||||
m_ctx(new context()),
|
||||
m_initial_buffer_size(initial_buffer_size)
|
||||
{
|
||||
if(m_initial_buffer_size < COUNTER_SIZE) {
|
||||
m_initial_buffer_size = COUNTER_SIZE;
|
||||
}
|
||||
|
||||
as_ctx(m_ctx)->set_zone(m_zone.get());
|
||||
|
||||
m_buffer = (char*)::malloc(m_initial_buffer_size);
|
||||
if(!m_buffer) { throw std::bad_alloc(); }
|
||||
init_count(m_buffer);
|
||||
|
||||
m_used = COUNTER_SIZE;
|
||||
m_free = m_initial_buffer_size - m_used;
|
||||
m_off = COUNTER_SIZE;
|
||||
}
|
||||
|
||||
|
||||
unpacker::~unpacker()
|
||||
{
|
||||
delete as_ctx(m_ctx);
|
||||
decl_count(m_buffer);
|
||||
}
|
||||
|
||||
void unpacker::expand_buffer(size_t len)
|
||||
{
|
||||
if(m_used == m_off && get_count(m_buffer) == 1 &&
|
||||
!as_ctx(m_ctx)->is_referenced()) {
|
||||
// rewind buffer
|
||||
m_free += m_used - COUNTER_SIZE;
|
||||
m_used = COUNTER_SIZE;
|
||||
m_off = COUNTER_SIZE;
|
||||
if(m_free >= len) { return; }
|
||||
}
|
||||
|
||||
if(m_off == COUNTER_SIZE) {
|
||||
size_t next_size = (m_used + m_free) * 2;
|
||||
while(next_size < len + m_used) { next_size *= 2; }
|
||||
|
||||
char* tmp = (char*)::realloc(m_buffer, next_size);
|
||||
if(!tmp) { throw std::bad_alloc(); }
|
||||
|
||||
m_buffer = tmp;
|
||||
m_free = next_size - m_used;
|
||||
|
||||
} else {
|
||||
size_t next_size = m_initial_buffer_size; // include COUNTER_SIZE
|
||||
size_t not_parsed = m_used - m_off;
|
||||
while(next_size < len + not_parsed + COUNTER_SIZE) { next_size *= 2; }
|
||||
|
||||
char* tmp = (char*)::malloc(next_size);
|
||||
if(!tmp) { throw std::bad_alloc(); }
|
||||
init_count(tmp);
|
||||
|
||||
try {
|
||||
m_zone->push_finalizer(decl_count, m_buffer);
|
||||
} catch (...) { free(tmp); throw; }
|
||||
|
||||
memcpy(tmp+COUNTER_SIZE, m_buffer+m_off, not_parsed);
|
||||
|
||||
m_buffer = tmp;
|
||||
m_used = not_parsed + COUNTER_SIZE;
|
||||
m_free = next_size - m_used;
|
||||
m_off = COUNTER_SIZE;
|
||||
}
|
||||
}
|
||||
|
||||
bool unpacker::execute()
|
||||
{
|
||||
int ret = as_ctx(m_ctx)->execute(m_buffer, m_used, &m_off);
|
||||
if(ret < 0) {
|
||||
throw unpack_error("parse error");
|
||||
} else if(ret == 0) {
|
||||
return false;
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
zone* unpacker::release_zone()
|
||||
{
|
||||
m_zone->push_finalizer(decl_count, m_buffer);
|
||||
incr_count(m_buffer);
|
||||
|
||||
//std::auto_ptr<zone> old(new zone());
|
||||
//m_zone.swap(old);
|
||||
zone* n = new zone();
|
||||
std::auto_ptr<zone> old(m_zone.release());
|
||||
m_zone.reset(n);
|
||||
|
||||
as_ctx(m_ctx)->set_zone(m_zone.get());
|
||||
|
||||
return old.release();
|
||||
}
|
||||
|
||||
object unpacker::data()
|
||||
{
|
||||
return as_ctx(m_ctx)->data();
|
||||
}
|
||||
|
||||
void unpacker::reset()
|
||||
{
|
||||
//if(!m_zone->empty()) { delete release_zone(); }
|
||||
as_ctx(m_ctx)->reset();
|
||||
}
|
||||
|
||||
|
||||
object unpacker::unpack(const char* data, size_t len, zone& z, size_t* off)
|
||||
{
|
||||
context ctx;
|
||||
ctx.set_zone(&z);
|
||||
if(off) {
|
||||
size_t noff = *off;
|
||||
int ret = ctx.execute(data, len, &noff);
|
||||
if(ret < 0) {
|
||||
throw unpack_error("parse error");
|
||||
} else if(ret == 0) {
|
||||
throw unpack_error("insufficient bytes");
|
||||
}
|
||||
*off = noff;
|
||||
} else {
|
||||
size_t noff = 0;
|
||||
int ret = ctx.execute(data, len, &noff);
|
||||
if(ret < 0) {
|
||||
throw unpack_error("parse error");
|
||||
} else if(ret == 0) {
|
||||
throw unpack_error("insufficient bytes");
|
||||
} else if(noff < len) {
|
||||
throw unpack_error("extra bytes");
|
||||
}
|
||||
}
|
||||
return ctx.data();
|
||||
}
|
||||
|
||||
|
||||
} // namespace msgpack
|
||||
|
171
cpp/unpack.hpp
171
cpp/unpack.hpp
@@ -18,6 +18,7 @@
|
||||
#ifndef MSGPACK_UNPACK_HPP__
|
||||
#define MSGPACK_UNPACK_HPP__
|
||||
|
||||
#include "msgpack/unpack.h"
|
||||
#include "msgpack/object.hpp"
|
||||
#include "msgpack/zone.hpp"
|
||||
#include <memory>
|
||||
@@ -36,21 +37,21 @@ struct unpack_error : public std::runtime_error {
|
||||
};
|
||||
|
||||
|
||||
class unpacker {
|
||||
class unpacker : public msgpack_unpacker {
|
||||
public:
|
||||
unpacker(size_t initial_buffer_size = MSGPACK_UNPACKER_DEFAULT_INITIAL_BUFFER_SIZE);
|
||||
~unpacker();
|
||||
|
||||
public:
|
||||
/*! 1. reserve buffer. at least `len' bytes of capacity will be ready */
|
||||
void reserve_buffer(size_t len);
|
||||
/*! 1. reserve buffer. at least `size' bytes of capacity will be ready */
|
||||
void reserve_buffer(size_t size);
|
||||
|
||||
/*! 2. read data to the buffer() up to buffer_capacity() bytes */
|
||||
char* buffer();
|
||||
size_t buffer_capacity() const;
|
||||
|
||||
/*! 3. specify the number of bytes actually copied */
|
||||
void buffer_consumed(size_t len);
|
||||
void buffer_consumed(size_t size);
|
||||
|
||||
/*! 4. repeat execute() until it retunrs false */
|
||||
bool execute();
|
||||
@@ -114,71 +115,157 @@ public:
|
||||
size_t nonparsed_size() const;
|
||||
|
||||
/*! skip specified size of non-parsed buffer, leaving the buffer */
|
||||
// Note that the `len' argument must be smaller than nonparsed_size()
|
||||
void skip_nonparsed_buffer(size_t len);
|
||||
// Note that the `size' argument must be smaller than nonparsed_size()
|
||||
void skip_nonparsed_buffer(size_t size);
|
||||
|
||||
/*! remove unparsed buffer from unpacker */
|
||||
// Note that reset() leaves non-parsed buffer.
|
||||
void remove_nonparsed_buffer();
|
||||
|
||||
private:
|
||||
char* m_buffer;
|
||||
size_t m_used;
|
||||
size_t m_free;
|
||||
size_t m_off;
|
||||
|
||||
std::auto_ptr<zone> m_zone;
|
||||
|
||||
void* m_ctx;
|
||||
|
||||
size_t m_initial_buffer_size;
|
||||
|
||||
private:
|
||||
void expand_buffer(size_t len);
|
||||
|
||||
private:
|
||||
unpacker(const unpacker&);
|
||||
|
||||
public:
|
||||
static object unpack(const char* data, size_t len, zone& z, size_t* off = NULL);
|
||||
};
|
||||
|
||||
|
||||
inline void unpacker::reserve_buffer(size_t len)
|
||||
typedef enum {
|
||||
MSGPACK_UNPACK_SUCCESS = 2,
|
||||
MSGPACK_UNPACK_EXTRA_BYTES = 1,
|
||||
MSGPACK_UNPACK_CONTINUE = 0,
|
||||
MSGPACK_UNPACK_PARSE_ERROR = -1,
|
||||
} unpack_return;
|
||||
|
||||
static unpack_return unpack(const char* data, size_t len, size_t* off,
|
||||
zone* z, object* result);
|
||||
|
||||
|
||||
// obsolete
|
||||
static object unpack(const char* data, size_t len, zone& z, size_t* off = NULL);
|
||||
|
||||
|
||||
inline unpacker::unpacker(size_t initial_buffer_size)
|
||||
{
|
||||
if(m_free >= len) { return; }
|
||||
expand_buffer(len);
|
||||
if(!msgpack_unpacker_init(this, initial_buffer_size)) {
|
||||
throw std::bad_alloc();
|
||||
}
|
||||
}
|
||||
|
||||
inline unpacker::~unpacker()
|
||||
{
|
||||
msgpack_unpacker_destroy(this);
|
||||
}
|
||||
|
||||
inline void unpacker::reserve_buffer(size_t size)
|
||||
{
|
||||
if(!msgpack_unpacker_reserve_buffer(this, size)) {
|
||||
throw std::bad_alloc();
|
||||
}
|
||||
}
|
||||
|
||||
inline char* unpacker::buffer()
|
||||
{ return m_buffer + m_used; }
|
||||
{
|
||||
return msgpack_unpacker_buffer(this);
|
||||
}
|
||||
|
||||
inline size_t unpacker::buffer_capacity() const
|
||||
{ return m_free; }
|
||||
|
||||
inline void unpacker::buffer_consumed(size_t len)
|
||||
{
|
||||
m_used += len;
|
||||
m_free -= len;
|
||||
return msgpack_unpacker_buffer_capacity(this);
|
||||
}
|
||||
|
||||
inline void unpacker::buffer_consumed(size_t size)
|
||||
{
|
||||
return msgpack_unpacker_buffer_consumed(this, size);
|
||||
}
|
||||
|
||||
|
||||
inline bool unpacker::execute()
|
||||
{
|
||||
int ret = msgpack_unpacker_execute(this);
|
||||
if(ret < 0) {
|
||||
throw unpack_error("parse error");
|
||||
} else if(ret == 0) {
|
||||
return false;
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
inline object unpacker::data()
|
||||
{
|
||||
msgpack_object obj = msgpack_unpacker_data(this);
|
||||
return *reinterpret_cast<object*>(&obj);
|
||||
}
|
||||
|
||||
inline zone* unpacker::release_zone()
|
||||
{
|
||||
if(!msgpack_unpacker_flush_zone(this)) {
|
||||
throw std::bad_alloc();
|
||||
}
|
||||
|
||||
zone* r = new zone();
|
||||
|
||||
msgpack_zone old = *this->z;
|
||||
*this->z = *z;
|
||||
*z = old;
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
inline void unpacker::reset()
|
||||
{
|
||||
msgpack_unpacker_reset(this);
|
||||
}
|
||||
|
||||
|
||||
inline char* unpacker::nonparsed_buffer()
|
||||
{ return m_buffer + m_off; }
|
||||
{
|
||||
return buf + off;
|
||||
}
|
||||
|
||||
inline size_t unpacker::nonparsed_size() const
|
||||
{ return m_used - m_off; }
|
||||
{
|
||||
return used - off;
|
||||
}
|
||||
|
||||
inline void unpacker::skip_nonparsed_buffer(size_t len)
|
||||
{ m_off += len; }
|
||||
inline void unpacker::skip_nonparsed_buffer(size_t size)
|
||||
{
|
||||
off += size;
|
||||
}
|
||||
|
||||
inline void unpacker::remove_nonparsed_buffer()
|
||||
{ m_used = m_off; }
|
||||
|
||||
|
||||
inline object unpack(const char* data, size_t len, zone& z, size_t* off = NULL)
|
||||
{
|
||||
return unpacker::unpack(data, len, z, off);
|
||||
used = off;
|
||||
}
|
||||
|
||||
|
||||
inline unpack_return unpack(const char* data, size_t len, size_t* off,
|
||||
zone* z, object* result)
|
||||
{
|
||||
return (unpack_return)msgpack_unpack(data, len, off,
|
||||
z, reinterpret_cast<msgpack_object*>(result));
|
||||
}
|
||||
|
||||
inline object unpack(const char* data, size_t len, zone& z, size_t* off)
|
||||
{
|
||||
object result;
|
||||
|
||||
switch( msgpack::unpack(data, len, off, &z, &result) ) {
|
||||
case MSGPACK_UNPACK_SUCCESS:
|
||||
return result;
|
||||
|
||||
case MSGPACK_UNPACK_EXTRA_BYTES:
|
||||
if(off) {
|
||||
return result;
|
||||
} else {
|
||||
throw unpack_error("extra bytes");
|
||||
}
|
||||
|
||||
case MSGPACK_UNPACK_CONTINUE:
|
||||
throw unpack_error("insufficient bytes");
|
||||
|
||||
case MSGPACK_UNPACK_PARSE_ERROR:
|
||||
default:
|
||||
throw unpack_error("parse error");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
100
cpp/zone.cpp
100
cpp/zone.cpp
@@ -1,100 +0,0 @@
|
||||
//
|
||||
// MessagePack for C++ memory pool
|
||||
//
|
||||
// Copyright (C) 2008-2009 FURUHASHI Sadayuki
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
//
|
||||
#include "msgpack/zone.hpp"
|
||||
#include <algorithm>
|
||||
|
||||
namespace msgpack {
|
||||
|
||||
|
||||
zone::zone(size_t chunk_size) :
|
||||
m_chunk_size(chunk_size)
|
||||
{
|
||||
chunk dummy = {0, NULL, NULL};
|
||||
m_chunk_array.push_back(dummy);
|
||||
}
|
||||
|
||||
zone::~zone()
|
||||
{
|
||||
clear();
|
||||
}
|
||||
|
||||
namespace {
|
||||
template <typename Private>
|
||||
struct zone_finalize {
|
||||
void operator() (Private& f) {
|
||||
(*f.func)(f.obj);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Private>
|
||||
struct zone_free {
|
||||
void operator() (Private& c) {
|
||||
::free(c.alloc);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
void zone::clear()
|
||||
{
|
||||
std::for_each(m_finalizers.rbegin(), m_finalizers.rend(),
|
||||
zone_finalize<finalizer>());
|
||||
m_finalizers.clear();
|
||||
|
||||
std::for_each(m_chunk_array.begin(), m_chunk_array.end(),
|
||||
zone_free<chunk>());
|
||||
m_chunk_array.resize(1);
|
||||
m_chunk_array[0].ptr = NULL;
|
||||
m_chunk_array[0].free = 0;
|
||||
}
|
||||
|
||||
bool zone::empty() const
|
||||
{
|
||||
return m_chunk_array.back().alloc == NULL &&
|
||||
m_finalizers.empty();
|
||||
}
|
||||
|
||||
void* zone::malloc(size_t size)
|
||||
{
|
||||
if(m_chunk_array.back().free > size) {
|
||||
char* p = (char*)m_chunk_array.back().ptr;
|
||||
m_chunk_array.back().ptr = p + size;
|
||||
m_chunk_array.back().free -= size;
|
||||
return p;
|
||||
}
|
||||
|
||||
size_t sz = m_chunk_size;
|
||||
while(sz < size) { sz *= 2; }
|
||||
|
||||
chunk dummy = {0, NULL, NULL};
|
||||
m_chunk_array.push_back(dummy);
|
||||
|
||||
char* p = (char*)::malloc(sz);
|
||||
if(!p) {
|
||||
m_chunk_array.pop_back();
|
||||
throw std::bad_alloc();
|
||||
}
|
||||
|
||||
m_chunk_array.back().free = sz - size;
|
||||
m_chunk_array.back().ptr = p + size;
|
||||
m_chunk_array.back().alloc = p;
|
||||
return p;
|
||||
}
|
||||
|
||||
|
||||
} // namespace msgpack
|
||||
|
@@ -19,17 +19,15 @@
|
||||
#define MSGPACK_ZONE_HPP__
|
||||
|
||||
#include "msgpack/object.hpp"
|
||||
#include "msgpack/zone.h"
|
||||
#include <cstdlib>
|
||||
#include <vector>
|
||||
|
||||
#ifndef MSGPACK_ZONE_CHUNK_SIZE
|
||||
#define MSGPACK_ZONE_CHUNK_SIZE 2048
|
||||
#endif
|
||||
<% GENERATION_LIMIT = 15 %>
|
||||
namespace msgpack {
|
||||
|
||||
|
||||
class zone {
|
||||
class zone : public msgpack_zone {
|
||||
public:
|
||||
zone(size_t chunk_size = MSGPACK_ZONE_CHUNK_SIZE);
|
||||
~zone();
|
||||
@@ -37,11 +35,7 @@ public:
|
||||
public:
|
||||
void* malloc(size_t size);
|
||||
|
||||
void push_finalizer(void (*func)(void*), void* obj);
|
||||
|
||||
void clear();
|
||||
|
||||
bool empty() const;
|
||||
void push_finalizer(void (*func)(void*), void* data);
|
||||
|
||||
<%0.upto(GENERATION_LIMIT) {|i|%>
|
||||
template <typename T<%1.upto(i) {|j|%>, typename A<%=j%><%}%>>
|
||||
@@ -49,35 +43,39 @@ public:
|
||||
<%}%>
|
||||
|
||||
private:
|
||||
struct chunk {
|
||||
size_t free;
|
||||
void* ptr;
|
||||
void* alloc;
|
||||
};
|
||||
|
||||
std::vector<chunk> m_chunk_array;
|
||||
|
||||
struct finalizer {
|
||||
void (*func)(void*);
|
||||
void* obj;
|
||||
};
|
||||
|
||||
std::vector<finalizer> m_finalizers;
|
||||
|
||||
template <typename T>
|
||||
static void object_destructor(void* obj);
|
||||
|
||||
size_t m_chunk_size;
|
||||
|
||||
private:
|
||||
zone(const zone&);
|
||||
};
|
||||
|
||||
|
||||
inline void zone::push_finalizer(void (*func)(void*), void* obj)
|
||||
|
||||
inline zone::zone(size_t chunk_size)
|
||||
{
|
||||
finalizer f = {func, obj};
|
||||
m_finalizers.push_back(f);
|
||||
msgpack_zone_init(this, chunk_size);
|
||||
}
|
||||
|
||||
inline zone::~zone()
|
||||
{
|
||||
msgpack_zone_destroy(this);
|
||||
}
|
||||
|
||||
inline void* zone::malloc(size_t size)
|
||||
{
|
||||
void* ptr = msgpack_zone_malloc(this, size);
|
||||
if(!ptr) {
|
||||
throw std::bad_alloc();
|
||||
}
|
||||
return ptr;
|
||||
}
|
||||
|
||||
inline void zone::push_finalizer(void (*func)(void*), void* data)
|
||||
{
|
||||
if(!msgpack_zone_push_finalizer(this, func, data)) {
|
||||
throw std::bad_alloc();
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
@@ -93,7 +91,7 @@ T* zone::allocate(<%=(1..i).map{|j|"A#{j} a#{j}"}.join(', ')%>)
|
||||
void* x = malloc(sizeof(T));
|
||||
push_finalizer(&zone::object_destructor<T>, x);
|
||||
try { return new (x) T(<%=(1..i).map{|j|"a#{j}"}.join(', ')%>); }
|
||||
catch (...) { m_finalizers.pop_back(); throw; }
|
||||
catch (...) { --finalizer_array.tail; throw; }
|
||||
}
|
||||
<%}%>
|
||||
|
||||
@@ -101,3 +99,4 @@ T* zone::allocate(<%=(1..i).map{|j|"A#{j} a#{j}"}.join(', ')%>)
|
||||
|
||||
#endif /* msgpack/zone.hpp */
|
||||
|
||||
// vim: ft=cpp ts=4 sw=4 softtabstop=4 noexpandtab smarttab
|
||||
|
Reference in New Issue
Block a user