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

View File

@@ -1,9 +1,7 @@
lib_LTLIBRARIES = libmsgpack.la
libmsgpack_la_SOURCES = \
object.cpp \
unpack.cpp \
zone.cpp
object.cpp
nobase_include_HEADERS = \
msgpack.hpp \
@@ -28,7 +26,6 @@ noinst_HEADERS = \
# FIXME
object.lo: msgpack/type/tuple.hpp
unpack.lo: msgpack/type/tuple.hpp msgpack/zone.hpp
zone.lo: msgpack/type/tuple.hpp msgpack/zone.hpp
msgpack/type/tuple.hpp: msgpack/type/tuple.hpp.erb
$(ERB) $< > $@.tmp
@@ -42,6 +39,8 @@ MOSTLYCLEANFILES = \
msgpack/type/tuple.hpp \
msgpack/zone.hpp
libmsgpack_la_LIBADD = -L../c -lmsgpackc
# -version-info CURRENT:REVISION:AGE
libmsgpack_la_LDFLAGS = -version-info 1:0:0

View File

View File

@@ -1,21 +0,0 @@
MessagePack for C++
-------------------
MessagePack is a binary-based efficient data interchange format.
Copyright (C) 2008-2009 FURUHASHI Sadayuki
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

View File

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

View File

@@ -1,23 +0,0 @@
AC_INIT(object.cpp)
AM_INIT_AUTOMAKE(msgpack, 0.1.0)
AC_CONFIG_HEADER(config.h)
AC_SUBST(CXXFLAGS)
if test "" = "$CXXFLAGS"; then
CXXFLAGS="-g -O4"
fi
AC_PROG_CXX
AC_PROG_LIBTOOL
AC_CHECK_PROG(ERB, erb, erb)
if test "x$ERB" = x; then
AC_MSG_ERROR([cannot find erb. Ruby is needed to build.])
fi
AC_CHECK_LIB(stdc++, main)
CXXFLAGS="-O4 -Wall $CXXFLAGS -I.."
AC_OUTPUT([Makefile])

View File

@@ -1,7 +1,7 @@
//
// MessagePack for C++ static resolution routine
//
// Copyright (C) 2008 FURUHASHI Sadayuki
// Copyright (C) 2008-2009 FURUHASHI Sadayuki
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.

View File

@@ -1,7 +1,7 @@
//
// MessagePack for C++ static resolution routine
//
// Copyright (C) 2008 FURUHASHI Sadayuki
// Copyright (C) 2008-2009 FURUHASHI Sadayuki
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.

View File

@@ -1,7 +1,7 @@
//
// MessagePack for C++ static resolution routine
//
// Copyright (C) 2008 FURUHASHI Sadayuki
// Copyright (C) 2008-2009 FURUHASHI Sadayuki
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.

View File

@@ -1,7 +1,7 @@
//
// MessagePack for C++ static resolution routine
//
// Copyright (C) 2008 FURUHASHI Sadayuki
// Copyright (C) 2008-2009 FURUHASHI Sadayuki
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.

View File

@@ -1,7 +1,7 @@
//
// MessagePack for C++ static resolution routine
//
// Copyright (C) 2008 FURUHASHI Sadayuki
// Copyright (C) 2008-2009 FURUHASHI Sadayuki
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.

View File

@@ -1,7 +1,7 @@
//
// MessagePack for C++ static resolution routine
//
// Copyright (C) 2008 FURUHASHI Sadayuki
// Copyright (C) 2008-2009 FURUHASHI Sadayuki
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.

View File

@@ -1,7 +1,7 @@
//
// MessagePack for C++ static resolution routine
//
// Copyright (C) 2008 FURUHASHI Sadayuki
// Copyright (C) 2008-2009 FURUHASHI Sadayuki
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.

View File

@@ -1,7 +1,7 @@
//
// MessagePack for C++ static resolution routine
//
// Copyright (C) 2008 FURUHASHI Sadayuki
// Copyright (C) 2008-2009 FURUHASHI Sadayuki
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.

View File

