mirror of
https://github.com/msgpack/msgpack-c.git
synced 2025-03-17 12:16:21 +01:00
Added header files that use c++11 variadic templates instead of ruby code generation.
When the compiler configured to support C++11 (e.g. CXXFLAG contains -std=c++11 is given), those files are used. Decoupled unpacker and msgpack_unpacker. This modification introduced C++11 dependency such as nullptr and unique_ptr. I will support C++11 and C++03, finally. Decoupled msgpack.hpp and msgpack.h. Decoupled sbuffer from msgpack_sbuffer. Decoupled vrefbuffer from msgpack_vrefbuffer. Decoupled zbuffer from msgpack_zbuffer. Added some z_stream initialization. Removed unpack macros. Removed CTX_CAST and CTX_REFERENCED. Embed ctx_ as a member variable (not a pointer). Modified zone free using C++ way.
This commit is contained in:
parent
197ed8c983
commit
c2ca709d68
1
.gitignore
vendored
1
.gitignore
vendored
@ -19,6 +19,7 @@ Makefile.in
|
||||
/libtool
|
||||
/msgpack.pc
|
||||
/src/msgpack/version.h
|
||||
/src/msgpack/version.hpp
|
||||
/stamp-h1
|
||||
Makefile
|
||||
.deps
|
||||
|
@ -10,6 +10,18 @@ SET (exec_prefix "\${prefix}")
|
||||
SET (libdir "\${exec_prefix}/lib")
|
||||
SET (includedir "\${prefix}/include")
|
||||
|
||||
OPTION (MSGPACK_CXX11 "Using c++11 compiler" OFF)
|
||||
|
||||
IF (MSGPACK_CXX11)
|
||||
IF ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU")
|
||||
SET (CMAKE_CXX_FLAGS "-std=c++11 ${CMAKE_CXX_FLAGS}")
|
||||
ELSEIF ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang")
|
||||
SET (CMAKE_CXX_FLAGS "-std=c++11 ${CMAKE_CXX_FLAGS}")
|
||||
ELSEIF ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC")
|
||||
MESSAGE ( FATAL_ERROR "MSVC doesn't support C++11 yet.")
|
||||
ENDIF ()
|
||||
ENDIF ()
|
||||
|
||||
FIND_PACKAGE (GTest)
|
||||
FIND_PACKAGE (ZLIB)
|
||||
FIND_PACKAGE (Threads)
|
||||
@ -17,6 +29,26 @@ IF (GTEST_FOUND AND ZLIB_FOUND AND THREADS_FOUND)
|
||||
OPTION (MSGPACK_BUILD_TESTS "Build msgpack tests." ON)
|
||||
ENDIF ()
|
||||
|
||||
|
||||
# Files to copy
|
||||
|
||||
MACRO (COPY_FILE SOURCE DESTINATION)
|
||||
# COPY_FILE (readme.txt dir1/dir2/) would add new target
|
||||
# that will copy readme.txt to dir1/dir2 where dir1 will be located
|
||||
# in current binary directory.
|
||||
ADD_CUSTOM_COMMAND (
|
||||
OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${DESTINATION}/${SOURCE}
|
||||
COMMAND ${CMAKE_COMMAND} -E make_directory ${CMAKE_CURRENT_BINARY_DIR}/${DESTINATION}
|
||||
COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_SOURCE_DIR}/${SOURCE} ${CMAKE_CURRENT_BINARY_DIR}/${DESTINATION}/${SOURCE}
|
||||
)
|
||||
ENDMACRO ()
|
||||
|
||||
IF (MSGPACK_CXX11)
|
||||
COPY_FILE (cpp11/zone.hpp src/msgpack/zone.hpp)
|
||||
COPY_FILE (cpp11/define.hpp src/msgpack/type/define.hpp)
|
||||
COPY_FILE (cpp11/tuple.hpp src/msgpack/type/tuple.hpp)
|
||||
ENDIF ()
|
||||
|
||||
OPTION (MSGPACK_ENABLE_CXX "Enable C++ interface." ON)
|
||||
|
||||
INCLUDE (CheckCXXSourceCompiles)
|
||||
@ -109,6 +141,10 @@ CONFIGURE_FILE (
|
||||
src/msgpack/version.h.in
|
||||
${CMAKE_CURRENT_BINARY_DIR}/src/msgpack/version.h
|
||||
)
|
||||
CONFIGURE_FILE (
|
||||
src/msgpack/version.hpp.in
|
||||
${CMAKE_CURRENT_BINARY_DIR}/src/msgpack/version.hpp
|
||||
)
|
||||
|
||||
CONFIGURE_FILE (
|
||||
msgpack.pc.in
|
||||
|
20
README.md
20
README.md
@ -38,6 +38,16 @@ $ make
|
||||
$ sudo make install
|
||||
```
|
||||
|
||||
If you want to setup C++11 version of msgpack, execute the following command:
|
||||
|
||||
```
|
||||
$ git clone https://github.com/msgpack/msgpack-c.git
|
||||
$ cd msgpack-c
|
||||
$ ./bootstrap
|
||||
$ ./configure CXXFLAGS="-std=c++11"
|
||||
```
|
||||
You need the compiler that fully supports C++11.
|
||||
|
||||
##### Using cmake
|
||||
You will need gcc (4.1.0 or higher), cmake.
|
||||
|
||||
@ -48,6 +58,16 @@ $ cmake .
|
||||
$ make
|
||||
```
|
||||
|
||||
If you want to setup C++11 version of msgpack, execute the following command:
|
||||
|
||||
```
|
||||
$ git clone https://github.com/msgpack/msgpack-c.git
|
||||
$ cd msgpack-c
|
||||
$ cmake -DMSGPACK_CXX11=ON .
|
||||
```
|
||||
|
||||
You need the compiler that fully supports C++11.
|
||||
|
||||
#### Install from package
|
||||
|
||||
##### UNIX-like platform with ./configure
|
||||
|
22
configure.in
22
configure.in
@ -3,6 +3,27 @@ AC_CONFIG_AUX_DIR(ac)
|
||||
AM_INIT_AUTOMAKE(msgpack, 0.5.9)
|
||||
AC_CONFIG_HEADER(config.h)
|
||||
|
||||
|
||||
AC_LANG_PUSH([C++])
|
||||
AC_COMPILE_IFELSE([AC_LANG_SOURCE([
|
||||
#if __cplusplus < 201103
|
||||
#error
|
||||
#endif
|
||||
])],
|
||||
[
|
||||
./preprocess_cpp11
|
||||
if test $? != 0; then
|
||||
exit 1
|
||||
fi
|
||||
],
|
||||
[
|
||||
./preprocess
|
||||
if test $? != 0; then
|
||||
exit 1
|
||||
fi
|
||||
])
|
||||
AC_LANG_POP()
|
||||
|
||||
AC_SUBST(CFLAGS)
|
||||
CFLAGS="-O3 -Wall $CFLAGS"
|
||||
|
||||
@ -96,5 +117,6 @@ AC_OUTPUT([Makefile
|
||||
msgpack.pc
|
||||
src/Makefile
|
||||
src/msgpack/version.h
|
||||
src/msgpack/version.hpp
|
||||
test/Makefile])
|
||||
|
||||
|
170
cpp11/define.hpp
Normal file
170
cpp11/define.hpp
Normal file
@ -0,0 +1,170 @@
|
||||
//
|
||||
// MessagePack for C++ static resolution routine
|
||||
//
|
||||
// Copyright (C) 2008-2013 FURUHASHI Sadayuki and 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_TYPE_DEFINE_HPP
|
||||
#define MSGPACK_TYPE_DEFINE_HPP
|
||||
|
||||
#define MSGPACK_DEFINE(...) \
|
||||
template <typename Packer> \
|
||||
void msgpack_pack(Packer& pk) const \
|
||||
{ \
|
||||
msgpack::type::make_define(__VA_ARGS__).msgpack_pack(pk); \
|
||||
} \
|
||||
void msgpack_unpack(msgpack::object o) \
|
||||
{ \
|
||||
msgpack::type::make_define(__VA_ARGS__).msgpack_unpack(o); \
|
||||
}\
|
||||
template <typename MSGPACK_OBJECT> \
|
||||
void msgpack_object(MSGPACK_OBJECT* o, msgpack::zone* z) const \
|
||||
{ \
|
||||
msgpack::type::make_define(__VA_ARGS__).msgpack_object(o, z); \
|
||||
}
|
||||
|
||||
// MSGPACK_ADD_ENUM must be used in the global namespace.
|
||||
#define MSGPACK_ADD_ENUM(enum) \
|
||||
namespace msgpack { \
|
||||
template <> \
|
||||
inline enum& operator>> (object o, enum& v) \
|
||||
{ \
|
||||
int tmp; \
|
||||
o >> tmp; \
|
||||
v = static_cast<enum>(tmp); \
|
||||
return v; \
|
||||
} \
|
||||
template <> \
|
||||
void operator<< (object::with_zone& o, const enum& v) \
|
||||
{ \
|
||||
int tmp = static_cast<enum>(v); \
|
||||
o << tmp; \
|
||||
} \
|
||||
namespace detail { \
|
||||
template <typename Stream> \
|
||||
struct packer_serializer<Stream, enum> { \
|
||||
static packer<Stream>& pack(packer<Stream>& o, const enum& v) { \
|
||||
return o << static_cast<int>(v); \
|
||||
} \
|
||||
}; \
|
||||
} \
|
||||
}
|
||||
|
||||
namespace msgpack {
|
||||
namespace type {
|
||||
|
||||
template <typename Tuple, std::size_t N>
|
||||
struct define_imp {
|
||||
template <typename Packer>
|
||||
static void pack(Packer& pk, Tuple const& t) {
|
||||
define_imp<Tuple, N-1>::pack(pk, t);
|
||||
pk.pack(std::get<N-1>(t));
|
||||
}
|
||||
static void unpack(msgpack::object o, Tuple& t) {
|
||||
define_imp<Tuple, N-1>::unpack(o, t);
|
||||
const size_t size = o.via.array.size;
|
||||
if(size <= N-1) { return; }
|
||||
o.via.array.ptr[N-1].convert(&std::get<N-1>(t));
|
||||
}
|
||||
static void object(msgpack::object* o, msgpack::zone* z, Tuple const& t) {
|
||||
define_imp<Tuple, N-1>::object(o, z, t);
|
||||
o->via.array.ptr[N-1] = msgpack::object(std::get<N-1>(t), z);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Tuple>
|
||||
struct define_imp<Tuple, 1> {
|
||||
template <typename Packer>
|
||||
static void pack(Packer& pk, Tuple const& t) {
|
||||
pk.pack(std::get<0>(t));
|
||||
}
|
||||
static void unpack(msgpack::object o, Tuple& t) {
|
||||
const size_t size = o.via.array.size;
|
||||
if(size <= 0) { return; }
|
||||
o.via.array.ptr[0].convert(&std::get<0>(t));
|
||||
}
|
||||
static void object(msgpack::object* o, msgpack::zone* z, Tuple const& t) {
|
||||
o->via.array.ptr[0] = msgpack::object(std::get<0>(t), z);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename... Args>
|
||||
struct define {
|
||||
typedef define<Args...> value_type;
|
||||
typedef tuple<Args...> tuple_type;
|
||||
define(Args&... args) :
|
||||
a(args...) {}
|
||||
template <typename Packer>
|
||||
void msgpack_pack(Packer& pk) const
|
||||
{
|
||||
pk.pack_array(sizeof...(Args));
|
||||
|
||||
define_imp<tuple<Args&...>, sizeof...(Args)>::pack(pk, a);
|
||||
}
|
||||
void msgpack_unpack(msgpack::object o)
|
||||
{
|
||||
if(o.type != type::ARRAY) { throw type_error(); }
|
||||
|
||||
define_imp<tuple<Args&...>, sizeof...(Args)>::unpack(o, a);
|
||||
}
|
||||
void msgpack_object(msgpack::object* o, msgpack::zone* z) const
|
||||
{
|
||||
o->type = type::ARRAY;
|
||||
o->via.array.ptr = (object*)z->malloc(sizeof(object)*sizeof...(Args));
|
||||
o->via.array.size = sizeof...(Args);
|
||||
|
||||
define_imp<tuple<Args&...>, sizeof...(Args)>::object(o, z, a);
|
||||
}
|
||||
|
||||
tuple<Args&...> a;
|
||||
};
|
||||
|
||||
template <>
|
||||
struct define<> {
|
||||
typedef define<> value_type;
|
||||
typedef tuple<> tuple_type;
|
||||
template <typename Packer>
|
||||
void msgpack_pack(Packer& pk) const
|
||||
{
|
||||
pk.pack_array(0);
|
||||
}
|
||||
void msgpack_unpack(msgpack::object o)
|
||||
{
|
||||
if(o.type != type::ARRAY) { throw type_error(); }
|
||||
}
|
||||
void msgpack_object(msgpack::object* o, msgpack::zone* z) const
|
||||
{
|
||||
o->type = type::ARRAY;
|
||||
o->via.array.ptr = NULL;
|
||||
o->via.array.size = 0;
|
||||
}
|
||||
};
|
||||
|
||||
inline define<> make_define()
|
||||
{
|
||||
return define<>();
|
||||
}
|
||||
|
||||
template <typename... Args>
|
||||
define<Args...> make_define(Args&... args)
|
||||
{
|
||||
return define<Args...>(args...);
|
||||
}
|
||||
|
||||
} // namespace type
|
||||
} // namespace msgpack
|
||||
|
||||
|
||||
#endif /* msgpack/type/define.hpp */
|
||||
|
125
cpp11/tuple.hpp
Normal file
125
cpp11/tuple.hpp
Normal file
@ -0,0 +1,125 @@
|
||||
//
|
||||
// MessagePack for C++ static resolution routine
|
||||
//
|
||||
// Copyright (C) 2008-2013 FURUHASHI Sadayuki and 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_TYPE_TUPLE_HPP
|
||||
#define MSGPACK_TYPE_TUPLE_HPP
|
||||
|
||||
#include "msgpack/object.hpp"
|
||||
#include <tuple>
|
||||
|
||||
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>
|
||||
struct Packer {
|
||||
static void pack(
|
||||
packer<Stream>& o,
|
||||
const Tuple& v) {
|
||||
Packer<Stream, Tuple, N-1>::pack(o, v);
|
||||
o.pack(std::get<N-1>(v));
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Stream, typename Tuple>
|
||||
struct Packer<Stream, Tuple, 1> {
|
||||
static void pack (
|
||||
packer<Stream>& o,
|
||||
const Tuple& v) {
|
||||
o.pack(std::get<0>(v));
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Stream, typename... Args>
|
||||
const packer<Stream>& operator<< (
|
||||
packer<Stream>& o,
|
||||
const type::tuple<Args...>& v) {
|
||||
o.pack_array(sizeof...(Args));
|
||||
Packer<Stream, decltype(v), sizeof...(Args)>::pack(o, v);
|
||||
return o;
|
||||
}
|
||||
|
||||
// --- Convert from tuple to object ---
|
||||
|
||||
template <typename Tuple, std::size_t N>
|
||||
struct Converter {
|
||||
static void convert(
|
||||
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));
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Tuple>
|
||||
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));
|
||||
}
|
||||
};
|
||||
|
||||
template <typename... Args>
|
||||
type::tuple<Args...>& operator>> (
|
||||
object o,
|
||||
type::tuple<Args...>& v) {
|
||||
if(o.type != type::ARRAY) { throw type_error(); }
|
||||
if(o.via.array.size < sizeof...(Args)) { throw type_error(); }
|
||||
Converter<decltype(v), sizeof...(Args)>::convert(o, v);
|
||||
return v;
|
||||
}
|
||||
|
||||
// --- Convert from tuple to object with zone ---
|
||||
template <typename Tuple, std::size_t N>
|
||||
struct TupleToObjectWithZone {
|
||||
static void convert(
|
||||
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);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Tuple>
|
||||
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);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename... Args>
|
||||
inline void operator<< (
|
||||
object::with_zone& o,
|
||||
type::tuple<Args...>& v) {
|
||||
o.type = type::ARRAY;
|
||||
o.via.array.ptr = (object*)o.zone->malloc(sizeof(object)*sizeof...(Args));
|
||||
o.via.array.size = sizeof...(Args);
|
||||
TupleToObjectWithZone<decltype(v), sizeof...(Args)>::convert(o, v);
|
||||
}
|
||||
|
||||
} // msgpack
|
||||
|
||||
#endif /* msgpack/type/tuple.hpp */
|
||||
|
304
cpp11/zone.hpp
Normal file
304
cpp11/zone.hpp
Normal file
@ -0,0 +1,304 @@
|
||||
//
|
||||
// MessagePack for C++ memory pool
|
||||
//
|
||||
// Copyright (C) 2008-2013 FURUHASHI Sadayuki and 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_ZONE_HPP
|
||||
#define MSGPACK_ZONE_HPP
|
||||
|
||||
#include <cstdlib>
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
|
||||
#ifndef MSGPACK_ZONE_CHUNK_SIZE
|
||||
#define MSGPACK_ZONE_CHUNK_SIZE 8192
|
||||
#endif
|
||||
|
||||
#ifndef MSGPACK_ZONE_ALIGN
|
||||
#define MSGPACK_ZONE_ALIGN sizeof(int)
|
||||
#endif
|
||||
|
||||
namespace msgpack {
|
||||
|
||||
class zone {
|
||||
private:
|
||||
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);
|
||||
|
||||
++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);
|
||||
|
||||
public:
|
||||
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);
|
||||
|
||||
template <typename T>
|
||||
void push_finalizer(std::unique_ptr<T> obj);
|
||||
|
||||
void clear();
|
||||
|
||||
void swap(zone& o);
|
||||
|
||||
|
||||
template <typename T, typename... Args>
|
||||
T* allocate(Args... args);
|
||||
|
||||
private:
|
||||
void undo_malloc(size_t size);
|
||||
|
||||
template <typename T>
|
||||
static void object_destructor(void* obj);
|
||||
|
||||
void* malloc_expand(size_t size);
|
||||
};
|
||||
|
||||
inline zone* zone::create(size_t 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 void zone::destroy(zone* z)
|
||||
{
|
||||
z->~zone();
|
||||
::free(z);
|
||||
}
|
||||
|
||||
inline zone::zone(size_t chunk_size):chunk_size_(chunk_size), chunk_list_(chunk_size_)
|
||||
{
|
||||
}
|
||||
|
||||
inline void* zone::malloc(size_t size)
|
||||
{
|
||||
return malloc_no_align(
|
||||
((size)+((MSGPACK_ZONE_ALIGN)-1)) & ~((MSGPACK_ZONE_ALIGN)-1));
|
||||
}
|
||||
|
||||
inline void* zone::malloc_no_align(size_t size)
|
||||
{
|
||||
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)
|
||||
{
|
||||
finalizer_array_.push(func, data);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline void zone::push_finalizer(std::unique_ptr<T> obj)
|
||||
{
|
||||
finalizer_array_.push(&zone::object_destructor<T>, obj.get());
|
||||
obj.release();
|
||||
}
|
||||
|
||||
inline void zone::clear()
|
||||
{
|
||||
finalizer_array_.clear();
|
||||
chunk_list_.clear(chunk_size_);
|
||||
}
|
||||
|
||||
inline void zone::swap(zone& o)
|
||||
{
|
||||
std::swap(*this, o);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void zone::object_destructor(void* obj)
|
||||
{
|
||||
reinterpret_cast<T*>(obj)->~T();
|
||||
}
|
||||
|
||||
inline void zone::undo_malloc(size_t size)
|
||||
{
|
||||
chunk_list_.ptr_ -= size;
|
||||
chunk_list_.free_ += size;
|
||||
}
|
||||
|
||||
|
||||
template <typename T, typename... Args>
|
||||
T* zone::allocate(Args... args)
|
||||
{
|
||||
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(args...);
|
||||
} catch (...) {
|
||||
--finalizer_array_.tail_;
|
||||
undo_malloc(sizeof(T));
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace msgpack
|
||||
|
||||
#endif /* msgpack/zone.hpp */
|
17
preprocess_cpp11
Executable file
17
preprocess_cpp11
Executable file
@ -0,0 +1,17 @@
|
||||
#!/bin/sh
|
||||
|
||||
if [ "$1" = "clean" ];then
|
||||
rm -f src/msgpack/type/tuple.hpp
|
||||
rm -f src/msgpack/type/define.hpp
|
||||
rm -f src/msgpack/zone.hpp
|
||||
else
|
||||
cp -f cpp11/zone.hpp src/msgpack/
|
||||
cp -f cpp11/tuple.hpp src/msgpack/type/
|
||||
cp -f cpp11/define.hpp src/msgpack/type/
|
||||
fi
|
||||
cp -f cases.mpac test/
|
||||
cp -f cases_compact.mpac test/
|
||||
|
||||
sed -e 's/8\.00/9.00/' < msgpack_vc8.vcproj > msgpack_vc2008.vcproj
|
||||
sed -e 's/9\.00/10.00/' -e 's/msgpack_vc8/msgpack_vc2008/' < msgpack_vc8.sln > msgpack_vc2008.sln
|
||||
|
@ -62,6 +62,7 @@ nobase_include_HEADERS += \
|
||||
msgpack/fbuffer.hpp \
|
||||
msgpack/pack.hpp \
|
||||
msgpack/unpack.hpp \
|
||||
msgpack/version.hpp \
|
||||
msgpack/object.hpp \
|
||||
msgpack/zone.hpp \
|
||||
msgpack/type.hpp \
|
||||
@ -86,6 +87,7 @@ endif
|
||||
|
||||
EXTRA_DIST = \
|
||||
msgpack/version.h.in \
|
||||
msgpack/version.hpp.in \
|
||||
msgpack/zone.hpp.erb \
|
||||
msgpack/type/define.hpp.erb \
|
||||
msgpack/type/tuple.hpp.erb
|
||||
|
@ -21,4 +21,4 @@
|
||||
#include "msgpack/unpack.hpp"
|
||||
#include "msgpack/sbuffer.hpp"
|
||||
#include "msgpack/vrefbuffer.hpp"
|
||||
#include "msgpack.h"
|
||||
#include "msgpack/version.hpp"
|
||||
|
@ -1,7 +1,7 @@
|
||||
//
|
||||
// MessagePack for C++ simple buffer implementation
|
||||
//
|
||||
// Copyright (C) 2008-2009 FURUHASHI Sadayuki
|
||||
// Copyright (C) 2008-2013 FURUHASHI Sadayuki and KONDO Takatoshi
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
@ -15,94 +15,99 @@
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
//
|
||||
#ifndef MSGPACK_SBUFFER_HPP__
|
||||
#define MSGPACK_SBUFFER_HPP__
|
||||
#ifndef MSGPACK_SBUFFER_HPP
|
||||
#define MSGPACK_SBUFFER_HPP
|
||||
|
||||
#include "sbuffer.h"
|
||||
#include <stdexcept>
|
||||
|
||||
#ifndef MSGPACK_SBUFFER_INIT_SIZE
|
||||
#define MSGPACK_SBUFFER_INIT_SIZE 8192
|
||||
#endif
|
||||
|
||||
namespace msgpack {
|
||||
|
||||
|
||||
class sbuffer : public msgpack_sbuffer {
|
||||
class sbuffer {
|
||||
public:
|
||||
sbuffer(size_t initsz = MSGPACK_SBUFFER_INIT_SIZE)
|
||||
sbuffer(size_t initsz = MSGPACK_SBUFFER_INIT_SIZE):size_(0), alloc_(initsz)
|
||||
{
|
||||
if(initsz == 0) {
|
||||
base::data = NULL;
|
||||
data_ = nullptr;
|
||||
} else {
|
||||
base::data = (char*)::malloc(initsz);
|
||||
if(!base::data) {
|
||||
data_ = (char*)::malloc(initsz);
|
||||
if(!data_) {
|
||||
throw std::bad_alloc();
|
||||
}
|
||||
}
|
||||
|
||||
base::size = 0;
|
||||
base::alloc = initsz;
|
||||
}
|
||||
|
||||
~sbuffer()
|
||||
{
|
||||
::free(base::data);
|
||||
::free(data_);
|
||||
}
|
||||
|
||||
public:
|
||||
void write(const char* buf, size_t len)
|
||||
{
|
||||
if(base::alloc - base::size < len) {
|
||||
if(alloc_ - size_ < len) {
|
||||
expand_buffer(len);
|
||||
}
|
||||
memcpy(base::data + base::size, buf, len);
|
||||
base::size += len;
|
||||
::memcpy(data_ + size_, buf, len);
|
||||
size_ += len;
|
||||
}
|
||||
|
||||
char* data()
|
||||
{
|
||||
return base::data;
|
||||
return data_;
|
||||
}
|
||||
|
||||
const char* data() const
|
||||
{
|
||||
return base::data;
|
||||
return data_;
|
||||
}
|
||||
|
||||
size_t size() const
|
||||
{
|
||||
return base::size;
|
||||
return size_;
|
||||
}
|
||||
|
||||
char* release()
|
||||
{
|
||||
return msgpack_sbuffer_release(this);
|
||||
char* tmp = data_;
|
||||
size_ = 0;
|
||||
data_ = nullptr;
|
||||
alloc_ = 0;
|
||||
return tmp;
|
||||
}
|
||||
|
||||
void clear()
|
||||
{
|
||||
msgpack_sbuffer_clear(this);
|
||||
size_ = 0;
|
||||
}
|
||||
|
||||
private:
|
||||
void expand_buffer(size_t len)
|
||||
{
|
||||
size_t nsize = (base::alloc > 0) ?
|
||||
base::alloc * 2 : MSGPACK_SBUFFER_INIT_SIZE;
|
||||
size_t nsize = (alloc_ > 0) ?
|
||||
alloc_ * 2 : MSGPACK_SBUFFER_INIT_SIZE;
|
||||
|
||||
while(nsize < base::size + len) { nsize *= 2; }
|
||||
while(nsize < size_ + len) { nsize *= 2; }
|
||||
|
||||
void* tmp = realloc(base::data, nsize);
|
||||
void* tmp = ::realloc(data_, nsize);
|
||||
if(!tmp) {
|
||||
throw std::bad_alloc();
|
||||
}
|
||||
|
||||
base::data = (char*)tmp;
|
||||
base::alloc = nsize;
|
||||
data_ = (char*)tmp;
|
||||
alloc_ = nsize;
|
||||
}
|
||||
|
||||
private:
|
||||
typedef msgpack_sbuffer base;
|
||||
|
||||
private:
|
||||
sbuffer(const sbuffer&);
|
||||
private:
|
||||
size_t size_;
|
||||
char* data_;
|
||||
size_t alloc_;
|
||||
};
|
||||
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
//
|
||||
// MessagePack for C++ deserializing routine
|
||||
//
|
||||
// Copyright (C) 2008-2009 FURUHASHI Sadayuki
|
||||
// Copyright (C) 2008-2013 FURUHASHI Sadayuki and KONDO Takatoshi
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
@ -15,22 +15,490 @@
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
//
|
||||
#ifndef MSGPACK_UNPACK_HPP__
|
||||
#define MSGPACK_UNPACK_HPP__
|
||||
#ifndef MSGPACK_UNPACK_HPP
|
||||
#define MSGPACK_UNPACK_HPP
|
||||
|
||||
#include "unpack.h"
|
||||
#include "object.hpp"
|
||||
#include "zone.hpp"
|
||||
#include "unpack_define.h"
|
||||
|
||||
#include <memory>
|
||||
#include <stdexcept>
|
||||
|
||||
|
||||
#define COUNTER_SIZE (sizeof(_msgpack_atomic_counter_t))
|
||||
|
||||
#ifndef MSGPACK_UNPACKER_INIT_BUFFER_SIZE
|
||||
#define MSGPACK_UNPACKER_INIT_BUFFER_SIZE (64*1024)
|
||||
#endif
|
||||
|
||||
#ifndef MSGPACK_UNPACKER_RESERVE_SIZE
|
||||
#define MSGPACK_UNPACKER_RESERVE_SIZE (32*1024)
|
||||
#endif
|
||||
|
||||
|
||||
// backward compatibility
|
||||
#ifndef MSGPACK_UNPACKER_DEFAULT_INITIAL_BUFFER_SIZE
|
||||
#define MSGPACK_UNPACKER_DEFAULT_INITIAL_BUFFER_SIZE MSGPACK_UNPACKER_INIT_BUFFER_SIZE
|
||||
#endif
|
||||
|
||||
|
||||
namespace msgpack {
|
||||
|
||||
namespace detail {
|
||||
|
||||
struct unpack_user {
|
||||
zone* z;
|
||||
bool referenced;
|
||||
};
|
||||
|
||||
|
||||
static inline ::msgpack::object template_callback_root(unpack_user* u)
|
||||
{ ::msgpack::object o = {}; return o; }
|
||||
|
||||
static inline int template_callback_uint8(unpack_user* u, uint8_t d, ::msgpack::object* o)
|
||||
{ o->type = ::msgpack::type::POSITIVE_INTEGER; o->via.u64 = d; return 0; }
|
||||
|
||||
static inline int template_callback_uint16(unpack_user* u, uint16_t d, ::msgpack::object* o)
|
||||
{ o->type = ::msgpack::type::POSITIVE_INTEGER; o->via.u64 = d; return 0; }
|
||||
|
||||
static inline int template_callback_uint32(unpack_user* u, uint32_t d, ::msgpack::object* o)
|
||||
{ o->type = ::msgpack::type::POSITIVE_INTEGER; o->via.u64 = d; return 0; }
|
||||
|
||||
static inline int template_callback_uint64(unpack_user* u, uint64_t d, ::msgpack::object* o)
|
||||
{ o->type = ::msgpack::type::POSITIVE_INTEGER; o->via.u64 = d; return 0; }
|
||||
|
||||
static inline int template_callback_int8(unpack_user* u, int8_t d, ::msgpack::object* o)
|
||||
{ if(d >= 0) { o->type = ::msgpack::type::POSITIVE_INTEGER; o->via.u64 = d; return 0; }
|
||||
else { o->type = ::msgpack::type::NEGATIVE_INTEGER; o->via.i64 = d; return 0; } }
|
||||
|
||||
static inline int template_callback_int16(unpack_user* u, int16_t d, ::msgpack::object* o)
|
||||
{ if(d >= 0) { o->type = ::msgpack::type::POSITIVE_INTEGER; o->via.u64 = d; return 0; }
|
||||
else { o->type = ::msgpack::type::NEGATIVE_INTEGER; o->via.i64 = d; return 0; } }
|
||||
|
||||
static inline int template_callback_int32(unpack_user* u, int32_t d, ::msgpack::object* o)
|
||||
{ if(d >= 0) { o->type = ::msgpack::type::POSITIVE_INTEGER; o->via.u64 = d; return 0; }
|
||||
else { o->type = ::msgpack::type::NEGATIVE_INTEGER; o->via.i64 = d; return 0; } }
|
||||
|
||||
static inline int template_callback_int64(unpack_user* u, int64_t d, ::msgpack::object* o)
|
||||
{ if(d >= 0) { o->type = ::msgpack::type::POSITIVE_INTEGER; o->via.u64 = d; return 0; }
|
||||
else { o->type = ::msgpack::type::NEGATIVE_INTEGER; o->via.i64 = d; return 0; } }
|
||||
|
||||
static inline int template_callback_float(unpack_user* u, float d, ::msgpack::object* o)
|
||||
{ o->type = ::msgpack::type::DOUBLE; o->via.dec = d; return 0; }
|
||||
|
||||
static inline int template_callback_double(unpack_user* u, double d, ::msgpack::object* o)
|
||||
{ o->type = ::msgpack::type::DOUBLE; o->via.dec = d; return 0; }
|
||||
|
||||
static inline int template_callback_nil(unpack_user* u, ::msgpack::object* o)
|
||||
{ o->type = ::msgpack::type::NIL; return 0; }
|
||||
|
||||
static inline int template_callback_true(unpack_user* u, ::msgpack::object* o)
|
||||
{ o->type = ::msgpack::type::BOOLEAN; o->via.boolean = true; return 0; }
|
||||
|
||||
static inline int template_callback_false(unpack_user* u, ::msgpack::object* o)
|
||||
{ o->type = ::msgpack::type::BOOLEAN; o->via.boolean = false; return 0; }
|
||||
|
||||
static inline int template_callback_array(unpack_user* u, unsigned int n, ::msgpack::object* o)
|
||||
{
|
||||
o->type = ::msgpack::type::ARRAY;
|
||||
o->via.array.size = 0;
|
||||
o->via.array.ptr = (::msgpack::object*)u->z->malloc(n*sizeof(::msgpack::object));
|
||||
if(o->via.array.ptr == NULL) { return -1; }
|
||||
return 0;
|
||||
}
|
||||
|
||||
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 int template_callback_map(unpack_user* u, unsigned int n, ::msgpack::object* o)
|
||||
{
|
||||
o->type = ::msgpack::type::MAP;
|
||||
o->via.map.size = 0;
|
||||
o->via.map.ptr = (::msgpack::object_kv*)u->z->malloc(n*sizeof(::msgpack::object_kv));
|
||||
if(o->via.map.ptr == NULL) { return -1; }
|
||||
return 0;
|
||||
}
|
||||
|
||||
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::type::RAW;
|
||||
o->via.raw.ptr = p;
|
||||
o->via.raw.size = l;
|
||||
u->referenced = true;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
struct template_unpack_stack {
|
||||
::msgpack::object obj;
|
||||
size_t count;
|
||||
unsigned int ct;
|
||||
::msgpack::object map_key;
|
||||
};
|
||||
|
||||
struct template_context {
|
||||
unpack_user user;
|
||||
unsigned int cs;
|
||||
unsigned int trail;
|
||||
unsigned int top;
|
||||
template_unpack_stack stack[MSGPACK_EMBED_STACK_SIZE];
|
||||
};
|
||||
|
||||
|
||||
inline void init_count(void* buffer)
|
||||
{
|
||||
*(volatile _msgpack_atomic_counter_t*)buffer = 1;
|
||||
}
|
||||
|
||||
inline void decl_count(void* buffer)
|
||||
{
|
||||
// atomic if(--*(_msgpack_atomic_counter_t*)buffer == 0) { free(buffer); }
|
||||
if(_msgpack_sync_decr_and_fetch((volatile _msgpack_atomic_counter_t*)buffer) == 0) {
|
||||
free(buffer);
|
||||
}
|
||||
}
|
||||
|
||||
inline void incr_count(void* buffer)
|
||||
{
|
||||
// atomic ++*(_msgpack_atomic_counter_t*)buffer;
|
||||
_msgpack_sync_incr_and_fetch((volatile _msgpack_atomic_counter_t*)buffer);
|
||||
}
|
||||
|
||||
inline _msgpack_atomic_counter_t get_count(void* buffer)
|
||||
{
|
||||
return *(volatile _msgpack_atomic_counter_t*)buffer;
|
||||
}
|
||||
|
||||
inline void template_init(template_context& ctx)
|
||||
{
|
||||
ctx.cs = CS_HEADER;
|
||||
ctx.trail = 0;
|
||||
ctx.top = 0;
|
||||
ctx.stack[0].obj = template_callback_root(&ctx.user);
|
||||
}
|
||||
|
||||
::msgpack::object template_data(template_context const& ctx)
|
||||
{
|
||||
return ctx.stack[0].obj;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline unsigned int next_cs(T p)
|
||||
{
|
||||
return (unsigned int)*p & 0x1f;
|
||||
}
|
||||
|
||||
int template_execute(template_context& ctx, const char* data, size_t len, size_t* off)
|
||||
{
|
||||
assert(len >= *off);
|
||||
|
||||
const unsigned char* p = (unsigned char*)data + *off;
|
||||
const unsigned char* const pe = (unsigned char*)data + len;
|
||||
const void* n = nullptr;
|
||||
|
||||
unsigned int trail = ctx.trail;
|
||||
unsigned int cs = ctx.cs;
|
||||
unsigned int top = ctx.top;
|
||||
detail::template_unpack_stack* stack = ctx.stack;
|
||||
/*
|
||||
unsigned int stack_size = ctx.stack_size;
|
||||
*/
|
||||
unpack_user* user = &ctx.user;
|
||||
|
||||
::msgpack::object obj;
|
||||
detail::template_unpack_stack* c = nullptr;
|
||||
|
||||
int ret;
|
||||
|
||||
|
||||
if(p == pe) { goto _out; }
|
||||
do {
|
||||
switch(cs) {
|
||||
case CS_HEADER:
|
||||
if (0) {
|
||||
} else if(0x00 <= *p && *p <= 0x7f) { // Positive Fixnum
|
||||
if(template_callback_uint8(user, *(uint8_t*)p, &obj) < 0) { goto _failed; }
|
||||
goto _push;
|
||||
} else if(0xe0 <= *p && *p <= 0xff) { // Negative Fixnum
|
||||
if(template_callback_int8(user, *(int8_t*)p, &obj) < 0) { goto _failed; }
|
||||
goto _push;
|
||||
} else if(0xc0 <= *p && *p <= 0xdf) { // Variable
|
||||
switch(*p) {
|
||||
case 0xc0: // nil
|
||||
if(template_callback_nil(user, &obj) < 0) { goto _failed; }
|
||||
goto _push;
|
||||
//case 0xc1: // string
|
||||
// again_terminal_trail(next_cs(p), p+1);
|
||||
case 0xc2: // false
|
||||
if(template_callback_false(user, &obj) < 0) { goto _failed; }
|
||||
goto _push;
|
||||
case 0xc3: // true
|
||||
if(template_callback_true(user, &obj) < 0) { goto _failed; }
|
||||
goto _push;
|
||||
case 0xc4: // bin 8
|
||||
case 0xc5: // bin 16
|
||||
case 0xc6: // bin 32
|
||||
trail = 1 << (((unsigned int)*p) & 0x03);
|
||||
cs = next_cs(p);
|
||||
goto _fixed_trail_again;
|
||||
|
||||
//case 0xc7:
|
||||
//case 0xc8:
|
||||
//case 0xc9:
|
||||
case 0xca: // float
|
||||
case 0xcb: // double
|
||||
case 0xcc: // unsigned int 8
|
||||
case 0xcd: // unsigned int 16
|
||||
case 0xce: // unsigned int 32
|
||||
case 0xcf: // unsigned int 64
|
||||
case 0xd0: // signed int 8
|
||||
case 0xd1: // signed int 16
|
||||
case 0xd2: // signed int 32
|
||||
case 0xd3: // signed int 64
|
||||
trail = 1 << (((unsigned int)*p) & 0x03);
|
||||
cs = next_cs(p);
|
||||
goto _fixed_trail_again;
|
||||
//case 0xd4:
|
||||
//case 0xd5:
|
||||
//case 0xd6: // big integer 16
|
||||
//case 0xd7: // big integer 32
|
||||
//case 0xd8: // big float 16
|
||||
case 0xd9: // raw 8 (str 8)
|
||||
case 0xda: // raw 16 (str 16)
|
||||
case 0xdb: // raw 32 (str 32)
|
||||
trail = 1 << ((((unsigned int)*p) & 0x03) - 1);
|
||||
cs = next_cs(p);
|
||||
goto _fixed_trail_again;
|
||||
case 0xdc: // array 16
|
||||
case 0xdd: // array 32
|
||||
case 0xde: // map 16
|
||||
case 0xdf: // map 32
|
||||
trail = 2 << (((unsigned int)*p) & 0x01);
|
||||
cs = next_cs(p);
|
||||
goto _fixed_trail_again;
|
||||
default:
|
||||
goto _failed;
|
||||
}
|
||||
} else if(0xa0 <= *p && *p <= 0xbf) { // FixRaw
|
||||
trail = (unsigned int)*p & 0x1f;
|
||||
if(trail == 0) { goto _raw_zero; }
|
||||
cs = ACS_RAW_VALUE;
|
||||
goto _fixed_trail_again;
|
||||
|
||||
} else if(0x90 <= *p && *p <= 0x9f) { // FixArray
|
||||
if(top >= MSGPACK_EMBED_STACK_SIZE) { goto _failed; } /* FIXME */
|
||||
if(template_callback_array(user, ((unsigned int)*p) & 0x0f, &stack[top].obj) < 0) { goto _failed; }
|
||||
if((((unsigned int)*p) & 0x0f) == 0) { obj = stack[top].obj; goto _push; }
|
||||
stack[top].ct = CT_ARRAY_ITEM;
|
||||
stack[top].count = ((unsigned int)*p) & 0x0f;
|
||||
++top;
|
||||
goto _header_again;
|
||||
|
||||
} else if(0x80 <= *p && *p <= 0x8f) { // FixMap
|
||||
if(top >= MSGPACK_EMBED_STACK_SIZE) { goto _failed; } /* FIXME */
|
||||
if(template_callback_map(user, ((unsigned int)*p) & 0x0f, &stack[top].obj) < 0) { goto _failed; }
|
||||
if((((unsigned int)*p) & 0x0f) == 0) { obj = stack[top].obj; goto _push; }
|
||||
stack[top].ct = CT_MAP_KEY;
|
||||
stack[top].count = ((unsigned int)*p) & 0x0f;
|
||||
++top;
|
||||
goto _header_again;
|
||||
|
||||
} else {
|
||||
goto _failed;
|
||||
}
|
||||
// end CS_HEADER
|
||||
|
||||
|
||||
_fixed_trail_again:
|
||||
++p;
|
||||
|
||||
default:
|
||||
if((size_t)(pe - p) < trail) { goto _out; }
|
||||
n = p; p += trail - 1;
|
||||
switch(cs) {
|
||||
//case CS_
|
||||
//case CS_
|
||||
case CS_FLOAT: {
|
||||
union { uint32_t i; float f; } mem;
|
||||
mem.i = _msgpack_load32(uint32_t,n);
|
||||
if(template_callback_float(user, mem.f, &obj) < 0) { goto _failed; }
|
||||
goto _push; }
|
||||
case CS_DOUBLE: {
|
||||
union { uint64_t i; double f; } mem;
|
||||
mem.i = _msgpack_load64(uint64_t,n);
|
||||
#if defined(__arm__) && !(__ARM_EABI__) // arm-oabi
|
||||
// https://github.com/msgpack/msgpack-perl/pull/1
|
||||
mem.i = (mem.i & 0xFFFFFFFFUL) << 32UL | (mem.i >> 32UL);
|
||||
#endif
|
||||
if(template_callback_double(user, mem.f, &obj) < 0) { goto _failed; }
|
||||
goto _push; }
|
||||
case CS_UINT_8:
|
||||
if(template_callback_uint8(user, *(uint8_t*)n, &obj) < 0) { goto _failed; }
|
||||
goto _push;
|
||||
case CS_UINT_16:
|
||||
if(template_callback_uint16(user, _msgpack_load16(uint16_t,n), &obj) < 0) { goto _failed; }
|
||||
goto _push;
|
||||
case CS_UINT_32:
|
||||
if(template_callback_uint32(user, _msgpack_load32(uint32_t,n), &obj) < 0) { goto _failed; }
|
||||
goto _push;
|
||||
case CS_UINT_64:
|
||||
if(template_callback_uint64(user, _msgpack_load64(uint64_t,n), &obj) < 0) { goto _failed; }
|
||||
goto _push;
|
||||
|
||||
case CS_INT_8:
|
||||
if(template_callback_int8(user, *(int8_t*)n, &obj) < 0) { goto _failed; }
|
||||
goto _push;
|
||||
case CS_INT_16:
|
||||
if(template_callback_int16(user, _msgpack_load16(int16_t,n), &obj) < 0) { goto _failed; }
|
||||
goto _push;
|
||||
case CS_INT_32:
|
||||
if(template_callback_int32(user, _msgpack_load32(int32_t,n), &obj) < 0) { goto _failed; }
|
||||
goto _push;
|
||||
case CS_INT_64:
|
||||
if(template_callback_int64(user, _msgpack_load64(int64_t,n), &obj) < 0) { goto _failed; }
|
||||
goto _push;
|
||||
|
||||
case CS_BIN_8:
|
||||
case CS_RAW_8:
|
||||
trail = *(uint8_t*)n;
|
||||
if(trail == 0) { goto _raw_zero; }
|
||||
cs = ACS_RAW_VALUE;
|
||||
goto _fixed_trail_again;
|
||||
case CS_BIN_16:
|
||||
case CS_RAW_16:
|
||||
trail = _msgpack_load16(uint16_t, n);
|
||||
if(trail == 0) { goto _raw_zero; }
|
||||
cs = ACS_RAW_VALUE;
|
||||
goto _fixed_trail_again;
|
||||
case CS_BIN_32:
|
||||
case CS_RAW_32:
|
||||
trail = _msgpack_load32(uint32_t, n);
|
||||
if(trail == 0) { goto _raw_zero; }
|
||||
cs = ACS_RAW_VALUE;
|
||||
goto _fixed_trail_again;
|
||||
case ACS_RAW_VALUE:
|
||||
_raw_zero:
|
||||
if(template_callback_raw(user, (const char*)data, (const char*)n, trail, &obj) < 0) { goto _failed; }
|
||||
goto _push;
|
||||
case CS_ARRAY_16:
|
||||
if(top >= MSGPACK_EMBED_STACK_SIZE) { goto _failed; } /* FIXME */
|
||||
if(template_callback_array(user, _msgpack_load16(uint16_t, n), &stack[top].obj) < 0) { goto _failed; }
|
||||
if(_msgpack_load16(uint16_t, n) == 0) { obj = stack[top].obj; goto _push; }
|
||||
stack[top].ct = CT_ARRAY_ITEM;
|
||||
stack[top].count = _msgpack_load16(uint16_t, n);
|
||||
++top;
|
||||
goto _header_again;
|
||||
case CS_ARRAY_32:
|
||||
/* FIXME security guard */
|
||||
if(top >= MSGPACK_EMBED_STACK_SIZE) { goto _failed; } /* FIXME */
|
||||
if(template_callback_array(user, _msgpack_load32(uint32_t, n), &stack[top].obj) < 0) { goto _failed; }
|
||||
if(_msgpack_load32(uint32_t, n) == 0) { obj = stack[top].obj; goto _push; }
|
||||
stack[top].ct = CT_ARRAY_ITEM;
|
||||
stack[top].count = _msgpack_load32(uint32_t, n);
|
||||
++top;
|
||||
goto _header_again;
|
||||
|
||||
case CS_MAP_16:
|
||||
if(top >= MSGPACK_EMBED_STACK_SIZE) { goto _failed; } /* FIXME */
|
||||
if(template_callback_map(user, _msgpack_load16(uint16_t, n), &stack[top].obj) < 0) { goto _failed; }
|
||||
if(_msgpack_load16(uint16_t, n) == 0) { obj = stack[top].obj; goto _push; }
|
||||
stack[top].ct = CT_MAP_KEY;
|
||||
stack[top].count = _msgpack_load16(uint16_t, n);
|
||||
++top;
|
||||
goto _header_again;
|
||||
case CS_MAP_32:
|
||||
/* FIXME security guard */
|
||||
if(top >= MSGPACK_EMBED_STACK_SIZE) { goto _failed; } /* FIXME */
|
||||
if(template_callback_map(user, _msgpack_load32(uint32_t, n), &stack[top].obj) < 0) { goto _failed; }
|
||||
if(_msgpack_load32(uint32_t, n) == 0) { obj = stack[top].obj; goto _push; }
|
||||
stack[top].ct = CT_MAP_KEY;
|
||||
stack[top].count = _msgpack_load32(uint32_t, n);
|
||||
++top;
|
||||
goto _header_again;
|
||||
|
||||
default:
|
||||
goto _failed;
|
||||
}
|
||||
}
|
||||
|
||||
_push:
|
||||
if(top == 0) { goto _finish; }
|
||||
c = &stack[top-1];
|
||||
switch(c->ct) {
|
||||
case CT_ARRAY_ITEM:
|
||||
if(template_callback_array_item(user, &c->obj, obj) < 0) { goto _failed; }
|
||||
if(--c->count == 0) {
|
||||
obj = c->obj;
|
||||
--top;
|
||||
/*printf("stack pop %d\n", top);*/
|
||||
goto _push;
|
||||
}
|
||||
goto _header_again;
|
||||
case CT_MAP_KEY:
|
||||
c->map_key = obj;
|
||||
c->ct = CT_MAP_VALUE;
|
||||
goto _header_again;
|
||||
case CT_MAP_VALUE:
|
||||
if(template_callback_map_item(user, &c->obj, c->map_key, obj) < 0) { goto _failed; }
|
||||
if(--c->count == 0) {
|
||||
obj = c->obj;
|
||||
--top;
|
||||
/*printf("stack pop %d\n", top);*/
|
||||
goto _push;
|
||||
}
|
||||
c->ct = CT_MAP_KEY;
|
||||
goto _header_again;
|
||||
|
||||
default:
|
||||
goto _failed;
|
||||
}
|
||||
|
||||
_header_again:
|
||||
cs = CS_HEADER;
|
||||
++p;
|
||||
} while(p != pe);
|
||||
goto _out;
|
||||
|
||||
|
||||
_finish:
|
||||
stack[0].obj = obj;
|
||||
++p;
|
||||
ret = 1;
|
||||
/*printf("-- finish --\n"); */
|
||||
goto _end;
|
||||
|
||||
_failed:
|
||||
/*printf("** FAILED **\n"); */
|
||||
ret = -1;
|
||||
goto _end;
|
||||
|
||||
_out:
|
||||
ret = 0;
|
||||
goto _end;
|
||||
|
||||
_end:
|
||||
ctx.cs = cs;
|
||||
ctx.trail = trail;
|
||||
ctx.top = top;
|
||||
*off = p - (const unsigned char*)data;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
} // detail
|
||||
|
||||
|
||||
struct unpack_error : public std::runtime_error {
|
||||
unpack_error(const std::string& msg) :
|
||||
@ -42,8 +510,8 @@ class unpacked {
|
||||
public:
|
||||
unpacked() { }
|
||||
|
||||
unpacked(object obj, std::auto_ptr<msgpack::zone> z) :
|
||||
m_obj(obj), m_zone(z) { }
|
||||
unpacked(object obj, std::unique_ptr<msgpack::zone> z) :
|
||||
m_obj(obj), m_zone(std::move(z)) { }
|
||||
|
||||
object& get()
|
||||
{ return m_obj; }
|
||||
@ -51,19 +519,19 @@ public:
|
||||
const object& get() const
|
||||
{ return m_obj; }
|
||||
|
||||
std::auto_ptr<msgpack::zone>& zone()
|
||||
std::unique_ptr<msgpack::zone>& zone()
|
||||
{ return m_zone; }
|
||||
|
||||
const std::auto_ptr<msgpack::zone>& zone() const
|
||||
const std::unique_ptr<msgpack::zone>& zone() const
|
||||
{ return m_zone; }
|
||||
|
||||
private:
|
||||
object m_obj;
|
||||
std::auto_ptr<msgpack::zone> m_zone;
|
||||
std::unique_ptr<msgpack::zone> m_zone;
|
||||
};
|
||||
|
||||
|
||||
class unpacker : public msgpack_unpacker {
|
||||
class unpacker {
|
||||
public:
|
||||
unpacker(size_t init_buffer_size = MSGPACK_UNPACKER_INIT_BUFFER_SIZE);
|
||||
~unpacker();
|
||||
@ -154,7 +622,19 @@ public:
|
||||
void remove_nonparsed_buffer();
|
||||
|
||||
private:
|
||||
typedef msgpack_unpacker base;
|
||||
void expand_buffer(size_t size);
|
||||
int execute_imp();
|
||||
bool flush_zone();
|
||||
|
||||
private:
|
||||
char* buffer_;
|
||||
size_t used_;
|
||||
size_t free_;
|
||||
size_t off_;
|
||||
size_t parsed_;
|
||||
zone* z_;
|
||||
size_t initial_buffer_size_;
|
||||
detail::template_context ctx_;
|
||||
|
||||
private:
|
||||
unpacker(const unpacker&);
|
||||
@ -184,42 +664,130 @@ static object unpack(const char* data, size_t len, zone& z, size_t* off = NULL);
|
||||
|
||||
inline unpacker::unpacker(size_t initial_buffer_size)
|
||||
{
|
||||
if(!msgpack_unpacker_init(this, initial_buffer_size)) {
|
||||
if(initial_buffer_size < COUNTER_SIZE) {
|
||||
initial_buffer_size = COUNTER_SIZE;
|
||||
}
|
||||
|
||||
char* buffer = (char*)::malloc(initial_buffer_size);
|
||||
if(!buffer) {
|
||||
throw std::bad_alloc();
|
||||
}
|
||||
|
||||
zone* z = zone::create(MSGPACK_ZONE_CHUNK_SIZE);
|
||||
if(!z) {
|
||||
::free(buffer);
|
||||
throw std::bad_alloc();
|
||||
}
|
||||
|
||||
buffer_ = buffer;
|
||||
used_ = COUNTER_SIZE;
|
||||
free_ = initial_buffer_size - used_;
|
||||
off_ = COUNTER_SIZE;
|
||||
parsed_ = 0;
|
||||
initial_buffer_size_ = initial_buffer_size;
|
||||
z_ = z;
|
||||
|
||||
detail::init_count(buffer_);
|
||||
|
||||
detail::template_init(ctx_);
|
||||
ctx_.user.z = z_;
|
||||
ctx_.user.referenced = false;
|
||||
}
|
||||
|
||||
inline unpacker::~unpacker()
|
||||
{
|
||||
msgpack_unpacker_destroy(this);
|
||||
zone::destroy(z_);
|
||||
detail::decl_count(buffer_);
|
||||
}
|
||||
|
||||
|
||||
inline void unpacker::reserve_buffer(size_t size)
|
||||
{
|
||||
if(!msgpack_unpacker_reserve_buffer(this, size)) {
|
||||
throw std::bad_alloc();
|
||||
if(free_ >= size) return;
|
||||
expand_buffer(size);
|
||||
}
|
||||
|
||||
inline void unpacker::expand_buffer(size_t size)
|
||||
{
|
||||
if(used_ == off_ && detail::get_count(buffer_) == 1
|
||||
&& !ctx_.user.referenced) {
|
||||
// rewind buffer
|
||||
free_ += used_ - COUNTER_SIZE;
|
||||
used_ = COUNTER_SIZE;
|
||||
off_ = COUNTER_SIZE;
|
||||
|
||||
if(free_ >= size) return;
|
||||
}
|
||||
|
||||
if(off_ == COUNTER_SIZE) {
|
||||
size_t next_size = (used_ + free_) * 2; // include COUNTER_SIZE
|
||||
while(next_size < size + used_) {
|
||||
next_size *= 2;
|
||||
}
|
||||
|
||||
char* tmp = (char*)::realloc(buffer_, next_size);
|
||||
if(!tmp) {
|
||||
throw std::bad_alloc();
|
||||
}
|
||||
|
||||
buffer_ = tmp;
|
||||
free_ = next_size - used_;
|
||||
|
||||
} else {
|
||||
size_t next_size = initial_buffer_size_; // include COUNTER_SIZE
|
||||
size_t not_parsed = used_ - off_;
|
||||
while(next_size < size + not_parsed + COUNTER_SIZE) {
|
||||
next_size *= 2;
|
||||
}
|
||||
|
||||
char* tmp = (char*)::malloc(next_size);
|
||||
if(!tmp) {
|
||||
throw std::bad_alloc();
|
||||
}
|
||||
|
||||
detail::init_count(tmp);
|
||||
|
||||
::memcpy(tmp+COUNTER_SIZE, buffer_ + off_, not_parsed);
|
||||
|
||||
if(ctx_.user.referenced) {
|
||||
try {
|
||||
z_->push_finalizer(&detail::decl_count, buffer_);
|
||||
}
|
||||
catch (...) {
|
||||
::free(tmp);
|
||||
throw;
|
||||
}
|
||||
ctx_.user.referenced = false;
|
||||
} else {
|
||||
detail::decl_count(buffer_);
|
||||
}
|
||||
|
||||
buffer_ = tmp;
|
||||
used_ = not_parsed + COUNTER_SIZE;
|
||||
free_ = next_size - used_;
|
||||
off_ = COUNTER_SIZE;
|
||||
}
|
||||
}
|
||||
|
||||
inline char* unpacker::buffer()
|
||||
{
|
||||
return msgpack_unpacker_buffer(this);
|
||||
return buffer_ + used_;
|
||||
}
|
||||
|
||||
inline size_t unpacker::buffer_capacity() const
|
||||
{
|
||||
return msgpack_unpacker_buffer_capacity(this);
|
||||
return free_;
|
||||
}
|
||||
|
||||
inline void unpacker::buffer_consumed(size_t size)
|
||||
{
|
||||
return msgpack_unpacker_buffer_consumed(this, size);
|
||||
used_ += size;
|
||||
free_ -= size;
|
||||
}
|
||||
|
||||
inline bool unpacker::next(unpacked* result)
|
||||
{
|
||||
int ret = msgpack_unpacker_execute(this);
|
||||
int ret = execute_imp();
|
||||
|
||||
if(ret < 0) {
|
||||
throw unpack_error("parse error");
|
||||
@ -241,7 +809,7 @@ inline bool unpacker::next(unpacked* result)
|
||||
|
||||
inline bool unpacker::execute()
|
||||
{
|
||||
int ret = msgpack_unpacker_execute(this);
|
||||
int ret = execute_imp();
|
||||
if(ret < 0) {
|
||||
throw unpack_error("parse error");
|
||||
} else if(ret == 0) {
|
||||
@ -251,77 +819,159 @@ inline bool unpacker::execute()
|
||||
}
|
||||
}
|
||||
|
||||
inline int unpacker::execute_imp()
|
||||
{
|
||||
size_t off = off_;
|
||||
int ret = detail::template_execute(ctx_,
|
||||
buffer_, used_, &off_);
|
||||
if(off_ > off) {
|
||||
parsed_ += off_ - off;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
inline object unpacker::data()
|
||||
{
|
||||
return msgpack_unpacker_data(this);
|
||||
return template_data(ctx_);
|
||||
}
|
||||
|
||||
inline zone* unpacker::release_zone()
|
||||
{
|
||||
return static_cast<msgpack::zone*>(msgpack_unpacker_release_zone(static_cast<msgpack_unpacker*>(this)));
|
||||
if(!flush_zone()) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
zone* r = zone::create(MSGPACK_ZONE_CHUNK_SIZE);
|
||||
if(!r) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
zone* old = z_;
|
||||
z_ = r;
|
||||
ctx_.user.z = z_;
|
||||
|
||||
return old;
|
||||
}
|
||||
|
||||
inline void unpacker::reset_zone()
|
||||
{
|
||||
msgpack_unpacker_reset_zone(this);
|
||||
z_->clear();
|
||||
}
|
||||
|
||||
inline bool unpacker::flush_zone()
|
||||
{
|
||||
if(ctx_.user.referenced) {
|
||||
try {
|
||||
z_->push_finalizer(&detail::decl_count, buffer_);
|
||||
} catch (...) {
|
||||
return false;
|
||||
}
|
||||
ctx_.user.referenced = false;
|
||||
|
||||
detail::incr_count(buffer_);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
inline void unpacker::reset()
|
||||
{
|
||||
msgpack_unpacker_reset(this);
|
||||
detail::template_init(ctx_);
|
||||
// don't reset referenced flag
|
||||
parsed_ = 0;
|
||||
}
|
||||
|
||||
|
||||
inline size_t unpacker::message_size() const
|
||||
{
|
||||
return msgpack_unpacker_message_size(this);
|
||||
return parsed_ - off_ + used_;
|
||||
}
|
||||
|
||||
inline size_t unpacker::parsed_size() const
|
||||
{
|
||||
return msgpack_unpacker_parsed_size(this);
|
||||
return parsed_;
|
||||
}
|
||||
|
||||
inline char* unpacker::nonparsed_buffer()
|
||||
{
|
||||
return base::buffer + base::off;
|
||||
return buffer_ + off_;
|
||||
}
|
||||
|
||||
inline size_t unpacker::nonparsed_size() const
|
||||
{
|
||||
return base::used - base::off;
|
||||
return used_ - off_;
|
||||
}
|
||||
|
||||
inline void unpacker::skip_nonparsed_buffer(size_t size)
|
||||
{
|
||||
base::off += size;
|
||||
off_ += size;
|
||||
}
|
||||
|
||||
inline void unpacker::remove_nonparsed_buffer()
|
||||
{
|
||||
base::used = base::off;
|
||||
used_ = off_;
|
||||
}
|
||||
|
||||
namespace detail {
|
||||
|
||||
inline unpack_return
|
||||
unpack_imp(const char* data, size_t len, size_t* off,
|
||||
zone* result_zone, ::msgpack::object* result)
|
||||
{
|
||||
size_t noff = 0;
|
||||
if(off != NULL) { noff = *off; }
|
||||
|
||||
if(len <= noff) {
|
||||
// FIXME
|
||||
return UNPACK_CONTINUE;
|
||||
}
|
||||
|
||||
detail::template_context ctx;
|
||||
detail::template_init(ctx);
|
||||
|
||||
ctx.user.z = result_zone;
|
||||
ctx.user.referenced = false;
|
||||
|
||||
int e = detail::template_execute(ctx, data, len, &noff);
|
||||
if(e < 0) {
|
||||
return UNPACK_PARSE_ERROR;
|
||||
}
|
||||
|
||||
if(off != NULL) { *off = noff; }
|
||||
|
||||
if(e == 0) {
|
||||
return UNPACK_CONTINUE;
|
||||
}
|
||||
|
||||
*result = detail::template_data(ctx);
|
||||
|
||||
if(noff < len) {
|
||||
return UNPACK_EXTRA_BYTES;
|
||||
}
|
||||
|
||||
return UNPACK_SUCCESS;
|
||||
}
|
||||
|
||||
} // detail
|
||||
|
||||
inline void unpack(unpacked* result,
|
||||
const char* data, size_t len, size_t* offset)
|
||||
{
|
||||
msgpack::object obj;
|
||||
std::auto_ptr<msgpack::zone> z(new zone());
|
||||
std::unique_ptr<msgpack::zone> z(new zone());
|
||||
|
||||
unpack_return ret = detail::unpack_imp(
|
||||
data, len, offset, z.get(), &obj);
|
||||
|
||||
unpack_return ret = (unpack_return)msgpack_unpack(
|
||||
data, len, offset, z.get(),
|
||||
reinterpret_cast<msgpack_object*>(&obj));
|
||||
|
||||
switch(ret) {
|
||||
case UNPACK_SUCCESS:
|
||||
result->get() = obj;
|
||||
result->zone() = z;
|
||||
result->zone() = std::move(z);
|
||||
return;
|
||||
|
||||
case UNPACK_EXTRA_BYTES:
|
||||
result->get() = obj;
|
||||
result->zone() = z;
|
||||
result->zone() = std::move(z);
|
||||
return;
|
||||
|
||||
case UNPACK_CONTINUE:
|
||||
@ -338,8 +988,8 @@ inline void unpack(unpacked* result,
|
||||
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));
|
||||
return detail::unpack_imp(data, len, off,
|
||||
z, result);
|
||||
}
|
||||
|
||||
// obsolete
|
||||
@ -367,7 +1017,6 @@ inline object unpack(const char* data, size_t len, zone& z, size_t* off)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
} // namespace msgpack
|
||||
|
||||
#endif /* msgpack/unpack.hpp */
|
||||
|
37
src/msgpack/version.hpp.in
Normal file
37
src/msgpack/version.hpp.in
Normal file
@ -0,0 +1,37 @@
|
||||
/*
|
||||
* MessagePack for C++ version information
|
||||
*
|
||||
* Copyright (C) 2008-2013 FURUHASHI Sadayuki and Takatoshi Kondo
|
||||
*
|
||||
* 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_VERSION_HPP
|
||||
#define MSGPACK_VERSION_HPP
|
||||
|
||||
#define MSGPACK_VERSION "@VERSION@"
|
||||
#define MSGPACK_VERSION_MAJOR @VERSION_MAJOR@
|
||||
#define MSGPACK_VERSION_MINOR @VERSION_MINOR@
|
||||
|
||||
inline const char* msgpack_version(void) {
|
||||
return MSGPACK_VERSION;
|
||||
}
|
||||
|
||||
inline int msgpack_version_major(void) {
|
||||
return MSGPACK_VERSION_MAJOR;
|
||||
}
|
||||
|
||||
inline int msgpack_version_minor(void) {
|
||||
return MSGPACK_VERSION_MINOR;
|
||||
}
|
||||
|
||||
#endif /* msgpack/version.hpp */
|
@ -1,7 +1,7 @@
|
||||
//
|
||||
// MessagePack for C++ zero-copy buffer implementation
|
||||
//
|
||||
// Copyright (C) 2008-2009 FURUHASHI Sadayuki
|
||||
// Copyright (C) 2008-2013 FURUHASHI Sadayuki and KONDO Takatoshi
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
@ -15,34 +15,96 @@
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
//
|
||||
#ifndef MSGPACK_VREFBUFFER_HPP__
|
||||
#define MSGPACK_VREFBUFFER_HPP__
|
||||
#ifndef MSGPACK_VREFBUFFER_HPP
|
||||
#define MSGPACK_VREFBUFFER_HPP
|
||||
|
||||
#include "vrefbuffer.h"
|
||||
#include <stdexcept>
|
||||
|
||||
#ifndef MSGPACK_VREFBUFFER_REF_SIZE
|
||||
#define MSGPACK_VREFBUFFER_REF_SIZE 32
|
||||
#endif
|
||||
|
||||
#ifndef MSGPACK_VREFBUFFER_CHUNK_SIZE
|
||||
#define MSGPACK_VREFBUFFER_CHUNK_SIZE 8192
|
||||
#endif
|
||||
|
||||
#ifndef _WIN32
|
||||
#include <sys/uio.h>
|
||||
#else
|
||||
struct iovec {
|
||||
void *iov_base;
|
||||
size_t iov_len;
|
||||
};
|
||||
#endif
|
||||
|
||||
namespace msgpack {
|
||||
|
||||
namespace detail {
|
||||
|
||||
class vrefbuffer : public msgpack_vrefbuffer {
|
||||
|
||||
} // detail
|
||||
|
||||
class vrefbuffer {
|
||||
private:
|
||||
struct chunk {
|
||||
chunk* next;
|
||||
};
|
||||
struct inner_buffer {
|
||||
size_t free;
|
||||
char* ptr;
|
||||
chunk* head;
|
||||
};
|
||||
public:
|
||||
vrefbuffer(size_t ref_size = MSGPACK_VREFBUFFER_REF_SIZE,
|
||||
size_t chunk_size = MSGPACK_VREFBUFFER_CHUNK_SIZE)
|
||||
:ref_size_(ref_size), chunk_size_(chunk_size)
|
||||
{
|
||||
if (!msgpack_vrefbuffer_init(this, ref_size, chunk_size)) {
|
||||
size_t nfirst = (sizeof(iovec) < 72/2) ?
|
||||
72 / sizeof(iovec) : 8;
|
||||
|
||||
iovec* array = (iovec*)::malloc(
|
||||
sizeof(iovec) * nfirst);
|
||||
if(!array) {
|
||||
throw std::bad_alloc();
|
||||
}
|
||||
|
||||
tail_ = array;
|
||||
end_ = array + nfirst;
|
||||
array_ = array;
|
||||
|
||||
chunk* c = (chunk*)::malloc(sizeof(chunk) + chunk_size);
|
||||
if(!c) {
|
||||
::free(array);
|
||||
throw std::bad_alloc();
|
||||
}
|
||||
inner_buffer* const ib = &inner_buffer_;
|
||||
|
||||
ib->free = chunk_size;
|
||||
ib->ptr = ((char*)c) + sizeof(chunk);
|
||||
ib->head = c;
|
||||
c->next = nullptr;
|
||||
|
||||
}
|
||||
|
||||
~vrefbuffer()
|
||||
{
|
||||
msgpack_vrefbuffer_destroy(this);
|
||||
chunk* c = inner_buffer_.head;
|
||||
while(true) {
|
||||
chunk* n = c->next;
|
||||
::free(c);
|
||||
if(n != NULL) {
|
||||
c = n;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
::free(array_);
|
||||
}
|
||||
|
||||
public:
|
||||
void write(const char* buf, size_t len)
|
||||
{
|
||||
if(len < base::ref_size) {
|
||||
if(len < ref_size_) {
|
||||
append_copy(buf, len);
|
||||
} else {
|
||||
append_ref(buf, len);
|
||||
@ -51,45 +113,162 @@ public:
|
||||
|
||||
void append_ref(const char* buf, size_t len)
|
||||
{
|
||||
if(msgpack_vrefbuffer_append_ref(this, buf, len) < 0) {
|
||||
throw std::bad_alloc();
|
||||
if(tail_ == end_) {
|
||||
const size_t nused = tail_ - array_;
|
||||
const size_t nnext = nused * 2;
|
||||
|
||||
iovec* nvec = (iovec*)::realloc(
|
||||
array_, sizeof(iovec)*nnext);
|
||||
if(!nvec) {
|
||||
throw std::bad_alloc();
|
||||
}
|
||||
|
||||
array_ = nvec;
|
||||
end_ = nvec + nnext;
|
||||
tail_ = nvec + nused;
|
||||
}
|
||||
|
||||
tail_->iov_base = (char*)buf;
|
||||
tail_->iov_len = len;
|
||||
++tail_;
|
||||
}
|
||||
|
||||
void append_copy(const char* buf, size_t len)
|
||||
{
|
||||
if(msgpack_vrefbuffer_append_copy(this, buf, len) < 0) {
|
||||
throw std::bad_alloc();
|
||||
inner_buffer* const ib = &inner_buffer_;
|
||||
|
||||
if(ib->free < len) {
|
||||
size_t sz = chunk_size_;
|
||||
if(sz < len) {
|
||||
sz = len;
|
||||
}
|
||||
|
||||
chunk* c = (chunk*)::malloc(sizeof(chunk) + sz);
|
||||
if(!c) {
|
||||
throw std::bad_alloc();
|
||||
}
|
||||
|
||||
c->next = ib->head;
|
||||
ib->head = c;
|
||||
ib->free = sz;
|
||||
ib->ptr = ((char*)c) + sizeof(chunk);
|
||||
}
|
||||
|
||||
char* m = ib->ptr;
|
||||
::memcpy(m, buf, len);
|
||||
ib->free -= len;
|
||||
ib->ptr += len;
|
||||
|
||||
if(tail_ != array_ && m ==
|
||||
(const char*)((tail_ - 1)->iov_base) + (tail_ - 1)->iov_len) {
|
||||
(tail_ - 1)->iov_len += len;
|
||||
return;
|
||||
} else {
|
||||
append_ref( m, len);
|
||||
}
|
||||
}
|
||||
|
||||
const struct iovec* vector() const
|
||||
{
|
||||
return msgpack_vrefbuffer_vec(this);
|
||||
return array_;
|
||||
}
|
||||
|
||||
size_t vector_size() const
|
||||
{
|
||||
return msgpack_vrefbuffer_veclen(this);
|
||||
return tail_ - array_;
|
||||
}
|
||||
|
||||
void migrate(vrefbuffer* to)
|
||||
{
|
||||
if(msgpack_vrefbuffer_migrate(this, to) < 0) {
|
||||
size_t sz = chunk_size_;
|
||||
|
||||
chunk* empty = (chunk*)::malloc(sizeof(chunk) + sz);
|
||||
if(!empty) {
|
||||
throw std::bad_alloc();
|
||||
}
|
||||
}
|
||||
|
||||
empty->next = nullptr;
|
||||
|
||||
const size_t nused = tail_ - array_;
|
||||
if(to->tail_ + nused < end_) {
|
||||
const size_t tosize = to->tail_ - to->array_;
|
||||
const size_t reqsize = nused + tosize;
|
||||
size_t nnext = (to->end_ - to->array_) * 2;
|
||||
while(nnext < reqsize) {
|
||||
nnext *= 2;
|
||||
}
|
||||
|
||||
iovec* nvec = (iovec*)::realloc(
|
||||
to->array_, sizeof(iovec)*nnext);
|
||||
if(!nvec) {
|
||||
::free(empty);
|
||||
throw std::bad_alloc();
|
||||
}
|
||||
|
||||
to->array_ = nvec;
|
||||
to->end_ = nvec + nnext;
|
||||
to->tail_ = nvec + tosize;
|
||||
}
|
||||
|
||||
::memcpy(to->tail_, array_, sizeof(iovec)*nused);
|
||||
|
||||
to->tail_ += nused;
|
||||
tail_ = array_;
|
||||
|
||||
|
||||
inner_buffer* const ib = &inner_buffer_;
|
||||
inner_buffer* const toib = &to->inner_buffer_;
|
||||
|
||||
chunk* last = ib->head;
|
||||
while(last->next) {
|
||||
last = last->next;
|
||||
}
|
||||
last->next = toib->head;
|
||||
toib->head = ib->head;
|
||||
|
||||
if(toib->free < ib->free) {
|
||||
toib->free = ib->free;
|
||||
toib->ptr = ib->ptr;
|
||||
}
|
||||
|
||||
ib->head = empty;
|
||||
ib->free = sz;
|
||||
ib->ptr = ((char*)empty) + sizeof(chunk);
|
||||
|
||||
}
|
||||
|
||||
void clear()
|
||||
{
|
||||
msgpack_vrefbuffer_clear(this);
|
||||
}
|
||||
chunk* c = inner_buffer_.head->next;
|
||||
chunk* n;
|
||||
while(c) {
|
||||
n = c->next;
|
||||
::free(c);
|
||||
c = n;
|
||||
}
|
||||
|
||||
private:
|
||||
typedef msgpack_vrefbuffer base;
|
||||
inner_buffer* const ib = &inner_buffer_;
|
||||
c = ib->head;
|
||||
c->next = nullptr;
|
||||
ib->free = chunk_size_;
|
||||
ib->ptr = ((char*)c) + sizeof(chunk);
|
||||
|
||||
tail_ = array_;
|
||||
}
|
||||
|
||||
private:
|
||||
vrefbuffer(const vrefbuffer&);
|
||||
|
||||
private:
|
||||
iovec* tail_;
|
||||
iovec* end_;
|
||||
iovec* array_;
|
||||
|
||||
size_t ref_size_;
|
||||
size_t chunk_size_;
|
||||
|
||||
inner_buffer inner_buffer_;
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
//
|
||||
// MessagePack for C++ deflate buffer implementation
|
||||
//
|
||||
// Copyright (C) 2010 FURUHASHI Sadayuki
|
||||
// Copyright (C) 2010-2013 FURUHASHI Sadayuki and KONDO Takatoshi
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
@ -15,84 +15,144 @@
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
//
|
||||
#ifndef MSGPACK_ZBUFFER_HPP__
|
||||
#define MSGPACK_ZBUFFER_HPP__
|
||||
#ifndef MSGPACK_ZBUFFER_HPP
|
||||
#define MSGPACK_ZBUFFER_HPP
|
||||
|
||||
#include "zbuffer.h"
|
||||
#include <stdexcept>
|
||||
#include <zlib.h>
|
||||
|
||||
#ifndef MSGPACK_ZBUFFER_RESERVE_SIZE
|
||||
#define MSGPACK_ZBUFFER_RESERVE_SIZE 512
|
||||
#endif
|
||||
|
||||
#ifndef MSGPACK_ZBUFFER_INIT_SIZE
|
||||
#define MSGPACK_ZBUFFER_INIT_SIZE 8192
|
||||
#endif
|
||||
|
||||
namespace msgpack {
|
||||
|
||||
|
||||
class zbuffer : public msgpack_zbuffer {
|
||||
class zbuffer {
|
||||
public:
|
||||
zbuffer(int level = Z_DEFAULT_COMPRESSION,
|
||||
size_t init_size = MSGPACK_ZBUFFER_INIT_SIZE)
|
||||
: data_(nullptr), init_size_(init_size)
|
||||
{
|
||||
if (!msgpack_zbuffer_init(this, level, init_size)) {
|
||||
stream_.zalloc = Z_NULL;
|
||||
stream_.zfree = Z_NULL;
|
||||
stream_.opaque = Z_NULL;
|
||||
stream_.next_out = Z_NULL;
|
||||
stream_.avail_out = 0;
|
||||
if(deflateInit(&stream_, level) != Z_OK) {
|
||||
throw std::bad_alloc();
|
||||
}
|
||||
}
|
||||
|
||||
~zbuffer()
|
||||
{
|
||||
msgpack_zbuffer_destroy(this);
|
||||
deflateEnd(&stream_);
|
||||
::free(data_);
|
||||
}
|
||||
|
||||
public:
|
||||
void write(const char* buf, size_t len)
|
||||
{
|
||||
if(msgpack_zbuffer_write(this, buf, len) < 0) {
|
||||
throw std::bad_alloc();
|
||||
}
|
||||
stream_.next_in = (Bytef*)buf;
|
||||
stream_.avail_in = len;
|
||||
|
||||
do {
|
||||
if(stream_.avail_out < MSGPACK_ZBUFFER_RESERVE_SIZE) {
|
||||
if(!expand()) {
|
||||
throw std::bad_alloc();
|
||||
}
|
||||
}
|
||||
|
||||
if(deflate(&stream_, Z_NO_FLUSH) != Z_OK) {
|
||||
throw std::bad_alloc();
|
||||
}
|
||||
} while(stream_.avail_in > 0);
|
||||
}
|
||||
|
||||
char* flush()
|
||||
{
|
||||
char* buf = msgpack_zbuffer_flush(this);
|
||||
if(!buf) {
|
||||
throw std::bad_alloc();
|
||||
while(true) {
|
||||
switch(deflate(&stream_, Z_FINISH)) {
|
||||
case Z_STREAM_END:
|
||||
return data_;
|
||||
case Z_OK:
|
||||
if(!expand()) {
|
||||
throw std::bad_alloc();
|
||||
}
|
||||
break;
|
||||
default:
|
||||
throw std::bad_alloc();
|
||||
}
|
||||
}
|
||||
return buf;
|
||||
}
|
||||
|
||||
char* data()
|
||||
{
|
||||
return base::data;
|
||||
return data_;
|
||||
}
|
||||
|
||||
const char* data() const
|
||||
{
|
||||
return base::data;
|
||||
return data_;
|
||||
}
|
||||
|
||||
size_t size() const
|
||||
{
|
||||
return msgpack_zbuffer_size(this);
|
||||
return (char*)stream_.next_out - data_;
|
||||
}
|
||||
|
||||
void reset()
|
||||
{
|
||||
if(!msgpack_zbuffer_reset(this)) {
|
||||
if(deflateReset(&stream_) != Z_OK) {
|
||||
throw std::bad_alloc();
|
||||
}
|
||||
reset_buffer();
|
||||
}
|
||||
|
||||
void reset_buffer()
|
||||
{
|
||||
msgpack_zbuffer_reset_buffer(this);
|
||||
stream_.avail_out += (char*)stream_.next_out - data_;
|
||||
stream_.next_out = (Bytef*)data_;
|
||||
}
|
||||
|
||||
char* release_buffer()
|
||||
{
|
||||
return msgpack_zbuffer_release_buffer(this);
|
||||
char* tmp = data_;
|
||||
data_ = NULL;
|
||||
stream_.next_out = NULL;
|
||||
stream_.avail_out = 0;
|
||||
return tmp;
|
||||
}
|
||||
|
||||
private:
|
||||
typedef msgpack_zbuffer base;
|
||||
bool expand()
|
||||
{
|
||||
size_t used = (char*)stream_.next_out - data_;
|
||||
size_t csize = used + stream_.avail_out;
|
||||
size_t nsize = (csize == 0) ? init_size_ : csize * 2;
|
||||
|
||||
char* tmp = (char*)::realloc(data_, nsize);
|
||||
if(tmp == NULL) {
|
||||
return false;
|
||||
}
|
||||
|
||||
data_ = tmp;
|
||||
stream_.next_out = (Bytef*)(tmp + used);
|
||||
stream_.avail_out = nsize - used;
|
||||
|
||||
return true;
|
||||
}
|
||||
private:
|
||||
zbuffer(const zbuffer&);
|
||||
|
||||
private:
|
||||
z_stream stream_;
|
||||
char* data_;
|
||||
size_t init_size_;
|
||||
};
|
||||
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
#include <msgpack.hpp>
|
||||
#include <msgpack.h>
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
TEST(fixint, size)
|
||||
|
@ -170,10 +170,10 @@ TEST(MSGPACK, simple_buffer_float)
|
||||
float val2;
|
||||
obj.convert(&val2);
|
||||
|
||||
if (isnan(val1))
|
||||
EXPECT_TRUE(isnan(val2));
|
||||
else if (isinf(val1))
|
||||
EXPECT_TRUE(isinf(val2));
|
||||
if (std::isnan(val1))
|
||||
EXPECT_TRUE(std::isnan(val2));
|
||||
else if (std::isinf(val1))
|
||||
EXPECT_TRUE(std::isinf(val2));
|
||||
else
|
||||
EXPECT_TRUE(fabs(val2 - val1) <= kEPS);
|
||||
}
|
||||
@ -260,10 +260,10 @@ TEST(MSGPACK, simple_buffer_double)
|
||||
double val2;
|
||||
obj.convert(&val2);
|
||||
|
||||
if (isnan(val1))
|
||||
EXPECT_TRUE(isnan(val2));
|
||||
else if (isinf(val1))
|
||||
EXPECT_TRUE(isinf(val2));
|
||||
if (std::isnan(val1))
|
||||
EXPECT_TRUE(std::isnan(val2));
|
||||
else if (std::isinf(val1))
|
||||
EXPECT_TRUE(std::isinf(val2));
|
||||
else
|
||||
EXPECT_TRUE(fabs(val2 - val1) <= kEPS);
|
||||
}
|
||||
@ -901,11 +901,11 @@ public:
|
||||
msgpack::type::tuple<bool, msgpack::object> tuple;
|
||||
o.convert(&tuple);
|
||||
|
||||
is_double = tuple.get<0>();
|
||||
is_double = get<0>(tuple);
|
||||
if (is_double)
|
||||
tuple.get<1>().convert(&value.f);
|
||||
get<1>(tuple).convert(&value.f);
|
||||
else
|
||||
tuple.get<1>().convert(&value.i);
|
||||
get<1>(tuple).convert(&value.i);
|
||||
}
|
||||
};
|
||||
|
||||
@ -1097,7 +1097,7 @@ TEST(MSGPACK, vrefbuffer_int64)
|
||||
obj.convert(&val); \
|
||||
EXPECT_EQ(*it, val); \
|
||||
++it; \
|
||||
msgpack_zone_free(life); \
|
||||
msgpack::zone::destroy(life); \
|
||||
} \
|
||||
p += sz; \
|
||||
} \
|
||||
|
@ -69,7 +69,7 @@ public:
|
||||
|
||||
msgpack::unpacked result;
|
||||
while(pac.next(&result)) {
|
||||
on_message(result.get(), result.zone());
|
||||
on_message(result.get(), std::move(result.zone()));
|
||||
}
|
||||
|
||||
if(pac.message_size() > 10*1024*1024) {
|
||||
@ -78,7 +78,7 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
void on_message(msgpack::object obj, std::auto_ptr<msgpack::zone> z)
|
||||
void on_message(msgpack::object obj, std::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::auto_ptr<msgpack::zone> z(pac.release_zone());
|
||||
std::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::auto_ptr<msgpack::zone> z(pac.release_zone());
|
||||
std::unique_ptr<msgpack::zone> z(pac.release_zone());
|
||||
msgpack::object obj = pac.data();
|
||||
pac.reset();
|
||||
on_message(obj, z);
|
||||
on_message(obj, std::move(z));
|
||||
}
|
||||
|
||||
if(pac.message_size() > 10*1024*1024) {
|
||||
@ -186,7 +186,7 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
void on_message(msgpack::object obj, std::auto_ptr<msgpack::zone> z)
|
||||
void on_message(msgpack::object obj, std::unique_ptr<msgpack::zone> z)
|
||||
{
|
||||
EXPECT_EQ(expect, obj.as<int>());
|
||||
}
|
||||
|
@ -60,11 +60,11 @@ TEST(zone, push_finalizer)
|
||||
}
|
||||
|
||||
|
||||
TEST(zone, push_finalizer_auto_ptr)
|
||||
TEST(zone, push_finalizer_unique_ptr)
|
||||
{
|
||||
msgpack::zone z;
|
||||
std::auto_ptr<myclass> am(new myclass());
|
||||
z.push_finalizer(am);
|
||||
std::unique_ptr<myclass> am(new myclass());
|
||||
z.push_finalizer(std::move(am));
|
||||
}
|
||||
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user