mirror of
https://github.com/EQEmu/Server.git
synced 2026-02-04 17:33:51 +00:00
Event loop basics + libuv
This commit is contained in:
parent
7c40bcff53
commit
9597101f08
@ -323,7 +323,8 @@ IF(EQEMU_BUILD_LUA)
|
||||
SET(BOOST_ROOT "${CMAKE_CURRENT_SOURCE_DIR}/dependencies/boost")
|
||||
|
||||
FIND_PACKAGE(Boost REQUIRED)
|
||||
INCLUDE_DIRECTORIES(SYSTEM "${LUA_INCLUDE_DIR}" "${Boost_INCLUDE_DIRS}" "luabind")
|
||||
INCLUDE_DIRECTORIES(SYSTEM "${LUA_INCLUDE_DIR}" "${Boost_INCLUDE_DIRS}")
|
||||
INCLUDE_DIRECTORIES(SYSTEM "${CMAKE_CURRENT_SOURCE_DIR}/libs/luabind")
|
||||
|
||||
OPTION(EQEMU_SANITIZE_LUA_LIBS "Sanitize Lua Libraries (Remove OS and IO standard libraries from being able to run)." ON)
|
||||
IF(EQEMU_SANITIZE_LUA_LIBS)
|
||||
@ -331,14 +332,18 @@ IF(EQEMU_BUILD_LUA)
|
||||
ENDIF(EQEMU_SANITIZE_LUA_LIBS)
|
||||
ENDIF(EQEMU_BUILD_LUA)
|
||||
|
||||
INCLUDE_DIRECTORIES(SYSTEM "${ZLIB_INCLUDE_DIRS}" "${MySQL_INCLUDE_DIR}" "${CMAKE_CURRENT_SOURCE_DIR}/common/glm")
|
||||
|
||||
IF(EQEMU_BUILD_LUA)
|
||||
ADD_SUBDIRECTORY(luabind)
|
||||
ENDIF(EQEMU_BUILD_LUA)
|
||||
INCLUDE_DIRECTORIES(SYSTEM "${ZLIB_INCLUDE_DIRS}")
|
||||
INCLUDE_DIRECTORIES(SYSTEM "${MySQL_INCLUDE_DIR}")
|
||||
INCLUDE_DIRECTORIES(SYSTEM "${CMAKE_CURRENT_SOURCE_DIR}/common/glm")
|
||||
INCLUDE_DIRECTORIES(SYSTEM "${CMAKE_CURRENT_SOURCE_DIR}/common")
|
||||
INCLUDE_DIRECTORIES(SYSTEM "${CMAKE_CURRENT_SOURCE_DIR}/libs/cereal")
|
||||
INCLUDE_DIRECTORIES(SYSTEM "${CMAKE_CURRENT_SOURCE_DIR}/libs/libuv/include" )
|
||||
INCLUDE_DIRECTORIES(SYSTEM "${CMAKE_CURRENT_SOURCE_DIR}/libs/libuv/src")
|
||||
|
||||
IF(EQEMU_BUILD_SERVER OR EQEMU_BUILD_LOGIN OR EQEMU_BUILD_TESTS)
|
||||
ADD_SUBDIRECTORY(common)
|
||||
ADD_SUBDIRECTORY(libs)
|
||||
ENDIF(EQEMU_BUILD_SERVER OR EQEMU_BUILD_LOGIN OR EQEMU_BUILD_TESTS)
|
||||
IF(EQEMU_BUILD_SERVER)
|
||||
ADD_SUBDIRECTORY(shared_memory)
|
||||
|
||||
@ -9,7 +9,7 @@ SET(export_headers
|
||||
|
||||
ADD_EXECUTABLE(export_client_files ${export_sources} ${export_headers})
|
||||
|
||||
INSTALL(TARGETS export_client_files RUNTIME DESTINATION ${CMAKE_INSTALL_PREFIX})
|
||||
INSTALL(TARGETS export_client_files RUNTIME DESTINATION ${CMAKE_INSTALL_PREFIX}/bin)
|
||||
|
||||
TARGET_LINK_LIBRARIES(export_client_files common debug ${MySQL_LIBRARY_DEBUG} optimized ${MySQL_LIBRARY_RELEASE} ${ZLIB_LIBRARY})
|
||||
|
||||
@ -30,7 +30,6 @@ IF(UNIX)
|
||||
TARGET_LINK_LIBRARIES(export_client_files "rt")
|
||||
ENDIF(NOT DARWIN)
|
||||
TARGET_LINK_LIBRARIES(export_client_files "pthread")
|
||||
ADD_DEFINITIONS(-fPIC)
|
||||
ENDIF(UNIX)
|
||||
|
||||
SET(EXECUTABLE_OUTPUT_PATH ${PROJECT_BINARY_DIR}/bin)
|
||||
|
||||
@ -9,7 +9,7 @@ SET(import_headers
|
||||
|
||||
ADD_EXECUTABLE(import_client_files ${import_sources} ${import_headers})
|
||||
|
||||
INSTALL(TARGETS import_client_files RUNTIME DESTINATION ${CMAKE_INSTALL_PREFIX})
|
||||
INSTALL(TARGETS import_client_files RUNTIME DESTINATION ${CMAKE_INSTALL_PREFIX}/bin)
|
||||
|
||||
TARGET_LINK_LIBRARIES(import_client_files common debug ${MySQL_LIBRARY_DEBUG} optimized ${MySQL_LIBRARY_RELEASE} ${ZLIB_LIBRARY})
|
||||
|
||||
@ -30,7 +30,6 @@ IF(UNIX)
|
||||
TARGET_LINK_LIBRARIES(import_client_files "rt")
|
||||
ENDIF(NOT DARWIN)
|
||||
TARGET_LINK_LIBRARIES(import_client_files "pthread")
|
||||
ADD_DEFINITIONS(-fPIC)
|
||||
ENDIF(UNIX)
|
||||
|
||||
SET(EXECUTABLE_OUTPUT_PATH ${PROJECT_BINARY_DIR}/bin)
|
||||
|
||||
@ -210,6 +210,9 @@ SET(common_headers
|
||||
worldconn.h
|
||||
xml_parser.h
|
||||
zone_numbers.h
|
||||
event/background_task.h
|
||||
event/event_loop.h
|
||||
event/timer.h
|
||||
patches/patches.h
|
||||
patches/sod.h
|
||||
# patches/sod_itemfields.h
|
||||
@ -263,6 +266,13 @@ SET(common_headers
|
||||
tinyxml/tinyxml.h
|
||||
)
|
||||
|
||||
SOURCE_GROUP(Event FILES
|
||||
event/background_task.h
|
||||
event/event_loop.h
|
||||
event/timer.h
|
||||
)
|
||||
|
||||
|
||||
SOURCE_GROUP(Patches FILES
|
||||
patches/patches.h
|
||||
patches/sod.h
|
||||
@ -360,7 +370,6 @@ INCLUDE_DIRECTORIES(Patches SocketLib StackWalker TinyXML)
|
||||
ADD_LIBRARY(common ${common_sources} ${common_headers})
|
||||
|
||||
IF(UNIX)
|
||||
ADD_DEFINITIONS(-fPIC)
|
||||
SET_SOURCE_FILES_PROPERTIES("SocketLib/Mime.cpp" PROPERTY COMPILE_FLAGS -Wno-unused-result)
|
||||
SET_SOURCE_FILES_PROPERTIES("patches/sod.cpp" "patches/sof.cpp" "patches/rof.cpp" "patches/rof2.cpp" "patches/uf.cpp" PROPERTIES COMPILE_FLAGS -O0)
|
||||
ENDIF(UNIX)
|
||||
|
||||
39
common/event/background_task.h
Normal file
39
common/event/background_task.h
Normal file
@ -0,0 +1,39 @@
|
||||
#pragma once
|
||||
#include <functional>
|
||||
#include "event_loop.h"
|
||||
|
||||
namespace EQ {
|
||||
class BackgroundTask
|
||||
{
|
||||
public:
|
||||
typedef std::function<void(void)> BackgroundTaskFunction;
|
||||
struct BackgroundTaskBaton
|
||||
{
|
||||
BackgroundTaskFunction fn;
|
||||
BackgroundTaskFunction on_finish;
|
||||
};
|
||||
|
||||
BackgroundTask(BackgroundTaskFunction fn, BackgroundTaskFunction on_finish) {
|
||||
uv_work_t *m_work = new uv_work_t;
|
||||
memset(m_work, 0, sizeof(uv_work_t));
|
||||
BackgroundTaskBaton *baton = new BackgroundTaskBaton();
|
||||
baton->fn = fn;
|
||||
baton->on_finish = on_finish;
|
||||
|
||||
m_work->data = baton;
|
||||
uv_queue_work(EventLoop::Get().Handle(), m_work, [](uv_work_t* req) {
|
||||
BackgroundTaskBaton *baton = (BackgroundTaskBaton*)req->data;
|
||||
baton->fn();
|
||||
}, [](uv_work_t* req, int status) {
|
||||
BackgroundTaskBaton *baton = (BackgroundTaskBaton*)req->data;
|
||||
baton->on_finish();
|
||||
delete baton;
|
||||
delete req;
|
||||
});
|
||||
}
|
||||
|
||||
~BackgroundTask() {
|
||||
|
||||
}
|
||||
};
|
||||
}
|
||||
36
common/event/event_loop.h
Normal file
36
common/event/event_loop.h
Normal file
@ -0,0 +1,36 @@
|
||||
#pragma once
|
||||
#include <functional>
|
||||
#include <uv.h>
|
||||
|
||||
namespace EQ
|
||||
{
|
||||
class EventLoop
|
||||
{
|
||||
public:
|
||||
static EventLoop &Get() {
|
||||
static EventLoop inst;
|
||||
return inst;
|
||||
}
|
||||
|
||||
~EventLoop() {
|
||||
uv_loop_close(&m_loop);
|
||||
}
|
||||
|
||||
void Process() {
|
||||
uv_run(&m_loop, UV_RUN_NOWAIT);
|
||||
}
|
||||
|
||||
uv_loop_t* Handle() { return &m_loop; }
|
||||
|
||||
private:
|
||||
EventLoop() {
|
||||
memset(&m_loop, 0, sizeof(uv_loop_t));
|
||||
uv_loop_init(&m_loop);
|
||||
}
|
||||
|
||||
EventLoop(const EventLoop&);
|
||||
EventLoop& operator=(const EventLoop&);
|
||||
|
||||
uv_loop_t m_loop;
|
||||
};
|
||||
}
|
||||
63
common/event/timer.h
Normal file
63
common/event/timer.h
Normal file
@ -0,0 +1,63 @@
|
||||
#pragma once
|
||||
#include <functional>
|
||||
#include "event_loop.h"
|
||||
|
||||
namespace EQ {
|
||||
class Timer
|
||||
{
|
||||
public:
|
||||
Timer(uint64_t duration_ms, bool repeats, std::function<void(void)> cb)
|
||||
{
|
||||
memset(&m_timer, 0, sizeof(uv_timer_t));
|
||||
m_cb = cb;
|
||||
m_duration_ms = duration_ms;
|
||||
m_repeats = repeats;
|
||||
m_attached = nullptr;
|
||||
Attach(EventLoop::Get().Handle());
|
||||
}
|
||||
|
||||
~Timer()
|
||||
{
|
||||
Detach();
|
||||
}
|
||||
private:
|
||||
void Execute() {
|
||||
m_cb();
|
||||
}
|
||||
|
||||
virtual void Attach(uv_loop_t *loop) {
|
||||
if (!m_attached) {
|
||||
uv_timer_init(loop, &m_timer);
|
||||
m_timer.data = this;
|
||||
|
||||
if (m_repeats) {
|
||||
uv_timer_start(&m_timer, [](uv_timer_t *handle) {
|
||||
Timer *t = (Timer*)handle->data;
|
||||
t->Execute();
|
||||
}, m_duration_ms, m_duration_ms);
|
||||
}
|
||||
else {
|
||||
uv_timer_start(&m_timer, [](uv_timer_t *handle) {
|
||||
Timer *t = (Timer*)handle->data;
|
||||
t->Execute();
|
||||
}, m_duration_ms, 0);
|
||||
}
|
||||
|
||||
m_attached = loop;
|
||||
}
|
||||
}
|
||||
|
||||
virtual void Detach() {
|
||||
if (m_attached) {
|
||||
uv_timer_stop(&m_timer);
|
||||
m_attached = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
uv_timer_t m_timer;
|
||||
std::function<void(void)> m_cb;
|
||||
uint64_t m_duration_ms;
|
||||
bool m_repeats;
|
||||
uv_loop_t *m_attached;
|
||||
};
|
||||
}
|
||||
@ -13,7 +13,7 @@ SET(eqlaunch_headers
|
||||
|
||||
ADD_EXECUTABLE(eqlaunch ${eqlaunch_sources} ${eqlaunch_headers})
|
||||
|
||||
INSTALL(TARGETS eqlaunch RUNTIME DESTINATION ${CMAKE_INSTALL_PREFIX})
|
||||
INSTALL(TARGETS eqlaunch RUNTIME DESTINATION ${CMAKE_INSTALL_PREFIX}/bin)
|
||||
|
||||
TARGET_LINK_LIBRARIES(eqlaunch common debug ${MySQL_LIBRARY_DEBUG} optimized ${MySQL_LIBRARY_RELEASE} ${ZLIB_LIBRARY})
|
||||
|
||||
@ -34,7 +34,6 @@ IF(UNIX)
|
||||
TARGET_LINK_LIBRARIES(eqlaunch "rt")
|
||||
ENDIF(NOT DARWIN)
|
||||
TARGET_LINK_LIBRARIES(eqlaunch "pthread")
|
||||
ADD_DEFINITIONS(-fPIC)
|
||||
ENDIF(UNIX)
|
||||
|
||||
SET(EXECUTABLE_OUTPUT_PATH ${PROJECT_BINARY_DIR}/bin)
|
||||
|
||||
5
libs/CMakeLists.txt
Normal file
5
libs/CMakeLists.txt
Normal file
@ -0,0 +1,5 @@
|
||||
IF(EQEMU_BUILD_LUA)
|
||||
ADD_SUBDIRECTORY(luabind)
|
||||
ENDIF(EQEMU_BUILD_LUA)
|
||||
|
||||
ADD_SUBDIRECTORY(libuv)
|
||||
427
libs/cereal/cereal/access.hpp
Normal file
427
libs/cereal/cereal/access.hpp
Normal file
@ -0,0 +1,427 @@
|
||||
/*! \file access.hpp
|
||||
\brief Access control, default construction, and serialization disambiguation */
|
||||
/*
|
||||
Copyright (c) 2014, Randolph Voorhies, Shane Grant
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of cereal nor the
|
||||
names of its contributors may be used to endorse or promote products
|
||||
derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL RANDOLPH VOORHIES OR SHANE GRANT BE LIABLE FOR ANY
|
||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
#ifndef CEREAL_ACCESS_HPP_
|
||||
#define CEREAL_ACCESS_HPP_
|
||||
|
||||
#include <type_traits>
|
||||
#include <iostream>
|
||||
#include <cstdint>
|
||||
|
||||
#include <cereal/macros.hpp>
|
||||
#include <cereal/details/helpers.hpp>
|
||||
|
||||
namespace cereal
|
||||
{
|
||||
// ######################################################################
|
||||
//! A class that allows cereal to load smart pointers to types that have no default constructor
|
||||
/*! If your class does not have a default constructor, cereal will not be able
|
||||
to load any smart pointers to it unless you overload LoadAndConstruct
|
||||
for your class, and provide an appropriate load_and_construct method. You can also
|
||||
choose to define a member static function instead of specializing this class.
|
||||
|
||||
The specialization of LoadAndConstruct must be placed within the cereal namespace:
|
||||
|
||||
@code{.cpp}
|
||||
struct MyType
|
||||
{
|
||||
MyType( int x ); // note: no default ctor
|
||||
int myX;
|
||||
|
||||
// Define a serialize or load/save pair as you normally would
|
||||
template <class Archive>
|
||||
void serialize( Archive & ar )
|
||||
{
|
||||
ar( myX );
|
||||
}
|
||||
};
|
||||
|
||||
// Provide a specialization for LoadAndConstruct for your type
|
||||
namespace cereal
|
||||
{
|
||||
template <> struct LoadAndConstruct<MyType>
|
||||
{
|
||||
// load_and_construct will be passed the archive that you will be loading
|
||||
// from as well as a construct object which you can use as if it were the
|
||||
// constructor for your type. cereal will handle all memory management for you.
|
||||
template <class Archive>
|
||||
static void load_and_construct( Archive & ar, cereal::construct<MyType> & construct )
|
||||
{
|
||||
int x;
|
||||
ar( x );
|
||||
construct( x );
|
||||
}
|
||||
};
|
||||
} // end namespace cereal
|
||||
@endcode
|
||||
|
||||
Please note that just as in using external serialization functions, you cannot get
|
||||
access to non-public members of your class by befriending cereal::access. If you
|
||||
have the ability to modify the class you wish to serialize, it is recommended that you
|
||||
use member serialize functions and a static member load_and_construct function.
|
||||
|
||||
@tparam T The type to specialize for
|
||||
@ingroup Access */
|
||||
template <class T>
|
||||
struct LoadAndConstruct
|
||||
{
|
||||
//! Called by cereal if no default constructor exists to load and construct data simultaneously
|
||||
/*! Overloads of this should return a pointer to T and expect an archive as a parameter */
|
||||
static std::false_type load_and_construct(...)
|
||||
{ return std::false_type(); }
|
||||
};
|
||||
|
||||
// forward decl for construct
|
||||
//! @cond PRIVATE_NEVERDEFINED
|
||||
namespace memory_detail{ template <class Ar, class T> struct LoadAndConstructLoadWrapper; }
|
||||
//! @endcond
|
||||
|
||||
//! Used to construct types with no default constructor
|
||||
/*! When serializing a type that has no default constructor, cereal
|
||||
will attempt to call either the class static function load_and_construct
|
||||
or the appropriate template specialization of LoadAndConstruct. cereal
|
||||
will pass that function a reference to the archive as well as a reference
|
||||
to a construct object which should be used to perform the allocation once
|
||||
data has been appropriately loaded.
|
||||
|
||||
@code{.cpp}
|
||||
struct MyType
|
||||
{
|
||||
// note the lack of default constructor
|
||||
MyType( int xx, int yy );
|
||||
|
||||
int x, y;
|
||||
double notInConstructor;
|
||||
|
||||
template <class Archive>
|
||||
void serialize( Archive & ar )
|
||||
{
|
||||
ar( x, y );
|
||||
ar( notInConstructor );
|
||||
}
|
||||
|
||||
template <class Archive>
|
||||
static void load_and_construct( Archive & ar, cereal::construct<MyType> & construct )
|
||||
{
|
||||
int x, y;
|
||||
ar( x, y );
|
||||
|
||||
// use construct object to initialize with loaded data
|
||||
construct( x, y );
|
||||
|
||||
// access to member variables and functions via -> operator
|
||||
ar( construct->notInConstructor );
|
||||
|
||||
// could also do the above section by:
|
||||
double z;
|
||||
ar( z );
|
||||
construct->notInConstructor = z;
|
||||
}
|
||||
};
|
||||
@endcode
|
||||
|
||||
@tparam T The class type being serialized
|
||||
*/
|
||||
template <class T>
|
||||
class construct
|
||||
{
|
||||
public:
|
||||
//! Construct and initialize the type T with the given arguments
|
||||
/*! This will forward all arguments to the underlying type T,
|
||||
calling an appropriate constructor.
|
||||
|
||||
Calling this function more than once will result in an exception
|
||||
being thrown.
|
||||
|
||||
@param args The arguments to the constructor for T
|
||||
@throw Exception If called more than once */
|
||||
template <class ... Args>
|
||||
void operator()( Args && ... args );
|
||||
// implementation deferred due to reliance on cereal::access
|
||||
|
||||
//! Get a reference to the initialized underlying object
|
||||
/*! This must be called after the object has been initialized.
|
||||
|
||||
@return A reference to the initialized object
|
||||
@throw Exception If called before initialization */
|
||||
T * operator->()
|
||||
{
|
||||
if( !itsValid )
|
||||
throw Exception("Object must be initialized prior to accessing members");
|
||||
|
||||
return itsPtr;
|
||||
}
|
||||
|
||||
//! Returns a raw pointer to the initialized underlying object
|
||||
/*! This is mainly intended for use with passing an instance of
|
||||
a constructed object to cereal::base_class.
|
||||
|
||||
It is strongly recommended to avoid using this function in
|
||||
any other circumstance.
|
||||
|
||||
@return A raw pointer to the initialized type */
|
||||
T * ptr()
|
||||
{
|
||||
return operator->();
|
||||
}
|
||||
|
||||
private:
|
||||
template <class A, class B> friend struct ::cereal::memory_detail::LoadAndConstructLoadWrapper;
|
||||
|
||||
construct( T * p ) : itsPtr( p ), itsValid( false ) {}
|
||||
construct( construct const & ) = delete;
|
||||
construct & operator=( construct const & ) = delete;
|
||||
|
||||
T * itsPtr;
|
||||
bool itsValid;
|
||||
};
|
||||
|
||||
// ######################################################################
|
||||
//! A class that can be made a friend to give cereal access to non public functions
|
||||
/*! If you desire non-public serialization functions within a class, cereal can only
|
||||
access these if you declare cereal::access a friend.
|
||||
|
||||
@code{.cpp}
|
||||
class MyClass
|
||||
{
|
||||
private:
|
||||
friend class cereal::access; // gives access to the private serialize
|
||||
|
||||
template <class Archive>
|
||||
void serialize( Archive & ar )
|
||||
{
|
||||
// some code
|
||||
}
|
||||
};
|
||||
@endcode
|
||||
@ingroup Access */
|
||||
class access
|
||||
{
|
||||
public:
|
||||
// ####### Standard Serialization ########################################
|
||||
template<class Archive, class T> inline
|
||||
static auto member_serialize(Archive & ar, T & t) -> decltype(t.CEREAL_SERIALIZE_FUNCTION_NAME(ar))
|
||||
{ return t.CEREAL_SERIALIZE_FUNCTION_NAME(ar); }
|
||||
|
||||
template<class Archive, class T> inline
|
||||
static auto member_save(Archive & ar, T const & t) -> decltype(t.CEREAL_SAVE_FUNCTION_NAME(ar))
|
||||
{ return t.CEREAL_SAVE_FUNCTION_NAME(ar); }
|
||||
|
||||
template<class Archive, class T> inline
|
||||
static auto member_save_non_const(Archive & ar, T & t) -> decltype(t.CEREAL_SAVE_FUNCTION_NAME(ar))
|
||||
{ return t.CEREAL_SAVE_FUNCTION_NAME(ar); }
|
||||
|
||||
template<class Archive, class T> inline
|
||||
static auto member_load(Archive & ar, T & t) -> decltype(t.CEREAL_LOAD_FUNCTION_NAME(ar))
|
||||
{ return t.CEREAL_LOAD_FUNCTION_NAME(ar); }
|
||||
|
||||
template<class Archive, class T> inline
|
||||
static auto member_save_minimal(Archive const & ar, T const & t) -> decltype(t.CEREAL_SAVE_MINIMAL_FUNCTION_NAME(ar))
|
||||
{ return t.CEREAL_SAVE_MINIMAL_FUNCTION_NAME(ar); }
|
||||
|
||||
template<class Archive, class T> inline
|
||||
static auto member_save_minimal_non_const(Archive const & ar, T & t) -> decltype(t.CEREAL_SAVE_MINIMAL_FUNCTION_NAME(ar))
|
||||
{ return t.CEREAL_SAVE_MINIMAL_FUNCTION_NAME(ar); }
|
||||
|
||||
template<class Archive, class T, class U> inline
|
||||
static auto member_load_minimal(Archive const & ar, T & t, U && u) -> decltype(t.CEREAL_LOAD_MINIMAL_FUNCTION_NAME(ar, std::forward<U>(u)))
|
||||
{ return t.CEREAL_LOAD_MINIMAL_FUNCTION_NAME(ar, std::forward<U>(u)); }
|
||||
|
||||
// ####### Versioned Serialization #######################################
|
||||
template<class Archive, class T> inline
|
||||
static auto member_serialize(Archive & ar, T & t, const std::uint32_t version ) -> decltype(t.CEREAL_SERIALIZE_FUNCTION_NAME(ar, version))
|
||||
{ return t.CEREAL_SERIALIZE_FUNCTION_NAME(ar, version); }
|
||||
|
||||
template<class Archive, class T> inline
|
||||
static auto member_save(Archive & ar, T const & t, const std::uint32_t version ) -> decltype(t.CEREAL_SAVE_FUNCTION_NAME(ar, version))
|
||||
{ return t.CEREAL_SAVE_FUNCTION_NAME(ar, version); }
|
||||
|
||||
template<class Archive, class T> inline
|
||||
static auto member_save_non_const(Archive & ar, T & t, const std::uint32_t version ) -> decltype(t.CEREAL_SAVE_FUNCTION_NAME(ar, version))
|
||||
{ return t.CEREAL_SAVE_FUNCTION_NAME(ar, version); }
|
||||
|
||||
template<class Archive, class T> inline
|
||||
static auto member_load(Archive & ar, T & t, const std::uint32_t version ) -> decltype(t.CEREAL_LOAD_FUNCTION_NAME(ar, version))
|
||||
{ return t.CEREAL_LOAD_FUNCTION_NAME(ar, version); }
|
||||
|
||||
template<class Archive, class T> inline
|
||||
static auto member_save_minimal(Archive const & ar, T const & t, const std::uint32_t version) -> decltype(t.CEREAL_SAVE_MINIMAL_FUNCTION_NAME(ar, version))
|
||||
{ return t.CEREAL_SAVE_MINIMAL_FUNCTION_NAME(ar, version); }
|
||||
|
||||
template<class Archive, class T> inline
|
||||
static auto member_save_minimal_non_const(Archive const & ar, T & t, const std::uint32_t version) -> decltype(t.CEREAL_SAVE_MINIMAL_FUNCTION_NAME(ar, version))
|
||||
{ return t.CEREAL_SAVE_MINIMAL_FUNCTION_NAME(ar, version); }
|
||||
|
||||
template<class Archive, class T, class U> inline
|
||||
static auto member_load_minimal(Archive const & ar, T & t, U && u, const std::uint32_t version) -> decltype(t.CEREAL_LOAD_MINIMAL_FUNCTION_NAME(ar, std::forward<U>(u), version))
|
||||
{ return t.CEREAL_LOAD_MINIMAL_FUNCTION_NAME(ar, std::forward<U>(u), version); }
|
||||
|
||||
// ####### Other Functionality ##########################################
|
||||
// for detecting inheritance from enable_shared_from_this
|
||||
template <class T> inline
|
||||
static auto shared_from_this(T & t) -> decltype(t.shared_from_this());
|
||||
|
||||
// for placement new
|
||||
template <class T, class ... Args> inline
|
||||
static void construct( T *& ptr, Args && ... args )
|
||||
{
|
||||
new (ptr) T( std::forward<Args>( args )... );
|
||||
}
|
||||
|
||||
// for non-placement new with a default constructor
|
||||
template <class T> inline
|
||||
static T * construct()
|
||||
{
|
||||
return new T();
|
||||
}
|
||||
|
||||
template <class T> inline
|
||||
static std::false_type load_and_construct(...)
|
||||
{ return std::false_type(); }
|
||||
|
||||
template<class T, class Archive> inline
|
||||
static auto load_and_construct(Archive & ar, ::cereal::construct<T> & construct) -> decltype(T::load_and_construct(ar, construct))
|
||||
{
|
||||
T::load_and_construct( ar, construct );
|
||||
}
|
||||
}; // end class access
|
||||
|
||||
// ######################################################################
|
||||
//! A specifier used in conjunction with cereal::specialize to disambiguate
|
||||
//! serialization in special cases
|
||||
/*! @relates specialize
|
||||
@ingroup Access */
|
||||
enum class specialization
|
||||
{
|
||||
member_serialize, //!< Force the use of a member serialize function
|
||||
member_load_save, //!< Force the use of a member load/save pair
|
||||
member_load_save_minimal, //!< Force the use of a member minimal load/save pair
|
||||
non_member_serialize, //!< Force the use of a non-member serialize function
|
||||
non_member_load_save, //!< Force the use of a non-member load/save pair
|
||||
non_member_load_save_minimal //!< Force the use of a non-member minimal load/save pair
|
||||
};
|
||||
|
||||
//! A class used to disambiguate cases where cereal cannot detect a unique way of serializing a class
|
||||
/*! cereal attempts to figure out which method of serialization (member vs. non-member serialize
|
||||
or load/save pair) at compile time. If for some reason cereal cannot find a non-ambiguous way
|
||||
of serializing a type, it will produce a static assertion complaining about this.
|
||||
|
||||
This can happen because you have both a serialize and load/save pair, or even because a base
|
||||
class has a serialize (public or private with friend access) and a derived class does not
|
||||
overwrite this due to choosing some other serialization type.
|
||||
|
||||
Specializing this class will tell cereal to explicitly use the serialization type you specify
|
||||
and it will not complain about ambiguity in its compile time selection. However, if cereal detects
|
||||
an ambiguity in specializations, it will continue to issue a static assertion.
|
||||
|
||||
@code{.cpp}
|
||||
class MyParent
|
||||
{
|
||||
friend class cereal::access;
|
||||
template <class Archive>
|
||||
void serialize( Archive & ar ) {}
|
||||
};
|
||||
|
||||
// Although serialize is private in MyParent, to cereal::access it will look public,
|
||||
// even through MyDerived
|
||||
class MyDerived : public MyParent
|
||||
{
|
||||
public:
|
||||
template <class Archive>
|
||||
void load( Archive & ar ) {}
|
||||
|
||||
template <class Archive>
|
||||
void save( Archive & ar ) {}
|
||||
};
|
||||
|
||||
// The load/save pair in MyDerived is ambiguous because serialize in MyParent can
|
||||
// be accessed from cereal::access. This looks the same as making serialize public
|
||||
// in MyParent, making it seem as though MyDerived has both a serialize and a load/save pair.
|
||||
// cereal will complain about this at compile time unless we disambiguate:
|
||||
|
||||
namespace cereal
|
||||
{
|
||||
// This struct specialization will tell cereal which is the right way to serialize the ambiguity
|
||||
template <class Archive> struct specialize<Archive, MyDerived, cereal::specialization::member_load_save> {};
|
||||
|
||||
// If we only had a disambiguation for a specific archive type, it would look something like this
|
||||
template <> struct specialize<cereal::BinaryOutputArchive, MyDerived, cereal::specialization::member_load_save> {};
|
||||
}
|
||||
@endcode
|
||||
|
||||
You can also choose to use the macros CEREAL_SPECIALIZE_FOR_ALL_ARCHIVES or
|
||||
CEREAL_SPECIALIZE_FOR_ARCHIVE if you want to type a little bit less.
|
||||
|
||||
@tparam T The type to specialize the serialization for
|
||||
@tparam S The specialization type to use for T
|
||||
@ingroup Access */
|
||||
template <class Archive, class T, specialization S>
|
||||
struct specialize : public std::false_type {};
|
||||
|
||||
//! Convenient macro for performing specialization for all archive types
|
||||
/*! This performs specialization for the specific type for all types of archives.
|
||||
This macro should be placed at the global namespace.
|
||||
|
||||
@code{cpp}
|
||||
struct MyType {};
|
||||
CEREAL_SPECIALIZE_FOR_ALL_ARCHIVES( MyType, cereal::specialization::member_load_save );
|
||||
@endcode
|
||||
|
||||
@relates specialize
|
||||
@ingroup Access */
|
||||
#define CEREAL_SPECIALIZE_FOR_ALL_ARCHIVES( Type, Specialization ) \
|
||||
namespace cereal { template <class Archive> struct specialize<Archive, Type, Specialization> {}; }
|
||||
|
||||
//! Convenient macro for performing specialization for a single archive type
|
||||
/*! This performs specialization for the specific type for a single type of archive.
|
||||
This macro should be placed at the global namespace.
|
||||
|
||||
@code{cpp}
|
||||
struct MyType {};
|
||||
CEREAL_SPECIALIZE_FOR_ARCHIVE( cereal::XMLInputArchive, MyType, cereal::specialization::member_load_save );
|
||||
@endcode
|
||||
|
||||
@relates specialize
|
||||
@ingroup Access */
|
||||
#define CEREAL_SPECIALIZE_FOR_ARCHIVE( Archive, Type, Specialization ) \
|
||||
namespace cereal { template <> struct specialize<Archive, Type, Specialization> {}; }
|
||||
|
||||
// ######################################################################
|
||||
// Deferred Implementation, see construct for more information
|
||||
template <class T> template <class ... Args> inline
|
||||
void construct<T>::operator()( Args && ... args )
|
||||
{
|
||||
if( itsValid )
|
||||
throw Exception("Attempting to construct an already initialized object");
|
||||
|
||||
::cereal::access::construct( itsPtr, std::forward<Args>( args )... );
|
||||
itsValid = true;
|
||||
}
|
||||
} // namespace cereal
|
||||
|
||||
#endif // CEREAL_ACCESS_HPP_
|
||||
163
libs/cereal/cereal/archives/adapters.hpp
Normal file
163
libs/cereal/cereal/archives/adapters.hpp
Normal file
@ -0,0 +1,163 @@
|
||||
/*! \file adapters.hpp
|
||||
\brief Archive adapters that provide additional functionality
|
||||
on top of an existing archive */
|
||||
/*
|
||||
Copyright (c) 2014, Randolph Voorhies, Shane Grant
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of cereal nor the
|
||||
names of its contributors may be used to endorse or promote products
|
||||
derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL RANDOLPH VOORHIES OR SHANE GRANT BE LIABLE FOR ANY
|
||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
#ifndef CEREAL_ARCHIVES_ADAPTERS_HPP_
|
||||
#define CEREAL_ARCHIVES_ADAPTERS_HPP_
|
||||
|
||||
#include <cereal/details/helpers.hpp>
|
||||
#include <utility>
|
||||
|
||||
namespace cereal
|
||||
{
|
||||
#ifdef CEREAL_FUTURE_EXPERIMENTAL
|
||||
|
||||
// Forward declaration for friend access
|
||||
template <class U, class A> U & get_user_data( A & );
|
||||
|
||||
//! Wraps an archive and gives access to user data
|
||||
/*! This adapter is useful if you require access to
|
||||
either raw pointers or references within your
|
||||
serialization functions.
|
||||
|
||||
While cereal does not directly support serialization
|
||||
raw pointers or references, it is sometimes the case
|
||||
that you may want to supply something such as a raw
|
||||
pointer or global reference to some constructor.
|
||||
In this situation this adapter would likely be used
|
||||
with the construct class to allow for non-default
|
||||
constructors.
|
||||
|
||||
@note This feature is experimental and may be altered or removed in a future release. See issue #46.
|
||||
|
||||
@code{.cpp}
|
||||
struct MyUserData
|
||||
{
|
||||
int * myRawPointer;
|
||||
std::reference_wrapper<MyOtherType> myReference;
|
||||
};
|
||||
|
||||
struct MyClass
|
||||
{
|
||||
// Note the raw pointer parameter
|
||||
MyClass( int xx, int * rawP );
|
||||
|
||||
int x;
|
||||
|
||||
template <class Archive>
|
||||
void serialize( Archive & ar )
|
||||
{ ar( x ); }
|
||||
|
||||
template <class Archive>
|
||||
static void load_and_construct( Archive & ar, cereal::construct<MyClass> & construct )
|
||||
{
|
||||
int xx;
|
||||
ar( xx );
|
||||
// note the need to use get_user_data to retrieve user data from the archive
|
||||
construct( xx, cereal::get_user_data<MyUserData>( ar ).myRawPointer );
|
||||
}
|
||||
};
|
||||
|
||||
int main()
|
||||
{
|
||||
{
|
||||
MyUserData md;
|
||||
md.myRawPointer = &something;
|
||||
md.myReference = someInstanceOfType;
|
||||
|
||||
std::ifstream is( "data.xml" );
|
||||
cereal::UserDataAdapter<MyUserData, cereal::XMLInputArchive> ar( md, is );
|
||||
|
||||
std::unique_ptr<MyClass> sc;
|
||||
ar( sc ); // use as normal
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
@endcode
|
||||
|
||||
@relates get_user_data
|
||||
|
||||
@tparam UserData The type to give the archive access to
|
||||
@tparam Archive The archive to wrap */
|
||||
template <class UserData, class Archive>
|
||||
class UserDataAdapter : public Archive
|
||||
{
|
||||
public:
|
||||
//! Construct the archive with some user data struct
|
||||
/*! This will forward all arguments (other than the user
|
||||
data) to the wrapped archive type. The UserDataAdapter
|
||||
can then be used identically to the wrapped archive type
|
||||
|
||||
@tparam Args The arguments to pass to the constructor of
|
||||
the archive. */
|
||||
template <class ... Args>
|
||||
UserDataAdapter( UserData & ud, Args && ... args ) :
|
||||
Archive( std::forward<Args>( args )... ),
|
||||
userdata( ud )
|
||||
{ }
|
||||
|
||||
private:
|
||||
//! Overload the rtti function to enable dynamic_cast
|
||||
void rtti() {}
|
||||
friend UserData & get_user_data<UserData>( Archive & ar );
|
||||
UserData & userdata; //!< The actual user data
|
||||
};
|
||||
|
||||
//! Retrieves user data from an archive wrapped by UserDataAdapter
|
||||
/*! This will attempt to retrieve the user data associated with
|
||||
some archive wrapped by UserDataAdapter. If this is used on
|
||||
an archive that is not wrapped, a run-time exception will occur.
|
||||
|
||||
@note This feature is experimental and may be altered or removed in a future release. See issue #46.
|
||||
|
||||
@note The correct use of this function cannot be enforced at compile
|
||||
time.
|
||||
|
||||
@relates UserDataAdapter
|
||||
@tparam UserData The data struct contained in the archive
|
||||
@tparam Archive The archive, which should be wrapped by UserDataAdapter
|
||||
@param ar The archive
|
||||
@throws Exception if the archive this is used upon is not wrapped with
|
||||
UserDataAdapter. */
|
||||
template <class UserData, class Archive>
|
||||
UserData & get_user_data( Archive & ar )
|
||||
{
|
||||
try
|
||||
{
|
||||
return dynamic_cast<UserDataAdapter<UserData, Archive> &>( ar ).userdata;
|
||||
}
|
||||
catch( std::bad_cast const & )
|
||||
{
|
||||
throw ::cereal::Exception("Attempting to get user data from archive not wrapped in UserDataAdapter");
|
||||
}
|
||||
}
|
||||
#endif // CEREAL_FUTURE_EXPERIMENTAL
|
||||
} // namespace cereal
|
||||
|
||||
#endif // CEREAL_ARCHIVES_ADAPTERS_HPP_
|
||||
165
libs/cereal/cereal/archives/binary.hpp
Normal file
165
libs/cereal/cereal/archives/binary.hpp
Normal file
@ -0,0 +1,165 @@
|
||||
/*! \file binary.hpp
|
||||
\brief Binary input and output archives */
|
||||
/*
|
||||
Copyright (c) 2014, Randolph Voorhies, Shane Grant
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of cereal nor the
|
||||
names of its contributors may be used to endorse or promote products
|
||||
derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL RANDOLPH VOORHIES OR SHANE GRANT BE LIABLE FOR ANY
|
||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
#ifndef CEREAL_ARCHIVES_BINARY_HPP_
|
||||
#define CEREAL_ARCHIVES_BINARY_HPP_
|
||||
|
||||
#include <cereal/cereal.hpp>
|
||||
#include <sstream>
|
||||
|
||||
namespace cereal
|
||||
{
|
||||
// ######################################################################
|
||||
//! An output archive designed to save data in a compact binary representation
|
||||
/*! This archive outputs data to a stream in an extremely compact binary
|
||||
representation with as little extra metadata as possible.
|
||||
|
||||
This archive does nothing to ensure that the endianness of the saved
|
||||
and loaded data is the same. If you need to have portability over
|
||||
architectures with different endianness, use PortableBinaryOutputArchive.
|
||||
|
||||
When using a binary archive and a file stream, you must use the
|
||||
std::ios::binary format flag to avoid having your data altered
|
||||
inadvertently.
|
||||
|
||||
\ingroup Archives */
|
||||
class BinaryOutputArchive : public OutputArchive<BinaryOutputArchive, AllowEmptyClassElision>
|
||||
{
|
||||
public:
|
||||
//! Construct, outputting to the provided stream
|
||||
/*! @param stream The stream to output to. Can be a stringstream, a file stream, or
|
||||
even cout! */
|
||||
BinaryOutputArchive(std::ostream & stream) :
|
||||
OutputArchive<BinaryOutputArchive, AllowEmptyClassElision>(this),
|
||||
itsStream(stream)
|
||||
{ }
|
||||
|
||||
//! Writes size bytes of data to the output stream
|
||||
void saveBinary( const void * data, std::size_t size )
|
||||
{
|
||||
auto const writtenSize = static_cast<std::size_t>( itsStream.rdbuf()->sputn( reinterpret_cast<const char*>( data ), size ) );
|
||||
|
||||
if(writtenSize != size)
|
||||
throw Exception("Failed to write " + std::to_string(size) + " bytes to output stream! Wrote " + std::to_string(writtenSize));
|
||||
}
|
||||
|
||||
private:
|
||||
std::ostream & itsStream;
|
||||
};
|
||||
|
||||
// ######################################################################
|
||||
//! An input archive designed to load data saved using BinaryOutputArchive
|
||||
/* This archive does nothing to ensure that the endianness of the saved
|
||||
and loaded data is the same. If you need to have portability over
|
||||
architectures with different endianness, use PortableBinaryOutputArchive.
|
||||
|
||||
When using a binary archive and a file stream, you must use the
|
||||
std::ios::binary format flag to avoid having your data altered
|
||||
inadvertently.
|
||||
|
||||
\ingroup Archives */
|
||||
class BinaryInputArchive : public InputArchive<BinaryInputArchive, AllowEmptyClassElision>
|
||||
{
|
||||
public:
|
||||
//! Construct, loading from the provided stream
|
||||
BinaryInputArchive(std::istream & stream) :
|
||||
InputArchive<BinaryInputArchive, AllowEmptyClassElision>(this),
|
||||
itsStream(stream)
|
||||
{ }
|
||||
|
||||
//! Reads size bytes of data from the input stream
|
||||
void loadBinary( void * const data, std::size_t size )
|
||||
{
|
||||
auto const readSize = static_cast<std::size_t>( itsStream.rdbuf()->sgetn( reinterpret_cast<char*>( data ), size ) );
|
||||
|
||||
if(readSize != size)
|
||||
throw Exception("Failed to read " + std::to_string(size) + " bytes from input stream! Read " + std::to_string(readSize));
|
||||
}
|
||||
|
||||
private:
|
||||
std::istream & itsStream;
|
||||
};
|
||||
|
||||
// ######################################################################
|
||||
// Common BinaryArchive serialization functions
|
||||
|
||||
//! Saving for POD types to binary
|
||||
template<class T> inline
|
||||
typename std::enable_if<std::is_arithmetic<T>::value, void>::type
|
||||
CEREAL_SAVE_FUNCTION_NAME(BinaryOutputArchive & ar, T const & t)
|
||||
{
|
||||
ar.saveBinary(std::addressof(t), sizeof(t));
|
||||
}
|
||||
|
||||
//! Loading for POD types from binary
|
||||
template<class T> inline
|
||||
typename std::enable_if<std::is_arithmetic<T>::value, void>::type
|
||||
CEREAL_LOAD_FUNCTION_NAME(BinaryInputArchive & ar, T & t)
|
||||
{
|
||||
ar.loadBinary(std::addressof(t), sizeof(t));
|
||||
}
|
||||
|
||||
//! Serializing NVP types to binary
|
||||
template <class Archive, class T> inline
|
||||
CEREAL_ARCHIVE_RESTRICT(BinaryInputArchive, BinaryOutputArchive)
|
||||
CEREAL_SERIALIZE_FUNCTION_NAME( Archive & ar, NameValuePair<T> & t )
|
||||
{
|
||||
ar( t.value );
|
||||
}
|
||||
|
||||
//! Serializing SizeTags to binary
|
||||
template <class Archive, class T> inline
|
||||
CEREAL_ARCHIVE_RESTRICT(BinaryInputArchive, BinaryOutputArchive)
|
||||
CEREAL_SERIALIZE_FUNCTION_NAME( Archive & ar, SizeTag<T> & t )
|
||||
{
|
||||
ar( t.size );
|
||||
}
|
||||
|
||||
//! Saving binary data
|
||||
template <class T> inline
|
||||
void CEREAL_SAVE_FUNCTION_NAME(BinaryOutputArchive & ar, BinaryData<T> const & bd)
|
||||
{
|
||||
ar.saveBinary( bd.data, static_cast<std::size_t>( bd.size ) );
|
||||
}
|
||||
|
||||
//! Loading binary data
|
||||
template <class T> inline
|
||||
void CEREAL_LOAD_FUNCTION_NAME(BinaryInputArchive & ar, BinaryData<T> & bd)
|
||||
{
|
||||
ar.loadBinary(bd.data, static_cast<std::size_t>(bd.size));
|
||||
}
|
||||
} // namespace cereal
|
||||
|
||||
// register archives for polymorphic support
|
||||
CEREAL_REGISTER_ARCHIVE(cereal::BinaryOutputArchive)
|
||||
CEREAL_REGISTER_ARCHIVE(cereal::BinaryInputArchive)
|
||||
|
||||
// tie input and output archives together
|
||||
CEREAL_SETUP_ARCHIVE_TRAITS(cereal::BinaryInputArchive, cereal::BinaryOutputArchive)
|
||||
|
||||
#endif // CEREAL_ARCHIVES_BINARY_HPP_
|
||||
912
libs/cereal/cereal/archives/json.hpp
Normal file
912
libs/cereal/cereal/archives/json.hpp
Normal file
@ -0,0 +1,912 @@
|
||||
/*! \file json.hpp
|
||||
\brief JSON input and output archives */
|
||||
/*
|
||||
Copyright (c) 2014, Randolph Voorhies, Shane Grant
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of cereal nor the
|
||||
names of its contributors may be used to endorse or promote products
|
||||
derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL RANDOLPH VOORHIES OR SHANE GRANT BE LIABLE FOR ANY
|
||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
#ifndef CEREAL_ARCHIVES_JSON_HPP_
|
||||
#define CEREAL_ARCHIVES_JSON_HPP_
|
||||
|
||||
#include <cereal/cereal.hpp>
|
||||
#include <cereal/details/util.hpp>
|
||||
|
||||
namespace cereal
|
||||
{
|
||||
//! An exception thrown when rapidjson fails an internal assertion
|
||||
/*! @ingroup Utility */
|
||||
struct RapidJSONException : Exception
|
||||
{ RapidJSONException( const char * what_ ) : Exception( what_ ) {} };
|
||||
}
|
||||
|
||||
// Override rapidjson assertions to throw exceptions by default
|
||||
#ifndef RAPIDJSON_ASSERT
|
||||
#define RAPIDJSON_ASSERT(x) if(!(x)){ \
|
||||
throw ::cereal::RapidJSONException("rapidjson internal assertion failure: " #x); }
|
||||
#endif // RAPIDJSON_ASSERT
|
||||
|
||||
#include <cereal/external/rapidjson/prettywriter.h>
|
||||
#include <cereal/external/rapidjson/genericstream.h>
|
||||
#include <cereal/external/rapidjson/reader.h>
|
||||
#include <cereal/external/rapidjson/document.h>
|
||||
#include <cereal/external/base64.hpp>
|
||||
|
||||
#include <limits>
|
||||
#include <sstream>
|
||||
#include <stack>
|
||||
#include <vector>
|
||||
#include <string>
|
||||
|
||||
namespace cereal
|
||||
{
|
||||
// ######################################################################
|
||||
//! An output archive designed to save data to JSON
|
||||
/*! This archive uses RapidJSON to build serialie data to JSON.
|
||||
|
||||
JSON archives provides a human readable output but at decreased
|
||||
performance (both in time and space) compared to binary archives.
|
||||
|
||||
JSON benefits greatly from name-value pairs, which if present, will
|
||||
name the nodes in the output. If these are not present, each level
|
||||
of the output will be given an automatically generated delimited name.
|
||||
|
||||
The precision of the output archive controls the number of decimals output
|
||||
for floating point numbers and should be sufficiently large (i.e. at least 20)
|
||||
if there is a desire to have binary equality between the numbers output and
|
||||
those read in. In general you should expect a loss of precision when going
|
||||
from floating point to text and back.
|
||||
|
||||
JSON archives do not output the size information for any dynamically sized structure
|
||||
and instead infer it from the number of children for a node. This means that data
|
||||
can be hand edited for dynamic sized structures and will still be readable. This
|
||||
is accomplished through the cereal::SizeTag object, which will cause the archive
|
||||
to output the data as a JSON array (e.g. marked by [] instead of {}), which indicates
|
||||
that the container is variable sized and may be edited.
|
||||
|
||||
\ingroup Archives */
|
||||
class JSONOutputArchive : public OutputArchive<JSONOutputArchive>, public traits::TextArchive
|
||||
{
|
||||
enum class NodeType { StartObject, InObject, StartArray, InArray };
|
||||
|
||||
typedef rapidjson::GenericWriteStream WriteStream;
|
||||
typedef rapidjson::PrettyWriter<WriteStream> JSONWriter;
|
||||
|
||||
public:
|
||||
/*! @name Common Functionality
|
||||
Common use cases for directly interacting with an JSONOutputArchive */
|
||||
//! @{
|
||||
|
||||
//! A class containing various advanced options for the JSON archive
|
||||
class Options
|
||||
{
|
||||
public:
|
||||
//! Default options
|
||||
static Options Default(){ return Options(); }
|
||||
|
||||
//! Default options with no indentation
|
||||
static Options NoIndent(){ return Options( std::numeric_limits<double>::max_digits10, IndentChar::space, 0 ); }
|
||||
|
||||
//! The character to use for indenting
|
||||
enum class IndentChar : char
|
||||
{
|
||||
space = ' ',
|
||||
tab = '\t',
|
||||
newline = '\n',
|
||||
carriage_return = '\r'
|
||||
};
|
||||
|
||||
//! Specify specific options for the JSONOutputArchive
|
||||
/*! @param precision The precision used for floating point numbers
|
||||
@param indentChar The type of character to indent with
|
||||
@param indentLength The number of indentChar to use for indentation
|
||||
(0 corresponds to no indentation) */
|
||||
explicit Options( int precision = std::numeric_limits<double>::max_digits10,
|
||||
IndentChar indentChar = IndentChar::space,
|
||||
unsigned int indentLength = 4 ) :
|
||||
itsPrecision( precision ),
|
||||
itsIndentChar( static_cast<char>(indentChar) ),
|
||||
itsIndentLength( indentLength ) { }
|
||||
|
||||
private:
|
||||
friend class JSONOutputArchive;
|
||||
int itsPrecision;
|
||||
char itsIndentChar;
|
||||
unsigned int itsIndentLength;
|
||||
};
|
||||
|
||||
//! Construct, outputting to the provided stream
|
||||
/*! @param stream The stream to output to.
|
||||
@param options The JSON specific options to use. See the Options struct
|
||||
for the values of default parameters */
|
||||
JSONOutputArchive(std::ostream & stream, Options const & options = Options::Default() ) :
|
||||
OutputArchive<JSONOutputArchive>(this),
|
||||
itsWriteStream(stream),
|
||||
itsWriter(itsWriteStream, options.itsPrecision),
|
||||
itsNextName(nullptr)
|
||||
{
|
||||
itsWriter.SetIndent( options.itsIndentChar, options.itsIndentLength );
|
||||
itsNameCounter.push(0);
|
||||
itsNodeStack.push(NodeType::StartObject);
|
||||
}
|
||||
|
||||
//! Destructor, flushes the JSON
|
||||
~JSONOutputArchive()
|
||||
{
|
||||
if (itsNodeStack.top() == NodeType::InObject)
|
||||
itsWriter.EndObject();
|
||||
}
|
||||
|
||||
//! Saves some binary data, encoded as a base64 string, with an optional name
|
||||
/*! This will create a new node, optionally named, and insert a value that consists of
|
||||
the data encoded as a base64 string */
|
||||
void saveBinaryValue( const void * data, size_t size, const char * name = nullptr )
|
||||
{
|
||||
setNextName( name );
|
||||
writeName();
|
||||
|
||||
auto base64string = base64::encode( reinterpret_cast<const unsigned char *>( data ), size );
|
||||
saveValue( base64string );
|
||||
};
|
||||
|
||||
//! @}
|
||||
/*! @name Internal Functionality
|
||||
Functionality designed for use by those requiring control over the inner mechanisms of
|
||||
the JSONOutputArchive */
|
||||
//! @{
|
||||
|
||||
//! Starts a new node in the JSON output
|
||||
/*! The node can optionally be given a name by calling setNextName prior
|
||||
to creating the node
|
||||
|
||||
Nodes only need to be started for types that are themselves objects or arrays */
|
||||
void startNode()
|
||||
{
|
||||
writeName();
|
||||
itsNodeStack.push(NodeType::StartObject);
|
||||
itsNameCounter.push(0);
|
||||
}
|
||||
|
||||
//! Designates the most recently added node as finished
|
||||
void finishNode()
|
||||
{
|
||||
// if we ended up serializing an empty object or array, writeName
|
||||
// will never have been called - so start and then immediately end
|
||||
// the object/array.
|
||||
//
|
||||
// We'll also end any object/arrays we happen to be in
|
||||
switch(itsNodeStack.top())
|
||||
{
|
||||
case NodeType::StartArray:
|
||||
itsWriter.StartArray();
|
||||
case NodeType::InArray:
|
||||
itsWriter.EndArray();
|
||||
break;
|
||||
case NodeType::StartObject:
|
||||
itsWriter.StartObject();
|
||||
case NodeType::InObject:
|
||||
itsWriter.EndObject();
|
||||
break;
|
||||
}
|
||||
|
||||
itsNodeStack.pop();
|
||||
itsNameCounter.pop();
|
||||
}
|
||||
|
||||
//! Sets the name for the next node created with startNode
|
||||
void setNextName( const char * name )
|
||||
{
|
||||
itsNextName = name;
|
||||
}
|
||||
|
||||
//! Saves a bool to the current node
|
||||
void saveValue(bool b) { itsWriter.Bool_(b); }
|
||||
//! Saves an int to the current node
|
||||
void saveValue(int i) { itsWriter.Int(i); }
|
||||
//! Saves a uint to the current node
|
||||
void saveValue(unsigned u) { itsWriter.Uint(u); }
|
||||
//! Saves an int64 to the current node
|
||||
void saveValue(int64_t i64) { itsWriter.Int64(i64); }
|
||||
//! Saves a uint64 to the current node
|
||||
void saveValue(uint64_t u64) { itsWriter.Uint64(u64); }
|
||||
//! Saves a double to the current node
|
||||
void saveValue(double d) { itsWriter.Double(d); }
|
||||
//! Saves a string to the current node
|
||||
void saveValue(std::string const & s) { itsWriter.String(s.c_str(), static_cast<rapidjson::SizeType>( s.size() )); }
|
||||
//! Saves a const char * to the current node
|
||||
void saveValue(char const * s) { itsWriter.String(s); }
|
||||
|
||||
private:
|
||||
// Some compilers/OS have difficulty disambiguating the above for various flavors of longs, so we provide
|
||||
// special overloads to handle these cases.
|
||||
|
||||
//! 32 bit signed long saving to current node
|
||||
template <class T, traits::EnableIf<sizeof(T) == sizeof(std::int32_t),
|
||||
std::is_signed<T>::value> = traits::sfinae> inline
|
||||
void saveLong(T l){ saveValue( static_cast<std::int32_t>( l ) ); }
|
||||
|
||||
//! non 32 bit signed long saving to current node
|
||||
template <class T, traits::EnableIf<sizeof(T) != sizeof(std::int32_t),
|
||||
std::is_signed<T>::value> = traits::sfinae> inline
|
||||
void saveLong(T l){ saveValue( static_cast<std::int64_t>( l ) ); }
|
||||
|
||||
//! 32 bit unsigned long saving to current node
|
||||
template <class T, traits::EnableIf<sizeof(T) == sizeof(std::int32_t),
|
||||
std::is_unsigned<T>::value> = traits::sfinae> inline
|
||||
void saveLong(T lu){ saveValue( static_cast<std::uint32_t>( lu ) ); }
|
||||
|
||||
//! non 32 bit unsigned long saving to current node
|
||||
template <class T, traits::EnableIf<sizeof(T) != sizeof(std::int32_t),
|
||||
std::is_unsigned<T>::value> = traits::sfinae> inline
|
||||
void saveLong(T lu){ saveValue( static_cast<std::uint64_t>( lu ) ); }
|
||||
|
||||
public:
|
||||
#ifdef _MSC_VER
|
||||
//! MSVC only long overload to current node
|
||||
void saveValue( unsigned long lu ){ saveLong( lu ); };
|
||||
#else // _MSC_VER
|
||||
//! Serialize a long if it would not be caught otherwise
|
||||
template <class T, traits::EnableIf<std::is_same<T, long>::value,
|
||||
!std::is_same<T, std::int32_t>::value,
|
||||
!std::is_same<T, std::int64_t>::value> = traits::sfinae> inline
|
||||
void saveValue( T t ){ saveLong( t ); }
|
||||
|
||||
//! Serialize an unsigned long if it would not be caught otherwise
|
||||
template <class T, traits::EnableIf<std::is_same<T, unsigned long>::value,
|
||||
!std::is_same<T, std::uint32_t>::value,
|
||||
!std::is_same<T, std::uint64_t>::value> = traits::sfinae> inline
|
||||
void saveValue( T t ){ saveLong( t ); }
|
||||
#endif // _MSC_VER
|
||||
|
||||
//! Save exotic arithmetic as strings to current node
|
||||
/*! Handles long long (if distinct from other types), unsigned long (if distinct), and long double */
|
||||
template <class T, traits::EnableIf<std::is_arithmetic<T>::value,
|
||||
!std::is_same<T, long>::value,
|
||||
!std::is_same<T, unsigned long>::value,
|
||||
!std::is_same<T, std::int64_t>::value,
|
||||
!std::is_same<T, std::uint64_t>::value,
|
||||
(sizeof(T) >= sizeof(long double) || sizeof(T) >= sizeof(long long))> = traits::sfinae> inline
|
||||
void saveValue(T const & t)
|
||||
{
|
||||
std::stringstream ss; ss.precision( std::numeric_limits<long double>::max_digits10 );
|
||||
ss << t;
|
||||
saveValue( ss.str() );
|
||||
}
|
||||
|
||||
//! Write the name of the upcoming node and prepare object/array state
|
||||
/*! Since writeName is called for every value that is output, regardless of
|
||||
whether it has a name or not, it is the place where we will do a deferred
|
||||
check of our node state and decide whether we are in an array or an object.
|
||||
|
||||
The general workflow of saving to the JSON archive is:
|
||||
|
||||
1. (optional) Set the name for the next node to be created, usually done by an NVP
|
||||
2. Start the node
|
||||
3. (if there is data to save) Write the name of the node (this function)
|
||||
4. (if there is data to save) Save the data (with saveValue)
|
||||
5. Finish the node
|
||||
*/
|
||||
void writeName()
|
||||
{
|
||||
NodeType const & nodeType = itsNodeStack.top();
|
||||
|
||||
// Start up either an object or an array, depending on state
|
||||
if(nodeType == NodeType::StartArray)
|
||||
{
|
||||
itsWriter.StartArray();
|
||||
itsNodeStack.top() = NodeType::InArray;
|
||||
}
|
||||
else if(nodeType == NodeType::StartObject)
|
||||
{
|
||||
itsNodeStack.top() = NodeType::InObject;
|
||||
itsWriter.StartObject();
|
||||
}
|
||||
|
||||
// Array types do not output names
|
||||
if(nodeType == NodeType::InArray) return;
|
||||
|
||||
if(itsNextName == nullptr)
|
||||
{
|
||||
std::string name = "value" + std::to_string( itsNameCounter.top()++ ) + "\0";
|
||||
saveValue(name);
|
||||
}
|
||||
else
|
||||
{
|
||||
saveValue(itsNextName);
|
||||
itsNextName = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
//! Designates that the current node should be output as an array, not an object
|
||||
void makeArray()
|
||||
{
|
||||
itsNodeStack.top() = NodeType::StartArray;
|
||||
}
|
||||
|
||||
//! @}
|
||||
|
||||
private:
|
||||
WriteStream itsWriteStream; //!< Rapidjson write stream
|
||||
JSONWriter itsWriter; //!< Rapidjson writer
|
||||
char const * itsNextName; //!< The next name
|
||||
std::stack<uint32_t> itsNameCounter; //!< Counter for creating unique names for unnamed nodes
|
||||
std::stack<NodeType> itsNodeStack;
|
||||
}; // JSONOutputArchive
|
||||
|
||||
// ######################################################################
|
||||
//! An input archive designed to load data from JSON
|
||||
/*! This archive uses RapidJSON to read in a JSON archive.
|
||||
|
||||
Input JSON should have been produced by the JSONOutputArchive. Data can
|
||||
only be added to dynamically sized containers (marked by JSON arrays) -
|
||||
the input archive will determine their size by looking at the number of child nodes.
|
||||
Only JSON originating from a JSONOutputArchive is officially supported, but data
|
||||
from other sources may work if properly formatted.
|
||||
|
||||
The JSONInputArchive does not require that nodes are loaded in the same
|
||||
order they were saved by JSONOutputArchive. Using name value pairs (NVPs),
|
||||
it is possible to load in an out of order fashion or otherwise skip/select
|
||||
specific nodes to load.
|
||||
|
||||
The default behavior of the input archive is to read sequentially starting
|
||||
with the first node and exploring its children. When a given NVP does
|
||||
not match the read in name for a node, the archive will search for that
|
||||
node at the current level and load it if it exists. After loading an out of
|
||||
order node, the archive will then proceed back to loading sequentially from
|
||||
its new position.
|
||||
|
||||
Consider this simple example where loading of some data is skipped:
|
||||
|
||||
@code{cpp}
|
||||
// imagine the input file has someData(1-9) saved in order at the top level node
|
||||
ar( someData1, someData2, someData3 ); // XML loads in the order it sees in the file
|
||||
ar( cereal::make_nvp( "hello", someData6 ) ); // NVP given does not
|
||||
// match expected NVP name, so we search
|
||||
// for the given NVP and load that value
|
||||
ar( someData7, someData8, someData9 ); // with no NVP given, loading resumes at its
|
||||
// current location, proceeding sequentially
|
||||
@endcode
|
||||
|
||||
\ingroup Archives */
|
||||
class JSONInputArchive : public InputArchive<JSONInputArchive>, public traits::TextArchive
|
||||
{
|
||||
private:
|
||||
typedef rapidjson::GenericReadStream ReadStream;
|
||||
typedef rapidjson::GenericValue<rapidjson::UTF8<>> JSONValue;
|
||||
typedef JSONValue::ConstMemberIterator MemberIterator;
|
||||
typedef JSONValue::ConstValueIterator ValueIterator;
|
||||
typedef rapidjson::Document::GenericValue GenericValue;
|
||||
|
||||
public:
|
||||
/*! @name Common Functionality
|
||||
Common use cases for directly interacting with an JSONInputArchive */
|
||||
//! @{
|
||||
|
||||
//! Construct, reading from the provided stream
|
||||
/*! @param stream The stream to read from */
|
||||
JSONInputArchive(std::istream & stream) :
|
||||
InputArchive<JSONInputArchive>(this),
|
||||
itsNextName( nullptr ),
|
||||
itsReadStream(stream)
|
||||
{
|
||||
itsDocument.ParseStream<0>(itsReadStream);
|
||||
itsIteratorStack.emplace_back(itsDocument.MemberBegin(), itsDocument.MemberEnd());
|
||||
}
|
||||
|
||||
//! Loads some binary data, encoded as a base64 string
|
||||
/*! This will automatically start and finish a node to load the data, and can be called directly by
|
||||
users.
|
||||
|
||||
Note that this follows the same ordering rules specified in the class description in regards
|
||||
to loading in/out of order */
|
||||
void loadBinaryValue( void * data, size_t size, const char * name = nullptr )
|
||||
{
|
||||
itsNextName = name;
|
||||
|
||||
std::string encoded;
|
||||
loadValue( encoded );
|
||||
auto decoded = base64::decode( encoded );
|
||||
|
||||
if( size != decoded.size() )
|
||||
throw Exception("Decoded binary data size does not match specified size");
|
||||
|
||||
std::memcpy( data, decoded.data(), decoded.size() );
|
||||
itsNextName = nullptr;
|
||||
};
|
||||
|
||||
private:
|
||||
//! @}
|
||||
/*! @name Internal Functionality
|
||||
Functionality designed for use by those requiring control over the inner mechanisms of
|
||||
the JSONInputArchive */
|
||||
//! @{
|
||||
|
||||
//! An internal iterator that handles both array and object types
|
||||
/*! This class is a variant and holds both types of iterators that
|
||||
rapidJSON supports - one for arrays and one for objects. */
|
||||
class Iterator
|
||||
{
|
||||
public:
|
||||
Iterator() : itsIndex( 0 ), itsType(Null_) {}
|
||||
|
||||
Iterator(MemberIterator begin, MemberIterator end) :
|
||||
itsMemberItBegin(begin), itsMemberItEnd(end), itsIndex(0), itsType(Member)
|
||||
{ }
|
||||
|
||||
Iterator(ValueIterator begin, ValueIterator end) :
|
||||
itsValueItBegin(begin), itsValueItEnd(end), itsIndex(0), itsType(Value)
|
||||
{ }
|
||||
|
||||
//! Advance to the next node
|
||||
Iterator & operator++()
|
||||
{
|
||||
++itsIndex;
|
||||
return *this;
|
||||
}
|
||||
|
||||
//! Get the value of the current node
|
||||
GenericValue const & value()
|
||||
{
|
||||
switch(itsType)
|
||||
{
|
||||
case Value : return itsValueItBegin[itsIndex];
|
||||
case Member: return itsMemberItBegin[itsIndex].value;
|
||||
default: throw cereal::Exception("Invalid Iterator Type!");
|
||||
}
|
||||
}
|
||||
|
||||
//! Get the name of the current node, or nullptr if it has no name
|
||||
const char * name() const
|
||||
{
|
||||
if( itsType == Member && (itsMemberItBegin + itsIndex) != itsMemberItEnd )
|
||||
return itsMemberItBegin[itsIndex].name.GetString();
|
||||
else
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
//! Adjust our position such that we are at the node with the given name
|
||||
/*! @throws Exception if no such named node exists */
|
||||
inline void search( const char * searchName )
|
||||
{
|
||||
const auto len = std::strlen( searchName );
|
||||
size_t index = 0;
|
||||
for( auto it = itsMemberItBegin; it != itsMemberItEnd; ++it, ++index )
|
||||
{
|
||||
const auto currentName = it->name.GetString();
|
||||
if( ( std::strncmp( searchName, currentName, len ) == 0 ) &&
|
||||
( std::strlen( currentName ) == len ) )
|
||||
{
|
||||
itsIndex = index;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
throw Exception("JSON Parsing failed - provided NVP not found");
|
||||
}
|
||||
|
||||
private:
|
||||
MemberIterator itsMemberItBegin, itsMemberItEnd; //!< The member iterator (object)
|
||||
ValueIterator itsValueItBegin, itsValueItEnd; //!< The value iterator (array)
|
||||
size_t itsIndex; //!< The current index of this iterator
|
||||
enum Type {Value, Member, Null_} itsType; //!< Whether this holds values (array) or members (objects) or nothing
|
||||
};
|
||||
|
||||
//! Searches for the expectedName node if it doesn't match the actualName
|
||||
/*! This needs to be called before every load or node start occurs. This function will
|
||||
check to see if an NVP has been provided (with setNextName) and if so, see if that name matches the actual
|
||||
next name given. If the names do not match, it will search in the current level of the JSON for that name.
|
||||
If the name is not found, an exception will be thrown.
|
||||
|
||||
Resets the NVP name after called.
|
||||
|
||||
@throws Exception if an expectedName is given and not found */
|
||||
inline void search()
|
||||
{
|
||||
// The name an NVP provided with setNextName()
|
||||
if( itsNextName )
|
||||
{
|
||||
// The actual name of the current node
|
||||
auto const actualName = itsIteratorStack.back().name();
|
||||
|
||||
// Do a search if we don't see a name coming up, or if the names don't match
|
||||
if( !actualName || std::strcmp( itsNextName, actualName ) != 0 )
|
||||
itsIteratorStack.back().search( itsNextName );
|
||||
}
|
||||
|
||||
itsNextName = nullptr;
|
||||
}
|
||||
|
||||
public:
|
||||
//! Starts a new node, going into its proper iterator
|
||||
/*! This places an iterator for the next node to be parsed onto the iterator stack. If the next
|
||||
node is an array, this will be a value iterator, otherwise it will be a member iterator.
|
||||
|
||||
By default our strategy is to start with the document root node and then recursively iterate through
|
||||
all children in the order they show up in the document.
|
||||
We don't need to know NVPs to do this; we'll just blindly load in the order things appear in.
|
||||
|
||||
If we were given an NVP, we will search for it if it does not match our the name of the next node
|
||||
that would normally be loaded. This functionality is provided by search(). */
|
||||
void startNode()
|
||||
{
|
||||
search();
|
||||
|
||||
if(itsIteratorStack.back().value().IsArray())
|
||||
itsIteratorStack.emplace_back(itsIteratorStack.back().value().Begin(), itsIteratorStack.back().value().End());
|
||||
else
|
||||
itsIteratorStack.emplace_back(itsIteratorStack.back().value().MemberBegin(), itsIteratorStack.back().value().MemberEnd());
|
||||
}
|
||||
|
||||
//! Finishes the most recently started node
|
||||
void finishNode()
|
||||
{
|
||||
itsIteratorStack.pop_back();
|
||||
++itsIteratorStack.back();
|
||||
}
|
||||
|
||||
//! Retrieves the current node name
|
||||
/*! @return nullptr if no name exists */
|
||||
const char * getNodeName() const
|
||||
{
|
||||
return itsIteratorStack.back().name();
|
||||
}
|
||||
|
||||
//! Sets the name for the next node created with startNode
|
||||
void setNextName( const char * name )
|
||||
{
|
||||
itsNextName = name;
|
||||
}
|
||||
|
||||
//! Loads a value from the current node - small signed overload
|
||||
template <class T, traits::EnableIf<std::is_signed<T>::value,
|
||||
sizeof(T) < sizeof(int64_t)> = traits::sfinae> inline
|
||||
void loadValue(T & val)
|
||||
{
|
||||
search();
|
||||
|
||||
val = static_cast<T>( itsIteratorStack.back().value().GetInt() );
|
||||
++itsIteratorStack.back();
|
||||
}
|
||||
|
||||
//! Loads a value from the current node - small unsigned overload
|
||||
template <class T, traits::EnableIf<std::is_unsigned<T>::value,
|
||||
sizeof(T) < sizeof(uint64_t),
|
||||
!std::is_same<bool, T>::value> = traits::sfinae> inline
|
||||
void loadValue(T & val)
|
||||
{
|
||||
search();
|
||||
|
||||
val = static_cast<T>( itsIteratorStack.back().value().GetUint() );
|
||||
++itsIteratorStack.back();
|
||||
}
|
||||
|
||||
//! Loads a value from the current node - bool overload
|
||||
void loadValue(bool & val) { search(); val = itsIteratorStack.back().value().GetBool_(); ++itsIteratorStack.back(); }
|
||||
//! Loads a value from the current node - int64 overload
|
||||
void loadValue(int64_t & val) { search(); val = itsIteratorStack.back().value().GetInt64(); ++itsIteratorStack.back(); }
|
||||
//! Loads a value from the current node - uint64 overload
|
||||
void loadValue(uint64_t & val) { search(); val = itsIteratorStack.back().value().GetUint64(); ++itsIteratorStack.back(); }
|
||||
//! Loads a value from the current node - float overload
|
||||
void loadValue(float & val) { search(); val = static_cast<float>(itsIteratorStack.back().value().GetDouble()); ++itsIteratorStack.back(); }
|
||||
//! Loads a value from the current node - double overload
|
||||
void loadValue(double & val) { search(); val = itsIteratorStack.back().value().GetDouble(); ++itsIteratorStack.back(); }
|
||||
//! Loads a value from the current node - string overload
|
||||
void loadValue(std::string & val) { search(); val = itsIteratorStack.back().value().GetString(); ++itsIteratorStack.back(); }
|
||||
|
||||
// Special cases to handle various flavors of long, which tend to conflict with
|
||||
// the int32_t or int64_t on various compiler/OS combinations. MSVC doesn't need any of this.
|
||||
#ifndef _MSC_VER
|
||||
private:
|
||||
//! 32 bit signed long loading from current node
|
||||
template <class T> inline
|
||||
typename std::enable_if<sizeof(T) == sizeof(std::int32_t) && std::is_signed<T>::value, void>::type
|
||||
loadLong(T & l){ loadValue( reinterpret_cast<std::int32_t&>( l ) ); }
|
||||
|
||||
//! non 32 bit signed long loading from current node
|
||||
template <class T> inline
|
||||
typename std::enable_if<sizeof(T) == sizeof(std::int64_t) && std::is_signed<T>::value, void>::type
|
||||
loadLong(T & l){ loadValue( reinterpret_cast<std::int64_t&>( l ) ); }
|
||||
|
||||
//! 32 bit unsigned long loading from current node
|
||||
template <class T> inline
|
||||
typename std::enable_if<sizeof(T) == sizeof(std::uint32_t) && !std::is_signed<T>::value, void>::type
|
||||
loadLong(T & lu){ loadValue( reinterpret_cast<std::uint32_t&>( lu ) ); }
|
||||
|
||||
//! non 32 bit unsigned long loading from current node
|
||||
template <class T> inline
|
||||
typename std::enable_if<sizeof(T) == sizeof(std::uint64_t) && !std::is_signed<T>::value, void>::type
|
||||
loadLong(T & lu){ loadValue( reinterpret_cast<std::uint64_t&>( lu ) ); }
|
||||
|
||||
public:
|
||||
//! Serialize a long if it would not be caught otherwise
|
||||
template <class T> inline
|
||||
typename std::enable_if<std::is_same<T, long>::value &&
|
||||
!std::is_same<T, std::int32_t>::value &&
|
||||
!std::is_same<T, std::int64_t>::value, void>::type
|
||||
loadValue( T & t ){ loadLong(t); }
|
||||
|
||||
//! Serialize an unsigned long if it would not be caught otherwise
|
||||
template <class T> inline
|
||||
typename std::enable_if<std::is_same<T, unsigned long>::value &&
|
||||
!std::is_same<T, std::uint32_t>::value &&
|
||||
!std::is_same<T, std::uint64_t>::value, void>::type
|
||||
loadValue( T & t ){ loadLong(t); }
|
||||
#endif // _MSC_VER
|
||||
|
||||
private:
|
||||
//! Convert a string to a long long
|
||||
void stringToNumber( std::string const & str, long long & val ) { val = std::stoll( str ); }
|
||||
//! Convert a string to an unsigned long long
|
||||
void stringToNumber( std::string const & str, unsigned long long & val ) { val = std::stoull( str ); }
|
||||
//! Convert a string to a long double
|
||||
void stringToNumber( std::string const & str, long double & val ) { val = std::stold( str ); }
|
||||
|
||||
public:
|
||||
//! Loads a value from the current node - long double and long long overloads
|
||||
template <class T, traits::EnableIf<std::is_arithmetic<T>::value,
|
||||
!std::is_same<T, long>::value,
|
||||
!std::is_same<T, unsigned long>::value,
|
||||
!std::is_same<T, std::int64_t>::value,
|
||||
!std::is_same<T, std::uint64_t>::value,
|
||||
(sizeof(T) >= sizeof(long double) || sizeof(T) >= sizeof(long long))> = traits::sfinae>
|
||||
inline void loadValue(T & val)
|
||||
{
|
||||
std::string encoded;
|
||||
loadValue( encoded );
|
||||
stringToNumber( encoded, val );
|
||||
}
|
||||
|
||||
//! Loads the size for a SizeTag
|
||||
void loadSize(size_type & size)
|
||||
{
|
||||
size = (itsIteratorStack.rbegin() + 1)->value().Size();
|
||||
}
|
||||
|
||||
//! @}
|
||||
|
||||
private:
|
||||
const char * itsNextName; //!< Next name set by NVP
|
||||
ReadStream itsReadStream; //!< Rapidjson write stream
|
||||
std::vector<Iterator> itsIteratorStack; //!< 'Stack' of rapidJSON iterators
|
||||
rapidjson::Document itsDocument; //!< Rapidjson document
|
||||
};
|
||||
|
||||
// ######################################################################
|
||||
// JSONArchive prologue and epilogue functions
|
||||
// ######################################################################
|
||||
|
||||
// ######################################################################
|
||||
//! Prologue for NVPs for JSON archives
|
||||
/*! NVPs do not start or finish nodes - they just set up the names */
|
||||
template <class T> inline
|
||||
void prologue( JSONOutputArchive &, NameValuePair<T> const & )
|
||||
{ }
|
||||
|
||||
//! Prologue for NVPs for JSON archives
|
||||
template <class T> inline
|
||||
void prologue( JSONInputArchive &, NameValuePair<T> const & )
|
||||
{ }
|
||||
|
||||
// ######################################################################
|
||||
//! Epilogue for NVPs for JSON archives
|
||||
/*! NVPs do not start or finish nodes - they just set up the names */
|
||||
template <class T> inline
|
||||
void epilogue( JSONOutputArchive &, NameValuePair<T> const & )
|
||||
{ }
|
||||
|
||||
//! Epilogue for NVPs for JSON archives
|
||||
/*! NVPs do not start or finish nodes - they just set up the names */
|
||||
template <class T> inline
|
||||
void epilogue( JSONInputArchive &, NameValuePair<T> const & )
|
||||
{ }
|
||||
|
||||
// ######################################################################
|
||||
//! Prologue for SizeTags for JSON archives
|
||||
/*! SizeTags are strictly ignored for JSON, they just indicate
|
||||
that the current node should be made into an array */
|
||||
template <class T> inline
|
||||
void prologue( JSONOutputArchive & ar, SizeTag<T> const & )
|
||||
{
|
||||
ar.makeArray();
|
||||
}
|
||||
|
||||
//! Prologue for SizeTags for JSON archives
|
||||
template <class T> inline
|
||||
void prologue( JSONInputArchive &, SizeTag<T> const & )
|
||||
{ }
|
||||
|
||||
// ######################################################################
|
||||
//! Epilogue for SizeTags for JSON archives
|
||||
/*! SizeTags are strictly ignored for JSON */
|
||||
template <class T> inline
|
||||
void epilogue( JSONOutputArchive &, SizeTag<T> const & )
|
||||
{ }
|
||||
|
||||
//! Epilogue for SizeTags for JSON archives
|
||||
template <class T> inline
|
||||
void epilogue( JSONInputArchive &, SizeTag<T> const & )
|
||||
{ }
|
||||
|
||||
// ######################################################################
|
||||
//! Prologue for all other types for JSON archives (except minimal types)
|
||||
/*! Starts a new node, named either automatically or by some NVP,
|
||||
that may be given data by the type about to be archived
|
||||
|
||||
Minimal types do not start or finish nodes */
|
||||
template <class T, traits::DisableIf<std::is_arithmetic<T>::value ||
|
||||
traits::has_minimal_base_class_serialization<T, traits::has_minimal_output_serialization, JSONOutputArchive>::value ||
|
||||
traits::has_minimal_output_serialization<T, JSONOutputArchive>::value> = traits::sfinae>
|
||||
inline void prologue( JSONOutputArchive & ar, T const & )
|
||||
{
|
||||
ar.startNode();
|
||||
}
|
||||
|
||||
//! Prologue for all other types for JSON archives
|
||||
template <class T, traits::DisableIf<std::is_arithmetic<T>::value ||
|
||||
traits::has_minimal_base_class_serialization<T, traits::has_minimal_input_serialization, JSONInputArchive>::value ||
|
||||
traits::has_minimal_input_serialization<T, JSONInputArchive>::value> = traits::sfinae>
|
||||
inline void prologue( JSONInputArchive & ar, T const & )
|
||||
{
|
||||
ar.startNode();
|
||||
}
|
||||
|
||||
// ######################################################################
|
||||
//! Epilogue for all other types other for JSON archives (except minimal types
|
||||
/*! Finishes the node created in the prologue
|
||||
|
||||
Minimal types do not start or finish nodes */
|
||||
template <class T, traits::DisableIf<std::is_arithmetic<T>::value ||
|
||||
traits::has_minimal_base_class_serialization<T, traits::has_minimal_output_serialization, JSONOutputArchive>::value ||
|
||||
traits::has_minimal_output_serialization<T, JSONOutputArchive>::value> = traits::sfinae>
|
||||
inline void epilogue( JSONOutputArchive & ar, T const & )
|
||||
{
|
||||
ar.finishNode();
|
||||
}
|
||||
|
||||
//! Epilogue for all other types other for JSON archives
|
||||
template <class T, traits::DisableIf<std::is_arithmetic<T>::value ||
|
||||
traits::has_minimal_base_class_serialization<T, traits::has_minimal_input_serialization, JSONInputArchive>::value ||
|
||||
traits::has_minimal_input_serialization<T, JSONInputArchive>::value> = traits::sfinae>
|
||||
inline void epilogue( JSONInputArchive & ar, T const & )
|
||||
{
|
||||
ar.finishNode();
|
||||
}
|
||||
|
||||
// ######################################################################
|
||||
//! Prologue for arithmetic types for JSON archives
|
||||
template <class T, traits::EnableIf<std::is_arithmetic<T>::value> = traits::sfinae> inline
|
||||
void prologue( JSONOutputArchive & ar, T const & )
|
||||
{
|
||||
ar.writeName();
|
||||
}
|
||||
|
||||
//! Prologue for arithmetic types for JSON archives
|
||||
template <class T, traits::EnableIf<std::is_arithmetic<T>::value> = traits::sfinae> inline
|
||||
void prologue( JSONInputArchive &, T const & )
|
||||
{ }
|
||||
|
||||
// ######################################################################
|
||||
//! Epilogue for arithmetic types for JSON archives
|
||||
template <class T, traits::EnableIf<std::is_arithmetic<T>::value> = traits::sfinae> inline
|
||||
void epilogue( JSONOutputArchive &, T const & )
|
||||
{ }
|
||||
|
||||
//! Epilogue for arithmetic types for JSON archives
|
||||
template <class T, traits::EnableIf<std::is_arithmetic<T>::value> = traits::sfinae> inline
|
||||
void epilogue( JSONInputArchive &, T const & )
|
||||
{ }
|
||||
|
||||
// ######################################################################
|
||||
//! Prologue for strings for JSON archives
|
||||
template<class CharT, class Traits, class Alloc> inline
|
||||
void prologue(JSONOutputArchive & ar, std::basic_string<CharT, Traits, Alloc> const &)
|
||||
{
|
||||
ar.writeName();
|
||||
}
|
||||
|
||||
//! Prologue for strings for JSON archives
|
||||
template<class CharT, class Traits, class Alloc> inline
|
||||
void prologue(JSONInputArchive &, std::basic_string<CharT, Traits, Alloc> const &)
|
||||
{ }
|
||||
|
||||
// ######################################################################
|
||||
//! Epilogue for strings for JSON archives
|
||||
template<class CharT, class Traits, class Alloc> inline
|
||||
void epilogue(JSONOutputArchive &, std::basic_string<CharT, Traits, Alloc> const &)
|
||||
{ }
|
||||
|
||||
//! Epilogue for strings for JSON archives
|
||||
template<class CharT, class Traits, class Alloc> inline
|
||||
void epilogue(JSONInputArchive &, std::basic_string<CharT, Traits, Alloc> const &)
|
||||
{ }
|
||||
|
||||
// ######################################################################
|
||||
// Common JSONArchive serialization functions
|
||||
// ######################################################################
|
||||
//! Serializing NVP types to JSON
|
||||
template <class T> inline
|
||||
void CEREAL_SAVE_FUNCTION_NAME( JSONOutputArchive & ar, NameValuePair<T> const & t )
|
||||
{
|
||||
ar.setNextName( t.name );
|
||||
ar( t.value );
|
||||
}
|
||||
|
||||
template <class T> inline
|
||||
void CEREAL_LOAD_FUNCTION_NAME( JSONInputArchive & ar, NameValuePair<T> & t )
|
||||
{
|
||||
ar.setNextName( t.name );
|
||||
ar( t.value );
|
||||
}
|
||||
|
||||
//! Saving for arithmetic to JSON
|
||||
template <class T, traits::EnableIf<std::is_arithmetic<T>::value> = traits::sfinae> inline
|
||||
void CEREAL_SAVE_FUNCTION_NAME(JSONOutputArchive & ar, T const & t)
|
||||
{
|
||||
ar.saveValue( t );
|
||||
}
|
||||
|
||||
//! Loading arithmetic from JSON
|
||||
template <class T, traits::EnableIf<std::is_arithmetic<T>::value> = traits::sfinae> inline
|
||||
void CEREAL_LOAD_FUNCTION_NAME(JSONInputArchive & ar, T & t)
|
||||
{
|
||||
ar.loadValue( t );
|
||||
}
|
||||
|
||||
//! saving string to JSON
|
||||
template<class CharT, class Traits, class Alloc> inline
|
||||
void CEREAL_SAVE_FUNCTION_NAME(JSONOutputArchive & ar, std::basic_string<CharT, Traits, Alloc> const & str)
|
||||
{
|
||||
ar.saveValue( str );
|
||||
}
|
||||
|
||||
//! loading string from JSON
|
||||
template<class CharT, class Traits, class Alloc> inline
|
||||
void CEREAL_LOAD_FUNCTION_NAME(JSONInputArchive & ar, std::basic_string<CharT, Traits, Alloc> & str)
|
||||
{
|
||||
ar.loadValue( str );
|
||||
}
|
||||
|
||||
// ######################################################################
|
||||
//! Saving SizeTags to JSON
|
||||
template <class T> inline
|
||||
void CEREAL_SAVE_FUNCTION_NAME( JSONOutputArchive &, SizeTag<T> const & )
|
||||
{
|
||||
// nothing to do here, we don't explicitly save the size
|
||||
}
|
||||
|
||||
//! Loading SizeTags from JSON
|
||||
template <class T> inline
|
||||
void CEREAL_LOAD_FUNCTION_NAME( JSONInputArchive & ar, SizeTag<T> & st )
|
||||
{
|
||||
ar.loadSize( st.size );
|
||||
}
|
||||
} // namespace cereal
|
||||
|
||||
// register archives for polymorphic support
|
||||
CEREAL_REGISTER_ARCHIVE(cereal::JSONInputArchive)
|
||||
CEREAL_REGISTER_ARCHIVE(cereal::JSONOutputArchive)
|
||||
|
||||
// tie input and output archives together
|
||||
CEREAL_SETUP_ARCHIVE_TRAITS(cereal::JSONInputArchive, cereal::JSONOutputArchive)
|
||||
|
||||
#endif // CEREAL_ARCHIVES_JSON_HPP_
|
||||
245
libs/cereal/cereal/archives/portable_binary.hpp
Normal file
245
libs/cereal/cereal/archives/portable_binary.hpp
Normal file
@ -0,0 +1,245 @@
|
||||
/*! \file binary.hpp
|
||||
\brief Binary input and output archives */
|
||||
/*
|
||||
Copyright (c) 2014, Randolph Voorhies, Shane Grant
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of cereal nor the
|
||||
names of its contributors may be used to endorse or promote products
|
||||
derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL RANDOLPH VOORHIES OR SHANE GRANT BE LIABLE FOR ANY
|
||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
#ifndef CEREAL_ARCHIVES_PORTABLE_BINARY_HPP_
|
||||
#define CEREAL_ARCHIVES_PORTABLE_BINARY_HPP_
|
||||
|
||||
#include <cereal/cereal.hpp>
|
||||
#include <sstream>
|
||||
#include <limits>
|
||||
|
||||
namespace cereal
|
||||
{
|
||||
namespace portable_binary_detail
|
||||
{
|
||||
//! Returns true if the current machine is little endian
|
||||
/*! @ingroup Internal */
|
||||
inline bool is_little_endian()
|
||||
{
|
||||
static std::int32_t test = 1;
|
||||
return *reinterpret_cast<std::int8_t*>( &test ) == 1;
|
||||
}
|
||||
|
||||
//! Swaps the order of bytes for some chunk of memory
|
||||
/*! @param data The data as a uint8_t pointer
|
||||
@tparam DataSize The true size of the data
|
||||
@ingroup Internal */
|
||||
template <std::size_t DataSize>
|
||||
inline void swap_bytes( std::uint8_t * data )
|
||||
{
|
||||
for( std::size_t i = 0, end = DataSize / 2; i < end; ++i )
|
||||
std::swap( data[i], data[DataSize - i - 1] );
|
||||
}
|
||||
} // end namespace portable_binary_detail
|
||||
|
||||
// ######################################################################
|
||||
//! An output archive designed to save data in a compact binary representation portable over different architectures
|
||||
/*! This archive outputs data to a stream in an extremely compact binary
|
||||
representation with as little extra metadata as possible.
|
||||
|
||||
This archive will record the endianness of the data and assuming that
|
||||
the user takes care of ensuring serialized types are the same size
|
||||
across machines, is portable over different architectures.
|
||||
|
||||
When using a binary archive and a file stream, you must use the
|
||||
std::ios::binary format flag to avoid having your data altered
|
||||
inadvertently.
|
||||
|
||||
\warning This archive has not been thoroughly tested across different architectures.
|
||||
Please report any issues, optimizations, or feature requests at
|
||||
<a href="www.github.com/USCiLab/cereal">the project github</a>.
|
||||
|
||||
\ingroup Archives */
|
||||
class PortableBinaryOutputArchive : public OutputArchive<PortableBinaryOutputArchive, AllowEmptyClassElision>
|
||||
{
|
||||
public:
|
||||
//! Construct, outputting to the provided stream
|
||||
/*! @param stream The stream to output to. Can be a stringstream, a file stream, or
|
||||
even cout! */
|
||||
PortableBinaryOutputArchive(std::ostream & stream) :
|
||||
OutputArchive<PortableBinaryOutputArchive, AllowEmptyClassElision>(this),
|
||||
itsStream(stream)
|
||||
{
|
||||
this->operator()( portable_binary_detail::is_little_endian() );
|
||||
}
|
||||
|
||||
//! Writes size bytes of data to the output stream
|
||||
void saveBinary( const void * data, std::size_t size )
|
||||
{
|
||||
auto const writtenSize = static_cast<std::size_t>( itsStream.rdbuf()->sputn( reinterpret_cast<const char*>( data ), size ) );
|
||||
|
||||
if(writtenSize != size)
|
||||
throw Exception("Failed to write " + std::to_string(size) + " bytes to output stream! Wrote " + std::to_string(writtenSize));
|
||||
}
|
||||
|
||||
private:
|
||||
std::ostream & itsStream;
|
||||
};
|
||||
|
||||
// ######################################################################
|
||||
//! An input archive designed to load data saved using PortableBinaryOutputArchive
|
||||
/*! This archive outputs data to a stream in an extremely compact binary
|
||||
representation with as little extra metadata as possible.
|
||||
|
||||
This archive will load the endianness of the serialized data and
|
||||
if necessary transform it to match that of the local machine. This comes
|
||||
at a significant performance cost compared to non portable archives if
|
||||
the transformation is necessary, and also causes a small performance hit
|
||||
even if it is not necessary.
|
||||
|
||||
It is recommended to use portable archives only if you know that you will
|
||||
be sending binary data to machines with different endianness.
|
||||
|
||||
The archive will do nothing to ensure types are the same size - that is
|
||||
the responsibility of the user.
|
||||
|
||||
When using a binary archive and a file stream, you must use the
|
||||
std::ios::binary format flag to avoid having your data altered
|
||||
inadvertently.
|
||||
|
||||
\warning This archive has not been thoroughly tested across different architectures.
|
||||
Please report any issues, optimizations, or feature requests at
|
||||
<a href="www.github.com/USCiLab/cereal">the project github</a>.
|
||||
|
||||
\ingroup Archives */
|
||||
class PortableBinaryInputArchive : public InputArchive<PortableBinaryInputArchive, AllowEmptyClassElision>
|
||||
{
|
||||
public:
|
||||
//! Construct, loading from the provided stream
|
||||
/*! @param stream The stream to read from. */
|
||||
PortableBinaryInputArchive(std::istream & stream) :
|
||||
InputArchive<PortableBinaryInputArchive, AllowEmptyClassElision>(this),
|
||||
itsStream(stream),
|
||||
itsConvertEndianness( false )
|
||||
{
|
||||
bool streamLittleEndian;
|
||||
this->operator()( streamLittleEndian );
|
||||
itsConvertEndianness = portable_binary_detail::is_little_endian() ^ streamLittleEndian;
|
||||
}
|
||||
|
||||
//! Reads size bytes of data from the input stream
|
||||
/*! @param data The data to save
|
||||
@param size The number of bytes in the data
|
||||
@tparam DataSize T The size of the actual type of the data elements being loaded */
|
||||
template <std::size_t DataSize>
|
||||
void loadBinary( void * const data, std::size_t size )
|
||||
{
|
||||
// load data
|
||||
auto const readSize = static_cast<std::size_t>( itsStream.rdbuf()->sgetn( reinterpret_cast<char*>( data ), size ) );
|
||||
|
||||
if(readSize != size)
|
||||
throw Exception("Failed to read " + std::to_string(size) + " bytes from input stream! Read " + std::to_string(readSize));
|
||||
|
||||
// flip bits if needed
|
||||
if( itsConvertEndianness )
|
||||
{
|
||||
std::uint8_t * ptr = reinterpret_cast<std::uint8_t*>( data );
|
||||
for( std::size_t i = 0; i < size; i += DataSize )
|
||||
portable_binary_detail::swap_bytes<DataSize>( ptr );
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
std::istream & itsStream;
|
||||
bool itsConvertEndianness; //!< If set to true, we will need to swap bytes upon loading
|
||||
};
|
||||
|
||||
// ######################################################################
|
||||
// Common BinaryArchive serialization functions
|
||||
|
||||
//! Saving for POD types to portable binary
|
||||
template<class T> inline
|
||||
typename std::enable_if<std::is_arithmetic<T>::value, void>::type
|
||||
CEREAL_SAVE_FUNCTION_NAME(PortableBinaryOutputArchive & ar, T const & t)
|
||||
{
|
||||
static_assert( !std::is_floating_point<T>::value ||
|
||||
(std::is_floating_point<T>::value && std::numeric_limits<T>::is_iec559),
|
||||
"Portable binary only supports IEEE 754 standardized floating point" );
|
||||
ar.saveBinary(std::addressof(t), sizeof(t));
|
||||
}
|
||||
|
||||
//! Loading for POD types from portable binary
|
||||
template<class T> inline
|
||||
typename std::enable_if<std::is_arithmetic<T>::value, void>::type
|
||||
CEREAL_LOAD_FUNCTION_NAME(PortableBinaryInputArchive & ar, T & t)
|
||||
{
|
||||
static_assert( !std::is_floating_point<T>::value ||
|
||||
(std::is_floating_point<T>::value && std::numeric_limits<T>::is_iec559),
|
||||
"Portable binary only supports IEEE 754 standardized floating point" );
|
||||
ar.template loadBinary<sizeof(T)>(std::addressof(t), sizeof(t));
|
||||
}
|
||||
|
||||
//! Serializing NVP types to portable binary
|
||||
template <class Archive, class T> inline
|
||||
CEREAL_ARCHIVE_RESTRICT(PortableBinaryInputArchive, PortableBinaryOutputArchive)
|
||||
CEREAL_SERIALIZE_FUNCTION_NAME( Archive & ar, NameValuePair<T> & t )
|
||||
{
|
||||
ar( t.value );
|
||||
}
|
||||
|
||||
//! Serializing SizeTags to portable binary
|
||||
template <class Archive, class T> inline
|
||||
CEREAL_ARCHIVE_RESTRICT(PortableBinaryInputArchive, PortableBinaryOutputArchive)
|
||||
CEREAL_SERIALIZE_FUNCTION_NAME( Archive & ar, SizeTag<T> & t )
|
||||
{
|
||||
ar( t.size );
|
||||
}
|
||||
|
||||
//! Saving binary data to portable binary
|
||||
template <class T> inline
|
||||
void CEREAL_SAVE_FUNCTION_NAME(PortableBinaryOutputArchive & ar, BinaryData<T> const & bd)
|
||||
{
|
||||
typedef typename std::remove_pointer<T>::type TT;
|
||||
static_assert( !std::is_floating_point<TT>::value ||
|
||||
(std::is_floating_point<TT>::value && std::numeric_limits<TT>::is_iec559),
|
||||
"Portable binary only supports IEEE 754 standardized floating point" );
|
||||
|
||||
ar.saveBinary( bd.data, static_cast<std::size_t>( bd.size ) );
|
||||
}
|
||||
|
||||
//! Loading binary data from portable binary
|
||||
template <class T> inline
|
||||
void CEREAL_LOAD_FUNCTION_NAME(PortableBinaryInputArchive & ar, BinaryData<T> & bd)
|
||||
{
|
||||
typedef typename std::remove_pointer<T>::type TT;
|
||||
static_assert( !std::is_floating_point<TT>::value ||
|
||||
(std::is_floating_point<TT>::value && std::numeric_limits<TT>::is_iec559),
|
||||
"Portable binary only supports IEEE 754 standardized floating point" );
|
||||
|
||||
ar.template loadBinary<sizeof(TT)>( bd.data, static_cast<std::size_t>( bd.size ) );
|
||||
}
|
||||
} // namespace cereal
|
||||
|
||||
// register archives for polymorphic support
|
||||
CEREAL_REGISTER_ARCHIVE(cereal::PortableBinaryOutputArchive)
|
||||
CEREAL_REGISTER_ARCHIVE(cereal::PortableBinaryInputArchive)
|
||||
|
||||
// tie input and output archives together
|
||||
CEREAL_SETUP_ARCHIVE_TRAITS(cereal::PortableBinaryInputArchive, cereal::PortableBinaryOutputArchive)
|
||||
|
||||
#endif // CEREAL_ARCHIVES_PORTABLE_BINARY_HPP_
|
||||
882
libs/cereal/cereal/archives/xml.hpp
Normal file
882
libs/cereal/cereal/archives/xml.hpp
Normal file
@ -0,0 +1,882 @@
|
||||
/*! \file xml.hpp
|
||||
\brief XML input and output archives */
|
||||
/*
|
||||
Copyright (c) 2014, Randolph Voorhies, Shane Grant
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of cereal nor the
|
||||
names of its contributors may be used to endorse or promote products
|
||||
derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL RANDOLPH VOORHIES OR SHANE GRANT BE LIABLE FOR ANY
|
||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
#ifndef CEREAL_ARCHIVES_XML_HPP_
|
||||
#define CEREAL_ARCHIVES_XML_HPP_
|
||||
#include <cereal/cereal.hpp>
|
||||
#include <cereal/details/util.hpp>
|
||||
|
||||
#include <cereal/external/rapidxml/rapidxml.hpp>
|
||||
#include <cereal/external/rapidxml/rapidxml_print.hpp>
|
||||
#include <cereal/external/base64.hpp>
|
||||
|
||||
#include <sstream>
|
||||
#include <stack>
|
||||
#include <vector>
|
||||
#include <limits>
|
||||
#include <string>
|
||||
#include <cstring>
|
||||
#include <cmath>
|
||||
|
||||
namespace cereal
|
||||
{
|
||||
namespace xml_detail
|
||||
{
|
||||
#ifndef CEREAL_XML_STRING_VALUE
|
||||
//! The default name for the root node in a cereal xml archive.
|
||||
/*! You can define CEREAL_XML_STRING_VALUE to be different assuming you do so
|
||||
before this file is included. */
|
||||
#define CEREAL_XML_STRING_VALUE "cereal"
|
||||
#endif // CEREAL_XML_STRING_VALUE
|
||||
|
||||
//! The name given to the root node in a cereal xml archive
|
||||
static const char * CEREAL_XML_STRING = CEREAL_XML_STRING_VALUE;
|
||||
|
||||
//! Returns true if the character is whitespace
|
||||
inline bool isWhitespace( char c )
|
||||
{
|
||||
return c == ' ' || c == '\t' || c == '\n' || c == '\r';
|
||||
}
|
||||
}
|
||||
|
||||
// ######################################################################
|
||||
//! An output archive designed to save data to XML
|
||||
/*! This archive uses RapidXML to build an in memory XML tree of the
|
||||
data it serializes before outputting it to its stream upon destruction.
|
||||
The envisioned way of using this archive is in an RAII fashion, letting
|
||||
the automatic destruction of the object cause the flush to its stream.
|
||||
|
||||
XML archives provides a human readable output but at decreased
|
||||
performance (both in time and space) compared to binary archives.
|
||||
|
||||
XML benefits greatly from name-value pairs, which if present, will
|
||||
name the nodes in the output. If these are not present, each level
|
||||
of the output tree will be given an automatically generated delimited name.
|
||||
|
||||
The precision of the output archive controls the number of decimals output
|
||||
for floating point numbers and should be sufficiently large (i.e. at least 20)
|
||||
if there is a desire to have binary equality between the numbers output and
|
||||
those read in. In general you should expect a loss of precision when going
|
||||
from floating point to text and back.
|
||||
|
||||
XML archives can optionally print the type of everything they serialize, which
|
||||
adds an attribute to each node.
|
||||
|
||||
XML archives do not output the size information for any dynamically sized structure
|
||||
and instead infer it from the number of children for a node. This means that data
|
||||
can be hand edited for dynamic sized structures and will still be readable. This
|
||||
is accomplished through the cereal::SizeTag object, which will also add an attribute
|
||||
to its parent field.
|
||||
\ingroup Archives */
|
||||
class XMLOutputArchive : public OutputArchive<XMLOutputArchive>, public traits::TextArchive
|
||||
{
|
||||
public:
|
||||
/*! @name Common Functionality
|
||||
Common use cases for directly interacting with an XMLOutputArchive */
|
||||
//! @{
|
||||
|
||||
//! A class containing various advanced options for the XML archive
|
||||
class Options
|
||||
{
|
||||
public:
|
||||
//! Default options
|
||||
static Options Default(){ return Options(); }
|
||||
|
||||
//! Default options with no indentation
|
||||
static Options NoIndent(){ return Options( std::numeric_limits<double>::max_digits10, false ); }
|
||||
|
||||
//! Specify specific options for the XMLOutputArchive
|
||||
/*! @param precision The precision used for floating point numbers
|
||||
@param indent Whether to indent each line of XML
|
||||
@param outputType Whether to output the type of each serialized object as an attribute */
|
||||
explicit Options( int precision = std::numeric_limits<double>::max_digits10,
|
||||
bool indent = true,
|
||||
bool outputType = false ) :
|
||||
itsPrecision( precision ),
|
||||
itsIndent( indent ),
|
||||
itsOutputType( outputType ) { }
|
||||
|
||||
private:
|
||||
friend class XMLOutputArchive;
|
||||
int itsPrecision;
|
||||
bool itsIndent;
|
||||
bool itsOutputType;
|
||||
};
|
||||
|
||||
//! Construct, outputting to the provided stream upon destruction
|
||||
/*! @param stream The stream to output to. Note that XML is only guaranteed to flush
|
||||
its output to the stream upon destruction.
|
||||
@param options The XML specific options to use. See the Options struct
|
||||
for the values of default parameters */
|
||||
XMLOutputArchive( std::ostream & stream, Options const & options = Options::Default() ) :
|
||||
OutputArchive<XMLOutputArchive>(this),
|
||||
itsStream(stream),
|
||||
itsOutputType( options.itsOutputType ),
|
||||
itsIndent( options.itsIndent )
|
||||
{
|
||||
// rapidxml will delete all allocations when xml_document is cleared
|
||||
auto node = itsXML.allocate_node( rapidxml::node_declaration );
|
||||
node->append_attribute( itsXML.allocate_attribute( "version", "1.0" ) );
|
||||
node->append_attribute( itsXML.allocate_attribute( "encoding", "utf-8" ) );
|
||||
itsXML.append_node( node );
|
||||
|
||||
// allocate root node
|
||||
auto root = itsXML.allocate_node( rapidxml::node_element, xml_detail::CEREAL_XML_STRING );
|
||||
itsXML.append_node( root );
|
||||
itsNodes.emplace( root );
|
||||
|
||||
// set attributes on the streams
|
||||
itsStream << std::boolalpha;
|
||||
itsStream.precision( options.itsPrecision );
|
||||
itsOS << std::boolalpha;
|
||||
itsOS.precision( options.itsPrecision );
|
||||
}
|
||||
|
||||
//! Destructor, flushes the XML
|
||||
~XMLOutputArchive()
|
||||
{
|
||||
const int flags = itsIndent ? 0x0 : rapidxml::print_no_indenting;
|
||||
rapidxml::print( itsStream, itsXML, flags );
|
||||
itsXML.clear();
|
||||
}
|
||||
|
||||
//! Saves some binary data, encoded as a base64 string, with an optional name
|
||||
/*! This can be called directly by users and it will automatically create a child node for
|
||||
the current XML node, populate it with a base64 encoded string, and optionally name
|
||||
it. The node will be finished after it has been populated. */
|
||||
void saveBinaryValue( const void * data, size_t size, const char * name = nullptr )
|
||||
{
|
||||
itsNodes.top().name = name;
|
||||
|
||||
startNode();
|
||||
|
||||
auto base64string = base64::encode( reinterpret_cast<const unsigned char *>( data ), size );
|
||||
saveValue( base64string );
|
||||
|
||||
if( itsOutputType )
|
||||
itsNodes.top().node->append_attribute( itsXML.allocate_attribute( "type", "cereal binary data" ) );
|
||||
|
||||
finishNode();
|
||||
};
|
||||
|
||||
//! @}
|
||||
/*! @name Internal Functionality
|
||||
Functionality designed for use by those requiring control over the inner mechanisms of
|
||||
the XMLOutputArchive */
|
||||
//! @{
|
||||
|
||||
//! Creates a new node that is a child of the node at the top of the stack
|
||||
/*! Nodes will be given a name that has either been pre-set by a name value pair,
|
||||
or generated based upon a counter unique to the parent node. If you want to
|
||||
give a node a specific name, use setNextName prior to calling startNode.
|
||||
|
||||
The node will then be pushed onto the node stack. */
|
||||
void startNode()
|
||||
{
|
||||
// generate a name for this new node
|
||||
const auto nameString = itsNodes.top().getValueName();
|
||||
|
||||
// allocate strings for all of the data in the XML object
|
||||
auto namePtr = itsXML.allocate_string( nameString.data(), nameString.length() + 1 );
|
||||
|
||||
// insert into the XML
|
||||
auto node = itsXML.allocate_node( rapidxml::node_element, namePtr, nullptr, nameString.size() );
|
||||
itsNodes.top().node->append_node( node );
|
||||
itsNodes.emplace( node );
|
||||
}
|
||||
|
||||
//! Designates the most recently added node as finished
|
||||
void finishNode()
|
||||
{
|
||||
itsNodes.pop();
|
||||
}
|
||||
|
||||
//! Sets the name for the next node created with startNode
|
||||
void setNextName( const char * name )
|
||||
{
|
||||
itsNodes.top().name = name;
|
||||
}
|
||||
|
||||
//! Saves some data, encoded as a string, into the current top level node
|
||||
/*! The data will be be named with the most recent name if one exists,
|
||||
otherwise it will be given some default delimited value that depends upon
|
||||
the parent node */
|
||||
template <class T> inline
|
||||
void saveValue( T const & value )
|
||||
{
|
||||
itsOS.clear(); itsOS.seekp( 0, std::ios::beg );
|
||||
itsOS << value << std::ends;
|
||||
|
||||
const auto strValue = itsOS.str();
|
||||
|
||||
// If the first or last character is a whitespace, add xml:space attribute
|
||||
// the string always contains a '\0' added by std::ends, so the last character is at len-2 and an 'empty'
|
||||
// string has a length of 1 or lower
|
||||
const auto len = strValue.length();
|
||||
if ( len > 1 && ( xml_detail::isWhitespace( strValue[0] ) || xml_detail::isWhitespace( strValue[len - 2] ) ) )
|
||||
{
|
||||
itsNodes.top().node->append_attribute( itsXML.allocate_attribute( "xml:space", "preserve" ) );
|
||||
}
|
||||
|
||||
// allocate strings for all of the data in the XML object
|
||||
auto dataPtr = itsXML.allocate_string( itsOS.str().c_str(), itsOS.str().length() + 1 );
|
||||
|
||||
// insert into the XML
|
||||
itsNodes.top().node->append_node( itsXML.allocate_node( rapidxml::node_data, nullptr, dataPtr ) );
|
||||
}
|
||||
|
||||
//! Overload for uint8_t prevents them from being serialized as characters
|
||||
void saveValue( uint8_t const & value )
|
||||
{
|
||||
saveValue( static_cast<uint32_t>( value ) );
|
||||
}
|
||||
|
||||
//! Overload for int8_t prevents them from being serialized as characters
|
||||
void saveValue( int8_t const & value )
|
||||
{
|
||||
saveValue( static_cast<int32_t>( value ) );
|
||||
}
|
||||
|
||||
//! Causes the type to be appended as an attribute to the most recently made node if output type is set to true
|
||||
template <class T> inline
|
||||
void insertType()
|
||||
{
|
||||
if( !itsOutputType )
|
||||
return;
|
||||
|
||||
// generate a name for this new node
|
||||
const auto nameString = util::demangledName<T>();
|
||||
|
||||
// allocate strings for all of the data in the XML object
|
||||
auto namePtr = itsXML.allocate_string( nameString.data(), nameString.length() + 1 );
|
||||
|
||||
itsNodes.top().node->append_attribute( itsXML.allocate_attribute( "type", namePtr ) );
|
||||
}
|
||||
|
||||
//! Appends an attribute to the current top level node
|
||||
void appendAttribute( const char * name, const char * value )
|
||||
{
|
||||
auto namePtr = itsXML.allocate_string( name );
|
||||
auto valuePtr = itsXML.allocate_string( value );
|
||||
itsNodes.top().node->append_attribute( itsXML.allocate_attribute( namePtr, valuePtr ) );
|
||||
}
|
||||
|
||||
protected:
|
||||
//! A struct that contains metadata about a node
|
||||
struct NodeInfo
|
||||
{
|
||||
NodeInfo( rapidxml::xml_node<> * n = nullptr,
|
||||
const char * nm = nullptr ) :
|
||||
node( n ),
|
||||
counter( 0 ),
|
||||
name( nm )
|
||||
{ }
|
||||
|
||||
rapidxml::xml_node<> * node; //!< A pointer to this node
|
||||
size_t counter; //!< The counter for naming child nodes
|
||||
const char * name; //!< The name for the next child node
|
||||
|
||||
//! Gets the name for the next child node created from this node
|
||||
/*! The name will be automatically generated using the counter if
|
||||
a name has not been previously set. If a name has been previously
|
||||
set, that name will be returned only once */
|
||||
std::string getValueName()
|
||||
{
|
||||
if( name )
|
||||
{
|
||||
auto n = name;
|
||||
name = nullptr;
|
||||
return {n};
|
||||
}
|
||||
else
|
||||
return "value" + std::to_string( counter++ ) + "\0";
|
||||
}
|
||||
}; // NodeInfo
|
||||
|
||||
//! @}
|
||||
|
||||
private:
|
||||
std::ostream & itsStream; //!< The output stream
|
||||
rapidxml::xml_document<> itsXML; //!< The XML document
|
||||
std::stack<NodeInfo> itsNodes; //!< A stack of nodes added to the document
|
||||
std::ostringstream itsOS; //!< Used to format strings internally
|
||||
bool itsOutputType; //!< Controls whether type information is printed
|
||||
bool itsIndent; //!< Controls whether indenting is used
|
||||
}; // XMLOutputArchive
|
||||
|
||||
// ######################################################################
|
||||
//! An output archive designed to load data from XML
|
||||
/*! This archive uses RapidXML to build an in memory XML tree of the
|
||||
data in the stream it is given before loading any types serialized.
|
||||
|
||||
Input XML should have been produced by the XMLOutputArchive. Data can
|
||||
only be added to dynamically sized containers - the input archive will
|
||||
determine their size by looking at the number of child nodes. Data that
|
||||
did not originate from an XMLOutputArchive is not officially supported,
|
||||
but may be possible to use if properly formatted.
|
||||
|
||||
The XMLInputArchive does not require that nodes are loaded in the same
|
||||
order they were saved by XMLOutputArchive. Using name value pairs (NVPs),
|
||||
it is possible to load in an out of order fashion or otherwise skip/select
|
||||
specific nodes to load.
|
||||
|
||||
The default behavior of the input archive is to read sequentially starting
|
||||
with the first node and exploring its children. When a given NVP does
|
||||
not match the read in name for a node, the archive will search for that
|
||||
node at the current level and load it if it exists. After loading an out of
|
||||
order node, the archive will then proceed back to loading sequentially from
|
||||
its new position.
|
||||
|
||||
Consider this simple example where loading of some data is skipped:
|
||||
|
||||
@code{cpp}
|
||||
// imagine the input file has someData(1-9) saved in order at the top level node
|
||||
ar( someData1, someData2, someData3 ); // XML loads in the order it sees in the file
|
||||
ar( cereal::make_nvp( "hello", someData6 ) ); // NVP given does not
|
||||
// match expected NVP name, so we search
|
||||
// for the given NVP and load that value
|
||||
ar( someData7, someData8, someData9 ); // with no NVP given, loading resumes at its
|
||||
// current location, proceeding sequentially
|
||||
@endcode
|
||||
|
||||
\ingroup Archives */
|
||||
class XMLInputArchive : public InputArchive<XMLInputArchive>, public traits::TextArchive
|
||||
{
|
||||
public:
|
||||
/*! @name Common Functionality
|
||||
Common use cases for directly interacting with an XMLInputArchive */
|
||||
//! @{
|
||||
|
||||
//! Construct, reading in from the provided stream
|
||||
/*! Reads in an entire XML document from some stream and parses it as soon
|
||||
as serialization starts
|
||||
|
||||
@param stream The stream to read from. Can be a stringstream or a file. */
|
||||
XMLInputArchive( std::istream & stream ) :
|
||||
InputArchive<XMLInputArchive>( this ),
|
||||
itsData( std::istreambuf_iterator<char>( stream ), std::istreambuf_iterator<char>() )
|
||||
{
|
||||
try
|
||||
{
|
||||
itsData.push_back('\0'); // rapidxml will do terrible things without the data being null terminated
|
||||
itsXML.parse<rapidxml::parse_trim_whitespace | rapidxml::parse_no_data_nodes | rapidxml::parse_declaration_node>( reinterpret_cast<char *>( itsData.data() ) );
|
||||
}
|
||||
catch( rapidxml::parse_error const & )
|
||||
{
|
||||
//std::cerr << "-----Original-----" << std::endl;
|
||||
//stream.seekg(0);
|
||||
//std::cout << std::string( std::istreambuf_iterator<char>( stream ), std::istreambuf_iterator<char>() ) << std::endl;
|
||||
|
||||
//std::cerr << "-----Error-----" << std::endl;
|
||||
//std::cerr << e.what() << std::endl;
|
||||
//std::cerr << e.where<char>() << std::endl;
|
||||
throw Exception("XML Parsing failed - likely due to invalid characters or invalid naming");
|
||||
}
|
||||
|
||||
// Parse the root
|
||||
auto root = itsXML.first_node( xml_detail::CEREAL_XML_STRING );
|
||||
if( root == nullptr )
|
||||
throw Exception("Could not detect cereal root node - likely due to empty or invalid input");
|
||||
else
|
||||
itsNodes.emplace( root );
|
||||
}
|
||||
|
||||
//! Loads some binary data, encoded as a base64 string, optionally specified by some name
|
||||
/*! This will automatically start and finish a node to load the data, and can be called directly by
|
||||
users.
|
||||
|
||||
Note that this follows the same ordering rules specified in the class description in regards
|
||||
to loading in/out of order */
|
||||
void loadBinaryValue( void * data, size_t size, const char * name = nullptr )
|
||||
{
|
||||
setNextName( name );
|
||||
startNode();
|
||||
|
||||
std::string encoded;
|
||||
loadValue( encoded );
|
||||
|
||||
auto decoded = base64::decode( encoded );
|
||||
|
||||
if( size != decoded.size() )
|
||||
throw Exception("Decoded binary data size does not match specified size");
|
||||
|
||||
std::memcpy( data, decoded.data(), decoded.size() );
|
||||
|
||||
finishNode();
|
||||
};
|
||||
|
||||
//! @}
|
||||
/*! @name Internal Functionality
|
||||
Functionality designed for use by those requiring control over the inner mechanisms of
|
||||
the XMLInputArchive */
|
||||
//! @{
|
||||
|
||||
//! Prepares to start reading the next node
|
||||
/*! This places the next node to be parsed onto the nodes stack.
|
||||
|
||||
By default our strategy is to start with the document root node and then
|
||||
recursively iterate through all children in the order they show up in the document.
|
||||
We don't need to know NVPs do to this; we'll just blindly load in the order things appear in.
|
||||
|
||||
We check to see if the specified NVP matches what the next automatically loaded node is. If they
|
||||
match, we just continue as normal, going in order. If they don't match, we attempt to find a node
|
||||
named after the NVP that is being loaded. If that NVP does not exist, we throw an exception. */
|
||||
void startNode()
|
||||
{
|
||||
auto next = itsNodes.top().child; // By default we would move to the next child node
|
||||
auto const expectedName = itsNodes.top().name; // this is the expected name from the NVP, if provided
|
||||
|
||||
// If we were given an NVP name, look for it in the current level of the document.
|
||||
// We only need to do this if either we have exhausted the siblings of the current level or
|
||||
// the NVP name does not match the name of the node we would normally read next
|
||||
if( expectedName && ( next == nullptr || std::strcmp( next->name(), expectedName ) != 0 ) )
|
||||
{
|
||||
next = itsNodes.top().search( expectedName );
|
||||
|
||||
if( next == nullptr )
|
||||
throw Exception("XML Parsing failed - provided NVP not found");
|
||||
}
|
||||
|
||||
itsNodes.emplace( next );
|
||||
}
|
||||
|
||||
//! Finishes reading the current node
|
||||
void finishNode()
|
||||
{
|
||||
// remove current
|
||||
itsNodes.pop();
|
||||
|
||||
// advance parent
|
||||
itsNodes.top().advance();
|
||||
|
||||
// Reset name
|
||||
itsNodes.top().name = nullptr;
|
||||
}
|
||||
|
||||
//! Retrieves the current node name
|
||||
//! will return @c nullptr if the node does not have a name
|
||||
const char * getNodeName() const
|
||||
{
|
||||
return itsNodes.top().node->name();
|
||||
}
|
||||
|
||||
//! Sets the name for the next node created with startNode
|
||||
void setNextName( const char * name )
|
||||
{
|
||||
itsNodes.top().name = name;
|
||||
}
|
||||
|
||||
//! Loads a bool from the current top node
|
||||
template <class T, traits::EnableIf<std::is_unsigned<T>::value,
|
||||
std::is_same<T, bool>::value> = traits::sfinae> inline
|
||||
void loadValue( T & value )
|
||||
{
|
||||
std::istringstream is( itsNodes.top().node->value() );
|
||||
is.setf( std::ios::boolalpha );
|
||||
is >> value;
|
||||
}
|
||||
|
||||
//! Loads a char (signed or unsigned) from the current top node
|
||||
template <class T, traits::EnableIf<std::is_integral<T>::value,
|
||||
!std::is_same<T, bool>::value,
|
||||
sizeof(T) == sizeof(char)> = traits::sfinae> inline
|
||||
void loadValue( T & value )
|
||||
{
|
||||
value = *reinterpret_cast<T*>( itsNodes.top().node->value() );
|
||||
}
|
||||
|
||||
//! Load an int8_t from the current top node (ensures we parse entire number)
|
||||
void loadValue( int8_t & value )
|
||||
{
|
||||
int32_t val; loadValue( val ); value = static_cast<int8_t>( val );
|
||||
}
|
||||
|
||||
//! Load a uint8_t from the current top node (ensures we parse entire number)
|
||||
void loadValue( uint8_t & value )
|
||||
{
|
||||
uint32_t val; loadValue( val ); value = static_cast<uint8_t>( val );
|
||||
}
|
||||
|
||||
//! Loads a type best represented as an unsigned long from the current top node
|
||||
template <class T, traits::EnableIf<std::is_unsigned<T>::value,
|
||||
!std::is_same<T, bool>::value,
|
||||
!std::is_same<T, unsigned char>::value,
|
||||
sizeof(T) < sizeof(long long)> = traits::sfinae> inline
|
||||
void loadValue( T & value )
|
||||
{
|
||||
value = static_cast<T>( std::stoul( itsNodes.top().node->value() ) );
|
||||
}
|
||||
|
||||
//! Loads a type best represented as an unsigned long long from the current top node
|
||||
template <class T, traits::EnableIf<std::is_unsigned<T>::value,
|
||||
!std::is_same<T, bool>::value,
|
||||
sizeof(T) >= sizeof(long long)> = traits::sfinae> inline
|
||||
void loadValue( T & value )
|
||||
{
|
||||
value = static_cast<T>( std::stoull( itsNodes.top().node->value() ) );
|
||||
}
|
||||
|
||||
//! Loads a type best represented as an int from the current top node
|
||||
template <class T, traits::EnableIf<std::is_signed<T>::value,
|
||||
!std::is_same<T, char>::value,
|
||||
sizeof(T) <= sizeof(int)> = traits::sfinae> inline
|
||||
void loadValue( T & value )
|
||||
{
|
||||
value = static_cast<T>( std::stoi( itsNodes.top().node->value() ) );
|
||||
}
|
||||
|
||||
//! Loads a type best represented as a long from the current top node
|
||||
template <class T, traits::EnableIf<std::is_signed<T>::value,
|
||||
(sizeof(T) > sizeof(int)),
|
||||
sizeof(T) <= sizeof(long)> = traits::sfinae> inline
|
||||
void loadValue( T & value )
|
||||
{
|
||||
value = static_cast<T>( std::stol( itsNodes.top().node->value() ) );
|
||||
}
|
||||
|
||||
//! Loads a type best represented as a long long from the current top node
|
||||
template <class T, traits::EnableIf<std::is_signed<T>::value,
|
||||
(sizeof(T) > sizeof(long)),
|
||||
sizeof(T) <= sizeof(long long)> = traits::sfinae> inline
|
||||
void loadValue( T & value )
|
||||
{
|
||||
value = static_cast<T>( std::stoll( itsNodes.top().node->value() ) );
|
||||
}
|
||||
|
||||
//! Loads a type best represented as a float from the current top node
|
||||
void loadValue( float & value )
|
||||
{
|
||||
try
|
||||
{
|
||||
value = std::stof( itsNodes.top().node->value() );
|
||||
}
|
||||
catch( std::out_of_range const & )
|
||||
{
|
||||
// special case for denormalized values
|
||||
std::istringstream is( itsNodes.top().node->value() );
|
||||
is >> value;
|
||||
if( std::fpclassify( value ) != FP_SUBNORMAL )
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
//! Loads a type best represented as a double from the current top node
|
||||
void loadValue( double & value )
|
||||
{
|
||||
try
|
||||
{
|
||||
value = std::stod( itsNodes.top().node->value() );
|
||||
}
|
||||
catch( std::out_of_range const & )
|
||||
{
|
||||
// special case for denormalized values
|
||||
std::istringstream is( itsNodes.top().node->value() );
|
||||
is >> value;
|
||||
if( std::fpclassify( value ) != FP_SUBNORMAL )
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
//! Loads a type best represented as a long double from the current top node
|
||||
void loadValue( long double & value )
|
||||
{
|
||||
try
|
||||
{
|
||||
value = std::stold( itsNodes.top().node->value() );
|
||||
}
|
||||
catch( std::out_of_range const & )
|
||||
{
|
||||
// special case for denormalized values
|
||||
std::istringstream is( itsNodes.top().node->value() );
|
||||
is >> value;
|
||||
if( std::fpclassify( value ) != FP_SUBNORMAL )
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
//! Loads a string from the current node from the current top node
|
||||
template<class CharT, class Traits, class Alloc> inline
|
||||
void loadValue( std::basic_string<CharT, Traits, Alloc> & str )
|
||||
{
|
||||
std::basic_istringstream<CharT, Traits> is( itsNodes.top().node->value() );
|
||||
|
||||
str.assign( std::istreambuf_iterator<CharT, Traits>( is ),
|
||||
std::istreambuf_iterator<CharT, Traits>() );
|
||||
}
|
||||
|
||||
//! Loads the size of the current top node
|
||||
template <class T> inline
|
||||
void loadSize( T & value )
|
||||
{
|
||||
value = getNumChildren( itsNodes.top().node );
|
||||
}
|
||||
|
||||
protected:
|
||||
//! Gets the number of children (usually interpreted as size) for the specified node
|
||||
static size_t getNumChildren( rapidxml::xml_node<> * node )
|
||||
{
|
||||
size_t size = 0;
|
||||
node = node->first_node(); // get first child
|
||||
|
||||
while( node != nullptr )
|
||||
{
|
||||
++size;
|
||||
node = node->next_sibling();
|
||||
}
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
//! A struct that contains metadata about a node
|
||||
/*! Keeps track of some top level node, its number of
|
||||
remaining children, and the current active child node */
|
||||
struct NodeInfo
|
||||
{
|
||||
NodeInfo( rapidxml::xml_node<> * n = nullptr ) :
|
||||
node( n ),
|
||||
child( n->first_node() ),
|
||||
size( XMLInputArchive::getNumChildren( n ) ),
|
||||
name( nullptr )
|
||||
{ }
|
||||
|
||||
//! Advances to the next sibling node of the child
|
||||
/*! If this is the last sibling child will be null after calling */
|
||||
void advance()
|
||||
{
|
||||
if( size > 0 )
|
||||
{
|
||||
--size;
|
||||
child = child->next_sibling();
|
||||
}
|
||||
}
|
||||
|
||||
//! Searches for a child with the given name in this node
|
||||
/*! @param searchName The name to search for (must be null terminated)
|
||||
@return The node if found, nullptr otherwise */
|
||||
rapidxml::xml_node<> * search( const char * searchName )
|
||||
{
|
||||
if( searchName )
|
||||
{
|
||||
size_t new_size = XMLInputArchive::getNumChildren( node );
|
||||
const size_t name_size = rapidxml::internal::measure( searchName );
|
||||
|
||||
for( auto new_child = node->first_node(); new_child != nullptr; new_child = new_child->next_sibling() )
|
||||
{
|
||||
if( rapidxml::internal::compare( new_child->name(), new_child->name_size(), searchName, name_size, true ) )
|
||||
{
|
||||
size = new_size;
|
||||
child = new_child;
|
||||
|
||||
return new_child;
|
||||
}
|
||||
--new_size;
|
||||
}
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
rapidxml::xml_node<> * node; //!< A pointer to this node
|
||||
rapidxml::xml_node<> * child; //!< A pointer to its current child
|
||||
size_t size; //!< The remaining number of children for this node
|
||||
const char * name; //!< The NVP name for next next child node
|
||||
}; // NodeInfo
|
||||
|
||||
//! @}
|
||||
|
||||
private:
|
||||
std::vector<char> itsData; //!< The raw data loaded
|
||||
rapidxml::xml_document<> itsXML; //!< The XML document
|
||||
std::stack<NodeInfo> itsNodes; //!< A stack of nodes read from the document
|
||||
};
|
||||
|
||||
// ######################################################################
|
||||
// XMLArchive prologue and epilogue functions
|
||||
// ######################################################################
|
||||
|
||||
// ######################################################################
|
||||
//! Prologue for NVPs for XML output archives
|
||||
/*! NVPs do not start or finish nodes - they just set up the names */
|
||||
template <class T> inline
|
||||
void prologue( XMLOutputArchive &, NameValuePair<T> const & )
|
||||
{ }
|
||||
|
||||
//! Prologue for NVPs for XML input archives
|
||||
template <class T> inline
|
||||
void prologue( XMLInputArchive &, NameValuePair<T> const & )
|
||||
{ }
|
||||
|
||||
// ######################################################################
|
||||
//! Epilogue for NVPs for XML output archives
|
||||
/*! NVPs do not start or finish nodes - they just set up the names */
|
||||
template <class T> inline
|
||||
void epilogue( XMLOutputArchive &, NameValuePair<T> const & )
|
||||
{ }
|
||||
|
||||
//! Epilogue for NVPs for XML input archives
|
||||
template <class T> inline
|
||||
void epilogue( XMLInputArchive &, NameValuePair<T> const & )
|
||||
{ }
|
||||
|
||||
// ######################################################################
|
||||
//! Prologue for SizeTags for XML output archives
|
||||
/*! SizeTags do not start or finish nodes */
|
||||
template <class T> inline
|
||||
void prologue( XMLOutputArchive & ar, SizeTag<T> const & )
|
||||
{
|
||||
ar.appendAttribute( "size", "dynamic" );
|
||||
}
|
||||
|
||||
template <class T> inline
|
||||
void prologue( XMLInputArchive &, SizeTag<T> const & )
|
||||
{ }
|
||||
|
||||
//! Epilogue for SizeTags for XML output archives
|
||||
/*! SizeTags do not start or finish nodes */
|
||||
template <class T> inline
|
||||
void epilogue( XMLOutputArchive &, SizeTag<T> const & )
|
||||
{ }
|
||||
|
||||
template <class T> inline
|
||||
void epilogue( XMLInputArchive &, SizeTag<T> const & )
|
||||
{ }
|
||||
|
||||
// ######################################################################
|
||||
//! Prologue for all other types for XML output archives (except minimal types)
|
||||
/*! Starts a new node, named either automatically or by some NVP,
|
||||
that may be given data by the type about to be archived
|
||||
|
||||
Minimal types do not start or end nodes */
|
||||
template <class T, traits::DisableIf<traits::has_minimal_base_class_serialization<T, traits::has_minimal_output_serialization, XMLOutputArchive>::value ||
|
||||
traits::has_minimal_output_serialization<T, XMLOutputArchive>::value> = traits::sfinae> inline
|
||||
void prologue( XMLOutputArchive & ar, T const & )
|
||||
{
|
||||
ar.startNode();
|
||||
ar.insertType<T>();
|
||||
}
|
||||
|
||||
//! Prologue for all other types for XML input archives (except minimal types)
|
||||
template <class T, traits::DisableIf<traits::has_minimal_base_class_serialization<T, traits::has_minimal_input_serialization, XMLInputArchive>::value ||
|
||||
traits::has_minimal_input_serialization<T, XMLInputArchive>::value> = traits::sfinae> inline
|
||||
void prologue( XMLInputArchive & ar, T const & )
|
||||
{
|
||||
ar.startNode();
|
||||
}
|
||||
|
||||
// ######################################################################
|
||||
//! Epilogue for all other types other for XML output archives (except minimal types)
|
||||
/*! Finishes the node created in the prologue
|
||||
|
||||
Minimal types do not start or end nodes */
|
||||
template <class T, traits::DisableIf<traits::has_minimal_base_class_serialization<T, traits::has_minimal_output_serialization, XMLOutputArchive>::value ||
|
||||
traits::has_minimal_output_serialization<T, XMLOutputArchive>::value> = traits::sfinae> inline
|
||||
void epilogue( XMLOutputArchive & ar, T const & )
|
||||
{
|
||||
ar.finishNode();
|
||||
}
|
||||
|
||||
//! Epilogue for all other types other for XML output archives (except minimal types)
|
||||
template <class T, traits::DisableIf<traits::has_minimal_base_class_serialization<T, traits::has_minimal_input_serialization, XMLInputArchive>::value ||
|
||||
traits::has_minimal_input_serialization<T, XMLInputArchive>::value> = traits::sfinae> inline
|
||||
void epilogue( XMLInputArchive & ar, T const & )
|
||||
{
|
||||
ar.finishNode();
|
||||
}
|
||||
|
||||
// ######################################################################
|
||||
// Common XMLArchive serialization functions
|
||||
// ######################################################################
|
||||
|
||||
//! Saving NVP types to XML
|
||||
template <class T> inline
|
||||
void CEREAL_SAVE_FUNCTION_NAME( XMLOutputArchive & ar, NameValuePair<T> const & t )
|
||||
{
|
||||
ar.setNextName( t.name );
|
||||
ar( t.value );
|
||||
}
|
||||
|
||||
//! Loading NVP types from XML
|
||||
template <class T> inline
|
||||
void CEREAL_LOAD_FUNCTION_NAME( XMLInputArchive & ar, NameValuePair<T> & t )
|
||||
{
|
||||
ar.setNextName( t.name );
|
||||
ar( t.value );
|
||||
}
|
||||
|
||||
// ######################################################################
|
||||
//! Saving SizeTags to XML
|
||||
template <class T> inline
|
||||
void CEREAL_SAVE_FUNCTION_NAME( XMLOutputArchive &, SizeTag<T> const & )
|
||||
{ }
|
||||
|
||||
//! Loading SizeTags from XML
|
||||
template <class T> inline
|
||||
void CEREAL_LOAD_FUNCTION_NAME( XMLInputArchive & ar, SizeTag<T> & st )
|
||||
{
|
||||
ar.loadSize( st.size );
|
||||
}
|
||||
|
||||
// ######################################################################
|
||||
//! Saving for POD types to xml
|
||||
template <class T, traits::EnableIf<std::is_arithmetic<T>::value> = traits::sfinae> inline
|
||||
void CEREAL_SAVE_FUNCTION_NAME(XMLOutputArchive & ar, T const & t)
|
||||
{
|
||||
ar.saveValue( t );
|
||||
}
|
||||
|
||||
//! Loading for POD types from xml
|
||||
template <class T, traits::EnableIf<std::is_arithmetic<T>::value> = traits::sfinae> inline
|
||||
void CEREAL_LOAD_FUNCTION_NAME(XMLInputArchive & ar, T & t)
|
||||
{
|
||||
ar.loadValue( t );
|
||||
}
|
||||
|
||||
// ######################################################################
|
||||
//! saving string to xml
|
||||
template<class CharT, class Traits, class Alloc> inline
|
||||
void CEREAL_SAVE_FUNCTION_NAME(XMLOutputArchive & ar, std::basic_string<CharT, Traits, Alloc> const & str)
|
||||
{
|
||||
ar.saveValue( str );
|
||||
}
|
||||
|
||||
//! loading string from xml
|
||||
template<class CharT, class Traits, class Alloc> inline
|
||||
void CEREAL_LOAD_FUNCTION_NAME(XMLInputArchive & ar, std::basic_string<CharT, Traits, Alloc> & str)
|
||||
{
|
||||
ar.loadValue( str );
|
||||
}
|
||||
} // namespace cereal
|
||||
|
||||
// register archives for polymorphic support
|
||||
CEREAL_REGISTER_ARCHIVE(cereal::XMLOutputArchive)
|
||||
CEREAL_REGISTER_ARCHIVE(cereal::XMLInputArchive)
|
||||
|
||||
// tie input and output archives together
|
||||
CEREAL_SETUP_ARCHIVE_TRAITS(cereal::XMLInputArchive, cereal::XMLOutputArchive)
|
||||
|
||||
#endif // CEREAL_ARCHIVES_XML_HPP_
|
||||
955
libs/cereal/cereal/cereal.hpp
Normal file
955
libs/cereal/cereal/cereal.hpp
Normal file
@ -0,0 +1,955 @@
|
||||
/*! \file cereal.hpp
|
||||
\brief Main cereal functionality */
|
||||
/*
|
||||
Copyright (c) 2014, Randolph Voorhies, Shane Grant
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of cereal nor the
|
||||
names of its contributors may be used to endorse or promote products
|
||||
derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL RANDOLPH VOORHIES OR SHANE GRANT BE LIABLE FOR ANY
|
||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
#ifndef CEREAL_CEREAL_HPP_
|
||||
#define CEREAL_CEREAL_HPP_
|
||||
|
||||
#include <type_traits>
|
||||
#include <string>
|
||||
#include <memory>
|
||||
#include <unordered_map>
|
||||
#include <unordered_set>
|
||||
#include <vector>
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
#include <functional>
|
||||
|
||||
#include <cereal/macros.hpp>
|
||||
#include <cereal/details/traits.hpp>
|
||||
#include <cereal/details/helpers.hpp>
|
||||
#include <cereal/types/base_class.hpp>
|
||||
|
||||
namespace cereal
|
||||
{
|
||||
// ######################################################################
|
||||
//! Creates a name value pair
|
||||
/*! @relates NameValuePair
|
||||
@ingroup Utility */
|
||||
template <class T> inline
|
||||
NameValuePair<T> make_nvp( std::string const & name, T && value )
|
||||
{
|
||||
return {name.c_str(), std::forward<T>(value)};
|
||||
}
|
||||
|
||||
//! Creates a name value pair
|
||||
/*! @relates NameValuePair
|
||||
@ingroup Utility */
|
||||
template <class T> inline
|
||||
NameValuePair<T> make_nvp( const char * name, T && value )
|
||||
{
|
||||
return {name, std::forward<T>(value)};
|
||||
}
|
||||
|
||||
//! Creates a name value pair for the variable T with the same name as the variable
|
||||
/*! @relates NameValuePair
|
||||
@ingroup Utility */
|
||||
#define CEREAL_NVP(T) ::cereal::make_nvp(#T, T)
|
||||
|
||||
// ######################################################################
|
||||
//! Convenience function to create binary data for both const and non const pointers
|
||||
/*! @param data Pointer to beginning of the data
|
||||
@param size The size in bytes of the data
|
||||
@relates BinaryData
|
||||
@ingroup Utility */
|
||||
template <class T> inline
|
||||
BinaryData<T> binary_data( T && data, size_t size )
|
||||
{
|
||||
return {std::forward<T>(data), size};
|
||||
}
|
||||
|
||||
// ######################################################################
|
||||
//! Creates a size tag from some variable.
|
||||
/*! Will normally be used to serialize size (e.g. size()) information for
|
||||
variable size containers. If you have a variable sized container,
|
||||
the very first thing it serializes should be its size, wrapped in
|
||||
a SizeTag.
|
||||
|
||||
@relates SizeTag
|
||||
@ingroup Utility */
|
||||
template <class T>
|
||||
SizeTag<T> make_size_tag( T && sz )
|
||||
{
|
||||
return {std::forward<T>(sz)};
|
||||
}
|
||||
|
||||
// ######################################################################
|
||||
//! Called before a type is serialized to set up any special archive state
|
||||
//! for processing some type
|
||||
/*! If designing a serializer that needs to set up any kind of special
|
||||
state or output extra information for a type, specialize this function
|
||||
for the archive type and the types that require the extra information.
|
||||
@ingroup Internal */
|
||||
template <class Archive, class T>
|
||||
void prologue( Archive & /* archive */, T const & /* data */)
|
||||
{ }
|
||||
|
||||
//! Called after a type is serialized to tear down any special archive state
|
||||
//! for processing some type
|
||||
/*! @ingroup Internal */
|
||||
template <class Archive, class T>
|
||||
void epilogue( Archive & /* archive */, T const & /* data */)
|
||||
{ }
|
||||
|
||||
// ######################################################################
|
||||
//! Special flags for archives
|
||||
/*! AllowEmptyClassElision
|
||||
This allows for empty classes to be serialized even if they do not provide
|
||||
a serialization function. Classes with no data members are considered to be
|
||||
empty. Be warned that if this is enabled and you attempt to serialize an
|
||||
empty class with improperly formed serialize or load/save functions, no
|
||||
static error will occur - the error will propogate silently and your
|
||||
intended serialization functions may not be called. You can manually
|
||||
ensure that your classes that have custom serialization are correct
|
||||
by using the traits is_output_serializable and is_input_serializable
|
||||
in cereal/details/traits.hpp.
|
||||
@ingroup Internal */
|
||||
enum Flags { AllowEmptyClassElision = 1 };
|
||||
|
||||
// ######################################################################
|
||||
//! Registers a specific Archive type with cereal
|
||||
/*! This registration should be done once per archive. A good place to
|
||||
put this is immediately following the definition of your archive.
|
||||
Archive registration is only strictly necessary if you wish to
|
||||
support pointers to polymorphic data types. All archives that
|
||||
come with cereal are already registered.
|
||||
@ingroup Internal */
|
||||
#define CEREAL_REGISTER_ARCHIVE(Archive) \
|
||||
namespace cereal { namespace detail { \
|
||||
template <class T, class BindingTag> \
|
||||
typename polymorphic_serialization_support<Archive, T>::type \
|
||||
instantiate_polymorphic_binding( T*, Archive*, BindingTag, adl_tag ); \
|
||||
} } /* end namespaces */
|
||||
|
||||
// ######################################################################
|
||||
//! Defines a class version for some type
|
||||
/*! Versioning information is optional and adds some small amount of
|
||||
overhead to serialization. This overhead will occur both in terms of
|
||||
space in the archive (the version information for each class will be
|
||||
stored exactly once) as well as runtime (versioned serialization functions
|
||||
must check to see if they need to load or store version information).
|
||||
|
||||
Versioning is useful if you plan on fundamentally changing the way some
|
||||
type is serialized in the future. Versioned serialization functions
|
||||
cannot be used to load non-versioned data.
|
||||
|
||||
By default, all types have an assumed version value of zero. By
|
||||
using this macro, you may change the version number associated with
|
||||
some type. cereal will then use this value as a second parameter
|
||||
to your serialization functions.
|
||||
|
||||
The interface for the serialization functions is nearly identical
|
||||
to non-versioned serialization with the addition of a second parameter,
|
||||
const std::uint32_t version, which will be supplied with the correct
|
||||
version number. Serializing the version number on a save happens
|
||||
automatically.
|
||||
|
||||
Versioning cannot be mixed with non-versioned serialization functions.
|
||||
Having both types will result result in a compile time error. Data
|
||||
serialized without versioning cannot be loaded by a serialization
|
||||
function with added versioning support.
|
||||
|
||||
Example interface for versioning on a non-member serialize function:
|
||||
|
||||
@code{cpp}
|
||||
CEREAL_CLASS_VERSION( Mytype, 77 ); // register class version
|
||||
|
||||
template <class Archive>
|
||||
void serialize( Archive & ar, Mytype & t, const std::uint32_t version )
|
||||
{
|
||||
// When performing a load, the version associated with the class
|
||||
// is whatever it was when that data was originally serialized
|
||||
//
|
||||
// When we save, we'll use the version that is defined in the macro
|
||||
|
||||
if( version >= some_number )
|
||||
// do this
|
||||
else
|
||||
// do that
|
||||
}
|
||||
@endcode
|
||||
|
||||
Interfaces for other forms of serialization functions is similar. This
|
||||
macro should be placed at global scope.
|
||||
@ingroup Utility */
|
||||
#define CEREAL_CLASS_VERSION(TYPE, VERSION_NUMBER) \
|
||||
namespace cereal { namespace detail { \
|
||||
template <> struct Version<TYPE> \
|
||||
{ \
|
||||
static const std::uint32_t version; \
|
||||
static std::uint32_t registerVersion() \
|
||||
{ \
|
||||
::cereal::detail::StaticObject<Versions>::getInstance().mapping.emplace( \
|
||||
std::type_index(typeid(TYPE)).hash_code(), VERSION_NUMBER ); \
|
||||
return VERSION_NUMBER; \
|
||||
} \
|
||||
static void unused() { (void)version; } \
|
||||
}; /* end Version */ \
|
||||
const std::uint32_t Version<TYPE>::version = \
|
||||
Version<TYPE>::registerVersion(); \
|
||||
} } // end namespaces
|
||||
|
||||
// ######################################################################
|
||||
//! The base output archive class
|
||||
/*! This is the base output archive for all output archives. If you create
|
||||
a custom archive class, it should derive from this, passing itself as
|
||||
a template parameter for the ArchiveType.
|
||||
|
||||
The base class provides all of the functionality necessary to
|
||||
properly forward data to the correct serialization functions.
|
||||
|
||||
Individual archives should use a combination of prologue and
|
||||
epilogue functions together with specializations of serialize, save,
|
||||
and load to alter the functionality of their serialization.
|
||||
|
||||
@tparam ArchiveType The archive type that derives from OutputArchive
|
||||
@tparam Flags Flags to control advanced functionality. See the Flags
|
||||
enum for more information.
|
||||
@ingroup Internal */
|
||||
template<class ArchiveType, std::uint32_t Flags = 0>
|
||||
class OutputArchive : public detail::OutputArchiveBase
|
||||
{
|
||||
public:
|
||||
//! Construct the output archive
|
||||
/*! @param derived A pointer to the derived ArchiveType (pass this from the derived archive) */
|
||||
OutputArchive(ArchiveType * const derived) : self(derived), itsCurrentPointerId(1), itsCurrentPolymorphicTypeId(1)
|
||||
{ }
|
||||
|
||||
OutputArchive & operator=( OutputArchive const & ) = delete;
|
||||
|
||||
//! Serializes all passed in data
|
||||
/*! This is the primary interface for serializing data with an archive */
|
||||
template <class ... Types> inline
|
||||
ArchiveType & operator()( Types && ... args )
|
||||
{
|
||||
self->process( std::forward<Types>( args )... );
|
||||
return *self;
|
||||
}
|
||||
|
||||
/*! @name Boost Transition Layer
|
||||
Functionality that mirrors the syntax for Boost. This is useful if you are transitioning
|
||||
a large project from Boost to cereal. The preferred interface for cereal is using operator(). */
|
||||
//! @{
|
||||
|
||||
//! Serializes passed in data
|
||||
/*! This is a boost compatability layer and is not the preferred way of using
|
||||
cereal. If you are transitioning from boost, use this until you can
|
||||
transition to the operator() overload */
|
||||
template <class T> inline
|
||||
ArchiveType & operator&( T && arg )
|
||||
{
|
||||
self->process( std::forward<T>( arg ) );
|
||||
return *self;
|
||||
}
|
||||
|
||||
//! Serializes passed in data
|
||||
/*! This is a boost compatability layer and is not the preferred way of using
|
||||
cereal. If you are transitioning from boost, use this until you can
|
||||
transition to the operator() overload */
|
||||
template <class T> inline
|
||||
ArchiveType & operator<<( T && arg )
|
||||
{
|
||||
self->process( std::forward<T>( arg ) );
|
||||
return *self;
|
||||
}
|
||||
|
||||
//! @}
|
||||
|
||||
//! Registers a shared pointer with the archive
|
||||
/*! This function is used to track shared pointer targets to prevent
|
||||
unnecessary saves from taking place if multiple shared pointers
|
||||
point to the same data.
|
||||
|
||||
@internal
|
||||
@param addr The address (see shared_ptr get()) pointed to by the shared pointer
|
||||
@return A key that uniquely identifies the pointer */
|
||||
inline std::uint32_t registerSharedPointer( void const * addr )
|
||||
{
|
||||
// Handle null pointers by just returning 0
|
||||
if(addr == 0) return 0;
|
||||
|
||||
auto id = itsSharedPointerMap.find( addr );
|
||||
if( id == itsSharedPointerMap.end() )
|
||||
{
|
||||
auto ptrId = itsCurrentPointerId++;
|
||||
itsSharedPointerMap.insert( {addr, ptrId} );
|
||||
return ptrId | detail::msb_32bit; // mask MSB to be 1
|
||||
}
|
||||
else
|
||||
return id->second;
|
||||
}
|
||||
|
||||
//! Registers a polymorphic type name with the archive
|
||||
/*! This function is used to track polymorphic types to prevent
|
||||
unnecessary saves of identifying strings used by the polymorphic
|
||||
support functionality.
|
||||
|
||||
@internal
|
||||
@param name The name to associate with a polymorphic type
|
||||
@return A key that uniquely identifies the polymorphic type name */
|
||||
inline std::uint32_t registerPolymorphicType( char const * name )
|
||||
{
|
||||
auto id = itsPolymorphicTypeMap.find( name );
|
||||
if( id == itsPolymorphicTypeMap.end() )
|
||||
{
|
||||
auto polyId = itsCurrentPolymorphicTypeId++;
|
||||
itsPolymorphicTypeMap.insert( {name, polyId} );
|
||||
return polyId | detail::msb_32bit; // mask MSB to be 1
|
||||
}
|
||||
else
|
||||
return id->second;
|
||||
}
|
||||
|
||||
private:
|
||||
//! Serializes data after calling prologue, then calls epilogue
|
||||
template <class T> inline
|
||||
void process( T && head )
|
||||
{
|
||||
prologue( *self, head );
|
||||
self->processImpl( head );
|
||||
epilogue( *self, head );
|
||||
}
|
||||
|
||||
//! Unwinds to process all data
|
||||
template <class T, class ... Other> inline
|
||||
void process( T && head, Other && ... tail )
|
||||
{
|
||||
self->process( std::forward<T>( head ) );
|
||||
self->process( std::forward<Other>( tail )... );
|
||||
}
|
||||
|
||||
//! Serialization of a virtual_base_class wrapper
|
||||
/*! \sa virtual_base_class */
|
||||
template <class T> inline
|
||||
ArchiveType & processImpl(virtual_base_class<T> const & b)
|
||||
{
|
||||
traits::detail::base_class_id id(b.base_ptr);
|
||||
if(itsBaseClassSet.count(id) == 0)
|
||||
{
|
||||
itsBaseClassSet.insert(id);
|
||||
self->processImpl( *b.base_ptr );
|
||||
}
|
||||
return *self;
|
||||
}
|
||||
|
||||
//! Serialization of a base_class wrapper
|
||||
/*! \sa base_class */
|
||||
template <class T> inline
|
||||
ArchiveType & processImpl(base_class<T> const & b)
|
||||
{
|
||||
self->processImpl( *b.base_ptr );
|
||||
return *self;
|
||||
}
|
||||
|
||||
//! Helper macro that expands the requirements for activating an overload
|
||||
/*! Requirements:
|
||||
Has the requested serialization function
|
||||
Does not have version and unversioned at the same time
|
||||
Is output serializable AND
|
||||
is specialized for this type of function OR
|
||||
has no specialization at all */
|
||||
#define PROCESS_IF(name) \
|
||||
traits::EnableIf<traits::has_##name<T, ArchiveType>::value, \
|
||||
!traits::has_invalid_output_versioning<T, ArchiveType>::value, \
|
||||
(traits::is_output_serializable<T, ArchiveType>::value && \
|
||||
(traits::is_specialized_##name<T, ArchiveType>::value || \
|
||||
!traits::is_specialized<T, ArchiveType>::value))> = traits::sfinae
|
||||
|
||||
//! Member serialization
|
||||
template <class T, PROCESS_IF(member_serialize)> inline
|
||||
ArchiveType & processImpl(T const & t)
|
||||
{
|
||||
access::member_serialize(*self, const_cast<T &>(t));
|
||||
return *self;
|
||||
}
|
||||
|
||||
//! Non member serialization
|
||||
template <class T, PROCESS_IF(non_member_serialize)> inline
|
||||
ArchiveType & processImpl(T const & t)
|
||||
{
|
||||
CEREAL_SERIALIZE_FUNCTION_NAME(*self, const_cast<T &>(t));
|
||||
return *self;
|
||||
}
|
||||
|
||||
//! Member split (save)
|
||||
template <class T, PROCESS_IF(member_save)> inline
|
||||
ArchiveType & processImpl(T const & t)
|
||||
{
|
||||
access::member_save(*self, t);
|
||||
return *self;
|
||||
}
|
||||
|
||||
//! Non member split (save)
|
||||
template <class T, PROCESS_IF(non_member_save)> inline
|
||||
ArchiveType & processImpl(T const & t)
|
||||
{
|
||||
CEREAL_SAVE_FUNCTION_NAME(*self, t);
|
||||
return *self;
|
||||
}
|
||||
|
||||
//! Member split (save_minimal)
|
||||
template <class T, PROCESS_IF(member_save_minimal)> inline
|
||||
ArchiveType & processImpl(T const & t)
|
||||
{
|
||||
self->process( access::member_save_minimal(*self, t) );
|
||||
return *self;
|
||||
}
|
||||
|
||||
//! Non member split (save_minimal)
|
||||
template <class T, PROCESS_IF(non_member_save_minimal)> inline
|
||||
ArchiveType & processImpl(T const & t)
|
||||
{
|
||||
self->process( CEREAL_SAVE_MINIMAL_FUNCTION_NAME(*self, t) );
|
||||
return *self;
|
||||
}
|
||||
|
||||
//! Empty class specialization
|
||||
template <class T, traits::EnableIf<(Flags & AllowEmptyClassElision),
|
||||
!traits::is_output_serializable<T, ArchiveType>::value,
|
||||
std::is_empty<T>::value> = traits::sfinae> inline
|
||||
ArchiveType & processImpl(T const &)
|
||||
{
|
||||
return *self;
|
||||
}
|
||||
|
||||
//! No matching serialization
|
||||
/*! Invalid if we have invalid output versioning or
|
||||
we are not output serializable, and either
|
||||
don't allow empty class ellision or allow it but are not serializing an empty class */
|
||||
template <class T, traits::EnableIf<traits::has_invalid_output_versioning<T, ArchiveType>::value ||
|
||||
(!traits::is_output_serializable<T, ArchiveType>::value &&
|
||||
(!(Flags & AllowEmptyClassElision) || ((Flags & AllowEmptyClassElision) && !std::is_empty<T>::value)))> = traits::sfinae> inline
|
||||
ArchiveType & processImpl(T const &)
|
||||
{
|
||||
static_assert(traits::detail::count_output_serializers<T, ArchiveType>::value != 0,
|
||||
"cereal could not find any output serialization functions for the provided type and archive combination. \n\n "
|
||||
"Types must either have a serialize function, load/save pair, or load_minimal/save_minimal pair (you may not mix these). \n "
|
||||
"Serialize functions generally have the following signature: \n\n "
|
||||
"template<class Archive> \n "
|
||||
" void serialize(Archive & ar) \n "
|
||||
" { \n "
|
||||
" ar( member1, member2, member3 ); \n "
|
||||
" } \n\n " );
|
||||
|
||||
static_assert(traits::detail::count_output_serializers<T, ArchiveType>::value < 2,
|
||||
"cereal found more than one compatible output serialization function for the provided type and archive combination. \n\n "
|
||||
"Types must either have a serialize function, load/save pair, or load_minimal/save_minimal pair (you may not mix these). \n "
|
||||
"Use specialization (see access.hpp) if you need to disambiguate between serialize vs load/save functions. \n "
|
||||
"Note that serialization functions can be inherited which may lead to the aforementioned ambiguities. \n "
|
||||
"In addition, you may not mix versioned with non-versioned serialization functions. \n\n ");
|
||||
|
||||
return *self;
|
||||
}
|
||||
|
||||
//! Registers a class version with the archive and serializes it if necessary
|
||||
/*! If this is the first time this class has been serialized, we will record its
|
||||
version number and serialize that.
|
||||
|
||||
@tparam T The type of the class being serialized
|
||||
@param version The version number associated with it */
|
||||
template <class T> inline
|
||||
std::uint32_t registerClassVersion()
|
||||
{
|
||||
static const auto hash = std::type_index(typeid(T)).hash_code();
|
||||
const auto insertResult = itsVersionedTypes.insert( hash );
|
||||
const auto version =
|
||||
detail::StaticObject<detail::Versions>::getInstance().find( hash, detail::Version<T>::version );
|
||||
|
||||
if( insertResult.second ) // insertion took place, serialize the version number
|
||||
process( make_nvp<ArchiveType>("cereal_class_version", version) );
|
||||
|
||||
return version;
|
||||
}
|
||||
|
||||
//! Member serialization
|
||||
/*! Versioning implementation */
|
||||
template <class T, PROCESS_IF(member_versioned_serialize)> inline
|
||||
ArchiveType & processImpl(T const & t)
|
||||
{
|
||||
access::member_serialize(*self, const_cast<T &>(t), registerClassVersion<T>());
|
||||
return *self;
|
||||
}
|
||||
|
||||
//! Non member serialization
|
||||
/*! Versioning implementation */
|
||||
template <class T, PROCESS_IF(non_member_versioned_serialize)> inline
|
||||
ArchiveType & processImpl(T const & t)
|
||||
{
|
||||
CEREAL_SERIALIZE_FUNCTION_NAME(*self, const_cast<T &>(t), registerClassVersion<T>());
|
||||
return *self;
|
||||
}
|
||||
|
||||
//! Member split (save)
|
||||
/*! Versioning implementation */
|
||||
template <class T, PROCESS_IF(member_versioned_save)> inline
|
||||
ArchiveType & processImpl(T const & t)
|
||||
{
|
||||
access::member_save(*self, t, registerClassVersion<T>());
|
||||
return *self;
|
||||
}
|
||||
|
||||
//! Non member split (save)
|
||||
/*! Versioning implementation */
|
||||
template <class T, PROCESS_IF(non_member_versioned_save)> inline
|
||||
ArchiveType & processImpl(T const & t)
|
||||
{
|
||||
CEREAL_SAVE_FUNCTION_NAME(*self, t, registerClassVersion<T>());
|
||||
return *self;
|
||||
}
|
||||
|
||||
//! Member split (save_minimal)
|
||||
/*! Versioning implementation */
|
||||
template <class T, PROCESS_IF(member_versioned_save_minimal)> inline
|
||||
ArchiveType & processImpl(T const & t)
|
||||
{
|
||||
self->process( access::member_save_minimal(*self, t, registerClassVersion<T>()) );
|
||||
return *self;
|
||||
}
|
||||
|
||||
//! Non member split (save_minimal)
|
||||
/*! Versioning implementation */
|
||||
template <class T, PROCESS_IF(non_member_versioned_save_minimal)> inline
|
||||
ArchiveType & processImpl(T const & t)
|
||||
{
|
||||
self->process( CEREAL_SAVE_MINIMAL_FUNCTION_NAME(*self, t, registerClassVersion<T>()) );
|
||||
return *self;
|
||||
}
|
||||
|
||||
#undef PROCESS_IF
|
||||
|
||||
private:
|
||||
ArchiveType * const self;
|
||||
|
||||
//! A set of all base classes that have been serialized
|
||||
std::unordered_set<traits::detail::base_class_id, traits::detail::base_class_id_hash> itsBaseClassSet;
|
||||
|
||||
//! Maps from addresses to pointer ids
|
||||
std::unordered_map<void const *, std::uint32_t> itsSharedPointerMap;
|
||||
|
||||
//! The id to be given to the next pointer
|
||||
std::uint32_t itsCurrentPointerId;
|
||||
|
||||
//! Maps from polymorphic type name strings to ids
|
||||
std::unordered_map<char const *, std::uint32_t> itsPolymorphicTypeMap;
|
||||
|
||||
//! The id to be given to the next polymorphic type name
|
||||
std::uint32_t itsCurrentPolymorphicTypeId;
|
||||
|
||||
//! Keeps track of classes that have versioning information associated with them
|
||||
std::unordered_set<size_type> itsVersionedTypes;
|
||||
}; // class OutputArchive
|
||||
|
||||
// ######################################################################
|
||||
//! The base input archive class
|
||||
/*! This is the base input archive for all input archives. If you create
|
||||
a custom archive class, it should derive from this, passing itself as
|
||||
a template parameter for the ArchiveType.
|
||||
|
||||
The base class provides all of the functionality necessary to
|
||||
properly forward data to the correct serialization functions.
|
||||
|
||||
Individual archives should use a combination of prologue and
|
||||
epilogue functions together with specializations of serialize, save,
|
||||
and load to alter the functionality of their serialization.
|
||||
|
||||
@tparam ArchiveType The archive type that derives from InputArchive
|
||||
@tparam Flags Flags to control advanced functionality. See the Flags
|
||||
enum for more information.
|
||||
@ingroup Internal */
|
||||
template<class ArchiveType, std::uint32_t Flags = 0>
|
||||
class InputArchive : public detail::InputArchiveBase
|
||||
{
|
||||
public:
|
||||
//! Construct the output archive
|
||||
/*! @param derived A pointer to the derived ArchiveType (pass this from the derived archive) */
|
||||
InputArchive(ArchiveType * const derived) :
|
||||
self(derived),
|
||||
itsBaseClassSet(),
|
||||
itsSharedPointerMap(),
|
||||
itsPolymorphicTypeMap(),
|
||||
itsVersionedTypes()
|
||||
{ }
|
||||
|
||||
InputArchive & operator=( InputArchive const & ) = delete;
|
||||
|
||||
//! Serializes all passed in data
|
||||
/*! This is the primary interface for serializing data with an archive */
|
||||
template <class ... Types> inline
|
||||
ArchiveType & operator()( Types && ... args )
|
||||
{
|
||||
process( std::forward<Types>( args )... );
|
||||
return *self;
|
||||
}
|
||||
|
||||
/*! @name Boost Transition Layer
|
||||
Functionality that mirrors the syntax for Boost. This is useful if you are transitioning
|
||||
a large project from Boost to cereal. The preferred interface for cereal is using operator(). */
|
||||
//! @{
|
||||
|
||||
//! Serializes passed in data
|
||||
/*! This is a boost compatability layer and is not the preferred way of using
|
||||
cereal. If you are transitioning from boost, use this until you can
|
||||
transition to the operator() overload */
|
||||
template <class T> inline
|
||||
ArchiveType & operator&( T && arg )
|
||||
{
|
||||
self->process( std::forward<T>( arg ) );
|
||||
return *self;
|
||||
}
|
||||
|
||||
//! Serializes passed in data
|
||||
/*! This is a boost compatability layer and is not the preferred way of using
|
||||
cereal. If you are transitioning from boost, use this until you can
|
||||
transition to the operator() overload */
|
||||
template <class T> inline
|
||||
ArchiveType & operator>>( T && arg )
|
||||
{
|
||||
self->process( std::forward<T>( arg ) );
|
||||
return *self;
|
||||
}
|
||||
|
||||
//! @}
|
||||
|
||||
//! Retrieves a shared pointer given a unique key for it
|
||||
/*! This is used to retrieve a previously registered shared_ptr
|
||||
which has already been loaded.
|
||||
|
||||
@param id The unique id that was serialized for the pointer
|
||||
@return A shared pointer to the data
|
||||
@throw Exception if the id does not exist */
|
||||
inline std::shared_ptr<void> getSharedPointer(std::uint32_t const id)
|
||||
{
|
||||
if(id == 0) return std::shared_ptr<void>(nullptr);
|
||||
|
||||
auto iter = itsSharedPointerMap.find( id );
|
||||
if(iter == itsSharedPointerMap.end())
|
||||
throw Exception("Error while trying to deserialize a smart pointer. Could not find id " + std::to_string(id));
|
||||
|
||||
return iter->second;
|
||||
}
|
||||
|
||||
//! Registers a shared pointer to its unique identifier
|
||||
/*! After a shared pointer has been allocated for the first time, it should
|
||||
be registered with its loaded id for future references to it.
|
||||
|
||||
@param id The unique identifier for the shared pointer
|
||||
@param ptr The actual shared pointer */
|
||||
inline void registerSharedPointer(std::uint32_t const id, std::shared_ptr<void> ptr)
|
||||
{
|
||||
std::uint32_t const stripped_id = id & ~detail::msb_32bit;
|
||||
itsSharedPointerMap[stripped_id] = ptr;
|
||||
}
|
||||
|
||||
//! Retrieves the string for a polymorphic type given a unique key for it
|
||||
/*! This is used to retrieve a string previously registered during
|
||||
a polymorphic load.
|
||||
|
||||
@param id The unique id that was serialized for the polymorphic type
|
||||
@return The string identifier for the tyep */
|
||||
inline std::string getPolymorphicName(std::uint32_t const id)
|
||||
{
|
||||
auto name = itsPolymorphicTypeMap.find( id );
|
||||
if(name == itsPolymorphicTypeMap.end())
|
||||
{
|
||||
throw Exception("Error while trying to deserialize a polymorphic pointer. Could not find type id " + std::to_string(id));
|
||||
}
|
||||
return name->second;
|
||||
}
|
||||
|
||||
//! Registers a polymorphic name string to its unique identifier
|
||||
/*! After a polymorphic type has been loaded for the first time, it should
|
||||
be registered with its loaded id for future references to it.
|
||||
|
||||
@param id The unique identifier for the polymorphic type
|
||||
@param name The name associated with the tyep */
|
||||
inline void registerPolymorphicName(std::uint32_t const id, std::string const & name)
|
||||
{
|
||||
std::uint32_t const stripped_id = id & ~detail::msb_32bit;
|
||||
itsPolymorphicTypeMap.insert( {stripped_id, name} );
|
||||
}
|
||||
|
||||
private:
|
||||
//! Serializes data after calling prologue, then calls epilogue
|
||||
template <class T> inline
|
||||
void process( T && head )
|
||||
{
|
||||
prologue( *self, head );
|
||||
self->processImpl( head );
|
||||
epilogue( *self, head );
|
||||
}
|
||||
|
||||
//! Unwinds to process all data
|
||||
template <class T, class ... Other> inline
|
||||
void process( T && head, Other && ... tail )
|
||||
{
|
||||
process( std::forward<T>( head ) );
|
||||
process( std::forward<Other>( tail )... );
|
||||
}
|
||||
|
||||
//! Serialization of a virtual_base_class wrapper
|
||||
/*! \sa virtual_base_class */
|
||||
template <class T> inline
|
||||
ArchiveType & processImpl(virtual_base_class<T> & b)
|
||||
{
|
||||
traits::detail::base_class_id id(b.base_ptr);
|
||||
if(itsBaseClassSet.count(id) == 0)
|
||||
{
|
||||
itsBaseClassSet.insert(id);
|
||||
self->processImpl( *b.base_ptr );
|
||||
}
|
||||
return *self;
|
||||
}
|
||||
|
||||
//! Serialization of a base_class wrapper
|
||||
/*! \sa base_class */
|
||||
template <class T> inline
|
||||
ArchiveType & processImpl(base_class<T> & b)
|
||||
{
|
||||
self->processImpl( *b.base_ptr );
|
||||
return *self;
|
||||
}
|
||||
|
||||
//! Helper macro that expands the requirements for activating an overload
|
||||
/*! Requirements:
|
||||
Has the requested serialization function
|
||||
Does not have version and unversioned at the same time
|
||||
Is input serializable AND
|
||||
is specialized for this type of function OR
|
||||
has no specialization at all */
|
||||
#define PROCESS_IF(name) \
|
||||
traits::EnableIf<traits::has_##name<T, ArchiveType>::value, \
|
||||
!traits::has_invalid_input_versioning<T, ArchiveType>::value, \
|
||||
(traits::is_input_serializable<T, ArchiveType>::value && \
|
||||
(traits::is_specialized_##name<T, ArchiveType>::value || \
|
||||
!traits::is_specialized<T, ArchiveType>::value))> = traits::sfinae
|
||||
|
||||
//! Member serialization
|
||||
template <class T, PROCESS_IF(member_serialize)> inline
|
||||
ArchiveType & processImpl(T & t)
|
||||
{
|
||||
access::member_serialize(*self, t);
|
||||
return *self;
|
||||
}
|
||||
|
||||
//! Non member serialization
|
||||
template <class T, PROCESS_IF(non_member_serialize)> inline
|
||||
ArchiveType & processImpl(T & t)
|
||||
{
|
||||
CEREAL_SERIALIZE_FUNCTION_NAME(*self, t);
|
||||
return *self;
|
||||
}
|
||||
|
||||
//! Member split (load)
|
||||
template <class T, PROCESS_IF(member_load)> inline
|
||||
ArchiveType & processImpl(T & t)
|
||||
{
|
||||
access::member_load(*self, t);
|
||||
return *self;
|
||||
}
|
||||
|
||||
//! Non member split (load)
|
||||
template <class T, PROCESS_IF(non_member_load)> inline
|
||||
ArchiveType & processImpl(T & t)
|
||||
{
|
||||
CEREAL_LOAD_FUNCTION_NAME(*self, t);
|
||||
return *self;
|
||||
}
|
||||
|
||||
//! Member split (load_minimal)
|
||||
template <class T, PROCESS_IF(member_load_minimal)> inline
|
||||
ArchiveType & processImpl(T & t)
|
||||
{
|
||||
using OutArchiveType = typename traits::detail::get_output_from_input<ArchiveType>::type;
|
||||
typename traits::has_member_save_minimal<T, OutArchiveType>::type value;
|
||||
self->process( value );
|
||||
access::member_load_minimal(*self, t, value);
|
||||
return *self;
|
||||
}
|
||||
|
||||
//! Non member split (load_minimal)
|
||||
template <class T, PROCESS_IF(non_member_load_minimal)> inline
|
||||
ArchiveType & processImpl(T & t)
|
||||
{
|
||||
using OutArchiveType = typename traits::detail::get_output_from_input<ArchiveType>::type;
|
||||
typename traits::has_non_member_save_minimal<T, OutArchiveType>::type value;
|
||||
self->process( value );
|
||||
CEREAL_LOAD_MINIMAL_FUNCTION_NAME(*self, t, value);
|
||||
return *self;
|
||||
}
|
||||
|
||||
//! Empty class specialization
|
||||
template <class T, traits::EnableIf<(Flags & AllowEmptyClassElision),
|
||||
!traits::is_input_serializable<T, ArchiveType>::value,
|
||||
std::is_empty<T>::value> = traits::sfinae> inline
|
||||
ArchiveType & processImpl(T const &)
|
||||
{
|
||||
return *self;
|
||||
}
|
||||
|
||||
//! No matching serialization
|
||||
/*! Invalid if we have invalid input versioning or
|
||||
we are not input serializable, and either
|
||||
don't allow empty class ellision or allow it but are not serializing an empty class */
|
||||
template <class T, traits::EnableIf<traits::has_invalid_input_versioning<T, ArchiveType>::value ||
|
||||
(!traits::is_input_serializable<T, ArchiveType>::value &&
|
||||
(!(Flags & AllowEmptyClassElision) || ((Flags & AllowEmptyClassElision) && !std::is_empty<T>::value)))> = traits::sfinae> inline
|
||||
ArchiveType & processImpl(T const &)
|
||||
{
|
||||
static_assert(traits::detail::count_input_serializers<T, ArchiveType>::value != 0,
|
||||
"cereal could not find any input serialization functions for the provided type and archive combination. \n\n "
|
||||
"Types must either have a serialize function, load/save pair, or load_minimal/save_minimal pair (you may not mix these). \n "
|
||||
"Serialize functions generally have the following signature: \n\n "
|
||||
"template<class Archive> \n "
|
||||
" void serialize(Archive & ar) \n "
|
||||
" { \n "
|
||||
" ar( member1, member2, member3 ); \n "
|
||||
" } \n\n " );
|
||||
|
||||
static_assert(traits::detail::count_input_serializers<T, ArchiveType>::value < 2,
|
||||
"cereal found more than one compatible input serialization function for the provided type and archive combination. \n\n "
|
||||
"Types must either have a serialize function, load/save pair, or load_minimal/save_minimal pair (you may not mix these). \n "
|
||||
"Use specialization (see access.hpp) if you need to disambiguate between serialize vs load/save functions. \n "
|
||||
"Note that serialization functions can be inherited which may lead to the aforementioned ambiguities. \n "
|
||||
"In addition, you may not mix versioned with non-versioned serialization functions. \n\n ");
|
||||
|
||||
return *self;
|
||||
}
|
||||
|
||||
//! Registers a class version with the archive and serializes it if necessary
|
||||
/*! If this is the first time this class has been serialized, we will record its
|
||||
version number and serialize that.
|
||||
|
||||
@tparam T The type of the class being serialized
|
||||
@param version The version number associated with it */
|
||||
template <class T> inline
|
||||
std::uint32_t loadClassVersion()
|
||||
{
|
||||
static const auto hash = std::type_index(typeid(T)).hash_code();
|
||||
auto lookupResult = itsVersionedTypes.find( hash );
|
||||
|
||||
if( lookupResult != itsVersionedTypes.end() ) // already exists
|
||||
return lookupResult->second;
|
||||
else // need to load
|
||||
{
|
||||
std::uint32_t version;
|
||||
|
||||
process( make_nvp<ArchiveType>("cereal_class_version", version) );
|
||||
itsVersionedTypes.emplace_hint( lookupResult, hash, version );
|
||||
|
||||
return version;
|
||||
}
|
||||
}
|
||||
|
||||
//! Member serialization
|
||||
/*! Versioning implementation */
|
||||
template <class T, PROCESS_IF(member_versioned_serialize)> inline
|
||||
ArchiveType & processImpl(T & t)
|
||||
{
|
||||
const auto version = loadClassVersion<T>();
|
||||
access::member_serialize(*self, t, version);
|
||||
return *self;
|
||||
}
|
||||
|
||||
//! Non member serialization
|
||||
/*! Versioning implementation */
|
||||
template <class T, PROCESS_IF(non_member_versioned_serialize)> inline
|
||||
ArchiveType & processImpl(T & t)
|
||||
{
|
||||
const auto version = loadClassVersion<T>();
|
||||
CEREAL_SERIALIZE_FUNCTION_NAME(*self, t, version);
|
||||
return *self;
|
||||
}
|
||||
|
||||
//! Member split (load)
|
||||
/*! Versioning implementation */
|
||||
template <class T, PROCESS_IF(member_versioned_load)> inline
|
||||
ArchiveType & processImpl(T & t)
|
||||
{
|
||||
const auto version = loadClassVersion<T>();
|
||||
access::member_load(*self, t, version);
|
||||
return *self;
|
||||
}
|
||||
|
||||
//! Non member split (load)
|
||||
/*! Versioning implementation */
|
||||
template <class T, PROCESS_IF(non_member_versioned_load)> inline
|
||||
ArchiveType & processImpl(T & t)
|
||||
{
|
||||
const auto version = loadClassVersion<T>();
|
||||
CEREAL_LOAD_FUNCTION_NAME(*self, t, version);
|
||||
return *self;
|
||||
}
|
||||
|
||||
//! Member split (load_minimal)
|
||||
/*! Versioning implementation */
|
||||
template <class T, PROCESS_IF(member_versioned_load_minimal)> inline
|
||||
ArchiveType & processImpl(T & t)
|
||||
{
|
||||
using OutArchiveType = typename traits::detail::get_output_from_input<ArchiveType>::type;
|
||||
const auto version = loadClassVersion<T>();
|
||||
typename traits::has_member_versioned_save_minimal<T, OutArchiveType>::type value;
|
||||
self->process(value);
|
||||
access::member_load_minimal(*self, t, value, version);
|
||||
return *self;
|
||||
}
|
||||
|
||||
//! Non member split (load_minimal)
|
||||
/*! Versioning implementation */
|
||||
template <class T, PROCESS_IF(non_member_versioned_load_minimal)> inline
|
||||
ArchiveType & processImpl(T & t)
|
||||
{
|
||||
using OutArchiveType = typename traits::detail::get_output_from_input<ArchiveType>::type;
|
||||
const auto version = loadClassVersion<T>();
|
||||
typename traits::has_non_member_versioned_save_minimal<T, OutArchiveType>::type value;
|
||||
self->process(value);
|
||||
CEREAL_LOAD_MINIMAL_FUNCTION_NAME(*self, t, value, version);
|
||||
return *self;
|
||||
}
|
||||
|
||||
#undef PROCESS_IF
|
||||
|
||||
private:
|
||||
ArchiveType * const self;
|
||||
|
||||
//! A set of all base classes that have been serialized
|
||||
std::unordered_set<traits::detail::base_class_id, traits::detail::base_class_id_hash> itsBaseClassSet;
|
||||
|
||||
//! Maps from pointer ids to metadata
|
||||
std::unordered_map<std::uint32_t, std::shared_ptr<void>> itsSharedPointerMap;
|
||||
|
||||
//! Maps from name ids to names
|
||||
std::unordered_map<std::uint32_t, std::string> itsPolymorphicTypeMap;
|
||||
|
||||
//! Maps from type hash codes to version numbers
|
||||
std::unordered_map<std::size_t, std::uint32_t> itsVersionedTypes;
|
||||
}; // class InputArchive
|
||||
} // namespace cereal
|
||||
|
||||
// This include needs to come after things such as binary_data, make_nvp, etc
|
||||
#include <cereal/types/common.hpp>
|
||||
|
||||
#endif // CEREAL_CEREAL_HPP_
|
||||
360
libs/cereal/cereal/details/helpers.hpp
Normal file
360
libs/cereal/cereal/details/helpers.hpp
Normal file
@ -0,0 +1,360 @@
|
||||
/*! \file helpers.hpp
|
||||
\brief Internal helper functionality
|
||||
\ingroup Internal */
|
||||
/*
|
||||
Copyright (c) 2014, Randolph Voorhies, Shane Grant
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of cereal nor the
|
||||
names of its contributors may be used to endorse or promote products
|
||||
derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL RANDOLPH VOORHIES OR SHANE GRANT BE LIABLE FOR ANY
|
||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
#ifndef CEREAL_DETAILS_HELPERS_HPP_
|
||||
#define CEREAL_DETAILS_HELPERS_HPP_
|
||||
|
||||
#include <type_traits>
|
||||
#include <cstdint>
|
||||
#include <utility>
|
||||
#include <memory>
|
||||
#include <unordered_map>
|
||||
#include <stdexcept>
|
||||
|
||||
#include <cereal/macros.hpp>
|
||||
#include <cereal/details/static_object.hpp>
|
||||
|
||||
namespace cereal
|
||||
{
|
||||
// ######################################################################
|
||||
//! An exception class thrown when things go wrong at runtime
|
||||
/*! @ingroup Utility */
|
||||
struct Exception : public std::runtime_error
|
||||
{
|
||||
explicit Exception( const std::string & what_ ) : std::runtime_error(what_) {}
|
||||
explicit Exception( const char * what_ ) : std::runtime_error(what_) {}
|
||||
};
|
||||
|
||||
// ######################################################################
|
||||
//! The size type used by cereal
|
||||
/*! To ensure compatability between 32, 64, etc bit machines, we need to use
|
||||
a fixed size type instead of size_t, which may vary from machine to
|
||||
machine. */
|
||||
using size_type = uint64_t;
|
||||
|
||||
// forward decls
|
||||
class BinaryOutputArchive;
|
||||
class BinaryInputArchive;
|
||||
|
||||
// ######################################################################
|
||||
namespace detail
|
||||
{
|
||||
struct NameValuePairCore {}; //!< Traits struct for NVPs
|
||||
}
|
||||
|
||||
//! For holding name value pairs
|
||||
/*! This pairs a name (some string) with some value such that an archive
|
||||
can potentially take advantage of the pairing.
|
||||
|
||||
In serialization functions, NameValuePairs are usually created like so:
|
||||
@code{.cpp}
|
||||
struct MyStruct
|
||||
{
|
||||
int a, b, c, d, e;
|
||||
|
||||
template<class Archive>
|
||||
void serialize(Archive & archive)
|
||||
{
|
||||
archive( CEREAL_NVP(a),
|
||||
CEREAL_NVP(b),
|
||||
CEREAL_NVP(c),
|
||||
CEREAL_NVP(d),
|
||||
CEREAL_NVP(e) );
|
||||
}
|
||||
};
|
||||
@endcode
|
||||
|
||||
Alternatively, you can give you data members custom names like so:
|
||||
@code{.cpp}
|
||||
struct MyStruct
|
||||
{
|
||||
int a, b, my_embarrassing_variable_name, d, e;
|
||||
|
||||
template<class Archive>
|
||||
void serialize(Archive & archive)
|
||||
{
|
||||
archive( CEREAL_NVP(a),
|
||||
CEREAL_NVP(b),
|
||||
cereal::make_nvp("var", my_embarrassing_variable_name) );
|
||||
CEREAL_NVP(d),
|
||||
CEREAL_NVP(e) );
|
||||
}
|
||||
};
|
||||
@endcode
|
||||
|
||||
There is a slight amount of overhead to creating NameValuePairs, so there
|
||||
is a third method which will elide the names when they are not used by
|
||||
the Archive:
|
||||
|
||||
@code{.cpp}
|
||||
struct MyStruct
|
||||
{
|
||||
int a, b;
|
||||
|
||||
template<class Archive>
|
||||
void serialize(Archive & archive)
|
||||
{
|
||||
archive( cereal::make_nvp<Archive>(a),
|
||||
cereal::make_nvp<Archive>(b) );
|
||||
}
|
||||
};
|
||||
@endcode
|
||||
|
||||
This third method is generally only used when providing generic type
|
||||
support. Users writing their own serialize functions will normally
|
||||
explicitly control whether they want to use NVPs or not.
|
||||
|
||||
@internal */
|
||||
template <class T>
|
||||
class NameValuePair : detail::NameValuePairCore
|
||||
{
|
||||
private:
|
||||
// If we get passed an array, keep the type as is, otherwise store
|
||||
// a reference if we were passed an l value reference, else copy the value
|
||||
using Type = typename std::conditional<std::is_array<typename std::remove_reference<T>::type>::value,
|
||||
typename std::remove_cv<T>::type,
|
||||
typename std::conditional<std::is_lvalue_reference<T>::value,
|
||||
T,
|
||||
typename std::decay<T>::type>::type>::type;
|
||||
|
||||
// prevent nested nvps
|
||||
static_assert( !std::is_base_of<detail::NameValuePairCore, T>::value,
|
||||
"Cannot pair a name to a NameValuePair" );
|
||||
|
||||
NameValuePair & operator=( NameValuePair const & ) = delete;
|
||||
|
||||
public:
|
||||
//! Constructs a new NameValuePair
|
||||
/*! @param n The name of the pair
|
||||
@param v The value to pair. Ideally this should be an l-value reference so that
|
||||
the value can be both loaded and saved to. If you pass an r-value reference,
|
||||
the NameValuePair will store a copy of it instead of a reference. Thus you should
|
||||
only pass r-values in cases where this makes sense, such as the result of some
|
||||
size() call.
|
||||
@internal */
|
||||
NameValuePair( char const * n, T && v ) : name(n), value(std::forward<T>(v)) {}
|
||||
|
||||
char const * name;
|
||||
Type value;
|
||||
};
|
||||
|
||||
//! A specialization of make_nvp<> that simply forwards the value for binary archives
|
||||
/*! @relates NameValuePair
|
||||
@internal */
|
||||
template<class Archive, class T> inline
|
||||
typename
|
||||
std::enable_if<std::is_same<Archive, ::cereal::BinaryInputArchive>::value ||
|
||||
std::is_same<Archive, ::cereal::BinaryOutputArchive>::value,
|
||||
T && >::type
|
||||
make_nvp( const char *, T && value )
|
||||
{
|
||||
return std::forward<T>(value);
|
||||
}
|
||||
|
||||
//! A specialization of make_nvp<> that actually creates an nvp for non-binary archives
|
||||
/*! @relates NameValuePair
|
||||
@internal */
|
||||
template<class Archive, class T> inline
|
||||
typename
|
||||
std::enable_if<!std::is_same<Archive, ::cereal::BinaryInputArchive>::value &&
|
||||
!std::is_same<Archive, ::cereal::BinaryOutputArchive>::value,
|
||||
NameValuePair<T> >::type
|
||||
make_nvp( const char * name, T && value)
|
||||
{
|
||||
return {name, std::forward<T>(value)};
|
||||
}
|
||||
|
||||
//! Convenience for creating a templated NVP
|
||||
/*! For use in inteneral generic typing functions which have an
|
||||
Archive type declared
|
||||
@internal */
|
||||
#define CEREAL_NVP_(name, value) ::cereal::make_nvp<Archive>(name, value)
|
||||
|
||||
// ######################################################################
|
||||
//! A wrapper around data that can be serialized in a binary fashion
|
||||
/*! This class is used to demarcate data that can safely be serialized
|
||||
as a binary chunk of data. Individual archives can then choose how
|
||||
best represent this during serialization.
|
||||
|
||||
@internal */
|
||||
template <class T>
|
||||
struct BinaryData
|
||||
{
|
||||
//! Internally store the pointer as a void *, keeping const if created with
|
||||
//! a const pointer
|
||||
using PT = typename std::conditional<std::is_const<typename std::remove_pointer<T>::type>::value,
|
||||
const void *,
|
||||
void *>::type;
|
||||
|
||||
BinaryData( T && d, uint64_t s ) : data(std::forward<T>(d)), size(s) {}
|
||||
|
||||
PT data; //!< pointer to beginning of data
|
||||
uint64_t size; //!< size in bytes
|
||||
};
|
||||
|
||||
// ######################################################################
|
||||
namespace detail
|
||||
{
|
||||
// base classes for type checking
|
||||
/* The rtti virtual function only exists to enable an archive to
|
||||
be used in a polymorphic fashion, if necessary. See the
|
||||
archive adapters for an example of this */
|
||||
class OutputArchiveBase { private: virtual void rtti(){} };
|
||||
class InputArchiveBase { private: virtual void rtti(){} };
|
||||
|
||||
// forward decls for polymorphic support
|
||||
template <class Archive, class T> struct polymorphic_serialization_support;
|
||||
struct adl_tag;
|
||||
|
||||
// used during saving pointers
|
||||
static const int32_t msb_32bit = 0x80000000;
|
||||
static const int32_t msb2_32bit = 0x40000000;
|
||||
}
|
||||
|
||||
// ######################################################################
|
||||
//! A wrapper around size metadata
|
||||
/*! This class provides a way for archives to have more flexibility over how
|
||||
they choose to serialize size metadata for containers. For some archive
|
||||
types, the size may be implicitly encoded in the output (e.g. JSON) and
|
||||
not need an explicit entry. Specializing serialize or load/save for
|
||||
your archive and SizeTags allows you to choose what happens.
|
||||
|
||||
@internal */
|
||||
template <class T>
|
||||
class SizeTag
|
||||
{
|
||||
private:
|
||||
// Store a reference if passed an lvalue reference, otherwise
|
||||
// make a copy of the data
|
||||
using Type = typename std::conditional<std::is_lvalue_reference<T>::value,
|
||||
T,
|
||||
typename std::decay<T>::type>::type;
|
||||
|
||||
SizeTag & operator=( SizeTag const & ) = delete;
|
||||
|
||||
public:
|
||||
SizeTag( T && sz ) : size(std::forward<T>(sz)) {}
|
||||
|
||||
Type size;
|
||||
};
|
||||
|
||||
// ######################################################################
|
||||
//! A wrapper around a key and value for serializing data into maps.
|
||||
/*! This class just provides a grouping of keys and values into a struct for
|
||||
human readable archives. For example, XML archives will use this wrapper
|
||||
to write maps like so:
|
||||
|
||||
@code{.xml}
|
||||
<mymap>
|
||||
<item0>
|
||||
<key>MyFirstKey</key>
|
||||
<value>MyFirstValue</value>
|
||||
</item0>
|
||||
<item1>
|
||||
<key>MySecondKey</key>
|
||||
<value>MySecondValue</value>
|
||||
</item1>
|
||||
</mymap>
|
||||
@endcode
|
||||
|
||||
\sa make_map_item
|
||||
@internal */
|
||||
template <class Key, class Value>
|
||||
struct MapItem
|
||||
{
|
||||
using KeyType = typename std::conditional<
|
||||
std::is_lvalue_reference<Key>::value,
|
||||
Key,
|
||||
typename std::decay<Key>::type>::type;
|
||||
|
||||
using ValueType = typename std::conditional<
|
||||
std::is_lvalue_reference<Value>::value,
|
||||
Value,
|
||||
typename std::decay<Value>::type>::type;
|
||||
|
||||
//! Construct a MapItem from a key and a value
|
||||
/*! @internal */
|
||||
MapItem( Key && key_, Value && value_ ) : key(std::forward<Key>(key_)), value(std::forward<Value>(value_)) {}
|
||||
|
||||
MapItem & operator=( MapItem const & ) = delete;
|
||||
|
||||
KeyType key;
|
||||
ValueType value;
|
||||
|
||||
//! Serialize the MapItem with the NVPs "key" and "value"
|
||||
template <class Archive> inline
|
||||
void CEREAL_SERIALIZE_FUNCTION_NAME(Archive & archive)
|
||||
{
|
||||
archive( make_nvp<Archive>("key", key),
|
||||
make_nvp<Archive>("value", value) );
|
||||
}
|
||||
};
|
||||
|
||||
//! Create a MapItem so that human readable archives will group keys and values together
|
||||
/*! @internal
|
||||
@relates MapItem */
|
||||
template <class KeyType, class ValueType> inline
|
||||
MapItem<KeyType, ValueType> make_map_item(KeyType && key, ValueType && value)
|
||||
{
|
||||
return {std::forward<KeyType>(key), std::forward<ValueType>(value)};
|
||||
}
|
||||
|
||||
namespace detail
|
||||
{
|
||||
//! Tag for Version, which due to its anonymous namespace, becomes a different
|
||||
//! type in each translation unit
|
||||
/*! This allows CEREAL_CLASS_VERSION to be safely called in a header file */
|
||||
namespace{ struct version_binding_tag {}; }
|
||||
|
||||
// ######################################################################
|
||||
//! Version information class
|
||||
/*! This is the base case for classes that have not been explicitly
|
||||
registered */
|
||||
template <class T, class BindingTag = version_binding_tag> struct Version
|
||||
{
|
||||
static const std::uint32_t version = 0;
|
||||
// we don't need to explicitly register these types since they
|
||||
// always get a version number of 0
|
||||
};
|
||||
|
||||
//! Holds all registered version information
|
||||
struct Versions
|
||||
{
|
||||
std::unordered_map<std::size_t, std::uint32_t> mapping;
|
||||
|
||||
std::uint32_t find( std::size_t hash, std::uint32_t version )
|
||||
{
|
||||
const auto result = mapping.emplace( hash, version );
|
||||
return result.first->second;
|
||||
}
|
||||
}; // struct Versions
|
||||
} // namespace detail
|
||||
} // namespace cereal
|
||||
|
||||
#endif // CEREAL_DETAILS_HELPERS_HPP_
|
||||
437
libs/cereal/cereal/details/polymorphic_impl.hpp
Normal file
437
libs/cereal/cereal/details/polymorphic_impl.hpp
Normal file
@ -0,0 +1,437 @@
|
||||
/*! \file polymorphic_impl.hpp
|
||||
\brief Internal polymorphism support
|
||||
\ingroup Internal */
|
||||
/*
|
||||
Copyright (c) 2014, Randolph Voorhies, Shane Grant
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of cereal nor the
|
||||
names of its contributors may be used to endorse or promote products
|
||||
derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL RANDOLPH VOORHIES OR SHANE GRANT BE LIABLE FOR ANY
|
||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/* This code is heavily inspired by the boost serialization implementation by the following authors
|
||||
|
||||
(C) Copyright 2002 Robert Ramey - http://www.rrsd.com .
|
||||
Use, modification and distribution is subject to the Boost Software
|
||||
License, Version 1.0. (See http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
See http://www.boost.org for updates, documentation, and revision history.
|
||||
|
||||
(C) Copyright 2006 David Abrahams - http://www.boost.org.
|
||||
|
||||
See /boost/serialization/export.hpp and /boost/archive/detail/register_archive.hpp for their
|
||||
implementation.
|
||||
*/
|
||||
#ifndef CEREAL_DETAILS_POLYMORPHIC_IMPL_HPP_
|
||||
#define CEREAL_DETAILS_POLYMORPHIC_IMPL_HPP_
|
||||
|
||||
#include <cereal/details/static_object.hpp>
|
||||
#include <cereal/types/memory.hpp>
|
||||
#include <cereal/types/string.hpp>
|
||||
#include <functional>
|
||||
#include <typeindex>
|
||||
#include <map>
|
||||
|
||||
//! Binds a polymorhic type to all registered archives
|
||||
/*! This binds a polymorphic type to all compatible registered archives that
|
||||
have been registered with CEREAL_REGISTER_ARCHIVE. This must be called
|
||||
after all archives are registered (usually after the archives themselves
|
||||
have been included). */
|
||||
#define CEREAL_BIND_TO_ARCHIVES(T) \
|
||||
namespace cereal { \
|
||||
namespace detail { \
|
||||
template<> \
|
||||
struct init_binding<T> { \
|
||||
static bind_to_archives<T> const & b; \
|
||||
static void unused() { (void)b; } \
|
||||
}; \
|
||||
bind_to_archives<T> const & init_binding<T>::b = \
|
||||
::cereal::detail::StaticObject< \
|
||||
bind_to_archives<T> \
|
||||
>::getInstance().bind(); \
|
||||
}} /* end namespaces */
|
||||
|
||||
namespace cereal
|
||||
{
|
||||
namespace detail
|
||||
{
|
||||
//! Binds a compile time type with a user defined string
|
||||
template <class T>
|
||||
struct binding_name {};
|
||||
|
||||
//! A structure holding a map from type_indices to output serializer functions
|
||||
/*! A static object of this map should be created for each registered archive
|
||||
type, containing entries for every registered type that describe how to
|
||||
properly cast the type to its real type in polymorphic scenarios for
|
||||
shared_ptr, weak_ptr, and unique_ptr. */
|
||||
template <class Archive>
|
||||
struct OutputBindingMap
|
||||
{
|
||||
//! A serializer function
|
||||
/*! Serializer functions return nothing and take an archive as
|
||||
their first parameter (will be cast properly inside the function,
|
||||
and a pointer to actual data (contents of smart_ptr's get() function)
|
||||
as their second parameter */
|
||||
typedef std::function<void(void*, void const *)> Serializer;
|
||||
|
||||
//! Struct containing the serializer functions for all pointer types
|
||||
struct Serializers
|
||||
{
|
||||
Serializer shared_ptr, //!< Serializer function for shared/weak pointers
|
||||
unique_ptr; //!< Serializer function for unique pointers
|
||||
};
|
||||
|
||||
//! A map of serializers for pointers of all registered types
|
||||
std::map<std::type_index, Serializers> map;
|
||||
};
|
||||
|
||||
//! An empty noop deleter
|
||||
template<class T> struct EmptyDeleter { void operator()(T *) const {} };
|
||||
|
||||
//! A structure holding a map from type name strings to input serializer functions
|
||||
/*! A static object of this map should be created for each registered archive
|
||||
type, containing entries for every registered type that describe how to
|
||||
properly cast the type to its real type in polymorphic scenarios for
|
||||
shared_ptr, weak_ptr, and unique_ptr. */
|
||||
template <class Archive>
|
||||
struct InputBindingMap
|
||||
{
|
||||
//! Shared ptr serializer function
|
||||
/*! Serializer functions return nothing and take an archive as
|
||||
their first parameter (will be cast properly inside the function,
|
||||
and a shared_ptr (or unique_ptr for the unique case) of any base
|
||||
type. Internally it will properly be loaded and cast to the
|
||||
correct type. */
|
||||
typedef std::function<void(void*, std::shared_ptr<void> & )> SharedSerializer;
|
||||
//! Unique ptr serializer function
|
||||
typedef std::function<void(void*, std::unique_ptr<void, EmptyDeleter<void>> & )> UniqueSerializer;
|
||||
|
||||
//! Struct containing the serializer functions for all pointer types
|
||||
struct Serializers
|
||||
{
|
||||
SharedSerializer shared_ptr; //!< Serializer function for shared/weak pointers
|
||||
UniqueSerializer unique_ptr; //!< Serializer function for unique pointers
|
||||
};
|
||||
|
||||
//! A map of serializers for pointers of all registered types
|
||||
std::map<std::string, Serializers> map;
|
||||
};
|
||||
|
||||
// forward decls for archives from cereal.hpp
|
||||
class InputArchiveBase;
|
||||
class OutputArchiveBase;
|
||||
|
||||
//! Creates a binding (map entry) between an input archive type and a polymorphic type
|
||||
/*! Bindings are made when types are registered, assuming that at least one
|
||||
archive has already been registered. When this struct is created,
|
||||
it will insert (at run time) an entry into a map that properly handles
|
||||
casting for serializing polymorphic objects */
|
||||
template <class Archive, class T> struct InputBindingCreator
|
||||
{
|
||||
//! Initialize the binding
|
||||
InputBindingCreator()
|
||||
{
|
||||
auto & map = StaticObject<InputBindingMap<Archive>>::getInstance().map;
|
||||
auto key = std::string(binding_name<T>::name());
|
||||
auto lb = map.lower_bound(key);
|
||||
|
||||
if (lb != map.end() && lb->first == key)
|
||||
return;
|
||||
|
||||
typename InputBindingMap<Archive>::Serializers serializers;
|
||||
|
||||
serializers.shared_ptr =
|
||||
[](void * arptr, std::shared_ptr<void> & dptr)
|
||||
{
|
||||
Archive & ar = *static_cast<Archive*>(arptr);
|
||||
std::shared_ptr<T> ptr;
|
||||
|
||||
ar( CEREAL_NVP_("ptr_wrapper", ::cereal::memory_detail::make_ptr_wrapper(ptr)) );
|
||||
|
||||
dptr = ptr;
|
||||
};
|
||||
|
||||
serializers.unique_ptr =
|
||||
[](void * arptr, std::unique_ptr<void, EmptyDeleter<void>> & dptr)
|
||||
{
|
||||
Archive & ar = *static_cast<Archive*>(arptr);
|
||||
std::unique_ptr<T> ptr;
|
||||
|
||||
ar( CEREAL_NVP_("ptr_wrapper", ::cereal::memory_detail::make_ptr_wrapper(ptr)) );
|
||||
|
||||
dptr.reset(ptr.release());
|
||||
};
|
||||
|
||||
map.insert( lb, { std::move(key), std::move(serializers) } );
|
||||
}
|
||||
};
|
||||
|
||||
//! Creates a binding (map entry) between an output archive type and a polymorphic type
|
||||
/*! Bindings are made when types are registered, assuming that at least one
|
||||
archive has already been registered. When this struct is created,
|
||||
it will insert (at run time) an entry into a map that properly handles
|
||||
casting for serializing polymorphic objects */
|
||||
template <class Archive, class T> struct OutputBindingCreator
|
||||
{
|
||||
//! Writes appropriate metadata to the archive for this polymorphic type
|
||||
static void writeMetadata(Archive & ar)
|
||||
{
|
||||
// Register the polymorphic type name with the archive, and get the id
|
||||
char const * name = binding_name<T>::name();
|
||||
std::uint32_t id = ar.registerPolymorphicType(name);
|
||||
|
||||
// Serialize the id
|
||||
ar( CEREAL_NVP_("polymorphic_id", id) );
|
||||
|
||||
// If the msb of the id is 1, then the type name is new, and we should serialize it
|
||||
if( id & detail::msb_32bit )
|
||||
{
|
||||
std::string namestring(name);
|
||||
ar( CEREAL_NVP_("polymorphic_name", namestring) );
|
||||
}
|
||||
}
|
||||
|
||||
//! Holds a properly typed shared_ptr to the polymorphic type
|
||||
class PolymorphicSharedPointerWrapper
|
||||
{
|
||||
public:
|
||||
/*! Wrap a raw polymorphic pointer in a shared_ptr to its true type
|
||||
|
||||
The wrapped pointer will not be responsible for ownership of the held pointer
|
||||
so it will not attempt to destroy it; instead the refcount of the wrapped
|
||||
pointer will be tied to a fake 'ownership pointer' that will do nothing
|
||||
when it ultimately goes out of scope.
|
||||
|
||||
The main reason for doing this, other than not to destroy the true object
|
||||
with our wrapper pointer, is to avoid meddling with the internal reference
|
||||
count in a polymorphic type that inherits from std::enable_shared_from_this.
|
||||
|
||||
@param dptr A void pointer to the contents of the shared_ptr to serialize */
|
||||
PolymorphicSharedPointerWrapper( void const * dptr ) : refCount()
|
||||
{
|
||||
#ifdef _LIBCPP_VERSION
|
||||
// libc++ needs this hacky workaround, see http://llvm.org/bugs/show_bug.cgi?id=18843
|
||||
wrappedPtr = std::shared_ptr<T const>(
|
||||
std::const_pointer_cast<T const>(
|
||||
std::shared_ptr<T>( refCount, static_cast<T *>(const_cast<void *>(dptr) ))));
|
||||
#else // NOT _LIBCPP_VERSION
|
||||
wrappedPtr = std::shared_ptr<T const>( refCount, static_cast<T const *>(dptr) );
|
||||
#endif // _LIBCPP_VERSION
|
||||
}
|
||||
|
||||
//! Get the wrapped shared_ptr */
|
||||
inline std::shared_ptr<T const> const & operator()() const { return wrappedPtr; }
|
||||
|
||||
private:
|
||||
std::shared_ptr<void> refCount; //!< The ownership pointer
|
||||
std::shared_ptr<T const> wrappedPtr; //!< The wrapped pointer
|
||||
};
|
||||
|
||||
//! Does the actual work of saving a polymorphic shared_ptr
|
||||
/*! This function will properly create a shared_ptr from the void * that is passed in
|
||||
before passing it to the archive for serialization.
|
||||
|
||||
In addition, this will also preserve the state of any internal enable_shared_from_this mechanisms
|
||||
|
||||
@param ar The archive to serialize to
|
||||
@param dptr Pointer to the actual data held by the shared_ptr */
|
||||
static inline void savePolymorphicSharedPtr( Archive & ar, void const * dptr, std::true_type /* has_shared_from_this */ )
|
||||
{
|
||||
::cereal::memory_detail::EnableSharedStateHelper<T> state( static_cast<T *>(const_cast<void *>(dptr)) );
|
||||
PolymorphicSharedPointerWrapper psptr( dptr );
|
||||
ar( CEREAL_NVP_("ptr_wrapper", memory_detail::make_ptr_wrapper( psptr() ) ) );
|
||||
}
|
||||
|
||||
//! Does the actual work of saving a polymorphic shared_ptr
|
||||
/*! This function will properly create a shared_ptr from the void * that is passed in
|
||||
before passing it to the archive for serialization.
|
||||
|
||||
This version is for types that do not inherit from std::enable_shared_from_this.
|
||||
|
||||
@param ar The archive to serialize to
|
||||
@param dptr Pointer to the actual data held by the shared_ptr */
|
||||
static inline void savePolymorphicSharedPtr( Archive & ar, void const * dptr, std::false_type /* has_shared_from_this */ )
|
||||
{
|
||||
PolymorphicSharedPointerWrapper psptr( dptr );
|
||||
ar( CEREAL_NVP_("ptr_wrapper", memory_detail::make_ptr_wrapper( psptr() ) ) );
|
||||
}
|
||||
|
||||
//! Initialize the binding
|
||||
OutputBindingCreator()
|
||||
{
|
||||
auto & map = StaticObject<OutputBindingMap<Archive>>::getInstance().map;
|
||||
auto key = std::type_index(typeid(T));
|
||||
auto lb = map.lower_bound(key);
|
||||
|
||||
if (lb != map.end() && lb->first == key)
|
||||
return;
|
||||
|
||||
typename OutputBindingMap<Archive>::Serializers serializers;
|
||||
|
||||
serializers.shared_ptr =
|
||||
[&](void * arptr, void const * dptr)
|
||||
{
|
||||
Archive & ar = *static_cast<Archive*>(arptr);
|
||||
|
||||
writeMetadata(ar);
|
||||
|
||||
#ifdef _MSC_VER
|
||||
savePolymorphicSharedPtr( ar, dptr, ::cereal::traits::has_shared_from_this<T>::type() ); // MSVC doesn't like typename here
|
||||
#else // not _MSC_VER
|
||||
savePolymorphicSharedPtr( ar, dptr, typename ::cereal::traits::has_shared_from_this<T>::type() );
|
||||
#endif // _MSC_VER
|
||||
};
|
||||
|
||||
serializers.unique_ptr =
|
||||
[&](void * arptr, void const * dptr)
|
||||
{
|
||||
Archive & ar = *static_cast<Archive*>(arptr);
|
||||
|
||||
writeMetadata(ar);
|
||||
|
||||
std::unique_ptr<T const, EmptyDeleter<T const>> const ptr(static_cast<T const *>(dptr));
|
||||
|
||||
ar( CEREAL_NVP_("ptr_wrapper", memory_detail::make_ptr_wrapper(ptr)) );
|
||||
};
|
||||
|
||||
map.insert( { std::move(key), std::move(serializers) } );
|
||||
}
|
||||
};
|
||||
|
||||
//! Used to help out argument dependent lookup for finding potential overloads
|
||||
//! of instantiate_polymorphic_binding
|
||||
struct adl_tag {};
|
||||
|
||||
//! Tag for init_binding, bind_to_archives and instantiate_polymorphic_binding. Due to the use of anonymous
|
||||
//! namespace it becomes a different type in each translation unit.
|
||||
namespace { struct polymorphic_binding_tag {}; }
|
||||
|
||||
//! Causes the static object bindings between an archive type and a serializable type T
|
||||
template <class Archive, class T>
|
||||
struct create_bindings
|
||||
{
|
||||
static const InputBindingCreator<Archive, T> &
|
||||
load(std::true_type)
|
||||
{
|
||||
return cereal::detail::StaticObject<InputBindingCreator<Archive, T>>::getInstance();
|
||||
}
|
||||
|
||||
static const OutputBindingCreator<Archive, T> &
|
||||
save(std::true_type)
|
||||
{
|
||||
return cereal::detail::StaticObject<OutputBindingCreator<Archive, T>>::getInstance();
|
||||
}
|
||||
|
||||
inline static void load(std::false_type) {}
|
||||
inline static void save(std::false_type) {}
|
||||
};
|
||||
|
||||
//! When specialized, causes the compiler to instantiate its parameter
|
||||
template <void(*)()>
|
||||
struct instantiate_function {};
|
||||
|
||||
/*! This struct is used as the return type of instantiate_polymorphic_binding
|
||||
for specific Archive types. When the compiler looks for overloads of
|
||||
instantiate_polymorphic_binding, it will be forced to instantiate this
|
||||
struct during overload resolution, even though it will not be part of a valid
|
||||
overload */
|
||||
template <class Archive, class T>
|
||||
struct polymorphic_serialization_support
|
||||
{
|
||||
#if defined(_MSC_VER) && !defined(__INTEL_COMPILER)
|
||||
//! Creates the appropriate bindings depending on whether the archive supports
|
||||
//! saving or loading
|
||||
virtual CEREAL_DLL_EXPORT void instantiate() CEREAL_USED;
|
||||
#else // NOT _MSC_VER
|
||||
//! Creates the appropriate bindings depending on whether the archive supports
|
||||
//! saving or loading
|
||||
static CEREAL_DLL_EXPORT void instantiate() CEREAL_USED;
|
||||
//! This typedef causes the compiler to instantiate this static function
|
||||
typedef instantiate_function<instantiate> unused;
|
||||
#endif // _MSC_VER
|
||||
};
|
||||
|
||||
// instantiate implementation
|
||||
template <class Archive, class T>
|
||||
CEREAL_DLL_EXPORT void polymorphic_serialization_support<Archive,T>::instantiate()
|
||||
{
|
||||
create_bindings<Archive,T>::save( std::integral_constant<bool,
|
||||
std::is_base_of<detail::OutputArchiveBase, Archive>::value &&
|
||||
traits::is_output_serializable<T, Archive>::value>{} );
|
||||
|
||||
create_bindings<Archive,T>::load( std::integral_constant<bool,
|
||||
std::is_base_of<detail::InputArchiveBase, Archive>::value &&
|
||||
traits::is_input_serializable<T, Archive>::value>{} );
|
||||
}
|
||||
|
||||
//! Begins the binding process of a type to all registered archives
|
||||
/*! Archives need to be registered prior to this struct being instantiated via
|
||||
the CEREAL_REGISTER_ARCHIVE macro. Overload resolution will then force
|
||||
several static objects to be made that allow us to bind together all
|
||||
registered archive types with the parameter type T. */
|
||||
template <class T, class Tag = polymorphic_binding_tag>
|
||||
struct bind_to_archives
|
||||
{
|
||||
//! Binding for non abstract types
|
||||
void bind(std::false_type) const
|
||||
{
|
||||
instantiate_polymorphic_binding((T*) 0, 0, Tag{}, adl_tag{});
|
||||
}
|
||||
|
||||
//! Binding for abstract types
|
||||
void bind(std::true_type) const
|
||||
{ }
|
||||
|
||||
//! Binds the type T to all registered archives
|
||||
/*! If T is abstract, we will not serialize it and thus
|
||||
do not need to make a binding */
|
||||
bind_to_archives const & bind() const
|
||||
{
|
||||
static_assert( std::is_polymorphic<T>::value,
|
||||
"Attempting to register non polymorphic type" );
|
||||
bind( std::is_abstract<T>() );
|
||||
return *this;
|
||||
}
|
||||
};
|
||||
|
||||
//! Used to hide the static object used to bind T to registered archives
|
||||
template <class T, class Tag = polymorphic_binding_tag>
|
||||
struct init_binding;
|
||||
|
||||
//! Base case overload for instantiation
|
||||
/*! This will end up always being the best overload due to the second
|
||||
parameter always being passed as an int. All other overloads will
|
||||
accept pointers to archive types and have lower precedence than int.
|
||||
|
||||
Since the compiler needs to check all possible overloads, the
|
||||
other overloads created via CEREAL_REGISTER_ARCHIVE, which will have
|
||||
lower precedence due to requring a conversion from int to (Archive*),
|
||||
will cause their return types to be instantiated through the static object
|
||||
mechanisms even though they are never called.
|
||||
|
||||
See the documentation for the other functions to try and understand this */
|
||||
template <class T, typename BindingTag>
|
||||
void instantiate_polymorphic_binding( T*, int, BindingTag, adl_tag ) {}
|
||||
} // namespace detail
|
||||
} // namespace cereal
|
||||
|
||||
#endif // CEREAL_DETAILS_POLYMORPHIC_IMPL_HPP_
|
||||
90
libs/cereal/cereal/details/static_object.hpp
Normal file
90
libs/cereal/cereal/details/static_object.hpp
Normal file
@ -0,0 +1,90 @@
|
||||
/*! \file static_object.hpp
|
||||
\brief Internal polymorphism static object support
|
||||
\ingroup Internal */
|
||||
/*
|
||||
Copyright (c) 2014, Randolph Voorhies, Shane Grant
|
||||
All rights reserved.
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of cereal nor the
|
||||
names of its contributors may be used to endorse or promote products
|
||||
derived from this software without specific prior written permission.
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL RANDOLPH VOORHIES OR SHANE GRANT BE LIABLE FOR ANY
|
||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
#ifndef CEREAL_DETAILS_STATIC_OBJECT_HPP_
|
||||
#define CEREAL_DETAILS_STATIC_OBJECT_HPP_
|
||||
|
||||
//! Prevent link optimization from removing non-referenced static objects
|
||||
/*! Especially for polymorphic support, we create static objects which
|
||||
may not ever be explicitly referenced. Most linkers will detect this
|
||||
and remove the code causing various unpleasant runtime errors. These
|
||||
macros, adopted from Boost (see force_include.hpp) prevent this
|
||||
(C) Copyright 2002 Robert Ramey - http://www.rrsd.com .
|
||||
Use, modification and distribution is subject to the Boost Software
|
||||
License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
|
||||
http://www.boost.org/LICENSE_1_0.txt) */
|
||||
|
||||
#ifdef _MSC_VER
|
||||
# define CEREAL_DLL_EXPORT __declspec(dllexport)
|
||||
# define CEREAL_USED
|
||||
#else // clang or gcc
|
||||
# define CEREAL_DLL_EXPORT
|
||||
# define CEREAL_USED __attribute__ ((__used__))
|
||||
#endif
|
||||
|
||||
namespace cereal
|
||||
{
|
||||
namespace detail
|
||||
{
|
||||
//! A static, pre-execution object
|
||||
/*! This class will create a single copy (singleton) of some
|
||||
type and ensures that merely referencing this type will
|
||||
cause it to be instantiated and initialized pre-execution.
|
||||
For example, this is used heavily in the polymorphic pointer
|
||||
serialization mechanisms to bind various archive types with
|
||||
different polymorphic classes */
|
||||
template <class T>
|
||||
class CEREAL_DLL_EXPORT StaticObject
|
||||
{
|
||||
private:
|
||||
//! Forces instantiation at pre-execution time
|
||||
static void instantiate( T const & ) {}
|
||||
|
||||
static T & create()
|
||||
{
|
||||
static T t;
|
||||
instantiate(instance);
|
||||
return t;
|
||||
}
|
||||
|
||||
StaticObject( StaticObject const & /*other*/ ) {}
|
||||
|
||||
public:
|
||||
static T & getInstance()
|
||||
{
|
||||
return create();
|
||||
}
|
||||
|
||||
private:
|
||||
static T & instance;
|
||||
};
|
||||
|
||||
template <class T> T & StaticObject<T>::instance = StaticObject<T>::create();
|
||||
} // namespace detail
|
||||
} // namespace cereal
|
||||
|
||||
#endif // CEREAL_DETAILS_STATIC_OBJECT_HPP_
|
||||
1325
libs/cereal/cereal/details/traits.hpp
Normal file
1325
libs/cereal/cereal/details/traits.hpp
Normal file
File diff suppressed because it is too large
Load Diff
84
libs/cereal/cereal/details/util.hpp
Normal file
84
libs/cereal/cereal/details/util.hpp
Normal file
@ -0,0 +1,84 @@
|
||||
/*! \file util.hpp
|
||||
\brief Internal misc utilities
|
||||
\ingroup Internal */
|
||||
/*
|
||||
Copyright (c) 2014, Randolph Voorhies, Shane Grant
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of cereal nor the
|
||||
names of its contributors may be used to endorse or promote products
|
||||
derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL RANDOLPH VOORHIES OR SHANE GRANT BE LIABLE FOR ANY
|
||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
#ifndef CEREAL_DETAILS_UTIL_HPP_
|
||||
#define CEREAL_DETAILS_UTIL_HPP_
|
||||
|
||||
#include <typeinfo>
|
||||
#include <string>
|
||||
|
||||
#ifdef _MSC_VER
|
||||
namespace cereal
|
||||
{
|
||||
namespace util
|
||||
{
|
||||
//! Demangles the type encoded in a string
|
||||
/*! @internal */
|
||||
inline std::string demangle( std::string const & name )
|
||||
{ return name; }
|
||||
|
||||
//! Gets the demangled name of a type
|
||||
/*! @internal */
|
||||
template <class T> inline
|
||||
std::string demangledName()
|
||||
{ return typeid( T ).name(); }
|
||||
} // namespace util
|
||||
} // namespace cereal
|
||||
#else // clang or gcc
|
||||
#include <cxxabi.h>
|
||||
#include <cstdlib>
|
||||
namespace cereal
|
||||
{
|
||||
namespace util
|
||||
{
|
||||
//! Demangles the type encoded in a string
|
||||
/*! @internal */
|
||||
inline std::string demangle(std::string mangledName)
|
||||
{
|
||||
int status = 0;
|
||||
char *demangledName = nullptr;
|
||||
std::size_t len;
|
||||
|
||||
demangledName = abi::__cxa_demangle(mangledName.c_str(), 0, &len, &status);
|
||||
|
||||
std::string retName(demangledName);
|
||||
free(demangledName);
|
||||
|
||||
return retName;
|
||||
}
|
||||
|
||||
//! Gets the demangled name of a type
|
||||
/*! @internal */
|
||||
template<class T> inline
|
||||
std::string demangledName()
|
||||
{ return demangle(typeid(T).name()); }
|
||||
}
|
||||
} // namespace cereal
|
||||
#endif // clang or gcc branch of _MSC_VER
|
||||
#endif // CEREAL_DETAILS_UTIL_HPP_
|
||||
125
libs/cereal/cereal/external/base64.hpp
vendored
Normal file
125
libs/cereal/cereal/external/base64.hpp
vendored
Normal file
@ -0,0 +1,125 @@
|
||||
/*
|
||||
Copyright (C) 2004-2008 René Nyffenegger
|
||||
|
||||
This source code is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the author be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this source code must not be misrepresented; you must not
|
||||
claim that you wrote the original source code. If you use this source code
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original source code.
|
||||
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
|
||||
René Nyffenegger rene.nyffenegger@adp-gmbh.ch
|
||||
*/
|
||||
|
||||
#ifndef CEREAL_EXTERNAL_BASE64_HPP_
|
||||
#define CEREAL_EXTERNAL_BASE64_HPP_
|
||||
|
||||
#include <string>
|
||||
|
||||
namespace base64
|
||||
{
|
||||
static const std::string chars =
|
||||
"ABCDEFGHIJKLMNOPQRSTUVWXYZ"
|
||||
"abcdefghijklmnopqrstuvwxyz"
|
||||
"0123456789+/";
|
||||
|
||||
static inline bool is_base64(unsigned char c) {
|
||||
return (isalnum(c) || (c == '+') || (c == '/'));
|
||||
}
|
||||
|
||||
inline std::string encode(unsigned char const* bytes_to_encode, size_t in_len) {
|
||||
std::string ret;
|
||||
int i = 0;
|
||||
int j = 0;
|
||||
unsigned char char_array_3[3];
|
||||
unsigned char char_array_4[4];
|
||||
|
||||
while (in_len--) {
|
||||
char_array_3[i++] = *(bytes_to_encode++);
|
||||
if (i == 3) {
|
||||
char_array_4[0] = (unsigned char) ((char_array_3[0] & 0xfc) >> 2);
|
||||
char_array_4[1] = (unsigned char) ( ( ( char_array_3[0] & 0x03 ) << 4 ) + ( ( char_array_3[1] & 0xf0 ) >> 4 ) );
|
||||
char_array_4[2] = (unsigned char) ( ( ( char_array_3[1] & 0x0f ) << 2 ) + ( ( char_array_3[2] & 0xc0 ) >> 6 ) );
|
||||
char_array_4[3] = (unsigned char) ( char_array_3[2] & 0x3f );
|
||||
|
||||
for(i = 0; (i <4) ; i++)
|
||||
ret += chars[char_array_4[i]];
|
||||
i = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (i)
|
||||
{
|
||||
for(j = i; j < 3; j++)
|
||||
char_array_3[j] = '\0';
|
||||
|
||||
char_array_4[0] = (char_array_3[0] & 0xfc) >> 2;
|
||||
char_array_4[1] = ((char_array_3[0] & 0x03) << 4) + ((char_array_3[1] & 0xf0) >> 4);
|
||||
char_array_4[2] = ((char_array_3[1] & 0x0f) << 2) + ((char_array_3[2] & 0xc0) >> 6);
|
||||
char_array_4[3] = char_array_3[2] & 0x3f;
|
||||
|
||||
for (j = 0; (j < i + 1); j++)
|
||||
ret += chars[char_array_4[j]];
|
||||
|
||||
while((i++ < 3))
|
||||
ret += '=';
|
||||
|
||||
}
|
||||
|
||||
return ret;
|
||||
|
||||
}
|
||||
|
||||
inline std::string decode(std::string const& encoded_string) {
|
||||
size_t in_len = encoded_string.size();
|
||||
size_t i = 0;
|
||||
size_t j = 0;
|
||||
int in_ = 0;
|
||||
unsigned char char_array_4[4], char_array_3[3];
|
||||
std::string ret;
|
||||
|
||||
while (in_len-- && ( encoded_string[in_] != '=') && is_base64(encoded_string[in_])) {
|
||||
char_array_4[i++] = encoded_string[in_]; in_++;
|
||||
if (i ==4) {
|
||||
for (i = 0; i <4; i++)
|
||||
char_array_4[i] = (unsigned char) chars.find( char_array_4[i] );
|
||||
|
||||
char_array_3[0] = (char_array_4[0] << 2) + ((char_array_4[1] & 0x30) >> 4);
|
||||
char_array_3[1] = ((char_array_4[1] & 0xf) << 4) + ((char_array_4[2] & 0x3c) >> 2);
|
||||
char_array_3[2] = ((char_array_4[2] & 0x3) << 6) + char_array_4[3];
|
||||
|
||||
for (i = 0; (i < 3); i++)
|
||||
ret += char_array_3[i];
|
||||
i = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (i) {
|
||||
for (j = i; j <4; j++)
|
||||
char_array_4[j] = 0;
|
||||
|
||||
for (j = 0; j <4; j++)
|
||||
char_array_4[j] = (unsigned char) chars.find( char_array_4[j] );
|
||||
|
||||
char_array_3[0] = (char_array_4[0] << 2) + ((char_array_4[1] & 0x30) >> 4);
|
||||
char_array_3[1] = ((char_array_4[1] & 0xf) << 4) + ((char_array_4[2] & 0x3c) >> 2);
|
||||
char_array_3[2] = ((char_array_4[2] & 0x3) << 6) + char_array_4[3];
|
||||
|
||||
for (j = 0; (j < i - 1); j++) ret += char_array_3[j];
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
} // base64
|
||||
#endif // CEREAL_EXTERNAL_BASE64_HPP_
|
||||
821
libs/cereal/cereal/external/rapidjson/document.h
vendored
Normal file
821
libs/cereal/cereal/external/rapidjson/document.h
vendored
Normal file
@ -0,0 +1,821 @@
|
||||
#ifndef RAPIDJSON_DOCUMENT_H_
|
||||
#define RAPIDJSON_DOCUMENT_H_
|
||||
|
||||
#include "reader.h"
|
||||
#include "internal/strfunc.h"
|
||||
#include <new> // placement new
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable : 4127) // conditional expression is constant
|
||||
#endif
|
||||
|
||||
namespace rapidjson {
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// GenericValue
|
||||
|
||||
//! Represents a JSON value. Use Value for UTF8 encoding and default allocator.
|
||||
/*!
|
||||
A JSON value can be one of 7 types. This class is a variant type supporting
|
||||
these types.
|
||||
|
||||
Use the Value if UTF8 and default allocator
|
||||
|
||||
\tparam Encoding Encoding of the value. (Even non-string values need to have the same encoding in a document)
|
||||
\tparam Allocator Allocator type for allocating memory of object, array and string.
|
||||
*/
|
||||
#pragma pack (push, 4)
|
||||
template <typename Encoding, typename Allocator = MemoryPoolAllocator<> >
|
||||
class GenericValue {
|
||||
public:
|
||||
//! Name-value pair in an object.
|
||||
struct Member {
|
||||
GenericValue<Encoding, Allocator> name; //!< name of member (must be a string)
|
||||
GenericValue<Encoding, Allocator> value; //!< value of member.
|
||||
};
|
||||
|
||||
typedef Encoding EncodingType; //!< Encoding type from template parameter.
|
||||
typedef Allocator AllocatorType; //!< Allocator type from template parameter.
|
||||
typedef typename Encoding::Ch Ch; //!< Character type derived from Encoding.
|
||||
typedef Member* MemberIterator; //!< Member iterator for iterating in object.
|
||||
typedef const Member* ConstMemberIterator; //!< Constant member iterator for iterating in object.
|
||||
typedef GenericValue* ValueIterator; //!< Value iterator for iterating in array.
|
||||
typedef const GenericValue* ConstValueIterator; //!< Constant value iterator for iterating in array.
|
||||
|
||||
//!@name Constructors and destructor.
|
||||
//@{
|
||||
|
||||
//! Default constructor creates a null value.
|
||||
GenericValue() : flags_(kNull_Flag) {}
|
||||
|
||||
//! Copy constructor is not permitted.
|
||||
private:
|
||||
GenericValue(const GenericValue& rhs);
|
||||
|
||||
public:
|
||||
|
||||
//! Constructor with JSON value type.
|
||||
/*! This creates a Value of specified type with default content.
|
||||
\param type Type of the value.
|
||||
\note Default content for number is zero.
|
||||
*/
|
||||
GenericValue(Type type) {
|
||||
static const unsigned defaultFlags[7] = {
|
||||
kNull_Flag, kFalseFlag, kTrueFlag, kObjectFlag, kArrayFlag, kConstStringFlag,
|
||||
kNumberFlag | kIntFlag | kUintFlag | kInt64Flag | kUint64Flag | kDoubleFlag
|
||||
};
|
||||
RAPIDJSON_ASSERT(type <= kNumberType);
|
||||
flags_ = defaultFlags[type];
|
||||
memset(&data_, 0, sizeof(data_));
|
||||
}
|
||||
|
||||
//! Constructor for boolean value.
|
||||
GenericValue(bool b) : flags_(b ? kTrueFlag : kFalseFlag) {}
|
||||
|
||||
//! Constructor for int value.
|
||||
GenericValue(int i) : flags_(kNumberIntFlag) {
|
||||
data_.n.i64 = i;
|
||||
if (i >= 0)
|
||||
flags_ |= kUintFlag | kUint64Flag;
|
||||
}
|
||||
|
||||
//! Constructor for unsigned value.
|
||||
GenericValue(unsigned u) : flags_(kNumberUintFlag) {
|
||||
data_.n.u64 = u;
|
||||
if (!(u & 0x80000000))
|
||||
flags_ |= kIntFlag | kInt64Flag;
|
||||
}
|
||||
|
||||
//! Constructor for int64_t value.
|
||||
GenericValue(int64_t i64) : flags_(kNumberInt64Flag) {
|
||||
data_.n.i64 = i64;
|
||||
if (i64 >= 0) {
|
||||
flags_ |= kNumberUint64Flag;
|
||||
if (!(i64 & 0xFFFFFFFF00000000LL))
|
||||
flags_ |= kUintFlag;
|
||||
if (!(i64 & 0xFFFFFFFF80000000LL))
|
||||
flags_ |= kIntFlag;
|
||||
}
|
||||
else if (i64 >= -2147483648LL)
|
||||
flags_ |= kIntFlag;
|
||||
}
|
||||
|
||||
//! Constructor for uint64_t value.
|
||||
GenericValue(uint64_t u64) : flags_(kNumberUint64Flag) {
|
||||
data_.n.u64 = u64;
|
||||
if (!(u64 & 0x8000000000000000ULL))
|
||||
flags_ |= kInt64Flag;
|
||||
if (!(u64 & 0xFFFFFFFF00000000ULL))
|
||||
flags_ |= kUintFlag;
|
||||
if (!(u64 & 0xFFFFFFFF80000000ULL))
|
||||
flags_ |= kIntFlag;
|
||||
}
|
||||
|
||||
//! Constructor for double value.
|
||||
GenericValue(double d) : flags_(kNumberDoubleFlag) { data_.n.d = d; }
|
||||
|
||||
//! Constructor for constant string (i.e. do not make a copy of string)
|
||||
GenericValue(const Ch* s, SizeType length) {
|
||||
RAPIDJSON_ASSERT(s != NULL);
|
||||
flags_ = kConstStringFlag;
|
||||
data_.s.str = s;
|
||||
data_.s.length = length;
|
||||
}
|
||||
|
||||
//! Constructor for constant string (i.e. do not make a copy of string)
|
||||
GenericValue(const Ch* s) { SetStringRaw(s, internal::StrLen(s)); }
|
||||
|
||||
//! Constructor for copy-string (i.e. do make a copy of string)
|
||||
GenericValue(const Ch* s, SizeType length, Allocator& allocator) { SetStringRaw(s, length, allocator); }
|
||||
|
||||
//! Constructor for copy-string (i.e. do make a copy of string)
|
||||
GenericValue(const Ch*s, Allocator& allocator) { SetStringRaw(s, internal::StrLen(s), allocator); }
|
||||
|
||||
//! Destructor.
|
||||
/*! Need to destruct elements of array, members of object, or copy-string.
|
||||
*/
|
||||
~GenericValue() {
|
||||
if (Allocator::kNeedFree) { // Shortcut by Allocator's trait
|
||||
switch(flags_) {
|
||||
case kArrayFlag:
|
||||
for (GenericValue* v = data_.a.elements; v != data_.a.elements + data_.a.size; ++v)
|
||||
v->~GenericValue();
|
||||
Allocator::Free(data_.a.elements);
|
||||
break;
|
||||
|
||||
case kObjectFlag:
|
||||
for (Member* m = data_.o.members; m != data_.o.members + data_.o.size; ++m) {
|
||||
m->name.~GenericValue();
|
||||
m->value.~GenericValue();
|
||||
}
|
||||
Allocator::Free(data_.o.members);
|
||||
break;
|
||||
|
||||
case kCopyStringFlag:
|
||||
Allocator::Free(const_cast<Ch*>(data_.s.str));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//@}
|
||||
|
||||
//!@name Assignment operators
|
||||
//@{
|
||||
|
||||
//! Assignment with move semantics.
|
||||
/*! \param rhs Source of the assignment. It will become a null value after assignment.
|
||||
*/
|
||||
GenericValue& operator=(GenericValue& rhs) {
|
||||
RAPIDJSON_ASSERT(this != &rhs);
|
||||
this->~GenericValue();
|
||||
memcpy(this, &rhs, sizeof(GenericValue));
|
||||
rhs.flags_ = kNull_Flag;
|
||||
return *this;
|
||||
}
|
||||
|
||||
//! Assignment with primitive types.
|
||||
/*! \tparam T Either Type, int, unsigned, int64_t, uint64_t, const Ch*
|
||||
\param value The value to be assigned.
|
||||
*/
|
||||
template <typename T>
|
||||
GenericValue& operator=(T value) {
|
||||
this->~GenericValue();
|
||||
new (this) GenericValue(value);
|
||||
return *this;
|
||||
}
|
||||
//@}
|
||||
|
||||
//!@name Type
|
||||
//@{
|
||||
|
||||
Type GetType() const { return static_cast<Type>(flags_ & kTypeMask); }
|
||||
bool IsNull_() const { return flags_ == kNull_Flag; }
|
||||
bool IsFalse() const { return flags_ == kFalseFlag; }
|
||||
bool IsTrue() const { return flags_ == kTrueFlag; }
|
||||
bool IsBool_() const { return (flags_ & kBool_Flag) != 0; }
|
||||
bool IsObject() const { return flags_ == kObjectFlag; }
|
||||
bool IsArray() const { return flags_ == kArrayFlag; }
|
||||
bool IsNumber() const { return (flags_ & kNumberFlag) != 0; }
|
||||
bool IsInt() const { return (flags_ & kIntFlag) != 0; }
|
||||
bool IsUint() const { return (flags_ & kUintFlag) != 0; }
|
||||
bool IsInt64() const { return (flags_ & kInt64Flag) != 0; }
|
||||
bool IsUint64() const { return (flags_ & kUint64Flag) != 0; }
|
||||
bool IsDouble() const { return (flags_ & kDoubleFlag) != 0; }
|
||||
bool IsString() const { return (flags_ & kStringFlag) != 0; }
|
||||
|
||||
//@}
|
||||
|
||||
//!@name Null_
|
||||
//@{
|
||||
|
||||
GenericValue& SetNull_() { this->~GenericValue(); new (this) GenericValue(); return *this; }
|
||||
|
||||
//@}
|
||||
|
||||
//!@name Bool_
|
||||
//@{
|
||||
|
||||
bool GetBool_() const { RAPIDJSON_ASSERT(IsBool_()); return flags_ == kTrueFlag; }
|
||||
GenericValue& SetBool_(bool b) { this->~GenericValue(); new (this) GenericValue(b); return *this; }
|
||||
|
||||
//@}
|
||||
|
||||
//!@name Object
|
||||
//@{
|
||||
|
||||
//! Set this value as an empty object.
|
||||
GenericValue& SetObject() { this->~GenericValue(); new (this) GenericValue(kObjectType); return *this; }
|
||||
|
||||
//! Get the value associated with the object's name.
|
||||
GenericValue& operator[](const Ch* name) {
|
||||
if (Member* member = FindMember(name))
|
||||
return member->value;
|
||||
else {
|
||||
static GenericValue Null_Value;
|
||||
return Null_Value;
|
||||
}
|
||||
}
|
||||
const GenericValue& operator[](const Ch* name) const { return const_cast<GenericValue&>(*this)[name]; }
|
||||
|
||||
//! Member iterators.
|
||||
ConstMemberIterator MemberBegin() const { RAPIDJSON_ASSERT(IsObject()); return data_.o.members; }
|
||||
ConstMemberIterator MemberEnd() const { RAPIDJSON_ASSERT(IsObject()); return data_.o.members + data_.o.size; }
|
||||
MemberIterator MemberBegin() { RAPIDJSON_ASSERT(IsObject()); return data_.o.members; }
|
||||
MemberIterator MemberEnd() { RAPIDJSON_ASSERT(IsObject()); return data_.o.members + data_.o.size; }
|
||||
|
||||
//! Check whether a member exists in the object.
|
||||
bool HasMember(const Ch* name) const { return FindMember(name) != 0; }
|
||||
|
||||
//! Add a member (name-value pair) to the object.
|
||||
/*! \param name A string value as name of member.
|
||||
\param value Value of any type.
|
||||
\param allocator Allocator for reallocating memory.
|
||||
\return The value itself for fluent API.
|
||||
\note The ownership of name and value will be transfered to this object if success.
|
||||
*/
|
||||
GenericValue& AddMember(GenericValue& name, GenericValue& value, Allocator& allocator) {
|
||||
RAPIDJSON_ASSERT(IsObject());
|
||||
RAPIDJSON_ASSERT(name.IsString());
|
||||
Object& o = data_.o;
|
||||
if (o.size >= o.capacity) {
|
||||
if (o.capacity == 0) {
|
||||
o.capacity = kDefaultObjectCapacity;
|
||||
o.members = (Member*)allocator.Malloc(o.capacity * sizeof(Member));
|
||||
}
|
||||
else {
|
||||
SizeType oldCapacity = o.capacity;
|
||||
o.capacity *= 2;
|
||||
o.members = (Member*)allocator.Realloc(o.members, oldCapacity * sizeof(Member), o.capacity * sizeof(Member));
|
||||
}
|
||||
}
|
||||
o.members[o.size].name.RawAssign(name);
|
||||
o.members[o.size].value.RawAssign(value);
|
||||
o.size++;
|
||||
return *this;
|
||||
}
|
||||
|
||||
GenericValue& AddMember(const Ch* name, Allocator& nameAllocator, GenericValue& value, Allocator& allocator) {
|
||||
GenericValue n(name, internal::StrLen(name), nameAllocator);
|
||||
return AddMember(n, value, allocator);
|
||||
}
|
||||
|
||||
GenericValue& AddMember(const Ch* name, GenericValue& value, Allocator& allocator) {
|
||||
GenericValue n(name, internal::StrLen(name));
|
||||
return AddMember(n, value, allocator);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
GenericValue& AddMember(const Ch* name, T value, Allocator& allocator) {
|
||||
GenericValue n(name, internal::StrLen(name));
|
||||
GenericValue v(value);
|
||||
return AddMember(n, v, allocator);
|
||||
}
|
||||
|
||||
//! Remove a member in object by its name.
|
||||
/*! \param name Name of member to be removed.
|
||||
\return Whether the member existed.
|
||||
\note Removing member is implemented by moving the last member. So the ordering of members is changed.
|
||||
*/
|
||||
bool RemoveMember(const Ch* name) {
|
||||
RAPIDJSON_ASSERT(IsObject());
|
||||
if (Member* m = FindMember(name)) {
|
||||
RAPIDJSON_ASSERT(data_.o.size > 0);
|
||||
RAPIDJSON_ASSERT(data_.o.members != 0);
|
||||
|
||||
Member* last = data_.o.members + (data_.o.size - 1);
|
||||
if (data_.o.size > 1 && m != last) {
|
||||
// Move the last one to this place
|
||||
m->name = last->name;
|
||||
m->value = last->value;
|
||||
}
|
||||
else {
|
||||
// Only one left, just destroy
|
||||
m->name.~GenericValue();
|
||||
m->value.~GenericValue();
|
||||
}
|
||||
--data_.o.size;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
//@}
|
||||
|
||||
//!@name Array
|
||||
//@{
|
||||
|
||||
//! Set this value as an empty array.
|
||||
GenericValue& SetArray() { this->~GenericValue(); new (this) GenericValue(kArrayType); return *this; }
|
||||
|
||||
//! Get the number of elements in array.
|
||||
SizeType Size() const { RAPIDJSON_ASSERT(IsArray()); return data_.a.size; }
|
||||
|
||||
//! Get the capacity of array.
|
||||
SizeType Capacity() const { RAPIDJSON_ASSERT(IsArray()); return data_.a.capacity; }
|
||||
|
||||
//! Check whether the array is empty.
|
||||
bool Empty() const { RAPIDJSON_ASSERT(IsArray()); return data_.a.size == 0; }
|
||||
|
||||
//! Remove all elements in the array.
|
||||
/*! This function do not deallocate memory in the array, i.e. the capacity is unchanged.
|
||||
*/
|
||||
void Clear() {
|
||||
RAPIDJSON_ASSERT(IsArray());
|
||||
for (SizeType i = 0; i < data_.a.size; ++i)
|
||||
data_.a.elements[i].~GenericValue();
|
||||
data_.a.size = 0;
|
||||
}
|
||||
|
||||
//! Get an element from array by index.
|
||||
/*! \param index Zero-based index of element.
|
||||
\note
|
||||
\code
|
||||
Value a(kArrayType);
|
||||
a.PushBack(123);
|
||||
int x = a[0].GetInt(); // Error: operator[ is ambiguous, as 0 also mean a null pointer of const char* type.
|
||||
int y = a[SizeType(0)].GetInt(); // Cast to SizeType will work.
|
||||
int z = a[0u].GetInt(); // This works too.
|
||||
\endcode
|
||||
*/
|
||||
GenericValue& operator[](SizeType index) {
|
||||
RAPIDJSON_ASSERT(IsArray());
|
||||
RAPIDJSON_ASSERT(index < data_.a.size);
|
||||
return data_.a.elements[index];
|
||||
}
|
||||
const GenericValue& operator[](SizeType index) const { return const_cast<GenericValue&>(*this)[index]; }
|
||||
|
||||
//! Element iterator
|
||||
ValueIterator Begin() { RAPIDJSON_ASSERT(IsArray()); return data_.a.elements; }
|
||||
ValueIterator End() { RAPIDJSON_ASSERT(IsArray()); return data_.a.elements + data_.a.size; }
|
||||
ConstValueIterator Begin() const { return const_cast<GenericValue&>(*this).Begin(); }
|
||||
ConstValueIterator End() const { return const_cast<GenericValue&>(*this).End(); }
|
||||
|
||||
//! Request the array to have enough capacity to store elements.
|
||||
/*! \param newCapacity The capacity that the array at least need to have.
|
||||
\param allocator The allocator for allocating memory. It must be the same one use previously.
|
||||
\return The value itself for fluent API.
|
||||
*/
|
||||
GenericValue& Reserve(SizeType newCapacity, Allocator &allocator) {
|
||||
RAPIDJSON_ASSERT(IsArray());
|
||||
if (newCapacity > data_.a.capacity) {
|
||||
data_.a.elements = (GenericValue*)allocator.Realloc(data_.a.elements, data_.a.capacity * sizeof(GenericValue), newCapacity * sizeof(GenericValue));
|
||||
data_.a.capacity = newCapacity;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
//! Append a value at the end of the array.
|
||||
/*! \param value The value to be appended.
|
||||
\param allocator The allocator for allocating memory. It must be the same one use previously.
|
||||
\return The value itself for fluent API.
|
||||
\note The ownership of the value will be transfered to this object if success.
|
||||
\note If the number of elements to be appended is known, calls Reserve() once first may be more efficient.
|
||||
*/
|
||||
GenericValue& PushBack(GenericValue& value, Allocator& allocator) {
|
||||
RAPIDJSON_ASSERT(IsArray());
|
||||
if (data_.a.size >= data_.a.capacity)
|
||||
Reserve(data_.a.capacity == 0 ? kDefaultArrayCapacity : data_.a.capacity * 2, allocator);
|
||||
data_.a.elements[data_.a.size++].RawAssign(value);
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
GenericValue& PushBack(T value, Allocator& allocator) {
|
||||
GenericValue v(value);
|
||||
return PushBack(v, allocator);
|
||||
}
|
||||
|
||||
//! Remove the last element in the array.
|
||||
GenericValue& PopBack() {
|
||||
RAPIDJSON_ASSERT(IsArray());
|
||||
RAPIDJSON_ASSERT(!Empty());
|
||||
data_.a.elements[--data_.a.size].~GenericValue();
|
||||
return *this;
|
||||
}
|
||||
//@}
|
||||
|
||||
//!@name Number
|
||||
//@{
|
||||
|
||||
int GetInt() const { RAPIDJSON_ASSERT(flags_ & kIntFlag); return data_.n.i.i; }
|
||||
unsigned GetUint() const { RAPIDJSON_ASSERT(flags_ & kUintFlag); return data_.n.u.u; }
|
||||
int64_t GetInt64() const { RAPIDJSON_ASSERT(flags_ & kInt64Flag); return data_.n.i64; }
|
||||
uint64_t GetUint64() const { RAPIDJSON_ASSERT(flags_ & kUint64Flag); return data_.n.u64; }
|
||||
|
||||
double GetDouble() const {
|
||||
RAPIDJSON_ASSERT(IsNumber());
|
||||
if ((flags_ & kDoubleFlag) != 0) return data_.n.d; // exact type, no conversion.
|
||||
if ((flags_ & kIntFlag) != 0) return data_.n.i.i; // int -> double
|
||||
if ((flags_ & kUintFlag) != 0) return data_.n.u.u; // unsigned -> double
|
||||
if ((flags_ & kInt64Flag) != 0) return (double)data_.n.i64; // int64_t -> double (may lose precision)
|
||||
RAPIDJSON_ASSERT((flags_ & kUint64Flag) != 0); return (double)data_.n.u64; // uint64_t -> double (may lose precision)
|
||||
}
|
||||
|
||||
GenericValue& SetInt(int i) { this->~GenericValue(); new (this) GenericValue(i); return *this; }
|
||||
GenericValue& SetUint(unsigned u) { this->~GenericValue(); new (this) GenericValue(u); return *this; }
|
||||
GenericValue& SetInt64(int64_t i64) { this->~GenericValue(); new (this) GenericValue(i64); return *this; }
|
||||
GenericValue& SetUint64(uint64_t u64) { this->~GenericValue(); new (this) GenericValue(u64); return *this; }
|
||||
GenericValue& SetDouble(double d) { this->~GenericValue(); new (this) GenericValue(d); return *this; }
|
||||
|
||||
//@}
|
||||
|
||||
//!@name String
|
||||
//@{
|
||||
|
||||
const Ch* GetString() const { RAPIDJSON_ASSERT(IsString()); return data_.s.str; }
|
||||
|
||||
//! Get the length of string.
|
||||
/*! Since rapidjson permits "\u0000" in the json string, strlen(v.GetString()) may not equal to v.GetStringLength().
|
||||
*/
|
||||
SizeType GetStringLength() const { RAPIDJSON_ASSERT(IsString()); return data_.s.length; }
|
||||
|
||||
//! Set this value as a string without copying source string.
|
||||
/*! This version has better performance with supplied length, and also support string containing null character.
|
||||
\param s source string pointer.
|
||||
\param length The length of source string, excluding the trailing null terminator.
|
||||
\return The value itself for fluent API.
|
||||
*/
|
||||
GenericValue& SetString(const Ch* s, SizeType length) { this->~GenericValue(); SetStringRaw(s, length); return *this; }
|
||||
|
||||
//! Set this value as a string without copying source string.
|
||||
/*! \param s source string pointer.
|
||||
\return The value itself for fluent API.
|
||||
*/
|
||||
GenericValue& SetString(const Ch* s) { return SetString(s, internal::StrLen(s)); }
|
||||
|
||||
//! Set this value as a string by copying from source string.
|
||||
/*! This version has better performance with supplied length, and also support string containing null character.
|
||||
\param s source string.
|
||||
\param length The length of source string, excluding the trailing null terminator.
|
||||
\param allocator Allocator for allocating copied buffer. Commonly use document.GetAllocator().
|
||||
\return The value itself for fluent API.
|
||||
*/
|
||||
GenericValue& SetString(const Ch* s, SizeType length, Allocator& allocator) { this->~GenericValue(); SetStringRaw(s, length, allocator); return *this; }
|
||||
|
||||
//! Set this value as a string by copying from source string.
|
||||
/*! \param s source string.
|
||||
\param allocator Allocator for allocating copied buffer. Commonly use document.GetAllocator().
|
||||
\return The value itself for fluent API.
|
||||
*/
|
||||
GenericValue& SetString(const Ch* s, Allocator& allocator) { SetString(s, internal::StrLen(s), allocator); return *this; }
|
||||
|
||||
//@}
|
||||
|
||||
//! Generate events of this value to a Handler.
|
||||
/*! This function adopts the GoF visitor pattern.
|
||||
Typical usage is to output this JSON value as JSON text via Writer, which is a Handler.
|
||||
It can also be used to deep clone this value via GenericDocument, which is also a Handler.
|
||||
\tparam Handler type of handler.
|
||||
\param handler An object implementing concept Handler.
|
||||
*/
|
||||
template <typename Handler>
|
||||
const GenericValue& Accept(Handler& handler) const {
|
||||
switch(GetType()) {
|
||||
case kNull_Type: handler.Null_(); break;
|
||||
case kFalseType: handler.Bool_(false); break;
|
||||
case kTrueType: handler.Bool_(true); break;
|
||||
|
||||
case kObjectType:
|
||||
handler.StartObject();
|
||||
for (Member* m = data_.o.members; m != data_.o.members + data_.o.size; ++m) {
|
||||
handler.String(m->name.data_.s.str, m->name.data_.s.length, false);
|
||||
m->value.Accept(handler);
|
||||
}
|
||||
handler.EndObject(data_.o.size);
|
||||
break;
|
||||
|
||||
case kArrayType:
|
||||
handler.StartArray();
|
||||
for (GenericValue* v = data_.a.elements; v != data_.a.elements + data_.a.size; ++v)
|
||||
v->Accept(handler);
|
||||
handler.EndArray(data_.a.size);
|
||||
break;
|
||||
|
||||
case kStringType:
|
||||
handler.String(data_.s.str, data_.s.length, false);
|
||||
break;
|
||||
|
||||
case kNumberType:
|
||||
if (IsInt()) handler.Int(data_.n.i.i);
|
||||
else if (IsUint()) handler.Uint(data_.n.u.u);
|
||||
else if (IsInt64()) handler.Int64(data_.n.i64);
|
||||
else if (IsUint64()) handler.Uint64(data_.n.u64);
|
||||
else handler.Double(data_.n.d);
|
||||
break;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
private:
|
||||
template <typename, typename>
|
||||
friend class GenericDocument;
|
||||
|
||||
enum {
|
||||
kBool_Flag = 0x100,
|
||||
kNumberFlag = 0x200,
|
||||
kIntFlag = 0x400,
|
||||
kUintFlag = 0x800,
|
||||
kInt64Flag = 0x1000,
|
||||
kUint64Flag = 0x2000,
|
||||
kDoubleFlag = 0x4000,
|
||||
kStringFlag = 0x100000,
|
||||
kCopyFlag = 0x200000,
|
||||
|
||||
// Initial flags of different types.
|
||||
kNull_Flag = kNull_Type,
|
||||
kTrueFlag = kTrueType | kBool_Flag,
|
||||
kFalseFlag = kFalseType | kBool_Flag,
|
||||
kNumberIntFlag = kNumberType | kNumberFlag | kIntFlag | kInt64Flag,
|
||||
kNumberUintFlag = kNumberType | kNumberFlag | kUintFlag | kUint64Flag | kInt64Flag,
|
||||
kNumberInt64Flag = kNumberType | kNumberFlag | kInt64Flag,
|
||||
kNumberUint64Flag = kNumberType | kNumberFlag | kUint64Flag,
|
||||
kNumberDoubleFlag = kNumberType | kNumberFlag | kDoubleFlag,
|
||||
kConstStringFlag = kStringType | kStringFlag,
|
||||
kCopyStringFlag = kStringType | kStringFlag | kCopyFlag,
|
||||
kObjectFlag = kObjectType,
|
||||
kArrayFlag = kArrayType,
|
||||
|
||||
kTypeMask = 0xFF // bitwise-and with mask of 0xFF can be optimized by compiler
|
||||
};
|
||||
|
||||
static const SizeType kDefaultArrayCapacity = 16;
|
||||
static const SizeType kDefaultObjectCapacity = 16;
|
||||
|
||||
struct String {
|
||||
const Ch* str;
|
||||
SizeType length;
|
||||
unsigned hashcode; //!< reserved
|
||||
}; // 12 bytes in 32-bit mode, 16 bytes in 64-bit mode
|
||||
|
||||
// By using proper binary layout, retrieval of different integer types do not need conversions.
|
||||
union Number {
|
||||
#if RAPIDJSON_ENDIAN == RAPIDJSON_LITTLEENDIAN
|
||||
struct I {
|
||||
int i;
|
||||
char padding[4];
|
||||
}i;
|
||||
struct U {
|
||||
unsigned u;
|
||||
char padding2[4];
|
||||
}u;
|
||||
#else
|
||||
struct I {
|
||||
char padding[4];
|
||||
int i;
|
||||
}i;
|
||||
struct U {
|
||||
char padding2[4];
|
||||
unsigned u;
|
||||
}u;
|
||||
#endif
|
||||
int64_t i64;
|
||||
uint64_t u64;
|
||||
double d;
|
||||
}; // 8 bytes
|
||||
|
||||
struct Object {
|
||||
Member* members;
|
||||
SizeType size;
|
||||
SizeType capacity;
|
||||
}; // 12 bytes in 32-bit mode, 16 bytes in 64-bit mode
|
||||
|
||||
struct Array {
|
||||
GenericValue<Encoding, Allocator>* elements;
|
||||
SizeType size;
|
||||
SizeType capacity;
|
||||
}; // 12 bytes in 32-bit mode, 16 bytes in 64-bit mode
|
||||
|
||||
union Data {
|
||||
String s;
|
||||
Number n;
|
||||
Object o;
|
||||
Array a;
|
||||
}; // 12 bytes in 32-bit mode, 16 bytes in 64-bit mode
|
||||
|
||||
//! Find member by name.
|
||||
Member* FindMember(const Ch* name) {
|
||||
RAPIDJSON_ASSERT(name);
|
||||
RAPIDJSON_ASSERT(IsObject());
|
||||
|
||||
SizeType length = internal::StrLen(name);
|
||||
|
||||
Object& o = data_.o;
|
||||
for (Member* member = o.members; member != data_.o.members + data_.o.size; ++member)
|
||||
if (length == member->name.data_.s.length && memcmp(member->name.data_.s.str, name, length * sizeof(Ch)) == 0)
|
||||
return member;
|
||||
|
||||
return 0;
|
||||
}
|
||||
const Member* FindMember(const Ch* name) const { return const_cast<GenericValue&>(*this).FindMember(name); }
|
||||
|
||||
// Initialize this value as array with initial data, without calling destructor.
|
||||
void SetArrayRaw(GenericValue* values, SizeType count, Allocator& alloctaor) {
|
||||
flags_ = kArrayFlag;
|
||||
data_.a.elements = (GenericValue*)alloctaor.Malloc(count * sizeof(GenericValue));
|
||||
memcpy(data_.a.elements, values, count * sizeof(GenericValue));
|
||||
data_.a.size = data_.a.capacity = count;
|
||||
}
|
||||
|
||||
//! Initialize this value as object with initial data, without calling destructor.
|
||||
void SetObjectRaw(Member* members, SizeType count, Allocator& alloctaor) {
|
||||
flags_ = kObjectFlag;
|
||||
data_.o.members = (Member*)alloctaor.Malloc(count * sizeof(Member));
|
||||
memcpy(data_.o.members, members, count * sizeof(Member));
|
||||
data_.o.size = data_.o.capacity = count;
|
||||
}
|
||||
|
||||
//! Initialize this value as constant string, without calling destructor.
|
||||
void SetStringRaw(const Ch* s, SizeType length) {
|
||||
RAPIDJSON_ASSERT(s != NULL);
|
||||
flags_ = kConstStringFlag;
|
||||
data_.s.str = s;
|
||||
data_.s.length = length;
|
||||
}
|
||||
|
||||
//! Initialize this value as copy string with initial data, without calling destructor.
|
||||
void SetStringRaw(const Ch* s, SizeType length, Allocator& allocator) {
|
||||
RAPIDJSON_ASSERT(s != NULL);
|
||||
flags_ = kCopyStringFlag;
|
||||
data_.s.str = (Ch *)allocator.Malloc((length + 1) * sizeof(Ch));
|
||||
data_.s.length = length;
|
||||
memcpy(const_cast<Ch*>(data_.s.str), s, length * sizeof(Ch));
|
||||
const_cast<Ch*>(data_.s.str)[length] = '\0';
|
||||
}
|
||||
|
||||
//! Assignment without calling destructor
|
||||
void RawAssign(GenericValue& rhs) {
|
||||
memcpy(this, &rhs, sizeof(GenericValue));
|
||||
rhs.flags_ = kNull_Flag;
|
||||
}
|
||||
|
||||
Data data_;
|
||||
unsigned flags_;
|
||||
};
|
||||
#pragma pack (pop)
|
||||
|
||||
//! Value with UTF8 encoding.
|
||||
typedef GenericValue<UTF8<> > Value;
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// GenericDocument
|
||||
|
||||
//! A document for parsing JSON text as DOM.
|
||||
/*!
|
||||
\implements Handler
|
||||
\tparam Encoding encoding for both parsing and string storage.
|
||||
\tparam Alloactor allocator for allocating memory for the DOM, and the stack during parsing.
|
||||
*/
|
||||
template <typename Encoding, typename Allocator = MemoryPoolAllocator<> >
|
||||
class GenericDocument : public GenericValue<Encoding, Allocator> {
|
||||
public:
|
||||
typedef typename Encoding::Ch Ch; //!< Character type derived from Encoding.
|
||||
typedef GenericValue<Encoding, Allocator> ValueType; //!< Value type of the document.
|
||||
typedef Allocator AllocatorType; //!< Allocator type from template parameter.
|
||||
|
||||
//! Constructor
|
||||
/*! \param allocator Optional allocator for allocating stack memory.
|
||||
\param stackCapacity Initial capacity of stack in bytes.
|
||||
*/
|
||||
GenericDocument(Allocator* allocator = 0, size_t stackCapacity = kDefaultStackCapacity) : stack_(allocator, stackCapacity), parseError_(0), errorOffset_(0) {}
|
||||
|
||||
//! Parse JSON text from an input stream.
|
||||
/*! \tparam parseFlags Combination of ParseFlag.
|
||||
\param stream Input stream to be parsed.
|
||||
\return The document itself for fluent API.
|
||||
*/
|
||||
template <unsigned parseFlags, typename Stream>
|
||||
GenericDocument& ParseStream(Stream& stream) {
|
||||
ValueType::SetNull_(); // Remove existing root if exist
|
||||
GenericReader<Encoding, Allocator> reader;
|
||||
if (reader.template Parse<parseFlags>(stream, *this)) {
|
||||
RAPIDJSON_ASSERT(stack_.GetSize() == sizeof(ValueType)); // Got one and only one root object
|
||||
this->RawAssign(*stack_.template Pop<ValueType>(1)); // Add this-> to prevent issue 13.
|
||||
parseError_ = 0;
|
||||
errorOffset_ = 0;
|
||||
}
|
||||
else {
|
||||
parseError_ = reader.GetParseError();
|
||||
errorOffset_ = reader.GetErrorOffset();
|
||||
ClearStack();
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
//! Parse JSON text from a mutable string.
|
||||
/*! \tparam parseFlags Combination of ParseFlag.
|
||||
\param str Mutable zero-terminated string to be parsed.
|
||||
\return The document itself for fluent API.
|
||||
*/
|
||||
template <unsigned parseFlags>
|
||||
GenericDocument& ParseInsitu(Ch* str) {
|
||||
GenericInsituStringStream<Encoding> s(str);
|
||||
return ParseStream<parseFlags | kParseInsituFlag>(s);
|
||||
}
|
||||
|
||||
//! Parse JSON text from a read-only string.
|
||||
/*! \tparam parseFlags Combination of ParseFlag (must not contain kParseInsituFlag).
|
||||
\param str Read-only zero-terminated string to be parsed.
|
||||
*/
|
||||
template <unsigned parseFlags>
|
||||
GenericDocument& Parse(const Ch* str) {
|
||||
RAPIDJSON_ASSERT(!(parseFlags & kParseInsituFlag));
|
||||
GenericStringStream<Encoding> s(str);
|
||||
return ParseStream<parseFlags>(s);
|
||||
}
|
||||
|
||||
//! Whether a parse error was occured in the last parsing.
|
||||
bool HasParseError() const { return parseError_ != 0; }
|
||||
|
||||
//! Get the message of parsing error.
|
||||
const char* GetParseError() const { return parseError_; }
|
||||
|
||||
//! Get the offset in character of the parsing error.
|
||||
size_t GetErrorOffset() const { return errorOffset_; }
|
||||
|
||||
//! Get the allocator of this document.
|
||||
Allocator& GetAllocator() { return stack_.GetAllocator(); }
|
||||
|
||||
//! Get the capacity of stack in bytes.
|
||||
size_t GetStackCapacity() const { return stack_.GetCapacity(); }
|
||||
|
||||
private:
|
||||
// Prohibit assignment
|
||||
GenericDocument& operator=(const GenericDocument&);
|
||||
|
||||
friend class GenericReader<Encoding, Allocator>; // for Reader to call the following private handler functions
|
||||
|
||||
// Implementation of Handler
|
||||
void Null_() { new (stack_.template Push<ValueType>()) ValueType(); }
|
||||
void Bool_(bool b) { new (stack_.template Push<ValueType>()) ValueType(b); }
|
||||
void Int(int i) { new (stack_.template Push<ValueType>()) ValueType(i); }
|
||||
void Uint(unsigned i) { new (stack_.template Push<ValueType>()) ValueType(i); }
|
||||
void Int64(int64_t i) { new (stack_.template Push<ValueType>()) ValueType(i); }
|
||||
void Uint64(uint64_t i) { new (stack_.template Push<ValueType>()) ValueType(i); }
|
||||
void Double(double d) { new (stack_.template Push<ValueType>()) ValueType(d); }
|
||||
|
||||
void String(const Ch* str, SizeType length, bool copy) {
|
||||
if (copy)
|
||||
new (stack_.template Push<ValueType>()) ValueType(str, length, GetAllocator());
|
||||
else
|
||||
new (stack_.template Push<ValueType>()) ValueType(str, length);
|
||||
}
|
||||
|
||||
void StartObject() { new (stack_.template Push<ValueType>()) ValueType(kObjectType); }
|
||||
|
||||
void EndObject(SizeType memberCount) {
|
||||
typename ValueType::Member* members = stack_.template Pop<typename ValueType::Member>(memberCount);
|
||||
stack_.template Top<ValueType>()->SetObjectRaw(members, (SizeType)memberCount, GetAllocator());
|
||||
}
|
||||
|
||||
void StartArray() { new (stack_.template Push<ValueType>()) ValueType(kArrayType); }
|
||||
|
||||
void EndArray(SizeType elementCount) {
|
||||
ValueType* elements = stack_.template Pop<ValueType>(elementCount);
|
||||
stack_.template Top<ValueType>()->SetArrayRaw(elements, elementCount, GetAllocator());
|
||||
}
|
||||
|
||||
void ClearStack() {
|
||||
if (Allocator::kNeedFree)
|
||||
while (stack_.GetSize() > 0) // Here assumes all elements in stack array are GenericValue (Member is actually 2 GenericValue objects)
|
||||
(stack_.template Pop<ValueType>(1))->~ValueType();
|
||||
else
|
||||
stack_.Clear();
|
||||
}
|
||||
|
||||
static const size_t kDefaultStackCapacity = 1024;
|
||||
internal::Stack<Allocator> stack_;
|
||||
const char* parseError_;
|
||||
size_t errorOffset_;
|
||||
};
|
||||
|
||||
typedef GenericDocument<UTF8<> > Document;
|
||||
|
||||
} // namespace rapidjson
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(pop)
|
||||
#endif
|
||||
|
||||
#endif // RAPIDJSON_DOCUMENT_H_
|
||||
47
libs/cereal/cereal/external/rapidjson/filestream.h
vendored
Normal file
47
libs/cereal/cereal/external/rapidjson/filestream.h
vendored
Normal file
@ -0,0 +1,47 @@
|
||||
#ifndef RAPIDJSON_FILESTREAM_H_
|
||||
#define RAPIDJSON_FILESTREAM_H_
|
||||
|
||||
#include <cstdio>
|
||||
|
||||
namespace rapidjson {
|
||||
|
||||
//! Wrapper of C file stream for input or output.
|
||||
/*!
|
||||
This simple wrapper does not check the validity of the stream.
|
||||
\implements Stream
|
||||
*/
|
||||
class FileStream {
|
||||
public:
|
||||
typedef char Ch; //!< Character type. Only support char.
|
||||
|
||||
FileStream(FILE* fp) : fp_(fp), count_(0) { Read(); }
|
||||
|
||||
char Peek() const { return current_; }
|
||||
char Take() { char c = current_; Read(); return c; }
|
||||
size_t Tell() const { return count_; }
|
||||
void Put(char c) { fputc(c, fp_); }
|
||||
|
||||
// Not implemented
|
||||
char* PutBegin() { return 0; }
|
||||
size_t PutEnd(char*) { return 0; }
|
||||
|
||||
private:
|
||||
void Read() {
|
||||
RAPIDJSON_ASSERT(fp_ != 0);
|
||||
int c = fgetc(fp_);
|
||||
if (c != EOF) {
|
||||
current_ = (char)c;
|
||||
count_++;
|
||||
}
|
||||
else
|
||||
current_ = '\0';
|
||||
}
|
||||
|
||||
FILE* fp_;
|
||||
char current_;
|
||||
size_t count_;
|
||||
};
|
||||
|
||||
} // namespace rapidjson
|
||||
|
||||
#endif // RAPIDJSON_FILESTREAM_H_
|
||||
105
libs/cereal/cereal/external/rapidjson/genericstream.h
vendored
Normal file
105
libs/cereal/cereal/external/rapidjson/genericstream.h
vendored
Normal file
@ -0,0 +1,105 @@
|
||||
// Generic*Stream code from https://code.google.com/p/rapidjson/issues/detail?id=20
|
||||
#ifndef RAPIDJSON_GENERICSTREAM_H_
|
||||
#define RAPIDJSON_GENERICSTREAM_H_
|
||||
|
||||
#include "rapidjson.h"
|
||||
#include <iostream>
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable: 4127) // conditional expression is constant
|
||||
#pragma warning(disable: 4512) // assignment operator could not be generated
|
||||
#pragma warning(disable: 4100) // unreferenced formal parameter
|
||||
#endif
|
||||
|
||||
namespace rapidjson {
|
||||
|
||||
//! Wrapper of std::istream for input.
|
||||
class GenericReadStream {
|
||||
public:
|
||||
typedef char Ch; //!< Character type (byte).
|
||||
|
||||
//! Constructor.
|
||||
/*!
|
||||
\param is Input stream.
|
||||
*/
|
||||
GenericReadStream(std::istream & is) : is_(&is) {
|
||||
}
|
||||
|
||||
|
||||
Ch Peek() const {
|
||||
if(is_->eof()) return '\0';
|
||||
return static_cast<char>(is_->peek());
|
||||
}
|
||||
|
||||
Ch Take() {
|
||||
if(is_->eof()) return '\0';
|
||||
return static_cast<char>(is_->get());
|
||||
}
|
||||
|
||||
size_t Tell() const {
|
||||
return (int)is_->tellg();
|
||||
}
|
||||
|
||||
// Not implemented
|
||||
void Put(Ch) { RAPIDJSON_ASSERT(false); }
|
||||
void Flush() { RAPIDJSON_ASSERT(false); }
|
||||
Ch* PutBegin() { RAPIDJSON_ASSERT(false); return 0; }
|
||||
size_t PutEnd(Ch*) { RAPIDJSON_ASSERT(false); return 0; }
|
||||
|
||||
std::istream * is_;
|
||||
};
|
||||
|
||||
|
||||
//! Wrapper of std::ostream for output.
|
||||
class GenericWriteStream {
|
||||
public:
|
||||
typedef char Ch; //!< Character type. Only support char.
|
||||
|
||||
//! Constructor
|
||||
/*!
|
||||
\param os Output stream.
|
||||
*/
|
||||
GenericWriteStream(std::ostream& os) : os_(os) {
|
||||
}
|
||||
|
||||
void Put(char c) {
|
||||
os_.put(c);
|
||||
}
|
||||
|
||||
void PutN(char c, size_t n) {
|
||||
for (size_t i = 0; i < n; ++i) {
|
||||
Put(c);
|
||||
}
|
||||
}
|
||||
|
||||
void Flush() {
|
||||
os_.flush();
|
||||
}
|
||||
|
||||
size_t Tell() const {
|
||||
return (int)os_.tellp();
|
||||
}
|
||||
|
||||
// Not implemented
|
||||
char Peek() const { RAPIDJSON_ASSERT(false); }
|
||||
char Take() { RAPIDJSON_ASSERT(false); }
|
||||
char* PutBegin() { RAPIDJSON_ASSERT(false); return 0; }
|
||||
size_t PutEnd(char*) { RAPIDJSON_ASSERT(false); return 0; }
|
||||
|
||||
private:
|
||||
std::ostream& os_;
|
||||
};
|
||||
|
||||
template<>
|
||||
inline void PutN(GenericWriteStream& stream, char c, size_t n) {
|
||||
stream.PutN(c, n);
|
||||
}
|
||||
|
||||
} // namespace rapidjson
|
||||
|
||||
// On MSVC, restore warnings state
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(pop)
|
||||
#endif
|
||||
#endif // RAPIDJSON_GENERICSTREAM_H_
|
||||
54
libs/cereal/cereal/external/rapidjson/internal/pow10.h
vendored
Normal file
54
libs/cereal/cereal/external/rapidjson/internal/pow10.h
vendored
Normal file
@ -0,0 +1,54 @@
|
||||
#ifndef RAPIDJSON_POW10_
|
||||
#define RAPIDJSON_POW10_
|
||||
|
||||
namespace rapidjson {
|
||||
namespace internal {
|
||||
|
||||
//! Computes integer powers of 10 in double (10.0^n).
|
||||
/*! This function uses lookup table for fast and accurate results.
|
||||
\param n positive/negative exponent. Must <= 308.
|
||||
\return 10.0^n
|
||||
*/
|
||||
inline double Pow10(int n) {
|
||||
static const double e[] = { // 1e-308...1e308: 617 * 8 bytes = 4936 bytes
|
||||
1e-308,1e-307,1e-306,1e-305,1e-304,1e-303,1e-302,1e-301,1e-300,
|
||||
1e-299,1e-298,1e-297,1e-296,1e-295,1e-294,1e-293,1e-292,1e-291,1e-290,1e-289,1e-288,1e-287,1e-286,1e-285,1e-284,1e-283,1e-282,1e-281,1e-280,
|
||||
1e-279,1e-278,1e-277,1e-276,1e-275,1e-274,1e-273,1e-272,1e-271,1e-270,1e-269,1e-268,1e-267,1e-266,1e-265,1e-264,1e-263,1e-262,1e-261,1e-260,
|
||||
1e-259,1e-258,1e-257,1e-256,1e-255,1e-254,1e-253,1e-252,1e-251,1e-250,1e-249,1e-248,1e-247,1e-246,1e-245,1e-244,1e-243,1e-242,1e-241,1e-240,
|
||||
1e-239,1e-238,1e-237,1e-236,1e-235,1e-234,1e-233,1e-232,1e-231,1e-230,1e-229,1e-228,1e-227,1e-226,1e-225,1e-224,1e-223,1e-222,1e-221,1e-220,
|
||||
1e-219,1e-218,1e-217,1e-216,1e-215,1e-214,1e-213,1e-212,1e-211,1e-210,1e-209,1e-208,1e-207,1e-206,1e-205,1e-204,1e-203,1e-202,1e-201,1e-200,
|
||||
1e-199,1e-198,1e-197,1e-196,1e-195,1e-194,1e-193,1e-192,1e-191,1e-190,1e-189,1e-188,1e-187,1e-186,1e-185,1e-184,1e-183,1e-182,1e-181,1e-180,
|
||||
1e-179,1e-178,1e-177,1e-176,1e-175,1e-174,1e-173,1e-172,1e-171,1e-170,1e-169,1e-168,1e-167,1e-166,1e-165,1e-164,1e-163,1e-162,1e-161,1e-160,
|
||||
1e-159,1e-158,1e-157,1e-156,1e-155,1e-154,1e-153,1e-152,1e-151,1e-150,1e-149,1e-148,1e-147,1e-146,1e-145,1e-144,1e-143,1e-142,1e-141,1e-140,
|
||||
1e-139,1e-138,1e-137,1e-136,1e-135,1e-134,1e-133,1e-132,1e-131,1e-130,1e-129,1e-128,1e-127,1e-126,1e-125,1e-124,1e-123,1e-122,1e-121,1e-120,
|
||||
1e-119,1e-118,1e-117,1e-116,1e-115,1e-114,1e-113,1e-112,1e-111,1e-110,1e-109,1e-108,1e-107,1e-106,1e-105,1e-104,1e-103,1e-102,1e-101,1e-100,
|
||||
1e-99, 1e-98, 1e-97, 1e-96, 1e-95, 1e-94, 1e-93, 1e-92, 1e-91, 1e-90, 1e-89, 1e-88, 1e-87, 1e-86, 1e-85, 1e-84, 1e-83, 1e-82, 1e-81, 1e-80,
|
||||
1e-79, 1e-78, 1e-77, 1e-76, 1e-75, 1e-74, 1e-73, 1e-72, 1e-71, 1e-70, 1e-69, 1e-68, 1e-67, 1e-66, 1e-65, 1e-64, 1e-63, 1e-62, 1e-61, 1e-60,
|
||||
1e-59, 1e-58, 1e-57, 1e-56, 1e-55, 1e-54, 1e-53, 1e-52, 1e-51, 1e-50, 1e-49, 1e-48, 1e-47, 1e-46, 1e-45, 1e-44, 1e-43, 1e-42, 1e-41, 1e-40,
|
||||
1e-39, 1e-38, 1e-37, 1e-36, 1e-35, 1e-34, 1e-33, 1e-32, 1e-31, 1e-30, 1e-29, 1e-28, 1e-27, 1e-26, 1e-25, 1e-24, 1e-23, 1e-22, 1e-21, 1e-20,
|
||||
1e-19, 1e-18, 1e-17, 1e-16, 1e-15, 1e-14, 1e-13, 1e-12, 1e-11, 1e-10, 1e-9, 1e-8, 1e-7, 1e-6, 1e-5, 1e-4, 1e-3, 1e-2, 1e-1, 1e+0,
|
||||
1e+1, 1e+2, 1e+3, 1e+4, 1e+5, 1e+6, 1e+7, 1e+8, 1e+9, 1e+10, 1e+11, 1e+12, 1e+13, 1e+14, 1e+15, 1e+16, 1e+17, 1e+18, 1e+19, 1e+20,
|
||||
1e+21, 1e+22, 1e+23, 1e+24, 1e+25, 1e+26, 1e+27, 1e+28, 1e+29, 1e+30, 1e+31, 1e+32, 1e+33, 1e+34, 1e+35, 1e+36, 1e+37, 1e+38, 1e+39, 1e+40,
|
||||
1e+41, 1e+42, 1e+43, 1e+44, 1e+45, 1e+46, 1e+47, 1e+48, 1e+49, 1e+50, 1e+51, 1e+52, 1e+53, 1e+54, 1e+55, 1e+56, 1e+57, 1e+58, 1e+59, 1e+60,
|
||||
1e+61, 1e+62, 1e+63, 1e+64, 1e+65, 1e+66, 1e+67, 1e+68, 1e+69, 1e+70, 1e+71, 1e+72, 1e+73, 1e+74, 1e+75, 1e+76, 1e+77, 1e+78, 1e+79, 1e+80,
|
||||
1e+81, 1e+82, 1e+83, 1e+84, 1e+85, 1e+86, 1e+87, 1e+88, 1e+89, 1e+90, 1e+91, 1e+92, 1e+93, 1e+94, 1e+95, 1e+96, 1e+97, 1e+98, 1e+99, 1e+100,
|
||||
1e+101,1e+102,1e+103,1e+104,1e+105,1e+106,1e+107,1e+108,1e+109,1e+110,1e+111,1e+112,1e+113,1e+114,1e+115,1e+116,1e+117,1e+118,1e+119,1e+120,
|
||||
1e+121,1e+122,1e+123,1e+124,1e+125,1e+126,1e+127,1e+128,1e+129,1e+130,1e+131,1e+132,1e+133,1e+134,1e+135,1e+136,1e+137,1e+138,1e+139,1e+140,
|
||||
1e+141,1e+142,1e+143,1e+144,1e+145,1e+146,1e+147,1e+148,1e+149,1e+150,1e+151,1e+152,1e+153,1e+154,1e+155,1e+156,1e+157,1e+158,1e+159,1e+160,
|
||||
1e+161,1e+162,1e+163,1e+164,1e+165,1e+166,1e+167,1e+168,1e+169,1e+170,1e+171,1e+172,1e+173,1e+174,1e+175,1e+176,1e+177,1e+178,1e+179,1e+180,
|
||||
1e+181,1e+182,1e+183,1e+184,1e+185,1e+186,1e+187,1e+188,1e+189,1e+190,1e+191,1e+192,1e+193,1e+194,1e+195,1e+196,1e+197,1e+198,1e+199,1e+200,
|
||||
1e+201,1e+202,1e+203,1e+204,1e+205,1e+206,1e+207,1e+208,1e+209,1e+210,1e+211,1e+212,1e+213,1e+214,1e+215,1e+216,1e+217,1e+218,1e+219,1e+220,
|
||||
1e+221,1e+222,1e+223,1e+224,1e+225,1e+226,1e+227,1e+228,1e+229,1e+230,1e+231,1e+232,1e+233,1e+234,1e+235,1e+236,1e+237,1e+238,1e+239,1e+240,
|
||||
1e+241,1e+242,1e+243,1e+244,1e+245,1e+246,1e+247,1e+248,1e+249,1e+250,1e+251,1e+252,1e+253,1e+254,1e+255,1e+256,1e+257,1e+258,1e+259,1e+260,
|
||||
1e+261,1e+262,1e+263,1e+264,1e+265,1e+266,1e+267,1e+268,1e+269,1e+270,1e+271,1e+272,1e+273,1e+274,1e+275,1e+276,1e+277,1e+278,1e+279,1e+280,
|
||||
1e+281,1e+282,1e+283,1e+284,1e+285,1e+286,1e+287,1e+288,1e+289,1e+290,1e+291,1e+292,1e+293,1e+294,1e+295,1e+296,1e+297,1e+298,1e+299,1e+300,
|
||||
1e+301,1e+302,1e+303,1e+304,1e+305,1e+306,1e+307,1e+308
|
||||
};
|
||||
RAPIDJSON_ASSERT(n <= 308);
|
||||
return n < -308 ? 0.0 : e[n + 308];
|
||||
}
|
||||
|
||||
} // namespace internal
|
||||
} // namespace rapidjson
|
||||
|
||||
#endif // RAPIDJSON_POW10_
|
||||
82
libs/cereal/cereal/external/rapidjson/internal/stack.h
vendored
Normal file
82
libs/cereal/cereal/external/rapidjson/internal/stack.h
vendored
Normal file
@ -0,0 +1,82 @@
|
||||
#ifndef RAPIDJSON_INTERNAL_STACK_H_
|
||||
#define RAPIDJSON_INTERNAL_STACK_H_
|
||||
|
||||
namespace rapidjson {
|
||||
namespace internal {
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Stack
|
||||
|
||||
//! A type-unsafe stack for storing different types of data.
|
||||
/*! \tparam Allocator Allocator for allocating stack memory.
|
||||
*/
|
||||
template <typename Allocator>
|
||||
class Stack {
|
||||
public:
|
||||
Stack(Allocator* allocator, size_t stack_capacity) : allocator_(allocator), own_allocator_(0), stack_(0), stack_top_(0), stack_end_(0), stack_capacity_(stack_capacity) {
|
||||
RAPIDJSON_ASSERT(stack_capacity_ > 0);
|
||||
if (!allocator_)
|
||||
own_allocator_ = allocator_ = new Allocator();
|
||||
stack_top_ = stack_ = (char*)allocator_->Malloc(stack_capacity_);
|
||||
stack_end_ = stack_ + stack_capacity_;
|
||||
}
|
||||
|
||||
~Stack() {
|
||||
Allocator::Free(stack_);
|
||||
delete own_allocator_; // Only delete if it is owned by the stack
|
||||
}
|
||||
|
||||
void Clear() { /*stack_top_ = 0;*/ stack_top_ = stack_; }
|
||||
|
||||
template<typename T>
|
||||
T* Push(size_t count = 1) {
|
||||
// Expand the stack if needed
|
||||
if (stack_top_ + sizeof(T) * count >= stack_end_) {
|
||||
size_t new_capacity = stack_capacity_ * 2;
|
||||
size_t size = GetSize();
|
||||
size_t new_size = GetSize() + sizeof(T) * count;
|
||||
if (new_capacity < new_size)
|
||||
new_capacity = new_size;
|
||||
stack_ = (char*)allocator_->Realloc(stack_, stack_capacity_, new_capacity);
|
||||
stack_capacity_ = new_capacity;
|
||||
stack_top_ = stack_ + size;
|
||||
stack_end_ = stack_ + stack_capacity_;
|
||||
}
|
||||
T* ret = (T*)stack_top_;
|
||||
stack_top_ += sizeof(T) * count;
|
||||
return ret;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
T* Pop(size_t count) {
|
||||
RAPIDJSON_ASSERT(GetSize() >= count * sizeof(T));
|
||||
stack_top_ -= count * sizeof(T);
|
||||
return (T*)stack_top_;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
T* Top() {
|
||||
RAPIDJSON_ASSERT(GetSize() >= sizeof(T));
|
||||
return (T*)(stack_top_ - sizeof(T));
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
T* Bottom() { return (T*)stack_; }
|
||||
|
||||
Allocator& GetAllocator() { return *allocator_; }
|
||||
size_t GetSize() const { return stack_top_ - stack_; }
|
||||
size_t GetCapacity() const { return stack_capacity_; }
|
||||
|
||||
private:
|
||||
Allocator* allocator_;
|
||||
Allocator* own_allocator_;
|
||||
char *stack_;
|
||||
char *stack_top_;
|
||||
char *stack_end_;
|
||||
size_t stack_capacity_;
|
||||
};
|
||||
|
||||
} // namespace internal
|
||||
} // namespace rapidjson
|
||||
|
||||
#endif // RAPIDJSON_STACK_H_
|
||||
24
libs/cereal/cereal/external/rapidjson/internal/strfunc.h
vendored
Normal file
24
libs/cereal/cereal/external/rapidjson/internal/strfunc.h
vendored
Normal file
@ -0,0 +1,24 @@
|
||||
#ifndef RAPIDJSON_INTERNAL_STRFUNC_H_
|
||||
#define RAPIDJSON_INTERNAL_STRFUNC_H_
|
||||
|
||||
namespace rapidjson {
|
||||
namespace internal {
|
||||
|
||||
//! Custom strlen() which works on different character types.
|
||||
/*! \tparam Ch Character type (e.g. char, wchar_t, short)
|
||||
\param s Null-terminated input string.
|
||||
\return Number of characters in the string.
|
||||
\note This has the same semantics as strlen(), the return value is not number of Unicode codepoints.
|
||||
*/
|
||||
template <typename Ch>
|
||||
inline SizeType StrLen(const Ch* s) {
|
||||
const Ch* p = s;
|
||||
while (*p != '\0')
|
||||
++p;
|
||||
return SizeType(p - s);
|
||||
}
|
||||
|
||||
} // namespace internal
|
||||
} // namespace rapidjson
|
||||
|
||||
#endif // RAPIDJSON_INTERNAL_STRFUNC_H_
|
||||
19
libs/cereal/cereal/external/rapidjson/license.txt
vendored
Normal file
19
libs/cereal/cereal/external/rapidjson/license.txt
vendored
Normal file
@ -0,0 +1,19 @@
|
||||
Copyright (C) 2011 Milo Yip
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
156
libs/cereal/cereal/external/rapidjson/prettywriter.h
vendored
Normal file
156
libs/cereal/cereal/external/rapidjson/prettywriter.h
vendored
Normal file
@ -0,0 +1,156 @@
|
||||
#ifndef RAPIDJSON_PRETTYWRITER_H_
|
||||
#define RAPIDJSON_PRETTYWRITER_H_
|
||||
|
||||
#include "writer.h"
|
||||
|
||||
namespace rapidjson {
|
||||
|
||||
//! Writer with indentation and spacing.
|
||||
/*!
|
||||
\tparam Stream Type of ouptut stream.
|
||||
\tparam Encoding Encoding of both source strings and output.
|
||||
\tparam Allocator Type of allocator for allocating memory of stack.
|
||||
*/
|
||||
template<typename Stream, typename Encoding = UTF8<>, typename Allocator = MemoryPoolAllocator<> >
|
||||
class PrettyWriter : public Writer<Stream, Encoding, Allocator> {
|
||||
public:
|
||||
typedef Writer<Stream, Encoding, Allocator> Base;
|
||||
typedef typename Base::Ch Ch;
|
||||
|
||||
//! Constructor
|
||||
/*! \param stream Output stream.
|
||||
\param allocator User supplied allocator. If it is null, it will create a private one.
|
||||
\param levelDepth Initial capacity of
|
||||
*/
|
||||
PrettyWriter(Stream& stream, int precision = 20, Allocator* allocator = 0, size_t levelDepth = Base::kDefaultLevelDepth) :
|
||||
Base(stream, precision, allocator, levelDepth), indentChar_(' '), indentCharCount_(4) {}
|
||||
|
||||
//! Set custom indentation.
|
||||
/*! \param indentChar Character for indentation. Must be whitespace character (' ', '\t', '\n', '\r').
|
||||
\param indentCharCount Number of indent characters for each indentation level.
|
||||
\note The default indentation is 4 spaces.
|
||||
*/
|
||||
PrettyWriter& SetIndent(Ch indentChar, unsigned indentCharCount) {
|
||||
RAPIDJSON_ASSERT(indentChar == ' ' || indentChar == '\t' || indentChar == '\n' || indentChar == '\r');
|
||||
indentChar_ = indentChar;
|
||||
indentCharCount_ = indentCharCount;
|
||||
return *this;
|
||||
}
|
||||
|
||||
//@name Implementation of Handler.
|
||||
//@{
|
||||
|
||||
PrettyWriter& Null_() { PrettyPrefix(kNull_Type); Base::WriteNull_(); return *this; }
|
||||
PrettyWriter& Bool_(bool b) { PrettyPrefix(b ? kTrueType : kFalseType); Base::WriteBool_(b); return *this; }
|
||||
PrettyWriter& Int(int i) { PrettyPrefix(kNumberType); Base::WriteInt(i); return *this; }
|
||||
PrettyWriter& Uint(unsigned u) { PrettyPrefix(kNumberType); Base::WriteUint(u); return *this; }
|
||||
PrettyWriter& Int64(int64_t i64) { PrettyPrefix(kNumberType); Base::WriteInt64(i64); return *this; }
|
||||
PrettyWriter& Uint64(uint64_t u64) { PrettyPrefix(kNumberType); Base::WriteUint64(u64); return *this; }
|
||||
PrettyWriter& Double(double d) { PrettyPrefix(kNumberType); Base::WriteDouble(d); return *this; }
|
||||
|
||||
PrettyWriter& String(const Ch* str, SizeType length, bool copy = false) {
|
||||
(void)copy;
|
||||
PrettyPrefix(kStringType);
|
||||
Base::WriteString(str, length);
|
||||
return *this;
|
||||
}
|
||||
|
||||
PrettyWriter& StartObject() {
|
||||
PrettyPrefix(kObjectType);
|
||||
new (Base::level_stack_.template Push<typename Base::Level>()) typename Base::Level(false);
|
||||
Base::WriteStartObject();
|
||||
return *this;
|
||||
}
|
||||
|
||||
PrettyWriter& EndObject(SizeType memberCount = 0) {
|
||||
(void)memberCount;
|
||||
RAPIDJSON_ASSERT(Base::level_stack_.GetSize() >= sizeof(typename Base::Level));
|
||||
RAPIDJSON_ASSERT(!Base::level_stack_.template Top<typename Base::Level>()->inArray);
|
||||
bool empty = Base::level_stack_.template Pop<typename Base::Level>(1)->valueCount == 0;
|
||||
|
||||
if (!empty) {
|
||||
Base::stream_.Put('\n');
|
||||
WriteIndent();
|
||||
}
|
||||
Base::WriteEndObject();
|
||||
return *this;
|
||||
}
|
||||
|
||||
PrettyWriter& StartArray() {
|
||||
PrettyPrefix(kArrayType);
|
||||
new (Base::level_stack_.template Push<typename Base::Level>()) typename Base::Level(true);
|
||||
Base::WriteStartArray();
|
||||
return *this;
|
||||
}
|
||||
|
||||
PrettyWriter& EndArray(SizeType memberCount = 0) {
|
||||
(void)memberCount;
|
||||
RAPIDJSON_ASSERT(Base::level_stack_.GetSize() >= sizeof(typename Base::Level));
|
||||
RAPIDJSON_ASSERT(Base::level_stack_.template Top<typename Base::Level>()->inArray);
|
||||
bool empty = Base::level_stack_.template Pop<typename Base::Level>(1)->valueCount == 0;
|
||||
|
||||
if (!empty) {
|
||||
Base::stream_.Put('\n');
|
||||
WriteIndent();
|
||||
}
|
||||
Base::WriteEndArray();
|
||||
return *this;
|
||||
}
|
||||
|
||||
//@}
|
||||
|
||||
//! Simpler but slower overload.
|
||||
PrettyWriter& String(const Ch* str) { return String(str, internal::StrLen(str)); }
|
||||
|
||||
protected:
|
||||
void PrettyPrefix(Type type) {
|
||||
(void)type;
|
||||
if (Base::level_stack_.GetSize() != 0) { // this value is not at root
|
||||
typename Base::Level* level = Base::level_stack_.template Top<typename Base::Level>();
|
||||
|
||||
if (level->inArray) {
|
||||
if (level->valueCount > 0) {
|
||||
Base::stream_.Put(','); // add comma if it is not the first element in array
|
||||
Base::stream_.Put('\n');
|
||||
}
|
||||
else
|
||||
Base::stream_.Put('\n');
|
||||
WriteIndent();
|
||||
}
|
||||
else { // in object
|
||||
if (level->valueCount > 0) {
|
||||
if (level->valueCount % 2 == 0) {
|
||||
Base::stream_.Put(',');
|
||||
Base::stream_.Put('\n');
|
||||
}
|
||||
else {
|
||||
Base::stream_.Put(':');
|
||||
Base::stream_.Put(' ');
|
||||
}
|
||||
}
|
||||
else
|
||||
Base::stream_.Put('\n');
|
||||
|
||||
if (level->valueCount % 2 == 0)
|
||||
WriteIndent();
|
||||
}
|
||||
if (!level->inArray && level->valueCount % 2 == 0)
|
||||
RAPIDJSON_ASSERT(type == kStringType); // if it's in object, then even number should be a name
|
||||
level->valueCount++;
|
||||
}
|
||||
else
|
||||
RAPIDJSON_ASSERT(type == kObjectType || type == kArrayType);
|
||||
}
|
||||
|
||||
void WriteIndent() {
|
||||
size_t count = (Base::level_stack_.GetSize() / sizeof(typename Base::Level)) * indentCharCount_;
|
||||
PutN(Base::stream_, indentChar_, count);
|
||||
}
|
||||
|
||||
Ch indentChar_;
|
||||
unsigned indentCharCount_;
|
||||
};
|
||||
|
||||
} // namespace rapidjson
|
||||
|
||||
#endif // RAPIDJSON_RAPIDJSON_H_
|
||||
525
libs/cereal/cereal/external/rapidjson/rapidjson.h
vendored
Normal file
525
libs/cereal/cereal/external/rapidjson/rapidjson.h
vendored
Normal file
@ -0,0 +1,525 @@
|
||||
#ifndef RAPIDJSON_RAPIDJSON_H_
|
||||
#define RAPIDJSON_RAPIDJSON_H_
|
||||
|
||||
// Copyright (c) 2011-2012 Milo Yip (miloyip@gmail.com)
|
||||
// Version 0.11
|
||||
|
||||
#include <cstdlib> // malloc(), realloc(), free()
|
||||
#include <cstring> // memcpy()
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// RAPIDJSON_NO_INT64DEFINE
|
||||
|
||||
// Here defines int64_t and uint64_t types in global namespace.
|
||||
// If user have their own definition, can define RAPIDJSON_NO_INT64DEFINE to disable this.
|
||||
#ifndef RAPIDJSON_NO_INT64DEFINE
|
||||
#ifdef _MSC_VER
|
||||
typedef __int64 int64_t;
|
||||
typedef unsigned __int64 uint64_t;
|
||||
#else
|
||||
#include <inttypes.h>
|
||||
#endif
|
||||
#endif // RAPIDJSON_NO_INT64TYPEDEF
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// RAPIDJSON_ENDIAN
|
||||
#define RAPIDJSON_LITTLEENDIAN 0 //!< Little endian machine
|
||||
#define RAPIDJSON_BIGENDIAN 1 //!< Big endian machine
|
||||
|
||||
//! Endianness of the machine.
|
||||
/*! GCC provided macro for detecting endianness of the target machine. But other
|
||||
compilers may not have this. User can define RAPIDJSON_ENDIAN to either
|
||||
RAPIDJSON_LITTLEENDIAN or RAPIDJSON_BIGENDIAN.
|
||||
*/
|
||||
#ifndef RAPIDJSON_ENDIAN
|
||||
#ifdef __BYTE_ORDER__
|
||||
#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
|
||||
#define RAPIDJSON_ENDIAN RAPIDJSON_LITTLEENDIAN
|
||||
#else
|
||||
#define RAPIDJSON_ENDIAN RAPIDJSON_BIGENDIAN
|
||||
#endif // __BYTE_ORDER__
|
||||
#else
|
||||
#define RAPIDJSON_ENDIAN RAPIDJSON_LITTLEENDIAN // Assumes little endian otherwise.
|
||||
#endif
|
||||
#endif // RAPIDJSON_ENDIAN
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// RAPIDJSON_SSE2/RAPIDJSON_SSE42/RAPIDJSON_SIMD
|
||||
|
||||
// Enable SSE2 optimization.
|
||||
//#define RAPIDJSON_SSE2
|
||||
|
||||
// Enable SSE4.2 optimization.
|
||||
//#define RAPIDJSON_SSE42
|
||||
|
||||
#if defined(RAPIDJSON_SSE2) || defined(RAPIDJSON_SSE42)
|
||||
#define RAPIDJSON_SIMD
|
||||
#endif
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// RAPIDJSON_NO_SIZETYPEDEFINE
|
||||
|
||||
#ifndef RAPIDJSON_NO_SIZETYPEDEFINE
|
||||
namespace rapidjson {
|
||||
//! Use 32-bit array/string indices even for 64-bit platform, instead of using size_t.
|
||||
/*! User may override the SizeType by defining RAPIDJSON_NO_SIZETYPEDEFINE.
|
||||
*/
|
||||
typedef unsigned SizeType;
|
||||
} // namespace rapidjson
|
||||
#endif
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// RAPIDJSON_ASSERT
|
||||
|
||||
//! Assertion.
|
||||
/*! By default, rapidjson uses C assert() for assertion.
|
||||
User can override it by defining RAPIDJSON_ASSERT(x) macro.
|
||||
*/
|
||||
#ifndef RAPIDJSON_ASSERT
|
||||
#include <cassert>
|
||||
#define RAPIDJSON_ASSERT(x) assert(x)
|
||||
#endif // RAPIDJSON_ASSERT
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Helpers
|
||||
|
||||
#define RAPIDJSON_MULTILINEMACRO_BEGIN do {
|
||||
#define RAPIDJSON_MULTILINEMACRO_END \
|
||||
} while((void)0, 0)
|
||||
|
||||
namespace rapidjson {
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Allocator
|
||||
|
||||
/*! \class rapidjson::Allocator
|
||||
\brief Concept for allocating, resizing and freeing memory block.
|
||||
|
||||
Note that Malloc() and Realloc() are non-static but Free() is static.
|
||||
|
||||
So if an allocator need to support Free(), it needs to put its pointer in
|
||||
the header of memory block.
|
||||
|
||||
\code
|
||||
concept Allocator {
|
||||
static const bool kNeedFree; //!< Whether this allocator needs to call Free().
|
||||
|
||||
// Allocate a memory block.
|
||||
// \param size of the memory block in bytes.
|
||||
// \returns pointer to the memory block.
|
||||
void* Malloc(size_t size);
|
||||
|
||||
// Resize a memory block.
|
||||
// \param originalPtr The pointer to current memory block. Null_ pointer is permitted.
|
||||
// \param originalSize The current size in bytes. (Design issue: since some allocator may not book-keep this, explicitly pass to it can save memory.)
|
||||
// \param newSize the new size in bytes.
|
||||
void* Realloc(void* originalPtr, size_t originalSize, size_t newSize);
|
||||
|
||||
// Free a memory block.
|
||||
// \param pointer to the memory block. Null_ pointer is permitted.
|
||||
static void Free(void *ptr);
|
||||
};
|
||||
\endcode
|
||||
*/
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// CrtAllocator
|
||||
|
||||
//! C-runtime library allocator.
|
||||
/*! This class is just wrapper for standard C library memory routines.
|
||||
\implements Allocator
|
||||
*/
|
||||
class CrtAllocator {
|
||||
public:
|
||||
static const bool kNeedFree = true;
|
||||
void* Malloc(size_t size) { return malloc(size); }
|
||||
void* Realloc(void* originalPtr, size_t originalSize, size_t newSize) { (void)originalSize; return realloc(originalPtr, newSize); }
|
||||
static void Free(void *ptr) { free(ptr); }
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// MemoryPoolAllocator
|
||||
|
||||
//! Default memory allocator used by the parser and DOM.
|
||||
/*! This allocator allocate memory blocks from pre-allocated memory chunks.
|
||||
|
||||
It does not free memory blocks. And Realloc() only allocate new memory.
|
||||
|
||||
The memory chunks are allocated by BaseAllocator, which is CrtAllocator by default.
|
||||
|
||||
User may also supply a buffer as the first chunk.
|
||||
|
||||
If the user-buffer is full then additional chunks are allocated by BaseAllocator.
|
||||
|
||||
The user-buffer is not deallocated by this allocator.
|
||||
|
||||
\tparam BaseAllocator the allocator type for allocating memory chunks. Default is CrtAllocator.
|
||||
\implements Allocator
|
||||
*/
|
||||
template <typename BaseAllocator = CrtAllocator>
|
||||
class MemoryPoolAllocator {
|
||||
public:
|
||||
static const bool kNeedFree = false; //!< Tell users that no need to call Free() with this allocator. (concept Allocator)
|
||||
|
||||
//! Constructor with chunkSize.
|
||||
/*! \param chunkSize The size of memory chunk. The default is kDefaultChunkSize.
|
||||
\param baseAllocator The allocator for allocating memory chunks.
|
||||
*/
|
||||
MemoryPoolAllocator(size_t chunkSize = kDefaultChunkCapacity, BaseAllocator* baseAllocator = 0) :
|
||||
chunkHead_(0), chunk_capacity_(chunkSize), userBuffer_(0), baseAllocator_(baseAllocator), ownBaseAllocator_(0)
|
||||
{
|
||||
if (!baseAllocator_)
|
||||
ownBaseAllocator_ = baseAllocator_ = new BaseAllocator();
|
||||
AddChunk(chunk_capacity_);
|
||||
}
|
||||
|
||||
//! Constructor with user-supplied buffer.
|
||||
/*! The user buffer will be used firstly. When it is full, memory pool allocates new chunk with chunk size.
|
||||
|
||||
The user buffer will not be deallocated when this allocator is destructed.
|
||||
|
||||
\param buffer User supplied buffer.
|
||||
\param size Size of the buffer in bytes. It must at least larger than sizeof(ChunkHeader).
|
||||
\param chunkSize The size of memory chunk. The default is kDefaultChunkSize.
|
||||
\param baseAllocator The allocator for allocating memory chunks.
|
||||
*/
|
||||
MemoryPoolAllocator(char *buffer, size_t size, size_t chunkSize = kDefaultChunkCapacity, BaseAllocator* baseAllocator = 0) :
|
||||
chunkHead_(0), chunk_capacity_(chunkSize), userBuffer_(buffer), baseAllocator_(baseAllocator), ownBaseAllocator_(0)
|
||||
{
|
||||
RAPIDJSON_ASSERT(buffer != 0);
|
||||
RAPIDJSON_ASSERT(size > sizeof(ChunkHeader));
|
||||
chunkHead_ = (ChunkHeader*)buffer;
|
||||
chunkHead_->capacity = size - sizeof(ChunkHeader);
|
||||
chunkHead_->size = 0;
|
||||
chunkHead_->next = 0;
|
||||
}
|
||||
|
||||
//! Destructor.
|
||||
/*! This deallocates all memory chunks, excluding the user-supplied buffer.
|
||||
*/
|
||||
~MemoryPoolAllocator() {
|
||||
Clear();
|
||||
delete ownBaseAllocator_;
|
||||
}
|
||||
|
||||
//! Deallocates all memory chunks, excluding the user-supplied buffer.
|
||||
void Clear() {
|
||||
while(chunkHead_ != 0 && chunkHead_ != (ChunkHeader *)userBuffer_) {
|
||||
ChunkHeader* next = chunkHead_->next;
|
||||
baseAllocator_->Free(chunkHead_);
|
||||
chunkHead_ = next;
|
||||
}
|
||||
}
|
||||
|
||||
//! Computes the total capacity of allocated memory chunks.
|
||||
/*! \return total capacity in bytes.
|
||||
*/
|
||||
size_t Capacity() {
|
||||
size_t capacity = 0;
|
||||
for (ChunkHeader* c = chunkHead_; c != 0; c = c->next)
|
||||
capacity += c->capacity;
|
||||
return capacity;
|
||||
}
|
||||
|
||||
//! Computes the memory blocks allocated.
|
||||
/*! \return total used bytes.
|
||||
*/
|
||||
size_t Size() {
|
||||
size_t size = 0;
|
||||
for (ChunkHeader* c = chunkHead_; c != 0; c = c->next)
|
||||
size += c->size;
|
||||
return size;
|
||||
}
|
||||
|
||||
//! Allocates a memory block. (concept Allocator)
|
||||
void* Malloc(size_t size) {
|
||||
size = (size + 3) & ~3; // Force aligning size to 4
|
||||
|
||||
if (chunkHead_->size + size > chunkHead_->capacity)
|
||||
AddChunk(chunk_capacity_ > size ? chunk_capacity_ : size);
|
||||
|
||||
char *buffer = (char *)(chunkHead_ + 1) + chunkHead_->size;
|
||||
RAPIDJSON_ASSERT(((uintptr_t)buffer & 3) == 0); // returned buffer is aligned to 4
|
||||
chunkHead_->size += size;
|
||||
|
||||
return buffer;
|
||||
}
|
||||
|
||||
//! Resizes a memory block (concept Allocator)
|
||||
void* Realloc(void* originalPtr, size_t originalSize, size_t newSize) {
|
||||
if (originalPtr == 0)
|
||||
return Malloc(newSize);
|
||||
|
||||
// Do not shrink if new size is smaller than original
|
||||
if (originalSize >= newSize)
|
||||
return originalPtr;
|
||||
|
||||
// Simply expand it if it is the last allocation and there is sufficient space
|
||||
if (originalPtr == (char *)(chunkHead_ + 1) + chunkHead_->size - originalSize) {
|
||||
size_t increment = newSize - originalSize;
|
||||
increment = (increment + 3) & ~3; // Force aligning size to 4
|
||||
if (chunkHead_->size + increment <= chunkHead_->capacity) {
|
||||
chunkHead_->size += increment;
|
||||
RAPIDJSON_ASSERT(((uintptr_t)originalPtr & 3) == 0); // returned buffer is aligned to 4
|
||||
return originalPtr;
|
||||
}
|
||||
}
|
||||
|
||||
// Realloc process: allocate and copy memory, do not free original buffer.
|
||||
void* newBuffer = Malloc(newSize);
|
||||
RAPIDJSON_ASSERT(newBuffer != 0); // Do not handle out-of-memory explicitly.
|
||||
return memcpy(newBuffer, originalPtr, originalSize);
|
||||
}
|
||||
|
||||
//! Frees a memory block (concept Allocator)
|
||||
static void Free(void *) {} // Do nothing
|
||||
|
||||
private:
|
||||
//! Creates a new chunk.
|
||||
/*! \param capacity Capacity of the chunk in bytes.
|
||||
*/
|
||||
void AddChunk(size_t capacity) {
|
||||
ChunkHeader* chunk = (ChunkHeader*)baseAllocator_->Malloc(sizeof(ChunkHeader) + capacity);
|
||||
chunk->capacity = capacity;
|
||||
chunk->size = 0;
|
||||
chunk->next = chunkHead_;
|
||||
chunkHead_ = chunk;
|
||||
}
|
||||
|
||||
static const int kDefaultChunkCapacity = 64 * 1024; //!< Default chunk capacity.
|
||||
|
||||
//! Chunk header for perpending to each chunk.
|
||||
/*! Chunks are stored as a singly linked list.
|
||||
*/
|
||||
struct ChunkHeader {
|
||||
size_t capacity; //!< Capacity of the chunk in bytes (excluding the header itself).
|
||||
size_t size; //!< Current size of allocated memory in bytes.
|
||||
ChunkHeader *next; //!< Next chunk in the linked list.
|
||||
};
|
||||
|
||||
ChunkHeader *chunkHead_; //!< Head of the chunk linked-list. Only the head chunk serves allocation.
|
||||
size_t chunk_capacity_; //!< The minimum capacity of chunk when they are allocated.
|
||||
char *userBuffer_; //!< User supplied buffer.
|
||||
BaseAllocator* baseAllocator_; //!< base allocator for allocating memory chunks.
|
||||
BaseAllocator* ownBaseAllocator_; //!< base allocator created by this object.
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Encoding
|
||||
|
||||
/*! \class rapidjson::Encoding
|
||||
\brief Concept for encoding of Unicode characters.
|
||||
|
||||
\code
|
||||
concept Encoding {
|
||||
typename Ch; //! Type of character.
|
||||
|
||||
//! \brief Encode a Unicode codepoint to a buffer.
|
||||
//! \param buffer pointer to destination buffer to store the result. It should have sufficient size of encoding one character.
|
||||
//! \param codepoint An unicode codepoint, ranging from 0x0 to 0x10FFFF inclusively.
|
||||
//! \returns the pointer to the next character after the encoded data.
|
||||
static Ch* Encode(Ch *buffer, unsigned codepoint);
|
||||
};
|
||||
\endcode
|
||||
*/
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// UTF8
|
||||
|
||||
//! UTF-8 encoding.
|
||||
/*! http://en.wikipedia.org/wiki/UTF-8
|
||||
\tparam CharType Type for storing 8-bit UTF-8 data. Default is char.
|
||||
\implements Encoding
|
||||
*/
|
||||
template<typename CharType = char>
|
||||
struct UTF8 {
|
||||
typedef CharType Ch;
|
||||
|
||||
static Ch* Encode(Ch *buffer, unsigned codepoint) {
|
||||
if (codepoint <= 0x7F)
|
||||
*buffer++ = codepoint & 0xFF;
|
||||
else if (codepoint <= 0x7FF) {
|
||||
*buffer++ = 0xC0 | ((codepoint >> 6) & 0xFF);
|
||||
*buffer++ = 0x80 | ((codepoint & 0x3F));
|
||||
}
|
||||
else if (codepoint <= 0xFFFF) {
|
||||
*buffer++ = 0xE0 | ((codepoint >> 12) & 0xFF);
|
||||
*buffer++ = 0x80 | ((codepoint >> 6) & 0x3F);
|
||||
*buffer++ = 0x80 | (codepoint & 0x3F);
|
||||
}
|
||||
else {
|
||||
RAPIDJSON_ASSERT(codepoint <= 0x10FFFF);
|
||||
*buffer++ = 0xF0 | ((codepoint >> 18) & 0xFF);
|
||||
*buffer++ = 0x80 | ((codepoint >> 12) & 0x3F);
|
||||
*buffer++ = 0x80 | ((codepoint >> 6) & 0x3F);
|
||||
*buffer++ = 0x80 | (codepoint & 0x3F);
|
||||
}
|
||||
return buffer;
|
||||
}
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// UTF16
|
||||
|
||||
//! UTF-16 encoding.
|
||||
/*! http://en.wikipedia.org/wiki/UTF-16
|
||||
\tparam CharType Type for storing 16-bit UTF-16 data. Default is wchar_t. C++11 may use char16_t instead.
|
||||
\implements Encoding
|
||||
*/
|
||||
template<typename CharType = wchar_t>
|
||||
struct UTF16 {
|
||||
typedef CharType Ch;
|
||||
|
||||
static Ch* Encode(Ch* buffer, unsigned codepoint) {
|
||||
if (codepoint <= 0xFFFF) {
|
||||
RAPIDJSON_ASSERT(codepoint < 0xD800 || codepoint > 0xDFFF); // Code point itself cannot be surrogate pair
|
||||
*buffer++ = static_cast<Ch>(codepoint);
|
||||
}
|
||||
else {
|
||||
RAPIDJSON_ASSERT(codepoint <= 0x10FFFF);
|
||||
unsigned v = codepoint - 0x10000;
|
||||
*buffer++ = static_cast<Ch>((v >> 10) + 0xD800);
|
||||
*buffer++ = (v & 0x3FF) + 0xDC00;
|
||||
}
|
||||
return buffer;
|
||||
}
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// UTF32
|
||||
|
||||
//! UTF-32 encoding.
|
||||
/*! http://en.wikipedia.org/wiki/UTF-32
|
||||
\tparam Ch Type for storing 32-bit UTF-32 data. Default is unsigned. C++11 may use char32_t instead.
|
||||
\implements Encoding
|
||||
*/
|
||||
template<typename CharType = unsigned>
|
||||
struct UTF32 {
|
||||
typedef CharType Ch;
|
||||
|
||||
static Ch *Encode(Ch* buffer, unsigned codepoint) {
|
||||
RAPIDJSON_ASSERT(codepoint <= 0x10FFFF);
|
||||
*buffer++ = codepoint;
|
||||
return buffer;
|
||||
}
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Stream
|
||||
|
||||
/*! \class rapidjson::Stream
|
||||
\brief Concept for reading and writing characters.
|
||||
|
||||
For read-only stream, no need to implement PutBegin(), Put() and PutEnd().
|
||||
|
||||
For write-only stream, only need to implement Put().
|
||||
|
||||
\code
|
||||
concept Stream {
|
||||
typename Ch; //!< Character type of the stream.
|
||||
|
||||
//! Read the current character from stream without moving the read cursor.
|
||||
Ch Peek() const;
|
||||
|
||||
//! Read the current character from stream and moving the read cursor to next character.
|
||||
Ch Take();
|
||||
|
||||
//! Get the current read cursor.
|
||||
//! \return Number of characters read from start.
|
||||
size_t Tell();
|
||||
|
||||
//! Begin writing operation at the current read pointer.
|
||||
//! \return The begin writer pointer.
|
||||
Ch* PutBegin();
|
||||
|
||||
//! Write a character.
|
||||
void Put(Ch c);
|
||||
|
||||
//! End the writing operation.
|
||||
//! \param begin The begin write pointer returned by PutBegin().
|
||||
//! \return Number of characters written.
|
||||
size_t PutEnd(Ch* begin);
|
||||
}
|
||||
\endcode
|
||||
*/
|
||||
|
||||
//! Put N copies of a character to a stream.
|
||||
template<typename Stream, typename Ch>
|
||||
inline void PutN(Stream& stream, Ch c, size_t n) {
|
||||
for (size_t i = 0; i < n; i++)
|
||||
stream.Put(c);
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// StringStream
|
||||
|
||||
//! Read-only string stream.
|
||||
/*! \implements Stream
|
||||
*/
|
||||
template <typename Encoding>
|
||||
struct GenericStringStream {
|
||||
typedef typename Encoding::Ch Ch;
|
||||
|
||||
GenericStringStream(const Ch *src) : src_(src), head_(src) {}
|
||||
|
||||
Ch Peek() const { return *src_; }
|
||||
Ch Take() { return *src_++; }
|
||||
size_t Tell() const { return src_ - head_; }
|
||||
|
||||
Ch* PutBegin() { RAPIDJSON_ASSERT(false); return 0; }
|
||||
void Put(Ch) { RAPIDJSON_ASSERT(false); }
|
||||
size_t PutEnd(Ch*) { RAPIDJSON_ASSERT(false); return 0; }
|
||||
|
||||
const Ch* src_; //!< Current read position.
|
||||
const Ch* head_; //!< Original head of the string.
|
||||
};
|
||||
|
||||
typedef GenericStringStream<UTF8<> > StringStream;
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// InsituStringStream
|
||||
|
||||
//! A read-write string stream.
|
||||
/*! This string stream is particularly designed for in-situ parsing.
|
||||
\implements Stream
|
||||
*/
|
||||
template <typename Encoding>
|
||||
struct GenericInsituStringStream {
|
||||
typedef typename Encoding::Ch Ch;
|
||||
|
||||
GenericInsituStringStream(Ch *src) : src_(src), dst_(0), head_(src) {}
|
||||
|
||||
// Read
|
||||
Ch Peek() { return *src_; }
|
||||
Ch Take() { return *src_++; }
|
||||
size_t Tell() { return src_ - head_; }
|
||||
|
||||
// Write
|
||||
Ch* PutBegin() { return dst_ = src_; }
|
||||
void Put(Ch c) { RAPIDJSON_ASSERT(dst_ != 0); *dst_++ = c; }
|
||||
size_t PutEnd(Ch* begin) { return dst_ - begin; }
|
||||
|
||||
Ch* src_;
|
||||
Ch* dst_;
|
||||
Ch* head_;
|
||||
};
|
||||
|
||||
typedef GenericInsituStringStream<UTF8<> > InsituStringStream;
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Type
|
||||
|
||||
//! Type of JSON value
|
||||
enum Type {
|
||||
kNull_Type = 0, //!< null
|
||||
kFalseType = 1, //!< false
|
||||
kTrueType = 2, //!< true
|
||||
kObjectType = 3, //!< object
|
||||
kArrayType = 4, //!< array
|
||||
kStringType = 5, //!< string
|
||||
kNumberType = 6, //!< number
|
||||
};
|
||||
|
||||
} // namespace rapidjson
|
||||
|
||||
#endif // RAPIDJSON_RAPIDJSON_H_
|
||||
749
libs/cereal/cereal/external/rapidjson/reader.h
vendored
Normal file
749
libs/cereal/cereal/external/rapidjson/reader.h
vendored
Normal file
@ -0,0 +1,749 @@
|
||||
#ifndef RAPIDJSON_READER_H_
|
||||
#define RAPIDJSON_READER_H_
|
||||
|
||||
// Copyright (c) 2011 Milo Yip (miloyip@gmail.com)
|
||||
// Version 0.1
|
||||
|
||||
#include "rapidjson.h"
|
||||
#include "internal/pow10.h"
|
||||
#include "internal/stack.h"
|
||||
#include <csetjmp>
|
||||
|
||||
// All part of denormalized parsing
|
||||
#include <limits> // for numeric_limits
|
||||
#include <cmath> // for fpclassify
|
||||
#include <sstream>
|
||||
|
||||
#ifdef RAPIDJSON_SSE42
|
||||
#include <nmmintrin.h>
|
||||
#elif defined(RAPIDJSON_SSE2)
|
||||
#include <emmintrin.h>
|
||||
#endif
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable : 4127) // conditional expression is constant
|
||||
#pragma warning(disable : 4702) // uncreachable code
|
||||
#endif
|
||||
|
||||
#ifndef RAPIDJSON_PARSE_ERROR
|
||||
#define RAPIDJSON_PARSE_ERROR(msg, offset) \
|
||||
RAPIDJSON_MULTILINEMACRO_BEGIN \
|
||||
parseError_ = msg; \
|
||||
errorOffset_ = offset; \
|
||||
longjmp(jmpbuf_, 1); \
|
||||
RAPIDJSON_MULTILINEMACRO_END
|
||||
#endif
|
||||
namespace rapidjson {
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// ParseFlag
|
||||
|
||||
//! Combination of parseFlags
|
||||
enum ParseFlag {
|
||||
kParseDefaultFlags = 0, //!< Default parse flags. Non-destructive parsing. Text strings are decoded into allocated buffer.
|
||||
kParseInsituFlag = 1 //!< In-situ(destructive) parsing.
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Handler
|
||||
|
||||
/*! \class rapidjson::Handler
|
||||
\brief Concept for receiving events from GenericReader upon parsing.
|
||||
\code
|
||||
concept Handler {
|
||||
typename Ch;
|
||||
|
||||
void Null_();
|
||||
void Bool_(bool b);
|
||||
void Int(int i);
|
||||
void Uint(unsigned i);
|
||||
void Int64(int64_t i);
|
||||
void Uint64(uint64_t i);
|
||||
void Double(double d);
|
||||
void String(const Ch* str, SizeType length, bool copy);
|
||||
void StartObject();
|
||||
void EndObject(SizeType memberCount);
|
||||
void StartArray();
|
||||
void EndArray(SizeType elementCount);
|
||||
};
|
||||
\endcode
|
||||
*/
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// BaseReaderHandler
|
||||
|
||||
//! Default implementation of Handler.
|
||||
/*! This can be used as base class of any reader handler.
|
||||
\implements Handler
|
||||
*/
|
||||
template<typename Encoding = UTF8<> >
|
||||
struct BaseReaderHandler {
|
||||
typedef typename Encoding::Ch Ch;
|
||||
|
||||
void Default() {}
|
||||
void Null_() { Default(); }
|
||||
void Bool_(bool) { Default(); }
|
||||
void Int(int) { Default(); }
|
||||
void Uint(unsigned) { Default(); }
|
||||
void Int64(int64_t) { Default(); }
|
||||
void Uint64(uint64_t) { Default(); }
|
||||
void Double(double) { Default(); }
|
||||
void String(const Ch*, SizeType, bool) { Default(); }
|
||||
void StartObject() { Default(); }
|
||||
void EndObject(SizeType) { Default(); }
|
||||
void StartArray() { Default(); }
|
||||
void EndArray(SizeType) { Default(); }
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// SkipWhitespace
|
||||
|
||||
//! Skip the JSON white spaces in a stream.
|
||||
/*! \param stream A input stream for skipping white spaces.
|
||||
\note This function has SSE2/SSE4.2 specialization.
|
||||
*/
|
||||
template<typename Stream>
|
||||
void SkipWhitespace(Stream& stream) {
|
||||
Stream s = stream; // Use a local copy for optimization
|
||||
while (s.Peek() == ' ' || s.Peek() == '\n' || s.Peek() == '\r' || s.Peek() == '\t')
|
||||
s.Take();
|
||||
stream = s;
|
||||
}
|
||||
|
||||
#ifdef RAPIDJSON_SSE42
|
||||
//! Skip whitespace with SSE 4.2 pcmpistrm instruction, testing 16 8-byte characters at once.
|
||||
inline const char *SkipWhitespace_SIMD(const char* p) {
|
||||
static const char whitespace[16] = " \n\r\t";
|
||||
__m128i w = _mm_loadu_si128((const __m128i *)&whitespace[0]);
|
||||
|
||||
for (;;) {
|
||||
__m128i s = _mm_loadu_si128((const __m128i *)p);
|
||||
unsigned r = _mm_cvtsi128_si32(_mm_cmpistrm(w, s, _SIDD_UBYTE_OPS | _SIDD_CMP_EQUAL_ANY | _SIDD_BIT_MASK | _SIDD_NEGATIVE_POLARITY));
|
||||
if (r == 0) // all 16 characters are whitespace
|
||||
p += 16;
|
||||
else { // some of characters may be non-whitespace
|
||||
#ifdef _MSC_VER // Find the index of first non-whitespace
|
||||
unsigned long offset;
|
||||
if (_BitScanForward(&offset, r))
|
||||
return p + offset;
|
||||
#else
|
||||
if (r != 0)
|
||||
return p + __builtin_ffs(r) - 1;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#elif defined(RAPIDJSON_SSE2)
|
||||
|
||||
//! Skip whitespace with SSE2 instructions, testing 16 8-byte characters at once.
|
||||
inline const char *SkipWhitespace_SIMD(const char* p) {
|
||||
static const char whitespaces[4][17] = {
|
||||
" ",
|
||||
"\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n",
|
||||
"\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r",
|
||||
"\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t"};
|
||||
|
||||
__m128i w0 = _mm_loadu_si128((const __m128i *)&whitespaces[0][0]);
|
||||
__m128i w1 = _mm_loadu_si128((const __m128i *)&whitespaces[1][0]);
|
||||
__m128i w2 = _mm_loadu_si128((const __m128i *)&whitespaces[2][0]);
|
||||
__m128i w3 = _mm_loadu_si128((const __m128i *)&whitespaces[3][0]);
|
||||
|
||||
for (;;) {
|
||||
__m128i s = _mm_loadu_si128((const __m128i *)p);
|
||||
__m128i x = _mm_cmpeq_epi8(s, w0);
|
||||
x = _mm_or_si128(x, _mm_cmpeq_epi8(s, w1));
|
||||
x = _mm_or_si128(x, _mm_cmpeq_epi8(s, w2));
|
||||
x = _mm_or_si128(x, _mm_cmpeq_epi8(s, w3));
|
||||
unsigned short r = ~_mm_movemask_epi8(x);
|
||||
if (r == 0) // all 16 characters are whitespace
|
||||
p += 16;
|
||||
else { // some of characters may be non-whitespace
|
||||
#ifdef _MSC_VER // Find the index of first non-whitespace
|
||||
unsigned long offset;
|
||||
if (_BitScanForward(&offset, r))
|
||||
return p + offset;
|
||||
#else
|
||||
if (r != 0)
|
||||
return p + __builtin_ffs(r) - 1;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif // RAPIDJSON_SSE2
|
||||
|
||||
#ifdef RAPIDJSON_SIMD
|
||||
//! Template function specialization for InsituStringStream
|
||||
template<> inline void SkipWhitespace(InsituStringStream& stream) {
|
||||
stream.src_ = const_cast<char*>(SkipWhitespace_SIMD(stream.src_));
|
||||
}
|
||||
|
||||
//! Template function specialization for StringStream
|
||||
template<> inline void SkipWhitespace(StringStream& stream) {
|
||||
stream.src_ = SkipWhitespace_SIMD(stream.src_);
|
||||
}
|
||||
#endif // RAPIDJSON_SIMD
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// GenericReader
|
||||
|
||||
//! SAX-style JSON parser. Use Reader for UTF8 encoding and default allocator.
|
||||
/*! GenericReader parses JSON text from a stream, and send events synchronously to an
|
||||
object implementing Handler concept.
|
||||
|
||||
It needs to allocate a stack for storing a single decoded string during
|
||||
non-destructive parsing.
|
||||
|
||||
For in-situ parsing, the decoded string is directly written to the source
|
||||
text string, no temporary buffer is required.
|
||||
|
||||
A GenericReader object can be reused for parsing multiple JSON text.
|
||||
|
||||
\tparam Encoding Encoding of both the stream and the parse output.
|
||||
\tparam Allocator Allocator type for stack.
|
||||
*/
|
||||
template <typename Encoding, typename Allocator = MemoryPoolAllocator<> >
|
||||
class GenericReader {
|
||||
public:
|
||||
typedef typename Encoding::Ch Ch;
|
||||
|
||||
//! Constructor.
|
||||
/*! \param allocator Optional allocator for allocating stack memory. (Only use for non-destructive parsing)
|
||||
\param stackCapacity stack capacity in bytes for storing a single decoded string. (Only use for non-destructive parsing)
|
||||
*/
|
||||
GenericReader(Allocator* allocator = 0, size_t stackCapacity = kDefaultStackCapacity) : stack_(allocator, stackCapacity), parseError_(0), errorOffset_(0) {}
|
||||
|
||||
//! Parse JSON text.
|
||||
/*! \tparam parseFlags Combination of ParseFlag.
|
||||
\tparam Stream Type of input stream.
|
||||
\tparam Handler Type of handler which must implement Handler concept.
|
||||
\param stream Input stream to be parsed.
|
||||
\param handler The handler to receive events.
|
||||
\return Whether the parsing is successful.
|
||||
*/
|
||||
template <unsigned parseFlags, typename Stream, typename Handler>
|
||||
bool Parse(Stream& stream, Handler& handler) {
|
||||
parseError_ = 0;
|
||||
errorOffset_ = 0;
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable : 4611) // interaction between '_setjmp' and C++ object destruction is non-portable
|
||||
#endif
|
||||
if (setjmp(jmpbuf_)) {
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(pop)
|
||||
#endif
|
||||
stack_.Clear();
|
||||
return false;
|
||||
}
|
||||
|
||||
SkipWhitespace(stream);
|
||||
|
||||
if (stream.Peek() == '\0')
|
||||
RAPIDJSON_PARSE_ERROR("Text only contains white space(s)", stream.Tell());
|
||||
else {
|
||||
switch (stream.Peek()) {
|
||||
case '{': ParseObject<parseFlags>(stream, handler); break;
|
||||
case '[': ParseArray<parseFlags>(stream, handler); break;
|
||||
default: RAPIDJSON_PARSE_ERROR("Expect either an object or array at root", stream.Tell());
|
||||
}
|
||||
SkipWhitespace(stream);
|
||||
|
||||
if (stream.Peek() != '\0' && stream.Peek() != static_cast<Ch>(std::char_traits<Ch>::eof()))
|
||||
RAPIDJSON_PARSE_ERROR("Nothing should follow the root object or array.", stream.Tell());
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool HasParseError() const { return parseError_ != 0; }
|
||||
const char* GetParseError() const { return parseError_; }
|
||||
size_t GetErrorOffset() const { return errorOffset_; }
|
||||
|
||||
private:
|
||||
// Parse object: { string : value, ... }
|
||||
template<unsigned parseFlags, typename Stream, typename Handler>
|
||||
void ParseObject(Stream& stream, Handler& handler) {
|
||||
RAPIDJSON_ASSERT(stream.Peek() == '{');
|
||||
stream.Take(); // Skip '{'
|
||||
handler.StartObject();
|
||||
SkipWhitespace(stream);
|
||||
|
||||
if (stream.Peek() == '}') {
|
||||
stream.Take();
|
||||
handler.EndObject(0); // empty object
|
||||
return;
|
||||
}
|
||||
|
||||
for (SizeType memberCount = 0;;) {
|
||||
if (stream.Peek() != '"') {
|
||||
RAPIDJSON_PARSE_ERROR("Name of an object member must be a string", stream.Tell());
|
||||
break;
|
||||
}
|
||||
|
||||
ParseString<parseFlags>(stream, handler);
|
||||
SkipWhitespace(stream);
|
||||
|
||||
if (stream.Take() != ':') {
|
||||
RAPIDJSON_PARSE_ERROR("There must be a colon after the name of object member", stream.Tell());
|
||||
break;
|
||||
}
|
||||
SkipWhitespace(stream);
|
||||
|
||||
ParseValue<parseFlags>(stream, handler);
|
||||
SkipWhitespace(stream);
|
||||
|
||||
++memberCount;
|
||||
|
||||
switch(stream.Take()) {
|
||||
case ',': SkipWhitespace(stream); break;
|
||||
case '}': handler.EndObject(memberCount); return;
|
||||
default: RAPIDJSON_PARSE_ERROR("Must be a comma or '}' after an object member", stream.Tell());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Parse array: [ value, ... ]
|
||||
template<unsigned parseFlags, typename Stream, typename Handler>
|
||||
void ParseArray(Stream& stream, Handler& handler) {
|
||||
RAPIDJSON_ASSERT(stream.Peek() == '[');
|
||||
stream.Take(); // Skip '['
|
||||
handler.StartArray();
|
||||
SkipWhitespace(stream);
|
||||
|
||||
if (stream.Peek() == ']') {
|
||||
stream.Take();
|
||||
handler.EndArray(0); // empty array
|
||||
return;
|
||||
}
|
||||
|
||||
for (SizeType elementCount = 0;;) {
|
||||
ParseValue<parseFlags>(stream, handler);
|
||||
++elementCount;
|
||||
SkipWhitespace(stream);
|
||||
|
||||
switch (stream.Take()) {
|
||||
case ',': SkipWhitespace(stream); break;
|
||||
case ']': handler.EndArray(elementCount); return;
|
||||
default: RAPIDJSON_PARSE_ERROR("Must be a comma or ']' after an array element.", stream.Tell());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Parses for null or NaN
|
||||
template<unsigned parseFlags, typename Stream, typename Handler>
|
||||
void ParseNaNNull_(Stream& stream, Handler& handler) {
|
||||
RAPIDJSON_ASSERT(stream.Peek() == 'n');
|
||||
stream.Take();
|
||||
|
||||
if( stream.Peek() == 'a' && stream.Take() == 'a' && stream.Take() == 'n' )
|
||||
handler.Double( std::numeric_limits<double>::quiet_NaN() );
|
||||
else if (stream.Take() == 'u' && stream.Take() == 'l' && stream.Take() == 'l')
|
||||
handler.Null_();
|
||||
else
|
||||
RAPIDJSON_PARSE_ERROR("Invalid value", stream.Tell() - 1);
|
||||
}
|
||||
|
||||
// Parses for infinity
|
||||
template<unsigned parseFlags, typename Stream, typename Handler>
|
||||
void ParseInfinity(Stream& stream, Handler& handler) {
|
||||
RAPIDJSON_ASSERT(stream.Peek() == 'i');
|
||||
stream.Take();
|
||||
|
||||
if (stream.Take() == 'n' && stream.Take() == 'f')
|
||||
handler.Double( std::numeric_limits<double>::infinity() );
|
||||
else
|
||||
RAPIDJSON_PARSE_ERROR("Invalid value", stream.Tell() - 1);
|
||||
}
|
||||
|
||||
template<unsigned parseFlags, typename Stream, typename Handler>
|
||||
void ParseTrue(Stream& stream, Handler& handler) {
|
||||
RAPIDJSON_ASSERT(stream.Peek() == 't');
|
||||
stream.Take();
|
||||
|
||||
if (stream.Take() == 'r' && stream.Take() == 'u' && stream.Take() == 'e')
|
||||
handler.Bool_(true);
|
||||
else
|
||||
RAPIDJSON_PARSE_ERROR("Invalid value", stream.Tell());
|
||||
}
|
||||
|
||||
template<unsigned parseFlags, typename Stream, typename Handler>
|
||||
void ParseFalse(Stream& stream, Handler& handler) {
|
||||
RAPIDJSON_ASSERT(stream.Peek() == 'f');
|
||||
stream.Take();
|
||||
|
||||
if (stream.Take() == 'a' && stream.Take() == 'l' && stream.Take() == 's' && stream.Take() == 'e')
|
||||
handler.Bool_(false);
|
||||
else
|
||||
RAPIDJSON_PARSE_ERROR("Invalid value", stream.Tell() - 1);
|
||||
}
|
||||
|
||||
// Helper function to parse four hexidecimal digits in \uXXXX in ParseString().
|
||||
template<typename Stream>
|
||||
unsigned ParseHex4(Stream& stream) {
|
||||
Stream s = stream; // Use a local copy for optimization
|
||||
unsigned codepoint = 0;
|
||||
for (int i = 0; i < 4; i++) {
|
||||
Ch c = s.Take();
|
||||
codepoint <<= 4;
|
||||
codepoint += c;
|
||||
if (c >= '0' && c <= '9')
|
||||
codepoint -= '0';
|
||||
else if (c >= 'A' && c <= 'F')
|
||||
codepoint -= 'A' - 10;
|
||||
else if (c >= 'a' && c <= 'f')
|
||||
codepoint -= 'a' - 10;
|
||||
else
|
||||
RAPIDJSON_PARSE_ERROR("Incorrect hex digit after \\u escape", s.Tell() - 1);
|
||||
}
|
||||
stream = s; // Restore stream
|
||||
return codepoint;
|
||||
}
|
||||
|
||||
// cereal Temporary until constexpr support is added in RTM
|
||||
#ifdef _MSC_VER
|
||||
template <class Ch>
|
||||
bool characterOk( Ch c )
|
||||
{
|
||||
return c < 256;
|
||||
}
|
||||
|
||||
template <>
|
||||
bool characterOk<char>( char )
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
#else
|
||||
// As part of a fix for GCC 4.7
|
||||
template <class T>
|
||||
static constexpr int to_int( T t ){ return t; }
|
||||
|
||||
template<class Ch>
|
||||
typename std::enable_if < to_int(std::numeric_limits<Ch>::max()) < to_int(256), bool>::type
|
||||
characterOk( Ch )
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
template<class Ch>
|
||||
typename std::enable_if< to_int(std::numeric_limits<Ch>::max()) >= to_int(256), bool>::type
|
||||
characterOk(Ch c)
|
||||
{ return c < 256; }
|
||||
#endif
|
||||
|
||||
// Parse string, handling the prefix and suffix double quotes and escaping.
|
||||
template<unsigned parseFlags, typename Stream, typename Handler>
|
||||
void ParseString(Stream& stream, Handler& handler) {
|
||||
#define Z16 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
|
||||
static const Ch escape[256] = {
|
||||
Z16, Z16, 0, 0,'\"', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,'/',
|
||||
Z16, Z16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,'\\', 0, 0, 0,
|
||||
0, 0,'\b', 0, 0, 0,'\f', 0, 0, 0, 0, 0, 0, 0,'\n', 0,
|
||||
0, 0,'\r', 0,'\t', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
Z16, Z16, Z16, Z16, Z16, Z16, Z16, Z16
|
||||
};
|
||||
#undef Z16
|
||||
|
||||
Stream s = stream; // Use a local copy for optimization
|
||||
RAPIDJSON_ASSERT(s.Peek() == '\"');
|
||||
s.Take(); // Skip '\"'
|
||||
Ch *head;
|
||||
SizeType len;
|
||||
if (parseFlags & kParseInsituFlag)
|
||||
head = s.PutBegin();
|
||||
else
|
||||
len = 0;
|
||||
|
||||
#define RAPIDJSON_PUT(x) \
|
||||
do { \
|
||||
if (parseFlags & kParseInsituFlag) \
|
||||
s.Put(x); \
|
||||
else { \
|
||||
*stack_.template Push<Ch>() = x; \
|
||||
++len; \
|
||||
} \
|
||||
} while(false)
|
||||
|
||||
for (;;) {
|
||||
Ch c = s.Take();
|
||||
if (c == '\\') { // Escape
|
||||
Ch e = s.Take();
|
||||
if ((sizeof(Ch) == 1 || characterOk(e)) && escape[(unsigned char)e])
|
||||
RAPIDJSON_PUT(escape[(unsigned char)e]);
|
||||
else if (e == 'u') { // Unicode
|
||||
unsigned codepoint = ParseHex4(s);
|
||||
if (codepoint >= 0xD800 && codepoint <= 0xDBFF) { // Handle UTF-16 surrogate pair
|
||||
if (s.Take() != '\\' || s.Take() != 'u') {
|
||||
RAPIDJSON_PARSE_ERROR("Missing the second \\u in surrogate pair", s.Tell() - 2);
|
||||
return;
|
||||
}
|
||||
unsigned codepoint2 = ParseHex4(s);
|
||||
if (codepoint2 < 0xDC00 || codepoint2 > 0xDFFF) {
|
||||
RAPIDJSON_PARSE_ERROR("The second \\u in surrogate pair is invalid", s.Tell() - 2);
|
||||
return;
|
||||
}
|
||||
codepoint = (((codepoint - 0xD800) << 10) | (codepoint2 - 0xDC00)) + 0x10000;
|
||||
}
|
||||
|
||||
Ch buffer[4];
|
||||
SizeType count = SizeType(Encoding::Encode(buffer, codepoint) - &buffer[0]);
|
||||
|
||||
if (parseFlags & kParseInsituFlag)
|
||||
for (SizeType i = 0; i < count; i++)
|
||||
s.Put(buffer[i]);
|
||||
else {
|
||||
memcpy(stack_.template Push<Ch>(count), buffer, count * sizeof(Ch));
|
||||
len += count;
|
||||
}
|
||||
}
|
||||
else {
|
||||
RAPIDJSON_PARSE_ERROR("Unknown escape character", stream.Tell() - 1);
|
||||
return;
|
||||
}
|
||||
}
|
||||
else if (c == '"') { // Closing double quote
|
||||
if (parseFlags & kParseInsituFlag) {
|
||||
size_t length = s.PutEnd(head);
|
||||
RAPIDJSON_ASSERT(length <= 0xFFFFFFFF);
|
||||
RAPIDJSON_PUT('\0'); // null-terminate the string
|
||||
handler.String(head, SizeType(length), false);
|
||||
}
|
||||
else {
|
||||
RAPIDJSON_PUT('\0');
|
||||
handler.String(stack_.template Pop<Ch>(len), len - 1, true);
|
||||
}
|
||||
stream = s; // restore stream
|
||||
return;
|
||||
}
|
||||
else if (c == '\0') {
|
||||
RAPIDJSON_PARSE_ERROR("lacks ending quotation before the end of string", stream.Tell() - 1);
|
||||
return;
|
||||
}
|
||||
else if ((unsigned)c < 0x20) { // RFC 4627: unescaped = %x20-21 / %x23-5B / %x5D-10FFFF
|
||||
RAPIDJSON_PARSE_ERROR("Incorrect unescaped character in string", stream.Tell() - 1);
|
||||
return;
|
||||
}
|
||||
else
|
||||
RAPIDJSON_PUT(c); // Normal character, just copy
|
||||
}
|
||||
#undef RAPIDJSON_PUT
|
||||
}
|
||||
|
||||
template<unsigned parseFlags, typename Stream, typename Handler>
|
||||
void ParseNumber(Stream& stream, Handler& handler) {
|
||||
Stream s = stream; // Local copy for optimization
|
||||
|
||||
// Parse minus
|
||||
bool minus = false;
|
||||
if (s.Peek() == '-') {
|
||||
minus = true;
|
||||
s.Take();
|
||||
}
|
||||
|
||||
// Parse int: zero / ( digit1-9 *DIGIT )
|
||||
unsigned i;
|
||||
bool try64bit = false;
|
||||
if (s.Peek() == '0') {
|
||||
i = 0;
|
||||
s.Take();
|
||||
}
|
||||
else if (s.Peek() >= '1' && s.Peek() <= '9') {
|
||||
i = s.Take() - '0';
|
||||
|
||||
if (minus)
|
||||
while (s.Peek() >= '0' && s.Peek() <= '9') {
|
||||
if (i >= 214748364) { // 2^31 = 2147483648
|
||||
if (i != 214748364 || s.Peek() > '8') {
|
||||
try64bit = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
i = i * 10 + (s.Take() - '0');
|
||||
}
|
||||
else
|
||||
while (s.Peek() >= '0' && s.Peek() <= '9') {
|
||||
if (i >= 429496729) { // 2^32 - 1 = 4294967295
|
||||
if (i != 429496729 || s.Peek() > '5') {
|
||||
try64bit = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
i = i * 10 + (s.Take() - '0');
|
||||
}
|
||||
}
|
||||
else {
|
||||
RAPIDJSON_PARSE_ERROR("Expect a value here.", stream.Tell());
|
||||
return;
|
||||
}
|
||||
|
||||
// Parse 64bit int
|
||||
uint64_t i64 = 0;
|
||||
bool useDouble = false;
|
||||
if (try64bit) {
|
||||
i64 = i;
|
||||
if (minus)
|
||||
while (s.Peek() >= '0' && s.Peek() <= '9') {
|
||||
if (i64 >= 922337203685477580uLL) // 2^63 = 9223372036854775808
|
||||
if (i64 != 922337203685477580uLL || s.Peek() > '8') {
|
||||
useDouble = true;
|
||||
break;
|
||||
}
|
||||
i64 = i64 * 10 + (s.Take() - '0');
|
||||
}
|
||||
else
|
||||
while (s.Peek() >= '0' && s.Peek() <= '9') {
|
||||
if (i64 >= 1844674407370955161uLL) // 2^64 - 1 = 18446744073709551615
|
||||
if (i64 != 1844674407370955161uLL || s.Peek() > '5') {
|
||||
useDouble = true;
|
||||
break;
|
||||
}
|
||||
i64 = i64 * 10 + (s.Take() - '0');
|
||||
}
|
||||
}
|
||||
|
||||
// Force double for big integer
|
||||
double d = 0.0;
|
||||
if (useDouble) {
|
||||
d = (double)i64;
|
||||
while (s.Peek() >= '0' && s.Peek() <= '9') {
|
||||
if (d >= 1E307) {
|
||||
RAPIDJSON_PARSE_ERROR("Number too big to store in double", stream.Tell());
|
||||
return;
|
||||
}
|
||||
d = d * 10 + (s.Take() - '0');
|
||||
}
|
||||
}
|
||||
|
||||
// Parse frac = decimal-point 1*DIGIT
|
||||
int expFrac = 0;
|
||||
if (s.Peek() == '.') {
|
||||
if (!useDouble) {
|
||||
d = try64bit ? (double)i64 : (double)i;
|
||||
useDouble = true;
|
||||
}
|
||||
s.Take();
|
||||
|
||||
if (s.Peek() >= '0' && s.Peek() <= '9') {
|
||||
d = d * 10 + (s.Take() - '0');
|
||||
--expFrac;
|
||||
}
|
||||
else {
|
||||
RAPIDJSON_PARSE_ERROR("At least one digit in fraction part", stream.Tell());
|
||||
return;
|
||||
}
|
||||
|
||||
while (s.Peek() >= '0' && s.Peek() <= '9') {
|
||||
if (expFrac > -20) {
|
||||
d = d * 10 + (s.Peek() - '0');
|
||||
--expFrac;
|
||||
}
|
||||
s.Take();
|
||||
}
|
||||
}
|
||||
|
||||
// Parse exp = e [ minus / plus ] 1*DIGIT
|
||||
int exp = 0;
|
||||
if (s.Peek() == 'e' || s.Peek() == 'E') {
|
||||
if (!useDouble) {
|
||||
d = try64bit ? (double)i64 : (double)i;
|
||||
useDouble = true;
|
||||
}
|
||||
s.Take();
|
||||
|
||||
bool expMinus = false;
|
||||
if (s.Peek() == '+')
|
||||
s.Take();
|
||||
else if (s.Peek() == '-') {
|
||||
s.Take();
|
||||
expMinus = true;
|
||||
}
|
||||
|
||||
if (s.Peek() >= '0' && s.Peek() <= '9') {
|
||||
exp = s.Take() - '0';
|
||||
while (s.Peek() >= '0' && s.Peek() <= '9') {
|
||||
exp = exp * 10 + (s.Take() - '0');
|
||||
if (exp > 308) {
|
||||
// Attempt denormalized construction
|
||||
std::stringstream ss;
|
||||
ss.precision( std::numeric_limits<double>::max_digits10 );
|
||||
ss << d * internal::Pow10(expFrac) << 'e' << (expMinus ? '-' : '+') << exp;
|
||||
|
||||
double dd;
|
||||
ss >> dd;
|
||||
|
||||
if( std::fpclassify( dd ) == FP_SUBNORMAL )
|
||||
handler.Double( dd );
|
||||
else
|
||||
RAPIDJSON_PARSE_ERROR("Number too big to store in double", stream.Tell());
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
RAPIDJSON_PARSE_ERROR("At least one digit in exponent", s.Tell());
|
||||
return;
|
||||
}
|
||||
|
||||
if (expMinus)
|
||||
exp = -exp;
|
||||
}
|
||||
|
||||
// Finish parsing, call event according to the type of number.
|
||||
if (useDouble) {
|
||||
d *= internal::Pow10(exp + expFrac);
|
||||
handler.Double(minus ? -d : d);
|
||||
}
|
||||
else {
|
||||
if (try64bit) {
|
||||
if (minus)
|
||||
handler.Int64(-(int64_t)i64);
|
||||
else
|
||||
handler.Uint64(i64);
|
||||
}
|
||||
else {
|
||||
if (minus)
|
||||
handler.Int(-(int)i);
|
||||
else
|
||||
handler.Uint(i);
|
||||
}
|
||||
}
|
||||
|
||||
stream = s; // restore stream
|
||||
}
|
||||
|
||||
// Parse any JSON value
|
||||
template<unsigned parseFlags, typename Stream, typename Handler>
|
||||
void ParseValue(Stream& stream, Handler& handler) {
|
||||
switch (stream.Peek()) {
|
||||
case 'n': ParseNaNNull_ <parseFlags>(stream, handler); break;
|
||||
case 'i': ParseInfinity <parseFlags>(stream, handler); break;
|
||||
case 't': ParseTrue <parseFlags>(stream, handler); break;
|
||||
case 'f': ParseFalse <parseFlags>(stream, handler); break;
|
||||
case '"': ParseString <parseFlags>(stream, handler); break;
|
||||
case '{': ParseObject <parseFlags>(stream, handler); break;
|
||||
case '[': ParseArray <parseFlags>(stream, handler); break;
|
||||
default : ParseNumber <parseFlags>(stream, handler);
|
||||
}
|
||||
}
|
||||
|
||||
static const size_t kDefaultStackCapacity = 256; //!< Default stack capacity in bytes for storing a single decoded string.
|
||||
internal::Stack<Allocator> stack_; //!< A stack for storing decoded string temporarily during non-destructive parsing.
|
||||
jmp_buf jmpbuf_; //!< setjmp buffer for fast exit from nested parsing function calls.
|
||||
const char* parseError_;
|
||||
size_t errorOffset_;
|
||||
}; // class GenericReader
|
||||
|
||||
//! Reader with UTF8 encoding and default allocator.
|
||||
typedef GenericReader<UTF8<> > Reader;
|
||||
|
||||
} // namespace rapidjson
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(pop)
|
||||
#endif
|
||||
|
||||
#endif // RAPIDJSON_READER_H_
|
||||
49
libs/cereal/cereal/external/rapidjson/stringbuffer.h
vendored
Normal file
49
libs/cereal/cereal/external/rapidjson/stringbuffer.h
vendored
Normal file
@ -0,0 +1,49 @@
|
||||
#ifndef RAPIDJSON_STRINGBUFFER_H_
|
||||
#define RAPIDJSON_STRINGBUFFER_H_
|
||||
|
||||
#include "rapidjson.h"
|
||||
#include "internal/stack.h"
|
||||
|
||||
namespace rapidjson {
|
||||
|
||||
//! Represents an in-memory output stream.
|
||||
/*!
|
||||
\tparam Encoding Encoding of the stream.
|
||||
\tparam Allocator type for allocating memory buffer.
|
||||
\implements Stream
|
||||
*/
|
||||
template <typename Encoding, typename Allocator = CrtAllocator>
|
||||
struct GenericStringBuffer {
|
||||
typedef typename Encoding::Ch Ch;
|
||||
|
||||
GenericStringBuffer(Allocator* allocator = 0, size_t capacity = kDefaultCapacity) : stack_(allocator, capacity) {}
|
||||
|
||||
void Put(Ch c) { *stack_.template Push<Ch>() = c; }
|
||||
|
||||
void Clear() { stack_.Clear(); }
|
||||
|
||||
const char* GetString() const {
|
||||
// Push and pop a null terminator. This is safe.
|
||||
*stack_.template Push<Ch>() = '\0';
|
||||
stack_.template Pop<Ch>(1);
|
||||
|
||||
return stack_.template Bottom<Ch>();
|
||||
}
|
||||
|
||||
size_t Size() const { return stack_.GetSize(); }
|
||||
|
||||
static const size_t kDefaultCapacity = 256;
|
||||
mutable internal::Stack<Allocator> stack_;
|
||||
};
|
||||
|
||||
typedef GenericStringBuffer<UTF8<> > StringBuffer;
|
||||
|
||||
//! Implement specialized version of PutN() with memset() for better performance.
|
||||
template<>
|
||||
inline void PutN(GenericStringBuffer<UTF8<> >& stream, char c, size_t n) {
|
||||
memset(stream.stack_.Push<char>(n), c, n * sizeof(c));
|
||||
}
|
||||
|
||||
} // namespace rapidjson
|
||||
|
||||
#endif // RAPIDJSON_STRINGBUFFER_H_
|
||||
330
libs/cereal/cereal/external/rapidjson/writer.h
vendored
Normal file
330
libs/cereal/cereal/external/rapidjson/writer.h
vendored
Normal file
@ -0,0 +1,330 @@
|
||||
#ifndef RAPIDJSON_WRITER_H_
|
||||
#define RAPIDJSON_WRITER_H_
|
||||
|
||||
#include "rapidjson.h"
|
||||
#include "internal/stack.h"
|
||||
#include "internal/strfunc.h"
|
||||
#include <cstdio> // snprintf() or _sprintf_s()
|
||||
#include <new> // placement new
|
||||
#include <limits>
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable : 4127) // conditional expression is constant
|
||||
#endif
|
||||
|
||||
namespace rapidjson {
|
||||
|
||||
//! JSON writer
|
||||
/*! Writer implements the concept Handler.
|
||||
It generates JSON text by events to an output stream.
|
||||
|
||||
User may programmatically calls the functions of a writer to generate JSON text.
|
||||
|
||||
On the other side, a writer can also be passed to objects that generates events,
|
||||
|
||||
for example Reader::Parse() and Document::Accept().
|
||||
|
||||
\tparam Stream Type of ouptut stream.
|
||||
\tparam Encoding Encoding of both source strings and output.
|
||||
\implements Handler
|
||||
*/
|
||||
template<typename Stream, typename Encoding = UTF8<>, typename Allocator = MemoryPoolAllocator<> >
|
||||
class Writer {
|
||||
public:
|
||||
typedef typename Encoding::Ch Ch;
|
||||
|
||||
Writer(Stream& stream, int precision = 20, Allocator* allocator = 0, size_t levelDepth = kDefaultLevelDepth) :
|
||||
stream_(stream), level_stack_(allocator, levelDepth * sizeof(Level))
|
||||
{
|
||||
#if _MSC_VER
|
||||
(void) sprintf_s(double_format, sizeof(double_format), "%%0.%dg", precision);
|
||||
(void) sprintf_s( long_double_format, sizeof( long_double_format ), "%%0.%dLg", precision );
|
||||
#else
|
||||
(void) snprintf(double_format, sizeof(double_format), "%%0.%dg", precision);
|
||||
(void) snprintf( long_double_format, sizeof( long_double_format ), "%%0.%dLg", precision );
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
protected:
|
||||
char double_format[32];
|
||||
char long_double_format[32];
|
||||
public:
|
||||
|
||||
//@name Implementation of Handler
|
||||
//@{
|
||||
|
||||
Writer& Null_() { Prefix(kNull_Type); WriteNull_(); return *this; }
|
||||
Writer& Bool_(bool b) { Prefix(b ? kTrueType : kFalseType); WriteBool_(b); return *this; }
|
||||
Writer& Int(int i) { Prefix(kNumberType); WriteInt(i); return *this; }
|
||||
Writer& Uint(unsigned u) { Prefix(kNumberType); WriteUint(u); return *this; }
|
||||
Writer& Int64(int64_t i64) { Prefix(kNumberType); WriteInt64(i64); return *this; }
|
||||
Writer& Uint64(uint64_t u64) { Prefix(kNumberType); WriteUint64(u64); return *this; }
|
||||
Writer& Double(double d) { Prefix(kNumberType); WriteDouble(d); return *this; }
|
||||
Writer& LongDouble(long double d) { Prefix(kNumberType); WriteLongDouble(d); return *this; }
|
||||
Writer& LongLong(long long d) { Prefix(kNumberType); WriteLongLong(d); return *this; }
|
||||
Writer& ULongLong(unsigned long long d) { Prefix(kNumberType); WriteULongLong(d); return *this; }
|
||||
|
||||
Writer& String(const Ch* str, SizeType length, bool copy = false) {
|
||||
(void)copy;
|
||||
Prefix(kStringType);
|
||||
WriteString(str, length);
|
||||
return *this;
|
||||
}
|
||||
|
||||
Writer& StartObject() {
|
||||
Prefix(kObjectType);
|
||||
new (level_stack_.template Push<Level>()) Level(false);
|
||||
WriteStartObject();
|
||||
return *this;
|
||||
}
|
||||
|
||||
Writer& EndObject(SizeType memberCount = 0) {
|
||||
(void)memberCount;
|
||||
RAPIDJSON_ASSERT(level_stack_.GetSize() >= sizeof(Level));
|
||||
RAPIDJSON_ASSERT(!level_stack_.template Top<Level>()->inArray);
|
||||
level_stack_.template Pop<Level>(1);
|
||||
WriteEndObject();
|
||||
return *this;
|
||||
}
|
||||
|
||||
Writer& StartArray() {
|
||||
Prefix(kArrayType);
|
||||
new (level_stack_.template Push<Level>()) Level(true);
|
||||
WriteStartArray();
|
||||
return *this;
|
||||
}
|
||||
|
||||
Writer& EndArray(SizeType elementCount = 0) {
|
||||
(void)elementCount;
|
||||
RAPIDJSON_ASSERT(level_stack_.GetSize() >= sizeof(Level));
|
||||
RAPIDJSON_ASSERT(level_stack_.template Top<Level>()->inArray);
|
||||
level_stack_.template Pop<Level>(1);
|
||||
WriteEndArray();
|
||||
return *this;
|
||||
}
|
||||
//@}
|
||||
|
||||
//! Simpler but slower overload.
|
||||
Writer& String(const Ch* str) { return String(str, internal::StrLen(str)); }
|
||||
|
||||
protected:
|
||||
//! Information for each nested level
|
||||
struct Level {
|
||||
Level(bool inArray_) : inArray(inArray_), valueCount(0) {}
|
||||
bool inArray; //!< true if in array, otherwise in object
|
||||
size_t valueCount; //!< number of values in this level
|
||||
};
|
||||
|
||||
static const size_t kDefaultLevelDepth = 32;
|
||||
|
||||
void WriteNull_() {
|
||||
stream_.Put('n'); stream_.Put('u'); stream_.Put('l'); stream_.Put('l');
|
||||
}
|
||||
|
||||
void WriteBool_(bool b) {
|
||||
if (b) {
|
||||
stream_.Put('t'); stream_.Put('r'); stream_.Put('u'); stream_.Put('e');
|
||||
}
|
||||
else {
|
||||
stream_.Put('f'); stream_.Put('a'); stream_.Put('l'); stream_.Put('s'); stream_.Put('e');
|
||||
}
|
||||
}
|
||||
|
||||
void WriteInt(int i) {
|
||||
if (i < 0) {
|
||||
stream_.Put('-');
|
||||
i = -i;
|
||||
}
|
||||
WriteUint((unsigned)i);
|
||||
}
|
||||
|
||||
void WriteUint(unsigned u) {
|
||||
char buffer[10];
|
||||
char *p = buffer;
|
||||
do {
|
||||
*p++ = (u % 10) + '0';
|
||||
u /= 10;
|
||||
} while (u > 0);
|
||||
|
||||
do {
|
||||
--p;
|
||||
stream_.Put(*p);
|
||||
} while (p != buffer);
|
||||
}
|
||||
|
||||
void WriteInt64(int64_t i64) {
|
||||
if (i64 < 0) {
|
||||
stream_.Put('-');
|
||||
i64 = -i64;
|
||||
}
|
||||
WriteUint64((uint64_t)i64);
|
||||
}
|
||||
|
||||
void WriteUint64(uint64_t u64) {
|
||||
char buffer[20];
|
||||
char *p = buffer;
|
||||
do {
|
||||
*p++ = char(u64 % 10) + '0';
|
||||
u64 /= 10;
|
||||
} while (u64 > 0);
|
||||
|
||||
do {
|
||||
--p;
|
||||
stream_.Put(*p);
|
||||
} while (p != buffer);
|
||||
}
|
||||
|
||||
// cereal Temporary until constexpr support is added in RTM
|
||||
#ifdef _MSC_VER
|
||||
template <class Ch>
|
||||
bool characterOk( Ch c )
|
||||
{
|
||||
return c < 256;
|
||||
}
|
||||
|
||||
template <>
|
||||
bool characterOk<char>( char )
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
#else
|
||||
// As part of a fix for GCC 4.7
|
||||
template <class T>
|
||||
static constexpr int to_int( T t ){ return t; }
|
||||
|
||||
template<class Ch>
|
||||
typename std::enable_if < to_int(std::numeric_limits<Ch>::max()) < to_int(256), bool>::type
|
||||
characterOk( Ch )
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
template<class Ch>
|
||||
typename std::enable_if< to_int(std::numeric_limits<Ch>::max()) >= to_int(256), bool>::type
|
||||
characterOk(Ch c)
|
||||
{ return c < 256; }
|
||||
#endif
|
||||
|
||||
//! \todo Optimization with custom double-to-string converter.
|
||||
void WriteDouble(double d) {
|
||||
char buffer[100];
|
||||
#if _MSC_VER
|
||||
int ret = sprintf_s(buffer, sizeof(buffer), double_format, d);
|
||||
#else
|
||||
int ret = snprintf(buffer, sizeof(buffer), double_format, d);
|
||||
#endif
|
||||
RAPIDJSON_ASSERT(ret >= 1);
|
||||
for (int i = 0; i < ret; i++)
|
||||
stream_.Put(buffer[i]);
|
||||
}
|
||||
|
||||
void WriteLongDouble(long double d) {
|
||||
char buffer[256];
|
||||
#if _MSC_VER
|
||||
int ret = sprintf_s(buffer, sizeof(buffer), long_double_format, d);
|
||||
#else
|
||||
int ret = snprintf(buffer, sizeof(buffer), long_double_format, d);
|
||||
#endif
|
||||
RAPIDJSON_ASSERT(ret >= 1);
|
||||
for (int i = 0; i < ret; i++)
|
||||
stream_.Put(buffer[i]);
|
||||
}
|
||||
|
||||
void WriteLongLong(long long d) {
|
||||
char buffer[256];
|
||||
#if _MSC_VER
|
||||
int ret = sprintf_s(buffer, sizeof(buffer), "%lld", d);
|
||||
#else
|
||||
int ret = snprintf(buffer, sizeof(buffer), "%lld", d);
|
||||
#endif
|
||||
RAPIDJSON_ASSERT(ret >= 1);
|
||||
for (int i = 0; i < ret; i++)
|
||||
stream_.Put(buffer[i]);
|
||||
}
|
||||
|
||||
void WriteULongLong(unsigned long long d) {
|
||||
char buffer[256];
|
||||
#if _MSC_VER
|
||||
int ret = sprintf_s(buffer, sizeof(buffer), "%llu", d);
|
||||
#else
|
||||
int ret = snprintf(buffer, sizeof(buffer), "%llu", d);
|
||||
#endif
|
||||
RAPIDJSON_ASSERT(ret >= 1);
|
||||
for (int i = 0; i < ret; i++)
|
||||
stream_.Put(buffer[i]);
|
||||
}
|
||||
|
||||
void WriteString(const Ch* str, SizeType length) {
|
||||
static const char hexDigits[] = "0123456789ABCDEF";
|
||||
static const char escape[256] = {
|
||||
#define Z16 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
|
||||
//0 1 2 3 4 5 6 7 8 9 A B C D E F
|
||||
'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'b', 't', 'n', 'u', 'f', 'r', 'u', 'u', // 00
|
||||
'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', // 10
|
||||
0, 0, '"', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 20
|
||||
Z16, Z16, // 30~4F
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,'\\', 0, 0, 0, // 50
|
||||
Z16, Z16, Z16, Z16, Z16, Z16, Z16, Z16, Z16, Z16 // 60~FF
|
||||
#undef Z16
|
||||
};
|
||||
|
||||
stream_.Put('\"');
|
||||
for (const Ch* p = str; p != str + length; ++p) {
|
||||
if ((sizeof(Ch) == 1 || characterOk(*p)) && escape[(unsigned char)*p]) {
|
||||
//if ((sizeof(Ch) == 1 || *p < 256) && escape[(unsigned char)*p]) {
|
||||
stream_.Put('\\');
|
||||
stream_.Put(escape[(unsigned char)*p]);
|
||||
if (escape[(unsigned char)*p] == 'u') {
|
||||
stream_.Put('0');
|
||||
stream_.Put('0');
|
||||
stream_.Put(hexDigits[(*p) >> 4]);
|
||||
stream_.Put(hexDigits[(*p) & 0xF]);
|
||||
}
|
||||
}
|
||||
else
|
||||
stream_.Put(*p);
|
||||
}
|
||||
stream_.Put('\"');
|
||||
}
|
||||
|
||||
void WriteStartObject() { stream_.Put('{'); }
|
||||
void WriteEndObject() { stream_.Put('}'); }
|
||||
void WriteStartArray() { stream_.Put('['); }
|
||||
void WriteEndArray() { stream_.Put(']'); }
|
||||
|
||||
void Prefix(Type type) {
|
||||
(void)type;
|
||||
if (level_stack_.GetSize() != 0) { // this value is not at root
|
||||
Level* level = level_stack_.template Top<Level>();
|
||||
if (level->valueCount > 0) {
|
||||
if (level->inArray)
|
||||
stream_.Put(','); // add comma if it is not the first element in array
|
||||
else // in object
|
||||
stream_.Put((level->valueCount % 2 == 0) ? ',' : ':');
|
||||
}
|
||||
if (!level->inArray && level->valueCount % 2 == 0)
|
||||
RAPIDJSON_ASSERT(type == kStringType); // if it's in object, then even number should be a name
|
||||
level->valueCount++;
|
||||
}
|
||||
else
|
||||
RAPIDJSON_ASSERT(type == kObjectType || type == kArrayType);
|
||||
}
|
||||
|
||||
Stream& stream_;
|
||||
internal::Stack<Allocator> level_stack_;
|
||||
|
||||
private:
|
||||
// Prohibit assignment for VC C4512 warning
|
||||
Writer& operator=(const Writer& w);
|
||||
};
|
||||
|
||||
} // namespace rapidjson
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(pop)
|
||||
#endif
|
||||
|
||||
#endif // RAPIDJSON_RAPIDJSON_H_
|
||||
52
libs/cereal/cereal/external/rapidxml/license.txt
vendored
Normal file
52
libs/cereal/cereal/external/rapidxml/license.txt
vendored
Normal file
@ -0,0 +1,52 @@
|
||||
Use of this software is granted under one of the following two licenses,
|
||||
to be chosen freely by the user.
|
||||
|
||||
1. Boost Software License - Version 1.0 - August 17th, 2003
|
||||
===============================================================================
|
||||
|
||||
Copyright (c) 2006, 2007 Marcin Kalicinski
|
||||
|
||||
Permission is hereby granted, free of charge, to any person or organization
|
||||
obtaining a copy of the software and accompanying documentation covered by
|
||||
this license (the "Software") to use, reproduce, display, distribute,
|
||||
execute, and transmit the Software, and to prepare derivative works of the
|
||||
Software, and to permit third-parties to whom the Software is furnished to
|
||||
do so, all subject to the following:
|
||||
|
||||
The copyright notices in the Software and this entire statement, including
|
||||
the above license grant, this restriction and the following disclaimer,
|
||||
must be included in all copies of the Software, in whole or in part, and
|
||||
all derivative works of the Software, unless such copies or derivative
|
||||
works are solely in the form of machine-executable object code generated by
|
||||
a source language processor.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
|
||||
SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
|
||||
FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
|
||||
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
DEALINGS IN THE SOFTWARE.
|
||||
|
||||
2. The MIT License
|
||||
===============================================================================
|
||||
|
||||
Copyright (c) 2006, 2007 Marcin Kalicinski
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
of the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
IN THE SOFTWARE.
|
||||
406
libs/cereal/cereal/external/rapidxml/manual.html
vendored
Normal file
406
libs/cereal/cereal/external/rapidxml/manual.html
vendored
Normal file
File diff suppressed because one or more lines are too long
2618
libs/cereal/cereal/external/rapidxml/rapidxml.hpp
vendored
Normal file
2618
libs/cereal/cereal/external/rapidxml/rapidxml.hpp
vendored
Normal file
File diff suppressed because it is too large
Load Diff
173
libs/cereal/cereal/external/rapidxml/rapidxml_iterators.hpp
vendored
Normal file
173
libs/cereal/cereal/external/rapidxml/rapidxml_iterators.hpp
vendored
Normal file
@ -0,0 +1,173 @@
|
||||
#ifndef RAPIDXML_ITERATORS_HPP_INCLUDED
|
||||
#define RAPIDXML_ITERATORS_HPP_INCLUDED
|
||||
|
||||
// Copyright (C) 2006, 2009 Marcin Kalicinski
|
||||
// Version 1.13
|
||||
// Revision $DateTime: 2009/05/13 01:46:17 $
|
||||
|
||||
#include "rapidxml.hpp"
|
||||
|
||||
namespace rapidxml
|
||||
{
|
||||
|
||||
//! Iterator of child nodes of xml_node
|
||||
template<class Ch>
|
||||
class node_iterator
|
||||
{
|
||||
|
||||
public:
|
||||
|
||||
typedef typename xml_node<Ch> value_type;
|
||||
typedef typename xml_node<Ch> &reference;
|
||||
typedef typename xml_node<Ch> *pointer;
|
||||
typedef std::ptrdiff_t difference_type;
|
||||
typedef std::bidirectional_iterator_tag iterator_category;
|
||||
|
||||
node_iterator()
|
||||
: m_node(0)
|
||||
{
|
||||
}
|
||||
|
||||
node_iterator(xml_node<Ch> *node)
|
||||
: m_node(node->first_node())
|
||||
{
|
||||
}
|
||||
|
||||
reference operator *() const
|
||||
{
|
||||
assert(m_node);
|
||||
return *m_node;
|
||||
}
|
||||
|
||||
pointer operator->() const
|
||||
{
|
||||
assert(m_node);
|
||||
return m_node;
|
||||
}
|
||||
|
||||
node_iterator& operator++()
|
||||
{
|
||||
assert(m_node);
|
||||
m_node = m_node->next_sibling();
|
||||
return *this;
|
||||
}
|
||||
|
||||
node_iterator operator++(int)
|
||||
{
|
||||
node_iterator tmp = *this;
|
||||
++this;
|
||||
return tmp;
|
||||
}
|
||||
|
||||
node_iterator& operator--()
|
||||
{
|
||||
assert(m_node && m_node->previous_sibling());
|
||||
m_node = m_node->previous_sibling();
|
||||
return *this;
|
||||
}
|
||||
|
||||
node_iterator operator--(int)
|
||||
{
|
||||
node_iterator tmp = *this;
|
||||
++this;
|
||||
return tmp;
|
||||
}
|
||||
|
||||
bool operator ==(const node_iterator<Ch> &rhs)
|
||||
{
|
||||
return m_node == rhs.m_node;
|
||||
}
|
||||
|
||||
bool operator !=(const node_iterator<Ch> &rhs)
|
||||
{
|
||||
return m_node != rhs.m_node;
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
xml_node<Ch> *m_node;
|
||||
|
||||
};
|
||||
|
||||
//! Iterator of child attributes of xml_node
|
||||
template<class Ch>
|
||||
class attribute_iterator
|
||||
{
|
||||
|
||||
public:
|
||||
|
||||
typedef typename xml_attribute<Ch> value_type;
|
||||
typedef typename xml_attribute<Ch> &reference;
|
||||
typedef typename xml_attribute<Ch> *pointer;
|
||||
typedef std::ptrdiff_t difference_type;
|
||||
typedef std::bidirectional_iterator_tag iterator_category;
|
||||
|
||||
attribute_iterator()
|
||||
: m_attribute(0)
|
||||
{
|
||||
}
|
||||
|
||||
attribute_iterator(xml_node<Ch> *node)
|
||||
: m_attribute(node->first_attribute())
|
||||
{
|
||||
}
|
||||
|
||||
reference operator *() const
|
||||
{
|
||||
assert(m_attribute);
|
||||
return *m_attribute;
|
||||
}
|
||||
|
||||
pointer operator->() const
|
||||
{
|
||||
assert(m_attribute);
|
||||
return m_attribute;
|
||||
}
|
||||
|
||||
attribute_iterator& operator++()
|
||||
{
|
||||
assert(m_attribute);
|
||||
m_attribute = m_attribute->next_attribute();
|
||||
return *this;
|
||||
}
|
||||
|
||||
attribute_iterator operator++(int)
|
||||
{
|
||||
attribute_iterator tmp = *this;
|
||||
++this;
|
||||
return tmp;
|
||||
}
|
||||
|
||||
attribute_iterator& operator--()
|
||||
{
|
||||
assert(m_attribute && m_attribute->previous_attribute());
|
||||
m_attribute = m_attribute->previous_attribute();
|
||||
return *this;
|
||||
}
|
||||
|
||||
attribute_iterator operator--(int)
|
||||
{
|
||||
attribute_iterator tmp = *this;
|
||||
++this;
|
||||
return tmp;
|
||||
}
|
||||
|
||||
bool operator ==(const attribute_iterator<Ch> &rhs)
|
||||
{
|
||||
return m_attribute == rhs.m_attribute;
|
||||
}
|
||||
|
||||
bool operator !=(const attribute_iterator<Ch> &rhs)
|
||||
{
|
||||
return m_attribute != rhs.m_attribute;
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
xml_attribute<Ch> *m_attribute;
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
424
libs/cereal/cereal/external/rapidxml/rapidxml_print.hpp
vendored
Normal file
424
libs/cereal/cereal/external/rapidxml/rapidxml_print.hpp
vendored
Normal file
@ -0,0 +1,424 @@
|
||||
#ifndef RAPIDXML_PRINT_HPP_INCLUDED
|
||||
#define RAPIDXML_PRINT_HPP_INCLUDED
|
||||
|
||||
// Copyright (C) 2006, 2009 Marcin Kalicinski
|
||||
// Version 1.13
|
||||
// Revision $DateTime: 2009/05/13 01:46:17 $
|
||||
|
||||
#include "rapidxml.hpp"
|
||||
|
||||
// Only include streams if not disabled
|
||||
#ifndef RAPIDXML_NO_STREAMS
|
||||
#include <ostream>
|
||||
#include <iterator>
|
||||
#endif
|
||||
|
||||
namespace rapidxml
|
||||
{
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
// Printing flags
|
||||
|
||||
const int print_no_indenting = 0x1; //!< Printer flag instructing the printer to suppress indenting of XML. See print() function.
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
// Internal
|
||||
|
||||
//! \cond internal
|
||||
namespace internal
|
||||
{
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// Internal character operations
|
||||
|
||||
// Copy characters from given range to given output iterator
|
||||
template<class OutIt, class Ch>
|
||||
inline OutIt copy_chars(const Ch *begin, const Ch *end, OutIt out)
|
||||
{
|
||||
while (begin != end)
|
||||
*out++ = *begin++;
|
||||
return out;
|
||||
}
|
||||
|
||||
// Copy characters from given range to given output iterator and expand
|
||||
// characters into references (< > ' " &)
|
||||
template<class OutIt, class Ch>
|
||||
inline OutIt copy_and_expand_chars(const Ch *begin, const Ch *end, Ch noexpand, OutIt out)
|
||||
{
|
||||
while (begin != end)
|
||||
{
|
||||
if (*begin == noexpand)
|
||||
{
|
||||
*out++ = *begin; // No expansion, copy character
|
||||
}
|
||||
else
|
||||
{
|
||||
switch (*begin)
|
||||
{
|
||||
case Ch('<'):
|
||||
*out++ = Ch('&'); *out++ = Ch('l'); *out++ = Ch('t'); *out++ = Ch(';');
|
||||
break;
|
||||
case Ch('>'):
|
||||
*out++ = Ch('&'); *out++ = Ch('g'); *out++ = Ch('t'); *out++ = Ch(';');
|
||||
break;
|
||||
case Ch('\''):
|
||||
*out++ = Ch('&'); *out++ = Ch('a'); *out++ = Ch('p'); *out++ = Ch('o'); *out++ = Ch('s'); *out++ = Ch(';');
|
||||
break;
|
||||
case Ch('"'):
|
||||
*out++ = Ch('&'); *out++ = Ch('q'); *out++ = Ch('u'); *out++ = Ch('o'); *out++ = Ch('t'); *out++ = Ch(';');
|
||||
break;
|
||||
case Ch('&'):
|
||||
*out++ = Ch('&'); *out++ = Ch('a'); *out++ = Ch('m'); *out++ = Ch('p'); *out++ = Ch(';');
|
||||
break;
|
||||
default:
|
||||
*out++ = *begin; // No expansion, copy character
|
||||
}
|
||||
}
|
||||
++begin; // Step to next character
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
// Fill given output iterator with repetitions of the same character
|
||||
template<class OutIt, class Ch>
|
||||
inline OutIt fill_chars(OutIt out, int n, Ch ch)
|
||||
{
|
||||
for (int i = 0; i < n; ++i)
|
||||
*out++ = ch;
|
||||
return out;
|
||||
}
|
||||
|
||||
// Find character
|
||||
template<class Ch, Ch ch>
|
||||
inline bool find_char(const Ch *begin, const Ch *end)
|
||||
{
|
||||
while (begin != end)
|
||||
if (*begin++ == ch)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// Internal printing operations
|
||||
|
||||
// Print node
|
||||
template<class OutIt, class Ch>
|
||||
inline OutIt print_node(OutIt out, const xml_node<Ch> *node, int flags, int indent);
|
||||
|
||||
// Print children of the node
|
||||
template<class OutIt, class Ch>
|
||||
inline OutIt print_children(OutIt out, const xml_node<Ch> *node, int flags, int indent)
|
||||
{
|
||||
for (xml_node<Ch> *child = node->first_node(); child; child = child->next_sibling())
|
||||
out = print_node(out, child, flags, indent);
|
||||
return out;
|
||||
}
|
||||
|
||||
// Print attributes of the node
|
||||
template<class OutIt, class Ch>
|
||||
inline OutIt print_attributes(OutIt out, const xml_node<Ch> *node, int /*flags*/)
|
||||
{
|
||||
for (xml_attribute<Ch> *attribute = node->first_attribute(); attribute; attribute = attribute->next_attribute())
|
||||
{
|
||||
if (attribute->name() && attribute->value())
|
||||
{
|
||||
// Print attribute name
|
||||
*out = Ch(' '), ++out;
|
||||
out = copy_chars(attribute->name(), attribute->name() + attribute->name_size(), out);
|
||||
*out = Ch('='), ++out;
|
||||
// Print attribute value using appropriate quote type
|
||||
if (find_char<Ch, Ch('"')>(attribute->value(), attribute->value() + attribute->value_size()))
|
||||
{
|
||||
*out = Ch('\''), ++out;
|
||||
out = copy_and_expand_chars(attribute->value(), attribute->value() + attribute->value_size(), Ch('"'), out);
|
||||
*out = Ch('\''), ++out;
|
||||
}
|
||||
else
|
||||
{
|
||||
*out = Ch('"'), ++out;
|
||||
out = copy_and_expand_chars(attribute->value(), attribute->value() + attribute->value_size(), Ch('\''), out);
|
||||
*out = Ch('"'), ++out;
|
||||
}
|
||||
}
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
// Print data node
|
||||
template<class OutIt, class Ch>
|
||||
inline OutIt print_data_node(OutIt out, const xml_node<Ch> *node, int flags, int indent)
|
||||
{
|
||||
assert(node->type() == node_data);
|
||||
if (!(flags & print_no_indenting))
|
||||
out = fill_chars(out, indent, Ch('\t'));
|
||||
out = copy_and_expand_chars(node->value(), node->value() + node->value_size(), Ch(0), out);
|
||||
return out;
|
||||
}
|
||||
|
||||
// Print data node
|
||||
template<class OutIt, class Ch>
|
||||
inline OutIt print_cdata_node(OutIt out, const xml_node<Ch> *node, int flags, int indent)
|
||||
{
|
||||
assert(node->type() == node_cdata);
|
||||
if (!(flags & print_no_indenting))
|
||||
out = fill_chars(out, indent, Ch('\t'));
|
||||
*out = Ch('<'); ++out;
|
||||
*out = Ch('!'); ++out;
|
||||
*out = Ch('['); ++out;
|
||||
*out = Ch('C'); ++out;
|
||||
*out = Ch('D'); ++out;
|
||||
*out = Ch('A'); ++out;
|
||||
*out = Ch('T'); ++out;
|
||||
*out = Ch('A'); ++out;
|
||||
*out = Ch('['); ++out;
|
||||
out = copy_chars(node->value(), node->value() + node->value_size(), out);
|
||||
*out = Ch(']'); ++out;
|
||||
*out = Ch(']'); ++out;
|
||||
*out = Ch('>'); ++out;
|
||||
return out;
|
||||
}
|
||||
|
||||
// Print element node
|
||||
template<class OutIt, class Ch>
|
||||
inline OutIt print_element_node(OutIt out, const xml_node<Ch> *node, int flags, int indent)
|
||||
{
|
||||
assert(node->type() == node_element);
|
||||
|
||||
// Print element name and attributes, if any
|
||||
if (!(flags & print_no_indenting))
|
||||
out = fill_chars(out, indent, Ch('\t'));
|
||||
*out = Ch('<'), ++out;
|
||||
out = copy_chars(node->name(), node->name() + node->name_size(), out);
|
||||
out = print_attributes(out, node, flags);
|
||||
|
||||
// If node is childless
|
||||
if (node->value_size() == 0 && !node->first_node())
|
||||
{
|
||||
// Print childless node tag ending
|
||||
*out = Ch('/'), ++out;
|
||||
*out = Ch('>'), ++out;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Print normal node tag ending
|
||||
*out = Ch('>'), ++out;
|
||||
|
||||
// Test if node contains a single data node only (and no other nodes)
|
||||
xml_node<Ch> *child = node->first_node();
|
||||
if (!child)
|
||||
{
|
||||
// If node has no children, only print its value without indenting
|
||||
out = copy_and_expand_chars(node->value(), node->value() + node->value_size(), Ch(0), out);
|
||||
}
|
||||
else if (child->next_sibling() == 0 && child->type() == node_data)
|
||||
{
|
||||
// If node has a sole data child, only print its value without indenting
|
||||
out = copy_and_expand_chars(child->value(), child->value() + child->value_size(), Ch(0), out);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Print all children with full indenting
|
||||
if (!(flags & print_no_indenting))
|
||||
*out = Ch('\n'), ++out;
|
||||
out = print_children(out, node, flags, indent + 1);
|
||||
if (!(flags & print_no_indenting))
|
||||
out = fill_chars(out, indent, Ch('\t'));
|
||||
}
|
||||
|
||||
// Print node end
|
||||
*out = Ch('<'), ++out;
|
||||
*out = Ch('/'), ++out;
|
||||
out = copy_chars(node->name(), node->name() + node->name_size(), out);
|
||||
*out = Ch('>'), ++out;
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
// Print declaration node
|
||||
template<class OutIt, class Ch>
|
||||
inline OutIt print_declaration_node(OutIt out, const xml_node<Ch> *node, int flags, int indent)
|
||||
{
|
||||
// Print declaration start
|
||||
if (!(flags & print_no_indenting))
|
||||
out = fill_chars(out, indent, Ch('\t'));
|
||||
*out = Ch('<'), ++out;
|
||||
*out = Ch('?'), ++out;
|
||||
*out = Ch('x'), ++out;
|
||||
*out = Ch('m'), ++out;
|
||||
*out = Ch('l'), ++out;
|
||||
|
||||
// Print attributes
|
||||
out = print_attributes(out, node, flags);
|
||||
|
||||
// Print declaration end
|
||||
*out = Ch('?'), ++out;
|
||||
*out = Ch('>'), ++out;
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
// Print comment node
|
||||
template<class OutIt, class Ch>
|
||||
inline OutIt print_comment_node(OutIt out, const xml_node<Ch> *node, int flags, int indent)
|
||||
{
|
||||
assert(node->type() == node_comment);
|
||||
if (!(flags & print_no_indenting))
|
||||
out = fill_chars(out, indent, Ch('\t'));
|
||||
*out = Ch('<'), ++out;
|
||||
*out = Ch('!'), ++out;
|
||||
*out = Ch('-'), ++out;
|
||||
*out = Ch('-'), ++out;
|
||||
out = copy_chars(node->value(), node->value() + node->value_size(), out);
|
||||
*out = Ch('-'), ++out;
|
||||
*out = Ch('-'), ++out;
|
||||
*out = Ch('>'), ++out;
|
||||
return out;
|
||||
}
|
||||
|
||||
// Print doctype node
|
||||
template<class OutIt, class Ch>
|
||||
inline OutIt print_doctype_node(OutIt out, const xml_node<Ch> *node, int flags, int indent)
|
||||
{
|
||||
assert(node->type() == node_doctype);
|
||||
if (!(flags & print_no_indenting))
|
||||
out = fill_chars(out, indent, Ch('\t'));
|
||||
*out = Ch('<'), ++out;
|
||||
*out = Ch('!'), ++out;
|
||||
*out = Ch('D'), ++out;
|
||||
*out = Ch('O'), ++out;
|
||||
*out = Ch('C'), ++out;
|
||||
*out = Ch('T'), ++out;
|
||||
*out = Ch('Y'), ++out;
|
||||
*out = Ch('P'), ++out;
|
||||
*out = Ch('E'), ++out;
|
||||
*out = Ch(' '), ++out;
|
||||
out = copy_chars(node->value(), node->value() + node->value_size(), out);
|
||||
*out = Ch('>'), ++out;
|
||||
return out;
|
||||
}
|
||||
|
||||
// Print pi node
|
||||
template<class OutIt, class Ch>
|
||||
inline OutIt print_pi_node(OutIt out, const xml_node<Ch> *node, int flags, int indent)
|
||||
{
|
||||
assert(node->type() == node_pi);
|
||||
if (!(flags & print_no_indenting))
|
||||
out = fill_chars(out, indent, Ch('\t'));
|
||||
*out = Ch('<'), ++out;
|
||||
*out = Ch('?'), ++out;
|
||||
out = copy_chars(node->name(), node->name() + node->name_size(), out);
|
||||
*out = Ch(' '), ++out;
|
||||
out = copy_chars(node->value(), node->value() + node->value_size(), out);
|
||||
*out = Ch('?'), ++out;
|
||||
*out = Ch('>'), ++out;
|
||||
return out;
|
||||
}
|
||||
|
||||
// Print node
|
||||
template<class OutIt, class Ch>
|
||||
inline OutIt print_node(OutIt out, const xml_node<Ch> *node, int flags, int indent)
|
||||
{
|
||||
// Print proper node type
|
||||
switch (node->type())
|
||||
{
|
||||
|
||||
// Document
|
||||
case node_document:
|
||||
out = print_children(out, node, flags, indent);
|
||||
break;
|
||||
|
||||
// Element
|
||||
case node_element:
|
||||
out = print_element_node(out, node, flags, indent);
|
||||
break;
|
||||
|
||||
// Data
|
||||
case node_data:
|
||||
out = print_data_node(out, node, flags, indent);
|
||||
break;
|
||||
|
||||
// CDATA
|
||||
case node_cdata:
|
||||
out = print_cdata_node(out, node, flags, indent);
|
||||
break;
|
||||
|
||||
// Declaration
|
||||
case node_declaration:
|
||||
out = print_declaration_node(out, node, flags, indent);
|
||||
break;
|
||||
|
||||
// Comment
|
||||
case node_comment:
|
||||
out = print_comment_node(out, node, flags, indent);
|
||||
break;
|
||||
|
||||
// Doctype
|
||||
case node_doctype:
|
||||
out = print_doctype_node(out, node, flags, indent);
|
||||
break;
|
||||
|
||||
// Pi
|
||||
case node_pi:
|
||||
out = print_pi_node(out, node, flags, indent);
|
||||
break;
|
||||
|
||||
// Unknown
|
||||
default:
|
||||
assert(0);
|
||||
break;
|
||||
}
|
||||
|
||||
// If indenting not disabled, add line break after node
|
||||
if (!(flags & print_no_indenting))
|
||||
*out = Ch('\n'), ++out;
|
||||
|
||||
// Return modified iterator
|
||||
return out;
|
||||
}
|
||||
|
||||
}
|
||||
//! \endcond
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// Printing
|
||||
|
||||
//! Prints XML to given output iterator.
|
||||
//! \param out Output iterator to print to.
|
||||
//! \param node Node to be printed. Pass xml_document to print entire document.
|
||||
//! \param flags Flags controlling how XML is printed.
|
||||
//! \return Output iterator pointing to position immediately after last character of printed text.
|
||||
template<class OutIt, class Ch>
|
||||
inline OutIt print(OutIt out, const xml_node<Ch> &node, int flags = 0)
|
||||
{
|
||||
return internal::print_node(out, &node, flags, 0);
|
||||
}
|
||||
|
||||
#ifndef RAPIDXML_NO_STREAMS
|
||||
|
||||
//! Prints XML to given output stream.
|
||||
//! \param out Output stream to print to.
|
||||
//! \param node Node to be printed. Pass xml_document to print entire document.
|
||||
//! \param flags Flags controlling how XML is printed.
|
||||
//! \return Output stream.
|
||||
template<class Ch>
|
||||
inline std::basic_ostream<Ch> &print(std::basic_ostream<Ch> &out, const xml_node<Ch> &node, int flags = 0)
|
||||
{
|
||||
print(std::ostream_iterator<Ch>(out), node, flags);
|
||||
return out;
|
||||
}
|
||||
|
||||
//! Prints formatted XML to given output stream. Uses default printing flags. Use print() function to customize printing process.
|
||||
//! \param out Output stream to print to.
|
||||
//! \param node Node to be printed.
|
||||
//! \return Output stream.
|
||||
template<class Ch>
|
||||
inline std::basic_ostream<Ch> &operator <<(std::basic_ostream<Ch> &out, const xml_node<Ch> &node)
|
||||
{
|
||||
return print(out, node);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
121
libs/cereal/cereal/external/rapidxml/rapidxml_utils.hpp
vendored
Normal file
121
libs/cereal/cereal/external/rapidxml/rapidxml_utils.hpp
vendored
Normal file
@ -0,0 +1,121 @@
|
||||
#ifndef RAPIDXML_UTILS_HPP_INCLUDED
|
||||
#define RAPIDXML_UTILS_HPP_INCLUDED
|
||||
|
||||
// Copyright (C) 2006, 2009 Marcin Kalicinski
|
||||
// Version 1.13
|
||||
// Revision $DateTime: 2009/05/13 01:46:17 $
|
||||
//! in certain simple scenarios. They should probably not be used if maximizing performance is the main objective.
|
||||
|
||||
#include "rapidxml.hpp"
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include <fstream>
|
||||
#include <stdexcept>
|
||||
|
||||
namespace rapidxml
|
||||
{
|
||||
|
||||
//! Represents data loaded from a file
|
||||
template<class Ch = char>
|
||||
class file
|
||||
{
|
||||
|
||||
public:
|
||||
|
||||
//! Loads file into the memory. Data will be automatically destroyed by the destructor.
|
||||
//! \param filename Filename to load.
|
||||
file(const char *filename)
|
||||
{
|
||||
using namespace std;
|
||||
|
||||
// Open stream
|
||||
basic_ifstream<Ch> stream(filename, ios::binary);
|
||||
if (!stream)
|
||||
throw runtime_error(string("cannot open file ") + filename);
|
||||
stream.unsetf(ios::skipws);
|
||||
|
||||
// Determine stream size
|
||||
stream.seekg(0, ios::end);
|
||||
size_t size = stream.tellg();
|
||||
stream.seekg(0);
|
||||
|
||||
// Load data and add terminating 0
|
||||
m_data.resize(size + 1);
|
||||
stream.read(&m_data.front(), static_cast<streamsize>(size));
|
||||
m_data[size] = 0;
|
||||
}
|
||||
|
||||
//! Loads file into the memory. Data will be automatically destroyed by the destructor
|
||||
//! \param stream Stream to load from
|
||||
file(std::basic_istream<Ch> &stream)
|
||||
{
|
||||
using namespace std;
|
||||
|
||||
// Load data and add terminating 0
|
||||
stream.unsetf(ios::skipws);
|
||||
m_data.assign(istreambuf_iterator<Ch>(stream), istreambuf_iterator<Ch>());
|
||||
if (stream.fail() || stream.bad())
|
||||
throw runtime_error("error reading stream");
|
||||
m_data.push_back(0);
|
||||
}
|
||||
|
||||
//! Gets file data.
|
||||
//! \return Pointer to data of file.
|
||||
Ch *data()
|
||||
{
|
||||
return &m_data.front();
|
||||
}
|
||||
|
||||
//! Gets file data.
|
||||
//! \return Pointer to data of file.
|
||||
const Ch *data() const
|
||||
{
|
||||
return &m_data.front();
|
||||
}
|
||||
|
||||
//! Gets file data size.
|
||||
//! \return Size of file data, in characters.
|
||||
std::size_t size() const
|
||||
{
|
||||
return m_data.size();
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
std::vector<Ch> m_data; // File data
|
||||
|
||||
};
|
||||
|
||||
//! Counts children of node. Time complexity is O(n).
|
||||
//! \return Number of children of node
|
||||
template<class Ch>
|
||||
inline std::size_t count_children(xml_node<Ch> *node)
|
||||
{
|
||||
xml_node<Ch> *child = node->first_node();
|
||||
std::size_t count = 0;
|
||||
while (child)
|
||||
{
|
||||
++count;
|
||||
child = child->next_sibling();
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
//! Counts attributes of node. Time complexity is O(n).
|
||||
//! \return Number of attributes of node
|
||||
template<class Ch>
|
||||
inline std::size_t count_attributes(xml_node<Ch> *node)
|
||||
{
|
||||
xml_attribute<Ch> *attr = node->first_attribute();
|
||||
std::size_t count = 0;
|
||||
while (attr)
|
||||
{
|
||||
++count;
|
||||
attr = attr->next_attribute();
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
82
libs/cereal/cereal/macros.hpp
Normal file
82
libs/cereal/cereal/macros.hpp
Normal file
@ -0,0 +1,82 @@
|
||||
/*! \file macros.hpp
|
||||
\brief Preprocessor macros that can customise the cereal library
|
||||
|
||||
By default, cereal looks for serialization functions with very
|
||||
specific names, that is: serialize, load, save, load_minimal,
|
||||
or save_minimal.
|
||||
|
||||
This file allows an advanced user to change these names to conform
|
||||
to some other style or preference. This is implemented using
|
||||
preprocessor macros.
|
||||
|
||||
As a result of this, in internal cereal code you will see macros
|
||||
used for these function names. In user code, you should name
|
||||
the functions like you normally would and not use the macros
|
||||
to improve readability.
|
||||
\ingroup utility */
|
||||
/*
|
||||
Copyright (c) 2014, Randolph Voorhies, Shane Grant
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of cereal nor the
|
||||
names of its contributors may be used to endorse or promote products
|
||||
derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL RANDOLPH VOORHIES OR SHANE GRANT BE LIABLE FOR ANY
|
||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef CEREAL_MACROS_HPP_
|
||||
#define CEREAL_MACROS_HPP_
|
||||
|
||||
#ifndef CEREAL_SERIALIZE_FUNCTION_NAME
|
||||
//! The serialization/deserialization function name to search for.
|
||||
/*! You can define @c CEREAL_SERIALIZE_FUNCTION_NAME to be different assuming
|
||||
you do so before this file is included. */
|
||||
#define CEREAL_SERIALIZE_FUNCTION_NAME serialize
|
||||
#endif // CEREAL_SERIALIZE_FUNCTION_NAME
|
||||
|
||||
#ifndef CEREAL_LOAD_FUNCTION_NAME
|
||||
//! The deserialization (load) function name to search for.
|
||||
/*! You can define @c CEREAL_LOAD_FUNCTION_NAME to be different assuming you do so
|
||||
before this file is included. */
|
||||
#define CEREAL_LOAD_FUNCTION_NAME load
|
||||
#endif // CEREAL_LOAD_FUNCTION_NAME
|
||||
|
||||
#ifndef CEREAL_SAVE_FUNCTION_NAME
|
||||
//! The serialization (save) function name to search for.
|
||||
/*! You can define @c CEREAL_SAVE_FUNCTION_NAME to be different assuming you do so
|
||||
before this file is included. */
|
||||
#define CEREAL_SAVE_FUNCTION_NAME save
|
||||
#endif // CEREAL_SAVE_FUNCTION_NAME
|
||||
|
||||
#ifndef CEREAL_LOAD_MINIMAL_FUNCTION_NAME
|
||||
//! The deserialization (load_minimal) function name to search for.
|
||||
/*! You can define @c CEREAL_LOAD_MINIMAL_FUNCTION_NAME to be different assuming you do so
|
||||
before this file is included. */
|
||||
#define CEREAL_LOAD_MINIMAL_FUNCTION_NAME load_minimal
|
||||
#endif // CEREAL_LOAD_MINIMAL_FUNCTION_NAME
|
||||
|
||||
#ifndef CEREAL_SAVE_MINIMAL_FUNCTION_NAME
|
||||
//! The serialization (save_minimal) function name to search for.
|
||||
/*! You can define @c CEREAL_SAVE_MINIMAL_FUNCTION_NAME to be different assuming you do so
|
||||
before this file is included. */
|
||||
#define CEREAL_SAVE_MINIMAL_FUNCTION_NAME save_minimal
|
||||
#endif // CEREAL_SAVE_MINIMAL_FUNCTION_NAME
|
||||
|
||||
#endif // CEREAL_MACROS_HPP_
|
||||
79
libs/cereal/cereal/types/array.hpp
Normal file
79
libs/cereal/cereal/types/array.hpp
Normal file
@ -0,0 +1,79 @@
|
||||
/*! \file array.hpp
|
||||
\brief Support for types found in \<array\>
|
||||
\ingroup STLSupport */
|
||||
/*
|
||||
Copyright (c) 2014, Randolph Voorhies, Shane Grant
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of cereal nor the
|
||||
names of its contributors may be used to endorse or promote products
|
||||
derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL RANDOLPH VOORHIES OR SHANE GRANT BE LIABLE FOR ANY
|
||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
#ifndef CEREAL_TYPES_ARRAY_HPP_
|
||||
#define CEREAL_TYPES_ARRAY_HPP_
|
||||
|
||||
#include <cereal/cereal.hpp>
|
||||
#include <array>
|
||||
|
||||
namespace cereal
|
||||
{
|
||||
//! Saving for std::array primitive types
|
||||
//! using binary serialization, if supported
|
||||
template <class Archive, class T, size_t N> inline
|
||||
typename std::enable_if<traits::is_output_serializable<BinaryData<T>, Archive>::value
|
||||
&& std::is_arithmetic<T>::value, void>::type
|
||||
CEREAL_SAVE_FUNCTION_NAME( Archive & ar, std::array<T, N> const & array )
|
||||
{
|
||||
ar( binary_data( array.data(), sizeof(array) ) );
|
||||
}
|
||||
|
||||
//! Loading for std::array primitive types
|
||||
//! using binary serialization, if supported
|
||||
template <class Archive, class T, size_t N> inline
|
||||
typename std::enable_if<traits::is_input_serializable<BinaryData<T>, Archive>::value
|
||||
&& std::is_arithmetic<T>::value, void>::type
|
||||
CEREAL_LOAD_FUNCTION_NAME( Archive & ar, std::array<T, N> & array )
|
||||
{
|
||||
ar( binary_data( array.data(), sizeof(array) ) );
|
||||
}
|
||||
|
||||
//! Saving for std::array all other types
|
||||
template <class Archive, class T, size_t N> inline
|
||||
typename std::enable_if<!traits::is_output_serializable<BinaryData<T>, Archive>::value
|
||||
|| !std::is_arithmetic<T>::value, void>::type
|
||||
CEREAL_SAVE_FUNCTION_NAME( Archive & ar, std::array<T, N> const & array )
|
||||
{
|
||||
for( auto const & i : array )
|
||||
ar( i );
|
||||
}
|
||||
|
||||
//! Loading for std::array all other types
|
||||
template <class Archive, class T, size_t N> inline
|
||||
typename std::enable_if<!traits::is_input_serializable<BinaryData<T>, Archive>::value
|
||||
|| !std::is_arithmetic<T>::value, void>::type
|
||||
CEREAL_LOAD_FUNCTION_NAME( Archive & ar, std::array<T, N> & array )
|
||||
{
|
||||
for( auto & i : array )
|
||||
ar( i );
|
||||
}
|
||||
} // namespace cereal
|
||||
|
||||
#endif // CEREAL_TYPES_ARRAY_HPP_
|
||||
164
libs/cereal/cereal/types/base_class.hpp
Normal file
164
libs/cereal/cereal/types/base_class.hpp
Normal file
@ -0,0 +1,164 @@
|
||||
/*! \file base_class.hpp
|
||||
\brief Support for base classes (virtual and non-virtual)
|
||||
\ingroup OtherTypes */
|
||||
/*
|
||||
Copyright (c) 2014, Randolph Voorhies, Shane Grant
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of cereal nor the
|
||||
names of its contributors may be used to endorse or promote products
|
||||
derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL RANDOLPH VOORHIES OR SHANE GRANT BE LIABLE FOR ANY
|
||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
#ifndef CEREAL_TYPES_BASE_CLASS_HPP_
|
||||
#define CEREAL_TYPES_BASE_CLASS_HPP_
|
||||
|
||||
#include <cereal/details/traits.hpp>
|
||||
|
||||
namespace cereal
|
||||
{
|
||||
//! Casts a derived class to its non-virtual base class in a way that safely supports abstract classes
|
||||
/*! This should be used in cases when a derived type needs to serialize its base type. This is better than directly
|
||||
using static_cast, as it allows for serialization of pure virtual (abstract) base classes.
|
||||
|
||||
\sa virtual_base_class
|
||||
|
||||
@code{.cpp}
|
||||
struct MyBase
|
||||
{
|
||||
int x;
|
||||
|
||||
virtual void foo() = 0;
|
||||
|
||||
template <class Archive>
|
||||
void serialize( Archive & ar )
|
||||
{
|
||||
ar( x );
|
||||
}
|
||||
};
|
||||
|
||||
struct MyDerived : public MyBase //<-- Note non-virtual inheritance
|
||||
{
|
||||
int y;
|
||||
|
||||
virtual void foo() {};
|
||||
|
||||
template <class Archive>
|
||||
void serialize( Archive & ar )
|
||||
{
|
||||
ar( cereal::base_class<MyBase>(this) );
|
||||
ar( y );
|
||||
}
|
||||
};
|
||||
@endcode */
|
||||
template<class Base>
|
||||
struct base_class : private traits::detail::BaseCastBase
|
||||
{
|
||||
template<class Derived>
|
||||
base_class(Derived const * derived) :
|
||||
base_ptr(const_cast<Base*>(static_cast<Base const *>(derived)))
|
||||
{ static_assert( std::is_base_of<Base, Derived>::value, "Can only use base_class on a valid base class" ); }
|
||||
|
||||
Base * base_ptr;
|
||||
};
|
||||
|
||||
//! Casts a derived class to its virtual base class in a way that allows cereal to track inheritance
|
||||
/*! This should be used in cases when a derived type features virtual inheritance from some
|
||||
base type. This allows cereal to track the inheritance and to avoid making duplicate copies
|
||||
during serialization.
|
||||
|
||||
It is safe to use virtual_base_class in all circumstances for serializing base classes, even in cases
|
||||
where virtual inheritance does not take place, though it may be slightly faster to utilize
|
||||
cereal::base_class<> if you do not need to worry about virtual inheritance.
|
||||
|
||||
\sa base_class
|
||||
|
||||
@code{.cpp}
|
||||
struct MyBase
|
||||
{
|
||||
int x;
|
||||
|
||||
template <class Archive>
|
||||
void serialize( Archive & ar )
|
||||
{
|
||||
ar( x );
|
||||
}
|
||||
};
|
||||
|
||||
struct MyLeft : virtual MyBase //<-- Note the virtual inheritance
|
||||
{
|
||||
int y;
|
||||
|
||||
template <class Archive>
|
||||
void serialize( Archive & ar )
|
||||
{
|
||||
ar( cereal::virtual_base_class<MyBase>( this ) );
|
||||
ar( y );
|
||||
}
|
||||
};
|
||||
|
||||
struct MyRight : virtual MyBase
|
||||
{
|
||||
int z;
|
||||
|
||||
template <class Archive>
|
||||
void serialize( Archive & ar )
|
||||
{
|
||||
ar( cereal::virtual_base_clas<MyBase>( this ) );
|
||||
ar( z );
|
||||
}
|
||||
};
|
||||
|
||||
// diamond virtual inheritance; contains one copy of each base class
|
||||
struct MyDerived : virtual MyLeft, virtual MyRight
|
||||
{
|
||||
int a;
|
||||
|
||||
template <class Archive>
|
||||
void serialize( Archive & ar )
|
||||
{
|
||||
ar( cereal::virtual_base_class<MyLeft>( this ) ); // safely serialize data members in MyLeft
|
||||
ar( cereal::virtual_base_class<MyRight>( this ) ); // safely serialize data members in MyRight
|
||||
ar( a );
|
||||
|
||||
// Because we used virtual_base_class, cereal will ensure that only one instance of MyBase is
|
||||
// serialized as we traverse the inheritance heirarchy. This means that there will be one copy
|
||||
// each of the variables x, y, z, and a
|
||||
|
||||
// If we had chosen to use static_cast<> instead, cereal would perform no tracking and
|
||||
// assume that every base class should be serialized (in this case leading to a duplicate
|
||||
// serialization of MyBase due to diamond inheritance
|
||||
};
|
||||
}
|
||||
@endcode */
|
||||
template<class Base>
|
||||
struct virtual_base_class : private traits::detail::BaseCastBase
|
||||
{
|
||||
template<class Derived>
|
||||
virtual_base_class(Derived const * derived) :
|
||||
base_ptr(const_cast<Base*>(static_cast<Base const *>(derived)))
|
||||
{ static_assert( std::is_base_of<Base, Derived>::value, "Can only use base_class on a valid base class" ); }
|
||||
|
||||
Base * base_ptr;
|
||||
};
|
||||
|
||||
} // namespace cereal
|
||||
|
||||
#endif // CEREAL_TYPES_BASE_CLASS_HPP_
|
||||
112
libs/cereal/cereal/types/bitset.hpp
Normal file
112
libs/cereal/cereal/types/bitset.hpp
Normal file
@ -0,0 +1,112 @@
|
||||
/*! \file bitset.hpp
|
||||
\brief Support for types found in \<bitset\>
|
||||
\ingroup STLSupport */
|
||||
/*
|
||||
Copyright (c) 2014, Randolph Voorhies, Shane Grant
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of cereal nor the
|
||||
names of its contributors may be used to endorse or promote products
|
||||
derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL RANDOLPH VOORHIES OR SHANE GRANT BE LIABLE FOR ANY
|
||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
#ifndef CEREAL_TYPES_BITSET_HPP_
|
||||
#define CEREAL_TYPES_BITSET_HPP_
|
||||
|
||||
#include <cereal/cereal.hpp>
|
||||
#include <bitset>
|
||||
|
||||
namespace cereal
|
||||
{
|
||||
namespace bitset_detail
|
||||
{
|
||||
//! The type the bitset is encoded with
|
||||
/*! @internal */
|
||||
enum class type : uint8_t
|
||||
{
|
||||
ulong,
|
||||
ullong,
|
||||
string
|
||||
};
|
||||
}
|
||||
|
||||
//! Serializing (save) for std::bitset
|
||||
template <class Archive, size_t N> inline
|
||||
void CEREAL_SAVE_FUNCTION_NAME( Archive & ar, std::bitset<N> const & bits )
|
||||
{
|
||||
try
|
||||
{
|
||||
auto const b = bits.to_ulong();
|
||||
ar( CEREAL_NVP_("type", bitset_detail::type::ulong) );
|
||||
ar( CEREAL_NVP_("data", b) );
|
||||
}
|
||||
catch( std::overflow_error const & )
|
||||
{
|
||||
try
|
||||
{
|
||||
auto const b = bits.to_ullong();
|
||||
ar( CEREAL_NVP_("type", bitset_detail::type::ullong) );
|
||||
ar( CEREAL_NVP_("data", b) );
|
||||
}
|
||||
catch( std::overflow_error const & )
|
||||
{
|
||||
ar( CEREAL_NVP_("type", bitset_detail::type::string) );
|
||||
ar( CEREAL_NVP_("data", bits.to_string()) );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//! Serializing (load) for std::bitset
|
||||
template <class Archive, size_t N> inline
|
||||
void CEREAL_LOAD_FUNCTION_NAME( Archive & ar, std::bitset<N> & bits )
|
||||
{
|
||||
bitset_detail::type t;
|
||||
ar( CEREAL_NVP_("type", t) );
|
||||
|
||||
switch( t )
|
||||
{
|
||||
case bitset_detail::type::ulong:
|
||||
{
|
||||
unsigned long b;
|
||||
ar( CEREAL_NVP_("data", b) );
|
||||
bits = std::bitset<N>( b );
|
||||
break;
|
||||
}
|
||||
case bitset_detail::type::ullong:
|
||||
{
|
||||
unsigned long long b;
|
||||
ar( CEREAL_NVP_("data", b) );
|
||||
bits = std::bitset<N>( b );
|
||||
break;
|
||||
}
|
||||
case bitset_detail::type::string:
|
||||
{
|
||||
std::string b;
|
||||
ar( CEREAL_NVP_("data", b) );
|
||||
bits = std::bitset<N>( b );
|
||||
break;
|
||||
}
|
||||
default:
|
||||
throw Exception("Invalid bitset data representation");
|
||||
}
|
||||
}
|
||||
} // namespace cereal
|
||||
|
||||
#endif // CEREAL_TYPES_BITSET_HPP_
|
||||
106
libs/cereal/cereal/types/boost_variant.hpp
Normal file
106
libs/cereal/cereal/types/boost_variant.hpp
Normal file
@ -0,0 +1,106 @@
|
||||
/*! \file boost_variant.hpp
|
||||
\brief Support for boost::variant
|
||||
\ingroup OtherTypes */
|
||||
/*
|
||||
Copyright (c) 2014, Randolph Voorhies, Shane Grant
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of cereal nor the
|
||||
names of its contributors may be used to endorse or promote products
|
||||
derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL RANDOLPH VOORHIES OR SHANE GRANT BE LIABLE FOR ANY
|
||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
#ifndef CEREAL_TYPES_BOOST_VARIANT_HPP_
|
||||
#define CEREAL_TYPES_BOOST_VARIANT_HPP_
|
||||
|
||||
#include <cereal/cereal.hpp>
|
||||
#include <boost/variant.hpp>
|
||||
#include <boost/mpl/size.hpp>
|
||||
|
||||
namespace cereal
|
||||
{
|
||||
namespace variant_detail
|
||||
{
|
||||
//! @internal
|
||||
template <class Archive>
|
||||
struct variant_save_visitor : boost::static_visitor<>
|
||||
{
|
||||
variant_save_visitor(Archive & ar_) : ar(ar_) {}
|
||||
|
||||
template<class T>
|
||||
void operator()(T const & value) const
|
||||
{
|
||||
ar( CEREAL_NVP_("data", value) );
|
||||
}
|
||||
|
||||
Archive & ar;
|
||||
};
|
||||
|
||||
//! @internal
|
||||
template<int N, class Variant, class ... Args, class Archive>
|
||||
typename std::enable_if<N == boost::mpl::size<typename Variant::types>::value, void>::type
|
||||
load_variant(Archive & /*ar*/, int /*target*/, Variant & /*variant*/)
|
||||
{
|
||||
throw ::cereal::Exception("Error traversing variant during load");
|
||||
}
|
||||
|
||||
//! @internal
|
||||
template<int N, class Variant, class H, class ... T, class Archive>
|
||||
typename std::enable_if<N < boost::mpl::size<typename Variant::types>::value, void>::type
|
||||
load_variant(Archive & ar, int target, Variant & variant)
|
||||
{
|
||||
if(N == target)
|
||||
{
|
||||
H value;
|
||||
ar( CEREAL_NVP_("data", value) );
|
||||
variant = value;
|
||||
}
|
||||
else
|
||||
load_variant<N+1, Variant, T...>(ar, target, variant);
|
||||
}
|
||||
|
||||
} // namespace variant_detail
|
||||
|
||||
//! Saving for boost::variant
|
||||
template <class Archive, typename... VariantTypes> inline
|
||||
void CEREAL_SAVE_FUNCTION_NAME( Archive & ar, boost::variant<VariantTypes...> const & variant )
|
||||
{
|
||||
int32_t which = variant.which();
|
||||
ar( CEREAL_NVP_("which", which) );
|
||||
variant_detail::variant_save_visitor<Archive> visitor(ar);
|
||||
variant.apply_visitor(visitor);
|
||||
}
|
||||
|
||||
//! Loading for boost::variant
|
||||
template <class Archive, typename... VariantTypes> inline
|
||||
void CEREAL_LOAD_FUNCTION_NAME( Archive & ar, boost::variant<VariantTypes...> & variant )
|
||||
{
|
||||
typedef typename boost::variant<VariantTypes...>::types types;
|
||||
|
||||
int32_t which;
|
||||
ar( CEREAL_NVP_("which", which) );
|
||||
if(which >= boost::mpl::size<types>::value)
|
||||
throw Exception("Invalid 'which' selector when deserializing boost::variant");
|
||||
|
||||
variant_detail::load_variant<0, boost::variant<VariantTypes...>, VariantTypes...>(ar, which, variant);
|
||||
}
|
||||
} // namespace cereal
|
||||
|
||||
#endif // CEREAL_TYPES_BOOST_VARIANT_HPP_
|
||||
72
libs/cereal/cereal/types/chrono.hpp
Normal file
72
libs/cereal/cereal/types/chrono.hpp
Normal file
@ -0,0 +1,72 @@
|
||||
/*! \file chrono.hpp
|
||||
\brief Support for types found in \<chrono\>
|
||||
\ingroup STLSupport */
|
||||
/*
|
||||
Copyright (c) 2014, Randolph Voorhies, Shane Grant
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of cereal nor the
|
||||
names of its contributors may be used to endorse or promote products
|
||||
derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL RANDOLPH VOORHIES OR SHANE GRANT BE LIABLE FOR ANY
|
||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
#ifndef CEREAL_TYPES_CHRONO_HPP_
|
||||
#define CEREAL_TYPES_CHRONO_HPP_
|
||||
|
||||
#include <chrono>
|
||||
|
||||
namespace cereal
|
||||
{
|
||||
//! Saving std::chrono::duration
|
||||
template <class Archive, class R, class P> inline
|
||||
void CEREAL_SAVE_FUNCTION_NAME( Archive & ar, std::chrono::duration<R, P> const & dur )
|
||||
{
|
||||
ar( CEREAL_NVP_("count", dur.count()) );
|
||||
}
|
||||
|
||||
//! Loading std::chrono::duration
|
||||
template <class Archive, class R, class P> inline
|
||||
void CEREAL_LOAD_FUNCTION_NAME( Archive & ar, std::chrono::duration<R, P> & dur )
|
||||
{
|
||||
R count;
|
||||
ar( CEREAL_NVP_("count", count) );
|
||||
|
||||
dur = std::chrono::duration<R, P>{count};
|
||||
}
|
||||
|
||||
//! Saving std::chrono::time_point
|
||||
template <class Archive, class C, class D> inline
|
||||
void CEREAL_SAVE_FUNCTION_NAME( Archive & ar, std::chrono::time_point<C, D> const & dur )
|
||||
{
|
||||
ar( CEREAL_NVP_("time_since_epoch", dur.time_since_epoch()) );
|
||||
}
|
||||
|
||||
//! Loading std::chrono::time_point
|
||||
template <class Archive, class C, class D> inline
|
||||
void CEREAL_LOAD_FUNCTION_NAME( Archive & ar, std::chrono::time_point<C, D> & dur )
|
||||
{
|
||||
D elapsed;
|
||||
ar( CEREAL_NVP_("time_since_epoch", elapsed) );
|
||||
|
||||
dur = std::chrono::time_point<C, D>{elapsed};
|
||||
}
|
||||
} // namespace cereal
|
||||
|
||||
#endif // CEREAL_TYPES_CHRONO_HPP_
|
||||
129
libs/cereal/cereal/types/common.hpp
Normal file
129
libs/cereal/cereal/types/common.hpp
Normal file
@ -0,0 +1,129 @@
|
||||
/*! \file common.hpp
|
||||
\brief Support common types - always included automatically
|
||||
\ingroup OtherTypes */
|
||||
/*
|
||||
Copyright (c) 2014, Randolph Voorhies, Shane Grant
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of cereal nor the
|
||||
names of its contributors may be used to endorse or promote products
|
||||
derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL RANDOLPH VOORHIES OR SHANE GRANT BE LIABLE FOR ANY
|
||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
#ifndef CEREAL_TYPES_COMMON_HPP_
|
||||
#define CEREAL_TYPES_COMMON_HPP_
|
||||
|
||||
#include <cereal/cereal.hpp>
|
||||
|
||||
namespace cereal
|
||||
{
|
||||
namespace common_detail
|
||||
{
|
||||
//! Serialization for arrays if BinaryData is supported and we are arithmetic
|
||||
/*! @internal */
|
||||
template <class Archive, class T> inline
|
||||
void serializeArray( Archive & ar, T & array, std::true_type /* binary_supported */ )
|
||||
{
|
||||
ar( binary_data( array, sizeof(array) ) );
|
||||
}
|
||||
|
||||
//! Serialization for arrays if BinaryData is not supported or we are not arithmetic
|
||||
/*! @internal */
|
||||
template <class Archive, class T> inline
|
||||
void serializeArray( Archive & ar, T & array, std::false_type /* binary_supported */ )
|
||||
{
|
||||
for( auto & i : array )
|
||||
ar( i );
|
||||
}
|
||||
|
||||
namespace
|
||||
{
|
||||
//! Gets the underlying type of an enum
|
||||
/*! @internal */
|
||||
template <class T, bool IsEnum>
|
||||
struct enum_underlying_type : std::false_type {};
|
||||
|
||||
//! Gets the underlying type of an enum
|
||||
/*! Specialization for when we actually have an enum
|
||||
@internal */
|
||||
template <class T>
|
||||
struct enum_underlying_type<T, true> { using type = typename std::underlying_type<T>::type; };
|
||||
} // anon namespace
|
||||
|
||||
//! Checks if a type is an enum
|
||||
/*! This is needed over simply calling std::is_enum because the type
|
||||
traits checking at compile time will attempt to call something like
|
||||
load_minimal with a special NoConvertRef struct that wraps up the true type.
|
||||
|
||||
This will strip away any of that and also expose the true underlying type.
|
||||
@internal */
|
||||
template <class T>
|
||||
class is_enum
|
||||
{
|
||||
private:
|
||||
using DecayedT = typename std::decay<T>::type;
|
||||
using StrippedT = typename ::cereal::traits::strip_minimal<DecayedT>::type;
|
||||
|
||||
public:
|
||||
static const bool value = std::is_enum<StrippedT>::value;
|
||||
using type = StrippedT;
|
||||
using base_type = typename enum_underlying_type<StrippedT, value>::type;
|
||||
};
|
||||
}
|
||||
|
||||
//! Saving for enum types
|
||||
template <class Archive, class T> inline
|
||||
typename std::enable_if<common_detail::is_enum<T>::value,
|
||||
typename common_detail::is_enum<T>::base_type>::type
|
||||
CEREAL_SAVE_MINIMAL_FUNCTION_NAME( Archive const &, T const & t )
|
||||
{
|
||||
return static_cast<typename common_detail::is_enum<T>::base_type>(t);
|
||||
}
|
||||
|
||||
//! Loading for enum types
|
||||
template <class Archive, class T> inline
|
||||
typename std::enable_if<common_detail::is_enum<T>::value, void>::type
|
||||
CEREAL_LOAD_MINIMAL_FUNCTION_NAME( Archive const &, T && t,
|
||||
typename common_detail::is_enum<T>::base_type const & value )
|
||||
{
|
||||
t = reinterpret_cast<typename common_detail::is_enum<T>::type const &>( value );
|
||||
}
|
||||
|
||||
//! Serialization for raw pointers
|
||||
/*! This exists only to throw a static_assert to let users know we don't support raw pointers. */
|
||||
template <class Archive, class T> inline
|
||||
void CEREAL_SERIALIZE_FUNCTION_NAME( Archive &, T * & )
|
||||
{
|
||||
static_assert(cereal::traits::detail::delay_static_assert<T>::value,
|
||||
"Cereal does not support serializing raw pointers - please use a smart pointer");
|
||||
}
|
||||
|
||||
//! Serialization for C style arrays
|
||||
template <class Archive, class T> inline
|
||||
typename std::enable_if<std::is_array<T>::value, void>::type
|
||||
CEREAL_SERIALIZE_FUNCTION_NAME(Archive & ar, T & array)
|
||||
{
|
||||
common_detail::serializeArray( ar, array,
|
||||
std::integral_constant<bool, traits::is_output_serializable<BinaryData<T>, Archive>::value &&
|
||||
std::is_arithmetic<typename std::remove_all_extents<T>::type>::value>() );
|
||||
}
|
||||
} // namespace cereal
|
||||
|
||||
#endif // CEREAL_TYPES_COMMON_HPP_
|
||||
56
libs/cereal/cereal/types/complex.hpp
Normal file
56
libs/cereal/cereal/types/complex.hpp
Normal file
@ -0,0 +1,56 @@
|
||||
/*! \file complex.hpp
|
||||
\brief Support for types found in \<complex\>
|
||||
\ingroup STLSupport */
|
||||
/*
|
||||
Copyright (c) 2014, Randolph Voorhies, Shane Grant
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of cereal nor the
|
||||
names of its contributors may be used to endorse or promote products
|
||||
derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL RANDOLPH VOORHIES OR SHANE GRANT BE LIABLE FOR ANY
|
||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
#ifndef CEREAL_TYPES_COMPLEX_HPP_
|
||||
#define CEREAL_TYPES_COMPLEX_HPP_
|
||||
|
||||
#include <complex>
|
||||
|
||||
namespace cereal
|
||||
{
|
||||
//! Serializing (save) for std::complex
|
||||
template <class Archive, class T> inline
|
||||
void CEREAL_SAVE_FUNCTION_NAME( Archive & ar, std::complex<T> const & comp )
|
||||
{
|
||||
ar( CEREAL_NVP_("real", comp.real()),
|
||||
CEREAL_NVP_("imag", comp.imag()) );
|
||||
}
|
||||
|
||||
//! Serializing (load) for std::complex
|
||||
template <class Archive, class T> inline
|
||||
void CEREAL_LOAD_FUNCTION_NAME( Archive & ar, std::complex<T> & bits )
|
||||
{
|
||||
T real, imag;
|
||||
ar( CEREAL_NVP_("real", real),
|
||||
CEREAL_NVP_("imag", imag) );
|
||||
bits = {real, imag};
|
||||
}
|
||||
} // namespace cereal
|
||||
|
||||
#endif // CEREAL_TYPES_COMPLEX_HPP_
|
||||
62
libs/cereal/cereal/types/deque.hpp
Normal file
62
libs/cereal/cereal/types/deque.hpp
Normal file
@ -0,0 +1,62 @@
|
||||
/*! \file deque.hpp
|
||||
\brief Support for types found in \<deque\>
|
||||
\ingroup STLSupport */
|
||||
/*
|
||||
Copyright (c) 2014, Randolph Voorhies, Shane Grant
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of cereal nor the
|
||||
names of its contributors may be used to endorse or promote products
|
||||
derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL RANDOLPH VOORHIES OR SHANE GRANT BE LIABLE FOR ANY
|
||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
#ifndef CEREAL_TYPES_DEQUE_HPP_
|
||||
#define CEREAL_TYPES_DEQUE_HPP_
|
||||
|
||||
#include <cereal/cereal.hpp>
|
||||
#include <deque>
|
||||
|
||||
namespace cereal
|
||||
{
|
||||
//! Saving for std::deque
|
||||
template <class Archive, class T, class A> inline
|
||||
void CEREAL_SAVE_FUNCTION_NAME( Archive & ar, std::deque<T, A> const & deque )
|
||||
{
|
||||
ar( make_size_tag( static_cast<size_type>(deque.size()) ) );
|
||||
|
||||
for( auto const & i : deque )
|
||||
ar( i );
|
||||
}
|
||||
|
||||
//! Loading for std::deque
|
||||
template <class Archive, class T, class A> inline
|
||||
void CEREAL_LOAD_FUNCTION_NAME( Archive & ar, std::deque<T, A> & deque )
|
||||
{
|
||||
size_type size;
|
||||
ar( make_size_tag( size ) );
|
||||
|
||||
deque.resize( static_cast<size_t>( size ) );
|
||||
|
||||
for( auto & i : deque )
|
||||
ar( i );
|
||||
}
|
||||
} // namespace cereal
|
||||
|
||||
#endif // CEREAL_TYPES_DEQUE_HPP_
|
||||
68
libs/cereal/cereal/types/forward_list.hpp
Normal file
68
libs/cereal/cereal/types/forward_list.hpp
Normal file
@ -0,0 +1,68 @@
|
||||
/*! \file forward_list.hpp
|
||||
\brief Support for types found in \<forward_list\>
|
||||
\ingroup STLSupport */
|
||||
/*
|
||||
Copyright (c) 2014, Randolph Voorhies, Shane Grant
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of cereal nor the
|
||||
names of its contributors may be used to endorse or promote products
|
||||
derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL RANDOLPH VOORHIES OR SHANE GRANT BE LIABLE FOR ANY
|
||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
#ifndef CEREAL_TYPES_FORWARD_LIST_HPP_
|
||||
#define CEREAL_TYPES_FORWARD_LIST_HPP_
|
||||
|
||||
#include <cereal/cereal.hpp>
|
||||
#include <forward_list>
|
||||
|
||||
namespace cereal
|
||||
{
|
||||
//! Saving for std::forward_list all other types
|
||||
template <class Archive, class T, class A> inline
|
||||
void CEREAL_SAVE_FUNCTION_NAME( Archive & ar, std::forward_list<T, A> const & forward_list )
|
||||
{
|
||||
// write the size - note that this is slow because we need to traverse
|
||||
// the entire list. there are ways we could avoid this but this was chosen
|
||||
// since it works in the most general fashion with any archive type
|
||||
size_type const size = std::distance( forward_list.begin(), forward_list.end() );
|
||||
|
||||
ar( make_size_tag( size ) );
|
||||
|
||||
// write the list
|
||||
for( const auto & i : forward_list )
|
||||
ar( i );
|
||||
}
|
||||
|
||||
//! Loading for std::forward_list all other types from
|
||||
template <class Archive, class T, class A>
|
||||
void CEREAL_LOAD_FUNCTION_NAME( Archive & ar, std::forward_list<T, A> & forward_list )
|
||||
{
|
||||
size_type size;
|
||||
ar( make_size_tag( size ) );
|
||||
|
||||
forward_list.resize( static_cast<size_t>( size ) );
|
||||
|
||||
for( auto & i : forward_list )
|
||||
ar( i );
|
||||
}
|
||||
} // namespace cereal
|
||||
|
||||
#endif // CEREAL_TYPES_FORWARD_LIST_HPP_
|
||||
62
libs/cereal/cereal/types/list.hpp
Normal file
62
libs/cereal/cereal/types/list.hpp
Normal file
@ -0,0 +1,62 @@
|
||||
/*! \file list.hpp
|
||||
\brief Support for types found in \<list\>
|
||||
\ingroup STLSupport */
|
||||
/*
|
||||
Copyright (c) 2014, Randolph Voorhies, Shane Grant
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of cereal nor the
|
||||
names of its contributors may be used to endorse or promote products
|
||||
derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL RANDOLPH VOORHIES OR SHANE GRANT BE LIABLE FOR ANY
|
||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
#ifndef CEREAL_TYPES_LIST_HPP_
|
||||
#define CEREAL_TYPES_LIST_HPP_
|
||||
|
||||
#include <cereal/cereal.hpp>
|
||||
#include <list>
|
||||
|
||||
namespace cereal
|
||||
{
|
||||
//! Saving for std::list
|
||||
template <class Archive, class T, class A> inline
|
||||
void CEREAL_SAVE_FUNCTION_NAME( Archive & ar, std::list<T, A> const & list )
|
||||
{
|
||||
ar( make_size_tag( static_cast<size_type>(list.size()) ) );
|
||||
|
||||
for( auto const & i : list )
|
||||
ar( i );
|
||||
}
|
||||
|
||||
//! Loading for std::list
|
||||
template <class Archive, class T, class A> inline
|
||||
void CEREAL_LOAD_FUNCTION_NAME( Archive & ar, std::list<T, A> & list )
|
||||
{
|
||||
size_type size;
|
||||
ar( make_size_tag( size ) );
|
||||
|
||||
list.resize( static_cast<size_t>( size ) );
|
||||
|
||||
for( auto & i : list )
|
||||
ar( i );
|
||||
}
|
||||
} // namespace cereal
|
||||
|
||||
#endif // CEREAL_TYPES_LIST_HPP_
|
||||
108
libs/cereal/cereal/types/map.hpp
Normal file
108
libs/cereal/cereal/types/map.hpp
Normal file
@ -0,0 +1,108 @@
|
||||
/*! \file map.hpp
|
||||
\brief Support for types found in \<map\>
|
||||
\ingroup STLSupport */
|
||||
/*
|
||||
Copyright (c) 2014, Randolph Voorhies, Shane Grant
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of cereal nor the
|
||||
names of its contributors may be used to endorse or promote products
|
||||
derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL RANDOLPH VOORHIES OR SHANE GRANT BE LIABLE FOR ANY
|
||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
#ifndef CEREAL_TYPES_MAP_HPP_
|
||||
#define CEREAL_TYPES_MAP_HPP_
|
||||
|
||||
#include <cereal/cereal.hpp>
|
||||
#include <map>
|
||||
|
||||
namespace cereal
|
||||
{
|
||||
namespace map_detail
|
||||
{
|
||||
//! @internal
|
||||
template <class Archive, class MapT> inline
|
||||
void save( Archive & ar, MapT const & map )
|
||||
{
|
||||
ar( make_size_tag( static_cast<size_type>(map.size()) ) );
|
||||
|
||||
for( const auto & i : map )
|
||||
{
|
||||
ar( make_map_item(i.first, i.second) );
|
||||
}
|
||||
}
|
||||
|
||||
//! @internal
|
||||
template <class Archive, class MapT> inline
|
||||
void load( Archive & ar, MapT & map )
|
||||
{
|
||||
size_type size;
|
||||
ar( make_size_tag( size ) );
|
||||
|
||||
map.clear();
|
||||
|
||||
auto hint = map.begin();
|
||||
for( size_t i = 0; i < size; ++i )
|
||||
{
|
||||
typename MapT::key_type key;
|
||||
typename MapT::mapped_type value;
|
||||
|
||||
ar( make_map_item(key, value) );
|
||||
#ifdef CEREAL_OLDER_GCC
|
||||
hint = map.insert( hint, std::make_pair(std::move(key), std::move(value)) );
|
||||
#else // NOT CEREAL_OLDER_GCC
|
||||
hint = map.emplace_hint( hint, std::move( key ), std::move( value ) );
|
||||
#endif // NOT CEREAL_OLDER_GCC
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//! Saving for std::map
|
||||
template <class Archive, class K, class T, class C, class A> inline
|
||||
void CEREAL_SAVE_FUNCTION_NAME( Archive & ar, std::map<K, T, C, A> const & map )
|
||||
{
|
||||
map_detail::save( ar, map );
|
||||
}
|
||||
|
||||
//! Loading for std::map
|
||||
template <class Archive, class K, class T, class C, class A> inline
|
||||
void CEREAL_LOAD_FUNCTION_NAME( Archive & ar, std::map<K, T, C, A> & map )
|
||||
{
|
||||
map_detail::load( ar, map );
|
||||
}
|
||||
|
||||
//! Saving for std::multimap
|
||||
/*! @note serialization for this type is not guaranteed to preserve ordering */
|
||||
template <class Archive, class K, class T, class C, class A> inline
|
||||
void CEREAL_SAVE_FUNCTION_NAME( Archive & ar, std::multimap<K, T, C, A> const & multimap )
|
||||
{
|
||||
map_detail::save( ar, multimap );
|
||||
}
|
||||
|
||||
//! Loading for std::multimap
|
||||
/*! @note serialization for this type is not guaranteed to preserve ordering */
|
||||
template <class Archive, class K, class T, class C, class A> inline
|
||||
void CEREAL_LOAD_FUNCTION_NAME( Archive & ar, std::multimap<K, T, C, A> & multimap )
|
||||
{
|
||||
map_detail::load( ar, multimap );
|
||||
}
|
||||
} // namespace cereal
|
||||
|
||||
#endif // CEREAL_TYPES_MAP_HPP_
|
||||
392
libs/cereal/cereal/types/memory.hpp
Normal file
392
libs/cereal/cereal/types/memory.hpp
Normal file
@ -0,0 +1,392 @@
|
||||
/*! \file memory.hpp
|
||||
\brief Support for types found in \<memory\>
|
||||
\ingroup STLSupport */
|
||||
/*
|
||||
Copyright (c) 2014, Randolph Voorhies, Shane Grant
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of cereal nor the
|
||||
names of its contributors may be used to endorse or promote products
|
||||
derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL RANDOLPH VOORHIES OR SHANE GRANT BE LIABLE FOR ANY
|
||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
#ifndef CEREAL_TYPES_SHARED_PTR_HPP_
|
||||
#define CEREAL_TYPES_SHARED_PTR_HPP_
|
||||
|
||||
#include <cereal/cereal.hpp>
|
||||
#include <memory>
|
||||
#include <cstring>
|
||||
|
||||
namespace cereal
|
||||
{
|
||||
namespace memory_detail
|
||||
{
|
||||
//! A wrapper class to notify cereal that it is ok to serialize the contained pointer
|
||||
/*! This mechanism allows us to intercept and properly handle polymorphic pointers
|
||||
@internal */
|
||||
template<class T>
|
||||
struct PtrWrapper
|
||||
{
|
||||
PtrWrapper(T && p) : ptr(std::forward<T>(p)) {}
|
||||
T & ptr;
|
||||
|
||||
PtrWrapper & operator=( PtrWrapper const & ) = delete;
|
||||
};
|
||||
|
||||
//! Make a PtrWrapper
|
||||
/*! @internal */
|
||||
template<class T> inline
|
||||
PtrWrapper<T> make_ptr_wrapper(T && t)
|
||||
{
|
||||
return {std::forward<T>(t)};
|
||||
}
|
||||
|
||||
//! A struct that acts as a wrapper around calling load_andor_construct
|
||||
/*! The purpose of this is to allow a load_and_construct call to properly enter into the
|
||||
'data' NVP of the ptr_wrapper
|
||||
@internal */
|
||||
template <class Archive, class T>
|
||||
struct LoadAndConstructLoadWrapper
|
||||
{
|
||||
LoadAndConstructLoadWrapper( T * ptr ) :
|
||||
construct( ptr )
|
||||
{ }
|
||||
|
||||
inline void CEREAL_SERIALIZE_FUNCTION_NAME( Archive & ar )
|
||||
{
|
||||
::cereal::detail::Construct<T, Archive>::load_andor_construct( ar, construct );
|
||||
}
|
||||
|
||||
::cereal::construct<T> construct;
|
||||
};
|
||||
|
||||
//! A helper struct for saving and restoring the state of types that derive from
|
||||
//! std::enable_shared_from_this
|
||||
/*! This special struct is necessary because when a user uses load_and_construct,
|
||||
the weak_ptr (or whatever implementation defined variant) that allows
|
||||
enable_shared_from_this to function correctly will not be initialized properly.
|
||||
|
||||
This internal weak_ptr can also be modified by the shared_ptr that is created
|
||||
during the serialization of a polymorphic pointer, where cereal creates a
|
||||
wrapper shared_ptr out of a void pointer to the real data.
|
||||
|
||||
In the case of load_and_construct, this happens because it is the allocation
|
||||
of shared_ptr that perform this initialization, which we let happen on a buffer
|
||||
of memory (aligned_storage). This buffer is then used for placement new
|
||||
later on, effectively overwriting any initialized weak_ptr with a default
|
||||
initialized one, eventually leading to issues when the user calls shared_from_this.
|
||||
|
||||
To get around these issues, we will store the memory for the enable_shared_from_this
|
||||
portion of the class and replace it after whatever happens to modify it (e.g. the
|
||||
user performing construction or the wrapper shared_ptr in saving).
|
||||
|
||||
Example usage:
|
||||
|
||||
@code{.cpp}
|
||||
T * myActualPointer;
|
||||
{
|
||||
EnableSharedStateHelper<T> helper( myActualPointer ); // save the state
|
||||
std::shared_ptr<T> myPtr( myActualPointer ); // modifies the internal weak_ptr
|
||||
// helper restores state when it goes out of scope
|
||||
}
|
||||
@endcode
|
||||
|
||||
This is designed to be used in an RAII fashion - it will save state on construction
|
||||
and restore it on destruction.
|
||||
|
||||
@tparam T Type pointed to by shared_ptr
|
||||
@internal */
|
||||
template <class T>
|
||||
class EnableSharedStateHelper
|
||||
{
|
||||
// typedefs for parent type and storage type
|
||||
using BaseType = typename ::cereal::traits::get_shared_from_this_base<T>::type;
|
||||
using ParentType = std::enable_shared_from_this<BaseType>;
|
||||
using StorageType = typename std::aligned_storage<sizeof(ParentType)>::type;
|
||||
|
||||
public:
|
||||
//! Saves the state of some type inheriting from enable_shared_from_this
|
||||
/*! @param ptr The raw pointer held by the shared_ptr */
|
||||
inline EnableSharedStateHelper( T * ptr ) :
|
||||
itsPtr( static_cast<ParentType *>( ptr ) ),
|
||||
itsState()
|
||||
{
|
||||
std::memcpy( &itsState, itsPtr, sizeof(ParentType) );
|
||||
}
|
||||
|
||||
//! Restores the state of the held pointer
|
||||
inline ~EnableSharedStateHelper()
|
||||
{
|
||||
std::memcpy( itsPtr, &itsState, sizeof(ParentType) );
|
||||
}
|
||||
|
||||
private:
|
||||
ParentType * itsPtr;
|
||||
StorageType itsState;
|
||||
}; // end EnableSharedStateHelper
|
||||
|
||||
//! Performs loading and construction for a shared pointer that is derived from
|
||||
//! std::enable_shared_from_this
|
||||
/*! @param ar The archive
|
||||
@param ptr Raw pointer held by the shared_ptr
|
||||
@internal */
|
||||
template <class Archive, class T> inline
|
||||
void loadAndConstructSharedPtr( Archive & ar, T * ptr, std::true_type /* has_shared_from_this */ )
|
||||
{
|
||||
memory_detail::LoadAndConstructLoadWrapper<Archive, T> loadWrapper( ptr );
|
||||
memory_detail::EnableSharedStateHelper<T> state( ptr );
|
||||
|
||||
// let the user perform their initialization
|
||||
ar( CEREAL_NVP_("data", loadWrapper) );
|
||||
}
|
||||
|
||||
//! Performs loading and construction for a shared pointer that is NOT derived from
|
||||
//! std::enable_shared_from_this
|
||||
/*! This is the typical case, where we simply pass the load wrapper to the
|
||||
archive.
|
||||
|
||||
@param ar The archive
|
||||
@param ptr Raw pointer held by the shared_ptr
|
||||
@internal */
|
||||
template <class Archive, class T> inline
|
||||
void loadAndConstructSharedPtr( Archive & ar, T * ptr, std::false_type /* has_shared_from_this */ )
|
||||
{
|
||||
memory_detail::LoadAndConstructLoadWrapper<Archive, T> loadWrapper( ptr );
|
||||
ar( CEREAL_NVP_("data", loadWrapper) );
|
||||
}
|
||||
} // end namespace memory_detail
|
||||
|
||||
//! Saving std::shared_ptr for non polymorphic types
|
||||
template <class Archive, class T> inline
|
||||
typename std::enable_if<!std::is_polymorphic<T>::value, void>::type
|
||||
CEREAL_SAVE_FUNCTION_NAME( Archive & ar, std::shared_ptr<T> const & ptr )
|
||||
{
|
||||
ar( CEREAL_NVP_("ptr_wrapper", memory_detail::make_ptr_wrapper( ptr )) );
|
||||
}
|
||||
|
||||
//! Loading std::shared_ptr, case when no user load and construct for non polymorphic types
|
||||
template <class Archive, class T> inline
|
||||
typename std::enable_if<!std::is_polymorphic<T>::value, void>::type
|
||||
CEREAL_LOAD_FUNCTION_NAME( Archive & ar, std::shared_ptr<T> & ptr )
|
||||
{
|
||||
ar( CEREAL_NVP_("ptr_wrapper", memory_detail::make_ptr_wrapper( ptr )) );
|
||||
}
|
||||
|
||||
//! Saving std::weak_ptr for non polymorphic types
|
||||
template <class Archive, class T> inline
|
||||
typename std::enable_if<!std::is_polymorphic<T>::value, void>::type
|
||||
CEREAL_SAVE_FUNCTION_NAME( Archive & ar, std::weak_ptr<T> const & ptr )
|
||||
{
|
||||
auto const sptr = ptr.lock();
|
||||
ar( CEREAL_NVP_("ptr_wrapper", memory_detail::make_ptr_wrapper( sptr )) );
|
||||
}
|
||||
|
||||
//! Loading std::weak_ptr for non polymorphic types
|
||||
template <class Archive, class T> inline
|
||||
typename std::enable_if<!std::is_polymorphic<T>::value, void>::type
|
||||
CEREAL_LOAD_FUNCTION_NAME( Archive & ar, std::weak_ptr<T> & ptr )
|
||||
{
|
||||
std::shared_ptr<T> sptr;
|
||||
ar( CEREAL_NVP_("ptr_wrapper", memory_detail::make_ptr_wrapper( sptr )) );
|
||||
ptr = sptr;
|
||||
}
|
||||
|
||||
//! Saving std::unique_ptr for non polymorphic types
|
||||
template <class Archive, class T, class D> inline
|
||||
typename std::enable_if<!std::is_polymorphic<T>::value, void>::type
|
||||
CEREAL_SAVE_FUNCTION_NAME( Archive & ar, std::unique_ptr<T, D> const & ptr )
|
||||
{
|
||||
ar( CEREAL_NVP_("ptr_wrapper", memory_detail::make_ptr_wrapper( ptr )) );
|
||||
}
|
||||
|
||||
//! Loading std::unique_ptr, case when user provides load_and_construct for non polymorphic types
|
||||
template <class Archive, class T, class D> inline
|
||||
typename std::enable_if<!std::is_polymorphic<T>::value, void>::type
|
||||
CEREAL_LOAD_FUNCTION_NAME( Archive & ar, std::unique_ptr<T, D> & ptr )
|
||||
{
|
||||
ar( CEREAL_NVP_("ptr_wrapper", memory_detail::make_ptr_wrapper( ptr )) );
|
||||
}
|
||||
|
||||
// ######################################################################
|
||||
// Pointer wrapper implementations follow below
|
||||
|
||||
//! Saving std::shared_ptr (wrapper implementation)
|
||||
/*! @internal */
|
||||
template <class Archive, class T> inline
|
||||
void CEREAL_SAVE_FUNCTION_NAME( Archive & ar, memory_detail::PtrWrapper<std::shared_ptr<T> const &> const & wrapper )
|
||||
{
|
||||
auto & ptr = wrapper.ptr;
|
||||
|
||||
uint32_t id = ar.registerSharedPointer( ptr.get() );
|
||||
ar( CEREAL_NVP_("id", id) );
|
||||
|
||||
if( id & detail::msb_32bit )
|
||||
{
|
||||
ar( CEREAL_NVP_("data", *ptr) );
|
||||
}
|
||||
}
|
||||
|
||||
//! Loading std::shared_ptr, case when user load and construct (wrapper implementation)
|
||||
/*! @internal */
|
||||
template <class Archive, class T> inline
|
||||
typename std::enable_if<traits::has_load_and_construct<T, Archive>::value, void>::type
|
||||
CEREAL_LOAD_FUNCTION_NAME( Archive & ar, memory_detail::PtrWrapper<std::shared_ptr<T> &> & wrapper )
|
||||
{
|
||||
auto & ptr = wrapper.ptr;
|
||||
|
||||
uint32_t id;
|
||||
|
||||
ar( CEREAL_NVP_("id", id) );
|
||||
|
||||
if( id & detail::msb_32bit )
|
||||
{
|
||||
// Storage type for the pointer - since we can't default construct this type,
|
||||
// we'll allocate it using std::aligned_storage and use a custom deleter
|
||||
using ST = typename std::aligned_storage<sizeof(T)>::type;
|
||||
|
||||
// Valid flag - set to true once construction finishes
|
||||
// This prevents us from calling the destructor on
|
||||
// uninitialized data.
|
||||
auto valid = std::make_shared<bool>( false );
|
||||
|
||||
// Allocate our storage, which we will treat as
|
||||
// uninitialized until initialized with placement new
|
||||
ptr.reset( reinterpret_cast<T *>( new ST() ),
|
||||
[=]( T * t )
|
||||
{
|
||||
if( valid )
|
||||
t->~T();
|
||||
|
||||
delete reinterpret_cast<ST *>( t );
|
||||
} );
|
||||
|
||||
// Register the pointer
|
||||
ar.registerSharedPointer( id, ptr );
|
||||
|
||||
// Perform the actual loading and allocation
|
||||
memory_detail::loadAndConstructSharedPtr( ar, ptr.get(), typename ::cereal::traits::has_shared_from_this<T>::type() );
|
||||
|
||||
// Mark pointer as valid (initialized)
|
||||
*valid = true;
|
||||
}
|
||||
else
|
||||
ptr = std::static_pointer_cast<T>(ar.getSharedPointer(id));
|
||||
}
|
||||
|
||||
//! Loading std::shared_ptr, case when no user load and construct (wrapper implementation)
|
||||
/*! @internal */
|
||||
template <class Archive, class T> inline
|
||||
typename std::enable_if<!traits::has_load_and_construct<T, Archive>::value, void>::type
|
||||
CEREAL_LOAD_FUNCTION_NAME( Archive & ar, memory_detail::PtrWrapper<std::shared_ptr<T> &> & wrapper )
|
||||
{
|
||||
auto & ptr = wrapper.ptr;
|
||||
|
||||
uint32_t id;
|
||||
|
||||
ar( CEREAL_NVP_("id", id) );
|
||||
|
||||
if( id & detail::msb_32bit )
|
||||
{
|
||||
ptr.reset( detail::Construct<T, Archive>::load_andor_construct() );
|
||||
ar.registerSharedPointer( id, ptr );
|
||||
ar( CEREAL_NVP_("data", *ptr) );
|
||||
}
|
||||
else
|
||||
ptr = std::static_pointer_cast<T>(ar.getSharedPointer(id));
|
||||
}
|
||||
|
||||
//! Saving std::unique_ptr (wrapper implementation)
|
||||
/*! @internal */
|
||||
template <class Archive, class T, class D> inline
|
||||
void CEREAL_SAVE_FUNCTION_NAME( Archive & ar, memory_detail::PtrWrapper<std::unique_ptr<T, D> const &> const & wrapper )
|
||||
{
|
||||
auto & ptr = wrapper.ptr;
|
||||
|
||||
// unique_ptr get one byte of metadata which signifies whether they were a nullptr
|
||||
// 0 == nullptr
|
||||
// 1 == not null
|
||||
|
||||
if( !ptr )
|
||||
ar( CEREAL_NVP_("valid", uint8_t(0)) );
|
||||
else
|
||||
{
|
||||
ar( CEREAL_NVP_("valid", uint8_t(1)) );
|
||||
ar( CEREAL_NVP_("data", *ptr) );
|
||||
}
|
||||
}
|
||||
|
||||
//! Loading std::unique_ptr, case when user provides load_and_construct (wrapper implementation)
|
||||
/*! @internal */
|
||||
template <class Archive, class T, class D> inline
|
||||
typename std::enable_if<traits::has_load_and_construct<T, Archive>::value, void>::type
|
||||
CEREAL_LOAD_FUNCTION_NAME( Archive & ar, memory_detail::PtrWrapper<std::unique_ptr<T, D> &> & wrapper )
|
||||
{
|
||||
uint8_t isValid;
|
||||
ar( CEREAL_NVP_("valid", isValid) );
|
||||
|
||||
auto & ptr = wrapper.ptr;
|
||||
|
||||
if( isValid )
|
||||
{
|
||||
// Storage type for the pointer - since we can't default construct this type,
|
||||
// we'll allocate it using std::aligned_storage
|
||||
using ST = typename std::aligned_storage<sizeof(T)>::type;
|
||||
|
||||
// Allocate storage - note the ST type so that deleter is correct if
|
||||
// an exception is thrown before we are initialized
|
||||
std::unique_ptr<ST> stPtr( new ST() );
|
||||
|
||||
// Use wrapper to enter into "data" nvp of ptr_wrapper
|
||||
memory_detail::LoadAndConstructLoadWrapper<Archive, T> loadWrapper( reinterpret_cast<T *>( stPtr.get() ) );
|
||||
|
||||
// Initialize storage
|
||||
ar( CEREAL_NVP_("data", loadWrapper) );
|
||||
|
||||
// Transfer ownership to correct unique_ptr type
|
||||
ptr.reset( reinterpret_cast<T *>( stPtr.release() ) );
|
||||
}
|
||||
else
|
||||
ptr.reset( nullptr );
|
||||
}
|
||||
|
||||
//! Loading std::unique_ptr, case when no load_and_construct (wrapper implementation)
|
||||
/*! @internal */
|
||||
template <class Archive, class T, class D> inline
|
||||
typename std::enable_if<!traits::has_load_and_construct<T, Archive>::value, void>::type
|
||||
CEREAL_LOAD_FUNCTION_NAME( Archive & ar, memory_detail::PtrWrapper<std::unique_ptr<T, D> &> & wrapper )
|
||||
{
|
||||
uint8_t isValid;
|
||||
ar( CEREAL_NVP_("valid", isValid) );
|
||||
|
||||
auto & ptr = wrapper.ptr;
|
||||
|
||||
if( isValid )
|
||||
{
|
||||
ptr.reset( detail::Construct<T, Archive>::load_andor_construct() );
|
||||
ar( CEREAL_NVP_( "data", *ptr ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
ptr.reset( nullptr );
|
||||
}
|
||||
}
|
||||
} // namespace cereal
|
||||
|
||||
#endif // CEREAL_TYPES_SHARED_PTR_HPP_
|
||||
462
libs/cereal/cereal/types/polymorphic.hpp
Normal file
462
libs/cereal/cereal/types/polymorphic.hpp
Normal file
@ -0,0 +1,462 @@
|
||||
/*! \file polymorphic.hpp
|
||||
\brief Support for pointers to polymorphic base classes
|
||||
\ingroup OtherTypes */
|
||||
/*
|
||||
Copyright (c) 2014, Randolph Voorhies, Shane Grant
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of cereal nor the
|
||||
names of its contributors may be used to endorse or promote products
|
||||
derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL RANDOLPH VOORHIES OR SHANE GRANT BE LIABLE FOR ANY
|
||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
#ifndef CEREAL_TYPES_POLYMORPHIC_HPP_
|
||||
#define CEREAL_TYPES_POLYMORPHIC_HPP_
|
||||
|
||||
#include <cereal/cereal.hpp>
|
||||
#include <cereal/types/memory.hpp>
|
||||
|
||||
#include <cereal/details/util.hpp>
|
||||
#include <cereal/details/helpers.hpp>
|
||||
#include <cereal/details/traits.hpp>
|
||||
#include <cereal/details/polymorphic_impl.hpp>
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#define STATIC_CONSTEXPR static
|
||||
#else
|
||||
#define STATIC_CONSTEXPR static constexpr
|
||||
#endif
|
||||
|
||||
//! Registers a derived polymorphic type with cereal
|
||||
/*! Polymorphic types must be registered before smart
|
||||
pointers to them can be serialized. Note that base
|
||||
classes do not need to be registered.
|
||||
|
||||
Registering a type lets cereal know how to properly
|
||||
serialize it when a smart pointer to a base object is
|
||||
used in conjunction with a derived class.
|
||||
|
||||
This assumes that all relevant archives have also
|
||||
previously been registered. Registration for archives
|
||||
is usually done in the header file in which they are
|
||||
defined. This means that type registration needs to
|
||||
happen after specific archives to be used are included.
|
||||
|
||||
It is recommended that type registration be done in
|
||||
the header file in which the type is declared.
|
||||
|
||||
Registration can also be placed in a source file,
|
||||
but this may require the use of the
|
||||
CEREAL_REGISTER_DYNAMIC_INIT macro (see below).
|
||||
|
||||
Registration may be called repeatedly for the same
|
||||
type in different translation units to add support
|
||||
for additional archives if they are not initially
|
||||
available (included and registered).
|
||||
|
||||
When building serialization support as a DLL on
|
||||
Windows, registration must happen in the header file.
|
||||
On Linux and Mac things should still work properly
|
||||
if placed in a source file, but see the above comments
|
||||
on registering in source files.
|
||||
|
||||
Polymorphic support in cereal requires RTTI to be
|
||||
enabled */
|
||||
#define CEREAL_REGISTER_TYPE(T) \
|
||||
namespace cereal { \
|
||||
namespace detail { \
|
||||
template <> \
|
||||
struct binding_name<T> \
|
||||
{ \
|
||||
STATIC_CONSTEXPR char const * name() { return #T; } \
|
||||
}; \
|
||||
} } /* end namespaces */ \
|
||||
CEREAL_BIND_TO_ARCHIVES(T)
|
||||
|
||||
//! Registers a polymorphic type with cereal, giving it a
|
||||
//! user defined name
|
||||
/*! In some cases the default name used with
|
||||
CEREAL_REGISTER_TYPE (the name of the type) may not be
|
||||
suitable. This macro allows any name to be associated
|
||||
with the type. The name should be unique */
|
||||
#define CEREAL_REGISTER_TYPE_WITH_NAME(T, Name) \
|
||||
namespace cereal { \
|
||||
namespace detail { \
|
||||
template <> \
|
||||
struct binding_name<T> \
|
||||
{ STATIC_CONSTEXPR char const * name() { return Name; } }; \
|
||||
} } /* end namespaces */ \
|
||||
CEREAL_BIND_TO_ARCHIVES(T)
|
||||
|
||||
//! Adds a way to force initialization of a translation unit containing
|
||||
//! calls to CEREAL_REGISTER_TYPE
|
||||
/*! In C++, dynamic initialization of non-local variables of a translation
|
||||
unit may be deferred until "the first odr-use of any function or variable
|
||||
defined in the same translation unit as the variable to be initialized."
|
||||
|
||||
Informally, odr-use means that your program takes the address of or binds
|
||||
a reference directly to an object, which must have a definition.
|
||||
|
||||
Since polymorphic type support in cereal relies on the dynamic
|
||||
initialization of certain global objects happening before
|
||||
serialization is performed, it is important to ensure that something
|
||||
from files that call CEREAL_REGISTER_TYPE is odr-used before serialization
|
||||
occurs, otherwise the registration will never take place. This may often
|
||||
be the case when serialization is built as a shared library external from
|
||||
your main program.
|
||||
|
||||
This macro, with any name of your choosing, should be placed into the
|
||||
source file that contains calls to CEREAL_REGISTER_TYPE.
|
||||
|
||||
Its counterpart, CEREAL_FORCE_DYNAMIC_INIT, should be placed in its
|
||||
associated header file such that it is included in the translation units
|
||||
(source files) in which you want the registration to appear.
|
||||
|
||||
@relates CEREAL_FORCE_DYNAMIC_INIT
|
||||
*/
|
||||
#define CEREAL_REGISTER_DYNAMIC_INIT(LibName) \
|
||||
namespace cereal { \
|
||||
namespace detail { \
|
||||
void CEREAL_DLL_EXPORT dynamic_init_dummy_##LibName() {} \
|
||||
} } /* end namespaces */
|
||||
|
||||
//! Forces dynamic initialization of polymorphic support in a
|
||||
//! previously registered source file
|
||||
/*! @sa CEREAL_REGISTER_DYNAMIC_INIT
|
||||
|
||||
See CEREAL_REGISTER_DYNAMIC_INIT for detailed explanation
|
||||
of how this macro should be used. The name used should
|
||||
match that for CEREAL_REGISTER_DYNAMIC_INIT. */
|
||||
#define CEREAL_FORCE_DYNAMIC_INIT(LibName) \
|
||||
namespace cereal { \
|
||||
namespace detail { \
|
||||
void dynamic_init_dummy_##LibName(); \
|
||||
} /* end detail */ \
|
||||
namespace { \
|
||||
void dynamic_init_##LibName() \
|
||||
{ \
|
||||
::cereal::detail::dynamic_init_dummy_##LibName(); \
|
||||
} \
|
||||
} } /* end namespaces */
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#undef CONSTEXPR
|
||||
#endif
|
||||
|
||||
namespace cereal
|
||||
{
|
||||
namespace polymorphic_detail
|
||||
{
|
||||
//! Error message used for unregistered polymorphic types
|
||||
/*! @internal */
|
||||
#define UNREGISTERED_POLYMORPHIC_EXCEPTION(LoadSave, Name) \
|
||||
throw cereal::Exception("Trying to " #LoadSave " an unregistered polymorphic type (" + Name + ").\n" \
|
||||
"Make sure your type is registered with CEREAL_REGISTER_TYPE and that the archive " \
|
||||
"you are using was included (and registered with CEREAL_REGISTER_ARCHIVE) prior to calling CEREAL_REGISTER_TYPE.\n" \
|
||||
"If your type is already registered and you still see this error, you may need to use CEREAL_REGISTER_DYNAMIC_INIT.");
|
||||
|
||||
//! Get an input binding from the given archive by deserializing the type meta data
|
||||
/*! @internal */
|
||||
template<class Archive> inline
|
||||
typename ::cereal::detail::InputBindingMap<Archive>::Serializers getInputBinding(Archive & ar, std::uint32_t const nameid)
|
||||
{
|
||||
// If the nameid is zero, we serialized a null pointer
|
||||
if(nameid == 0)
|
||||
{
|
||||
typename ::cereal::detail::InputBindingMap<Archive>::Serializers emptySerializers;
|
||||
emptySerializers.shared_ptr = [](void*, std::shared_ptr<void> & ptr) { ptr.reset(); };
|
||||
emptySerializers.unique_ptr = [](void*, std::unique_ptr<void, ::cereal::detail::EmptyDeleter<void>> & ptr) { ptr.reset( nullptr ); };
|
||||
return emptySerializers;
|
||||
}
|
||||
|
||||
std::string name;
|
||||
if(nameid & detail::msb_32bit)
|
||||
{
|
||||
ar( CEREAL_NVP_("polymorphic_name", name) );
|
||||
ar.registerPolymorphicName(nameid, name);
|
||||
}
|
||||
else
|
||||
name = ar.getPolymorphicName(nameid);
|
||||
|
||||
auto & bindingMap = detail::StaticObject<detail::InputBindingMap<Archive>>::getInstance().map;
|
||||
|
||||
auto binding = bindingMap.find(name);
|
||||
if(binding == bindingMap.end())
|
||||
UNREGISTERED_POLYMORPHIC_EXCEPTION(load, name)
|
||||
return binding->second;
|
||||
}
|
||||
|
||||
//! Serialize a shared_ptr if the 2nd msb in the nameid is set, and if we can actually construct the pointee
|
||||
/*! This check lets us try and skip doing polymorphic machinery if we can get away with
|
||||
using the derived class serialize function
|
||||
|
||||
Note that on MSVC 2013 preview, is_default_constructible<T> returns true for abstract classes with
|
||||
default constructors, but on clang/gcc this will return false. So we also need to check for that here.
|
||||
@internal */
|
||||
template<class Archive, class T> inline
|
||||
typename std::enable_if<(traits::is_default_constructible<T>::value
|
||||
|| traits::has_load_and_construct<T, Archive>::value)
|
||||
&& !std::is_abstract<T>::value, bool>::type
|
||||
serialize_wrapper(Archive & ar, std::shared_ptr<T> & ptr, std::uint32_t const nameid)
|
||||
{
|
||||
if(nameid & detail::msb2_32bit)
|
||||
{
|
||||
ar( CEREAL_NVP_("ptr_wrapper", memory_detail::make_ptr_wrapper(ptr)) );
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
//! Serialize a unique_ptr if the 2nd msb in the nameid is set, and if we can actually construct the pointee
|
||||
/*! This check lets us try and skip doing polymorphic machinery if we can get away with
|
||||
using the derived class serialize function
|
||||
@internal */
|
||||
template<class Archive, class T, class D> inline
|
||||
typename std::enable_if<(traits::is_default_constructible<T>::value
|
||||
|| traits::has_load_and_construct<T, Archive>::value)
|
||||
&& !std::is_abstract<T>::value, bool>::type
|
||||
serialize_wrapper(Archive & ar, std::unique_ptr<T, D> & ptr, std::uint32_t const nameid)
|
||||
{
|
||||
if(nameid & detail::msb2_32bit)
|
||||
{
|
||||
ar( CEREAL_NVP_("ptr_wrapper", memory_detail::make_ptr_wrapper(ptr)) );
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
//! Serialize a shared_ptr if the 2nd msb in the nameid is set, and if we can actually construct the pointee
|
||||
/*! This case is for when we can't actually construct the shared pointer. Normally this would be caught
|
||||
as the pointer itself is serialized, but since this is a polymorphic pointer, if we tried to serialize
|
||||
the pointer we'd end up back here recursively. So we have to catch the error here as well, if
|
||||
this was a polymorphic type serialized by its proper pointer type
|
||||
@internal */
|
||||
template<class Archive, class T> inline
|
||||
typename std::enable_if<(!traits::is_default_constructible<T>::value
|
||||
&& !traits::has_load_and_construct<T, Archive>::value)
|
||||
|| std::is_abstract<T>::value, bool>::type
|
||||
serialize_wrapper(Archive &, std::shared_ptr<T> &, std::uint32_t const nameid)
|
||||
{
|
||||
if(nameid & detail::msb2_32bit)
|
||||
throw cereal::Exception("Cannot load a polymorphic type that is not default constructable and does not have a load_and_construct function");
|
||||
return false;
|
||||
}
|
||||
|
||||
//! Serialize a unique_ptr if the 2nd msb in the nameid is set, and if we can actually construct the pointee
|
||||
/*! This case is for when we can't actually construct the unique pointer. Normally this would be caught
|
||||
as the pointer itself is serialized, but since this is a polymorphic pointer, if we tried to serialize
|
||||
the pointer we'd end up back here recursively. So we have to catch the error here as well, if
|
||||
this was a polymorphic type serialized by its proper pointer type
|
||||
@internal */
|
||||
template<class Archive, class T, class D> inline
|
||||
typename std::enable_if<(!traits::is_default_constructible<T>::value
|
||||
&& !traits::has_load_and_construct<T, Archive>::value)
|
||||
|| std::is_abstract<T>::value, bool>::type
|
||||
serialize_wrapper(Archive &, std::unique_ptr<T, D> &, std::uint32_t const nameid)
|
||||
{
|
||||
if(nameid & detail::msb2_32bit)
|
||||
throw cereal::Exception("Cannot load a polymorphic type that is not default constructable and does not have a load_and_construct function");
|
||||
return false;
|
||||
}
|
||||
} // polymorphic_detail
|
||||
|
||||
// ######################################################################
|
||||
// Pointer serialization for polymorphic types
|
||||
|
||||
//! Saving std::shared_ptr for polymorphic types, abstract
|
||||
template <class Archive, class T> inline
|
||||
typename std::enable_if<std::is_polymorphic<T>::value && std::is_abstract<T>::value, void>::type
|
||||
CEREAL_SAVE_FUNCTION_NAME( Archive & ar, std::shared_ptr<T> const & ptr )
|
||||
{
|
||||
if(!ptr)
|
||||
{
|
||||
// same behavior as nullptr in memory implementation
|
||||
ar( CEREAL_NVP_("polymorphic_id", std::uint32_t(0)) );
|
||||
return;
|
||||
}
|
||||
|
||||
std::type_info const & ptrinfo = typeid(*ptr.get());
|
||||
// ptrinfo can never be equal to T info since we can't have an instance
|
||||
// of an abstract object
|
||||
// this implies we need to do the lookup
|
||||
|
||||
auto & bindingMap = detail::StaticObject<detail::OutputBindingMap<Archive>>::getInstance().map;
|
||||
|
||||
auto binding = bindingMap.find(std::type_index(ptrinfo));
|
||||
if(binding == bindingMap.end())
|
||||
UNREGISTERED_POLYMORPHIC_EXCEPTION(save, cereal::util::demangle(ptrinfo.name()))
|
||||
|
||||
binding->second.shared_ptr(&ar, ptr.get());
|
||||
}
|
||||
|
||||
//! Saving std::shared_ptr for polymorphic types, not abstract
|
||||
template <class Archive, class T> inline
|
||||
typename std::enable_if<std::is_polymorphic<T>::value && !std::is_abstract<T>::value, void>::type
|
||||
CEREAL_SAVE_FUNCTION_NAME( Archive & ar, std::shared_ptr<T> const & ptr )
|
||||
{
|
||||
if(!ptr)
|
||||
{
|
||||
// same behavior as nullptr in memory implementation
|
||||
ar( CEREAL_NVP_("polymorphic_id", std::uint32_t(0)) );
|
||||
return;
|
||||
}
|
||||
|
||||
std::type_info const & ptrinfo = typeid(*ptr.get());
|
||||
static std::type_info const & tinfo = typeid(T);
|
||||
|
||||
if(ptrinfo == tinfo)
|
||||
{
|
||||
// The 2nd msb signals that the following pointer does not need to be
|
||||
// cast with our polymorphic machinery
|
||||
ar( CEREAL_NVP_("polymorphic_id", detail::msb2_32bit) );
|
||||
|
||||
ar( CEREAL_NVP_("ptr_wrapper", memory_detail::make_ptr_wrapper(ptr)) );
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
auto & bindingMap = detail::StaticObject<detail::OutputBindingMap<Archive>>::getInstance().map;
|
||||
|
||||
auto binding = bindingMap.find(std::type_index(ptrinfo));
|
||||
if(binding == bindingMap.end())
|
||||
UNREGISTERED_POLYMORPHIC_EXCEPTION(save, cereal::util::demangle(ptrinfo.name()))
|
||||
|
||||
binding->second.shared_ptr(&ar, ptr.get());
|
||||
}
|
||||
|
||||
//! Loading std::shared_ptr for polymorphic types
|
||||
template <class Archive, class T> inline
|
||||
typename std::enable_if<std::is_polymorphic<T>::value, void>::type
|
||||
CEREAL_LOAD_FUNCTION_NAME( Archive & ar, std::shared_ptr<T> & ptr )
|
||||
{
|
||||
std::uint32_t nameid;
|
||||
ar( CEREAL_NVP_("polymorphic_id", nameid) );
|
||||
|
||||
// Check to see if we can skip all of this polymorphism business
|
||||
if(polymorphic_detail::serialize_wrapper(ar, ptr, nameid))
|
||||
return;
|
||||
|
||||
auto binding = polymorphic_detail::getInputBinding(ar, nameid);
|
||||
std::shared_ptr<void> result;
|
||||
binding.shared_ptr(&ar, result);
|
||||
ptr = std::static_pointer_cast<T>(result);
|
||||
}
|
||||
|
||||
//! Saving std::weak_ptr for polymorphic types
|
||||
template <class Archive, class T> inline
|
||||
typename std::enable_if<std::is_polymorphic<T>::value, void>::type
|
||||
CEREAL_SAVE_FUNCTION_NAME( Archive & ar, std::weak_ptr<T> const & ptr )
|
||||
{
|
||||
auto const sptr = ptr.lock();
|
||||
ar( CEREAL_NVP_("locked_ptr", sptr) );
|
||||
}
|
||||
|
||||
//! Loading std::weak_ptr for polymorphic types
|
||||
template <class Archive, class T> inline
|
||||
typename std::enable_if<std::is_polymorphic<T>::value, void>::type
|
||||
CEREAL_LOAD_FUNCTION_NAME( Archive & ar, std::weak_ptr<T> & ptr )
|
||||
{
|
||||
std::shared_ptr<T> sptr;
|
||||
ar( CEREAL_NVP_("locked_ptr", sptr) );
|
||||
ptr = sptr;
|
||||
}
|
||||
|
||||
//! Saving std::unique_ptr for polymorphic types that are abstract
|
||||
template <class Archive, class T, class D> inline
|
||||
typename std::enable_if<std::is_polymorphic<T>::value && std::is_abstract<T>::value, void>::type
|
||||
CEREAL_SAVE_FUNCTION_NAME( Archive & ar, std::unique_ptr<T, D> const & ptr )
|
||||
{
|
||||
if(!ptr)
|
||||
{
|
||||
// same behavior as nullptr in memory implementation
|
||||
ar( CEREAL_NVP_("polymorphic_id", std::uint32_t(0)) );
|
||||
return;
|
||||
}
|
||||
|
||||
std::type_info const & ptrinfo = typeid(*ptr.get());
|
||||
// ptrinfo can never be equal to T info since we can't have an instance
|
||||
// of an abstract object
|
||||
// this implies we need to do the lookup
|
||||
|
||||
auto & bindingMap = detail::StaticObject<detail::OutputBindingMap<Archive>>::getInstance().map;
|
||||
|
||||
auto binding = bindingMap.find(std::type_index(ptrinfo));
|
||||
if(binding == bindingMap.end())
|
||||
UNREGISTERED_POLYMORPHIC_EXCEPTION(save, cereal::util::demangle(ptrinfo.name()))
|
||||
|
||||
binding->second.unique_ptr(&ar, ptr.get());
|
||||
}
|
||||
|
||||
//! Saving std::unique_ptr for polymorphic types, not abstract
|
||||
template <class Archive, class T, class D> inline
|
||||
typename std::enable_if<std::is_polymorphic<T>::value && !std::is_abstract<T>::value, void>::type
|
||||
CEREAL_SAVE_FUNCTION_NAME( Archive & ar, std::unique_ptr<T, D> const & ptr )
|
||||
{
|
||||
if(!ptr)
|
||||
{
|
||||
// same behavior as nullptr in memory implementation
|
||||
ar( CEREAL_NVP_("polymorphic_id", std::uint32_t(0)) );
|
||||
return;
|
||||
}
|
||||
|
||||
std::type_info const & ptrinfo = typeid(*ptr.get());
|
||||
static std::type_info const & tinfo = typeid(T);
|
||||
|
||||
if(ptrinfo == tinfo)
|
||||
{
|
||||
// The 2nd msb signals that the following pointer does not need to be
|
||||
// cast with our polymorphic machinery
|
||||
ar( CEREAL_NVP_("polymorphic_id", detail::msb2_32bit) );
|
||||
|
||||
ar( CEREAL_NVP_("ptr_wrapper", memory_detail::make_ptr_wrapper(ptr)) );
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
auto & bindingMap = detail::StaticObject<detail::OutputBindingMap<Archive>>::getInstance().map;
|
||||
|
||||
auto binding = bindingMap.find(std::type_index(ptrinfo));
|
||||
if(binding == bindingMap.end())
|
||||
UNREGISTERED_POLYMORPHIC_EXCEPTION(save, cereal::util::demangle(ptrinfo.name()))
|
||||
|
||||
binding->second.unique_ptr(&ar, ptr.get());
|
||||
}
|
||||
|
||||
//! Loading std::unique_ptr, case when user provides load_and_construct for polymorphic types
|
||||
template <class Archive, class T, class D> inline
|
||||
typename std::enable_if<std::is_polymorphic<T>::value, void>::type
|
||||
CEREAL_LOAD_FUNCTION_NAME( Archive & ar, std::unique_ptr<T, D> & ptr )
|
||||
{
|
||||
std::uint32_t nameid;
|
||||
ar( CEREAL_NVP_("polymorphic_id", nameid) );
|
||||
|
||||
// Check to see if we can skip all of this polymorphism business
|
||||
if(polymorphic_detail::serialize_wrapper(ar, ptr, nameid))
|
||||
return;
|
||||
|
||||
auto binding = polymorphic_detail::getInputBinding(ar, nameid);
|
||||
std::unique_ptr<void, ::cereal::detail::EmptyDeleter<void>> result;
|
||||
binding.unique_ptr(&ar, result);
|
||||
ptr.reset(static_cast<T*>(result.release()));
|
||||
}
|
||||
|
||||
#undef UNREGISTERED_POLYMORPHIC_EXCEPTION
|
||||
} // namespace cereal
|
||||
#endif // CEREAL_TYPES_POLYMORPHIC_HPP_
|
||||
130
libs/cereal/cereal/types/queue.hpp
Normal file
130
libs/cereal/cereal/types/queue.hpp
Normal file
@ -0,0 +1,130 @@
|
||||
/*! \file queue.hpp
|
||||
\brief Support for types found in \<queue\>
|
||||
\ingroup STLSupport */
|
||||
/*
|
||||
Copyright (c) 2014, Randolph Voorhies, Shane Grant
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of cereal nor the
|
||||
names of its contributors may be used to endorse or promote products
|
||||
derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL RANDOLPH VOORHIES OR SHANE GRANT BE LIABLE FOR ANY
|
||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
#ifndef CEREAL_TYPES_QUEUE_HPP_
|
||||
#define CEREAL_TYPES_QUEUE_HPP_
|
||||
|
||||
#include <cereal/details/helpers.hpp>
|
||||
#include <queue>
|
||||
|
||||
// The default container for queue is deque, so let's include that too
|
||||
#include <cereal/types/deque.hpp>
|
||||
|
||||
namespace cereal
|
||||
{
|
||||
namespace queue_detail
|
||||
{
|
||||
//! Allows access to the protected container in queue
|
||||
/*! @internal */
|
||||
template <class T, class C> inline
|
||||
C const & container( std::queue<T, C> const & queue )
|
||||
{
|
||||
struct H : public std::queue<T, C>
|
||||
{
|
||||
static C const & get( std::queue<T, C> const & q )
|
||||
{
|
||||
return q.*(&H::c);
|
||||
}
|
||||
};
|
||||
|
||||
return H::get( queue );
|
||||
}
|
||||
|
||||
//! Allows access to the protected container in priority queue
|
||||
/*! @internal */
|
||||
template <class T, class C, class Comp> inline
|
||||
C const & container( std::priority_queue<T, C, Comp> const & priority_queue )
|
||||
{
|
||||
struct H : public std::priority_queue<T, C, Comp>
|
||||
{
|
||||
static C const & get( std::priority_queue<T, C, Comp> const & pq )
|
||||
{
|
||||
return pq.*(&H::c);
|
||||
}
|
||||
};
|
||||
|
||||
return H::get( priority_queue );
|
||||
}
|
||||
|
||||
//! Allows access to the protected comparator in priority queue
|
||||
/*! @internal */
|
||||
template <class T, class C, class Comp> inline
|
||||
Comp const & comparator( std::priority_queue<T, C, Comp> const & priority_queue )
|
||||
{
|
||||
struct H : public std::priority_queue<T, C, Comp>
|
||||
{
|
||||
static Comp const & get( std::priority_queue<T, C, Comp> const & pq )
|
||||
{
|
||||
return pq.*(&H::comp);
|
||||
}
|
||||
};
|
||||
|
||||
return H::get( priority_queue );
|
||||
}
|
||||
}
|
||||
|
||||
//! Saving for std::queue
|
||||
template <class Archive, class T, class C> inline
|
||||
void CEREAL_SAVE_FUNCTION_NAME( Archive & ar, std::queue<T, C> const & queue )
|
||||
{
|
||||
ar( CEREAL_NVP_("container", queue_detail::container( queue )) );
|
||||
}
|
||||
|
||||
//! Loading for std::queue
|
||||
template <class Archive, class T, class C> inline
|
||||
void CEREAL_LOAD_FUNCTION_NAME( Archive & ar, std::queue<T, C> & queue )
|
||||
{
|
||||
C container;
|
||||
ar( CEREAL_NVP_("container", container) );
|
||||
queue = std::queue<T, C>( std::move( container ) );
|
||||
}
|
||||
|
||||
//! Saving for std::priority_queue
|
||||
template <class Archive, class T, class C, class Comp> inline
|
||||
void CEREAL_SAVE_FUNCTION_NAME( Archive & ar, std::priority_queue<T, C, Comp> const & priority_queue )
|
||||
{
|
||||
ar( CEREAL_NVP_("comparator", queue_detail::comparator( priority_queue )) );
|
||||
ar( CEREAL_NVP_("container", queue_detail::container( priority_queue )) );
|
||||
}
|
||||
|
||||
//! Loading for std::priority_queue
|
||||
template <class Archive, class T, class C, class Comp> inline
|
||||
void CEREAL_LOAD_FUNCTION_NAME( Archive & ar, std::priority_queue<T, C, Comp> & priority_queue )
|
||||
{
|
||||
Comp comparator;
|
||||
ar( CEREAL_NVP_("comparator", comparator) );
|
||||
|
||||
C container;
|
||||
ar( CEREAL_NVP_("container", container) );
|
||||
|
||||
priority_queue = std::priority_queue<T, C, Comp>( comparator, std::move( container ) );
|
||||
}
|
||||
} // namespace cereal
|
||||
|
||||
#endif // CEREAL_TYPES_QUEUE_HPP_
|
||||
103
libs/cereal/cereal/types/set.hpp
Normal file
103
libs/cereal/cereal/types/set.hpp
Normal file
@ -0,0 +1,103 @@
|
||||
/*! \file set.hpp
|
||||
\brief Support for types found in \<set\>
|
||||
\ingroup STLSupport */
|
||||
/*
|
||||
Copyright (c) 2014, Randolph Voorhies, Shane Grant
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of cereal nor the
|
||||
names of its contributors may be used to endorse or promote products
|
||||
derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL RANDOLPH VOORHIES OR SHANE GRANT BE LIABLE FOR ANY
|
||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
#ifndef CEREAL_TYPES_SET_HPP_
|
||||
#define CEREAL_TYPES_SET_HPP_
|
||||
|
||||
#include <cereal/cereal.hpp>
|
||||
#include <set>
|
||||
|
||||
namespace cereal
|
||||
{
|
||||
namespace set_detail
|
||||
{
|
||||
//! @internal
|
||||
template <class Archive, class SetT> inline
|
||||
void save( Archive & ar, SetT const & set )
|
||||
{
|
||||
ar( make_size_tag( static_cast<size_type>(set.size()) ) );
|
||||
|
||||
for( const auto & i : set )
|
||||
ar( i );
|
||||
}
|
||||
|
||||
//! @internal
|
||||
template <class Archive, class SetT> inline
|
||||
void load( Archive & ar, SetT & set )
|
||||
{
|
||||
size_type size;
|
||||
ar( make_size_tag( size ) );
|
||||
|
||||
set.clear();
|
||||
|
||||
auto hint = set.begin();
|
||||
for( size_type i = 0; i < size; ++i )
|
||||
{
|
||||
typename SetT::key_type key;
|
||||
|
||||
ar( key );
|
||||
#ifdef CEREAL_OLDER_GCC
|
||||
hint = set.insert( hint, std::move( key ) );
|
||||
#else // NOT CEREAL_OLDER_GCC
|
||||
hint = set.emplace_hint( hint, std::move( key ) );
|
||||
#endif // NOT CEREAL_OLDER_GCC
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//! Saving for std::set
|
||||
template <class Archive, class K, class C, class A> inline
|
||||
void CEREAL_SAVE_FUNCTION_NAME( Archive & ar, std::set<K, C, A> const & set )
|
||||
{
|
||||
set_detail::save( ar, set );
|
||||
}
|
||||
|
||||
//! Loading for std::set
|
||||
template <class Archive, class K, class C, class A> inline
|
||||
void CEREAL_LOAD_FUNCTION_NAME( Archive & ar, std::set<K, C, A> & set )
|
||||
{
|
||||
set_detail::load( ar, set );
|
||||
}
|
||||
|
||||
//! Saving for std::multiset
|
||||
template <class Archive, class K, class C, class A> inline
|
||||
void CEREAL_SAVE_FUNCTION_NAME( Archive & ar, std::multiset<K, C, A> const & multiset )
|
||||
{
|
||||
set_detail::save( ar, multiset );
|
||||
}
|
||||
|
||||
//! Loading for std::multiset
|
||||
template <class Archive, class K, class C, class A> inline
|
||||
void CEREAL_LOAD_FUNCTION_NAME( Archive & ar, std::multiset<K, C, A> & multiset )
|
||||
{
|
||||
set_detail::load( ar, multiset );
|
||||
}
|
||||
} // namespace cereal
|
||||
|
||||
#endif // CEREAL_TYPES_SET_HPP_
|
||||
76
libs/cereal/cereal/types/stack.hpp
Normal file
76
libs/cereal/cereal/types/stack.hpp
Normal file
@ -0,0 +1,76 @@
|
||||
/*! \file stack.hpp
|
||||
\brief Support for types found in \<stack\>
|
||||
\ingroup STLSupport */
|
||||
/*
|
||||
Copyright (c) 2014, Randolph Voorhies, Shane Grant
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of cereal nor the
|
||||
names of its contributors may be used to endorse or promote products
|
||||
derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL RANDOLPH VOORHIES OR SHANE GRANT BE LIABLE FOR ANY
|
||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
#ifndef CEREAL_TYPES_STACK_HPP_
|
||||
#define CEREAL_TYPES_STACK_HPP_
|
||||
|
||||
#include <cereal/cereal.hpp>
|
||||
#include <stack>
|
||||
|
||||
// The default container for stack is deque, so let's include that too
|
||||
#include <cereal/types/deque.hpp>
|
||||
|
||||
namespace cereal
|
||||
{
|
||||
namespace stack_detail
|
||||
{
|
||||
//! Allows access to the protected container in stack
|
||||
template <class T, class C> inline
|
||||
C const & container( std::stack<T, C> const & stack )
|
||||
{
|
||||
struct H : public std::stack<T, C>
|
||||
{
|
||||
static C const & get( std::stack<T, C> const & s )
|
||||
{
|
||||
return s.*(&H::c);
|
||||
}
|
||||
};
|
||||
|
||||
return H::get( stack );
|
||||
}
|
||||
}
|
||||
|
||||
//! Saving for std::stack
|
||||
template <class Archive, class T, class C> inline
|
||||
void CEREAL_SAVE_FUNCTION_NAME( Archive & ar, std::stack<T, C> const & stack )
|
||||
{
|
||||
ar( CEREAL_NVP_("container", stack_detail::container( stack )) );
|
||||
}
|
||||
|
||||
//! Loading for std::stack
|
||||
template <class Archive, class T, class C> inline
|
||||
void CEREAL_LOAD_FUNCTION_NAME( Archive & ar, std::stack<T, C> & stack )
|
||||
{
|
||||
C container;
|
||||
ar( CEREAL_NVP_("container", container) );
|
||||
stack = std::stack<T, C>( std::move( container ) );
|
||||
}
|
||||
} // namespace cereal
|
||||
|
||||
#endif // CEREAL_TYPES_STACK_HPP_
|
||||
61
libs/cereal/cereal/types/string.hpp
Normal file
61
libs/cereal/cereal/types/string.hpp
Normal file
@ -0,0 +1,61 @@
|
||||
/*! \file string.hpp
|
||||
\brief Support for types found in \<string\>
|
||||
\ingroup STLSupport */
|
||||
/*
|
||||
Copyright (c) 2014, Randolph Voorhies, Shane Grant
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of cereal nor the
|
||||
names of its contributors may be used to endorse or promote products
|
||||
derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL RANDOLPH VOORHIES OR SHANE GRANT BE LIABLE FOR ANY
|
||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
#ifndef CEREAL_TYPES_STRING_HPP_
|
||||
#define CEREAL_TYPES_STRING_HPP_
|
||||
|
||||
#include <cereal/cereal.hpp>
|
||||
#include <string>
|
||||
|
||||
namespace cereal
|
||||
{
|
||||
//! Serialization for basic_string types, if binary data is supported
|
||||
template<class Archive, class CharT, class Traits, class Alloc> inline
|
||||
typename std::enable_if<traits::is_output_serializable<BinaryData<CharT>, Archive>::value, void>::type
|
||||
CEREAL_SAVE_FUNCTION_NAME(Archive & ar, std::basic_string<CharT, Traits, Alloc> const & str)
|
||||
{
|
||||
// Save number of chars + the data
|
||||
ar( make_size_tag( static_cast<size_type>(str.size()) ) );
|
||||
ar( binary_data( str.data(), str.size() * sizeof(CharT) ) );
|
||||
}
|
||||
|
||||
//! Serialization for basic_string types, if binary data is supported
|
||||
template<class Archive, class CharT, class Traits, class Alloc> inline
|
||||
typename std::enable_if<traits::is_input_serializable<BinaryData<CharT>, Archive>::value, void>::type
|
||||
CEREAL_LOAD_FUNCTION_NAME(Archive & ar, std::basic_string<CharT, Traits, Alloc> & str)
|
||||
{
|
||||
size_type size;
|
||||
ar( make_size_tag( size ) );
|
||||
str.resize(static_cast<std::size_t>(size));
|
||||
ar( binary_data( const_cast<CharT *>( str.data() ), static_cast<std::size_t>(size) * sizeof(CharT) ) );
|
||||
}
|
||||
} // namespace cereal
|
||||
|
||||
#endif // CEREAL_TYPES_STRING_HPP_
|
||||
|
||||
123
libs/cereal/cereal/types/tuple.hpp
Normal file
123
libs/cereal/cereal/types/tuple.hpp
Normal file
@ -0,0 +1,123 @@
|
||||
/*! \file tuple.hpp
|
||||
\brief Support for types found in \<tuple\>
|
||||
\ingroup STLSupport */
|
||||
/*
|
||||
Copyright (c) 2014, Randolph Voorhies, Shane Grant
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of cereal nor the
|
||||
names of its contributors may be used to endorse or promote products
|
||||
derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL RANDOLPH VOORHIES OR SHANE GRANT BE LIABLE FOR ANY
|
||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
#ifndef CEREAL_TYPES_TUPLE_HPP_
|
||||
#define CEREAL_TYPES_TUPLE_HPP_
|
||||
|
||||
#include <cereal/cereal.hpp>
|
||||
#include <tuple>
|
||||
|
||||
namespace cereal
|
||||
{
|
||||
namespace tuple_detail
|
||||
{
|
||||
//! Creates a c string from a sequence of characters
|
||||
/*! The c string created will alwas be prefixed by "tuple_element"
|
||||
Based on code from: http://stackoverflow/a/20973438/710791
|
||||
@internal */
|
||||
template<char...Cs>
|
||||
struct char_seq_to_c_str
|
||||
{
|
||||
static const int size = 14;// Size of array for the word: tuple_element
|
||||
typedef const char (&arr_type)[sizeof...(Cs) + size];
|
||||
static const char str[sizeof...(Cs) + size];
|
||||
};
|
||||
|
||||
// the word tuple_element plus a number
|
||||
//! @internal
|
||||
template<char...Cs>
|
||||
const char char_seq_to_c_str<Cs...>::str[sizeof...(Cs) + size] =
|
||||
{'t','u','p','l','e','_','e','l','e','m','e','n','t', Cs..., '\0'};
|
||||
|
||||
//! Converts a number into a sequence of characters
|
||||
/*! @tparam Q The quotient of dividing the original number by 10
|
||||
@tparam R The remainder of dividing the original number by 10
|
||||
@tparam C The sequence built so far
|
||||
@internal */
|
||||
template <size_t Q, size_t R, char ... C>
|
||||
struct to_string_impl
|
||||
{
|
||||
using type = typename to_string_impl<Q/10, Q%10, R+'0', C...>::type;
|
||||
};
|
||||
|
||||
//! Base case with no quotient
|
||||
/*! @internal */
|
||||
template <size_t R, char ... C>
|
||||
struct to_string_impl<0, R, C...>
|
||||
{
|
||||
using type = char_seq_to_c_str<R+'0', C...>;
|
||||
};
|
||||
|
||||
//! Generates a c string for a given index of a tuple
|
||||
/*! Example use:
|
||||
@code{cpp}
|
||||
tuple_element_name<3>::c_str();// returns "tuple_element3"
|
||||
@endcode
|
||||
@internal */
|
||||
template<size_t T>
|
||||
struct tuple_element_name
|
||||
{
|
||||
using type = typename to_string_impl<T/10, T%10>::type;
|
||||
static const typename type::arr_type c_str(){ return type::str; };
|
||||
};
|
||||
|
||||
// unwinds a tuple to save it
|
||||
//! @internal
|
||||
template <size_t Height>
|
||||
struct serialize
|
||||
{
|
||||
template <class Archive, class ... Types> inline
|
||||
static void apply( Archive & ar, std::tuple<Types...> & tuple )
|
||||
{
|
||||
serialize<Height - 1>::template apply( ar, tuple );
|
||||
ar( CEREAL_NVP_(tuple_element_name<Height - 1>::c_str(),
|
||||
std::get<Height - 1>( tuple )) );
|
||||
}
|
||||
};
|
||||
|
||||
// Zero height specialization - nothing to do here
|
||||
//! @internal
|
||||
template <>
|
||||
struct serialize<0>
|
||||
{
|
||||
template <class Archive, class ... Types> inline
|
||||
static void apply( Archive &, std::tuple<Types...> & )
|
||||
{ }
|
||||
};
|
||||
}
|
||||
|
||||
//! Serializing for std::tuple
|
||||
template <class Archive, class ... Types> inline
|
||||
void CEREAL_SERIALIZE_FUNCTION_NAME( Archive & ar, std::tuple<Types...> & tuple )
|
||||
{
|
||||
tuple_detail::serialize<std::tuple_size<std::tuple<Types...>>::value>::template apply( ar, tuple );
|
||||
}
|
||||
} // namespace cereal
|
||||
|
||||
#endif // CEREAL_TYPES_TUPLE_HPP_
|
||||
100
libs/cereal/cereal/types/unordered_map.hpp
Normal file
100
libs/cereal/cereal/types/unordered_map.hpp
Normal file
@ -0,0 +1,100 @@
|
||||
/*! \file unordered_map.hpp
|
||||
\brief Support for types found in \<unordered_map\>
|
||||
\ingroup STLSupport */
|
||||
/*
|
||||
Copyright (c) 2014, Randolph Voorhies, Shane Grant
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of cereal nor the
|
||||
names of its contributors may be used to endorse or promote products
|
||||
derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL RANDOLPH VOORHIES OR SHANE GRANT BE LIABLE FOR ANY
|
||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
#ifndef CEREAL_TYPES_UNORDERED_MAP_HPP_
|
||||
#define CEREAL_TYPES_UNORDERED_MAP_HPP_
|
||||
|
||||
#include <cereal/cereal.hpp>
|
||||
#include <unordered_map>
|
||||
|
||||
namespace cereal
|
||||
{
|
||||
namespace unordered_map_detail
|
||||
{
|
||||
//! @internal
|
||||
template <class Archive, class MapT> inline
|
||||
void save( Archive & ar, MapT const & map )
|
||||
{
|
||||
ar( make_size_tag( static_cast<size_type>(map.size()) ) );
|
||||
|
||||
for( const auto & i : map )
|
||||
ar( make_map_item(i.first, i.second) );
|
||||
}
|
||||
|
||||
//! @internal
|
||||
template <class Archive, class MapT> inline
|
||||
void load( Archive & ar, MapT & map )
|
||||
{
|
||||
size_type size;
|
||||
ar( make_size_tag( size ) );
|
||||
|
||||
map.clear();
|
||||
map.reserve( static_cast<std::size_t>( size ) );
|
||||
|
||||
for( size_type i = 0; i < size; ++i )
|
||||
{
|
||||
typename MapT::key_type key;
|
||||
typename MapT::mapped_type value;
|
||||
|
||||
ar( make_map_item(key, value) );
|
||||
map.emplace( std::move( key ), std::move( value ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//! Saving for std::unordered_map
|
||||
template <class Archive, class K, class T, class H, class KE, class A> inline
|
||||
void CEREAL_SAVE_FUNCTION_NAME( Archive & ar, std::unordered_map<K, T, H, KE, A> const & unordered_map )
|
||||
{
|
||||
unordered_map_detail::save( ar, unordered_map );
|
||||
}
|
||||
|
||||
//! Loading for std::unordered_map
|
||||
template <class Archive, class K, class T, class H, class KE, class A> inline
|
||||
void CEREAL_LOAD_FUNCTION_NAME( Archive & ar, std::unordered_map<K, T, H, KE, A> & unordered_map )
|
||||
{
|
||||
unordered_map_detail::load( ar, unordered_map );
|
||||
}
|
||||
|
||||
//! Saving for std::unordered_multimap
|
||||
template <class Archive, class K, class T, class H, class KE, class A> inline
|
||||
void CEREAL_SAVE_FUNCTION_NAME( Archive & ar, std::unordered_multimap<K, T, H, KE, A> const & unordered_multimap )
|
||||
{
|
||||
unordered_map_detail::save( ar, unordered_multimap );
|
||||
}
|
||||
|
||||
//! Loading for std::unordered_multimap
|
||||
template <class Archive, class K, class T, class H, class KE, class A> inline
|
||||
void CEREAL_LOAD_FUNCTION_NAME( Archive & ar, std::unordered_multimap<K, T, H, KE, A> & unordered_multimap )
|
||||
{
|
||||
unordered_map_detail::load( ar, unordered_multimap );
|
||||
}
|
||||
} // namespace cereal
|
||||
|
||||
#endif // CEREAL_TYPES_UNORDERED_MAP_HPP_
|
||||
99
libs/cereal/cereal/types/unordered_set.hpp
Normal file
99
libs/cereal/cereal/types/unordered_set.hpp
Normal file
@ -0,0 +1,99 @@
|
||||
/*! \file unordered_set.hpp
|
||||
\brief Support for types found in \<unordered_set\>
|
||||
\ingroup STLSupport */
|
||||
/*
|
||||
Copyright (c) 2014, Randolph Voorhies, Shane Grant
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of cereal nor the
|
||||
names of its contributors may be used to endorse or promote products
|
||||
derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL RANDOLPH VOORHIES OR SHANE GRANT BE LIABLE FOR ANY
|
||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
#ifndef CEREAL_TYPES_UNORDERED_SET_HPP_
|
||||
#define CEREAL_TYPES_UNORDERED_SET_HPP_
|
||||
|
||||
#include <cereal/cereal.hpp>
|
||||
#include <unordered_set>
|
||||
|
||||
namespace cereal
|
||||
{
|
||||
namespace unordered_set_detail
|
||||
{
|
||||
//! @internal
|
||||
template <class Archive, class SetT> inline
|
||||
void save( Archive & ar, SetT const & set )
|
||||
{
|
||||
ar( make_size_tag( static_cast<size_type>(set.size()) ) );
|
||||
|
||||
for( const auto & i : set )
|
||||
ar( i );
|
||||
}
|
||||
|
||||
//! @internal
|
||||
template <class Archive, class SetT> inline
|
||||
void load( Archive & ar, SetT & set )
|
||||
{
|
||||
size_type size;
|
||||
ar( make_size_tag( size ) );
|
||||
|
||||
set.clear();
|
||||
set.reserve( static_cast<std::size_t>( size ) );
|
||||
|
||||
for( size_type i = 0; i < size; ++i )
|
||||
{
|
||||
typename SetT::key_type key;
|
||||
|
||||
ar( key );
|
||||
set.emplace( std::move( key ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//! Saving for std::unordered_set
|
||||
template <class Archive, class K, class H, class KE, class A> inline
|
||||
void CEREAL_SAVE_FUNCTION_NAME( Archive & ar, std::unordered_set<K, H, KE, A> const & unordered_set )
|
||||
{
|
||||
unordered_set_detail::save( ar, unordered_set );
|
||||
}
|
||||
|
||||
//! Loading for std::unordered_set
|
||||
template <class Archive, class K, class H, class KE, class A> inline
|
||||
void CEREAL_LOAD_FUNCTION_NAME( Archive & ar, std::unordered_set<K, H, KE, A> & unordered_set )
|
||||
{
|
||||
unordered_set_detail::load( ar, unordered_set );
|
||||
}
|
||||
|
||||
//! Saving for std::unordered_multiset
|
||||
template <class Archive, class K, class H, class KE, class A> inline
|
||||
void CEREAL_SAVE_FUNCTION_NAME( Archive & ar, std::unordered_multiset<K, H, KE, A> const & unordered_multiset )
|
||||
{
|
||||
unordered_set_detail::save( ar, unordered_multiset );
|
||||
}
|
||||
|
||||
//! Loading for std::unordered_multiset
|
||||
template <class Archive, class K, class H, class KE, class A> inline
|
||||
void CEREAL_LOAD_FUNCTION_NAME( Archive & ar, std::unordered_multiset<K, H, KE, A> & unordered_multiset )
|
||||
{
|
||||
unordered_set_detail::load( ar, unordered_multiset );
|
||||
}
|
||||
} // namespace cereal
|
||||
|
||||
#endif // CEREAL_TYPES_UNORDERED_SET_HPP_
|
||||
47
libs/cereal/cereal/types/utility.hpp
Normal file
47
libs/cereal/cereal/types/utility.hpp
Normal file
@ -0,0 +1,47 @@
|
||||
/*! \file utility.hpp
|
||||
\brief Support for types found in \<utility\>
|
||||
\ingroup STLSupport */
|
||||
/*
|
||||
Copyright (c) 2014, Randolph Voorhies, Shane Grant
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of cereal nor the
|
||||
names of its contributors may be used to endorse or promote products
|
||||
derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL RANDOLPH VOORHIES OR SHANE GRANT BE LIABLE FOR ANY
|
||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
#ifndef CEREAL_TYPES_UTILITY_HPP_
|
||||
#define CEREAL_TYPES_UTILITY_HPP_
|
||||
|
||||
#include <cereal/cereal.hpp>
|
||||
#include <utility>
|
||||
|
||||
namespace cereal
|
||||
{
|
||||
//! Serializing for std::pair
|
||||
template <class Archive, class T1, class T2> inline
|
||||
void CEREAL_SERIALIZE_FUNCTION_NAME( Archive & ar, std::pair<T1, T2> & pair )
|
||||
{
|
||||
ar( CEREAL_NVP_("first", pair.first),
|
||||
CEREAL_NVP_("second", pair.second) );
|
||||
}
|
||||
} // namespace cereal
|
||||
|
||||
#endif // CEREAL_TYPES_UTILITY_HPP_
|
||||
89
libs/cereal/cereal/types/valarray.hpp
Normal file
89
libs/cereal/cereal/types/valarray.hpp
Normal file
@ -0,0 +1,89 @@
|
||||
/*! \file valarray.hpp
|
||||
\brief Support for types found in \<valarray\>
|
||||
\ingroup STLSupport */
|
||||
|
||||
/*
|
||||
Copyright (c) 2014, Randolph Voorhies, Shane Grant
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of cereal nor the
|
||||
names of its contributors may be used to endorse or promote products
|
||||
derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL RANDOLPH VOORHIES OR SHANE GRANT BE LIABLE FOR ANY
|
||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef CEREAL_TYPES_VALARRAY_HPP_
|
||||
#define CEREAL_TYPES_VALARRAY_HPP_
|
||||
|
||||
#include <cereal/cereal.hpp>
|
||||
#include <valarray>
|
||||
|
||||
namespace cereal
|
||||
{
|
||||
//! Saving for std::valarray arithmetic types, using binary serialization, if supported
|
||||
template <class Archive, class T> inline
|
||||
typename std::enable_if<traits::is_output_serializable<BinaryData<T>, Archive>::value
|
||||
&& std::is_arithmetic<T>::value, void>::type
|
||||
CEREAL_SAVE_FUNCTION_NAME( Archive & ar, std::valarray<T> const & valarray )
|
||||
{
|
||||
ar( make_size_tag( static_cast<size_type>(valarray.size()) ) ); // number of elements
|
||||
ar( binary_data( &valarray[0], valarray.size() * sizeof(T) ) ); // &valarray[0] ok since guaranteed contiguous
|
||||
}
|
||||
|
||||
//! Loading for std::valarray arithmetic types, using binary serialization, if supported
|
||||
template <class Archive, class T> inline
|
||||
typename std::enable_if<traits::is_input_serializable<BinaryData<T>, Archive>::value
|
||||
&& std::is_arithmetic<T>::value, void>::type
|
||||
CEREAL_LOAD_FUNCTION_NAME( Archive & ar, std::valarray<T> & valarray )
|
||||
{
|
||||
size_type valarraySize;
|
||||
ar( make_size_tag( valarraySize ) );
|
||||
|
||||
valarray.resize( static_cast<std::size_t>( valarraySize ) );
|
||||
ar( binary_data( &valarray[0], static_cast<std::size_t>( valarraySize ) * sizeof(T) ) );
|
||||
}
|
||||
|
||||
//! Saving for std::valarray all other types
|
||||
template <class Archive, class T> inline
|
||||
typename std::enable_if<!traits::is_output_serializable<BinaryData<T>, Archive>::value
|
||||
|| !std::is_arithmetic<T>::value, void>::type
|
||||
CEREAL_SAVE_FUNCTION_NAME( Archive & ar, std::valarray<T> const & valarray )
|
||||
{
|
||||
ar( make_size_tag( static_cast<size_type>(valarray.size()) ) ); // number of elements
|
||||
for(auto && v : valarray)
|
||||
ar(v);
|
||||
}
|
||||
|
||||
//! Loading for std::valarray all other types
|
||||
template <class Archive, class T> inline
|
||||
typename std::enable_if<!traits::is_input_serializable<BinaryData<T>, Archive>::value
|
||||
|| !std::is_arithmetic<T>::value, void>::type
|
||||
CEREAL_LOAD_FUNCTION_NAME( Archive & ar, std::valarray<T> & valarray )
|
||||
{
|
||||
size_type valarraySize;
|
||||
ar( make_size_tag( valarraySize ) );
|
||||
|
||||
valarray.resize( static_cast<size_t>( valarraySize ) );
|
||||
for(auto && v : valarray)
|
||||
ar(v);
|
||||
}
|
||||
} // namespace cereal
|
||||
|
||||
#endif // CEREAL_TYPES_VALARRAY_HPP_
|
||||
112
libs/cereal/cereal/types/vector.hpp
Normal file
112
libs/cereal/cereal/types/vector.hpp
Normal file
@ -0,0 +1,112 @@
|
||||
/*! \file vector.hpp
|
||||
\brief Support for types found in \<vector\>
|
||||
\ingroup STLSupport */
|
||||
/*
|
||||
Copyright (c) 2014, Randolph Voorhies, Shane Grant
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of cereal nor the
|
||||
names of its contributors may be used to endorse or promote products
|
||||
derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL RANDOLPH VOORHIES OR SHANE GRANT BE LIABLE FOR ANY
|
||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
#ifndef CEREAL_TYPES_VECTOR_HPP_
|
||||
#define CEREAL_TYPES_VECTOR_HPP_
|
||||
|
||||
#include <cereal/cereal.hpp>
|
||||
#include <vector>
|
||||
|
||||
namespace cereal
|
||||
{
|
||||
//! Serialization for std::vectors of arithmetic (but not bool) using binary serialization, if supported
|
||||
template <class Archive, class T, class A> inline
|
||||
typename std::enable_if<traits::is_output_serializable<BinaryData<T>, Archive>::value
|
||||
&& std::is_arithmetic<T>::value && !std::is_same<T, bool>::value, void>::type
|
||||
CEREAL_SAVE_FUNCTION_NAME( Archive & ar, std::vector<T, A> const & vector )
|
||||
{
|
||||
ar( make_size_tag( static_cast<size_type>(vector.size()) ) ); // number of elements
|
||||
ar( binary_data( vector.data(), vector.size() * sizeof(T) ) );
|
||||
}
|
||||
|
||||
//! Serialization for std::vectors of arithmetic (but not bool) using binary serialization, if supported
|
||||
template <class Archive, class T, class A> inline
|
||||
typename std::enable_if<traits::is_input_serializable<BinaryData<T>, Archive>::value
|
||||
&& std::is_arithmetic<T>::value && !std::is_same<T, bool>::value, void>::type
|
||||
CEREAL_LOAD_FUNCTION_NAME( Archive & ar, std::vector<T, A> & vector )
|
||||
{
|
||||
size_type vectorSize;
|
||||
ar( make_size_tag( vectorSize ) );
|
||||
|
||||
vector.resize( static_cast<std::size_t>( vectorSize ) );
|
||||
ar( binary_data( vector.data(), static_cast<std::size_t>( vectorSize ) * sizeof(T) ) );
|
||||
}
|
||||
|
||||
//! Serialization for non-arithmetic vector types
|
||||
template <class Archive, class T, class A> inline
|
||||
typename std::enable_if<!traits::is_output_serializable<BinaryData<T>, Archive>::value
|
||||
|| !std::is_arithmetic<T>::value, void>::type
|
||||
CEREAL_SAVE_FUNCTION_NAME( Archive & ar, std::vector<T, A> const & vector )
|
||||
{
|
||||
ar( make_size_tag( static_cast<size_type>(vector.size()) ) ); // number of elements
|
||||
for(auto && v : vector)
|
||||
ar( v );
|
||||
}
|
||||
|
||||
//! Serialization for non-arithmetic vector types
|
||||
template <class Archive, class T, class A> inline
|
||||
typename std::enable_if<!traits::is_input_serializable<BinaryData<T>, Archive>::value
|
||||
|| !std::is_arithmetic<T>::value, void>::type
|
||||
CEREAL_LOAD_FUNCTION_NAME( Archive & ar, std::vector<T, A> & vector )
|
||||
{
|
||||
size_type size;
|
||||
ar( make_size_tag( size ) );
|
||||
|
||||
vector.resize( static_cast<std::size_t>( size ) );
|
||||
for(auto && v : vector)
|
||||
ar( v );
|
||||
}
|
||||
|
||||
//! Serialization for bool vector types
|
||||
template <class Archive, class A> inline
|
||||
void CEREAL_SAVE_FUNCTION_NAME( Archive & ar, std::vector<bool, A> const & vector )
|
||||
{
|
||||
ar( make_size_tag( static_cast<size_type>(vector.size()) ) ); // number of elements
|
||||
for(auto && v : vector)
|
||||
ar( static_cast<bool>(v) );
|
||||
}
|
||||
|
||||
//! Serialization for bool vector types
|
||||
template <class Archive, class A> inline
|
||||
void CEREAL_LOAD_FUNCTION_NAME( Archive & ar, std::vector<bool, A> & vector )
|
||||
{
|
||||
size_type size;
|
||||
ar( make_size_tag( size ) );
|
||||
|
||||
vector.resize( static_cast<std::size_t>( size ) );
|
||||
for(auto && v : vector)
|
||||
{
|
||||
bool b;
|
||||
ar( b );
|
||||
v = b;
|
||||
}
|
||||
}
|
||||
} // namespace cereal
|
||||
|
||||
#endif // CEREAL_TYPES_VECTOR_HPP_
|
||||
78
libs/libuv/.gitignore
vendored
Normal file
78
libs/libuv/.gitignore
vendored
Normal file
@ -0,0 +1,78 @@
|
||||
*.swp
|
||||
*.[oa]
|
||||
*.l[oa]
|
||||
*.opensdf
|
||||
*.orig
|
||||
*.pyc
|
||||
*.sdf
|
||||
*.suo
|
||||
.vs/
|
||||
*.VC.db
|
||||
*.VC.opendb
|
||||
core
|
||||
vgcore.*
|
||||
.buildstamp
|
||||
.dirstamp
|
||||
.deps/
|
||||
/.libs/
|
||||
/aclocal.m4
|
||||
/ar-lib
|
||||
/autom4te.cache/
|
||||
/compile
|
||||
/config.guess
|
||||
/config.log
|
||||
/config.status
|
||||
/config.sub
|
||||
/configure
|
||||
/depcomp
|
||||
/install-sh
|
||||
/libtool
|
||||
/libuv.a
|
||||
/libuv.dylib
|
||||
/libuv.pc
|
||||
/libuv.so
|
||||
/ltmain.sh
|
||||
/missing
|
||||
/test-driver
|
||||
Makefile
|
||||
Makefile.in
|
||||
|
||||
# Generated by gyp for android
|
||||
*.target.mk
|
||||
|
||||
/out/
|
||||
/build/gyp
|
||||
|
||||
/test/.libs/
|
||||
/test/run-tests
|
||||
/test/run-tests.exe
|
||||
/test/run-tests.dSYM
|
||||
/test/run-benchmarks
|
||||
/test/run-benchmarks.exe
|
||||
/test/run-benchmarks.dSYM
|
||||
|
||||
*.sln
|
||||
*.sln.cache
|
||||
*.ncb
|
||||
*.vcproj
|
||||
*.vcproj*.user
|
||||
*.vcxproj
|
||||
*.vcxproj.filters
|
||||
*.vcxproj.user
|
||||
_UpgradeReport_Files/
|
||||
UpgradeLog*.XML
|
||||
Debug
|
||||
Release
|
||||
ipch
|
||||
|
||||
# sphinx generated files
|
||||
/docs/build/
|
||||
|
||||
# Clion / IntelliJ project files
|
||||
/.idea/
|
||||
|
||||
*.xcodeproj
|
||||
*.xcworkspace
|
||||
|
||||
# make dist output
|
||||
libuv-*.tar.*
|
||||
40
libs/libuv/.mailmap
Normal file
40
libs/libuv/.mailmap
Normal file
@ -0,0 +1,40 @@
|
||||
Aaron Bieber <qbit@deftly.net> <deftly@gmail.com>
|
||||
Alan Gutierrez <alan@prettyrobots.com> <alan@blogometer.com>
|
||||
Andrius Bentkus <andrius.bentkus@gmail.com> <toxedvirus@gmail.com>
|
||||
Bert Belder <bertbelder@gmail.com> <info@2bs.nl>
|
||||
Bert Belder <bertbelder@gmail.com> <user@ChrUbuntu.(none)>
|
||||
Brandon Philips <brandon.philips@rackspace.com> <brandon@ifup.org>
|
||||
Brian White <mscdex@mscdex.net>
|
||||
Brian White <mscdex@mscdex.net> <mscdex@gmail.com>
|
||||
Caleb James DeLisle <cjd@hyperboria.ca> <cjd@cjdns.fr>
|
||||
Christoph Iserlohn <christoph.iserlohn@innoq.com>
|
||||
Devchandra Meetei Leishangthem <dlmeetei@gmail.com>
|
||||
Fedor Indutny <fedor.indutny@gmail.com> <fedor@indutny.com>
|
||||
Frank Denis <github@pureftpd.org>
|
||||
Imran Iqbal <imrani@ca.ibm.com> <imran@imraniqbal.org>
|
||||
Isaac Z. Schlueter <i@izs.me>
|
||||
Jason Williams <necmon@yahoo.com>
|
||||
Justin Venus <justin.venus@gmail.com> <justin.venus@orbitz.com>
|
||||
Keno Fischer <kenof@stanford.edu> <kfischer+github@college.harvard.edu>
|
||||
Keno Fischer <kenof@stanford.edu> <kfischer@college.harvard.edu>
|
||||
Leith Bade <leith@leithalweapon.geek.nz> <leith@mapbox.com>
|
||||
Leonard Hecker <leonard.hecker91@gmail.com> <leonard@hecker.io>
|
||||
Maciej Małecki <maciej.malecki@notimplemented.org> <me@mmalecki.com>
|
||||
Marc Schlaich <marc.schlaich@googlemail.com> <marc.schlaich@gmail.com>
|
||||
Michael <michael_dawson@ca.ibm.com>
|
||||
Michael Neumann <mneumann@think.localnet> <mneumann@ntecs.de>
|
||||
Nicholas Vavilov <vvnicholas@gmail.com>
|
||||
Rasmus Christian Pedersen <zerhacken@yahoo.com>
|
||||
Rasmus Christian Pedersen <zerhacken@yahoo.com> <ruysch@outlook.com>
|
||||
Robert Mustacchi <rm@joyent.com> <rm@fingolfin.org>
|
||||
Ryan Dahl <ryan@joyent.com> <ry@tinyclouds.org>
|
||||
Ryan Emery <seebees@gmail.com>
|
||||
Sam Roberts <vieuxtech@gmail.com> <sam@strongloop.com>
|
||||
San-Tai Hsu <vanilla@fatpipi.com>
|
||||
Santiago Gimeno <santiago.gimeno@quantion.es> <santiago.gimeno@gmail.com>
|
||||
Saúl Ibarra Corretgé <saghul@gmail.com>
|
||||
Shigeki Ohtsu <ohtsu@iij.ad.jp> <ohtsu@ohtsu.org>
|
||||
Timothy J. Fontaine <tjfontaine@gmail.com>
|
||||
Yasuhiro Matsumoto <mattn.jp@gmail.com>
|
||||
Yazhong Liu <yorkiefixer@gmail.com>
|
||||
Yuki Okumura <mjt@cltn.org>
|
||||
259
libs/libuv/AUTHORS
Normal file
259
libs/libuv/AUTHORS
Normal file
@ -0,0 +1,259 @@
|
||||
# Authors ordered by first contribution.
|
||||
Ryan Dahl <ryan@joyent.com>
|
||||
Bert Belder <bertbelder@gmail.com>
|
||||
Josh Roesslein <jroesslein@gmail.com>
|
||||
Alan Gutierrez <alan@prettyrobots.com>
|
||||
Joshua Peek <josh@joshpeek.com>
|
||||
Igor Zinkovsky <igorzi@microsoft.com>
|
||||
San-Tai Hsu <vanilla@fatpipi.com>
|
||||
Ben Noordhuis <info@bnoordhuis.nl>
|
||||
Henry Rawas <henryr@schakra.com>
|
||||
Robert Mustacchi <rm@joyent.com>
|
||||
Matt Stevens <matt@alloysoft.com>
|
||||
Paul Querna <pquerna@apache.org>
|
||||
Shigeki Ohtsu <ohtsu@iij.ad.jp>
|
||||
Tom Hughes <tom.hughes@palm.com>
|
||||
Peter Bright <drpizza@quiscalusmexicanus.org>
|
||||
Jeroen Janssen <jeroen.janssen@gmail.com>
|
||||
Andrea Lattuada <ndr.lattuada@gmail.com>
|
||||
Augusto Henrique Hentz <ahhentz@gmail.com>
|
||||
Clifford Heath <clifford.heath@gmail.com>
|
||||
Jorge Chamorro Bieling <jorge@jorgechamorro.com>
|
||||
Luis Lavena <luislavena@gmail.com>
|
||||
Matthew Sporleder <msporleder@gmail.com>
|
||||
Erick Tryzelaar <erick.tryzelaar@gmail.com>
|
||||
Isaac Z. Schlueter <i@izs.me>
|
||||
Pieter Noordhuis <pcnoordhuis@gmail.com>
|
||||
Marek Jelen <marek@jelen.biz>
|
||||
Fedor Indutny <fedor.indutny@gmail.com>
|
||||
Saúl Ibarra Corretgé <saghul@gmail.com>
|
||||
Felix Geisendörfer <felix@debuggable.com>
|
||||
Yuki Okumura <mjt@cltn.org>
|
||||
Roman Shtylman <shtylman@gmail.com>
|
||||
Frank Denis <github@pureftpd.org>
|
||||
Carter Allen <CarterA@opt-6.com>
|
||||
Tj Holowaychuk <tj@vision-media.ca>
|
||||
Shimon Doodkin <helpmepro1@gmail.com>
|
||||
Ryan Emery <seebees@gmail.com>
|
||||
Bruce Mitchener <bruce.mitchener@gmail.com>
|
||||
Maciej Małecki <maciej.malecki@notimplemented.org>
|
||||
Yasuhiro Matsumoto <mattn.jp@gmail.com>
|
||||
Daisuke Murase <typester@cpan.org>
|
||||
Paddy Byers <paddy.byers@gmail.com>
|
||||
Dan VerWeire <dverweire@gmail.com>
|
||||
Brandon Benvie <brandon@bbenvie.com>
|
||||
Brandon Philips <brandon.philips@rackspace.com>
|
||||
Nathan Rajlich <nathan@tootallnate.net>
|
||||
Charlie McConnell <charlie@charlieistheman.com>
|
||||
Vladimir Dronnikov <dronnikov@gmail.com>
|
||||
Aaron Bieber <qbit@deftly.net>
|
||||
Bulat Shakirzyanov <mallluhuct@gmail.com>
|
||||
Brian White <mscdex@mscdex.net>
|
||||
Erik Dubbelboer <erik@dubbelboer.com>
|
||||
Keno Fischer <kenof@stanford.edu>
|
||||
Ira Cooper <Ira.Cooper@mathworks.com>
|
||||
Andrius Bentkus <andrius.bentkus@gmail.com>
|
||||
Iñaki Baz Castillo <ibc@aliax.net>
|
||||
Mark Cavage <mark.cavage@joyent.com>
|
||||
George Yohng <georgegh@oss3d.com>
|
||||
Xidorn Quan <quanxunzhen@gmail.com>
|
||||
Roman Neuhauser <rneuhauser@suse.cz>
|
||||
Shuhei Tanuma <shuhei.tanuma@gmail.com>
|
||||
Bryan Cantrill <bcantrill@acm.org>
|
||||
Trond Norbye <trond.norbye@gmail.com>
|
||||
Tim Holy <holy@wustl.edu>
|
||||
Prancesco Pertugio <meh@schizofreni.co>
|
||||
Leonard Hecker <leonard.hecker91@gmail.com>
|
||||
Andrew Paprocki <andrew@ishiboo.com>
|
||||
Luigi Grilli <luigi.grilli@gmail.com>
|
||||
Shannen Saez <shannenlaptop@gmail.com>
|
||||
Artur Adib <arturadib@gmail.com>
|
||||
Hiroaki Nakamura <hnakamur@gmail.com>
|
||||
Ting-Yu Lin <ph.minamo@cytisan.com>
|
||||
Stephen Gallagher <sgallagh@redhat.com>
|
||||
Shane Holloway <shane.holloway@ieee.org>
|
||||
Andrew Shaffer <darawk@gmail.com>
|
||||
Vlad Tudose <vlad.tudose@intel.com>
|
||||
Ben Leslie <benno@benno.id.au>
|
||||
Tim Bradshaw <tfb@cley.com>
|
||||
Timothy J. Fontaine <tjfontaine@gmail.com>
|
||||
Marc Schlaich <marc.schlaich@googlemail.com>
|
||||
Brian Mazza <louseman@gmail.com>
|
||||
Elliot Saba <staticfloat@gmail.com>
|
||||
Ben Kelly <ben@wanderview.com>
|
||||
Nils Maier <maierman@web.de>
|
||||
Nicholas Vavilov <vvnicholas@gmail.com>
|
||||
Miroslav Bajtoš <miro.bajtos@gmail.com>
|
||||
Sean Silva <chisophugis@gmail.com>
|
||||
Wynn Wilkes <wynnw@movenetworks.com>
|
||||
Andrei Sedoi <bsnote@gmail.com>
|
||||
Alex Crichton <alex@alexcrichton.com>
|
||||
Brent Cook <brent@boundary.com>
|
||||
Brian Kaisner <bkize1@gmail.com>
|
||||
Luca Bruno <lucab@debian.org>
|
||||
Reini Urban <rurban@cpanel.net>
|
||||
Maks Naumov <maksqwe1@ukr.net>
|
||||
Sean Farrell <sean.farrell@rioki.org>
|
||||
Chris Bank <cbank@adobe.com>
|
||||
Geert Jansen <geertj@gmail.com>
|
||||
Christoph Iserlohn <christoph.iserlohn@innoq.com>
|
||||
Steven Kabbes <stevenkabbes@gmail.com>
|
||||
Alex Gaynor <alex.gaynor@gmail.com>
|
||||
huxingyi <huxingyi@msn.com>
|
||||
Tenor Biel <tenorbiel@gmail.com>
|
||||
Andrej Manduch <AManduch@gmail.com>
|
||||
Joshua Neuheisel <joshua@neuheisel.us>
|
||||
Alexis Campailla <alexis@janeasystems.com>
|
||||
Yazhong Liu <yorkiefixer@gmail.com>
|
||||
Sam Roberts <vieuxtech@gmail.com>
|
||||
River Tarnell <river@loreley.flyingparchment.org.uk>
|
||||
Nathan Sweet <nathanjsweet@gmail.com>
|
||||
Trevor Norris <trev.norris@gmail.com>
|
||||
Oguz Bastemur <obastemur@gmail.com>
|
||||
Dylan Cali <calid1984@gmail.com>
|
||||
Austin Foxley <austinf@cetoncorp.com>
|
||||
Benjamin Saunders <ben.e.saunders@gmail.com>
|
||||
Geoffry Song <goffrie@gmail.com>
|
||||
Rasmus Christian Pedersen <ruysch@outlook.com>
|
||||
William Light <wrl@illest.net>
|
||||
Oleg Efimov <o.efimov@corp.badoo.com>
|
||||
Lars Gierth <larsg@systemli.org>
|
||||
Rasmus Christian Pedersen <zerhacken@yahoo.com>
|
||||
Justin Venus <justin.venus@gmail.com>
|
||||
Kristian Evensen <kristian.evensen@gmail.com>
|
||||
Linus Mårtensson <linus.martensson@sonymobile.com>
|
||||
Navaneeth Kedaram Nambiathan <navaneethkn@gmail.com>
|
||||
Yorkie <yorkiefixer@gmail.com>
|
||||
StarWing <weasley.wx@gmail.com>
|
||||
thierry-FreeBSD <thierry@FreeBSD.org>
|
||||
Isaiah Norton <isaiah.norton@gmail.com>
|
||||
Raul Martins <raulms.martins@gmail.com>
|
||||
David Capello <davidcapello@gmail.com>
|
||||
Paul Tan <pyokagan@gmail.com>
|
||||
Javier Hernández <jhernandez@emergya.com>
|
||||
Tonis Tiigi <tonistiigi@gmail.com>
|
||||
Norio Kobota <nori.0428@gmail.com>
|
||||
李港平 <chopdown@gmail.com>
|
||||
Chernyshev Viacheslav <astellar@ro.ru>
|
||||
Stephen von Takach <steve@advancedcontrol.com.au>
|
||||
JD Ballard <jd@pixelandline.com>
|
||||
Luka Perkov <luka.perkov@sartura.hr>
|
||||
Ryan Cole <ryan@rycole.com>
|
||||
HungMingWu <u9089000@gmail.com>
|
||||
Jay Satiro <raysatiro@yahoo.com>
|
||||
Leith Bade <leith@leithalweapon.geek.nz>
|
||||
Peter Atashian <retep998@gmail.com>
|
||||
Tim Cooper <tim.cooper@layeh.com>
|
||||
Caleb James DeLisle <cjd@hyperboria.ca>
|
||||
Jameson Nash <vtjnash@gmail.com>
|
||||
Graham Lee <ghmlee@ghmlee.com>
|
||||
Andrew Low <Andrew_Low@ca.ibm.com>
|
||||
Pavel Platto <hinidu@gmail.com>
|
||||
Tony Kelman <tony@kelman.net>
|
||||
John Firebaugh <john.firebaugh@gmail.com>
|
||||
lilohuang <lilohuang@hotmail.com>
|
||||
Paul Goldsmith <paul.goldsmith@aplink.net>
|
||||
Julien Gilli <julien.gilli@joyent.com>
|
||||
Michael Hudson-Doyle <michael.hudson@linaro.org>
|
||||
Recep ASLANTAS <m@recp.me>
|
||||
Rob Adams <readams@readams.net>
|
||||
Zachary Newman <znewman01@gmail.com>
|
||||
Robin Hahling <robin.hahling@gw-computing.net>
|
||||
Jeff Widman <jeff@jeffwidman.com>
|
||||
cjihrig <cjihrig@gmail.com>
|
||||
Tomasz Kołodziejski <tkolodziejski@mozilla.com>
|
||||
Unknown W. Brackets <checkins@unknownbrackets.org>
|
||||
Emmanuel Odeke <odeke@ualberta.ca>
|
||||
Mikhail Mukovnikov <yndi@me.com>
|
||||
Thorsten Lorenz <thlorenz@gmx.de>
|
||||
Yuri D'Elia <yuri.delia@eurac.edu>
|
||||
Manos Nikolaidis <manos@shadowrobot.com>
|
||||
Elijah Andrews <elijah@busbud.com>
|
||||
Michael Ira Krufky <m.krufky@samsung.com>
|
||||
Helge Deller <deller@gmx.de>
|
||||
Joey Geralnik <jgeralnik@gmail.com>
|
||||
Tim Caswell <tim@creationix.com>
|
||||
Logan Rosen <loganrosen@gmail.com>
|
||||
Kenneth Perry <thothonegan@gmail.com>
|
||||
John Marino <marino@FreeBSD.org>
|
||||
Alexey Melnichuk <mimir@newmail.ru>
|
||||
Johan Bergström <bugs@bergstroem.nu>
|
||||
Alex Mo <almosnow@gmail.com>
|
||||
Luis Martinez de Bartolome <lasote@gmail.com>
|
||||
Michael Penick <michael.penick@datastax.com>
|
||||
Michael <michael_dawson@ca.ibm.com>
|
||||
Massimiliano Torromeo <massimiliano.torromeo@gmail.com>
|
||||
TomCrypto <thomas.beneteau@yahoo.fr>
|
||||
Brett Vickers <brett@beevik.com>
|
||||
Ole André Vadla Ravnås <oleavr@gmail.com>
|
||||
Kazuho Oku <kazuhooku@gmail.com>
|
||||
Ryan Phillips <ryan.phillips@rackspace.com>
|
||||
Brian Green <briangreenery@gmail.com>
|
||||
Devchandra Meetei Leishangthem <dlmeetei@gmail.com>
|
||||
Corey Farrell <git@cfware.com>
|
||||
Per Nilsson <pni@qlik.com>
|
||||
Alan Rogers <alanjrogers@me.com>
|
||||
Daryl Haresign <github@daryl.haresign.com>
|
||||
Rui Abreu Ferreira <raf-ep@gmx.com>
|
||||
João Reis <reis@janeasystems.com>
|
||||
farblue68 <farblue68@gmail.com>
|
||||
Jason Williams <necmon@yahoo.com>
|
||||
Igor Soarez <igorsoarez@gmail.com>
|
||||
Miodrag Milanovic <mmicko@gmail.com>
|
||||
Cheng Zhao <zcbenz@gmail.com>
|
||||
Michael Neumann <mneumann@think.localnet>
|
||||
Stefano Cristiano <stefanocristiano82@gmail.com>
|
||||
heshamsafi <hesham.safi.eldeen@gmail.com>
|
||||
A. Hauptmann <andreashauptmann@t-online.de>
|
||||
John McNamee <jpm@microwiz.com>
|
||||
Yosuke Furukawa <yosuke.furukawa@gmail.com>
|
||||
Santiago Gimeno <santiago.gimeno@quantion.es>
|
||||
guworks <ground.up.works@gmail.com>
|
||||
RossBencina <rossb@audiomulch.com>
|
||||
Roger A. Light <roger@atchoo.org>
|
||||
chenttuuvv <chenttuuvv@yahoo.com>
|
||||
Richard Lau <riclau@uk.ibm.com>
|
||||
ronkorving <rkorving@wizcorp.jp>
|
||||
Corbin Simpson <MostAwesomeDude@gmail.com>
|
||||
Zachary Hamm <zsh@imipolexg.org>
|
||||
Karl Skomski <karl@skomski.com>
|
||||
Jeremy Whitlock <jwhitlock@apache.org>
|
||||
Willem Thiart <himself@willemthiart.com>
|
||||
Ben Trask <bentrask@comcast.net>
|
||||
Jianghua Yang <jianghua.yjh@alibaba-inc.com>
|
||||
Colin Snover <github.com@zetafleet.com>
|
||||
Sakthipriyan Vairamani <thechargingvolcano@gmail.com>
|
||||
Eli Skeggs <skeggse@gmail.com>
|
||||
nmushell <nmushell@bloomberg.net>
|
||||
Gireesh Punathil <gpunathi@in.ibm.com>
|
||||
Ryan Johnston <ryan@mediapixel.co.nz>
|
||||
Adam Stylinski <stylinae@mail.uc.edu>
|
||||
Nathan Corvino <nathan@corvino.com>
|
||||
Wink Saville <wink@saville.com>
|
||||
Angel Leon <gubatron@gmail.com>
|
||||
Louis DeJardin <lodejard@microsoft.com>
|
||||
Imran Iqbal <imrani@ca.ibm.com>
|
||||
Petka Antonov <petka_antonov@hotmail.com>
|
||||
Ian Kronquist <iankronquist@teleport.com>
|
||||
kkdaemon <kkdaemon@gmail.com>
|
||||
Yuval Brik <yuval@brik.org.il>
|
||||
Joran Dirk Greef <joran@ronomon.com>
|
||||
Andrey Mazo <andrey.mazo@fidelissecurity.com>
|
||||
sztomi <hello.sztomi@gmail.com>
|
||||
Martin Bark <martin@barkynet.com>
|
||||
Dave <dave@jut.io>
|
||||
Alexis Murzeau <amubtdx@gmail.com>
|
||||
Didiet <lynxluna@gmail.com>
|
||||
Nan Xiang <514580344@qq.com>
|
||||
Samuel Lorétan <sloretan@riotgames.com>
|
||||
Nándor István Krácser <bonifaido@gmail.com>
|
||||
Katsutoshi Horie <mps299792458@gmail.com>
|
||||
Lukasz Jagiello <lukasz@wikia-inc.com>
|
||||
Robert Chiras <robert.chiras@intel.com>
|
||||
Kári Tristan Helgason <kthelgason@gmail.com>
|
||||
Krishnaraj Bhat <krrishnarraj@gmail.com>
|
||||
Enno Boland <g@s01.de>
|
||||
Michael Fero <michael.fero@datastax.com>
|
||||
Robert Jefe Lindstaedt <robert.lindstaedt@gmail.com>
|
||||
Myles Borins <myles.borins@gmail.com>
|
||||
Tony Theodore <tonyt@logyst.com>
|
||||
117
libs/libuv/CMakeLists.txt
Normal file
117
libs/libuv/CMakeLists.txt
Normal file
@ -0,0 +1,117 @@
|
||||
cmake_minimum_required(VERSION 2.8.5)
|
||||
project(libuv)
|
||||
|
||||
set(libuv_sources
|
||||
src/fs-poll.c
|
||||
src/inet.c
|
||||
src/threadpool.c
|
||||
src/uv-common.c
|
||||
src/version.c
|
||||
)
|
||||
|
||||
set(libuv_headers
|
||||
src/heap-inl.h
|
||||
src/queue.h
|
||||
src/uv-common.h
|
||||
)
|
||||
|
||||
if(NOT WIN32)
|
||||
find_package (Threads REQUIRED)
|
||||
|
||||
list(APPEND libuv_sources
|
||||
src/unix/async.c
|
||||
src/unix/core.c
|
||||
src/unix/dl.c
|
||||
src/unix/fs.c
|
||||
src/unix/getaddrinfo.c
|
||||
src/unix/getnameinfo.c
|
||||
src/unix/loop-watcher.c
|
||||
src/unix/loop.c
|
||||
src/unix/pipe.c
|
||||
src/unix/poll.c
|
||||
src/unix/process.c
|
||||
src/unix/signal.c
|
||||
src/unix/stream.c
|
||||
src/unix/tcp.c
|
||||
src/unix/thread.c
|
||||
src/unix/timer.c
|
||||
src/unix/tty.c
|
||||
src/unix/udp.c
|
||||
)
|
||||
|
||||
list(APPEND libuv_headers
|
||||
src/unix/atomic-ops.h
|
||||
src/unix/internal.h
|
||||
src/unix/spinlock.h
|
||||
)
|
||||
|
||||
if(${CMAKE_SYSTEM_NAME} STREQUAL "Linux")
|
||||
add_definitions(-D_GNU_SOURCE)
|
||||
list(APPEND libuv_sources
|
||||
src/unix/linux-core.c
|
||||
src/unix/linux-inotify.c
|
||||
src/unix/linux-syscalls.c
|
||||
src/unix/proctitle.c
|
||||
)
|
||||
|
||||
list(APPEND libuv_headers
|
||||
src/unix/linux-syscalls.h
|
||||
)
|
||||
endif()
|
||||
|
||||
if(${CMAKE_SYSTEM_NAME} STREQUAL "Darwin")
|
||||
add_definitions(-D_DARWIN_USE_64_BIT_INODE=1)
|
||||
add_definitions(-D_DARWIN_UNLIMITED_SELECT=1)
|
||||
list(APPEND libuv_sources
|
||||
src/unix/darwin.c
|
||||
src/unix/darwin-proctitle.c
|
||||
src/unix/fsevents.c
|
||||
src/unix/kqueue.c
|
||||
src/unix/proctitle.c
|
||||
)
|
||||
endif()
|
||||
|
||||
else()
|
||||
add_definitions(-DWIN32_LEAN_AND_MEAN)
|
||||
add_definitions(-D_WIN32_WINNT=0x0600)
|
||||
|
||||
list(APPEND libuv_sources
|
||||
src/win/async.c
|
||||
src/win/core.c
|
||||
src/win/dl.c
|
||||
src/win/error.c
|
||||
src/win/fs-event.c
|
||||
src/win/fs.c
|
||||
src/win/getaddrinfo.c
|
||||
src/win/getnameinfo.c
|
||||
src/win/handle.c
|
||||
src/win/loop-watcher.c
|
||||
src/win/pipe.c
|
||||
src/win/poll.c
|
||||
src/win/process-stdio.c
|
||||
src/win/process.c
|
||||
src/win/req.c
|
||||
src/win/signal.c
|
||||
src/win/stream.c
|
||||
src/win/tcp.c
|
||||
src/win/thread.c
|
||||
src/win/timer.c
|
||||
src/win/tty.c
|
||||
src/win/udp.c
|
||||
src/win/util.c
|
||||
src/win/winapi.c
|
||||
src/win/winsock.c
|
||||
)
|
||||
|
||||
list(APPEND libuv_headers
|
||||
src/win/atomicops-inl.h
|
||||
src/win/handle-inl.h
|
||||
src/win/internal.h
|
||||
src/win/req-inl.h
|
||||
src/win/stream-inl.h
|
||||
src/win/winapi.h
|
||||
src/win/winsock.h
|
||||
)
|
||||
endif()
|
||||
|
||||
add_library(libuv ${libuv_sources} ${libuv_headers})
|
||||
133
libs/libuv/CMakeLists.txt.old
Normal file
133
libs/libuv/CMakeLists.txt.old
Normal file
@ -0,0 +1,133 @@
|
||||
CMAKE_MINIMUM_REQUIRED(VERSION 2.8)
|
||||
|
||||
SET(libuv_sources
|
||||
src/fs-poll.c
|
||||
src/inet.c
|
||||
src/threadpool.c
|
||||
src/uv-common.c
|
||||
src/version.c
|
||||
)
|
||||
|
||||
SET(libuv_headers
|
||||
include/uv.h
|
||||
include/tree.h
|
||||
include/uv-errno.h
|
||||
include/uv-threadpool.h
|
||||
include/uv-version.h
|
||||
src/heap-inl.h
|
||||
src/queue.h
|
||||
src/uv-common.h
|
||||
)
|
||||
|
||||
IF(NOT WIN32)
|
||||
ADD_DEFINITIONS(-D_LARGEFILE_SOURCE)
|
||||
ADD_DEFINITIONS(-D_FILE_OFFSET_BITS=64)
|
||||
|
||||
SET(libuv_sources ${libuv_sources}
|
||||
src/unix/async.c
|
||||
src/unix/core.c
|
||||
src/unix/dl.c
|
||||
src/unix/fs.c
|
||||
src/unix/getaddrinfo.c
|
||||
src/unix/getnameinfo.c
|
||||
src/unix/loop.c
|
||||
src/unix/loop-watcher.c
|
||||
src/unix/pipe.c
|
||||
src/unix/poll.c
|
||||
src/unix/process.c
|
||||
src/unix/signal.c
|
||||
src/unix/stream.c
|
||||
src/unix/tcp.c
|
||||
src/unix/thread.c
|
||||
src/unix/timer.c
|
||||
src/unix/tty.c
|
||||
src/unix/udp.c
|
||||
)
|
||||
|
||||
SET(libuv_headers ${libuv_headers}
|
||||
include/uv-unix.h
|
||||
include/uv-linux.h
|
||||
include/uv-sunos.h
|
||||
include/uv-darwin.h
|
||||
include/uv-bsd.h
|
||||
include/uv-aix.h
|
||||
src/unix/atomic-ops.h
|
||||
src/unix/internal.h
|
||||
src/unix/spinlock.h
|
||||
)
|
||||
|
||||
IF(CMAKE_SYSTEM_NAME STREQUAL Linux)
|
||||
ADD_DEFINITIONS(-D_POSIX_C_SOURCE=200112)
|
||||
ADD_DEFINITIONS(-D_GNU_SOURCE)
|
||||
|
||||
SET(libuv_sources ${libuv_sources}
|
||||
src/unix/proctitle.c
|
||||
src/unix/linux-core.c
|
||||
src/unix/linux-inotify.c
|
||||
src/unix/linux-syscalls.c
|
||||
)
|
||||
|
||||
SET(libuv_headers ${libuv_headers}
|
||||
src/unix/linux-syscalls.h
|
||||
)
|
||||
ENDIF()
|
||||
|
||||
IF(APPLE)
|
||||
ADD_DEFINITIONS(-D_DARWIN_USE_64_BIT_INODE=1)
|
||||
ADD_DEFINITIONS(-D_DARWIN_UNLIMITED_SELECT=1)
|
||||
|
||||
SET(libuv_sources ${libuv_sources}
|
||||
src/unix/proctitle.c
|
||||
src/unix/darwin.c
|
||||
src/unix/fsevents.c
|
||||
src/unix/darwin-proctitle.c
|
||||
src/unix/pthread-barrier.c
|
||||
src/unix/kqueue.c
|
||||
)
|
||||
ENDIF()
|
||||
ELSE()
|
||||
ADD_DEFINITIONS(-D_WIN32_WINNT=0x0600)
|
||||
ADD_DEFINITIONS(-D_GNU_SOURCE)
|
||||
|
||||
SET(libuv_sources ${libuv_sources}
|
||||
src/win/async.c
|
||||
src/win/core.c
|
||||
src/win/dl.c
|
||||
src/win/error.c
|
||||
src/win/fs.c
|
||||
src/win/fs-event.c
|
||||
src/win/getaddrinfo.c
|
||||
src/win/getnameinfo.c
|
||||
src/win/handle.c
|
||||
src/win/loop-watcher.c
|
||||
src/win/pipe.c
|
||||
src/win/thread.c
|
||||
src/win/poll.c
|
||||
src/win/process.c
|
||||
src/win/process-stdio.c
|
||||
src/win/req.c
|
||||
src/win/signal.c
|
||||
src/win/snprintf.c
|
||||
src/win/stream.c
|
||||
src/win/tcp.c
|
||||
src/win/tty.c
|
||||
src/win/timer.c
|
||||
src/win/udp.c
|
||||
src/win/util.c
|
||||
src/win/winapi.c
|
||||
src/win/winsock.c
|
||||
)
|
||||
|
||||
SET(libuv_headers ${libuv_headers}
|
||||
include/uv-win.h
|
||||
src/win/atomicops-inl.h
|
||||
src/win/handle-inl.h
|
||||
src/win/internal.h
|
||||
src/win/req-inl.h
|
||||
src/win/stream-inl.h
|
||||
src/win/winapi.h
|
||||
src/win/winsock.h
|
||||
)
|
||||
ENDIF()
|
||||
|
||||
ADD_LIBRARY(libuv ${libuv_sources} ${libuv_headers})
|
||||
169
libs/libuv/CONTRIBUTING.md
Normal file
169
libs/libuv/CONTRIBUTING.md
Normal file
@ -0,0 +1,169 @@
|
||||
# CONTRIBUTING
|
||||
|
||||
The libuv project welcomes new contributors. This document will guide you
|
||||
through the process.
|
||||
|
||||
|
||||
### FORK
|
||||
|
||||
Fork the project [on GitHub](https://github.com/libuv/libuv) and check out
|
||||
your copy.
|
||||
|
||||
```
|
||||
$ git clone https://github.com/username/libuv.git
|
||||
$ cd libuv
|
||||
$ git remote add upstream https://github.com/libuv/libuv.git
|
||||
```
|
||||
|
||||
Now decide if you want your feature or bug fix to go into the master branch
|
||||
or the stable branch. As a rule of thumb, bug fixes go into the stable branch
|
||||
while new features go into the master branch.
|
||||
|
||||
The stable branch is effectively frozen; patches that change the libuv
|
||||
API/ABI or affect the run-time behavior of applications get rejected.
|
||||
|
||||
In case of doubt, open an issue in the [issue tracker][], post your question
|
||||
to the [libuv mailing list], or contact one of [project maintainers][] on [IRC][].
|
||||
|
||||
Especially do so if you plan to work on something big. Nothing is more
|
||||
frustrating than seeing your hard work go to waste because your vision
|
||||
does not align with that of a project maintainers.
|
||||
|
||||
|
||||
### BRANCH
|
||||
|
||||
Okay, so you have decided on the proper branch. Create a feature branch
|
||||
and start hacking:
|
||||
|
||||
```
|
||||
$ git checkout -b my-feature-branch -t origin/v1.x
|
||||
```
|
||||
|
||||
(Where v1.x is the latest stable branch as of this writing.)
|
||||
|
||||
### CODE
|
||||
|
||||
Please adhere to libuv's code style. In general it follows the conventions from
|
||||
the [Google C/C++ style guide]. Some of the key points, as well as some
|
||||
additional guidelines, are enumerated below.
|
||||
|
||||
* Code that is specific to unix-y platforms should be placed in `src/unix`, and
|
||||
declarations go into `include/uv-unix.h`.
|
||||
|
||||
* Source code that is Windows-specific goes into `src/win`, and related
|
||||
publicly exported types, functions and macro declarations should generally
|
||||
be declared in `include/uv-win.h`.
|
||||
|
||||
* Names should be descriptive and concise.
|
||||
|
||||
* All the symbols and types that libuv makes available publicly should be
|
||||
prefixed with `uv_` (or `UV_` in case of macros).
|
||||
|
||||
* Internal, non-static functions should be prefixed with `uv__`.
|
||||
|
||||
* Use two spaces and no tabs.
|
||||
|
||||
* Lines should be wrapped at 80 characters.
|
||||
|
||||
* Ensure that lines have no trailing whitespace, and use unix-style (LF) line
|
||||
endings.
|
||||
|
||||
* Use C89-compliant syntax. In other words, variables can only be declared at
|
||||
the top of a scope (function, if/for/while-block).
|
||||
|
||||
* When writing comments, use properly constructed sentences, including
|
||||
punctuation.
|
||||
|
||||
* When documenting APIs and/or source code, don't make assumptions or make
|
||||
implications about race, gender, religion, political orientation or anything
|
||||
else that isn't relevant to the project.
|
||||
|
||||
* Remember that source code usually gets written once and read often: ensure
|
||||
the reader doesn't have to make guesses. Make sure that the purpose and inner
|
||||
logic are either obvious to a reasonably skilled professional, or add a
|
||||
comment that explains it.
|
||||
|
||||
|
||||
### COMMIT
|
||||
|
||||
Make sure git knows your name and email address:
|
||||
|
||||
```
|
||||
$ git config --global user.name "J. Random User"
|
||||
$ git config --global user.email "j.random.user@example.com"
|
||||
```
|
||||
|
||||
Writing good commit logs is important. A commit log should describe what
|
||||
changed and why. Follow these guidelines when writing one:
|
||||
|
||||
1. The first line should be 50 characters or less and contain a short
|
||||
description of the change prefixed with the name of the changed
|
||||
subsystem (e.g. "net: add localAddress and localPort to Socket").
|
||||
2. Keep the second line blank.
|
||||
3. Wrap all other lines at 72 columns.
|
||||
|
||||
A good commit log looks like this:
|
||||
|
||||
```
|
||||
subsystem: explaining the commit in one line
|
||||
|
||||
Body of commit message is a few lines of text, explaining things
|
||||
in more detail, possibly giving some background about the issue
|
||||
being fixed, etc etc.
|
||||
|
||||
The body of the commit message can be several paragraphs, and
|
||||
please do proper word-wrap and keep columns shorter than about
|
||||
72 characters or so. That way `git log` will show things
|
||||
nicely even when it is indented.
|
||||
```
|
||||
|
||||
The header line should be meaningful; it is what other people see when they
|
||||
run `git shortlog` or `git log --oneline`.
|
||||
|
||||
Check the output of `git log --oneline files_that_you_changed` to find out
|
||||
what subsystem (or subsystems) your changes touch.
|
||||
|
||||
|
||||
### REBASE
|
||||
|
||||
Use `git rebase` (not `git merge`) to sync your work from time to time.
|
||||
|
||||
```
|
||||
$ git fetch upstream
|
||||
$ git rebase upstream/v1.x # or upstream/master
|
||||
```
|
||||
|
||||
|
||||
### TEST
|
||||
|
||||
Bug fixes and features should come with tests. Add your tests in the
|
||||
`test/` directory. Each new test needs to be registered in `test/test-list.h`. If you add a new test file, it needs to be registered in two places:
|
||||
- `Makefile.am`: add the file's name to the `test_run_tests_SOURCES` list.
|
||||
- `uv.gyp`: add the file's name to the `sources` list in the `run-tests` target.
|
||||
|
||||
Look at other tests to see how they should be structured (license boilerplate,
|
||||
the way entry points are declared, etc.).
|
||||
|
||||
Check README.md file to find out how to run the test suite and make sure that
|
||||
there are no test regressions.
|
||||
|
||||
### PUSH
|
||||
|
||||
```
|
||||
$ git push origin my-feature-branch
|
||||
```
|
||||
|
||||
Go to https://github.com/username/libuv and select your feature branch. Click
|
||||
the 'Pull Request' button and fill out the form.
|
||||
|
||||
Pull requests are usually reviewed within a few days. If there are comments
|
||||
to address, apply your changes in a separate commit and push that to your
|
||||
feature branch. Post a comment in the pull request afterwards; GitHub does
|
||||
not send out notifications when you add commits.
|
||||
|
||||
|
||||
[issue tracker]: https://github.com/libuv/libuv/issues
|
||||
[libuv mailing list]: http://groups.google.com/group/libuv
|
||||
[IRC]: http://webchat.freelibuv.net/?channels=libuv
|
||||
[Google C/C++ style guide]: http://google-styleguide.googlecode.com/svn/trunk/cppguide.xml
|
||||
[project maintainers]: https://github.com/libuv/libuv/blob/master/MAINTAINERS.md
|
||||
2600
libs/libuv/ChangeLog
Normal file
2600
libs/libuv/ChangeLog
Normal file
File diff suppressed because it is too large
Load Diff
46
libs/libuv/LICENSE
Normal file
46
libs/libuv/LICENSE
Normal file
@ -0,0 +1,46 @@
|
||||
libuv is part of the Node project: http://nodejs.org/
|
||||
libuv may be distributed alone under Node's license:
|
||||
|
||||
====
|
||||
|
||||
Copyright Joyent, Inc. and other Node contributors. All rights reserved.
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to
|
||||
deal in the Software without restriction, including without limitation the
|
||||
rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
sell copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
IN THE SOFTWARE.
|
||||
|
||||
====
|
||||
|
||||
This license applies to all parts of libuv that are not externally
|
||||
maintained libraries.
|
||||
|
||||
The externally maintained libraries used by libuv are:
|
||||
|
||||
- tree.h (from FreeBSD), copyright Niels Provos. Two clause BSD license.
|
||||
|
||||
- inet_pton and inet_ntop implementations, contained in src/inet.c, are
|
||||
copyright the Internet Systems Consortium, Inc., and licensed under the ISC
|
||||
license.
|
||||
|
||||
- stdint-msvc2008.h (from msinttypes), copyright Alexander Chemeris. Three
|
||||
clause BSD license.
|
||||
|
||||
- pthread-fixes.h, pthread-fixes.c, copyright Google Inc. and Sony Mobile
|
||||
Communications AB. Three clause BSD license.
|
||||
|
||||
- android-ifaddrs.h, android-ifaddrs.c, copyright Berkeley Software Design
|
||||
Inc, Kenneth MacKay and Emergya (Cloud4all, FP7/2007-2013, grant agreement
|
||||
n° 289016). Three clause BSD license.
|
||||
37
libs/libuv/MAINTAINERS.md
Normal file
37
libs/libuv/MAINTAINERS.md
Normal file
@ -0,0 +1,37 @@
|
||||
|
||||
# Project Maintainers
|
||||
|
||||
libuv is currently managed by the following individuals:
|
||||
|
||||
* **Ben Noordhuis** ([@bnoordhuis](https://github.com/bnoordhuis))
|
||||
- GPG key: D77B 1E34 243F BAF0 5F8E 9CC3 4F55 C8C8 46AB 89B9 (pubkey-bnoordhuis)
|
||||
* **Bert Belder** ([@piscisaureus](https://github.com/piscisaureus))
|
||||
* **Colin Ihrig** ([@cjihrig](https://github.com/cjihrig))
|
||||
* **Fedor Indutny** ([@indutny](https://github.com/indutny))
|
||||
- GPG key: AF2E EA41 EC34 47BF DD86 FED9 D706 3CCE 19B7 E890 (pubkey-indutny)
|
||||
* **Saúl Ibarra Corretgé** ([@saghul](https://github.com/saghul))
|
||||
- GPG key: FDF5 1936 4458 319F A823 3DC9 410E 5553 AE9B C059 (pubkey-saghul)
|
||||
|
||||
## Storing a maintainer key in Git
|
||||
|
||||
It's quite handy to store a maintainer's signature as a git blob, and have
|
||||
that object tagged and signed with such key.
|
||||
|
||||
Export your public key:
|
||||
|
||||
$ gpg --armor --export saghul@gmail.com > saghul.asc
|
||||
|
||||
Store it as a blob on the repo:
|
||||
|
||||
$ git hash-object -w saghul.asc
|
||||
|
||||
The previous command returns a hash, copy it. For the sake of this explanation,
|
||||
we'll assume it's 'abcd1234'. Storing the blob in git is not enough, it could
|
||||
be garbage collected since nothing references it, so we'll create a tag for it:
|
||||
|
||||
$ git tag -s pubkey-saghul abcd1234
|
||||
|
||||
Commit the changes and push:
|
||||
|
||||
$ git push origin pubkey-saghul
|
||||
|
||||
356
libs/libuv/Makefile.am
Normal file
356
libs/libuv/Makefile.am
Normal file
@ -0,0 +1,356 @@
|
||||
# Copyright (c) 2013, Ben Noordhuis <info@bnoordhuis.nl>
|
||||
#
|
||||
# Permission to use, copy, modify, and/or distribute this software for any
|
||||
# purpose with or without fee is hereby granted, provided that the above
|
||||
# copyright notice and this permission notice appear in all copies.
|
||||
#
|
||||
# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
|
||||
ACLOCAL_AMFLAGS = -I m4
|
||||
|
||||
AM_CPPFLAGS = -I$(top_srcdir)/include \
|
||||
-I$(top_srcdir)/src
|
||||
|
||||
include_HEADERS=include/uv.h include/uv-errno.h include/uv-threadpool.h include/uv-version.h
|
||||
|
||||
CLEANFILES =
|
||||
|
||||
lib_LTLIBRARIES = libuv.la
|
||||
libuv_la_CFLAGS = @CFLAGS@
|
||||
libuv_la_LDFLAGS = -no-undefined -version-info 1:0:0
|
||||
libuv_la_SOURCES = src/fs-poll.c \
|
||||
src/heap-inl.h \
|
||||
src/inet.c \
|
||||
src/queue.h \
|
||||
src/threadpool.c \
|
||||
src/uv-common.c \
|
||||
src/uv-common.h \
|
||||
src/version.c
|
||||
|
||||
if SUNOS
|
||||
# Can't be turned into a CC_CHECK_CFLAGS in configure.ac, it makes compilers
|
||||
# on other platforms complain that the argument is unused during compilation.
|
||||
libuv_la_CFLAGS += -pthread
|
||||
endif
|
||||
|
||||
if WINNT
|
||||
|
||||
include_HEADERS += include/uv-win.h include/tree.h
|
||||
AM_CPPFLAGS += -I$(top_srcdir)/src/win \
|
||||
-DWIN32_LEAN_AND_MEAN \
|
||||
-D_WIN32_WINNT=0x0600
|
||||
libuv_la_SOURCES += src/win/async.c \
|
||||
src/win/atomicops-inl.h \
|
||||
src/win/core.c \
|
||||
src/win/dl.c \
|
||||
src/win/error.c \
|
||||
src/win/fs-event.c \
|
||||
src/win/fs.c \
|
||||
src/win/getaddrinfo.c \
|
||||
src/win/getnameinfo.c \
|
||||
src/win/handle.c \
|
||||
src/win/handle-inl.h \
|
||||
src/win/internal.h \
|
||||
src/win/loop-watcher.c \
|
||||
src/win/pipe.c \
|
||||
src/win/poll.c \
|
||||
src/win/process-stdio.c \
|
||||
src/win/process.c \
|
||||
src/win/req.c \
|
||||
src/win/req-inl.h \
|
||||
src/win/signal.c \
|
||||
src/win/stream.c \
|
||||
src/win/stream-inl.h \
|
||||
src/win/tcp.c \
|
||||
src/win/thread.c \
|
||||
src/win/timer.c \
|
||||
src/win/tty.c \
|
||||
src/win/udp.c \
|
||||
src/win/util.c \
|
||||
src/win/winapi.c \
|
||||
src/win/winapi.h \
|
||||
src/win/winsock.c \
|
||||
src/win/winsock.h
|
||||
|
||||
else # WINNT
|
||||
|
||||
include_HEADERS += include/uv-unix.h
|
||||
AM_CPPFLAGS += -I$(top_srcdir)/src/unix
|
||||
libuv_la_SOURCES += src/unix/async.c \
|
||||
src/unix/atomic-ops.h \
|
||||
src/unix/core.c \
|
||||
src/unix/dl.c \
|
||||
src/unix/fs.c \
|
||||
src/unix/getaddrinfo.c \
|
||||
src/unix/getnameinfo.c \
|
||||
src/unix/internal.h \
|
||||
src/unix/loop-watcher.c \
|
||||
src/unix/loop.c \
|
||||
src/unix/pipe.c \
|
||||
src/unix/poll.c \
|
||||
src/unix/process.c \
|
||||
src/unix/signal.c \
|
||||
src/unix/spinlock.h \
|
||||
src/unix/stream.c \
|
||||
src/unix/tcp.c \
|
||||
src/unix/thread.c \
|
||||
src/unix/timer.c \
|
||||
src/unix/tty.c \
|
||||
src/unix/udp.c
|
||||
|
||||
endif # WINNT
|
||||
|
||||
EXTRA_DIST = test/fixtures/empty_file \
|
||||
test/fixtures/load_error.node \
|
||||
include \
|
||||
test \
|
||||
docs \
|
||||
img \
|
||||
samples \
|
||||
android-configure \
|
||||
CONTRIBUTING.md \
|
||||
LICENSE \
|
||||
README.md \
|
||||
checksparse.sh \
|
||||
vcbuild.bat \
|
||||
Makefile.mingw \
|
||||
common.gypi \
|
||||
gyp_uv.py \
|
||||
uv.gyp
|
||||
|
||||
|
||||
|
||||
TESTS = test/run-tests
|
||||
check_PROGRAMS = test/run-tests
|
||||
test_run_tests_CFLAGS =
|
||||
test_run_tests_LDFLAGS =
|
||||
test_run_tests_SOURCES = test/blackhole-server.c \
|
||||
test/dns-server.c \
|
||||
test/echo-server.c \
|
||||
test/run-tests.c \
|
||||
test/runner.c \
|
||||
test/runner.h \
|
||||
test/task.h \
|
||||
test/test-active.c \
|
||||
test/test-async.c \
|
||||
test/test-async-null-cb.c \
|
||||
test/test-barrier.c \
|
||||
test/test-callback-order.c \
|
||||
test/test-callback-stack.c \
|
||||
test/test-close-fd.c \
|
||||
test/test-close-order.c \
|
||||
test/test-condvar.c \
|
||||
test/test-connection-fail.c \
|
||||
test/test-cwd-and-chdir.c \
|
||||
test/test-default-loop-close.c \
|
||||
test/test-delayed-accept.c \
|
||||
test/test-dlerror.c \
|
||||
test/test-eintr-handling.c \
|
||||
test/test-embed.c \
|
||||
test/test-emfile.c \
|
||||
test/test-error.c \
|
||||
test/test-fail-always.c \
|
||||
test/test-fs-event.c \
|
||||
test/test-fs-poll.c \
|
||||
test/test-fs.c \
|
||||
test/test-get-currentexe.c \
|
||||
test/test-get-loadavg.c \
|
||||
test/test-get-memory.c \
|
||||
test/test-get-passwd.c \
|
||||
test/test-getaddrinfo.c \
|
||||
test/test-getnameinfo.c \
|
||||
test/test-getsockname.c \
|
||||
test/test-handle-fileno.c \
|
||||
test/test-homedir.c \
|
||||
test/test-hrtime.c \
|
||||
test/test-idle.c \
|
||||
test/test-ip4-addr.c \
|
||||
test/test-ip6-addr.c \
|
||||
test/test-ipc-send-recv.c \
|
||||
test/test-ipc.c \
|
||||
test/test-list.h \
|
||||
test/test-loop-handles.c \
|
||||
test/test-loop-alive.c \
|
||||
test/test-loop-close.c \
|
||||
test/test-loop-stop.c \
|
||||
test/test-loop-time.c \
|
||||
test/test-loop-configure.c \
|
||||
test/test-multiple-listen.c \
|
||||
test/test-mutexes.c \
|
||||
test/test-osx-select.c \
|
||||
test/test-pass-always.c \
|
||||
test/test-ping-pong.c \
|
||||
test/test-pipe-bind-error.c \
|
||||
test/test-pipe-connect-error.c \
|
||||
test/test-pipe-connect-multiple.c \
|
||||
test/test-pipe-connect-prepare.c \
|
||||
test/test-pipe-getsockname.c \
|
||||
test/test-pipe-pending-instances.c \
|
||||
test/test-pipe-sendmsg.c \
|
||||
test/test-pipe-server-close.c \
|
||||
test/test-pipe-close-stdout-read-stdin.c \
|
||||
test/test-pipe-set-non-blocking.c \
|
||||
test/test-platform-output.c \
|
||||
test/test-poll-close.c \
|
||||
test/test-poll-close-doesnt-corrupt-stack.c \
|
||||
test/test-poll-closesocket.c \
|
||||
test/test-poll.c \
|
||||
test/test-process-title.c \
|
||||
test/test-queue-foreach-delete.c \
|
||||
test/test-ref.c \
|
||||
test/test-run-nowait.c \
|
||||
test/test-run-once.c \
|
||||
test/test-semaphore.c \
|
||||
test/test-shutdown-close.c \
|
||||
test/test-shutdown-eof.c \
|
||||
test/test-shutdown-twice.c \
|
||||
test/test-signal-multiple-loops.c \
|
||||
test/test-signal.c \
|
||||
test/test-socket-buffer-size.c \
|
||||
test/test-spawn.c \
|
||||
test/test-stdio-over-pipes.c \
|
||||
test/test-tcp-bind-error.c \
|
||||
test/test-tcp-bind6-error.c \
|
||||
test/test-tcp-close-accept.c \
|
||||
test/test-tcp-close-while-connecting.c \
|
||||
test/test-tcp-close.c \
|
||||
test/test-tcp-create-socket-early.c \
|
||||
test/test-tcp-connect-error-after-write.c \
|
||||
test/test-tcp-connect-error.c \
|
||||
test/test-tcp-connect-timeout.c \
|
||||
test/test-tcp-connect6-error.c \
|
||||
test/test-tcp-flags.c \
|
||||
test/test-tcp-open.c \
|
||||
test/test-tcp-read-stop.c \
|
||||
test/test-tcp-shutdown-after-write.c \
|
||||
test/test-tcp-unexpected-read.c \
|
||||
test/test-tcp-oob.c \
|
||||
test/test-tcp-write-to-half-open-connection.c \
|
||||
test/test-tcp-write-after-connect.c \
|
||||
test/test-tcp-writealot.c \
|
||||
test/test-tcp-write-fail.c \
|
||||
test/test-tcp-try-write.c \
|
||||
test/test-tcp-write-queue-order.c \
|
||||
test/test-thread-equal.c \
|
||||
test/test-thread.c \
|
||||
test/test-threadpool-cancel.c \
|
||||
test/test-threadpool.c \
|
||||
test/test-timer-again.c \
|
||||
test/test-timer-from-check.c \
|
||||
test/test-timer.c \
|
||||
test/test-tmpdir.c \
|
||||
test/test-tty.c \
|
||||
test/test-udp-bind.c \
|
||||
test/test-udp-create-socket-early.c \
|
||||
test/test-udp-dgram-too-big.c \
|
||||
test/test-udp-ipv6.c \
|
||||
test/test-udp-multicast-interface.c \
|
||||
test/test-udp-multicast-interface6.c \
|
||||
test/test-udp-multicast-join.c \
|
||||
test/test-udp-multicast-join6.c \
|
||||
test/test-udp-multicast-ttl.c \
|
||||
test/test-udp-open.c \
|
||||
test/test-udp-options.c \
|
||||
test/test-udp-send-and-recv.c \
|
||||
test/test-udp-send-immediate.c \
|
||||
test/test-udp-send-unreachable.c \
|
||||
test/test-udp-try-send.c \
|
||||
test/test-walk-handles.c \
|
||||
test/test-watcher-cross-stop.c
|
||||
test_run_tests_LDADD = libuv.la
|
||||
|
||||
if WINNT
|
||||
test_run_tests_SOURCES += test/runner-win.c \
|
||||
test/runner-win.h
|
||||
else
|
||||
test_run_tests_SOURCES += test/runner-unix.c \
|
||||
test/runner-unix.h
|
||||
endif
|
||||
|
||||
if AIX
|
||||
test_run_tests_CFLAGS += -D_ALL_SOURCE -D_XOPEN_SOURCE=500 -D_LINUX_SOURCE_COMPAT
|
||||
endif
|
||||
|
||||
if SUNOS
|
||||
test_run_tests_CFLAGS += -D__EXTENSIONS__ -D_XOPEN_SOURCE=500
|
||||
endif
|
||||
|
||||
|
||||
if AIX
|
||||
libuv_la_CFLAGS += -D_ALL_SOURCE -D_XOPEN_SOURCE=500 -D_LINUX_SOURCE_COMPAT -D_THREAD_SAFE
|
||||
include_HEADERS += include/uv-aix.h
|
||||
libuv_la_SOURCES += src/unix/aix.c
|
||||
endif
|
||||
|
||||
if ANDROID
|
||||
include_HEADERS += include/android-ifaddrs.h \
|
||||
include/pthread-barrier.h
|
||||
libuv_la_SOURCES += src/unix/android-ifaddrs.c \
|
||||
src/unix/pthread-fixes.c \
|
||||
src/unix/pthread-barrier.c
|
||||
endif
|
||||
|
||||
if DARWIN
|
||||
include_HEADERS += include/uv-darwin.h \
|
||||
include/pthread-barrier.h
|
||||
libuv_la_CFLAGS += -D_DARWIN_USE_64_BIT_INODE=1
|
||||
libuv_la_CFLAGS += -D_DARWIN_UNLIMITED_SELECT=1
|
||||
libuv_la_SOURCES += src/unix/darwin.c \
|
||||
src/unix/darwin-proctitle.c \
|
||||
src/unix/fsevents.c \
|
||||
src/unix/kqueue.c \
|
||||
src/unix/proctitle.c \
|
||||
src/unix/pthread-barrier.c
|
||||
test_run_tests_LDFLAGS += -lutil
|
||||
endif
|
||||
|
||||
if DRAGONFLY
|
||||
include_HEADERS += include/uv-bsd.h
|
||||
test_run_tests_LDFLAGS += -lutil
|
||||
endif
|
||||
|
||||
if FREEBSD
|
||||
include_HEADERS += include/uv-bsd.h
|
||||
libuv_la_SOURCES += src/unix/freebsd.c src/unix/kqueue.c
|
||||
test_run_tests_LDFLAGS += -lutil
|
||||
endif
|
||||
|
||||
if LINUX
|
||||
include_HEADERS += include/uv-linux.h
|
||||
libuv_la_CFLAGS += -D_GNU_SOURCE
|
||||
libuv_la_SOURCES += src/unix/linux-core.c \
|
||||
src/unix/linux-inotify.c \
|
||||
src/unix/linux-syscalls.c \
|
||||
src/unix/linux-syscalls.h \
|
||||
src/unix/proctitle.c
|
||||
test_run_tests_LDFLAGS += -lutil
|
||||
endif
|
||||
|
||||
if NETBSD
|
||||
include_HEADERS += include/uv-bsd.h
|
||||
libuv_la_SOURCES += src/unix/kqueue.c src/unix/netbsd.c
|
||||
test_run_tests_LDFLAGS += -lutil
|
||||
endif
|
||||
|
||||
if OPENBSD
|
||||
include_HEADERS += include/uv-bsd.h
|
||||
libuv_la_SOURCES += src/unix/kqueue.c src/unix/openbsd.c
|
||||
test_run_tests_LDFLAGS += -lutil
|
||||
endif
|
||||
|
||||
if SUNOS
|
||||
include_HEADERS += include/uv-sunos.h
|
||||
libuv_la_CFLAGS += -D__EXTENSIONS__ -D_XOPEN_SOURCE=500
|
||||
libuv_la_SOURCES += src/unix/sunos.c
|
||||
endif
|
||||
|
||||
if HAVE_PKG_CONFIG
|
||||
pkgconfigdir = $(libdir)/pkgconfig
|
||||
pkgconfig_DATA = @PACKAGE_NAME@.pc
|
||||
endif
|
||||
84
libs/libuv/Makefile.mingw
Normal file
84
libs/libuv/Makefile.mingw
Normal file
@ -0,0 +1,84 @@
|
||||
# Copyright (c) 2013, Ben Noordhuis <info@bnoordhuis.nl>
|
||||
#
|
||||
# Permission to use, copy, modify, and/or distribute this software for any
|
||||
# purpose with or without fee is hereby granted, provided that the above
|
||||
# copyright notice and this permission notice appear in all copies.
|
||||
#
|
||||
# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
|
||||
CC ?= gcc
|
||||
|
||||
CFLAGS += -Wall \
|
||||
-Wextra \
|
||||
-Wno-unused-parameter \
|
||||
-Iinclude \
|
||||
-Isrc \
|
||||
-Isrc/win \
|
||||
-DWIN32_LEAN_AND_MEAN \
|
||||
-D_WIN32_WINNT=0x0600
|
||||
|
||||
INCLUDES = include/stdint-msvc2008.h \
|
||||
include/tree.h \
|
||||
include/uv-errno.h \
|
||||
include/uv-threadpool.h \
|
||||
include/uv-version.h \
|
||||
include/uv-win.h \
|
||||
include/uv.h \
|
||||
src/heap-inl.h \
|
||||
src/queue.h \
|
||||
src/uv-common.h \
|
||||
src/win/atomicops-inl.h \
|
||||
src/win/handle-inl.h \
|
||||
src/win/internal.h \
|
||||
src/win/req-inl.h \
|
||||
src/win/stream-inl.h \
|
||||
src/win/winapi.h \
|
||||
src/win/winsock.h
|
||||
|
||||
OBJS = src/fs-poll.o \
|
||||
src/inet.o \
|
||||
src/threadpool.o \
|
||||
src/uv-common.o \
|
||||
src/version.o \
|
||||
src/win/async.o \
|
||||
src/win/core.o \
|
||||
src/win/dl.o \
|
||||
src/win/error.o \
|
||||
src/win/fs-event.o \
|
||||
src/win/fs.o \
|
||||
src/win/getaddrinfo.o \
|
||||
src/win/getnameinfo.o \
|
||||
src/win/handle.o \
|
||||
src/win/loop-watcher.o \
|
||||
src/win/pipe.o \
|
||||
src/win/poll.o \
|
||||
src/win/process-stdio.o \
|
||||
src/win/process.o \
|
||||
src/win/req.o \
|
||||
src/win/signal.o \
|
||||
src/win/stream.o \
|
||||
src/win/tcp.o \
|
||||
src/win/thread.o \
|
||||
src/win/timer.o \
|
||||
src/win/tty.o \
|
||||
src/win/udp.o \
|
||||
src/win/util.o \
|
||||
src/win/winapi.o \
|
||||
src/win/winsock.o
|
||||
|
||||
all: libuv.a
|
||||
|
||||
clean:
|
||||
-$(RM) $(OBJS) libuv.a
|
||||
|
||||
libuv.a: $(OBJS)
|
||||
$(AR) crs $@ $^
|
||||
|
||||
$(OBJS): %.o : %.c $(INCLUDES)
|
||||
$(CC) $(CFLAGS) -c -o $@ $<
|
||||
256
libs/libuv/README.md
Normal file
256
libs/libuv/README.md
Normal file
@ -0,0 +1,256 @@
|
||||
![libuv][libuv_banner]
|
||||
|
||||
## Overview
|
||||
|
||||
libuv is a multi-platform support library with a focus on asynchronous I/O. It
|
||||
was primarily developed for use by [Node.js](http://nodejs.org), but it's also
|
||||
used by [Luvit](http://luvit.io/), [Julia](http://julialang.org/),
|
||||
[pyuv](https://github.com/saghul/pyuv), and [others](https://github.com/libuv/libuv/wiki/Projects-that-use-libuv).
|
||||
|
||||
## Feature highlights
|
||||
|
||||
* Full-featured event loop backed by epoll, kqueue, IOCP, event ports.
|
||||
|
||||
* Asynchronous TCP and UDP sockets
|
||||
|
||||
* Asynchronous DNS resolution
|
||||
|
||||
* Asynchronous file and file system operations
|
||||
|
||||
* File system events
|
||||
|
||||
* ANSI escape code controlled TTY
|
||||
|
||||
* IPC with socket sharing, using Unix domain sockets or named pipes (Windows)
|
||||
|
||||
* Child processes
|
||||
|
||||
* Thread pool
|
||||
|
||||
* Signal handling
|
||||
|
||||
* High resolution clock
|
||||
|
||||
* Threading and synchronization primitives
|
||||
|
||||
## Versioning
|
||||
|
||||
Starting with version 1.0.0 libuv follows the [semantic versioning](http://semver.org/)
|
||||
scheme. The API change and backwards compatibility rules are those indicated by
|
||||
SemVer. libuv will keep a stable ABI across major releases.
|
||||
|
||||
## Community
|
||||
|
||||
* [Mailing list](http://groups.google.com/group/libuv)
|
||||
* [IRC chatroom (#libuv@irc.freenode.org)](http://webchat.freenode.net?channels=libuv&uio=d4)
|
||||
|
||||
## Documentation
|
||||
|
||||
### Official API documentation
|
||||
|
||||
Located in the docs/ subdirectory. It uses the [Sphinx](http://sphinx-doc.org/)
|
||||
framework, which makes it possible to build the documentation in multiple
|
||||
formats.
|
||||
|
||||
Show different supported building options:
|
||||
|
||||
$ make help
|
||||
|
||||
Build documentation as HTML:
|
||||
|
||||
$ make html
|
||||
|
||||
Build documentation as HTML and live reload it when it changes (this requires
|
||||
sphinx-autobuild to be installed and is only supported on Unix):
|
||||
|
||||
$ make livehtml
|
||||
|
||||
Build documentation as man pages:
|
||||
|
||||
$ make man
|
||||
|
||||
Build documentation as ePub:
|
||||
|
||||
$ make epub
|
||||
|
||||
NOTE: Windows users need to use make.bat instead of plain 'make'.
|
||||
|
||||
Documentation can be browsed online [here](http://docs.libuv.org).
|
||||
|
||||
The [tests and benchmarks](https://github.com/libuv/libuv/tree/master/test)
|
||||
also serve as API specification and usage examples.
|
||||
|
||||
### Other resources
|
||||
|
||||
* [An Introduction to libuv](http://nikhilm.github.com/uvbook/)
|
||||
— An overview of libuv with tutorials.
|
||||
* [LXJS 2012 talk](http://www.youtube.com/watch?v=nGn60vDSxQ4)
|
||||
— High-level introductory talk about libuv.
|
||||
* [libuv-dox](https://github.com/thlorenz/libuv-dox)
|
||||
— Documenting types and methods of libuv, mostly by reading uv.h.
|
||||
* [learnuv](https://github.com/thlorenz/learnuv)
|
||||
— Learn uv for fun and profit, a self guided workshop to libuv.
|
||||
|
||||
These resources are not handled by libuv maintainers and might be out of
|
||||
date. Please verify it before opening new issues.
|
||||
|
||||
## Downloading
|
||||
|
||||
libuv can be downloaded either from the
|
||||
[GitHub repository](https://github.com/libuv/libuv)
|
||||
or from the [downloads site](http://dist.libuv.org/dist/).
|
||||
|
||||
Starting with libuv 1.7.0, binaries for Windows are also provided. This is to
|
||||
be considered EXPERIMENTAL.
|
||||
|
||||
Before verifying the git tags or signature files, importing the relevant keys
|
||||
is necessary. Key IDs are listed in the
|
||||
[MAINTAINERS](https://github.com/libuv/libuv/blob/master/MAINTAINERS.md)
|
||||
file, but are also available as git blob objects for easier use.
|
||||
|
||||
Importing a key the usual way:
|
||||
|
||||
$ gpg --keyserver pool.sks-keyservers.net \
|
||||
--recv-keys AE9BC059
|
||||
|
||||
Importing a key from a git blob object:
|
||||
|
||||
$ git show pubkey-saghul | gpg --import
|
||||
|
||||
### Verifying releases
|
||||
|
||||
Git tags are signed with the developer's key, they can be verified as follows:
|
||||
|
||||
$ git verify-tag v1.6.1
|
||||
|
||||
Starting with libuv 1.7.0, the tarballs stored in the
|
||||
[downloads site](http://dist.libuv.org/dist/) are signed and an accompanying
|
||||
signature file sit alongside each. Once both the release tarball and the
|
||||
signature file are downloaded, the file can be verified as follows:
|
||||
|
||||
$ gpg --verify libuv-1.7.0.tar.gz.sign
|
||||
|
||||
## Build Instructions
|
||||
|
||||
For GCC there are two build methods: via autotools or via [GYP][].
|
||||
GYP is a meta-build system which can generate MSVS, Makefile, and XCode
|
||||
backends. It is best used for integration into other projects.
|
||||
|
||||
To build with autotools:
|
||||
|
||||
$ sh autogen.sh
|
||||
$ ./configure
|
||||
$ make
|
||||
$ make check
|
||||
$ make install
|
||||
|
||||
### Windows
|
||||
|
||||
First, [Python][] 2.6 or 2.7 must be installed as it is required by [GYP][].
|
||||
If python is not in your path, set the environment variable `PYTHON` to its
|
||||
location. For example: `set PYTHON=C:\Python27\python.exe`
|
||||
|
||||
To build with Visual Studio, launch a git shell (e.g. Cmd or PowerShell)
|
||||
and run vcbuild.bat which will checkout the GYP code into build/gyp and
|
||||
generate uv.sln as well as related project files.
|
||||
|
||||
To have GYP generate build script for another system, checkout GYP into the
|
||||
project tree manually:
|
||||
|
||||
$ git clone https://chromium.googlesource.com/external/gyp.git build/gyp
|
||||
|
||||
### Unix
|
||||
|
||||
For Debug builds (recommended) run:
|
||||
|
||||
$ ./gyp_uv.py -f make
|
||||
$ make -C out
|
||||
|
||||
For Release builds run:
|
||||
|
||||
$ ./gyp_uv.py -f make
|
||||
$ BUILDTYPE=Release make -C out
|
||||
|
||||
Run `./gyp_uv.py -f make -Dtarget_arch=x32` to build [x32][] binaries.
|
||||
|
||||
### OS X
|
||||
|
||||
Run:
|
||||
|
||||
$ ./gyp_uv.py -f xcode
|
||||
$ xcodebuild -ARCHS="x86_64" -project uv.xcodeproj \
|
||||
-configuration Release -target All
|
||||
|
||||
Using Homebrew:
|
||||
|
||||
$ brew install --HEAD libuv
|
||||
|
||||
Note to OS X users:
|
||||
|
||||
Make sure that you specify the architecture you wish to build for in the
|
||||
"ARCHS" flag. You can specify more than one by delimiting with a space
|
||||
(e.g. "x86_64 i386").
|
||||
|
||||
### Android
|
||||
|
||||
Run:
|
||||
|
||||
$ source ./android-configure NDK_PATH gyp
|
||||
$ make -C out
|
||||
|
||||
Note for UNIX users: compile your project with `-D_LARGEFILE_SOURCE` and
|
||||
`-D_FILE_OFFSET_BITS=64`. GYP builds take care of that automatically.
|
||||
|
||||
### Using Ninja
|
||||
|
||||
To use ninja for build on ninja supported platforms, run:
|
||||
|
||||
$ ./gyp_uv.py -f ninja
|
||||
$ ninja -C out/Debug #for debug build OR
|
||||
$ ninja -C out/Release
|
||||
|
||||
|
||||
### Running tests
|
||||
|
||||
Run:
|
||||
|
||||
$ ./gyp_uv.py -f make
|
||||
$ make -C out
|
||||
$ ./out/Debug/run-tests
|
||||
|
||||
## Supported Platforms
|
||||
|
||||
Microsoft Windows operating systems since Windows XP SP2. It can be built
|
||||
with either Visual Studio or MinGW. Consider using
|
||||
[Visual Studio Express 2010][] or later if you do not have a full Visual
|
||||
Studio license.
|
||||
|
||||
Linux using the GCC toolchain.
|
||||
|
||||
OS X using the GCC or XCode toolchain.
|
||||
|
||||
Solaris 121 and later using GCC toolchain.
|
||||
|
||||
AIX 6 and later using GCC toolchain (see notes).
|
||||
|
||||
### AIX Notes
|
||||
|
||||
AIX support for filesystem events requires the non-default IBM `bos.ahafs`
|
||||
package to be installed. This package provides the AIX Event Infrastructure
|
||||
that is detected by `autoconf`.
|
||||
[IBM documentation](http://www.ibm.com/developerworks/aix/library/au-aix_event_infrastructure/)
|
||||
describes the package in more detail.
|
||||
|
||||
AIX support for filesystem events is not compiled when building with `gyp`.
|
||||
|
||||
## Patches
|
||||
|
||||
See the [guidelines for contributing][].
|
||||
|
||||
[node.js]: http://nodejs.org/
|
||||
[GYP]: http://code.google.com/p/gyp/
|
||||
[Python]: https://www.python.org/downloads/
|
||||
[Visual Studio Express 2010]: http://www.microsoft.com/visualstudio/eng/products/visual-studio-2010-express
|
||||
[guidelines for contributing]: https://github.com/libuv/libuv/blob/master/CONTRIBUTING.md
|
||||
[libuv_banner]: https://raw.githubusercontent.com/libuv/libuv/master/img/banner.png
|
||||
[x32]: https://en.wikipedia.org/wiki/X32_ABI
|
||||
20
libs/libuv/android-configure
Normal file
20
libs/libuv/android-configure
Normal file
@ -0,0 +1,20 @@
|
||||
#!/bin/bash
|
||||
|
||||
export TOOLCHAIN=$PWD/android-toolchain
|
||||
mkdir -p $TOOLCHAIN
|
||||
$1/build/tools/make-standalone-toolchain.sh \
|
||||
--toolchain=arm-linux-androideabi-4.9 \
|
||||
--arch=arm \
|
||||
--install-dir=$TOOLCHAIN \
|
||||
--platform=android-21
|
||||
export PATH=$TOOLCHAIN/bin:$PATH
|
||||
export AR=arm-linux-androideabi-ar
|
||||
export CC=arm-linux-androideabi-gcc
|
||||
export CXX=arm-linux-androideabi-g++
|
||||
export LINK=arm-linux-androideabi-g++
|
||||
export PLATFORM=android
|
||||
|
||||
if [[ $2 == 'gyp' ]]
|
||||
then
|
||||
./gyp_uv.py -Dtarget_arch=arm -DOS=android -f make-android
|
||||
fi
|
||||
36
libs/libuv/appveyor.yml
Normal file
36
libs/libuv/appveyor.yml
Normal file
@ -0,0 +1,36 @@
|
||||
version: v1.9.1.build{build}
|
||||
|
||||
install:
|
||||
- cinst -y nsis
|
||||
|
||||
matrix:
|
||||
fast_finish: true
|
||||
allow_failures:
|
||||
- platform: x86
|
||||
configuration: Release
|
||||
- platform: x64
|
||||
configuration: Release
|
||||
|
||||
platform:
|
||||
- x86
|
||||
- x64
|
||||
|
||||
configuration:
|
||||
- Release
|
||||
|
||||
build_script:
|
||||
# Fixed tag version number if using a tag.
|
||||
- cmd: if "%APPVEYOR_REPO_TAG%" == "true" set APPVEYOR_BUILD_VERSION=%APPVEYOR_REPO_TAG_NAME%
|
||||
# vcbuild overwrites the platform variable.
|
||||
- cmd: set ARCH=%platform%
|
||||
- cmd: vcbuild.bat release %ARCH% shared
|
||||
|
||||
after_build:
|
||||
- '"%PROGRAMFILES(x86)%\NSIS\makensis" /DVERSION=%APPVEYOR_BUILD_VERSION% /DARCH=%ARCH% libuv.nsi'
|
||||
|
||||
artifacts:
|
||||
- name: Installer
|
||||
path: 'libuv-*.exe'
|
||||
|
||||
cache:
|
||||
- C:\projects\libuv\build\gyp
|
||||
46
libs/libuv/autogen.sh
Normal file
46
libs/libuv/autogen.sh
Normal file
@ -0,0 +1,46 @@
|
||||
#!/bin/sh
|
||||
|
||||
# Copyright (c) 2013, Ben Noordhuis <info@bnoordhuis.nl>
|
||||
#
|
||||
# Permission to use, copy, modify, and/or distribute this software for any
|
||||
# purpose with or without fee is hereby granted, provided that the above
|
||||
# copyright notice and this permission notice appear in all copies.
|
||||
#
|
||||
# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
|
||||
cd `dirname "$0"`
|
||||
|
||||
if [ "$LIBTOOLIZE" = "" ] && [ "`uname`" = "Darwin" ]; then
|
||||
LIBTOOLIZE=glibtoolize
|
||||
fi
|
||||
|
||||
ACLOCAL=${ACLOCAL:-aclocal}
|
||||
AUTOCONF=${AUTOCONF:-autoconf}
|
||||
AUTOMAKE=${AUTOMAKE:-automake}
|
||||
LIBTOOLIZE=${LIBTOOLIZE:-libtoolize}
|
||||
|
||||
automake_version=`"$AUTOMAKE" --version | head -n 1 | sed 's/[^.0-9]//g'`
|
||||
automake_version_major=`echo "$automake_version" | cut -d. -f1`
|
||||
automake_version_minor=`echo "$automake_version" | cut -d. -f2`
|
||||
|
||||
UV_EXTRA_AUTOMAKE_FLAGS=
|
||||
if test "$automake_version_major" -gt 1 || \
|
||||
test "$automake_version_major" -eq 1 && \
|
||||
test "$automake_version_minor" -gt 11; then
|
||||
# serial-tests is available in v1.12 and newer.
|
||||
UV_EXTRA_AUTOMAKE_FLAGS="$UV_EXTRA_AUTOMAKE_FLAGS serial-tests"
|
||||
fi
|
||||
echo "m4_define([UV_EXTRA_AUTOMAKE_FLAGS], [$UV_EXTRA_AUTOMAKE_FLAGS])" \
|
||||
> m4/libuv-extra-automake-flags.m4
|
||||
|
||||
set -ex
|
||||
"$LIBTOOLIZE" --copy
|
||||
"$ACLOCAL" -I m4
|
||||
"$AUTOCONF"
|
||||
"$AUTOMAKE" --add-missing --copy
|
||||
236
libs/libuv/checksparse.sh
Normal file
236
libs/libuv/checksparse.sh
Normal file
@ -0,0 +1,236 @@
|
||||
#!/bin/sh
|
||||
|
||||
# Copyright (c) 2013, Ben Noordhuis <info@bnoordhuis.nl>
|
||||
#
|
||||
# Permission to use, copy, modify, and/or distribute this software for any
|
||||
# purpose with or without fee is hereby granted, provided that the above
|
||||
# copyright notice and this permission notice appear in all copies.
|
||||
#
|
||||
# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
|
||||
SPARSE=${SPARSE:-sparse}
|
||||
|
||||
SPARSE_FLAGS=${SPARSE_FLAGS:-"
|
||||
-D__POSIX__
|
||||
-Wsparse-all
|
||||
-Wno-do-while
|
||||
-Wno-transparent-union
|
||||
-Iinclude
|
||||
-Isrc
|
||||
"}
|
||||
|
||||
SOURCES="
|
||||
include/tree.h
|
||||
include/uv-unix.h
|
||||
include/uv.h
|
||||
src/fs-poll.c
|
||||
src/inet.c
|
||||
src/queue.h
|
||||
src/unix/async.c
|
||||
src/unix/core.c
|
||||
src/unix/dl.c
|
||||
src/unix/fs.c
|
||||
src/unix/getaddrinfo.c
|
||||
src/unix/internal.h
|
||||
src/unix/loop-watcher.c
|
||||
src/unix/loop.c
|
||||
src/unix/pipe.c
|
||||
src/unix/poll.c
|
||||
src/unix/process.c
|
||||
src/unix/signal.c
|
||||
src/unix/stream.c
|
||||
src/unix/tcp.c
|
||||
src/unix/thread.c
|
||||
src/unix/threadpool.c
|
||||
src/unix/timer.c
|
||||
src/unix/tty.c
|
||||
src/unix/udp.c
|
||||
src/uv-common.c
|
||||
src/uv-common.h
|
||||
"
|
||||
|
||||
TESTS="
|
||||
test/benchmark-async-pummel.c
|
||||
test/benchmark-async.c
|
||||
test/benchmark-fs-stat.c
|
||||
test/benchmark-getaddrinfo.c
|
||||
test/benchmark-loop-count.c
|
||||
test/benchmark-million-async.c
|
||||
test/benchmark-million-timers.c
|
||||
test/benchmark-multi-accept.c
|
||||
test/benchmark-ping-pongs.c
|
||||
test/benchmark-pound.c
|
||||
test/benchmark-pump.c
|
||||
test/benchmark-sizes.c
|
||||
test/benchmark-spawn.c
|
||||
test/benchmark-tcp-write-batch.c
|
||||
test/benchmark-thread.c
|
||||
test/benchmark-udp-pummel.c
|
||||
test/blackhole-server.c
|
||||
test/dns-server.c
|
||||
test/echo-server.c
|
||||
test/run-benchmarks.c
|
||||
test/run-tests.c
|
||||
test/runner-unix.c
|
||||
test/runner-unix.h
|
||||
test/runner.c
|
||||
test/runner.h
|
||||
test/task.h
|
||||
test/test-active.c
|
||||
test/test-async.c
|
||||
test/test-barrier.c
|
||||
test/test-callback-order.c
|
||||
test/test-callback-stack.c
|
||||
test/test-condvar.c
|
||||
test/test-connection-fail.c
|
||||
test/test-cwd-and-chdir.c
|
||||
test/test-delayed-accept.c
|
||||
test/test-dlerror.c
|
||||
test/test-embed.c
|
||||
test/test-error.c
|
||||
test/test-fail-always.c
|
||||
test/test-fs-event.c
|
||||
test/test-fs-poll.c
|
||||
test/test-fs.c
|
||||
test/test-get-currentexe.c
|
||||
test/test-get-loadavg.c
|
||||
test/test-get-memory.c
|
||||
test/test-get-passwd.c
|
||||
test/test-getaddrinfo.c
|
||||
test/test-getsockname.c
|
||||
test/test-homedir.c
|
||||
test/test-hrtime.c
|
||||
test/test-idle.c
|
||||
test/test-ip6-addr.c
|
||||
test/test-ipc-send-recv.c
|
||||
test/test-ipc.c
|
||||
test/test-loop-handles.c
|
||||
test/test-multiple-listen.c
|
||||
test/test-mutexes.c
|
||||
test/test-pass-always.c
|
||||
test/test-ping-pong.c
|
||||
test/test-pipe-bind-error.c
|
||||
test/test-pipe-connect-error.c
|
||||
test/test-pipe-sendmsg.c
|
||||
test/test-pipe-server-close.c
|
||||
test/test-platform-output.c
|
||||
test/test-poll-close.c
|
||||
test/test-poll.c
|
||||
test/test-process-title.c
|
||||
test/test-ref.c
|
||||
test/test-run-nowait.c
|
||||
test/test-run-once.c
|
||||
test/test-semaphore.c
|
||||
test/test-shutdown-close.c
|
||||
test/test-shutdown-eof.c
|
||||
test/test-signal-multiple-loops.c
|
||||
test/test-signal.c
|
||||
test/test-spawn.c
|
||||
test/test-stdio-over-pipes.c
|
||||
test/test-tcp-bind-error.c
|
||||
test/test-tcp-bind6-error.c
|
||||
test/test-tcp-close-while-connecting.c
|
||||
test/test-tcp-close-accept.c
|
||||
test/test-tcp-close.c
|
||||
test/test-tcp-connect-error-after-write.c
|
||||
test/test-tcp-connect-error.c
|
||||
test/test-tcp-connect-timeout.c
|
||||
test/test-tcp-connect6-error.c
|
||||
test/test-tcp-flags.c
|
||||
test/test-tcp-open.c
|
||||
test/test-tcp-read-stop.c
|
||||
test/test-tcp-shutdown-after-write.c
|
||||
test/test-tcp-unexpected-read.c
|
||||
test/test-tcp-oob.c
|
||||
test/test-tcp-write-error.c
|
||||
test/test-tcp-write-to-half-open-connection.c
|
||||
test/test-tcp-writealot.c
|
||||
test/test-thread.c
|
||||
test/test-threadpool-cancel.c
|
||||
test/test-threadpool.c
|
||||
test/test-timer-again.c
|
||||
test/test-timer.c
|
||||
test/test-tmpdir.c
|
||||
test/test-tty.c
|
||||
test/test-udp-dgram-too-big.c
|
||||
test/test-udp-ipv6.c
|
||||
test/test-udp-multicast-join.c
|
||||
test/test-udp-multicast-ttl.c
|
||||
test/test-udp-open.c
|
||||
test/test-udp-options.c
|
||||
test/test-udp-send-and-recv.c
|
||||
test/test-walk-handles.c
|
||||
test/test-watcher-cross-stop.c
|
||||
"
|
||||
|
||||
case `uname -s` in
|
||||
AIX)
|
||||
SPARSE_FLAGS="$SPARSE_FLAGS -D_AIX=1"
|
||||
SOURCES="$SOURCES
|
||||
src/unix/aix.c"
|
||||
;;
|
||||
Darwin)
|
||||
SPARSE_FLAGS="$SPARSE_FLAGS -D__APPLE__=1"
|
||||
SOURCES="$SOURCES
|
||||
include/uv-bsd.h
|
||||
src/unix/darwin.c
|
||||
src/unix/kqueue.c
|
||||
src/unix/fsevents.c"
|
||||
;;
|
||||
DragonFly)
|
||||
SPARSE_FLAGS="$SPARSE_FLAGS -D__DragonFly__=1"
|
||||
SOURCES="$SOURCES
|
||||
include/uv-bsd.h
|
||||
src/unix/kqueue.c
|
||||
src/unix/freebsd.c"
|
||||
;;
|
||||
FreeBSD)
|
||||
SPARSE_FLAGS="$SPARSE_FLAGS -D__FreeBSD__=1"
|
||||
SOURCES="$SOURCES
|
||||
include/uv-bsd.h
|
||||
src/unix/kqueue.c
|
||||
src/unix/freebsd.c"
|
||||
;;
|
||||
Linux)
|
||||
SPARSE_FLAGS="$SPARSE_FLAGS -D__linux__=1"
|
||||
SOURCES="$SOURCES
|
||||
include/uv-linux.h
|
||||
src/unix/linux-inotify.c
|
||||
src/unix/linux-core.c
|
||||
src/unix/linux-syscalls.c
|
||||
src/unix/linux-syscalls.h"
|
||||
;;
|
||||
NetBSD)
|
||||
SPARSE_FLAGS="$SPARSE_FLAGS -D__NetBSD__=1"
|
||||
SOURCES="$SOURCES
|
||||
include/uv-bsd.h
|
||||
src/unix/kqueue.c
|
||||
src/unix/netbsd.c"
|
||||
;;
|
||||
OpenBSD)
|
||||
SPARSE_FLAGS="$SPARSE_FLAGS -D__OpenBSD__=1"
|
||||
SOURCES="$SOURCES
|
||||
include/uv-bsd.h
|
||||
src/unix/kqueue.c
|
||||
src/unix/openbsd.c"
|
||||
;;
|
||||
SunOS)
|
||||
SPARSE_FLAGS="$SPARSE_FLAGS -D__sun=1"
|
||||
SOURCES="$SOURCES
|
||||
include/uv-sunos.h
|
||||
src/unix/sunos.c"
|
||||
;;
|
||||
esac
|
||||
|
||||
for ARCH in __i386__ __x86_64__ __arm__ __mips__; do
|
||||
$SPARSE $SPARSE_FLAGS -D$ARCH=1 $SOURCES
|
||||
done
|
||||
|
||||
# Tests are architecture independent.
|
||||
$SPARSE $SPARSE_FLAGS -Itest $TESTS
|
||||
203
libs/libuv/common.gypi
Normal file
203
libs/libuv/common.gypi
Normal file
@ -0,0 +1,203 @@
|
||||
{
|
||||
'variables': {
|
||||
'target_arch%': 'ia32', # set v8's target architecture
|
||||
'host_arch%': 'ia32', # set v8's host architecture
|
||||
'uv_library%': 'static_library', # allow override to 'shared_library' for DLL/.so builds
|
||||
'msvs_multi_core_compile': '0', # we do enable multicore compiles, but not using the V8 way
|
||||
},
|
||||
|
||||
'target_defaults': {
|
||||
'default_configuration': 'Debug',
|
||||
'configurations': {
|
||||
'Debug': {
|
||||
'defines': [ 'DEBUG', '_DEBUG' ],
|
||||
'cflags': [ '-g', '-O0', '-fwrapv' ],
|
||||
'msvs_settings': {
|
||||
'VCCLCompilerTool': {
|
||||
'target_conditions': [
|
||||
['uv_library=="static_library"', {
|
||||
'RuntimeLibrary': 1, # static debug
|
||||
}, {
|
||||
'RuntimeLibrary': 3, # DLL debug
|
||||
}],
|
||||
],
|
||||
'Optimization': 0, # /Od, no optimization
|
||||
'MinimalRebuild': 'false',
|
||||
'OmitFramePointers': 'false',
|
||||
'BasicRuntimeChecks': 3, # /RTC1
|
||||
},
|
||||
'VCLinkerTool': {
|
||||
'LinkIncremental': 2, # enable incremental linking
|
||||
},
|
||||
},
|
||||
'xcode_settings': {
|
||||
'GCC_OPTIMIZATION_LEVEL': '0',
|
||||
'OTHER_CFLAGS': [ '-Wno-strict-aliasing' ],
|
||||
},
|
||||
'conditions': [
|
||||
['OS == "android"', {
|
||||
'cflags': [ '-fPIE' ],
|
||||
'ldflags': [ '-fPIE', '-pie' ]
|
||||
}]
|
||||
]
|
||||
},
|
||||
'Release': {
|
||||
'defines': [ 'NDEBUG' ],
|
||||
'cflags': [
|
||||
'-O3',
|
||||
'-fstrict-aliasing',
|
||||
'-fomit-frame-pointer',
|
||||
'-fdata-sections',
|
||||
'-ffunction-sections',
|
||||
],
|
||||
'msvs_settings': {
|
||||
'VCCLCompilerTool': {
|
||||
'target_conditions': [
|
||||
['uv_library=="static_library"', {
|
||||
'RuntimeLibrary': 0, # static release
|
||||
}, {
|
||||
'RuntimeLibrary': 2, # debug release
|
||||
}],
|
||||
],
|
||||
'Optimization': 3, # /Ox, full optimization
|
||||
'FavorSizeOrSpeed': 1, # /Ot, favour speed over size
|
||||
'InlineFunctionExpansion': 2, # /Ob2, inline anything eligible
|
||||
'WholeProgramOptimization': 'true', # /GL, whole program optimization, needed for LTCG
|
||||
'OmitFramePointers': 'true',
|
||||
'EnableFunctionLevelLinking': 'true',
|
||||
'EnableIntrinsicFunctions': 'true',
|
||||
},
|
||||
'VCLibrarianTool': {
|
||||
'AdditionalOptions': [
|
||||
'/LTCG', # link time code generation
|
||||
],
|
||||
},
|
||||
'VCLinkerTool': {
|
||||
'LinkTimeCodeGeneration': 1, # link-time code generation
|
||||
'OptimizeReferences': 2, # /OPT:REF
|
||||
'EnableCOMDATFolding': 2, # /OPT:ICF
|
||||
'LinkIncremental': 1, # disable incremental linking
|
||||
},
|
||||
},
|
||||
}
|
||||
},
|
||||
'msvs_settings': {
|
||||
'VCCLCompilerTool': {
|
||||
'StringPooling': 'true', # pool string literals
|
||||
'DebugInformationFormat': 3, # Generate a PDB
|
||||
'WarningLevel': 3,
|
||||
'BufferSecurityCheck': 'true',
|
||||
'ExceptionHandling': 1, # /EHsc
|
||||
'SuppressStartupBanner': 'true',
|
||||
'WarnAsError': 'false',
|
||||
'AdditionalOptions': [
|
||||
'/MP', # compile across multiple CPUs
|
||||
],
|
||||
},
|
||||
'VCLibrarianTool': {
|
||||
},
|
||||
'VCLinkerTool': {
|
||||
'GenerateDebugInformation': 'true',
|
||||
'RandomizedBaseAddress': 2, # enable ASLR
|
||||
'DataExecutionPrevention': 2, # enable DEP
|
||||
'AllowIsolation': 'true',
|
||||
'SuppressStartupBanner': 'true',
|
||||
'target_conditions': [
|
||||
['_type=="executable"', {
|
||||
'SubSystem': 1, # console executable
|
||||
}],
|
||||
],
|
||||
},
|
||||
},
|
||||
'conditions': [
|
||||
['OS == "win"', {
|
||||
'msvs_cygwin_shell': 0, # prevent actions from trying to use cygwin
|
||||
'defines': [
|
||||
'WIN32',
|
||||
# we don't really want VC++ warning us about
|
||||
# how dangerous C functions are...
|
||||
'_CRT_SECURE_NO_DEPRECATE',
|
||||
# ... or that C implementations shouldn't use
|
||||
# POSIX names
|
||||
'_CRT_NONSTDC_NO_DEPRECATE',
|
||||
],
|
||||
'target_conditions': [
|
||||
['target_arch=="x64"', {
|
||||
'msvs_configuration_platform': 'x64'
|
||||
}]
|
||||
]
|
||||
}],
|
||||
['OS in "freebsd dragonflybsd linux openbsd solaris android"', {
|
||||
'cflags': [ '-Wall' ],
|
||||
'cflags_cc': [ '-fno-rtti', '-fno-exceptions' ],
|
||||
'target_conditions': [
|
||||
['_type=="static_library"', {
|
||||
'standalone_static_library': 1, # disable thin archive which needs binutils >= 2.19
|
||||
}],
|
||||
],
|
||||
'conditions': [
|
||||
[ 'host_arch != target_arch and target_arch=="ia32"', {
|
||||
'cflags': [ '-m32' ],
|
||||
'ldflags': [ '-m32' ],
|
||||
}],
|
||||
[ 'target_arch=="x32"', {
|
||||
'cflags': [ '-mx32' ],
|
||||
'ldflags': [ '-mx32' ],
|
||||
}],
|
||||
[ 'OS=="linux"', {
|
||||
'cflags': [ '-ansi' ],
|
||||
}],
|
||||
[ 'OS=="solaris"', {
|
||||
'cflags': [ '-pthreads' ],
|
||||
'ldflags': [ '-pthreads' ],
|
||||
}],
|
||||
[ 'OS not in "solaris android"', {
|
||||
'cflags': [ '-pthread' ],
|
||||
'ldflags': [ '-pthread' ],
|
||||
}],
|
||||
],
|
||||
}],
|
||||
['OS=="mac"', {
|
||||
'xcode_settings': {
|
||||
'ALWAYS_SEARCH_USER_PATHS': 'NO',
|
||||
'GCC_CW_ASM_SYNTAX': 'NO', # No -fasm-blocks
|
||||
'GCC_DYNAMIC_NO_PIC': 'NO', # No -mdynamic-no-pic
|
||||
# (Equivalent to -fPIC)
|
||||
'GCC_ENABLE_CPP_EXCEPTIONS': 'NO', # -fno-exceptions
|
||||
'GCC_ENABLE_CPP_RTTI': 'NO', # -fno-rtti
|
||||
'GCC_ENABLE_PASCAL_STRINGS': 'NO', # No -mpascal-strings
|
||||
'GCC_THREADSAFE_STATICS': 'NO', # -fno-threadsafe-statics
|
||||
'PREBINDING': 'NO', # No -Wl,-prebind
|
||||
'USE_HEADERMAP': 'NO',
|
||||
'OTHER_CFLAGS': [
|
||||
'-fstrict-aliasing',
|
||||
],
|
||||
'WARNING_CFLAGS': [
|
||||
'-Wall',
|
||||
'-Wendif-labels',
|
||||
'-W',
|
||||
'-Wno-unused-parameter',
|
||||
],
|
||||
},
|
||||
'conditions': [
|
||||
['target_arch=="ia32"', {
|
||||
'xcode_settings': {'ARCHS': ['i386']},
|
||||
}],
|
||||
['target_arch=="x64"', {
|
||||
'xcode_settings': {'ARCHS': ['x86_64']},
|
||||
}],
|
||||
],
|
||||
'target_conditions': [
|
||||
['_type!="static_library"', {
|
||||
'xcode_settings': {'OTHER_LDFLAGS': ['-Wl,-search_paths_first']},
|
||||
}],
|
||||
],
|
||||
}],
|
||||
['OS=="solaris"', {
|
||||
'cflags': [ '-fno-omit-frame-pointer' ],
|
||||
# pull in V8's postmortem metadata
|
||||
'ldflags': [ '-Wl,-z,allextract' ]
|
||||
}],
|
||||
],
|
||||
},
|
||||
}
|
||||
71
libs/libuv/configure.ac
Normal file
71
libs/libuv/configure.ac
Normal file
@ -0,0 +1,71 @@
|
||||
# Copyright (c) 2013, Ben Noordhuis <info@bnoordhuis.nl>
|
||||
#
|
||||
# Permission to use, copy, modify, and/or distribute this software for any
|
||||
# purpose with or without fee is hereby granted, provided that the above
|
||||
# copyright notice and this permission notice appear in all copies.
|
||||
#
|
||||
# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
|
||||
AC_PREREQ(2.57)
|
||||
AC_INIT([libuv], [1.9.1], [https://github.com/libuv/libuv/issues])
|
||||
AC_CONFIG_MACRO_DIR([m4])
|
||||
m4_include([m4/libuv-extra-automake-flags.m4])
|
||||
m4_include([m4/as_case.m4])
|
||||
m4_include([m4/libuv-check-flags.m4])
|
||||
AM_INIT_AUTOMAKE([-Wall -Werror foreign subdir-objects] UV_EXTRA_AUTOMAKE_FLAGS)
|
||||
AC_CANONICAL_HOST
|
||||
AC_ENABLE_SHARED
|
||||
AC_ENABLE_STATIC
|
||||
AC_PROG_CC
|
||||
AM_PROG_CC_C_O
|
||||
CC_CHECK_CFLAGS_APPEND([-fvisibility=hidden])
|
||||
CC_CHECK_CFLAGS_APPEND([-g])
|
||||
CC_CHECK_CFLAGS_APPEND([-std=gnu89])
|
||||
CC_CHECK_CFLAGS_APPEND([-pedantic])
|
||||
CC_CHECK_CFLAGS_APPEND([-Wall])
|
||||
CC_CHECK_CFLAGS_APPEND([-Wextra])
|
||||
CC_CHECK_CFLAGS_APPEND([-Wno-unused-parameter])
|
||||
# AM_PROG_AR is not available in automake v0.11 but it's essential in v0.12.
|
||||
m4_ifdef([AM_PROG_AR], [AM_PROG_AR])
|
||||
# autoconf complains if AC_PROG_LIBTOOL precedes AM_PROG_AR.
|
||||
AC_PROG_LIBTOOL
|
||||
m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES([yes])])
|
||||
LT_INIT
|
||||
# TODO(bnoordhuis) Check for -pthread vs. -pthreads
|
||||
AC_CHECK_LIB([dl], [dlopen])
|
||||
AC_CHECK_LIB([kstat], [kstat_lookup])
|
||||
AC_CHECK_LIB([kvm], [kvm_open])
|
||||
AC_CHECK_LIB([nsl], [gethostbyname])
|
||||
AC_CHECK_LIB([perfstat], [perfstat_cpu])
|
||||
AC_CHECK_LIB([pthread], [pthread_mutex_init])
|
||||
AC_CHECK_LIB([rt], [clock_gettime])
|
||||
AC_CHECK_LIB([sendfile], [sendfile])
|
||||
AC_CHECK_LIB([socket], [socket])
|
||||
AC_SYS_LARGEFILE
|
||||
AM_CONDITIONAL([AIX], [AS_CASE([$host_os],[aix*], [true], [false])])
|
||||
AM_CONDITIONAL([ANDROID], [AS_CASE([$host_os],[linux-android*],[true], [false])])
|
||||
AM_CONDITIONAL([DARWIN], [AS_CASE([$host_os],[darwin*], [true], [false])])
|
||||
AM_CONDITIONAL([DRAGONFLY],[AS_CASE([$host_os],[dragonfly*], [true], [false])])
|
||||
AM_CONDITIONAL([FREEBSD], [AS_CASE([$host_os],[freebsd*], [true], [false])])
|
||||
AM_CONDITIONAL([LINUX], [AS_CASE([$host_os],[linux*], [true], [false])])
|
||||
AM_CONDITIONAL([NETBSD], [AS_CASE([$host_os],[netbsd*], [true], [false])])
|
||||
AM_CONDITIONAL([OPENBSD], [AS_CASE([$host_os],[openbsd*], [true], [false])])
|
||||
AM_CONDITIONAL([SUNOS], [AS_CASE([$host_os],[solaris*], [true], [false])])
|
||||
AM_CONDITIONAL([WINNT], [AS_CASE([$host_os],[mingw*], [true], [false])])
|
||||
AS_CASE([$host_os],[mingw*], [
|
||||
LIBS="$LIBS -lws2_32 -lpsapi -liphlpapi -lshell32 -luserenv -luser32"
|
||||
])
|
||||
AC_CHECK_HEADERS([sys/ahafs_evProds.h])
|
||||
AC_CHECK_PROG(PKG_CONFIG, pkg-config, yes)
|
||||
AM_CONDITIONAL([HAVE_PKG_CONFIG], [test "x$PKG_CONFIG" != "x"])
|
||||
AS_IF([test "x$PKG_CONFIG" != "x"], [
|
||||
AC_CONFIG_FILES([libuv.pc])
|
||||
])
|
||||
AC_CONFIG_FILES([Makefile])
|
||||
AC_OUTPUT
|
||||
243
libs/libuv/docs/make.bat
Normal file
243
libs/libuv/docs/make.bat
Normal file
@ -0,0 +1,243 @@
|
||||
@ECHO OFF
|
||||
|
||||
REM Command file for Sphinx documentation
|
||||
|
||||
if "%SPHINXBUILD%" == "" (
|
||||
set SPHINXBUILD=sphinx-build
|
||||
)
|
||||
set BUILDDIR=build
|
||||
set SRCDIR=src
|
||||
set ALLSPHINXOPTS=-d %BUILDDIR%/doctrees %SPHINXOPTS% %SRCDIR%
|
||||
set I18NSPHINXOPTS=%SPHINXOPTS% %SRCDIR%
|
||||
if NOT "%PAPER%" == "" (
|
||||
set ALLSPHINXOPTS=-D latex_paper_size=%PAPER% %ALLSPHINXOPTS%
|
||||
set I18NSPHINXOPTS=-D latex_paper_size=%PAPER% %I18NSPHINXOPTS%
|
||||
)
|
||||
|
||||
if "%1" == "" goto help
|
||||
|
||||
if "%1" == "help" (
|
||||
:help
|
||||
echo.Please use `make ^<target^>` where ^<target^> is one of
|
||||
echo. html to make standalone HTML files
|
||||
echo. dirhtml to make HTML files named index.html in directories
|
||||
echo. singlehtml to make a single large HTML file
|
||||
echo. pickle to make pickle files
|
||||
echo. json to make JSON files
|
||||
echo. htmlhelp to make HTML files and a HTML help project
|
||||
echo. qthelp to make HTML files and a qthelp project
|
||||
echo. devhelp to make HTML files and a Devhelp project
|
||||
echo. epub to make an epub
|
||||
echo. latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter
|
||||
echo. text to make text files
|
||||
echo. man to make manual pages
|
||||
echo. texinfo to make Texinfo files
|
||||
echo. gettext to make PO message catalogs
|
||||
echo. changes to make an overview over all changed/added/deprecated items
|
||||
echo. xml to make Docutils-native XML files
|
||||
echo. pseudoxml to make pseudoxml-XML files for display purposes
|
||||
echo. linkcheck to check all external links for integrity
|
||||
echo. doctest to run all doctests embedded in the documentation if enabled
|
||||
goto end
|
||||
)
|
||||
|
||||
if "%1" == "clean" (
|
||||
for /d %%i in (%BUILDDIR%\*) do rmdir /q /s %%i
|
||||
del /q /s %BUILDDIR%\*
|
||||
goto end
|
||||
)
|
||||
|
||||
|
||||
%SPHINXBUILD% 2> nul
|
||||
if errorlevel 9009 (
|
||||
echo.
|
||||
echo.The 'sphinx-build' command was not found. Make sure you have Sphinx
|
||||
echo.installed, then set the SPHINXBUILD environment variable to point
|
||||
echo.to the full path of the 'sphinx-build' executable. Alternatively you
|
||||
echo.may add the Sphinx directory to PATH.
|
||||
echo.
|
||||
echo.If you don't have Sphinx installed, grab it from
|
||||
echo.http://sphinx-doc.org/
|
||||
exit /b 1
|
||||
)
|
||||
|
||||
if "%1" == "html" (
|
||||
%SPHINXBUILD% -b html %ALLSPHINXOPTS% %BUILDDIR%/html
|
||||
if errorlevel 1 exit /b 1
|
||||
echo.
|
||||
echo.Build finished. The HTML pages are in %BUILDDIR%/html.
|
||||
goto end
|
||||
)
|
||||
|
||||
if "%1" == "dirhtml" (
|
||||
%SPHINXBUILD% -b dirhtml %ALLSPHINXOPTS% %BUILDDIR%/dirhtml
|
||||
if errorlevel 1 exit /b 1
|
||||
echo.
|
||||
echo.Build finished. The HTML pages are in %BUILDDIR%/dirhtml.
|
||||
goto end
|
||||
)
|
||||
|
||||
if "%1" == "singlehtml" (
|
||||
%SPHINXBUILD% -b singlehtml %ALLSPHINXOPTS% %BUILDDIR%/singlehtml
|
||||
if errorlevel 1 exit /b 1
|
||||
echo.
|
||||
echo.Build finished. The HTML pages are in %BUILDDIR%/singlehtml.
|
||||
goto end
|
||||
)
|
||||
|
||||
if "%1" == "pickle" (
|
||||
%SPHINXBUILD% -b pickle %ALLSPHINXOPTS% %BUILDDIR%/pickle
|
||||
if errorlevel 1 exit /b 1
|
||||
echo.
|
||||
echo.Build finished; now you can process the pickle files.
|
||||
goto end
|
||||
)
|
||||
|
||||
if "%1" == "json" (
|
||||
%SPHINXBUILD% -b json %ALLSPHINXOPTS% %BUILDDIR%/json
|
||||
if errorlevel 1 exit /b 1
|
||||
echo.
|
||||
echo.Build finished; now you can process the JSON files.
|
||||
goto end
|
||||
)
|
||||
|
||||
if "%1" == "htmlhelp" (
|
||||
%SPHINXBUILD% -b htmlhelp %ALLSPHINXOPTS% %BUILDDIR%/htmlhelp
|
||||
if errorlevel 1 exit /b 1
|
||||
echo.
|
||||
echo.Build finished; now you can run HTML Help Workshop with the ^
|
||||
.hhp project file in %BUILDDIR%/htmlhelp.
|
||||
goto end
|
||||
)
|
||||
|
||||
if "%1" == "qthelp" (
|
||||
%SPHINXBUILD% -b qthelp %ALLSPHINXOPTS% %BUILDDIR%/qthelp
|
||||
if errorlevel 1 exit /b 1
|
||||
echo.
|
||||
echo.Build finished; now you can run "qcollectiongenerator" with the ^
|
||||
.qhcp project file in %BUILDDIR%/qthelp, like this:
|
||||
echo.^> qcollectiongenerator %BUILDDIR%\qthelp\libuv.qhcp
|
||||
echo.To view the help file:
|
||||
echo.^> assistant -collectionFile %BUILDDIR%\qthelp\libuv.ghc
|
||||
goto end
|
||||
)
|
||||
|
||||
if "%1" == "devhelp" (
|
||||
%SPHINXBUILD% -b devhelp %ALLSPHINXOPTS% %BUILDDIR%/devhelp
|
||||
if errorlevel 1 exit /b 1
|
||||
echo.
|
||||
echo.Build finished.
|
||||
goto end
|
||||
)
|
||||
|
||||
if "%1" == "epub" (
|
||||
%SPHINXBUILD% -b epub %ALLSPHINXOPTS% %BUILDDIR%/epub
|
||||
if errorlevel 1 exit /b 1
|
||||
echo.
|
||||
echo.Build finished. The epub file is in %BUILDDIR%/epub.
|
||||
goto end
|
||||
)
|
||||
|
||||
if "%1" == "latex" (
|
||||
%SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex
|
||||
if errorlevel 1 exit /b 1
|
||||
echo.
|
||||
echo.Build finished; the LaTeX files are in %BUILDDIR%/latex.
|
||||
goto end
|
||||
)
|
||||
|
||||
if "%1" == "latexpdf" (
|
||||
%SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex
|
||||
cd %BUILDDIR%/latex
|
||||
make all-pdf
|
||||
cd %BUILDDIR%/..
|
||||
echo.
|
||||
echo.Build finished; the PDF files are in %BUILDDIR%/latex.
|
||||
goto end
|
||||
)
|
||||
|
||||
if "%1" == "latexpdfja" (
|
||||
%SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex
|
||||
cd %BUILDDIR%/latex
|
||||
make all-pdf-ja
|
||||
cd %BUILDDIR%/..
|
||||
echo.
|
||||
echo.Build finished; the PDF files are in %BUILDDIR%/latex.
|
||||
goto end
|
||||
)
|
||||
|
||||
if "%1" == "text" (
|
||||
%SPHINXBUILD% -b text %ALLSPHINXOPTS% %BUILDDIR%/text
|
||||
if errorlevel 1 exit /b 1
|
||||
echo.
|
||||
echo.Build finished. The text files are in %BUILDDIR%/text.
|
||||
goto end
|
||||
)
|
||||
|
||||
if "%1" == "man" (
|
||||
%SPHINXBUILD% -b man %ALLSPHINXOPTS% %BUILDDIR%/man
|
||||
if errorlevel 1 exit /b 1
|
||||
echo.
|
||||
echo.Build finished. The manual pages are in %BUILDDIR%/man.
|
||||
goto end
|
||||
)
|
||||
|
||||
if "%1" == "texinfo" (
|
||||
%SPHINXBUILD% -b texinfo %ALLSPHINXOPTS% %BUILDDIR%/texinfo
|
||||
if errorlevel 1 exit /b 1
|
||||
echo.
|
||||
echo.Build finished. The Texinfo files are in %BUILDDIR%/texinfo.
|
||||
goto end
|
||||
)
|
||||
|
||||
if "%1" == "gettext" (
|
||||
%SPHINXBUILD% -b gettext %I18NSPHINXOPTS% %BUILDDIR%/locale
|
||||
if errorlevel 1 exit /b 1
|
||||
echo.
|
||||
echo.Build finished. The message catalogs are in %BUILDDIR%/locale.
|
||||
goto end
|
||||
)
|
||||
|
||||
if "%1" == "changes" (
|
||||
%SPHINXBUILD% -b changes %ALLSPHINXOPTS% %BUILDDIR%/changes
|
||||
if errorlevel 1 exit /b 1
|
||||
echo.
|
||||
echo.The overview file is in %BUILDDIR%/changes.
|
||||
goto end
|
||||
)
|
||||
|
||||
if "%1" == "linkcheck" (
|
||||
%SPHINXBUILD% -b linkcheck %ALLSPHINXOPTS% %BUILDDIR%/linkcheck
|
||||
if errorlevel 1 exit /b 1
|
||||
echo.
|
||||
echo.Link check complete; look for any errors in the above output ^
|
||||
or in %BUILDDIR%/linkcheck/output.txt.
|
||||
goto end
|
||||
)
|
||||
|
||||
if "%1" == "doctest" (
|
||||
%SPHINXBUILD% -b doctest %ALLSPHINXOPTS% %BUILDDIR%/doctest
|
||||
if errorlevel 1 exit /b 1
|
||||
echo.
|
||||
echo.Testing of doctests in the sources finished, look at the ^
|
||||
results in %BUILDDIR%/doctest/output.txt.
|
||||
goto end
|
||||
)
|
||||
|
||||
if "%1" == "xml" (
|
||||
%SPHINXBUILD% -b xml %ALLSPHINXOPTS% %BUILDDIR%/xml
|
||||
if errorlevel 1 exit /b 1
|
||||
echo.
|
||||
echo.Build finished. The XML files are in %BUILDDIR%/xml.
|
||||
goto end
|
||||
)
|
||||
|
||||
if "%1" == "pseudoxml" (
|
||||
%SPHINXBUILD% -b pseudoxml %ALLSPHINXOPTS% %BUILDDIR%/pseudoxml
|
||||
if errorlevel 1 exit /b 1
|
||||
echo.
|
||||
echo.Build finished. The pseudo-XML files are in %BUILDDIR%/pseudoxml.
|
||||
goto end
|
||||
)
|
||||
|
||||
:end
|
||||
57
libs/libuv/docs/src/async.rst
Normal file
57
libs/libuv/docs/src/async.rst
Normal file
@ -0,0 +1,57 @@
|
||||
|
||||
.. _async:
|
||||
|
||||
:c:type:`uv_async_t` --- Async handle
|
||||
=====================================
|
||||
|
||||
Async handles allow the user to "wakeup" the event loop and get a callback
|
||||
called from another thread.
|
||||
|
||||
|
||||
Data types
|
||||
----------
|
||||
|
||||
.. c:type:: uv_async_t
|
||||
|
||||
Async handle type.
|
||||
|
||||
.. c:type:: void (*uv_async_cb)(uv_async_t* handle)
|
||||
|
||||
Type definition for callback passed to :c:func:`uv_async_init`.
|
||||
|
||||
|
||||
Public members
|
||||
^^^^^^^^^^^^^^
|
||||
|
||||
N/A
|
||||
|
||||
.. seealso:: The :c:type:`uv_handle_t` members also apply.
|
||||
|
||||
|
||||
API
|
||||
---
|
||||
|
||||
.. c:function:: int uv_async_init(uv_loop_t* loop, uv_async_t* async, uv_async_cb async_cb)
|
||||
|
||||
Initialize the handle. A NULL callback is allowed.
|
||||
|
||||
.. note::
|
||||
Unlike other handle initialization functions, it immediately starts the handle.
|
||||
|
||||
.. c:function:: int uv_async_send(uv_async_t* async)
|
||||
|
||||
Wakeup the event loop and call the async handle's callback.
|
||||
|
||||
.. note::
|
||||
It's safe to call this function from any thread. The callback will be called on the
|
||||
loop thread.
|
||||
|
||||
.. warning::
|
||||
libuv will coalesce calls to :c:func:`uv_async_send`, that is, not every call to it will
|
||||
yield an execution of the callback. For example: if :c:func:`uv_async_send` is called 5
|
||||
times in a row before the callback is called, the callback will only be called once. If
|
||||
:c:func:`uv_async_send` is called again after the callback was called, it will be called
|
||||
again.
|
||||
|
||||
.. seealso::
|
||||
The :c:type:`uv_handle_t` API functions also apply.
|
||||
46
libs/libuv/docs/src/check.rst
Normal file
46
libs/libuv/docs/src/check.rst
Normal file
@ -0,0 +1,46 @@
|
||||
|
||||
.. _check:
|
||||
|
||||
:c:type:`uv_check_t` --- Check handle
|
||||
=====================================
|
||||
|
||||
Check handles will run the given callback once per loop iteration, right
|
||||
after polling for i/o.
|
||||
|
||||
|
||||
Data types
|
||||
----------
|
||||
|
||||
.. c:type:: uv_check_t
|
||||
|
||||
Check handle type.
|
||||
|
||||
.. c:type:: void (*uv_check_cb)(uv_check_t* handle)
|
||||
|
||||
Type definition for callback passed to :c:func:`uv_check_start`.
|
||||
|
||||
|
||||
Public members
|
||||
^^^^^^^^^^^^^^
|
||||
|
||||
N/A
|
||||
|
||||
.. seealso:: The :c:type:`uv_handle_t` members also apply.
|
||||
|
||||
|
||||
API
|
||||
---
|
||||
|
||||
.. c:function:: int uv_check_init(uv_loop_t* loop, uv_check_t* check)
|
||||
|
||||
Initialize the handle.
|
||||
|
||||
.. c:function:: int uv_check_start(uv_check_t* check, uv_check_cb cb)
|
||||
|
||||
Start the handle with the given callback.
|
||||
|
||||
.. c:function:: int uv_check_stop(uv_check_t* check)
|
||||
|
||||
Stop the handle, the callback will no longer be called.
|
||||
|
||||
.. seealso:: The :c:type:`uv_handle_t` API functions also apply.
|
||||
348
libs/libuv/docs/src/conf.py
Normal file
348
libs/libuv/docs/src/conf.py
Normal file
@ -0,0 +1,348 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# libuv API documentation documentation build configuration file, created by
|
||||
# sphinx-quickstart on Sun Jul 27 11:47:51 2014.
|
||||
#
|
||||
# This file is execfile()d with the current directory set to its
|
||||
# containing dir.
|
||||
#
|
||||
# Note that not all possible configuration values are present in this
|
||||
# autogenerated file.
|
||||
#
|
||||
# All configuration values have a default; values that are commented out
|
||||
# serve to show the default.
|
||||
|
||||
import os
|
||||
import re
|
||||
import sys
|
||||
|
||||
|
||||
def get_libuv_version():
|
||||
with open('../../include/uv-version.h') as f:
|
||||
data = f.read()
|
||||
try:
|
||||
m = re.search(r"""^#define UV_VERSION_MAJOR (\d)$""", data, re.MULTILINE)
|
||||
major = int(m.group(1))
|
||||
m = re.search(r"""^#define UV_VERSION_MINOR (\d)$""", data, re.MULTILINE)
|
||||
minor = int(m.group(1))
|
||||
m = re.search(r"""^#define UV_VERSION_PATCH (\d)$""", data, re.MULTILINE)
|
||||
patch = int(m.group(1))
|
||||
m = re.search(r"""^#define UV_VERSION_IS_RELEASE (\d)$""", data, re.MULTILINE)
|
||||
is_release = int(m.group(1))
|
||||
m = re.search(r"""^#define UV_VERSION_SUFFIX \"(\w*)\"$""", data, re.MULTILINE)
|
||||
suffix = m.group(1)
|
||||
return '%d.%d.%d%s' % (major, minor, patch, '-%s' % suffix if not is_release else '')
|
||||
except Exception:
|
||||
return 'unknown'
|
||||
|
||||
# If extensions (or modules to document with autodoc) are in another directory,
|
||||
# add these directories to sys.path here. If the directory is relative to the
|
||||
# documentation root, use os.path.abspath to make it absolute, like shown here.
|
||||
sys.path.insert(0, os.path.abspath('sphinx-plugins'))
|
||||
|
||||
# -- General configuration ------------------------------------------------
|
||||
|
||||
# If your documentation needs a minimal Sphinx version, state it here.
|
||||
#needs_sphinx = '1.0'
|
||||
|
||||
# Add any Sphinx extension module names here, as strings. They can be
|
||||
# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
|
||||
# ones.
|
||||
extensions = ['manpage']
|
||||
|
||||
# Add any paths that contain templates here, relative to this directory.
|
||||
templates_path = ['templates']
|
||||
|
||||
# The suffix of source filenames.
|
||||
source_suffix = '.rst'
|
||||
|
||||
# The encoding of source files.
|
||||
#source_encoding = 'utf-8-sig'
|
||||
|
||||
# The master toctree document.
|
||||
master_doc = 'index'
|
||||
|
||||
# General information about the project.
|
||||
project = u'libuv API documentation'
|
||||
copyright = u'libuv contributors'
|
||||
|
||||
# The version info for the project you're documenting, acts as replacement for
|
||||
# |version| and |release|, also used in various other places throughout the
|
||||
# built documents.
|
||||
#
|
||||
# The short X.Y version.
|
||||
version = get_libuv_version()
|
||||
# The full version, including alpha/beta/rc tags.
|
||||
release = version
|
||||
|
||||
# The language for content autogenerated by Sphinx. Refer to documentation
|
||||
# for a list of supported languages.
|
||||
#language = None
|
||||
|
||||
# There are two options for replacing |today|: either, you set today to some
|
||||
# non-false value, then it is used:
|
||||
#today = ''
|
||||
# Else, today_fmt is used as the format for a strftime call.
|
||||
#today_fmt = '%B %d, %Y'
|
||||
|
||||
# List of patterns, relative to source directory, that match files and
|
||||
# directories to ignore when looking for source files.
|
||||
exclude_patterns = []
|
||||
|
||||
# The reST default role (used for this markup: `text`) to use for all
|
||||
# documents.
|
||||
#default_role = None
|
||||
|
||||
# If true, '()' will be appended to :func: etc. cross-reference text.
|
||||
#add_function_parentheses = True
|
||||
|
||||
# If true, the current module name will be prepended to all description
|
||||
# unit titles (such as .. function::).
|
||||
#add_module_names = True
|
||||
|
||||
# If true, sectionauthor and moduleauthor directives will be shown in the
|
||||
# output. They are ignored by default.
|
||||
#show_authors = False
|
||||
|
||||
# The name of the Pygments (syntax highlighting) style to use.
|
||||
pygments_style = 'sphinx'
|
||||
|
||||
# A list of ignored prefixes for module index sorting.
|
||||
#modindex_common_prefix = []
|
||||
|
||||
# If true, keep warnings as "system message" paragraphs in the built documents.
|
||||
#keep_warnings = False
|
||||
|
||||
|
||||
# -- Options for HTML output ----------------------------------------------
|
||||
|
||||
# The theme to use for HTML and HTML Help pages. See the documentation for
|
||||
# a list of builtin themes.
|
||||
html_theme = 'nature'
|
||||
|
||||
# Theme options are theme-specific and customize the look and feel of a theme
|
||||
# further. For a list of options available for each theme, see the
|
||||
# documentation.
|
||||
#html_theme_options = {}
|
||||
|
||||
# Add any paths that contain custom themes here, relative to this directory.
|
||||
#html_theme_path = []
|
||||
|
||||
# The name for this set of Sphinx documents. If None, it defaults to
|
||||
# "<project> v<release> documentation".
|
||||
html_title = 'libuv API documentation'
|
||||
|
||||
# A shorter title for the navigation bar. Default is the same as html_title.
|
||||
html_short_title = 'libuv %s API documentation' % version
|
||||
|
||||
# The name of an image file (relative to this directory) to place at the top
|
||||
# of the sidebar.
|
||||
html_logo = 'static/logo.png'
|
||||
|
||||
# The name of an image file (within the static path) to use as favicon of the
|
||||
# docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32
|
||||
# pixels large.
|
||||
html_favicon = 'static/favicon.ico'
|
||||
|
||||
# Add any paths that contain custom static files (such as style sheets) here,
|
||||
# relative to this directory. They are copied after the builtin static files,
|
||||
# so a file named "default.css" will overwrite the builtin "default.css".
|
||||
html_static_path = ['static']
|
||||
|
||||
# Add any extra paths that contain custom files (such as robots.txt or
|
||||
# .htaccess) here, relative to this directory. These files are copied
|
||||
# directly to the root of the documentation.
|
||||
#html_extra_path = []
|
||||
|
||||
# If not '', a 'Last updated on:' timestamp is inserted at every page bottom,
|
||||
# using the given strftime format.
|
||||
#html_last_updated_fmt = '%b %d, %Y'
|
||||
|
||||
# If true, SmartyPants will be used to convert quotes and dashes to
|
||||
# typographically correct entities.
|
||||
#html_use_smartypants = True
|
||||
|
||||
# Custom sidebar templates, maps document names to template names.
|
||||
#html_sidebars = {}
|
||||
|
||||
# Additional templates that should be rendered to pages, maps page names to
|
||||
# template names.
|
||||
#html_additional_pages = {}
|
||||
|
||||
# If false, no module index is generated.
|
||||
#html_domain_indices = True
|
||||
|
||||
# If false, no index is generated.
|
||||
#html_use_index = True
|
||||
|
||||
# If true, the index is split into individual pages for each letter.
|
||||
#html_split_index = False
|
||||
|
||||
# If true, links to the reST sources are added to the pages.
|
||||
#html_show_sourcelink = True
|
||||
|
||||
# If true, "Created using Sphinx" is shown in the HTML footer. Default is True.
|
||||
#html_show_sphinx = True
|
||||
|
||||
# If true, "(C) Copyright ..." is shown in the HTML footer. Default is True.
|
||||
#html_show_copyright = True
|
||||
|
||||
# If true, an OpenSearch description file will be output, and all pages will
|
||||
# contain a <link> tag referring to it. The value of this option must be the
|
||||
# base URL from which the finished HTML is served.
|
||||
#html_use_opensearch = ''
|
||||
|
||||
# This is the file name suffix for HTML files (e.g. ".xhtml").
|
||||
#html_file_suffix = None
|
||||
|
||||
# Output file base name for HTML help builder.
|
||||
htmlhelp_basename = 'libuv'
|
||||
|
||||
|
||||
# -- Options for LaTeX output ---------------------------------------------
|
||||
|
||||
latex_elements = {
|
||||
# The paper size ('letterpaper' or 'a4paper').
|
||||
#'papersize': 'letterpaper',
|
||||
|
||||
# The font size ('10pt', '11pt' or '12pt').
|
||||
#'pointsize': '10pt',
|
||||
|
||||
# Additional stuff for the LaTeX preamble.
|
||||
#'preamble': '',
|
||||
}
|
||||
|
||||
# Grouping the document tree into LaTeX files. List of tuples
|
||||
# (source start file, target name, title,
|
||||
# author, documentclass [howto, manual, or own class]).
|
||||
latex_documents = [
|
||||
('index', 'libuv.tex', u'libuv API documentation',
|
||||
u'libuv contributors', 'manual'),
|
||||
]
|
||||
|
||||
# The name of an image file (relative to this directory) to place at the top of
|
||||
# the title page.
|
||||
#latex_logo = None
|
||||
|
||||
# For "manual" documents, if this is true, then toplevel headings are parts,
|
||||
# not chapters.
|
||||
#latex_use_parts = False
|
||||
|
||||
# If true, show page references after internal links.
|
||||
#latex_show_pagerefs = False
|
||||
|
||||
# If true, show URL addresses after external links.
|
||||
#latex_show_urls = False
|
||||
|
||||
# Documents to append as an appendix to all manuals.
|
||||
#latex_appendices = []
|
||||
|
||||
# If false, no module index is generated.
|
||||
#latex_domain_indices = True
|
||||
|
||||
|
||||
# -- Options for manual page output ---------------------------------------
|
||||
|
||||
# One entry per manual page. List of tuples
|
||||
# (source start file, name, description, authors, manual section).
|
||||
man_pages = [
|
||||
('index', 'libuv', u'libuv API documentation',
|
||||
[u'libuv contributors'], 1)
|
||||
]
|
||||
|
||||
# If true, show URL addresses after external links.
|
||||
#man_show_urls = False
|
||||
|
||||
|
||||
# -- Options for Texinfo output -------------------------------------------
|
||||
|
||||
# Grouping the document tree into Texinfo files. List of tuples
|
||||
# (source start file, target name, title, author,
|
||||
# dir menu entry, description, category)
|
||||
texinfo_documents = [
|
||||
('index', 'libuv', u'libuv API documentation',
|
||||
u'libuv contributors', 'libuv', 'Cross-platform asynchronous I/O',
|
||||
'Miscellaneous'),
|
||||
]
|
||||
|
||||
# Documents to append as an appendix to all manuals.
|
||||
#texinfo_appendices = []
|
||||
|
||||
# If false, no module index is generated.
|
||||
#texinfo_domain_indices = True
|
||||
|
||||
# How to display URL addresses: 'footnote', 'no', or 'inline'.
|
||||
#texinfo_show_urls = 'footnote'
|
||||
|
||||
# If true, do not generate a @detailmenu in the "Top" node's menu.
|
||||
#texinfo_no_detailmenu = False
|
||||
|
||||
|
||||
# -- Options for Epub output ----------------------------------------------
|
||||
|
||||
# Bibliographic Dublin Core info.
|
||||
epub_title = u'libuv API documentation'
|
||||
epub_author = u'libuv contributors'
|
||||
epub_publisher = u'libuv contributors'
|
||||
epub_copyright = u'2014, libuv contributors'
|
||||
|
||||
# The basename for the epub file. It defaults to the project name.
|
||||
epub_basename = u'libuv'
|
||||
|
||||
# The HTML theme for the epub output. Since the default themes are not optimized
|
||||
# for small screen space, using the same theme for HTML and epub output is
|
||||
# usually not wise. This defaults to 'epub', a theme designed to save visual
|
||||
# space.
|
||||
#epub_theme = 'epub'
|
||||
|
||||
# The language of the text. It defaults to the language option
|
||||
# or en if the language is not set.
|
||||
#epub_language = ''
|
||||
|
||||
# The scheme of the identifier. Typical schemes are ISBN or URL.
|
||||
#epub_scheme = ''
|
||||
|
||||
# The unique identifier of the text. This can be a ISBN number
|
||||
# or the project homepage.
|
||||
#epub_identifier = ''
|
||||
|
||||
# A unique identification for the text.
|
||||
#epub_uid = ''
|
||||
|
||||
# A tuple containing the cover image and cover page html template filenames.
|
||||
#epub_cover = ()
|
||||
|
||||
# A sequence of (type, uri, title) tuples for the guide element of content.opf.
|
||||
#epub_guide = ()
|
||||
|
||||
# HTML files that should be inserted before the pages created by sphinx.
|
||||
# The format is a list of tuples containing the path and title.
|
||||
#epub_pre_files = []
|
||||
|
||||
# HTML files shat should be inserted after the pages created by sphinx.
|
||||
# The format is a list of tuples containing the path and title.
|
||||
#epub_post_files = []
|
||||
|
||||
# A list of files that should not be packed into the epub file.
|
||||
epub_exclude_files = ['search.html']
|
||||
|
||||
# The depth of the table of contents in toc.ncx.
|
||||
#epub_tocdepth = 3
|
||||
|
||||
# Allow duplicate toc entries.
|
||||
#epub_tocdup = True
|
||||
|
||||
# Choose between 'default' and 'includehidden'.
|
||||
#epub_tocscope = 'default'
|
||||
|
||||
# Fix unsupported image types using the PIL.
|
||||
#epub_fix_images = False
|
||||
|
||||
# Scale large images.
|
||||
#epub_max_image_width = 0
|
||||
|
||||
# How to display URL addresses: 'footnote', 'no', or 'inline'.
|
||||
#epub_show_urls = 'inline'
|
||||
|
||||
# If false, no index is generated.
|
||||
#epub_use_index = True
|
||||
137
libs/libuv/docs/src/design.rst
Normal file
137
libs/libuv/docs/src/design.rst
Normal file
@ -0,0 +1,137 @@
|
||||
|
||||
.. _design:
|
||||
|
||||
Design overview
|
||||
===============
|
||||
|
||||
libuv is cross-platform support library which was originally written for NodeJS. It's designed
|
||||
around the event-driven asynchronous I/O model.
|
||||
|
||||
The library provides much more than simply abstraction over different I/O polling mechanisms:
|
||||
'handles' and 'streams' provide a high level abstraction for sockets and other entities;
|
||||
cross-platform file I/O and threading functionality is also provided, amongst other things.
|
||||
|
||||
Here is a diagram illustrating the different parts that compose libuv and what subsystem they
|
||||
relate to:
|
||||
|
||||
.. image:: static/architecture.png
|
||||
:scale: 75%
|
||||
:align: center
|
||||
|
||||
|
||||
Handles and requests
|
||||
^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
libuv provides users with 2 abstractions to work with, in combination with the event loop:
|
||||
handles and requests.
|
||||
|
||||
Handles represent long-lived objects capable of performing certain operations while active. Some
|
||||
examples: a prepare handle gets its callback called once every loop iteration when active, and
|
||||
a TCP server handle get its connection callback called every time there is a new connection.
|
||||
|
||||
Requests represent (typically) short-lived operations. These operations can be performed over a
|
||||
handle: write requests are used to write data on a handle; or standalone: getaddrinfo requests
|
||||
don't need a handle they run directly on the loop.
|
||||
|
||||
|
||||
The I/O loop
|
||||
^^^^^^^^^^^^
|
||||
|
||||
The I/O (or event) loop is the central part of libuv. It establishes the content for all I/O
|
||||
operations, and it's meant to be tied to a single thread. One can run multiple event loops
|
||||
as long as each runs in a different thread. The libuv event loop (or any other API involving
|
||||
the loop or handles, for that matter) **is not thread-safe** except where stated otherwise.
|
||||
|
||||
The event loop follows the rather usual single threaded asynchronous I/O approach: all (network)
|
||||
I/O is performed on non-blocking sockets which are polled using the best mechanism available
|
||||
on the given platform: epoll on Linux, kqueue on OSX and other BSDs, event ports on SunOS and IOCP
|
||||
on Windows. As part of a loop iteration the loop will block waiting for I/O activity on sockets
|
||||
which have been added to the poller and callbacks will be fired indicating socket conditions
|
||||
(readable, writable hangup) so handles can read, write or perform the desired I/O operation.
|
||||
|
||||
In order to better understand how the event loop operates, the following diagram illustrates all
|
||||
stages of a loop iteration:
|
||||
|
||||
.. image:: static/loop_iteration.png
|
||||
:scale: 75%
|
||||
:align: center
|
||||
|
||||
|
||||
#. The loop concept of 'now' is updated. The event loop caches the current time at the start of
|
||||
the event loop tick in order to reduce the number of time-related system calls.
|
||||
|
||||
#. If the loop is *alive* an iteration is started, otherwise the loop will exit immediately. So,
|
||||
when is a loop considered to be *alive*? If a loop has active and ref'd handles, active
|
||||
requests or closing handles it's considered to be *alive*.
|
||||
|
||||
#. Due timers are run. All active timers scheduled for a time before the loop's concept of *now*
|
||||
get their callbacks called.
|
||||
|
||||
#. Pending callbacks are called. All I/O callbacks are called right after polling for I/O, for the
|
||||
most part. There are cases, however, in which calling such a callback is deferred for the next
|
||||
loop iteration. If the previous iteration deferred any I/O callback it will be run at this point.
|
||||
|
||||
#. Idle handle callbacks are called. Despite the unfortunate name, idle handles are run on every
|
||||
loop iteration, if they are active.
|
||||
|
||||
#. Prepare handle callbacks are called. Prepare handles get their callbacks called right before
|
||||
the loop will block for I/O.
|
||||
|
||||
#. Poll timeout is calculated. Before blocking for I/O the loop calculates for how long it should
|
||||
block. These are the rules when calculating the timeout:
|
||||
|
||||
* If the loop was run with the ``UV_RUN_NOWAIT`` flag, the timeout is 0.
|
||||
* If the loop is going to be stopped (:c:func:`uv_stop` was called), the timeout is 0.
|
||||
* If there are no active handles or requests, the timeout is 0.
|
||||
* If there are any idle handles active, the timeout is 0.
|
||||
* If there are any handles pending to be closed, the timeout is 0.
|
||||
* If none of the above cases was matched, the timeout of the closest timer is taken, or
|
||||
if there are no active timers, infinity.
|
||||
|
||||
#. The loop blocks for I/O. At this point the loop will block for I/O for the timeout calculated
|
||||
on the previous step. All I/O related handles that were monitoring a given file descriptor
|
||||
for a read or write operation get their callbacks called at this point.
|
||||
|
||||
#. Check handle callbacks are called. Check handles get their callbacks called right after the
|
||||
loop has blocked for I/O. Check handles are essentially the counterpart of prepare handles.
|
||||
|
||||
#. Close callbacks are called. If a handle was closed by calling :c:func:`uv_close` it will
|
||||
get the close callback called.
|
||||
|
||||
#. Special case in case the loop was run with ``UV_RUN_ONCE``, as it implies forward progress.
|
||||
It's possible that no I/O callbacks were fired after blocking for I/O, but some time has passed
|
||||
so there might be timers which are due, those timers get their callbacks called.
|
||||
|
||||
#. Iteration ends. If the loop was run with ``UV_RUN_NOWAIT`` or ``UV_RUN_ONCE`` modes the
|
||||
iteration is ended and :c:func:`uv_run` will return. If the loop was run with ``UV_RUN_DEFAULT``
|
||||
it will continue from the start if it's still *alive*, otherwise it will also end.
|
||||
|
||||
|
||||
.. important::
|
||||
libuv uses a thread pool to make asynchronous file I/O operations possible, but
|
||||
network I/O is **always** performed in a single thread, each loop's thread.
|
||||
|
||||
.. note::
|
||||
While the polling mechanism is different, libuv makes the execution model consistent
|
||||
across Unix systems and Windows.
|
||||
|
||||
|
||||
File I/O
|
||||
^^^^^^^^
|
||||
|
||||
Unlike network I/O, there are no platform-specific file I/O primitives libuv could rely on,
|
||||
so the current approach is to run blocking file I/O operations in a thread pool.
|
||||
|
||||
For a thorough explanation of the cross-platform file I/O landscape, checkout
|
||||
`this post <http://blog.libtorrent.org/2012/10/asynchronous-disk-io/>`_.
|
||||
|
||||
libuv currently uses a global thread pool on which all loops can queue work on. 3 types of
|
||||
operations are currently run on this pool:
|
||||
|
||||
* Filesystem operations
|
||||
* DNS functions (getaddrinfo and getnameinfo)
|
||||
* User specified code via :c:func:`uv_queue_work`
|
||||
|
||||
.. warning::
|
||||
See the :c:ref:`threadpool` section for more details, but keep in mind the thread pool size
|
||||
is quite limited.
|
||||
44
libs/libuv/docs/src/dll.rst
Normal file
44
libs/libuv/docs/src/dll.rst
Normal file
@ -0,0 +1,44 @@
|
||||
|
||||
.. _dll:
|
||||
|
||||
Shared library handling
|
||||
=======================
|
||||
|
||||
libuv provides cross platform utilities for loading shared libraries and
|
||||
retrieving symbols from them, using the following API.
|
||||
|
||||
|
||||
Data types
|
||||
----------
|
||||
|
||||
.. c:type:: uv_lib_t
|
||||
|
||||
Shared library data type.
|
||||
|
||||
|
||||
Public members
|
||||
^^^^^^^^^^^^^^
|
||||
|
||||
N/A
|
||||
|
||||
|
||||
API
|
||||
---
|
||||
|
||||
.. c:function:: int uv_dlopen(const char* filename, uv_lib_t* lib)
|
||||
|
||||
Opens a shared library. The filename is in utf-8. Returns 0 on success and
|
||||
-1 on error. Call :c:func:`uv_dlerror` to get the error message.
|
||||
|
||||
.. c:function:: void uv_dlclose(uv_lib_t* lib)
|
||||
|
||||
Close the shared library.
|
||||
|
||||
.. c:function:: int uv_dlsym(uv_lib_t* lib, const char* name, void** ptr)
|
||||
|
||||
Retrieves a data pointer from a dynamic library. It is legal for a symbol
|
||||
to map to NULL. Returns 0 on success and -1 if the symbol was not found.
|
||||
|
||||
.. c:function:: const char* uv_dlerror(const uv_lib_t* lib)
|
||||
|
||||
Returns the last uv_dlopen() or uv_dlsym() error message.
|
||||
108
libs/libuv/docs/src/dns.rst
Normal file
108
libs/libuv/docs/src/dns.rst
Normal file
@ -0,0 +1,108 @@
|
||||
|
||||
.. _dns:
|
||||
|
||||
DNS utility functions
|
||||
=====================
|
||||
|
||||
libuv provides asynchronous variants of `getaddrinfo` and `getnameinfo`.
|
||||
|
||||
|
||||
Data types
|
||||
----------
|
||||
|
||||
.. c:type:: uv_getaddrinfo_t
|
||||
|
||||
`getaddrinfo` request type.
|
||||
|
||||
.. c:type:: void (*uv_getaddrinfo_cb)(uv_getaddrinfo_t* req, int status, struct addrinfo* res)
|
||||
|
||||
Callback which will be called with the getaddrinfo request result once
|
||||
complete. In case it was cancelled, `status` will have a value of
|
||||
``UV_ECANCELED``.
|
||||
|
||||
.. c:type:: uv_getnameinfo_t
|
||||
|
||||
`getnameinfo` request type.
|
||||
|
||||
.. c:type:: void (*uv_getnameinfo_cb)(uv_getnameinfo_t* req, int status, const char* hostname, const char* service)
|
||||
|
||||
Callback which will be called with the getnameinfo request result once
|
||||
complete. In case it was cancelled, `status` will have a value of
|
||||
``UV_ECANCELED``.
|
||||
|
||||
|
||||
Public members
|
||||
^^^^^^^^^^^^^^
|
||||
|
||||
.. c:member:: uv_loop_t* uv_getaddrinfo_t.loop
|
||||
|
||||
Loop that started this getaddrinfo request and where completion will be
|
||||
reported. Readonly.
|
||||
|
||||
.. c:member:: struct addrinfo* uv_getaddrinfo_t.addrinfo
|
||||
|
||||
Pointer to a `struct addrinfo` containing the result. Must be freed by the user
|
||||
with :c:func:`uv_freeaddrinfo`.
|
||||
|
||||
.. versionchanged:: 1.3.0 the field is declared as public.
|
||||
|
||||
.. c:member:: uv_loop_t* uv_getnameinfo_t.loop
|
||||
|
||||
Loop that started this getnameinfo request and where completion will be
|
||||
reported. Readonly.
|
||||
|
||||
.. c:member:: char[NI_MAXHOST] uv_getnameinfo_t.host
|
||||
|
||||
Char array containing the resulting host. It's null terminated.
|
||||
|
||||
.. versionchanged:: 1.3.0 the field is declared as public.
|
||||
|
||||
.. c:member:: char[NI_MAXSERV] uv_getnameinfo_t.service
|
||||
|
||||
Char array containing the resulting service. It's null terminated.
|
||||
|
||||
.. versionchanged:: 1.3.0 the field is declared as public.
|
||||
|
||||
.. seealso:: The :c:type:`uv_req_t` members also apply.
|
||||
|
||||
|
||||
API
|
||||
---
|
||||
|
||||
.. c:function:: int uv_getaddrinfo(uv_loop_t* loop, uv_getaddrinfo_t* req, uv_getaddrinfo_cb getaddrinfo_cb, const char* node, const char* service, const struct addrinfo* hints)
|
||||
|
||||
Asynchronous :man:`getaddrinfo(3)`.
|
||||
|
||||
Either node or service may be NULL but not both.
|
||||
|
||||
`hints` is a pointer to a struct addrinfo with additional address type
|
||||
constraints, or NULL. Consult `man -s 3 getaddrinfo` for more details.
|
||||
|
||||
Returns 0 on success or an error code < 0 on failure. If successful, the
|
||||
callback will get called sometime in the future with the lookup result,
|
||||
which is either:
|
||||
|
||||
* status == 0, the res argument points to a valid `struct addrinfo`, or
|
||||
* status < 0, the res argument is NULL. See the UV_EAI_* constants.
|
||||
|
||||
Call :c:func:`uv_freeaddrinfo` to free the addrinfo structure.
|
||||
|
||||
.. versionchanged:: 1.3.0 the callback parameter is now allowed to be NULL,
|
||||
in which case the request will run **synchronously**.
|
||||
|
||||
.. c:function:: void uv_freeaddrinfo(struct addrinfo* ai)
|
||||
|
||||
Free the struct addrinfo. Passing NULL is allowed and is a no-op.
|
||||
|
||||
.. c:function:: int uv_getnameinfo(uv_loop_t* loop, uv_getnameinfo_t* req, uv_getnameinfo_cb getnameinfo_cb, const struct sockaddr* addr, int flags)
|
||||
|
||||
Asynchronous :man:`getnameinfo(3)`.
|
||||
|
||||
Returns 0 on success or an error code < 0 on failure. If successful, the
|
||||
callback will get called sometime in the future with the lookup result.
|
||||
Consult `man -s 3 getnameinfo` for more details.
|
||||
|
||||
.. versionchanged:: 1.3.0 the callback parameter is now allowed to be NULL,
|
||||
in which case the request will run **synchronously**.
|
||||
|
||||
.. seealso:: The :c:type:`uv_req_t` API functions also apply.
|
||||
331
libs/libuv/docs/src/errors.rst
Normal file
331
libs/libuv/docs/src/errors.rst
Normal file
@ -0,0 +1,331 @@
|
||||
|
||||
.. _errors:
|
||||
|
||||
Error handling
|
||||
==============
|
||||
|
||||
In libuv errors are negative numbered constants. As a rule of thumb, whenever
|
||||
there is a status parameter, or an API functions returns an integer, a negative
|
||||
number will imply an error.
|
||||
|
||||
.. note::
|
||||
Implementation detail: on Unix error codes are the negated `errno` (or `-errno`), while on
|
||||
Windows they are defined by libuv to arbitrary negative numbers.
|
||||
|
||||
|
||||
Error constants
|
||||
---------------
|
||||
|
||||
.. c:macro:: UV_E2BIG
|
||||
|
||||
argument list too long
|
||||
|
||||
.. c:macro:: UV_EACCES
|
||||
|
||||
permission denied
|
||||
|
||||
.. c:macro:: UV_EADDRINUSE
|
||||
|
||||
address already in use
|
||||
|
||||
.. c:macro:: UV_EADDRNOTAVAIL
|
||||
|
||||
address not available
|
||||
|
||||
.. c:macro:: UV_EAFNOSUPPORT
|
||||
|
||||
address family not supported
|
||||
|
||||
.. c:macro:: UV_EAGAIN
|
||||
|
||||
resource temporarily unavailable
|
||||
|
||||
.. c:macro:: UV_EAI_ADDRFAMILY
|
||||
|
||||
address family not supported
|
||||
|
||||
.. c:macro:: UV_EAI_AGAIN
|
||||
|
||||
temporary failure
|
||||
|
||||
.. c:macro:: UV_EAI_BADFLAGS
|
||||
|
||||
bad ai_flags value
|
||||
|
||||
.. c:macro:: UV_EAI_BADHINTS
|
||||
|
||||
invalid value for hints
|
||||
|
||||
.. c:macro:: UV_EAI_CANCELED
|
||||
|
||||
request canceled
|
||||
|
||||
.. c:macro:: UV_EAI_FAIL
|
||||
|
||||
permanent failure
|
||||
|
||||
.. c:macro:: UV_EAI_FAMILY
|
||||
|
||||
ai_family not supported
|
||||
|
||||
.. c:macro:: UV_EAI_MEMORY
|
||||
|
||||
out of memory
|
||||
|
||||
.. c:macro:: UV_EAI_NODATA
|
||||
|
||||
no address
|
||||
|
||||
.. c:macro:: UV_EAI_NONAME
|
||||
|
||||
unknown node or service
|
||||
|
||||
.. c:macro:: UV_EAI_OVERFLOW
|
||||
|
||||
argument buffer overflow
|
||||
|
||||
.. c:macro:: UV_EAI_PROTOCOL
|
||||
|
||||
resolved protocol is unknown
|
||||
|
||||
.. c:macro:: UV_EAI_SERVICE
|
||||
|
||||
service not available for socket type
|
||||
|
||||
.. c:macro:: UV_EAI_SOCKTYPE
|
||||
|
||||
socket type not supported
|
||||
|
||||
.. c:macro:: UV_EALREADY
|
||||
|
||||
connection already in progress
|
||||
|
||||
.. c:macro:: UV_EBADF
|
||||
|
||||
bad file descriptor
|
||||
|
||||
.. c:macro:: UV_EBUSY
|
||||
|
||||
resource busy or locked
|
||||
|
||||
.. c:macro:: UV_ECANCELED
|
||||
|
||||
operation canceled
|
||||
|
||||
.. c:macro:: UV_ECHARSET
|
||||
|
||||
invalid Unicode character
|
||||
|
||||
.. c:macro:: UV_ECONNABORTED
|
||||
|
||||
software caused connection abort
|
||||
|
||||
.. c:macro:: UV_ECONNREFUSED
|
||||
|
||||
connection refused
|
||||
|
||||
.. c:macro:: UV_ECONNRESET
|
||||
|
||||
connection reset by peer
|
||||
|
||||
.. c:macro:: UV_EDESTADDRREQ
|
||||
|
||||
destination address required
|
||||
|
||||
.. c:macro:: UV_EEXIST
|
||||
|
||||
file already exists
|
||||
|
||||
.. c:macro:: UV_EFAULT
|
||||
|
||||
bad address in system call argument
|
||||
|
||||
.. c:macro:: UV_EFBIG
|
||||
|
||||
file too large
|
||||
|
||||
.. c:macro:: UV_EHOSTUNREACH
|
||||
|
||||
host is unreachable
|
||||
|
||||
.. c:macro:: UV_EINTR
|
||||
|
||||
interrupted system call
|
||||
|
||||
.. c:macro:: UV_EINVAL
|
||||
|
||||
invalid argument
|
||||
|
||||
.. c:macro:: UV_EIO
|
||||
|
||||
i/o error
|
||||
|
||||
.. c:macro:: UV_EISCONN
|
||||
|
||||
socket is already connected
|
||||
|
||||
.. c:macro:: UV_EISDIR
|
||||
|
||||
illegal operation on a directory
|
||||
|
||||
.. c:macro:: UV_ELOOP
|
||||
|
||||
too many symbolic links encountered
|
||||
|
||||
.. c:macro:: UV_EMFILE
|
||||
|
||||
too many open files
|
||||
|
||||
.. c:macro:: UV_EMSGSIZE
|
||||
|
||||
message too long
|
||||
|
||||
.. c:macro:: UV_ENAMETOOLONG
|
||||
|
||||
name too long
|
||||
|
||||
.. c:macro:: UV_ENETDOWN
|
||||
|
||||
network is down
|
||||
|
||||
.. c:macro:: UV_ENETUNREACH
|
||||
|
||||
network is unreachable
|
||||
|
||||
.. c:macro:: UV_ENFILE
|
||||
|
||||
file table overflow
|
||||
|
||||
.. c:macro:: UV_ENOBUFS
|
||||
|
||||
no buffer space available
|
||||
|
||||
.. c:macro:: UV_ENODEV
|
||||
|
||||
no such device
|
||||
|
||||
.. c:macro:: UV_ENOENT
|
||||
|
||||
no such file or directory
|
||||
|
||||
.. c:macro:: UV_ENOMEM
|
||||
|
||||
not enough memory
|
||||
|
||||
.. c:macro:: UV_ENONET
|
||||
|
||||
machine is not on the network
|
||||
|
||||
.. c:macro:: UV_ENOPROTOOPT
|
||||
|
||||
protocol not available
|
||||
|
||||
.. c:macro:: UV_ENOSPC
|
||||
|
||||
no space left on device
|
||||
|
||||
.. c:macro:: UV_ENOSYS
|
||||
|
||||
function not implemented
|
||||
|
||||
.. c:macro:: UV_ENOTCONN
|
||||
|
||||
socket is not connected
|
||||
|
||||
.. c:macro:: UV_ENOTDIR
|
||||
|
||||
not a directory
|
||||
|
||||
.. c:macro:: UV_ENOTEMPTY
|
||||
|
||||
directory not empty
|
||||
|
||||
.. c:macro:: UV_ENOTSOCK
|
||||
|
||||
socket operation on non-socket
|
||||
|
||||
.. c:macro:: UV_ENOTSUP
|
||||
|
||||
operation not supported on socket
|
||||
|
||||
.. c:macro:: UV_EPERM
|
||||
|
||||
operation not permitted
|
||||
|
||||
.. c:macro:: UV_EPIPE
|
||||
|
||||
broken pipe
|
||||
|
||||
.. c:macro:: UV_EPROTO
|
||||
|
||||
protocol error
|
||||
|
||||
.. c:macro:: UV_EPROTONOSUPPORT
|
||||
|
||||
protocol not supported
|
||||
|
||||
.. c:macro:: UV_EPROTOTYPE
|
||||
|
||||
protocol wrong type for socket
|
||||
|
||||
.. c:macro:: UV_ERANGE
|
||||
|
||||
result too large
|
||||
|
||||
.. c:macro:: UV_EROFS
|
||||
|
||||
read-only file system
|
||||
|
||||
.. c:macro:: UV_ESHUTDOWN
|
||||
|
||||
cannot send after transport endpoint shutdown
|
||||
|
||||
.. c:macro:: UV_ESPIPE
|
||||
|
||||
invalid seek
|
||||
|
||||
.. c:macro:: UV_ESRCH
|
||||
|
||||
no such process
|
||||
|
||||
.. c:macro:: UV_ETIMEDOUT
|
||||
|
||||
connection timed out
|
||||
|
||||
.. c:macro:: UV_ETXTBSY
|
||||
|
||||
text file is busy
|
||||
|
||||
.. c:macro:: UV_EXDEV
|
||||
|
||||
cross-device link not permitted
|
||||
|
||||
.. c:macro:: UV_UNKNOWN
|
||||
|
||||
unknown error
|
||||
|
||||
.. c:macro:: UV_EOF
|
||||
|
||||
end of file
|
||||
|
||||
.. c:macro:: UV_ENXIO
|
||||
|
||||
no such device or address
|
||||
|
||||
.. c:macro:: UV_EMLINK
|
||||
|
||||
too many links
|
||||
|
||||
|
||||
API
|
||||
---
|
||||
|
||||
.. c:function:: const char* uv_strerror(int err)
|
||||
|
||||
Returns the error message for the given error code. Leaks a few bytes
|
||||
of memory when you call it with an unknown error code.
|
||||
|
||||
.. c:function:: const char* uv_err_name(int err)
|
||||
|
||||
Returns the error name for the given error code. Leaks a few bytes
|
||||
of memory when you call it with an unknown error code.
|
||||
300
libs/libuv/docs/src/fs.rst
Normal file
300
libs/libuv/docs/src/fs.rst
Normal file
@ -0,0 +1,300 @@
|
||||
|
||||
.. _fs:
|
||||
|
||||
Filesystem operations
|
||||
=====================
|
||||
|
||||
libuv provides a wide variety of cross-platform sync and async filesystem
|
||||
operations. All functions defined in this document take a callback, which is
|
||||
allowed to be NULL. If the callback is NULL the request is completed synchronously,
|
||||
otherwise it will be performed asynchronously.
|
||||
|
||||
All file operations are run on the threadpool, see :ref:`threadpool` for information
|
||||
on the threadpool size.
|
||||
|
||||
|
||||
Data types
|
||||
----------
|
||||
|
||||
.. c:type:: uv_fs_t
|
||||
|
||||
Filesystem request type.
|
||||
|
||||
.. c:type:: uv_timespec_t
|
||||
|
||||
Portable equivalent of ``struct timespec``.
|
||||
|
||||
::
|
||||
|
||||
typedef struct {
|
||||
long tv_sec;
|
||||
long tv_nsec;
|
||||
} uv_timespec_t;
|
||||
|
||||
.. c:type:: uv_stat_t
|
||||
|
||||
Portable equivalent of ``struct stat``.
|
||||
|
||||
::
|
||||
|
||||
typedef struct {
|
||||
uint64_t st_dev;
|
||||
uint64_t st_mode;
|
||||
uint64_t st_nlink;
|
||||
uint64_t st_uid;
|
||||
uint64_t st_gid;
|
||||
uint64_t st_rdev;
|
||||
uint64_t st_ino;
|
||||
uint64_t st_size;
|
||||
uint64_t st_blksize;
|
||||
uint64_t st_blocks;
|
||||
uint64_t st_flags;
|
||||
uint64_t st_gen;
|
||||
uv_timespec_t st_atim;
|
||||
uv_timespec_t st_mtim;
|
||||
uv_timespec_t st_ctim;
|
||||
uv_timespec_t st_birthtim;
|
||||
} uv_stat_t;
|
||||
|
||||
.. c:type:: uv_fs_type
|
||||
|
||||
Filesystem request type.
|
||||
|
||||
::
|
||||
|
||||
typedef enum {
|
||||
UV_FS_UNKNOWN = -1,
|
||||
UV_FS_CUSTOM,
|
||||
UV_FS_OPEN,
|
||||
UV_FS_CLOSE,
|
||||
UV_FS_READ,
|
||||
UV_FS_WRITE,
|
||||
UV_FS_SENDFILE,
|
||||
UV_FS_STAT,
|
||||
UV_FS_LSTAT,
|
||||
UV_FS_FSTAT,
|
||||
UV_FS_FTRUNCATE,
|
||||
UV_FS_UTIME,
|
||||
UV_FS_FUTIME,
|
||||
UV_FS_ACCESS,
|
||||
UV_FS_CHMOD,
|
||||
UV_FS_FCHMOD,
|
||||
UV_FS_FSYNC,
|
||||
UV_FS_FDATASYNC,
|
||||
UV_FS_UNLINK,
|
||||
UV_FS_RMDIR,
|
||||
UV_FS_MKDIR,
|
||||
UV_FS_MKDTEMP,
|
||||
UV_FS_RENAME,
|
||||
UV_FS_SCANDIR,
|
||||
UV_FS_LINK,
|
||||
UV_FS_SYMLINK,
|
||||
UV_FS_READLINK,
|
||||
UV_FS_CHOWN,
|
||||
UV_FS_FCHOWN
|
||||
} uv_fs_type;
|
||||
|
||||
.. c:type:: uv_dirent_t
|
||||
|
||||
Cross platform (reduced) equivalent of ``struct dirent``.
|
||||
Used in :c:func:`uv_fs_scandir_next`.
|
||||
|
||||
::
|
||||
|
||||
typedef enum {
|
||||
UV_DIRENT_UNKNOWN,
|
||||
UV_DIRENT_FILE,
|
||||
UV_DIRENT_DIR,
|
||||
UV_DIRENT_LINK,
|
||||
UV_DIRENT_FIFO,
|
||||
UV_DIRENT_SOCKET,
|
||||
UV_DIRENT_CHAR,
|
||||
UV_DIRENT_BLOCK
|
||||
} uv_dirent_type_t;
|
||||
|
||||
typedef struct uv_dirent_s {
|
||||
const char* name;
|
||||
uv_dirent_type_t type;
|
||||
} uv_dirent_t;
|
||||
|
||||
|
||||
Public members
|
||||
^^^^^^^^^^^^^^
|
||||
|
||||
.. c:member:: uv_loop_t* uv_fs_t.loop
|
||||
|
||||
Loop that started this request and where completion will be reported.
|
||||
Readonly.
|
||||
|
||||
.. c:member:: uv_fs_type uv_fs_t.fs_type
|
||||
|
||||
FS request type.
|
||||
|
||||
.. c:member:: const char* uv_fs_t.path
|
||||
|
||||
Path affecting the request.
|
||||
|
||||
.. c:member:: ssize_t uv_fs_t.result
|
||||
|
||||
Result of the request. < 0 means error, success otherwise. On requests such
|
||||
as :c:func:`uv_fs_read` or :c:func:`uv_fs_write` it indicates the amount of
|
||||
data that was read or written, respectively.
|
||||
|
||||
.. c:member:: uv_stat_t uv_fs_t.statbuf
|
||||
|
||||
Stores the result of :c:func:`uv_fs_stat` and other stat requests.
|
||||
|
||||
.. c:member:: void* uv_fs_t.ptr
|
||||
|
||||
Stores the result of :c:func:`uv_fs_readlink` and serves as an alias to
|
||||
`statbuf`.
|
||||
|
||||
.. seealso:: The :c:type:`uv_req_t` members also apply.
|
||||
|
||||
|
||||
API
|
||||
---
|
||||
|
||||
.. c:function:: void uv_fs_req_cleanup(uv_fs_t* req)
|
||||
|
||||
Cleanup request. Must be called after a request is finished to deallocate
|
||||
any memory libuv might have allocated.
|
||||
|
||||
.. c:function:: int uv_fs_close(uv_loop_t* loop, uv_fs_t* req, uv_file file, uv_fs_cb cb)
|
||||
|
||||
Equivalent to :man:`close(2)`.
|
||||
|
||||
.. c:function:: int uv_fs_open(uv_loop_t* loop, uv_fs_t* req, const char* path, int flags, int mode, uv_fs_cb cb)
|
||||
|
||||
Equivalent to :man:`open(2)`.
|
||||
|
||||
.. note::
|
||||
On Windows libuv uses `CreateFileW` and thus the file is always opened
|
||||
in binary mode. Because of this the O_BINARY and O_TEXT flags are not
|
||||
supported.
|
||||
|
||||
.. c:function:: int uv_fs_read(uv_loop_t* loop, uv_fs_t* req, uv_file file, const uv_buf_t bufs[], unsigned int nbufs, int64_t offset, uv_fs_cb cb)
|
||||
|
||||
Equivalent to :man:`preadv(2)`.
|
||||
|
||||
.. c:function:: int uv_fs_unlink(uv_loop_t* loop, uv_fs_t* req, const char* path, uv_fs_cb cb)
|
||||
|
||||
Equivalent to :man:`unlink(2)`.
|
||||
|
||||
.. c:function:: int uv_fs_write(uv_loop_t* loop, uv_fs_t* req, uv_file file, const uv_buf_t bufs[], unsigned int nbufs, int64_t offset, uv_fs_cb cb)
|
||||
|
||||
Equivalent to :man:`pwritev(2)`.
|
||||
|
||||
.. c:function:: int uv_fs_mkdir(uv_loop_t* loop, uv_fs_t* req, const char* path, int mode, uv_fs_cb cb)
|
||||
|
||||
Equivalent to :man:`mkdir(2)`.
|
||||
|
||||
.. note::
|
||||
`mode` is currently not implemented on Windows.
|
||||
|
||||
.. c:function:: int uv_fs_mkdtemp(uv_loop_t* loop, uv_fs_t* req, const char* tpl, uv_fs_cb cb)
|
||||
|
||||
Equivalent to :man:`mkdtemp(3)`.
|
||||
|
||||
.. note::
|
||||
The result can be found as a null terminated string at `req->path`.
|
||||
|
||||
.. c:function:: int uv_fs_rmdir(uv_loop_t* loop, uv_fs_t* req, const char* path, uv_fs_cb cb)
|
||||
|
||||
Equivalent to :man:`rmdir(2)`.
|
||||
|
||||
.. c:function:: int uv_fs_scandir(uv_loop_t* loop, uv_fs_t* req, const char* path, int flags, uv_fs_cb cb)
|
||||
.. c:function:: int uv_fs_scandir_next(uv_fs_t* req, uv_dirent_t* ent)
|
||||
|
||||
Equivalent to :man:`scandir(3)`, with a slightly different API. Once the callback
|
||||
for the request is called, the user can use :c:func:`uv_fs_scandir_next` to
|
||||
get `ent` populated with the next directory entry data. When there are no
|
||||
more entries ``UV_EOF`` will be returned.
|
||||
|
||||
.. note::
|
||||
Unlike `scandir(3)`, this function does not return the "." and ".." entries.
|
||||
|
||||
.. note::
|
||||
On Linux, getting the type of an entry is only supported by some filesystems (btrfs, ext2,
|
||||
ext3 and ext4 at the time of this writing), check the :man:`getdents(2)` man page.
|
||||
|
||||
.. c:function:: int uv_fs_stat(uv_loop_t* loop, uv_fs_t* req, const char* path, uv_fs_cb cb)
|
||||
.. c:function:: int uv_fs_fstat(uv_loop_t* loop, uv_fs_t* req, uv_file file, uv_fs_cb cb)
|
||||
.. c:function:: int uv_fs_lstat(uv_loop_t* loop, uv_fs_t* req, const char* path, uv_fs_cb cb)
|
||||
|
||||
Equivalent to :man:`stat(2)`, :man:`fstat(2)` and :man:`fstat(2)` respectively.
|
||||
|
||||
.. c:function:: int uv_fs_rename(uv_loop_t* loop, uv_fs_t* req, const char* path, const char* new_path, uv_fs_cb cb)
|
||||
|
||||
Equivalent to :man:`rename(2)`.
|
||||
|
||||
.. c:function:: int uv_fs_fsync(uv_loop_t* loop, uv_fs_t* req, uv_file file, uv_fs_cb cb)
|
||||
|
||||
Equivalent to :man:`fsync(2)`.
|
||||
|
||||
.. c:function:: int uv_fs_fdatasync(uv_loop_t* loop, uv_fs_t* req, uv_file file, uv_fs_cb cb)
|
||||
|
||||
Equivalent to :man:`fdatasync(2)`.
|
||||
|
||||
.. c:function:: int uv_fs_ftruncate(uv_loop_t* loop, uv_fs_t* req, uv_file file, int64_t offset, uv_fs_cb cb)
|
||||
|
||||
Equivalent to :man:`ftruncate(2)`.
|
||||
|
||||
.. c:function:: int uv_fs_sendfile(uv_loop_t* loop, uv_fs_t* req, uv_file out_fd, uv_file in_fd, int64_t in_offset, size_t length, uv_fs_cb cb)
|
||||
|
||||
Limited equivalent to :man:`sendfile(2)`.
|
||||
|
||||
.. c:function:: int uv_fs_access(uv_loop_t* loop, uv_fs_t* req, const char* path, int mode, uv_fs_cb cb)
|
||||
|
||||
Equivalent to :man:`access(2)` on Unix. Windows uses ``GetFileAttributesW()``.
|
||||
|
||||
.. c:function:: int uv_fs_chmod(uv_loop_t* loop, uv_fs_t* req, const char* path, int mode, uv_fs_cb cb)
|
||||
.. c:function:: int uv_fs_fchmod(uv_loop_t* loop, uv_fs_t* req, uv_file file, int mode, uv_fs_cb cb)
|
||||
|
||||
Equivalent to :man:`chmod(2)` and :man:`fchmod(2)` respectively.
|
||||
|
||||
.. c:function:: int uv_fs_utime(uv_loop_t* loop, uv_fs_t* req, const char* path, double atime, double mtime, uv_fs_cb cb)
|
||||
.. c:function:: int uv_fs_futime(uv_loop_t* loop, uv_fs_t* req, uv_file file, double atime, double mtime, uv_fs_cb cb)
|
||||
|
||||
Equivalent to :man:`utime(2)` and :man:`futime(2)` respectively.
|
||||
|
||||
.. c:function:: int uv_fs_link(uv_loop_t* loop, uv_fs_t* req, const char* path, const char* new_path, uv_fs_cb cb)
|
||||
|
||||
Equivalent to :man:`link(2)`.
|
||||
|
||||
.. c:function:: int uv_fs_symlink(uv_loop_t* loop, uv_fs_t* req, const char* path, const char* new_path, int flags, uv_fs_cb cb)
|
||||
|
||||
Equivalent to :man:`symlink(2)`.
|
||||
|
||||
.. note::
|
||||
On Windows the `flags` parameter can be specified to control how the symlink will
|
||||
be created:
|
||||
|
||||
* ``UV_FS_SYMLINK_DIR``: indicates that `path` points to a directory.
|
||||
|
||||
* ``UV_FS_SYMLINK_JUNCTION``: request that the symlink is created
|
||||
using junction points.
|
||||
|
||||
.. c:function:: int uv_fs_readlink(uv_loop_t* loop, uv_fs_t* req, const char* path, uv_fs_cb cb)
|
||||
|
||||
Equivalent to :man:`readlink(2)`.
|
||||
|
||||
.. c:function:: int uv_fs_realpath(uv_loop_t* loop, uv_fs_t* req, const char* path, uv_fs_cb cb)
|
||||
|
||||
Equivalent to :man:`realpath(3)` on Unix. Windows uses ``GetFinalPathNameByHandle()``.
|
||||
|
||||
.. note::
|
||||
This function is not implemented on Windows XP and Windows Server 2003.
|
||||
On these systems, UV_ENOSYS is returned.
|
||||
|
||||
.. versionadded:: 1.8.0
|
||||
|
||||
.. c:function:: int uv_fs_chown(uv_loop_t* loop, uv_fs_t* req, const char* path, uv_uid_t uid, uv_gid_t gid, uv_fs_cb cb)
|
||||
.. c:function:: int uv_fs_fchown(uv_loop_t* loop, uv_fs_t* req, uv_file file, uv_uid_t uid, uv_gid_t gid, uv_fs_cb cb)
|
||||
|
||||
Equivalent to :man:`chown(2)` and :man:`fchown(2)` respectively.
|
||||
|
||||
.. note::
|
||||
These functions are not implemented on Windows.
|
||||
|
||||
.. seealso:: The :c:type:`uv_req_t` API functions also apply.
|
||||
108
libs/libuv/docs/src/fs_event.rst
Normal file
108
libs/libuv/docs/src/fs_event.rst
Normal file
@ -0,0 +1,108 @@
|
||||
|
||||
.. _fs_event:
|
||||
|
||||
:c:type:`uv_fs_event_t` --- FS Event handle
|
||||
===========================================
|
||||
|
||||
FS Event handles allow the user to monitor a given path for changes, for example,
|
||||
if the file was renamed or there was a generic change in it. This handle uses
|
||||
the best backend for the job on each platform.
|
||||
|
||||
|
||||
Data types
|
||||
----------
|
||||
|
||||
.. c:type:: uv_fs_event_t
|
||||
|
||||
FS Event handle type.
|
||||
|
||||
.. c:type:: void (*uv_fs_event_cb)(uv_fs_event_t* handle, const char* filename, int events, int status)
|
||||
|
||||
Callback passed to :c:func:`uv_fs_event_start` which will be called repeatedly
|
||||
after the handle is started. If the handle was started with a directory the
|
||||
`filename` parameter will be a relative path to a file contained in the directory.
|
||||
The `events` parameter is an ORed mask of :c:type:`uv_fs_event` elements.
|
||||
|
||||
.. c:type:: uv_fs_event
|
||||
|
||||
Event types that :c:type:`uv_fs_event_t` handles monitor.
|
||||
|
||||
::
|
||||
|
||||
enum uv_fs_event {
|
||||
UV_RENAME = 1,
|
||||
UV_CHANGE = 2
|
||||
};
|
||||
|
||||
.. c:type:: uv_fs_event_flags
|
||||
|
||||
Flags that can be passed to :c:func:`uv_fs_event_start` to control its
|
||||
behavior.
|
||||
|
||||
::
|
||||
|
||||
enum uv_fs_event_flags {
|
||||
/*
|
||||
* By default, if the fs event watcher is given a directory name, we will
|
||||
* watch for all events in that directory. This flags overrides this behavior
|
||||
* and makes fs_event report only changes to the directory entry itself. This
|
||||
* flag does not affect individual files watched.
|
||||
* This flag is currently not implemented yet on any backend.
|
||||
*/
|
||||
UV_FS_EVENT_WATCH_ENTRY = 1,
|
||||
/*
|
||||
* By default uv_fs_event will try to use a kernel interface such as inotify
|
||||
* or kqueue to detect events. This may not work on remote filesystems such
|
||||
* as NFS mounts. This flag makes fs_event fall back to calling stat() on a
|
||||
* regular interval.
|
||||
* This flag is currently not implemented yet on any backend.
|
||||
*/
|
||||
UV_FS_EVENT_STAT = 2,
|
||||
/*
|
||||
* By default, event watcher, when watching directory, is not registering
|
||||
* (is ignoring) changes in it's subdirectories.
|
||||
* This flag will override this behaviour on platforms that support it.
|
||||
*/
|
||||
UV_FS_EVENT_RECURSIVE = 4
|
||||
};
|
||||
|
||||
|
||||
Public members
|
||||
^^^^^^^^^^^^^^
|
||||
|
||||
N/A
|
||||
|
||||
.. seealso:: The :c:type:`uv_handle_t` members also apply.
|
||||
|
||||
|
||||
API
|
||||
---
|
||||
|
||||
.. c:function:: int uv_fs_event_init(uv_loop_t* loop, uv_fs_event_t* handle)
|
||||
|
||||
Initialize the handle.
|
||||
|
||||
.. c:function:: int uv_fs_event_start(uv_fs_event_t* handle, uv_fs_event_cb cb, const char* path, unsigned int flags)
|
||||
|
||||
Start the handle with the given callback, which will watch the specified
|
||||
`path` for changes. `flags` can be an ORed mask of :c:type:`uv_fs_event_flags`.
|
||||
|
||||
.. note:: Currently the only supported flag is ``UV_FS_EVENT_RECURSIVE`` and
|
||||
only on OSX and Windows.
|
||||
|
||||
.. c:function:: int uv_fs_event_stop(uv_fs_event_t* handle)
|
||||
|
||||
Stop the handle, the callback will no longer be called.
|
||||
|
||||
.. c:function:: int uv_fs_event_getpath(uv_fs_event_t* handle, char* buffer, size_t* size)
|
||||
|
||||
Get the path being monitored by the handle. The buffer must be preallocated
|
||||
by the user. Returns 0 on success or an error code < 0 in case of failure.
|
||||
On success, `buffer` will contain the path and `size` its length. If the buffer
|
||||
is not big enough UV_ENOBUFS will be returned and len will be set to the
|
||||
required size.
|
||||
|
||||
.. versionchanged:: 1.3.0 the returned length no longer includes the terminating null byte,
|
||||
and the buffer is not null terminated.
|
||||
|
||||
.. seealso:: The :c:type:`uv_handle_t` API functions also apply.
|
||||
72
libs/libuv/docs/src/fs_poll.rst
Normal file
72
libs/libuv/docs/src/fs_poll.rst
Normal file
@ -0,0 +1,72 @@
|
||||
|
||||
.. _fs_poll:
|
||||
|
||||
:c:type:`uv_fs_poll_t` --- FS Poll handle
|
||||
=========================================
|
||||
|
||||
FS Poll handles allow the user to monitor a given path for changes. Unlike
|
||||
:c:type:`uv_fs_event_t`, fs poll handles use `stat` to detect when a file has
|
||||
changed so they can work on file systems where fs event handles can't.
|
||||
|
||||
|
||||
Data types
|
||||
----------
|
||||
|
||||
.. c:type:: uv_fs_poll_t
|
||||
|
||||
FS Poll handle type.
|
||||
|
||||
.. c:type:: void (*uv_fs_poll_cb)(uv_fs_poll_t* handle, int status, const uv_stat_t* prev, const uv_stat_t* curr)
|
||||
|
||||
Callback passed to :c:func:`uv_fs_poll_start` which will be called repeatedly
|
||||
after the handle is started, when any change happens to the monitored path.
|
||||
|
||||
The callback is invoked with `status < 0` if `path` does not exist
|
||||
or is inaccessible. The watcher is *not* stopped but your callback is
|
||||
not called again until something changes (e.g. when the file is created
|
||||
or the error reason changes).
|
||||
|
||||
When `status == 0`, the callback receives pointers to the old and new
|
||||
:c:type:`uv_stat_t` structs. They are valid for the duration of the
|
||||
callback only.
|
||||
|
||||
|
||||
Public members
|
||||
^^^^^^^^^^^^^^
|
||||
|
||||
N/A
|
||||
|
||||
.. seealso:: The :c:type:`uv_handle_t` members also apply.
|
||||
|
||||
|
||||
API
|
||||
---
|
||||
|
||||
.. c:function:: int uv_fs_poll_init(uv_loop_t* loop, uv_fs_poll_t* handle)
|
||||
|
||||
Initialize the handle.
|
||||
|
||||
.. c:function:: int uv_fs_poll_start(uv_fs_poll_t* handle, uv_fs_poll_cb poll_cb, const char* path, unsigned int interval)
|
||||
|
||||
Check the file at `path` for changes every `interval` milliseconds.
|
||||
|
||||
.. note::
|
||||
For maximum portability, use multi-second intervals. Sub-second intervals will not detect
|
||||
all changes on many file systems.
|
||||
|
||||
.. c:function:: int uv_fs_poll_stop(uv_fs_poll_t* handle)
|
||||
|
||||
Stop the handle, the callback will no longer be called.
|
||||
|
||||
.. c:function:: int uv_fs_poll_getpath(uv_fs_poll_t* handle, char* buffer, size_t* size)
|
||||
|
||||
Get the path being monitored by the handle. The buffer must be preallocated
|
||||
by the user. Returns 0 on success or an error code < 0 in case of failure.
|
||||
On success, `buffer` will contain the path and `size` its length. If the buffer
|
||||
is not big enough UV_ENOBUFS will be returned and len will be set to the
|
||||
required size.
|
||||
|
||||
.. versionchanged:: 1.3.0 the returned length no longer includes the terminating null byte,
|
||||
and the buffer is not null terminated.
|
||||
|
||||
.. seealso:: The :c:type:`uv_handle_t` API functions also apply.
|
||||
181
libs/libuv/docs/src/handle.rst
Normal file
181
libs/libuv/docs/src/handle.rst
Normal file
@ -0,0 +1,181 @@
|
||||
|
||||
.. _handle:
|
||||
|
||||
:c:type:`uv_handle_t` --- Base handle
|
||||
=====================================
|
||||
|
||||
`uv_handle_t` is the base type for all libuv handle types.
|
||||
|
||||
Structures are aligned so that any libuv handle can be cast to `uv_handle_t`.
|
||||
All API functions defined here work with any handle type.
|
||||
|
||||
|
||||
Data types
|
||||
----------
|
||||
|
||||
.. c:type:: uv_handle_t
|
||||
|
||||
The base libuv handle type.
|
||||
|
||||
.. c:type:: uv_any_handle
|
||||
|
||||
Union of all handle types.
|
||||
|
||||
.. c:type:: void (*uv_alloc_cb)(uv_handle_t* handle, size_t suggested_size, uv_buf_t* buf)
|
||||
|
||||
Type definition for callback passed to :c:func:`uv_read_start` and
|
||||
:c:func:`uv_udp_recv_start`. The user must fill the supplied :c:type:`uv_buf_t`
|
||||
structure with whatever size, as long as it's > 0. A suggested size (65536 at the moment)
|
||||
is provided, but it doesn't need to be honored. Setting the buffer's length to 0
|
||||
will trigger a ``UV_ENOBUFS`` error in the :c:type:`uv_udp_recv_cb` or
|
||||
:c:type:`uv_read_cb` callback.
|
||||
|
||||
.. c:type:: void (*uv_close_cb)(uv_handle_t* handle)
|
||||
|
||||
Type definition for callback passed to :c:func:`uv_close`.
|
||||
|
||||
|
||||
Public members
|
||||
^^^^^^^^^^^^^^
|
||||
|
||||
.. c:member:: uv_loop_t* uv_handle_t.loop
|
||||
|
||||
Pointer to the :c:type:`uv_loop_t` where the handle is running on. Readonly.
|
||||
|
||||
.. c:member:: void* uv_handle_t.data
|
||||
|
||||
Space for user-defined arbitrary data. libuv does not use this field.
|
||||
|
||||
|
||||
API
|
||||
---
|
||||
|
||||
.. c:function:: int uv_is_active(const uv_handle_t* handle)
|
||||
|
||||
Returns non-zero if the handle is active, zero if it's inactive. What
|
||||
"active" means depends on the type of handle:
|
||||
|
||||
- A uv_async_t handle is always active and cannot be deactivated, except
|
||||
by closing it with uv_close().
|
||||
|
||||
- A uv_pipe_t, uv_tcp_t, uv_udp_t, etc. handle - basically any handle that
|
||||
deals with i/o - is active when it is doing something that involves i/o,
|
||||
like reading, writing, connecting, accepting new connections, etc.
|
||||
|
||||
- A uv_check_t, uv_idle_t, uv_timer_t, etc. handle is active when it has
|
||||
been started with a call to uv_check_start(), uv_idle_start(), etc.
|
||||
|
||||
Rule of thumb: if a handle of type `uv_foo_t` has a `uv_foo_start()`
|
||||
function, then it's active from the moment that function is called.
|
||||
Likewise, `uv_foo_stop()` deactivates the handle again.
|
||||
|
||||
.. c:function:: int uv_is_closing(const uv_handle_t* handle)
|
||||
|
||||
Returns non-zero if the handle is closing or closed, zero otherwise.
|
||||
|
||||
.. note::
|
||||
This function should only be used between the initialization of the handle and the
|
||||
arrival of the close callback.
|
||||
|
||||
.. c:function:: void uv_close(uv_handle_t* handle, uv_close_cb close_cb)
|
||||
|
||||
Request handle to be closed. `close_cb` will be called asynchronously after
|
||||
this call. This MUST be called on each handle before memory is released.
|
||||
|
||||
Handles that wrap file descriptors are closed immediately but
|
||||
`close_cb` will still be deferred to the next iteration of the event loop.
|
||||
It gives you a chance to free up any resources associated with the handle.
|
||||
|
||||
In-progress requests, like uv_connect_t or uv_write_t, are cancelled and
|
||||
have their callbacks called asynchronously with status=UV_ECANCELED.
|
||||
|
||||
.. c:function:: void uv_ref(uv_handle_t* handle)
|
||||
|
||||
Reference the given handle. References are idempotent, that is, if a handle
|
||||
is already referenced calling this function again will have no effect.
|
||||
|
||||
See :ref:`refcount`.
|
||||
|
||||
.. c:function:: void uv_unref(uv_handle_t* handle)
|
||||
|
||||
Un-reference the given handle. References are idempotent, that is, if a handle
|
||||
is not referenced calling this function again will have no effect.
|
||||
|
||||
See :ref:`refcount`.
|
||||
|
||||
.. c:function:: int uv_has_ref(const uv_handle_t* handle)
|
||||
|
||||
Returns non-zero if the handle referenced, zero otherwise.
|
||||
|
||||
See :ref:`refcount`.
|
||||
|
||||
.. c:function:: size_t uv_handle_size(uv_handle_type type)
|
||||
|
||||
Returns the size of the given handle type. Useful for FFI binding writers
|
||||
who don't want to know the structure layout.
|
||||
|
||||
|
||||
Miscellaneous API functions
|
||||
---------------------------
|
||||
|
||||
The following API functions take a :c:type:`uv_handle_t` argument but they work
|
||||
just for some handle types.
|
||||
|
||||
.. c:function:: int uv_send_buffer_size(uv_handle_t* handle, int* value)
|
||||
|
||||
Gets or sets the size of the send buffer that the operating
|
||||
system uses for the socket.
|
||||
|
||||
If `*value` == 0, it will return the current send buffer size,
|
||||
otherwise it will use `*value` to set the new send buffer size.
|
||||
|
||||
This function works for TCP, pipe and UDP handles on Unix and for TCP and
|
||||
UDP handles on Windows.
|
||||
|
||||
.. note::
|
||||
Linux will set double the size and return double the size of the original set value.
|
||||
|
||||
.. c:function:: int uv_recv_buffer_size(uv_handle_t* handle, int* value)
|
||||
|
||||
Gets or sets the size of the receive buffer that the operating
|
||||
system uses for the socket.
|
||||
|
||||
If `*value` == 0, it will return the current receive buffer size,
|
||||
otherwise it will use `*value` to set the new receive buffer size.
|
||||
|
||||
This function works for TCP, pipe and UDP handles on Unix and for TCP and
|
||||
UDP handles on Windows.
|
||||
|
||||
.. note::
|
||||
Linux will set double the size and return double the size of the original set value.
|
||||
|
||||
.. c:function:: int uv_fileno(const uv_handle_t* handle, uv_os_fd_t* fd)
|
||||
|
||||
Gets the platform dependent file descriptor equivalent.
|
||||
|
||||
The following handles are supported: TCP, pipes, TTY, UDP and poll. Passing
|
||||
any other handle type will fail with `UV_EINVAL`.
|
||||
|
||||
If a handle doesn't have an attached file descriptor yet or the handle
|
||||
itself has been closed, this function will return `UV_EBADF`.
|
||||
|
||||
.. warning::
|
||||
Be very careful when using this function. libuv assumes it's in control of the file
|
||||
descriptor so any change to it may lead to malfunction.
|
||||
|
||||
|
||||
.. _refcount:
|
||||
|
||||
Reference counting
|
||||
------------------
|
||||
|
||||
The libuv event loop (if run in the default mode) will run until there are no
|
||||
active `and` referenced handles left. The user can force the loop to exit early
|
||||
by unreferencing handles which are active, for example by calling :c:func:`uv_unref`
|
||||
after calling :c:func:`uv_timer_start`.
|
||||
|
||||
A handle can be referenced or unreferenced, the refcounting scheme doesn't use
|
||||
a counter, so both operations are idempotent.
|
||||
|
||||
All handles are referenced when active by default, see :c:func:`uv_is_active`
|
||||
for a more detailed explanation on what being `active` involves.
|
||||
54
libs/libuv/docs/src/idle.rst
Normal file
54
libs/libuv/docs/src/idle.rst
Normal file
@ -0,0 +1,54 @@
|
||||
|
||||
.. _idle:
|
||||
|
||||
:c:type:`uv_idle_t` --- Idle handle
|
||||
===================================
|
||||
|
||||
Idle handles will run the given callback once per loop iteration, right
|
||||
before the :c:type:`uv_prepare_t` handles.
|
||||
|
||||
.. note::
|
||||
The notable difference with prepare handles is that when there are active idle handles,
|
||||
the loop will perform a zero timeout poll instead of blocking for i/o.
|
||||
|
||||
.. warning::
|
||||
Despite the name, idle handles will get their callbacks called on every loop iteration,
|
||||
not when the loop is actually "idle".
|
||||
|
||||
|
||||
Data types
|
||||
----------
|
||||
|
||||
.. c:type:: uv_idle_t
|
||||
|
||||
Idle handle type.
|
||||
|
||||
.. c:type:: void (*uv_idle_cb)(uv_idle_t* handle)
|
||||
|
||||
Type definition for callback passed to :c:func:`uv_idle_start`.
|
||||
|
||||
|
||||
Public members
|
||||
^^^^^^^^^^^^^^
|
||||
|
||||
N/A
|
||||
|
||||
.. seealso:: The :c:type:`uv_handle_t` members also apply.
|
||||
|
||||
|
||||
API
|
||||
---
|
||||
|
||||
.. c:function:: int uv_idle_init(uv_loop_t* loop, uv_idle_t* idle)
|
||||
|
||||
Initialize the handle.
|
||||
|
||||
.. c:function:: int uv_idle_start(uv_idle_t* idle, uv_idle_cb cb)
|
||||
|
||||
Start the handle with the given callback.
|
||||
|
||||
.. c:function:: int uv_idle_stop(uv_idle_t* idle)
|
||||
|
||||
Stop the handle, the callback will no longer be called.
|
||||
|
||||
.. seealso:: The :c:type:`uv_handle_t` API functions also apply.
|
||||
95
libs/libuv/docs/src/index.rst
Normal file
95
libs/libuv/docs/src/index.rst
Normal file
@ -0,0 +1,95 @@
|
||||
|
||||
Welcome to the libuv API documentation
|
||||
======================================
|
||||
|
||||
Overview
|
||||
--------
|
||||
|
||||
libuv is a multi-platform support library with a focus on asynchronous I/O. It
|
||||
was primarily developed for use by `Node.js`_, but it's also used by `Luvit`_,
|
||||
`Julia`_, `pyuv`_, and `others`_.
|
||||
|
||||
.. note::
|
||||
In case you find errors in this documentation you can help by sending
|
||||
`pull requests <https://github.com/libuv/libuv>`_!
|
||||
|
||||
.. _Node.js: http://nodejs.org
|
||||
.. _Luvit: http://luvit.io
|
||||
.. _Julia: http://julialang.org
|
||||
.. _pyuv: https://github.com/saghul/pyuv
|
||||
.. _others: https://github.com/libuv/libuv/wiki/Projects-that-use-libuv
|
||||
|
||||
|
||||
Features
|
||||
--------
|
||||
|
||||
* Full-featured event loop backed by epoll, kqueue, IOCP, event ports.
|
||||
* Asynchronous TCP and UDP sockets
|
||||
* Asynchronous DNS resolution
|
||||
* Asynchronous file and file system operations
|
||||
* File system events
|
||||
* ANSI escape code controlled TTY
|
||||
* IPC with socket sharing, using Unix domain sockets or named pipes (Windows)
|
||||
* Child processes
|
||||
* Thread pool
|
||||
* Signal handling
|
||||
* High resolution clock
|
||||
* Threading and synchronization primitives
|
||||
|
||||
|
||||
Downloads
|
||||
---------
|
||||
|
||||
libuv can be downloaded from `here <http://dist.libuv.org/dist/>`_.
|
||||
|
||||
|
||||
Installation
|
||||
------------
|
||||
|
||||
Installation instructions can be found on `the README <https://github.com/libuv/libuv/blob/master/README.md>`_.
|
||||
|
||||
|
||||
Upgrading
|
||||
---------
|
||||
|
||||
Migration guides for different libuv versions, starting with 1.0.
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 1
|
||||
|
||||
migration_010_100
|
||||
|
||||
|
||||
Documentation
|
||||
-------------
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 1
|
||||
|
||||
design
|
||||
errors
|
||||
version
|
||||
loop
|
||||
handle
|
||||
request
|
||||
timer
|
||||
prepare
|
||||
check
|
||||
idle
|
||||
async
|
||||
poll
|
||||
signal
|
||||
process
|
||||
stream
|
||||
tcp
|
||||
pipe
|
||||
tty
|
||||
udp
|
||||
fs_event
|
||||
fs_poll
|
||||
fs
|
||||
threadpool
|
||||
dns
|
||||
dll
|
||||
threading
|
||||
misc
|
||||
167
libs/libuv/docs/src/loop.rst
Normal file
167
libs/libuv/docs/src/loop.rst
Normal file
@ -0,0 +1,167 @@
|
||||
|
||||
.. _loop:
|
||||
|
||||
:c:type:`uv_loop_t` --- Event loop
|
||||
==================================
|
||||
|
||||
The event loop is the central part of libuv's functionality. It takes care
|
||||
of polling for i/o and scheduling callbacks to be run based on different sources
|
||||
of events.
|
||||
|
||||
|
||||
Data types
|
||||
----------
|
||||
|
||||
.. c:type:: uv_loop_t
|
||||
|
||||
Loop data type.
|
||||
|
||||
.. c:type:: uv_run_mode
|
||||
|
||||
Mode used to run the loop with :c:func:`uv_run`.
|
||||
|
||||
::
|
||||
|
||||
typedef enum {
|
||||
UV_RUN_DEFAULT = 0,
|
||||
UV_RUN_ONCE,
|
||||
UV_RUN_NOWAIT
|
||||
} uv_run_mode;
|
||||
|
||||
.. c:type:: void (*uv_walk_cb)(uv_handle_t* handle, void* arg)
|
||||
|
||||
Type definition for callback passed to :c:func:`uv_walk`.
|
||||
|
||||
|
||||
Public members
|
||||
^^^^^^^^^^^^^^
|
||||
|
||||
.. c:member:: void* uv_loop_t.data
|
||||
|
||||
Space for user-defined arbitrary data. libuv does not use this field. libuv does, however,
|
||||
initialize it to NULL in :c:func:`uv_loop_init`, and it poisons the value (on debug builds)
|
||||
on :c:func:`uv_loop_close`.
|
||||
|
||||
|
||||
API
|
||||
---
|
||||
|
||||
.. c:function:: int uv_loop_init(uv_loop_t* loop)
|
||||
|
||||
Initializes the given `uv_loop_t` structure.
|
||||
|
||||
.. c:function:: int uv_loop_configure(uv_loop_t* loop, uv_loop_option option, ...)
|
||||
|
||||
.. versionadded:: 1.0.2
|
||||
|
||||
Set additional loop options. You should normally call this before the
|
||||
first call to :c:func:`uv_run` unless mentioned otherwise.
|
||||
|
||||
Returns 0 on success or a UV_E* error code on failure. Be prepared to
|
||||
handle UV_ENOSYS; it means the loop option is not supported by the platform.
|
||||
|
||||
Supported options:
|
||||
|
||||
- UV_LOOP_BLOCK_SIGNAL: Block a signal when polling for new events. The
|
||||
second argument to :c:func:`uv_loop_configure` is the signal number.
|
||||
|
||||
This operation is currently only implemented for SIGPROF signals,
|
||||
to suppress unnecessary wakeups when using a sampling profiler.
|
||||
Requesting other signals will fail with UV_EINVAL.
|
||||
|
||||
.. c:function:: int uv_loop_close(uv_loop_t* loop)
|
||||
|
||||
Releases all internal loop resources. Call this function only when the loop
|
||||
has finished executing and all open handles and requests have been closed,
|
||||
or it will return UV_EBUSY. After this function returns, the user can free
|
||||
the memory allocated for the loop.
|
||||
|
||||
.. c:function:: uv_loop_t* uv_default_loop(void)
|
||||
|
||||
Returns the initialized default loop. It may return NULL in case of
|
||||
allocation failure.
|
||||
|
||||
This function is just a convenient way for having a global loop throughout
|
||||
an application, the default loop is in no way different than the ones
|
||||
initialized with :c:func:`uv_loop_init`. As such, the default loop can (and
|
||||
should) be closed with :c:func:`uv_loop_close` so the resources associated
|
||||
with it are freed.
|
||||
|
||||
.. c:function:: int uv_run(uv_loop_t* loop, uv_run_mode mode)
|
||||
|
||||
This function runs the event loop. It will act differently depending on the
|
||||
specified mode:
|
||||
|
||||
- UV_RUN_DEFAULT: Runs the event loop until there are no more active and
|
||||
referenced handles or requests. Returns non-zero if :c:func:`uv_stop`
|
||||
was called and there are still active handles or requests. Returns
|
||||
zero in all other cases.
|
||||
- UV_RUN_ONCE: Poll for i/o once. Note that this function blocks if
|
||||
there are no pending callbacks. Returns zero when done (no active handles
|
||||
or requests left), or non-zero if more callbacks are expected (meaning
|
||||
you should run the event loop again sometime in the future).
|
||||
- UV_RUN_NOWAIT: Poll for i/o once but don't block if there are no
|
||||
pending callbacks. Returns zero if done (no active handles
|
||||
or requests left), or non-zero if more callbacks are expected (meaning
|
||||
you should run the event loop again sometime in the future).
|
||||
|
||||
.. c:function:: int uv_loop_alive(const uv_loop_t* loop)
|
||||
|
||||
Returns non-zero if there are active handles or request in the loop.
|
||||
|
||||
.. c:function:: void uv_stop(uv_loop_t* loop)
|
||||
|
||||
Stop the event loop, causing :c:func:`uv_run` to end as soon as
|
||||
possible. This will happen not sooner than the next loop iteration.
|
||||
If this function was called before blocking for i/o, the loop won't block
|
||||
for i/o on this iteration.
|
||||
|
||||
.. c:function:: size_t uv_loop_size(void)
|
||||
|
||||
Returns the size of the `uv_loop_t` structure. Useful for FFI binding
|
||||
writers who don't want to know the structure layout.
|
||||
|
||||
.. c:function:: int uv_backend_fd(const uv_loop_t* loop)
|
||||
|
||||
Get backend file descriptor. Only kqueue, epoll and event ports are
|
||||
supported.
|
||||
|
||||
This can be used in conjunction with `uv_run(loop, UV_RUN_NOWAIT)` to
|
||||
poll in one thread and run the event loop's callbacks in another see
|
||||
test/test-embed.c for an example.
|
||||
|
||||
.. note::
|
||||
Embedding a kqueue fd in another kqueue pollset doesn't work on all platforms. It's not
|
||||
an error to add the fd but it never generates events.
|
||||
|
||||
.. c:function:: int uv_backend_timeout(const uv_loop_t* loop)
|
||||
|
||||
Get the poll timeout. The return value is in milliseconds, or -1 for no
|
||||
timeout.
|
||||
|
||||
.. c:function:: uint64_t uv_now(const uv_loop_t* loop)
|
||||
|
||||
Return the current timestamp in milliseconds. The timestamp is cached at
|
||||
the start of the event loop tick, see :c:func:`uv_update_time` for details
|
||||
and rationale.
|
||||
|
||||
The timestamp increases monotonically from some arbitrary point in time.
|
||||
Don't make assumptions about the starting point, you will only get
|
||||
disappointed.
|
||||
|
||||
.. note::
|
||||
Use :c:func:`uv_hrtime` if you need sub-millisecond granularity.
|
||||
|
||||
.. c:function:: void uv_update_time(uv_loop_t* loop)
|
||||
|
||||
Update the event loop's concept of "now". Libuv caches the current time
|
||||
at the start of the event loop tick in order to reduce the number of
|
||||
time-related system calls.
|
||||
|
||||
You won't normally need to call this function unless you have callbacks
|
||||
that block the event loop for longer periods of time, where "longer" is
|
||||
somewhat subjective but probably on the order of a millisecond or more.
|
||||
|
||||
.. c:function:: void uv_walk(uv_loop_t* loop, uv_walk_cb walk_cb, void* arg)
|
||||
|
||||
Walk the list of handles: `walk_cb` will be executed with the given `arg`.
|
||||
244
libs/libuv/docs/src/migration_010_100.rst
Normal file
244
libs/libuv/docs/src/migration_010_100.rst
Normal file
@ -0,0 +1,244 @@
|
||||
|
||||
.. _migration_010_100:
|
||||
|
||||
libuv 0.10 -> 1.0.0 migration guide
|
||||
===================================
|
||||
|
||||
Some APIs changed quite a bit throughout the 1.0.0 development process. Here
|
||||
is a migration guide for the most significant changes that happened after 0.10
|
||||
was released.
|
||||
|
||||
|
||||
Loop initialization and closing
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
In libuv 0.10 (and previous versions), loops were created with `uv_loop_new`, which
|
||||
allocated memory for a new loop and initialized it; and destroyed with `uv_loop_delete`,
|
||||
which destroyed the loop and freed the memory. Starting with 1.0, those are deprecated
|
||||
and the user is responsible for allocating the memory and then initializing the loop.
|
||||
|
||||
libuv 0.10
|
||||
|
||||
::
|
||||
|
||||
uv_loop_t* loop = uv_loop_new();
|
||||
...
|
||||
uv_loop_delete(loop);
|
||||
|
||||
libuv 1.0
|
||||
|
||||
::
|
||||
|
||||
uv_loop_t* loop = malloc(sizeof *loop);
|
||||
uv_loop_init(loop);
|
||||
...
|
||||
uv_loop_close(loop);
|
||||
free(loop);
|
||||
|
||||
.. note::
|
||||
Error handling was omitted for brevity. Check the documentation for :c:func:`uv_loop_init`
|
||||
and :c:func:`uv_loop_close`.
|
||||
|
||||
|
||||
Error handling
|
||||
~~~~~~~~~~~~~~
|
||||
|
||||
Error handling had a major overhaul in libuv 1.0. In general, functions and status parameters
|
||||
would get 0 for success and -1 for failure on libuv 0.10, and the user had to use `uv_last_error`
|
||||
to fetch the error code, which was a positive number.
|
||||
|
||||
In 1.0, functions and status parameters contain the actual error code, which is 0 for success, or
|
||||
a negative number in case of error.
|
||||
|
||||
libuv 0.10
|
||||
|
||||
::
|
||||
|
||||
... assume 'server' is a TCP server which is already listening
|
||||
r = uv_listen((uv_stream_t*) server, 511, NULL);
|
||||
if (r == -1) {
|
||||
uv_err_t err = uv_last_error(uv_default_loop());
|
||||
/* err.code contains UV_EADDRINUSE */
|
||||
}
|
||||
|
||||
libuv 1.0
|
||||
|
||||
::
|
||||
|
||||
... assume 'server' is a TCP server which is already listening
|
||||
r = uv_listen((uv_stream_t*) server, 511, NULL);
|
||||
if (r < 0) {
|
||||
/* r contains UV_EADDRINUSE */
|
||||
}
|
||||
|
||||
|
||||
Threadpool changes
|
||||
~~~~~~~~~~~~~~~~~~
|
||||
|
||||
In libuv 0.10 Unix used a threadpool which defaulted to 4 threads, while Windows used the
|
||||
`QueueUserWorkItem` API, which uses a Windows internal threadpool, which defaults to 512
|
||||
threads per process.
|
||||
|
||||
In 1.0, we unified both implementations, so Windows now uses the same implementation Unix
|
||||
does. The threadpool size can be set by exporting the ``UV_THREADPOOL_SIZE`` environment
|
||||
variable. See :c:ref:`threadpool`.
|
||||
|
||||
|
||||
Allocation callback API change
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
In libuv 0.10 the callback had to return a filled :c:type:`uv_buf_t` by value:
|
||||
|
||||
::
|
||||
|
||||
uv_buf_t alloc_cb(uv_handle_t* handle, size_t size) {
|
||||
return uv_buf_init(malloc(size), size);
|
||||
}
|
||||
|
||||
In libuv 1.0 a pointer to a buffer is passed to the callback, which the user
|
||||
needs to fill:
|
||||
|
||||
::
|
||||
|
||||
void alloc_cb(uv_handle_t* handle, size_t size, uv_buf_t* buf) {
|
||||
buf->base = malloc(size);
|
||||
buf->len = size;
|
||||
}
|
||||
|
||||
|
||||
Unification of IPv4 / IPv6 APIs
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
libuv 1.0 unified the IPv4 and IPv6 APIS. There is no longer a `uv_tcp_bind` and `uv_tcp_bind6`
|
||||
duality, there is only :c:func:`uv_tcp_bind` now.
|
||||
|
||||
IPv4 functions took ``struct sockaddr_in`` structures by value, and IPv6 functions took
|
||||
``struct sockaddr_in6``. Now functions take a ``struct sockaddr*`` (note it's a pointer).
|
||||
It can be stack allocated.
|
||||
|
||||
libuv 0.10
|
||||
|
||||
::
|
||||
|
||||
struct sockaddr_in addr = uv_ip4_addr("0.0.0.0", 1234);
|
||||
...
|
||||
uv_tcp_bind(&server, addr)
|
||||
|
||||
libuv 1.0
|
||||
|
||||
::
|
||||
|
||||
struct sockaddr_in addr;
|
||||
uv_ip4_addr("0.0.0.0", 1234, &addr)
|
||||
...
|
||||
uv_tcp_bind(&server, (const struct sockaddr*) &addr, 0);
|
||||
|
||||
The IPv4 and IPv6 struct creating functions (:c:func:`uv_ip4_addr` and :c:func:`uv_ip6_addr`)
|
||||
have also changed, make sure you check the documentation.
|
||||
|
||||
..note::
|
||||
This change applies to all functions that made a distinction between IPv4 and IPv6
|
||||
addresses.
|
||||
|
||||
|
||||
Streams / UDP data receive callback API change
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
The streams and UDP data receive callbacks now get a pointer to a :c:type:`uv_buf_t` buffer,
|
||||
not a structure by value.
|
||||
|
||||
libuv 0.10
|
||||
|
||||
::
|
||||
|
||||
void on_read(uv_stream_t* handle,
|
||||
ssize_t nread,
|
||||
uv_buf_t buf) {
|
||||
...
|
||||
}
|
||||
|
||||
void recv_cb(uv_udp_t* handle,
|
||||
ssize_t nread,
|
||||
uv_buf_t buf,
|
||||
struct sockaddr* addr,
|
||||
unsigned flags) {
|
||||
...
|
||||
}
|
||||
|
||||
libuv 1.0
|
||||
|
||||
::
|
||||
|
||||
void on_read(uv_stream_t* handle,
|
||||
ssize_t nread,
|
||||
const uv_buf_t* buf) {
|
||||
...
|
||||
}
|
||||
|
||||
void recv_cb(uv_udp_t* handle,
|
||||
ssize_t nread,
|
||||
const uv_buf_t* buf,
|
||||
const struct sockaddr* addr,
|
||||
unsigned flags) {
|
||||
...
|
||||
}
|
||||
|
||||
|
||||
Receiving handles over pipes API change
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
In libuv 0.10 (and earlier versions) the `uv_read2_start` function was used to start reading
|
||||
data on a pipe, which could also result in the reception of handles over it. The callback
|
||||
for such function looked like this:
|
||||
|
||||
::
|
||||
|
||||
void on_read(uv_pipe_t* pipe,
|
||||
ssize_t nread,
|
||||
uv_buf_t buf,
|
||||
uv_handle_type pending) {
|
||||
...
|
||||
}
|
||||
|
||||
In libuv 1.0, `uv_read2_start` was removed, and the user needs to check if there are pending
|
||||
handles using :c:func:`uv_pipe_pending_count` and :c:func:`uv_pipe_pending_type` while in
|
||||
the read callback:
|
||||
|
||||
::
|
||||
|
||||
void on_read(uv_stream_t* handle,
|
||||
ssize_t nread,
|
||||
const uv_buf_t* buf) {
|
||||
...
|
||||
while (uv_pipe_pending_count((uv_pipe_t*) handle) != 0) {
|
||||
pending = uv_pipe_pending_type((uv_pipe_t*) handle);
|
||||
...
|
||||
}
|
||||
...
|
||||
}
|
||||
|
||||
|
||||
Extracting the file descriptor out of a handle
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
While it wasn't supported by the API, users often accessed the libuv internals in
|
||||
order to get access to the file descriptor of a TCP handle, for example.
|
||||
|
||||
::
|
||||
|
||||
fd = handle->io_watcher.fd;
|
||||
|
||||
This is now properly exposed through the :c:func:`uv_fileno` function.
|
||||
|
||||
|
||||
uv_fs_readdir rename and API change
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
`uv_fs_readdir` returned a list of strings in the `req->ptr` field upon completion in
|
||||
libuv 0.10. In 1.0, this function got renamed to :c:func:`uv_fs_scandir`, since it's
|
||||
actually implemented using ``scandir(3)``.
|
||||
|
||||
In addition, instead of allocating a full list strings, the user is able to get one
|
||||
result at a time by using the :c:func:`uv_fs_scandir_next` function. This function
|
||||
does not need to make a roundtrip to the threadpool, because libuv will keep the
|
||||
list of *dents* returned by ``scandir(3)`` around.
|
||||
378
libs/libuv/docs/src/misc.rst
Normal file
378
libs/libuv/docs/src/misc.rst
Normal file
@ -0,0 +1,378 @@
|
||||
|
||||
.. _misc:
|
||||
|
||||
Miscellaneous utilities
|
||||
=======================
|
||||
|
||||
This section contains miscellaneous functions that don't really belong in any
|
||||
other section.
|
||||
|
||||
|
||||
Data types
|
||||
----------
|
||||
|
||||
.. c:type:: uv_buf_t
|
||||
|
||||
Buffer data type.
|
||||
|
||||
.. c:member:: char* uv_buf_t.base
|
||||
|
||||
Pointer to the base of the buffer. Readonly.
|
||||
|
||||
.. c:member:: size_t uv_buf_t.len
|
||||
|
||||
Total bytes in the buffer. Readonly.
|
||||
|
||||
.. note::
|
||||
On Windows this field is ULONG.
|
||||
|
||||
.. c:type:: void* (*uv_malloc_func)(size_t size)
|
||||
|
||||
Replacement function for :man:`malloc(3)`.
|
||||
See :c:func:`uv_replace_allocator`.
|
||||
|
||||
.. c:type:: void* (*uv_realloc_func)(void* ptr, size_t size)
|
||||
|
||||
Replacement function for :man:`realloc(3)`.
|
||||
See :c:func:`uv_replace_allocator`.
|
||||
|
||||
.. c:type:: void* (*uv_calloc_func)(size_t count, size_t size)
|
||||
|
||||
Replacement function for :man:`calloc(3)`.
|
||||
See :c:func:`uv_replace_allocator`.
|
||||
|
||||
.. c:type:: void (*uv_free_func)(void* ptr)
|
||||
|
||||
Replacement function for :man:`free(3)`.
|
||||
See :c:func:`uv_replace_allocator`.
|
||||
|
||||
.. c:type:: uv_file
|
||||
|
||||
Cross platform representation of a file handle.
|
||||
|
||||
.. c:type:: uv_os_sock_t
|
||||
|
||||
Cross platform representation of a socket handle.
|
||||
|
||||
.. c:type:: uv_os_fd_t
|
||||
|
||||
Abstract representation of a file descriptor. On Unix systems this is a
|
||||
`typedef` of `int` and on Windows a `HANDLE`.
|
||||
|
||||
.. c:type:: uv_rusage_t
|
||||
|
||||
Data type for resource usage results.
|
||||
|
||||
::
|
||||
|
||||
typedef struct {
|
||||
uv_timeval_t ru_utime; /* user CPU time used */
|
||||
uv_timeval_t ru_stime; /* system CPU time used */
|
||||
uint64_t ru_maxrss; /* maximum resident set size */
|
||||
uint64_t ru_ixrss; /* integral shared memory size */
|
||||
uint64_t ru_idrss; /* integral unshared data size */
|
||||
uint64_t ru_isrss; /* integral unshared stack size */
|
||||
uint64_t ru_minflt; /* page reclaims (soft page faults) */
|
||||
uint64_t ru_majflt; /* page faults (hard page faults) */
|
||||
uint64_t ru_nswap; /* swaps */
|
||||
uint64_t ru_inblock; /* block input operations */
|
||||
uint64_t ru_oublock; /* block output operations */
|
||||
uint64_t ru_msgsnd; /* IPC messages sent */
|
||||
uint64_t ru_msgrcv; /* IPC messages received */
|
||||
uint64_t ru_nsignals; /* signals received */
|
||||
uint64_t ru_nvcsw; /* voluntary context switches */
|
||||
uint64_t ru_nivcsw; /* involuntary context switches */
|
||||
} uv_rusage_t;
|
||||
|
||||
.. c:type:: uv_cpu_info_t
|
||||
|
||||
Data type for CPU information.
|
||||
|
||||
::
|
||||
|
||||
typedef struct uv_cpu_info_s {
|
||||
char* model;
|
||||
int speed;
|
||||
struct uv_cpu_times_s {
|
||||
uint64_t user;
|
||||
uint64_t nice;
|
||||
uint64_t sys;
|
||||
uint64_t idle;
|
||||
uint64_t irq;
|
||||
} cpu_times;
|
||||
} uv_cpu_info_t;
|
||||
|
||||
.. c:type:: uv_interface_address_t
|
||||
|
||||
Data type for interface addresses.
|
||||
|
||||
::
|
||||
|
||||
typedef struct uv_interface_address_s {
|
||||
char* name;
|
||||
char phys_addr[6];
|
||||
int is_internal;
|
||||
union {
|
||||
struct sockaddr_in address4;
|
||||
struct sockaddr_in6 address6;
|
||||
} address;
|
||||
union {
|
||||
struct sockaddr_in netmask4;
|
||||
struct sockaddr_in6 netmask6;
|
||||
} netmask;
|
||||
} uv_interface_address_t;
|
||||
|
||||
.. c:type:: uv_passwd_t
|
||||
|
||||
Data type for password file information.
|
||||
|
||||
::
|
||||
|
||||
typedef struct uv_passwd_s {
|
||||
char* username;
|
||||
long uid;
|
||||
long gid;
|
||||
char* shell;
|
||||
char* homedir;
|
||||
} uv_passwd_t;
|
||||
|
||||
|
||||
API
|
||||
---
|
||||
|
||||
.. c:function:: uv_handle_type uv_guess_handle(uv_file file)
|
||||
|
||||
Used to detect what type of stream should be used with a given file
|
||||
descriptor. Usually this will be used during initialization to guess the
|
||||
type of the stdio streams.
|
||||
|
||||
For :man:`isatty(3)` equivalent functionality use this function and test
|
||||
for ``UV_TTY``.
|
||||
|
||||
.. c:function:: int uv_replace_allocator(uv_malloc_func malloc_func, uv_realloc_func realloc_func, uv_calloc_func calloc_func, uv_free_func free_func)
|
||||
|
||||
.. versionadded:: 1.6.0
|
||||
|
||||
Override the use of the standard library's :man:`malloc(3)`,
|
||||
:man:`calloc(3)`, :man:`realloc(3)`, :man:`free(3)`, memory allocation
|
||||
functions.
|
||||
|
||||
This function must be called before any other libuv function is called or
|
||||
after all resources have been freed and thus libuv doesn't reference
|
||||
any allocated memory chunk.
|
||||
|
||||
On success, it returns 0, if any of the function pointers is NULL it
|
||||
returns UV_EINVAL.
|
||||
|
||||
.. warning:: There is no protection against changing the allocator multiple
|
||||
times. If the user changes it they are responsible for making
|
||||
sure the allocator is changed while no memory was allocated with
|
||||
the previous allocator, or that they are compatible.
|
||||
|
||||
.. c:function:: uv_buf_t uv_buf_init(char* base, unsigned int len)
|
||||
|
||||
Constructor for :c:type:`uv_buf_t`.
|
||||
|
||||
Due to platform differences the user cannot rely on the ordering of the
|
||||
`base` and `len` members of the uv_buf_t struct. The user is responsible for
|
||||
freeing `base` after the uv_buf_t is done. Return struct passed by value.
|
||||
|
||||
.. c:function:: char** uv_setup_args(int argc, char** argv)
|
||||
|
||||
Store the program arguments. Required for getting / setting the process title.
|
||||
|
||||
.. c:function:: int uv_get_process_title(char* buffer, size_t size)
|
||||
|
||||
Gets the title of the current process.
|
||||
|
||||
.. c:function:: int uv_set_process_title(const char* title)
|
||||
|
||||
Sets the current process title.
|
||||
|
||||
.. c:function:: int uv_resident_set_memory(size_t* rss)
|
||||
|
||||
Gets the resident set size (RSS) for the current process.
|
||||
|
||||
.. c:function:: int uv_uptime(double* uptime)
|
||||
|
||||
Gets the current system uptime.
|
||||
|
||||
.. c:function:: int uv_getrusage(uv_rusage_t* rusage)
|
||||
|
||||
Gets the resource usage measures for the current process.
|
||||
|
||||
.. note::
|
||||
On Windows not all fields are set, the unsupported fields are filled with zeroes.
|
||||
|
||||
.. c:function:: int uv_cpu_info(uv_cpu_info_t** cpu_infos, int* count)
|
||||
|
||||
Gets information about the CPUs on the system. The `cpu_infos` array will
|
||||
have `count` elements and needs to be freed with :c:func:`uv_free_cpu_info`.
|
||||
|
||||
.. c:function:: void uv_free_cpu_info(uv_cpu_info_t* cpu_infos, int count)
|
||||
|
||||
Frees the `cpu_infos` array previously allocated with :c:func:`uv_cpu_info`.
|
||||
|
||||
.. c:function:: int uv_interface_addresses(uv_interface_address_t** addresses, int* count)
|
||||
|
||||
Gets address information about the network interfaces on the system. An
|
||||
array of `count` elements is allocated and returned in `addresses`. It must
|
||||
be freed by the user, calling :c:func:`uv_free_interface_addresses`.
|
||||
|
||||
.. c:function:: void uv_free_interface_addresses(uv_interface_address_t* addresses, int count)
|
||||
|
||||
Free an array of :c:type:`uv_interface_address_t` which was returned by
|
||||
:c:func:`uv_interface_addresses`.
|
||||
|
||||
.. c:function:: void uv_loadavg(double avg[3])
|
||||
|
||||
Gets the load average. See: `<http://en.wikipedia.org/wiki/Load_(computing)>`_
|
||||
|
||||
.. note::
|
||||
Returns [0,0,0] on Windows (i.e., it's not implemented).
|
||||
|
||||
.. c:function:: int uv_ip4_addr(const char* ip, int port, struct sockaddr_in* addr)
|
||||
|
||||
Convert a string containing an IPv4 addresses to a binary structure.
|
||||
|
||||
.. c:function:: int uv_ip6_addr(const char* ip, int port, struct sockaddr_in6* addr)
|
||||
|
||||
Convert a string containing an IPv6 addresses to a binary structure.
|
||||
|
||||
.. c:function:: int uv_ip4_name(const struct sockaddr_in* src, char* dst, size_t size)
|
||||
|
||||
Convert a binary structure containing an IPv4 address to a string.
|
||||
|
||||
.. c:function:: int uv_ip6_name(const struct sockaddr_in6* src, char* dst, size_t size)
|
||||
|
||||
Convert a binary structure containing an IPv6 address to a string.
|
||||
|
||||
.. c:function:: int uv_inet_ntop(int af, const void* src, char* dst, size_t size)
|
||||
.. c:function:: int uv_inet_pton(int af, const char* src, void* dst)
|
||||
|
||||
Cross-platform IPv6-capable implementation of :man:`inet_ntop(3)`
|
||||
and :man:`inet_pton(3)`. On success they return 0. In case of error
|
||||
the target `dst` pointer is unmodified.
|
||||
|
||||
.. c:function:: int uv_exepath(char* buffer, size_t* size)
|
||||
|
||||
Gets the executable path.
|
||||
|
||||
.. c:function:: int uv_cwd(char* buffer, size_t* size)
|
||||
|
||||
Gets the current working directory.
|
||||
|
||||
.. versionchanged:: 1.1.0
|
||||
|
||||
On Unix the path no longer ends in a slash.
|
||||
|
||||
.. c:function:: int uv_chdir(const char* dir)
|
||||
|
||||
Changes the current working directory.
|
||||
|
||||
.. c:function:: int uv_os_homedir(char* buffer, size_t* size)
|
||||
|
||||
Gets the current user's home directory. On Windows, `uv_os_homedir()` first
|
||||
checks the `USERPROFILE` environment variable using
|
||||
`GetEnvironmentVariableW()`. If `USERPROFILE` is not set,
|
||||
`GetUserProfileDirectoryW()` is called. On all other operating systems,
|
||||
`uv_os_homedir()` first checks the `HOME` environment variable using
|
||||
:man:`getenv(3)`. If `HOME` is not set, :man:`getpwuid_r(3)` is called. The
|
||||
user's home directory is stored in `buffer`. When `uv_os_homedir()` is
|
||||
called, `size` indicates the maximum size of `buffer`. On success `size` is set
|
||||
to the string length of `buffer`. On `UV_ENOBUFS` failure `size` is set to the
|
||||
required length for `buffer`, including the null byte.
|
||||
|
||||
.. warning::
|
||||
`uv_os_homedir()` is not thread safe.
|
||||
|
||||
.. versionadded:: 1.6.0
|
||||
|
||||
.. c:function:: int uv_os_tmpdir(char* buffer, size_t* size)
|
||||
|
||||
Gets the temp directory. On Windows, `uv_os_tmpdir()` uses `GetTempPathW()`.
|
||||
On all other operating systems, `uv_os_tmpdir()` uses the first environment
|
||||
variable found in the ordered list `TMPDIR`, `TMP`, `TEMP`, and `TEMPDIR`.
|
||||
If none of these are found, the path `"/tmp"` is used, or, on Android,
|
||||
`"/data/local/tmp"` is used. The temp directory is stored in `buffer`. When
|
||||
`uv_os_tmpdir()` is called, `size` indicates the maximum size of `buffer`.
|
||||
On success `size` is set to the string length of `buffer` (which does not
|
||||
include the terminating null). On `UV_ENOBUFS` failure `size` is set to the
|
||||
required length for `buffer`, including the null byte.
|
||||
|
||||
.. warning::
|
||||
`uv_os_tmpdir()` is not thread safe.
|
||||
|
||||
.. versionadded:: 1.9.0
|
||||
|
||||
.. c:function:: int uv_os_get_passwd(uv_passwd_t* pwd)
|
||||
|
||||
Gets a subset of the password file entry for the current effective uid (not
|
||||
the real uid). The populated data includes the username, euid, gid, shell,
|
||||
and home directory. On non-Windows systems, all data comes from
|
||||
:man:`getpwuid_r(3)`. On Windows, uid and gid are set to -1 and have no
|
||||
meaning, and shell is `NULL`. After successfully calling this function, the
|
||||
memory allocated to `pwd` needs to be freed with
|
||||
:c:func:`uv_os_free_passwd`.
|
||||
|
||||
.. versionadded:: 1.9.0
|
||||
|
||||
.. c:function:: void uv_os_free_passwd(uv_passwd_t* pwd)
|
||||
|
||||
Frees the `pwd` memory previously allocated with :c:func:`uv_os_get_passwd`.
|
||||
|
||||
.. versionadded:: 1.9.0
|
||||
|
||||
.. uint64_t uv_get_free_memory(void)
|
||||
.. c:function:: uint64_t uv_get_total_memory(void)
|
||||
|
||||
Gets memory information (in bytes).
|
||||
|
||||
.. c:function:: uint64_t uv_hrtime(void)
|
||||
|
||||
Returns the current high-resolution real time. This is expressed in
|
||||
nanoseconds. It is relative to an arbitrary time in the past. It is not
|
||||
related to the time of day and therefore not subject to clock drift. The
|
||||
primary use is for measuring performance between intervals.
|
||||
|
||||
.. note::
|
||||
Not every platform can support nanosecond resolution; however, this value will always
|
||||
be in nanoseconds.
|
||||
|
||||
.. c:function:: void uv_print_all_handles(uv_loop_t* loop, FILE* stream)
|
||||
|
||||
Prints all handles associated with the given `loop` to the given `stream`.
|
||||
|
||||
Example:
|
||||
|
||||
::
|
||||
|
||||
uv_print_all_handles(uv_default_loop(), stderr);
|
||||
/*
|
||||
[--I] signal 0x1a25ea8
|
||||
[-AI] async 0x1a25cf0
|
||||
[R--] idle 0x1a7a8c8
|
||||
*/
|
||||
|
||||
The format is `[flags] handle-type handle-address`. For `flags`:
|
||||
|
||||
- `R` is printed for a handle that is referenced
|
||||
- `A` is printed for a handle that is active
|
||||
- `I` is printed for a handle that is internal
|
||||
|
||||
.. warning::
|
||||
This function is meant for ad hoc debugging, there is no API/ABI
|
||||
stability guarantees.
|
||||
|
||||
.. versionadded:: 1.8.0
|
||||
|
||||
.. c:function:: void uv_print_active_handles(uv_loop_t* loop, FILE* stream)
|
||||
|
||||
This is the same as :c:func:`uv_print_all_handles` except only active handles
|
||||
are printed.
|
||||
|
||||
.. warning::
|
||||
This function is meant for ad hoc debugging, there is no API/ABI
|
||||
stability guarantees.
|
||||
|
||||
.. versionadded:: 1.8.0
|
||||
104
libs/libuv/docs/src/pipe.rst
Normal file
104
libs/libuv/docs/src/pipe.rst
Normal file
@ -0,0 +1,104 @@
|
||||
|
||||
.. _pipe:
|
||||
|
||||
:c:type:`uv_pipe_t` --- Pipe handle
|
||||
===================================
|
||||
|
||||
Pipe handles provide an abstraction over local domain sockets on Unix and named
|
||||
pipes on Windows.
|
||||
|
||||
:c:type:`uv_pipe_t` is a 'subclass' of :c:type:`uv_stream_t`.
|
||||
|
||||
|
||||
Data types
|
||||
----------
|
||||
|
||||
.. c:type:: uv_pipe_t
|
||||
|
||||
Pipe handle type.
|
||||
|
||||
|
||||
Public members
|
||||
^^^^^^^^^^^^^^
|
||||
|
||||
N/A
|
||||
|
||||
.. seealso:: The :c:type:`uv_stream_t` members also apply.
|
||||
|
||||
|
||||
API
|
||||
---
|
||||
|
||||
.. c:function:: int uv_pipe_init(uv_loop_t* loop, uv_pipe_t* handle, int ipc)
|
||||
|
||||
Initialize a pipe handle. The `ipc` argument is a boolean to indicate if
|
||||
this pipe will be used for handle passing between processes.
|
||||
|
||||
.. c:function:: int uv_pipe_open(uv_pipe_t* handle, uv_file file)
|
||||
|
||||
Open an existing file descriptor or HANDLE as a pipe.
|
||||
|
||||
.. versionchanged:: 1.2.1 the file descriptor is set to non-blocking mode.
|
||||
|
||||
.. note::
|
||||
The passed file descriptor or HANDLE is not checked for its type, but
|
||||
it's required that it represents a valid pipe.
|
||||
|
||||
.. c:function:: int uv_pipe_bind(uv_pipe_t* handle, const char* name)
|
||||
|
||||
Bind the pipe to a file path (Unix) or a name (Windows).
|
||||
|
||||
.. note::
|
||||
Paths on Unix get truncated to ``sizeof(sockaddr_un.sun_path)`` bytes, typically between
|
||||
92 and 108 bytes.
|
||||
|
||||
.. c:function:: void uv_pipe_connect(uv_connect_t* req, uv_pipe_t* handle, const char* name, uv_connect_cb cb)
|
||||
|
||||
Connect to the Unix domain socket or the named pipe.
|
||||
|
||||
.. note::
|
||||
Paths on Unix get truncated to ``sizeof(sockaddr_un.sun_path)`` bytes, typically between
|
||||
92 and 108 bytes.
|
||||
|
||||
.. c:function:: int uv_pipe_getsockname(const uv_pipe_t* handle, char* buffer, size_t* size)
|
||||
|
||||
Get the name of the Unix domain socket or the named pipe.
|
||||
|
||||
A preallocated buffer must be provided. The size parameter holds the length
|
||||
of the buffer and it's set to the number of bytes written to the buffer on
|
||||
output. If the buffer is not big enough ``UV_ENOBUFS`` will be returned and
|
||||
len will contain the required size.
|
||||
|
||||
.. versionchanged:: 1.3.0 the returned length no longer includes the terminating null byte,
|
||||
and the buffer is not null terminated.
|
||||
|
||||
.. c:function:: int uv_pipe_getpeername(const uv_pipe_t* handle, char* buffer, size_t* size)
|
||||
|
||||
Get the name of the Unix domain socket or the named pipe to which the handle
|
||||
is connected.
|
||||
|
||||
A preallocated buffer must be provided. The size parameter holds the length
|
||||
of the buffer and it's set to the number of bytes written to the buffer on
|
||||
output. If the buffer is not big enough ``UV_ENOBUFS`` will be returned and
|
||||
len will contain the required size.
|
||||
|
||||
.. versionadded:: 1.3.0
|
||||
|
||||
.. c:function:: void uv_pipe_pending_instances(uv_pipe_t* handle, int count)
|
||||
|
||||
Set the number of pending pipe instance handles when the pipe server is
|
||||
waiting for connections.
|
||||
|
||||
.. note::
|
||||
This setting applies to Windows only.
|
||||
|
||||
.. c:function:: int uv_pipe_pending_count(uv_pipe_t* handle)
|
||||
.. c:function:: uv_handle_type uv_pipe_pending_type(uv_pipe_t* handle)
|
||||
|
||||
Used to receive handles over IPC pipes.
|
||||
|
||||
First - call :c:func:`uv_pipe_pending_count`, if it's > 0 then initialize
|
||||
a handle of the given `type`, returned by :c:func:`uv_pipe_pending_type`
|
||||
and call ``uv_accept(pipe, handle)``.
|
||||
|
||||
.. seealso:: The :c:type:`uv_stream_t` API functions also apply.
|
||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user