@@ -1,369 +0,0 @@
//
// MessagePack for C++ deserializing routine
//
// Copyright (C) 2008-2009 FURUHASHI Sadayuki
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
#include "msgpack/unpack.hpp"
#include "msgpack/unpack_define.h"
#include <stdlib.h>
namespace msgpack {
//namespace {
struct unpack_user {
zone* z;
bool referenced;
};
//} // noname namespace
#define msgpack_unpack_struct(name) \
struct msgpack_unpacker ## name
#define msgpack_unpack_func(ret, name) \
ret msgpack_unpacker ## name
#define msgpack_unpack_callback(name) \
msgpack_unpack ## name
#define msgpack_unpack_object object
#define msgpack_unpack_user unpack_user
struct msgpack_unpacker_context;
static void msgpack_unpacker_init(struct msgpack_unpacker_context* ctx);
static object msgpack_unpacker_data(struct msgpack_unpacker_context* ctx);
static int msgpack_unpacker_execute(struct msgpack_unpacker_context* ctx,
const char* data, size_t len, size_t* off);
static inline object msgpack_unpack_init(unpack_user* u)
{ return object(); }
static inline object msgpack_unpack_uint8(unpack_user* u, uint8_t d)
{ object o; o.type = type::POSITIVE_INTEGER; o.via.u64 = d; return o; }
static inline object msgpack_unpack_uint16(unpack_user* u, uint16_t d)
{ object o; o.type = type::POSITIVE_INTEGER; o.via.u64 = d; return o; }
static inline object msgpack_unpack_uint32(unpack_user* u, uint32_t d)
{ object o; o.type = type::POSITIVE_INTEGER; o.via.u64 = d; return o; }
static inline object msgpack_unpack_uint64(unpack_user* u, uint64_t d)
{ object o; o.type = type::POSITIVE_INTEGER; o.via.u64 = d; return o; }
static inline object msgpack_unpack_int8(unpack_user* u, int8_t d)
{ if(d >= 0) { object o; o.type = type::POSITIVE_INTEGER; o.via.u64 = d; return o; }
else { object o; o.type = type::NEGATIVE_INTEGER; o.via.i64 = d; return o; } }
static inline object msgpack_unpack_int16(unpack_user* u, int16_t d)
{ if(d >= 0) { object o; o.type = type::POSITIVE_INTEGER; o.via.u64 = d; return o; }
else { object o; o.type = type::NEGATIVE_INTEGER; o.via.i64 = d; return o; } }
static inline object msgpack_unpack_int32(unpack_user* u, int32_t d)
{ if(d >= 0) { object o; o.type = type::POSITIVE_INTEGER; o.via.u64 = d; return o; }
else { object o; o.type = type::NEGATIVE_INTEGER; o.via.i64 = d; return o; } }
static inline object msgpack_unpack_int64(unpack_user* u, int64_t d)
{ if(d >= 0) { object o; o.type = type::POSITIVE_INTEGER; o.via.u64 = d; return o; }
else { object o; o.type = type::NEGATIVE_INTEGER; o.via.i64 = d; return o; } }
static inline object msgpack_unpack_float(unpack_user* u, float d)
{ object o; o.type = type::DOUBLE; o.via.dec = d; return o; }
static inline object msgpack_unpack_double(unpack_user* u, double d)
{ object o; o.type = type::DOUBLE; o.via.dec = d; return o; }
static inline object msgpack_unpack_nil(unpack_user* u)
{ object o; o.type = type::NIL; return o; }
static inline object msgpack_unpack_true(unpack_user* u)
{ object o; o.type = type::BOOLEAN; o.via.boolean = true; return o; }
static inline object msgpack_unpack_false(unpack_user* u)
{ object o; o.type = type::BOOLEAN; o.via.boolean = false; return o; }
static inline object msgpack_unpack_array(unpack_user* u, unsigned int n)
{
object o;
o.type = type::ARRAY;
o.via.array.size = 0;
o.via.array.ptr = (object*)u->z->malloc(n*sizeof(object));
return o;
}
static inline void msgpack_unpack_array_item(unpack_user* u, object* c, object o)
{ c->via.array.ptr[c->via.array.size++] = o; }
static inline object msgpack_unpack_map(unpack_user* u, unsigned int n)
{
object o;
o.type = type::MAP;
o.via.map.size = 0;
o.via.map.ptr = (object_kv*)u->z->malloc(n*sizeof(object_kv));
return o;
}
static inline void msgpack_unpack_map_item(unpack_user* u, object* c, object k, object v)
{
c->via.map.ptr[c->via.map.size].key = k;
c->via.map.ptr[c->via.map.size].val = v;
++c->via.map.size;
}
static inline object msgpack_unpack_raw(unpack_user* u, const char* b, const char* p, unsigned int l)
{
object o;
o.type = type::RAW;
o.via.raw.ptr = p;
o.via.raw.size = l;
u->referenced = true;
return o;
}
#include "msgpack/unpack_template.h"
namespace {
struct context {
context()
{
msgpack_unpacker_init(&m_ctx);
unpack_user u = {NULL, false};
m_ctx.user = u;
}
~context() { }
int execute(const char* data, size_t len, size_t* off)
{
return msgpack_unpacker_execute(&m_ctx, data, len, off);
}
object data()
{
return msgpack_unpacker_data(&m_ctx);
}
void reset()
{
zone* z = m_ctx.user.z;
msgpack_unpacker_init(&m_ctx);
unpack_user u = {z, false};
m_ctx.user = u;
}
void set_zone(zone* z)
{
m_ctx.user.z = z;
}
bool is_referenced() const
{
return m_ctx.user.referenced;
}
private:
msgpack_unpacker_context m_ctx;
zone* m_zone;
private:
context(const context&);
};
static inline context* as_ctx(void* m)
{
return reinterpret_cast<context*>(m);
}
static const size_t COUNTER_SIZE = sizeof(unsigned int);
static inline void init_count(void* buffer)
{
*(volatile unsigned int*)buffer = 1;
}
static inline void decl_count(void* buffer)
{
//if(--*(unsigned int*)buffer == 0) {
if(__sync_sub_and_fetch((unsigned int*)buffer, 1) == 0) {
free(buffer);
}
}
static inline void incr_count(void* buffer)
{
//++*(unsigned int*)buffer;
__sync_add_and_fetch((unsigned int*)buffer, 1);
}
static inline unsigned int get_count(void* buffer)
{
return *(volatile unsigned int*)buffer;
}
} // noname namespace
unpacker::unpacker(size_t initial_buffer_size) :
m_buffer(NULL),
m_used(0),
m_free(0),
m_off(0),
m_zone(new zone()),
m_ctx(new context()),
m_initial_buffer_size(initial_buffer_size)
{
if(m_initial_buffer_size < COUNTER_SIZE) {
m_initial_buffer_size = COUNTER_SIZE;
}
as_ctx(m_ctx)->set_zone(m_zone.get());
m_buffer = (char*)::malloc(m_initial_buffer_size);
if(!m_buffer) { throw std::bad_alloc(); }
init_count(m_buffer);
m_used = COUNTER_SIZE;
m_free = m_initial_buffer_size - m_used;
m_off = COUNTER_SIZE;
}
unpacker::~unpacker()
{
delete as_ctx(m_ctx);
decl_count(m_buffer);
}
void unpacker::expand_buffer(size_t len)
{
if(m_used == m_off && get_count(m_buffer) == 1 &&
!as_ctx(m_ctx)->is_referenced()) {
// rewind buffer
m_free += m_used - COUNTER_SIZE;
m_used = COUNTER_SIZE;
m_off = COUNTER_SIZE;
if(m_free >= len) { return; }
}
if(m_off == COUNTER_SIZE) {
size_t next_size = (m_used + m_free) * 2;
while(next_size < len + m_used) { next_size *= 2; }
char* tmp = (char*)::realloc(m_buffer, next_size);
if(!tmp) { throw std::bad_alloc(); }
m_buffer = tmp;
m_free = next_size - m_used;
} else {
size_t next_size = m_initial_buffer_size; // include COUNTER_SIZE
size_t not_parsed = m_used - m_off;
while(next_size < len + not_parsed + COUNTER_SIZE) { next_size *= 2; }
char* tmp = (char*)::malloc(next_size);
if(!tmp) { throw std::bad_alloc(); }
init_count(tmp);
try {
m_zone->push_finalizer(decl_count, m_buffer);
} catch (...) { free(tmp); throw; }
memcpy(tmp+COUNTER_SIZE, m_buffer+m_off, not_parsed);
m_buffer = tmp;
m_used = not_parsed + COUNTER_SIZE;
m_free = next_size - m_used;
m_off = COUNTER_SIZE;
}
}
bool unpacker::execute()
{
int ret = as_ctx(m_ctx)->execute(m_buffer, m_used, &m_off);
if(ret < 0) {
throw unpack_error("parse error");
} else if(ret == 0) {
return false;
} else {
return true;
}
}
zone* unpacker::release_zone()
{
m_zone->push_finalizer(decl_count, m_buffer);
incr_count(m_buffer);
//std::auto_ptr<zone> old(new zone());
//m_zone.swap(old);
zone* n = new zone();
std::auto_ptr<zone> old(m_zone.release());
m_zone.reset(n);
as_ctx(m_ctx)->set_zone(m_zone.get());
return old.release();
}
object unpacker::data()
{
return as_ctx(m_ctx)->data();
}
void unpacker::reset()
{
//if(!m_zone->empty()) { delete release_zone(); }
as_ctx(m_ctx)->reset();
}
object unpacker::unpack(const char* data, size_t len, zone& z, size_t* off)
{
context ctx;
ctx.set_zone(&z);
if(off) {
size_t noff = *off;
int ret = ctx.execute(data, len, &noff);
if(ret < 0) {
throw unpack_error("parse error");
} else if(ret == 0) {
throw unpack_error("insufficient bytes");
}
*off = noff;
} else {
size_t noff = 0;
int ret = ctx.execute(data, len, &noff);
if(ret < 0) {
throw unpack_error("parse error");
} else if(ret == 0) {
throw unpack_error("insufficient bytes");
} else if(noff < len) {
throw unpack_error("extra bytes");
}
}
return ctx.data();
}
} // namespace msgpack

