Supported C++03.

This commit is contained in:
Takatoshi Kondo
2013-08-29 13:44:34 +09:00
parent 11afd4820f
commit 5b3a168b86
9 changed files with 346 additions and 111 deletions

View File

@@ -19,15 +19,9 @@
#define MSGPACK_TYPE_TUPLE_HPP
#include "msgpack/object.hpp"
#include <tuple>
#include "msgpack/cpp_config.hpp"
namespace msgpack {
namespace type {
template <typename... Args>
using tuple = std::tuple<Args...>;
} // type
// --- Pack ( from tuple to packer stream ---
template <typename Stream, typename Tuple, std::size_t N>
@@ -36,7 +30,7 @@ struct Packer {
packer<Stream>& o,
const Tuple& v) {
Packer<Stream, Tuple, N-1>::pack(o, v);
o.pack(std::get<N-1>(v));
o.pack(type::get<N-1>(v));
}
};
@@ -45,7 +39,7 @@ struct Packer<Stream, Tuple, 1> {
static void pack (
packer<Stream>& o,
const Tuple& v) {
o.pack(std::get<0>(v));
o.pack(type::get<0>(v));
}
};
@@ -66,7 +60,7 @@ struct Converter {
object o,
Tuple& v) {
Converter<Tuple, N-1>::convert(o, v);
o.via.array.ptr[N-1].convert<typename std::remove_reference<decltype(std::get<N-1>(v))>::type>(&std::get<N-1>(v));
o.via.array.ptr[N-1].convert<typename std::remove_reference<decltype(type::get<N-1>(v))>::type>(&type::get<N-1>(v));
}
};
@@ -75,7 +69,7 @@ struct Converter<Tuple, 1> {
static void convert (
object o,
Tuple& v) {
o.via.array.ptr[0].convert<typename std::remove_reference<decltype(std::get<0>(v))>::type>(&std::get<0>(v));
o.via.array.ptr[0].convert<typename std::remove_reference<decltype(type::get<0>(v))>::type>(&type::get<0>(v));
}
};
@@ -96,7 +90,7 @@ struct TupleToObjectWithZone {
object::with_zone& o,
const Tuple& v) {
TupleToObjectWithZone<Tuple, N-1>::convert(o, v);
o.via.array.ptr[N-1] = object(std::get<N-1>(v), o.zone);
o.via.array.ptr[N-1] = object(type::get<N-1>(v), o.zone);
}
};
@@ -105,7 +99,7 @@ struct TupleToObjectWithZone<Tuple, 1> {
static void convert (
object::with_zone& o,
const Tuple& v) {
o.via.array.ptr[0] = object(std::get<0>(v), o.zone);
o.via.array.ptr[0] = object(type::get<0>(v), o.zone);
}
};

View File

@@ -22,6 +22,8 @@
#include <memory>
#include <vector>
#include "cpp_config.hpp"
#ifndef MSGPACK_ZONE_CHUNK_SIZE
#define MSGPACK_ZONE_CHUNK_SIZE 8192
#endif
@@ -158,7 +160,7 @@ public:
void push_finalizer(void (*func)(void*), void* data);
template <typename T>
void push_finalizer(std::unique_ptr<T> obj);
void push_finalizer(msgpack::unique_ptr<T> obj);
void clear();
@@ -250,7 +252,7 @@ inline void zone::push_finalizer(void (*func)(void*), void* data)
}
template <typename T>
inline void zone::push_finalizer(std::unique_ptr<T> obj)
inline void zone::push_finalizer(msgpack::unique_ptr<T> obj)
{
finalizer_array_.push(&zone::object_destructor<T>, obj.get());
obj.release();

View File

@@ -0,0 +1,86 @@
//
// MessagePack for C++ C++03/C++11 Adaptation
//
// Copyright (C) 2013 KONDO Takatoshi
//
// 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.
//
#ifndef MSGPACK_CPP_CONFIG_HPP
#define MSGPACK_CPP_CONFIG_HPP
#if defined __cplusplus
#if __cplusplus < 201103
#define nullptr (0)
namespace msgpack {
template <typename T>
struct unique_ptr : std::auto_ptr<T> {
explicit unique_ptr(T* p = 0) throw() : std::auto_ptr<T>(p) {}
unique_ptr(unique_ptr& a) throw() : std::auto_ptr<T>(a) {}
template<class Y>
unique_ptr (unique_ptr<Y>& a) throw() : std::auto_ptr<T>(a) {}
};
template <typename T>
T& move(T& t)
{
return t;
}
template <typename T>
T const& move(T const& t)
{
return t;
}
} // msgpack
#else // __cplusplus < 201103
#include <memory>
#include <tuple>
namespace msgpack {
// unique_ptr
using std::unique_ptr;
// using std::make_unique; // since C++14
using std::hash;
// utility
using std::move;
using std::swap;
namespace type {
// tuple
using std::tuple;
using std::get;
using std::make_tuple;
using std::tie;
using std::forward_as_tuple;
using std::tuple_cat;
using std::tuple_size;
using std::tuple_element;
using std::uses_allocator;
using std::ignore;
}
} // msgpack
#endif // __cplusplus < 201103
#endif // __cplusplus
#endif /* msgpack/cpp_config.hpp */

View File

@@ -110,6 +110,13 @@ struct tuple<A0<%1.upto(i) {|j|%>, A<%=j%><%}%>> {
<%0.upto(i) {|j|%>
A<%=j%> a<%=j%>;<%}%>
};
template <int N, typename A0<%1.upto(i) {|j|%>, typename A<%=j%><%}%>>
inline typename type::tuple_element<type::tuple<A0<%1.upto(i) {|j|%>, A<%=j%><%}%>>, N>::reference get(type::tuple<A0<%1.upto(i) {|j|%>, A<%=j%><%}%>>& t)
{ return t.get<N>(); }
template <int N, typename A0<%1.upto(i) {|j|%>, typename A<%=j%><%}%>>
inline typename type::const_tuple_element<type::tuple<A0<%1.upto(i) {|j|%>, A<%=j%><%}%>>, N>::const_reference get(type::tuple<A0<%1.upto(i) {|j|%>, A<%=j%><%}%>> const& t)
{ return t.get<N>(); }
<%}%>
inline tuple<> make_tuple()
@@ -126,7 +133,6 @@ tuple<A0<%1.upto(i) {|j|%>, A<%=j%><%}%>> make_tuple(typename tuple_type<A0>::tr
} // namespace type
inline type::tuple<>& operator>> (
object o,
type::tuple<>& v) {

View File

@@ -21,6 +21,7 @@
#include "object.hpp"
#include "zone.hpp"
#include "unpack_define.h"
#include "cpp_config.hpp"
#include <memory>
#include <stdexcept>
@@ -59,7 +60,7 @@ private:
};
static inline object template_callback_root(unpack_user* u)
{ object o = {}; return o; }
{ object o; return o; }
static inline int template_callback_uint8(unpack_user* u, uint8_t d, object* o)
{ o->type = type::POSITIVE_INTEGER; o->via.u64 = d; return 0; }
@@ -538,8 +539,8 @@ class unpacked {
public:
unpacked() { }
unpacked(object obj, std::unique_ptr<msgpack::zone> z) :
m_obj(obj), m_zone(std::move(z)) { }
unpacked(object obj, msgpack::unique_ptr<msgpack::zone> z) :
m_obj(obj), m_zone(msgpack::move(z)) { }
object& get()
{ return m_obj; }
@@ -547,15 +548,15 @@ public:
const object& get() const
{ return m_obj; }
std::unique_ptr<msgpack::zone>& zone()
msgpack::unique_ptr<msgpack::zone>& zone()
{ return m_zone; }
const std::unique_ptr<msgpack::zone>& zone() const
const msgpack::unique_ptr<msgpack::zone>& zone() const
{ return m_zone; }
private:
object m_obj;
std::unique_ptr<msgpack::zone> m_zone;
msgpack::unique_ptr<msgpack::zone> m_zone;
};
@@ -984,7 +985,7 @@ inline void unpack(unpacked* result,
const char* data, size_t len, size_t* offset)
{
object obj;
std::unique_ptr<zone> z(new zone());
msgpack::unique_ptr<zone> z(new zone());
unpack_return ret = detail::unpack_imp(
data, len, offset, z.get(), &obj);
@@ -993,12 +994,12 @@ inline void unpack(unpacked* result,
switch(ret) {
case UNPACK_SUCCESS:
result->get() = obj;
result->zone() = std::move(z);
result->zone() = msgpack::move(z);
return;
case UNPACK_EXTRA_BYTES:
result->get() = obj;
result->zone() = std::move(z);
result->zone() = msgpack::move(z);
return;
case UNPACK_CONTINUE:

View File

@@ -15,146 +15,292 @@
// See the License for the specific language governing permissions and
// limitations under the License.
//
#ifndef MSGPACK_ZONE_HPP__
#define MSGPACK_ZONE_HPP__
#ifndef MSGPACK_ZONE_HPP
#define MSGPACK_ZONE_HPP
#include "zone.h"
#include <cstdlib>
#include <memory>
#include <vector>
#include "cpp_config.hpp"
#ifndef MSGPACK_ZONE_CHUNK_SIZE
#define MSGPACK_ZONE_CHUNK_SIZE 8192
#endif
#ifndef MSGPACK_ZONE_ALIGN
#define MSGPACK_ZONE_ALIGN sizeof(int)
#endif
<% GENERATION_LIMIT = 15 %>
namespace msgpack {
class zone {
struct finalizer {
finalizer(void (*func)(void*), void* data):func_(func), data_(data) {}
void operator()() { func_(data_); }
void (*func_)(void*);
void* data_;
};
struct finalizer_array {
finalizer_array():tail_(nullptr), end_(nullptr), array_(nullptr) {}
void call() {
finalizer* fin = tail_;
for(; fin != array_; --fin) (*(fin-1))();
}
~finalizer_array() {
call();
::free(array_);
}
void clear() {
call();
tail_ = array_;
}
void push(void (*func)(void* data), void* data)
{
finalizer* fin = tail_;
if(fin == end_) {
push_expand(func, data);
return;
}
fin->func_ = func;
fin->data_ = data;
++tail_;
}
void push_expand(void (*func)(void*), void* data) {
const size_t nused = end_ - array_;
size_t nnext;
if(nused == 0) {
nnext = (sizeof(finalizer) < 72/2) ?
72 / sizeof(finalizer) : 8;
} else {
nnext = nused * 2;
}
finalizer* tmp =
(finalizer*)::realloc(array_, sizeof(finalizer) * nnext);
if(!tmp) {
throw std::bad_alloc();
}
array_ = tmp;
end_ = tmp + nnext;
tail_ = tmp + nused;
new (tail_) finalizer(func, data);
class zone : public msgpack_zone {
++tail_;
}
finalizer* tail_;
finalizer* end_;
finalizer* array_;
};
struct chunk {
chunk* next_;
};
struct chunk_list {
chunk_list(size_t chunk_size)
{
chunk* c = (chunk*)::malloc(sizeof(chunk) + chunk_size);
if(!c) {
throw std::bad_alloc();
}
head_ = c;
free_ = chunk_size;
ptr_ = ((char*)c) + sizeof(chunk);
c->next_ = nullptr;
}
~chunk_list()
{
chunk* c = head_;
while(true) {
chunk* n = c->next_;
::free(c);
if(n) {
c = n;
} else {
break;
}
}
}
void clear(size_t chunk_size)
{
chunk* c = head_;
while(true) {
chunk* n = c->next_;
if(n) {
::free(c);
c = n;
} else {
break;
}
}
head_->next_ = nullptr;
free_ = chunk_size;
ptr_ = ((char*)head_) + sizeof(chunk);
}
size_t free_;
char* ptr_;
chunk* head_;
};
size_t chunk_size_;
chunk_list chunk_list_;
finalizer_array finalizer_array_;
public:
zone(size_t chunk_size = MSGPACK_ZONE_CHUNK_SIZE);
~zone();
zone(size_t chunk_size = MSGPACK_ZONE_CHUNK_SIZE);
public:
void* malloc(size_t size);
void* malloc_no_align(size_t size);
static zone* create(size_t chunk_size);
static void destroy(zone* zone);
void* malloc(size_t size);
void* malloc_no_align(size_t size);
void push_finalizer(void (*func)(void*), void* data);
void push_finalizer(void (*func)(void*), void* data);
template <typename T>
void push_finalizer(std::auto_ptr<T> obj);
template <typename T>
void push_finalizer(msgpack::unique_ptr<T> obj);
void clear();
void clear();
void swap(zone& o);
static void* operator new(std::size_t size) throw(std::bad_alloc)
{
void* p = ::malloc(size);
if (!p) throw std::bad_alloc();
return p;
}
static void operator delete(void *p) throw()
{
::free(p);
}
<%0.upto(GENERATION_LIMIT) {|i|%>
template <typename T<%1.upto(i) {|j|%>, typename A<%=j%><%}%>>
T* allocate(<%=(1..i).map{|j|"A#{j} a#{j}"}.join(', ')%>);
<%}%>
void swap(zone& o);
<%0.upto(GENERATION_LIMIT) {|i|%>
template <typename T<%1.upto(i) {|j|%>, typename A<%=j%><%}%>>
T* allocate(<%=(1..i).map{|j|"A#{j} a#{j}"}.join(', ')%>);
<%}%>
private:
void undo_malloc(size_t size);
void undo_malloc(size_t size);
template <typename T>
static void object_destructor(void* obj);
template <typename T>
static void object_destructor(void* obj);
typedef msgpack_zone base;
private:
zone(const zone&);
void* malloc_expand(size_t size);
};
inline zone::zone(size_t chunk_size)
inline zone* zone::create(size_t chunk_size)
{
msgpack_zone_init(this, chunk_size);
zone* z = (zone*)::malloc(sizeof(zone) + chunk_size);
if (!z) {
return nullptr;
}
try {
new (z) zone(chunk_size);
}
catch (...) {
::free(z);
return nullptr;
}
return z;
}
inline zone::~zone()
inline void zone::destroy(zone* z)
{
z->~zone();
::free(z);
}
inline zone::zone(size_t chunk_size):chunk_size_(chunk_size), chunk_list_(chunk_size_)
{
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;
return malloc_no_align(
((size)+((MSGPACK_ZONE_ALIGN)-1)) & ~((MSGPACK_ZONE_ALIGN)-1));
}
inline void* zone::malloc_no_align(size_t size)
{
void* ptr = msgpack_zone_malloc_no_align(this, size);
if(!ptr) {
throw std::bad_alloc();
}
return ptr;
if(chunk_list_.free_ < size) {
return malloc_expand(size);
}
char* ptr = chunk_list_.ptr_;
chunk_list_.free_ -= size;
chunk_list_.ptr_ += size;
return ptr;
}
inline void* zone::malloc_expand(size_t size)
{
chunk_list* const cl = &chunk_list_;
size_t sz = chunk_size_;
while(sz < size) {
sz *= 2;
}
chunk* c = (chunk*)::malloc(sizeof(chunk) + sz);
char* ptr = ((char*)c) + sizeof(chunk);
c->next_ = cl->head_;
cl->head_ = c;
cl->free_ = sz - size;
cl->ptr_ = ptr + size;
return ptr;
}
inline void zone::push_finalizer(void (*func)(void*), void* data)
{
if(!msgpack_zone_push_finalizer(this, func, data)) {
throw std::bad_alloc();
}
finalizer_array_.push(func, data);
}
template <typename T>
inline void zone::push_finalizer(std::auto_ptr<T> obj)
inline void zone::push_finalizer(msgpack::unique_ptr<T> obj)
{
if(!msgpack_zone_push_finalizer(this, &zone::object_destructor<T>, obj.get())) {
throw std::bad_alloc();
}
obj.release();
finalizer_array_.push(&zone::object_destructor<T>, obj.get());
obj.release();
}
inline void zone::clear()
{
msgpack_zone_clear(this);
finalizer_array_.clear();
chunk_list_.clear(chunk_size_);
}
inline void zone::swap(zone& o)
{
msgpack_zone_swap(this, &o);
std::swap(*this, o);
}
template <typename T>
void zone::object_destructor(void* obj)
{
reinterpret_cast<T*>(obj)->~T();
reinterpret_cast<T*>(obj)->~T();
}
inline void zone::undo_malloc(size_t size)
{
base::chunk_list.ptr -= size;
base::chunk_list.free += size;
chunk_list_.ptr_ -= size;
chunk_list_.free_ += size;
}
<%0.upto(GENERATION_LIMIT) {|i|%>
template <typename T<%1.upto(i) {|j|%>, typename A<%=j%><%}%>>
T* zone::allocate(<%=(1..i).map{|j|"A#{j} a#{j}"}.join(', ')%>)
{
void* x = malloc(sizeof(T));
if(!msgpack_zone_push_finalizer(this, &zone::object_destructor<T>, x)) {
undo_malloc(sizeof(T));
throw std::bad_alloc();
}
try {
return new (x) T(<%=(1..i).map{|j|"a#{j}"}.join(', ')%>);
} catch (...) {
--base::finalizer_array.tail;
undo_malloc(sizeof(T));
throw;
}
void* x = malloc(sizeof(T));
try {
finalizer_array_.push(&zone::object_destructor<T>, x);
} catch (...) {
undo_malloc(sizeof(T));
throw;
}
try {
return new (x) T(<%=(1..i).map{|j|"a#{j}"}.join(', ')%>);
} catch (...) {
--finalizer_array_.tail_;
undo_malloc(sizeof(T));
throw;
}
}
<%}%>

View File

@@ -1,6 +1,6 @@
#include "msgpack.hpp"
#include <math.h>
#include <cmath>
#include <string>
#include <vector>
#include <map>
@@ -901,11 +901,11 @@ public:
msgpack::type::tuple<bool, msgpack::object> tuple;
o.convert(&tuple);
is_double = get<0>(tuple);
is_double = msgpack::type::get<0>(tuple);
if (is_double)
get<1>(tuple).convert(&value.f);
msgpack::type::get<1>(tuple).convert(&value.f);
else
get<1>(tuple).convert(&value.i);
msgpack::type::get<1>(tuple).convert(&value.i);
}
};

View File

@@ -69,7 +69,7 @@ public:
msgpack::unpacked result;
while(pac.next(&result)) {
on_message(result.get(), std::move(result.zone()));
on_message(result.get(), msgpack::move(result.zone()));
}
if(pac.message_size() > 10*1024*1024) {
@@ -78,7 +78,7 @@ public:
}
}
void on_message(msgpack::object obj, std::unique_ptr<msgpack::zone> z)
void on_message(msgpack::object obj, msgpack::unique_ptr<msgpack::zone> z)
{
EXPECT_EQ(expect, obj.as<int>());
}
@@ -133,7 +133,7 @@ TEST(streaming, basic_compat)
pac.buffer_consumed(len);
while(pac.execute()) {
std::unique_ptr<msgpack::zone> z(pac.release_zone());
msgpack::unique_ptr<msgpack::zone> z(pac.release_zone());
msgpack::object obj = pac.data();
pac.reset();
@@ -174,10 +174,10 @@ public:
pac.buffer_consumed(len);
while(pac.execute()) {
std::unique_ptr<msgpack::zone> z(pac.release_zone());
msgpack::unique_ptr<msgpack::zone> z(pac.release_zone());
msgpack::object obj = pac.data();
pac.reset();
on_message(obj, std::move(z));
on_message(obj, msgpack::move(z));
}
if(pac.message_size() > 10*1024*1024) {
@@ -186,7 +186,7 @@ public:
}
}
void on_message(msgpack::object obj, std::unique_ptr<msgpack::zone> z)
void on_message(msgpack::object obj, msgpack::unique_ptr<msgpack::zone> z)
{
EXPECT_EQ(expect, obj.as<int>());
}

View File

@@ -63,8 +63,8 @@ TEST(zone, push_finalizer)
TEST(zone, push_finalizer_unique_ptr)
{
msgpack::zone z;
std::unique_ptr<myclass> am(new myclass());
z.push_finalizer(std::move(am));
msgpack::unique_ptr<myclass> am(new myclass());
z.push_finalizer(msgpack::move(am));
}