View File

@@ -18,6 +18,7 @@
#ifndef MSGPACK_UNPACK_HPP__
#define MSGPACK_UNPACK_HPP__
#include "msgpack/unpack.h"
#include "msgpack/object.hpp"
#include "msgpack/zone.hpp"
#include <memory>
@@ -36,21 +37,21 @@ struct unpack_error : public std::runtime_error {
};
class unpacker {
class unpacker : public msgpack_unpacker {
public:
unpacker(size_t initial_buffer_size = MSGPACK_UNPACKER_DEFAULT_INITIAL_BUFFER_SIZE);
~unpacker();
public:
/*! 1. reserve buffer. at least `len' bytes of capacity will be ready */
void reserve_buffer(size_t len);
/*! 1. reserve buffer. at least `size' bytes of capacity will be ready */
void reserve_buffer(size_t size);
/*! 2. read data to the buffer() up to buffer_capacity() bytes */
char* buffer();
size_t buffer_capacity() const;
/*! 3. specify the number of bytes actually copied */
void buffer_consumed(size_t len);
void buffer_consumed(size_t size);
/*! 4. repeat execute() until it retunrs false */
bool execute();
@@ -114,71 +115,157 @@ public:
size_t nonparsed_size() const;
/*! skip specified size of non-parsed buffer, leaving the buffer */
// Note that the `len' argument must be smaller than nonparsed_size()
void skip_nonparsed_buffer(size_t len);
// Note that the `size' argument must be smaller than nonparsed_size()
void skip_nonparsed_buffer(size_t size);
/*! remove unparsed buffer from unpacker */
// Note that reset() leaves non-parsed buffer.
void remove_nonparsed_buffer();
private:
char* m_buffer;
size_t m_used;
size_t m_free;
size_t m_off;
std::auto_ptr<zone> m_zone;
void* m_ctx;
size_t m_initial_buffer_size;
private:
void expand_buffer(size_t len);
private:
unpacker(const unpacker&);
public:
static object unpack(const char* data, size_t len, zone& z, size_t* off = NULL);
};
inline void unpacker::reserve_buffer(size_t len)
typedef enum {
MSGPACK_UNPACK_SUCCESS = 2,
MSGPACK_UNPACK_EXTRA_BYTES = 1,
MSGPACK_UNPACK_CONTINUE = 0,
MSGPACK_UNPACK_PARSE_ERROR = -1,
} unpack_return;
static unpack_return unpack(const char* data, size_t len, size_t* off,
zone* z, object* result);
// obsolete
static object unpack(const char* data, size_t len, zone& z, size_t* off = NULL);
inline unpacker::unpacker(size_t initial_buffer_size)
{
if(m_free >= len) { return; }
expand_buffer(len);
if(!msgpack_unpacker_init(this, initial_buffer_size)) {
throw std::bad_alloc();
}
}
inline unpacker::~unpacker()
{
msgpack_unpacker_destroy(this);
}
inline void unpacker::reserve_buffer(size_t size)
{
if(!msgpack_unpacker_reserve_buffer(this, size)) {
throw std::bad_alloc();
}
}
inline char* unpacker::buffer()
{ return m_buffer + m_used; }
{
return msgpack_unpacker_buffer(this);
}
inline size_t unpacker::buffer_capacity() const
{ return m_free; }
inline void unpacker::buffer_consumed(size_t len)
{
m_used += len;
m_free -= len;
return msgpack_unpacker_buffer_capacity(this);
}
inline void unpacker::buffer_consumed(size_t size)
{
return msgpack_unpacker_buffer_consumed(this, size);
}
inline bool unpacker::execute()
{
int ret = msgpack_unpacker_execute(this);
if(ret < 0) {
throw unpack_error("parse error");
} else if(ret == 0) {
return false;
} else {
return true;
}
}
inline object unpacker::data()
{
msgpack_object obj = msgpack_unpacker_data(this);
return *reinterpret_cast<object*>(&obj);
}
inline zone* unpacker::release_zone()
{
if(!msgpack_unpacker_flush_zone(this)) {
throw std::bad_alloc();
}
zone* r = new zone();
msgpack_zone old = *this->z;
*this->z = *z;
*z = old;
return r;
}
inline void unpacker::reset()
{
msgpack_unpacker_reset(this);
}
inline char* unpacker::nonparsed_buffer()
{ return m_buffer + m_off; }
{
return buf + off;
}
inline size_t unpacker::nonparsed_size() const
{ return m_used - m_off; }
{
return used - off;
}
inline void unpacker::skip_nonparsed_buffer(size_t len)
{ m_off += len; }
inline void unpacker::skip_nonparsed_buffer(size_t size)
{
off += size;
}
inline void unpacker::remove_nonparsed_buffer()
{ m_used = m_off; }
inline object unpack(const char* data, size_t len, zone& z, size_t* off = NULL)
{
return unpacker::unpack(data, len, z, off);
used = off;
}
inline unpack_return unpack(const char* data, size_t len, size_t* off,
zone* z, object* result)
{
return (unpack_return)msgpack_unpack(data, len, off,
z, reinterpret_cast<msgpack_object*>(result));
}
inline object unpack(const char* data, size_t len, zone& z, size_t* off)
{
object result;
switch( msgpack::unpack(data, len, off, &z, &result) ) {
case MSGPACK_UNPACK_SUCCESS:
return result;
case MSGPACK_UNPACK_EXTRA_BYTES:
if(off) {
return result;
} else {
throw unpack_error("extra bytes");
}
case MSGPACK_UNPACK_CONTINUE:
throw unpack_error("insufficient bytes");
case MSGPACK_UNPACK_PARSE_ERROR:
default:
throw unpack_error("parse error");
}
}

View File

@@ -1,100 +0,0 @@
//
// MessagePack for C++ memory pool
//
// Copyright (C) 2008-2009 FURUHASHI Sadayuki
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
#include "msgpack/zone.hpp"
#include <algorithm>
namespace msgpack {
zone::zone(size_t chunk_size) :
m_chunk_size(chunk_size)
{
chunk dummy = {0, NULL, NULL};
m_chunk_array.push_back(dummy);
}
zone::~zone()
{
clear();
}
namespace {
template <typename Private>
struct zone_finalize {
void operator() (Private& f) {
(*f.func)(f.obj);
}
};
template <typename Private>
struct zone_free {
void operator() (Private& c) {
::free(c.alloc);
}
};
}
void zone::clear()
{
std::for_each(m_finalizers.rbegin(), m_finalizers.rend(),
zone_finalize<finalizer>());
m_finalizers.clear();
std::for_each(m_chunk_array.begin(), m_chunk_array.end(),
zone_free<chunk>());
m_chunk_array.resize(1);
m_chunk_array[0].ptr = NULL;
m_chunk_array[0].free = 0;
}
bool zone::empty() const
{
return m_chunk_array.back().alloc == NULL &&
m_finalizers.empty();
}
void* zone::malloc(size_t size)
{
if(m_chunk_array.back().free > size) {
char* p = (char*)m_chunk_array.back().ptr;
m_chunk_array.back().ptr = p + size;
m_chunk_array.back().free -= size;
return p;
}
size_t sz = m_chunk_size;
while(sz < size) { sz *= 2; }
chunk dummy = {0, NULL, NULL};
m_chunk_array.push_back(dummy);
char* p = (char*)::malloc(sz);
if(!p) {
m_chunk_array.pop_back();
throw std::bad_alloc();
}
m_chunk_array.back().free = sz - size;
m_chunk_array.back().ptr = p + size;
m_chunk_array.back().alloc = p;
return p;
}
} // namespace msgpack

View File

@@ -19,17 +19,15 @@
#define MSGPACK_ZONE_HPP__
#include "msgpack/object.hpp"
#include "msgpack/zone.h"
#include <cstdlib>
#include <vector>
#ifndef MSGPACK_ZONE_CHUNK_SIZE
#define MSGPACK_ZONE_CHUNK_SIZE 2048
#endif
<% GENERATION_LIMIT = 15 %>
namespace msgpack {
class zone {
class zone : public msgpack_zone {
public:
zone(size_t chunk_size = MSGPACK_ZONE_CHUNK_SIZE);
~zone();
@@ -37,11 +35,7 @@ public:
public:
void* malloc(size_t size);
void push_finalizer(void (*func)(void*), void* obj);
void clear();
bool empty() const;
void push_finalizer(void (*func)(void*), void* data);
<%0.upto(GENERATION_LIMIT) {|i|%>
template <typename T<%1.upto(i) {|j|%>, typename A<%=j%><%}%>>
@@ -49,35 +43,39 @@ public:
<%}%>
private:
struct chunk {
size_t free;
void* ptr;
void* alloc;
};
std::vector<chunk> m_chunk_array;
struct finalizer {
void (*func)(void*);
void* obj;
};
std::vector<finalizer> m_finalizers;
template <typename T>
static void object_destructor(void* obj);
size_t m_chunk_size;
private:
zone(const zone&);
};
inline void zone::push_finalizer(void (*func)(void*), void* obj)
inline zone::zone(size_t chunk_size)
{
finalizer f = {func, obj};
m_finalizers.push_back(f);
msgpack_zone_init(this, chunk_size);
}
inline zone::~zone()
{
msgpack_zone_destroy(this);
}
inline void* zone::malloc(size_t size)
{
void* ptr = msgpack_zone_malloc(this, size);
if(!ptr) {
throw std::bad_alloc();
}
return ptr;
}
inline void zone::push_finalizer(void (*func)(void*), void* data)
{
if(!msgpack_zone_push_finalizer(this, func, data)) {
throw std::bad_alloc();
}
}
template <typename T>
@@ -93,7 +91,7 @@ T* zone::allocate(<%=(1..i).map{|j|"A#{j} a#{j}"}.join(', ')%>)
void* x = malloc(sizeof(T));
push_finalizer(&zone::object_destructor<T>, x);
try { return new (x) T(<%=(1..i).map{|j|"a#{j}"}.join(', ')%>); }
catch (...) { m_finalizers.pop_back(); throw; }
catch (...) { --finalizer_array.tail; throw; }
}
<%}%>
@@ -101,3 +99,4 @@ T* zone::allocate(<%=(1..i).map{|j|"A#{j} a#{j}"}.join(', ')%>)
#endif /* msgpack/zone.hpp */
// vim: ft=cpp ts=4 sw=4 softtabstop=4 noexpandtab smarttab