Final release of the project Anonymizer (2015). Project settings for the Qt Creator (ver. 3.6).master v2.0.0
commit
22dbc25cce
@ -0,0 +1,9 @@
|
|||||||
|
.vs
|
||||||
|
.git
|
||||||
|
*.*sdf
|
||||||
|
*.suo
|
||||||
|
*.VC.*
|
||||||
|
*.vcxproj.user
|
||||||
|
*.user
|
||||||
|
*.user.*
|
||||||
|
Build/*
|
@ -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_
|
@ -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_
|
@ -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_
|
@ -0,0 +1,908 @@
|
|||||||
|
/*! \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 )
|
||||||
|
if( std::strncmp( searchName, it->name.GetString(), len ) == 0 )
|
||||||
|
{
|
||||||
|
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_
|
@ -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_
|
@ -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_
|
@ -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_
|
@ -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_
|
@ -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_
|
@ -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_
|
File diff suppressed because it is too large
Load Diff
@ -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_
|
@ -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_
|
@ -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_
|
@ -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_
|
@ -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_
|
@ -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_
|
@ -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_
|
@ -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_
|
@ -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.
|
@ -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_
|
@ -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_
|
@ -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_
|
@ -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_
|
@ -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_
|
@ -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.
|
File diff suppressed because one or more lines are too long
File diff suppressed because it is too large
Load Diff
@ -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
|
@ -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
|
@ -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
|
@ -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_
|
@ -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_
|
@ -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_
|
@ -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_
|
@ -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_
|
@ -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_
|
@ -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_
|
@ -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_
|
@ -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_
|
@ -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_
|
@ -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_
|
@ -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_
|
@ -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_
|
@ -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_
|
@ -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_
|
@ -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_
|
@ -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_
|
@ -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_
|
||||||
|
|
@ -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_
|
@ -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_
|
@ -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_
|
@ -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_
|
@ -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_
|
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,118 @@
|
|||||||
|
/*
|
||||||
|
* This file is part of FFmpeg.
|
||||||
|
*
|
||||||
|
* FFmpeg is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2.1 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* FFmpeg is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with FFmpeg; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef AVCODEC_AVFFT_H
|
||||||
|
#define AVCODEC_AVFFT_H
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @file
|
||||||
|
* @ingroup lavc_fft
|
||||||
|
* FFT functions
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @defgroup lavc_fft FFT functions
|
||||||
|
* @ingroup lavc_misc
|
||||||
|
*
|
||||||
|
* @{
|
||||||
|
*/
|
||||||
|
|
||||||
|
typedef float FFTSample;
|
||||||
|
|
||||||
|
typedef struct FFTComplex {
|
||||||
|
FFTSample re, im;
|
||||||
|
} FFTComplex;
|
||||||
|
|
||||||
|
typedef struct FFTContext FFTContext;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set up a complex FFT.
|
||||||
|
* @param nbits log2 of the length of the input array
|
||||||
|
* @param inverse if 0 perform the forward transform, if 1 perform the inverse
|
||||||
|
*/
|
||||||
|
FFTContext *av_fft_init(int nbits, int inverse);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Do the permutation needed BEFORE calling ff_fft_calc().
|
||||||
|
*/
|
||||||
|
void av_fft_permute(FFTContext *s, FFTComplex *z);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Do a complex FFT with the parameters defined in av_fft_init(). The
|
||||||
|
* input data must be permuted before. No 1.0/sqrt(n) normalization is done.
|
||||||
|
*/
|
||||||
|
void av_fft_calc(FFTContext *s, FFTComplex *z);
|
||||||
|
|
||||||
|
void av_fft_end(FFTContext *s);
|
||||||
|
|
||||||
|
FFTContext *av_mdct_init(int nbits, int inverse, double scale);
|
||||||
|
void av_imdct_calc(FFTContext *s, FFTSample *output, const FFTSample *input);
|
||||||
|
void av_imdct_half(FFTContext *s, FFTSample *output, const FFTSample *input);
|
||||||
|
void av_mdct_calc(FFTContext *s, FFTSample *output, const FFTSample *input);
|
||||||
|
void av_mdct_end(FFTContext *s);
|
||||||
|
|
||||||
|
/* Real Discrete Fourier Transform */
|
||||||
|
|
||||||
|
enum RDFTransformType {
|
||||||
|
DFT_R2C,
|
||||||
|
IDFT_C2R,
|
||||||
|
IDFT_R2C,
|
||||||
|
DFT_C2R,
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef struct RDFTContext RDFTContext;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set up a real FFT.
|
||||||
|
* @param nbits log2 of the length of the input array
|
||||||
|
* @param trans the type of transform
|
||||||
|
*/
|
||||||
|
RDFTContext *av_rdft_init(int nbits, enum RDFTransformType trans);
|
||||||
|
void av_rdft_calc(RDFTContext *s, FFTSample *data);
|
||||||
|
void av_rdft_end(RDFTContext *s);
|
||||||
|
|
||||||
|
/* Discrete Cosine Transform */
|
||||||
|
|
||||||
|
typedef struct DCTContext DCTContext;
|
||||||
|
|
||||||
|
enum DCTTransformType {
|
||||||
|
DCT_II = 0,
|
||||||
|
DCT_III,
|
||||||
|
DCT_I,
|
||||||
|
DST_I,
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set up DCT.
|
||||||
|
*
|
||||||
|
* @param nbits size of the input array:
|
||||||
|
* (1 << nbits) for DCT-II, DCT-III and DST-I
|
||||||
|
* (1 << nbits) + 1 for DCT-I
|
||||||
|
* @param type the type of transform
|
||||||
|
*
|
||||||
|
* @note the first element of the input of DST-I is ignored
|
||||||
|
*/
|
||||||
|
DCTContext *av_dct_init(int nbits, enum DCTTransformType type);
|
||||||
|
void av_dct_calc(DCTContext *s, FFTSample *data);
|
||||||
|
void av_dct_end (DCTContext *s);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @}
|
||||||
|
*/
|
||||||
|
|
||||||
|
#endif /* AVCODEC_AVFFT_H */
|
@ -0,0 +1,112 @@
|
|||||||
|
/*
|
||||||
|
* Direct3D11 HW acceleration
|
||||||
|
*
|
||||||
|
* copyright (c) 2009 Laurent Aimar
|
||||||
|
* copyright (c) 2015 Steve Lhomme
|
||||||
|
*
|
||||||
|
* This file is part of FFmpeg.
|
||||||
|
*
|
||||||
|
* FFmpeg is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2.1 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* FFmpeg is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with FFmpeg; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef AVCODEC_D3D11VA_H
|
||||||
|
#define AVCODEC_D3D11VA_H
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @file
|
||||||
|
* @ingroup lavc_codec_hwaccel_d3d11va
|
||||||
|
* Public libavcodec D3D11VA header.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#if !defined(_WIN32_WINNT) || _WIN32_WINNT < 0x0602
|
||||||
|
#undef _WIN32_WINNT
|
||||||
|
#define _WIN32_WINNT 0x0602
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <d3d11.h>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @defgroup lavc_codec_hwaccel_d3d11va Direct3D11
|
||||||
|
* @ingroup lavc_codec_hwaccel
|
||||||
|
*
|
||||||
|
* @{
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define FF_DXVA2_WORKAROUND_SCALING_LIST_ZIGZAG 1 ///< Work around for Direct3D11 and old UVD/UVD+ ATI video cards
|
||||||
|
#define FF_DXVA2_WORKAROUND_INTEL_CLEARVIDEO 2 ///< Work around for Direct3D11 and old Intel GPUs with ClearVideo interface
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This structure is used to provides the necessary configurations and data
|
||||||
|
* to the Direct3D11 FFmpeg HWAccel implementation.
|
||||||
|
*
|
||||||
|
* The application must make it available as AVCodecContext.hwaccel_context.
|
||||||
|
*
|
||||||
|
* Use av_d3d11va_alloc_context() exclusively to allocate an AVD3D11VAContext.
|
||||||
|
*/
|
||||||
|
typedef struct AVD3D11VAContext {
|
||||||
|
/**
|
||||||
|
* D3D11 decoder object
|
||||||
|
*/
|
||||||
|
ID3D11VideoDecoder *decoder;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* D3D11 VideoContext
|
||||||
|
*/
|
||||||
|
ID3D11VideoContext *video_context;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* D3D11 configuration used to create the decoder
|
||||||
|
*/
|
||||||
|
D3D11_VIDEO_DECODER_CONFIG *cfg;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The number of surface in the surface array
|
||||||
|
*/
|
||||||
|
unsigned surface_count;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The array of Direct3D surfaces used to create the decoder
|
||||||
|
*/
|
||||||
|
ID3D11VideoDecoderOutputView **surface;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A bit field configuring the workarounds needed for using the decoder
|
||||||
|
*/
|
||||||
|
uint64_t workaround;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Private to the FFmpeg AVHWAccel implementation
|
||||||
|
*/
|
||||||
|
unsigned report_id;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Mutex to access video_context
|
||||||
|
*/
|
||||||
|
HANDLE context_mutex;
|
||||||
|
} AVD3D11VAContext;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Allocate an AVD3D11VAContext.
|
||||||
|
*
|
||||||
|
* @return Newly-allocated AVD3D11VAContext or NULL on failure.
|
||||||
|
*/
|
||||||
|
AVD3D11VAContext *av_d3d11va_alloc_context(void);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @}
|
||||||
|
*/
|
||||||
|
|
||||||
|
#endif /* AVCODEC_D3D11VA_H */
|
@ -0,0 +1,83 @@
|
|||||||
|
/*
|
||||||
|
* This file is part of FFmpeg.
|
||||||
|
*
|
||||||
|
* FFmpeg is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2.1 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* FFmpeg is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with FFmpeg; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef AVCODEC_DV_PROFILE_H
|
||||||
|
#define AVCODEC_DV_PROFILE_H
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#include "libavutil/pixfmt.h"
|
||||||
|
#include "libavutil/rational.h"
|
||||||
|
#include "avcodec.h"
|
||||||
|
|
||||||
|
/* minimum number of bytes to read from a DV stream in order to
|
||||||
|
* determine the profile */
|
||||||
|
#define DV_PROFILE_BYTES (6 * 80) /* 6 DIF blocks */
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* AVDVProfile is used to express the differences between various
|
||||||
|
* DV flavors. For now it's primarily used for differentiating
|
||||||
|
* 525/60 and 625/50, but the plans are to use it for various
|
||||||
|
* DV specs as well (e.g. SMPTE314M vs. IEC 61834).
|
||||||
|
*/
|
||||||
|
typedef struct AVDVProfile {
|
||||||
|
int dsf; /* value of the dsf in the DV header */
|
||||||
|
int video_stype; /* stype for VAUX source pack */
|
||||||
|
int frame_size; /* total size of one frame in bytes */
|
||||||
|
int difseg_size; /* number of DIF segments per DIF channel */
|
||||||
|
int n_difchan; /* number of DIF channels per frame */
|
||||||
|
AVRational time_base; /* 1/framerate */
|
||||||
|
int ltc_divisor; /* FPS from the LTS standpoint */
|
||||||
|
int height; /* picture height in pixels */
|
||||||
|
int width; /* picture width in pixels */
|
||||||
|
AVRational sar[2]; /* sample aspect ratios for 4:3 and 16:9 */
|
||||||
|
enum AVPixelFormat pix_fmt; /* picture pixel format */
|
||||||
|
int bpm; /* blocks per macroblock */
|
||||||
|
const uint8_t *block_sizes; /* AC block sizes, in bits */
|
||||||
|
int audio_stride; /* size of audio_shuffle table */
|
||||||
|
int audio_min_samples[3]; /* min amount of audio samples */
|
||||||
|
/* for 48kHz, 44.1kHz and 32kHz */
|
||||||
|
int audio_samples_dist[5]; /* how many samples are supposed to be */
|
||||||
|
/* in each frame in a 5 frames window */
|
||||||
|
const uint8_t (*audio_shuffle)[9]; /* PCM shuffling table */
|
||||||
|
} AVDVProfile;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get a DV profile for the provided compressed frame.
|
||||||
|
*
|
||||||
|
* @param sys the profile used for the previous frame, may be NULL
|
||||||
|
* @param frame the compressed data buffer
|
||||||
|
* @param buf_size size of the buffer in bytes
|
||||||
|
* @return the DV profile for the supplied data or NULL on failure
|
||||||
|
*/
|
||||||
|
const AVDVProfile *av_dv_frame_profile(const AVDVProfile *sys,
|
||||||
|
const uint8_t *frame, unsigned buf_size);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get a DV profile for the provided stream parameters.
|
||||||
|
*/
|
||||||
|
const AVDVProfile *av_dv_codec_profile(int width, int height, enum AVPixelFormat pix_fmt);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get a DV profile for the provided stream parameters.
|
||||||
|
* The frame rate is used as a best-effort parameter.
|
||||||
|
*/
|
||||||
|
const AVDVProfile *av_dv_codec_profile2(int width, int height, enum AVPixelFormat pix_fmt, AVRational frame_rate);
|
||||||
|
|
||||||
|
#endif /* AVCODEC_DV_PROFILE_H */
|
@ -0,0 +1,93 @@
|
|||||||
|
/*
|
||||||
|
* DXVA2 HW acceleration
|
||||||
|
*
|
||||||
|
* copyright (c) 2009 Laurent Aimar
|
||||||
|
*
|
||||||
|
* This file is part of FFmpeg.
|
||||||
|
*
|
||||||
|
* FFmpeg is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2.1 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* FFmpeg is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with FFmpeg; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef AVCODEC_DXVA_H
|
||||||
|
#define AVCODEC_DXVA_H
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @file
|
||||||
|
* @ingroup lavc_codec_hwaccel_dxva2
|
||||||
|
* Public libavcodec DXVA2 header.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#if !defined(_WIN32_WINNT) || _WIN32_WINNT < 0x0602
|
||||||
|
#undef _WIN32_WINNT
|
||||||
|
#define _WIN32_WINNT 0x0602
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <d3d9.h>
|
||||||
|
#include <dxva2api.h>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @defgroup lavc_codec_hwaccel_dxva2 DXVA2
|
||||||
|
* @ingroup lavc_codec_hwaccel
|
||||||
|
*
|
||||||
|
* @{
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define FF_DXVA2_WORKAROUND_SCALING_LIST_ZIGZAG 1 ///< Work around for DXVA2 and old UVD/UVD+ ATI video cards
|
||||||
|
#define FF_DXVA2_WORKAROUND_INTEL_CLEARVIDEO 2 ///< Work around for DXVA2 and old Intel GPUs with ClearVideo interface
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This structure is used to provides the necessary configurations and data
|
||||||
|
* to the DXVA2 FFmpeg HWAccel implementation.
|
||||||
|
*
|
||||||
|
* The application must make it available as AVCodecContext.hwaccel_context.
|
||||||
|
*/
|
||||||
|
struct dxva_context {
|
||||||
|
/**
|
||||||
|
* DXVA2 decoder object
|
||||||
|
*/
|
||||||
|
IDirectXVideoDecoder *decoder;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* DXVA2 configuration used to create the decoder
|
||||||
|
*/
|
||||||
|
const DXVA2_ConfigPictureDecode *cfg;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The number of surface in the surface array
|
||||||
|
*/
|
||||||
|
unsigned surface_count;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The array of Direct3D surfaces used to create the decoder
|
||||||
|
*/
|
||||||
|
LPDIRECT3DSURFACE9 *surface;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A bit field configuring the workarounds needed for using the decoder
|
||||||
|
*/
|
||||||
|
uint64_t workaround;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Private to the FFmpeg AVHWAccel implementation
|
||||||
|
*/
|
||||||
|
unsigned report_id;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @}
|
||||||
|
*/
|
||||||
|
|
||||||
|
#endif /* AVCODEC_DXVA_H */
|
@ -0,0 +1,60 @@
|
|||||||
|
/*
|
||||||
|
* Intel MediaSDK QSV public API
|
||||||
|
*
|
||||||
|
* This file is part of FFmpeg.
|
||||||
|
*
|
||||||
|
* FFmpeg is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2.1 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* FFmpeg is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with FFmpeg; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef AVCODEC_QSV_H
|
||||||
|
#define AVCODEC_QSV_H
|
||||||
|
|
||||||
|
#include <mfx/mfxvideo.h>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This struct is used for communicating QSV parameters between libavcodec and
|
||||||
|
* the caller. It is managed by the caller and must be assigned to
|
||||||
|
* AVCodecContext.hwaccel_context.
|
||||||
|
* - decoding: hwaccel_context must be set on return from the get_format()
|
||||||
|
* callback
|
||||||
|
* - encoding: hwaccel_context must be set before avcodec_open2()
|
||||||
|
*/
|
||||||
|
typedef struct AVQSVContext {
|
||||||
|
/**
|
||||||
|
* If non-NULL, the session to use for encoding or decoding.
|
||||||
|
* Otherwise, libavcodec will try to create an internal session.
|
||||||
|
*/
|
||||||
|
mfxSession session;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The IO pattern to use.
|
||||||
|
*/
|
||||||
|
int iopattern;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Extra buffers to pass to encoder or decoder initialization.
|
||||||
|
*/
|
||||||
|
mfxExtBuffer **ext_buffers;
|
||||||
|
int nb_ext_buffers;
|
||||||
|
} AVQSVContext;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Allocate a new context.
|
||||||
|
*
|
||||||
|
* It must be freed by the caller with av_free().
|
||||||
|
*/
|
||||||
|
AVQSVContext *av_qsv_alloc_context(void);
|
||||||
|
|
||||||
|
#endif /* AVCODEC_QSV_H */
|
@ -0,0 +1,189 @@
|
|||||||
|
/*
|
||||||
|
* Video Acceleration API (shared data between FFmpeg and the video player)
|
||||||
|
* HW decode acceleration for MPEG-2, MPEG-4, H.264 and VC-1
|
||||||
|
*
|
||||||
|
* Copyright (C) 2008-2009 Splitted-Desktop Systems
|
||||||
|
*
|
||||||
|
* This file is part of FFmpeg.
|
||||||
|
*
|
||||||
|
* FFmpeg is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2.1 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* FFmpeg is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with FFmpeg; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef AVCODEC_VAAPI_H
|
||||||
|
#define AVCODEC_VAAPI_H
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @file
|
||||||
|
* @ingroup lavc_codec_hwaccel_vaapi
|
||||||
|
* Public libavcodec VA API header.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
#include "libavutil/attributes.h"
|
||||||
|
#include "version.h"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @defgroup lavc_codec_hwaccel_vaapi VA API Decoding
|
||||||
|
* @ingroup lavc_codec_hwaccel
|
||||||
|
* @{
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This structure is used to share data between the FFmpeg library and
|
||||||
|
* the client video application.
|
||||||
|
* This shall be zero-allocated and available as
|
||||||
|
* AVCodecContext.hwaccel_context. All user members can be set once
|
||||||
|
* during initialization or through each AVCodecContext.get_buffer()
|
||||||
|
* function call. In any case, they must be valid prior to calling
|
||||||
|
* decoding functions.
|
||||||
|
*/
|
||||||
|
struct vaapi_context {
|
||||||
|
/**
|
||||||
|
* Window system dependent data
|
||||||
|
*
|
||||||
|
* - encoding: unused
|
||||||
|
* - decoding: Set by user
|
||||||
|
*/
|
||||||
|
void *display;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Configuration ID
|
||||||
|
*
|
||||||
|
* - encoding: unused
|
||||||
|
* - decoding: Set by user
|
||||||
|
*/
|
||||||
|
uint32_t config_id;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Context ID (video decode pipeline)
|
||||||
|
*
|
||||||
|
* - encoding: unused
|
||||||
|
* - decoding: Set by user
|
||||||
|
*/
|
||||||
|
uint32_t context_id;
|
||||||
|
|
||||||
|
#if FF_API_VAAPI_CONTEXT
|
||||||
|
/**
|
||||||
|
* VAPictureParameterBuffer ID
|
||||||
|
*
|
||||||
|
* - encoding: unused
|
||||||
|
* - decoding: Set by libavcodec
|
||||||
|
*/
|
||||||
|
attribute_deprecated
|
||||||
|
uint32_t pic_param_buf_id;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* VAIQMatrixBuffer ID
|
||||||
|
*
|
||||||
|
* - encoding: unused
|
||||||
|
* - decoding: Set by libavcodec
|
||||||
|
*/
|
||||||
|
attribute_deprecated
|
||||||
|
uint32_t iq_matrix_buf_id;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* VABitPlaneBuffer ID (for VC-1 decoding)
|
||||||
|
*
|
||||||
|
* - encoding: unused
|
||||||
|
* - decoding: Set by libavcodec
|
||||||
|
*/
|
||||||
|
attribute_deprecated
|
||||||
|
uint32_t bitplane_buf_id;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Slice parameter/data buffer IDs
|
||||||
|
*
|
||||||
|
* - encoding: unused
|
||||||
|
* - decoding: Set by libavcodec
|
||||||
|
*/
|
||||||
|
attribute_deprecated
|
||||||
|
uint32_t *slice_buf_ids;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Number of effective slice buffer IDs to send to the HW
|
||||||
|
*
|
||||||
|
* - encoding: unused
|
||||||
|
* - decoding: Set by libavcodec
|
||||||
|
*/
|
||||||
|
attribute_deprecated
|
||||||
|
unsigned int n_slice_buf_ids;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Size of pre-allocated slice_buf_ids
|
||||||
|
*
|
||||||
|
* - encoding: unused
|
||||||
|
* - decoding: Set by libavcodec
|
||||||
|
*/
|
||||||
|
attribute_deprecated
|
||||||
|
unsigned int slice_buf_ids_alloc;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Pointer to VASliceParameterBuffers
|
||||||
|
*
|
||||||
|
* - encoding: unused
|
||||||
|
* - decoding: Set by libavcodec
|
||||||
|
*/
|
||||||
|
attribute_deprecated
|
||||||
|
void *slice_params;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Size of a VASliceParameterBuffer element
|
||||||
|
*
|
||||||
|
* - encoding: unused
|
||||||
|
* - decoding: Set by libavcodec
|
||||||
|
*/
|
||||||
|
attribute_deprecated
|
||||||
|
unsigned int slice_param_size;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Size of pre-allocated slice_params
|
||||||
|
*
|
||||||
|
* - encoding: unused
|
||||||
|
* - decoding: Set by libavcodec
|
||||||
|
*/
|
||||||
|
attribute_deprecated
|
||||||
|
unsigned int slice_params_alloc;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Number of slices currently filled in
|
||||||
|
*
|
||||||
|
* - encoding: unused
|
||||||
|
* - decoding: Set by libavcodec
|
||||||
|
*/
|
||||||
|
attribute_deprecated
|
||||||
|
unsigned int slice_count;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Pointer to slice data buffer base
|
||||||
|
* - encoding: unused
|
||||||
|
* - decoding: Set by libavcodec
|
||||||
|
*/
|
||||||
|
attribute_deprecated
|
||||||
|
const uint8_t *slice_data;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Current size of slice data
|
||||||
|
*
|
||||||
|
* - encoding: unused
|
||||||
|
* - decoding: Set by libavcodec
|
||||||
|
*/
|
||||||
|
attribute_deprecated
|
||||||
|
uint32_t slice_data_size;
|
||||||
|
#endif
|
||||||
|
};
|
||||||
|
|
||||||
|
/* @} */
|
||||||
|
|
||||||
|
#endif /* AVCODEC_VAAPI_H */
|
@ -0,0 +1,230 @@
|
|||||||
|
/*
|
||||||
|
* VDA HW acceleration
|
||||||
|
*
|
||||||
|
* copyright (c) 2011 Sebastien Zwickert
|
||||||
|
*
|
||||||
|
* This file is part of FFmpeg.
|
||||||
|
*
|
||||||
|
* FFmpeg is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2.1 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* FFmpeg is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with FFmpeg; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef AVCODEC_VDA_H
|
||||||
|
#define AVCODEC_VDA_H
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @file
|
||||||
|
* @ingroup lavc_codec_hwaccel_vda
|
||||||
|
* Public libavcodec VDA header.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "libavcodec/avcodec.h"
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
// emmintrin.h is unable to compile with -std=c99 -Werror=missing-prototypes
|
||||||
|
// http://openradar.appspot.com/8026390
|
||||||
|
#undef __GNUC_STDC_INLINE__
|
||||||
|
|
||||||
|
#define Picture QuickdrawPicture
|
||||||
|
#include <VideoDecodeAcceleration/VDADecoder.h>
|
||||||
|
#undef Picture
|
||||||
|
|
||||||
|
#include "libavcodec/version.h"
|
||||||
|
|
||||||
|
// extra flags not defined in VDADecoder.h
|
||||||
|
enum {
|
||||||
|
kVDADecodeInfo_Asynchronous = 1UL << 0,
|
||||||
|
kVDADecodeInfo_FrameDropped = 1UL << 1
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @defgroup lavc_codec_hwaccel_vda VDA
|
||||||
|
* @ingroup lavc_codec_hwaccel
|
||||||
|
*
|
||||||
|
* @{
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This structure is used to provide the necessary configurations and data
|
||||||
|
* to the VDA FFmpeg HWAccel implementation.
|
||||||
|
*
|
||||||
|
* The application must make it available as AVCodecContext.hwaccel_context.
|
||||||
|
*/
|
||||||
|
struct vda_context {
|
||||||
|
/**
|
||||||
|
* VDA decoder object.
|
||||||
|
*
|
||||||
|
* - encoding: unused
|
||||||
|
* - decoding: Set/Unset by libavcodec.
|
||||||
|
*/
|
||||||
|
VDADecoder decoder;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The Core Video pixel buffer that contains the current image data.
|
||||||
|
*
|
||||||
|
* encoding: unused
|
||||||
|
* decoding: Set by libavcodec. Unset by user.
|
||||||
|
*/
|
||||||
|
CVPixelBufferRef cv_buffer;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Use the hardware decoder in synchronous mode.
|
||||||
|
*
|
||||||
|
* encoding: unused
|
||||||
|
* decoding: Set by user.
|
||||||
|
*/
|
||||||
|
int use_sync_decoding;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The frame width.
|
||||||
|
*
|
||||||
|
* - encoding: unused
|
||||||
|
* - decoding: Set/Unset by user.
|
||||||
|
*/
|
||||||
|
int width;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The frame height.
|
||||||
|
*
|
||||||
|
* - encoding: unused
|
||||||
|
* - decoding: Set/Unset by user.
|
||||||
|
*/
|
||||||
|
int height;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The frame format.
|
||||||
|
*
|
||||||
|
* - encoding: unused
|
||||||
|
* - decoding: Set/Unset by user.
|
||||||
|
*/
|
||||||
|
int format;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The pixel format for output image buffers.
|
||||||
|
*
|
||||||
|
* - encoding: unused
|
||||||
|
* - decoding: Set/Unset by user.
|
||||||
|
*/
|
||||||
|
OSType cv_pix_fmt_type;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* unused
|
||||||
|
*/
|
||||||
|
uint8_t *priv_bitstream;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* unused
|
||||||
|
*/
|
||||||
|
int priv_bitstream_size;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* unused
|
||||||
|
*/
|
||||||
|
int priv_allocated_size;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Use av_buffer to manage buffer.
|
||||||
|
* When the flag is set, the CVPixelBuffers returned by the decoder will
|
||||||
|
* be released automatically, so you have to retain them if necessary.
|
||||||
|
* Not setting this flag may cause memory leak.
|
||||||
|
*
|
||||||
|
* encoding: unused
|
||||||
|
* decoding: Set by user.
|
||||||
|
*/
|
||||||
|
int use_ref_buffer;
|
||||||
|
};
|
||||||
|
|
||||||
|
/** Create the video decoder. */
|
||||||
|
int ff_vda_create_decoder(struct vda_context *vda_ctx,
|
||||||
|
uint8_t *extradata,
|
||||||
|
int extradata_size);
|
||||||
|
|
||||||
|
/** Destroy the video decoder. */
|
||||||
|
int ff_vda_destroy_decoder(struct vda_context *vda_ctx);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This struct holds all the information that needs to be passed
|
||||||
|
* between the caller and libavcodec for initializing VDA decoding.
|
||||||
|
* Its size is not a part of the public ABI, it must be allocated with
|
||||||
|
* av_vda_alloc_context() and freed with av_free().
|
||||||
|
*/
|
||||||
|
typedef struct AVVDAContext {
|
||||||
|
/**
|
||||||
|
* VDA decoder object. Created and freed by the caller.
|
||||||
|
*/
|
||||||
|
VDADecoder decoder;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The output callback that must be passed to VDADecoderCreate.
|
||||||
|
* Set by av_vda_alloc_context().
|
||||||
|
*/
|
||||||
|
VDADecoderOutputCallback output_callback;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* CVPixelBuffer Format Type that VDA will use for decoded frames; set by
|
||||||
|
* the caller.
|
||||||
|
*/
|
||||||
|
OSType cv_pix_fmt_type;
|
||||||
|
} AVVDAContext;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Allocate and initialize a VDA context.
|
||||||
|
*
|
||||||
|
* This function should be called from the get_format() callback when the caller
|
||||||
|
* selects the AV_PIX_FMT_VDA format. The caller must then create the decoder
|
||||||
|
* object (using the output callback provided by libavcodec) that will be used
|
||||||
|
* for VDA-accelerated decoding.
|
||||||
|
*
|
||||||
|
* When decoding with VDA is finished, the caller must destroy the decoder
|
||||||
|
* object and free the VDA context using av_free().
|
||||||
|
*
|
||||||
|
* @return the newly allocated context or NULL on failure
|
||||||
|
*/
|
||||||
|
AVVDAContext *av_vda_alloc_context(void);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This is a convenience function that creates and sets up the VDA context using
|
||||||
|
* an internal implementation.
|
||||||
|
*
|
||||||
|
* @param avctx the corresponding codec context
|
||||||
|
*
|
||||||
|
* @return >= 0 on success, a negative AVERROR code on failure
|
||||||
|
*/
|
||||||
|
int av_vda_default_init(AVCodecContext *avctx);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This is a convenience function that creates and sets up the VDA context using
|
||||||
|
* an internal implementation.
|
||||||
|
*
|
||||||
|
* @param avctx the corresponding codec context
|
||||||
|
* @param vdactx the VDA context to use
|
||||||
|
*
|
||||||
|
* @return >= 0 on success, a negative AVERROR code on failure
|
||||||
|
*/
|
||||||
|
int av_vda_default_init2(AVCodecContext *avctx, AVVDAContext *vdactx);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This function must be called to free the VDA context initialized with
|
||||||
|
* av_vda_default_init().
|
||||||
|
*
|
||||||
|
* @param avctx the corresponding codec context
|
||||||
|
*/
|
||||||
|
void av_vda_default_free(AVCodecContext *avctx);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @}
|
||||||
|
*/
|
||||||
|
|
||||||
|
#endif /* AVCODEC_VDA_H */
|
@ -0,0 +1,253 @@
|
|||||||
|
/*
|
||||||
|
* The Video Decode and Presentation API for UNIX (VDPAU) is used for
|
||||||
|
* hardware-accelerated decoding of MPEG-1/2, H.264 and VC-1.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2008 NVIDIA
|
||||||
|
*
|
||||||
|
* This file is part of FFmpeg.
|
||||||
|
*
|
||||||
|
* FFmpeg is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2.1 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* FFmpeg is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with FFmpeg; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef AVCODEC_VDPAU_H
|
||||||
|
#define AVCODEC_VDPAU_H
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @file
|
||||||
|
* @ingroup lavc_codec_hwaccel_vdpau
|
||||||
|
* Public libavcodec VDPAU header.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @defgroup lavc_codec_hwaccel_vdpau VDPAU Decoder and Renderer
|
||||||
|
* @ingroup lavc_codec_hwaccel
|
||||||
|
*
|
||||||
|
* VDPAU hardware acceleration has two modules
|
||||||
|
* - VDPAU decoding
|
||||||
|
* - VDPAU presentation
|
||||||
|
*
|
||||||
|
* The VDPAU decoding module parses all headers using FFmpeg
|
||||||
|
* parsing mechanisms and uses VDPAU for the actual decoding.
|
||||||
|
*
|
||||||
|
* As per the current implementation, the actual decoding
|
||||||
|
* and rendering (API calls) are done as part of the VDPAU
|
||||||
|
* presentation (vo_vdpau.c) module.
|
||||||
|
*
|
||||||
|
* @{
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <vdpau/vdpau.h>
|
||||||
|
#include <vdpau/vdpau_x11.h>
|
||||||
|
#include "libavutil/avconfig.h"
|
||||||
|
#include "libavutil/attributes.h"
|
||||||
|
|
||||||
|
#include "avcodec.h"
|
||||||
|
#include "version.h"
|
||||||
|
|
||||||
|
#if FF_API_BUFS_VDPAU
|
||||||
|
union AVVDPAUPictureInfo {
|
||||||
|
VdpPictureInfoH264 h264;
|
||||||
|
VdpPictureInfoMPEG1Or2 mpeg;
|
||||||
|
VdpPictureInfoVC1 vc1;
|
||||||
|
VdpPictureInfoMPEG4Part2 mpeg4;
|
||||||
|
};
|
||||||
|
#endif
|
||||||
|
|
||||||
|
struct AVCodecContext;
|
||||||
|
struct AVFrame;
|
||||||
|
|
||||||
|
typedef int (*AVVDPAU_Render2)(struct AVCodecContext *, struct AVFrame *,
|
||||||
|
const VdpPictureInfo *, uint32_t,
|
||||||
|
const VdpBitstreamBuffer *);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This structure is used to share data between the libavcodec library and
|
||||||
|
* the client video application.
|
||||||
|
* The user shall allocate the structure via the av_alloc_vdpau_hwaccel
|
||||||
|
* function and make it available as
|
||||||
|
* AVCodecContext.hwaccel_context. Members can be set by the user once
|
||||||
|
* during initialization or through each AVCodecContext.get_buffer()
|
||||||
|
* function call. In any case, they must be valid prior to calling
|
||||||
|
* decoding functions.
|
||||||
|
*
|
||||||
|
* The size of this structure is not a part of the public ABI and must not
|
||||||
|
* be used outside of libavcodec. Use av_vdpau_alloc_context() to allocate an
|
||||||
|
* AVVDPAUContext.
|
||||||
|
*/
|
||||||
|
typedef struct AVVDPAUContext {
|
||||||
|
/**
|
||||||
|
* VDPAU decoder handle
|
||||||
|
*
|
||||||
|
* Set by user.
|
||||||
|
*/
|
||||||
|
VdpDecoder decoder;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* VDPAU decoder render callback
|
||||||
|
*
|
||||||
|
* Set by the user.
|
||||||
|
*/
|
||||||
|
VdpDecoderRender *render;
|
||||||
|
|
||||||
|
#if FF_API_BUFS_VDPAU
|
||||||
|
/**
|
||||||
|
* VDPAU picture information
|
||||||
|
*
|
||||||
|
* Set by libavcodec.
|
||||||
|
*/
|
||||||
|
attribute_deprecated
|
||||||
|
union AVVDPAUPictureInfo info;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Allocated size of the bitstream_buffers table.
|
||||||
|
*
|
||||||
|
* Set by libavcodec.
|
||||||
|
*/
|
||||||
|
attribute_deprecated
|
||||||
|
int bitstream_buffers_allocated;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Useful bitstream buffers in the bitstream buffers table.
|
||||||
|
*
|
||||||
|
* Set by libavcodec.
|
||||||
|
*/
|
||||||
|
attribute_deprecated
|
||||||
|
int bitstream_buffers_used;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Table of bitstream buffers.
|
||||||
|
* The user is responsible for freeing this buffer using av_freep().
|
||||||
|
*
|
||||||
|
* Set by libavcodec.
|
||||||
|
*/
|
||||||
|
attribute_deprecated
|
||||||
|
VdpBitstreamBuffer *bitstream_buffers;
|
||||||
|
#endif
|
||||||
|
AVVDPAU_Render2 render2;
|
||||||
|
} AVVDPAUContext;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief allocation function for AVVDPAUContext
|
||||||
|
*
|
||||||
|
* Allows extending the struct without breaking API/ABI
|
||||||
|
*/
|
||||||
|
AVVDPAUContext *av_alloc_vdpaucontext(void);
|
||||||
|
|
||||||
|
AVVDPAU_Render2 av_vdpau_hwaccel_get_render2(const AVVDPAUContext *);
|
||||||
|
void av_vdpau_hwaccel_set_render2(AVVDPAUContext *, AVVDPAU_Render2);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Associate a VDPAU device with a codec context for hardware acceleration.
|
||||||
|
* This function is meant to be called from the get_format() codec callback,
|
||||||
|
* or earlier. It can also be called after avcodec_flush_buffers() to change
|
||||||
|
* the underlying VDPAU device mid-stream (e.g. to recover from non-transparent
|
||||||
|
* display preemption).
|
||||||
|
*
|
||||||
|
* @note get_format() must return AV_PIX_FMT_VDPAU if this function completes
|
||||||
|
* successfully.
|
||||||
|
*
|
||||||
|
* @param avctx decoding context whose get_format() callback is invoked
|
||||||
|
* @param device VDPAU device handle to use for hardware acceleration
|
||||||
|
* @param get_proc_address VDPAU device driver
|
||||||
|
* @param flags zero of more OR'd AV_HWACCEL_FLAG_* flags
|
||||||
|
*
|
||||||
|
* @return 0 on success, an AVERROR code on failure.
|
||||||
|
*/
|
||||||
|
int av_vdpau_bind_context(AVCodecContext *avctx, VdpDevice device,
|
||||||
|
VdpGetProcAddress *get_proc_address, unsigned flags);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the parameters to create an adequate VDPAU video surface for the codec
|
||||||
|
* context using VDPAU hardware decoding acceleration.
|
||||||
|
*
|
||||||
|
* @note Behavior is undefined if the context was not successfully bound to a
|
||||||
|
* VDPAU device using av_vdpau_bind_context().
|
||||||
|
*
|
||||||
|
* @param avctx the codec context being used for decoding the stream
|
||||||
|
* @param type storage space for the VDPAU video surface chroma type
|
||||||
|
* (or NULL to ignore)
|
||||||
|
* @param width storage space for the VDPAU video surface pixel width
|
||||||
|
* (or NULL to ignore)
|
||||||
|
* @param height storage space for the VDPAU video surface pixel height
|
||||||
|
* (or NULL to ignore)
|
||||||
|
*
|
||||||
|
* @return 0 on success, a negative AVERROR code on failure.
|
||||||
|
*/
|
||||||
|
int av_vdpau_get_surface_parameters(AVCodecContext *avctx, VdpChromaType *type,
|
||||||
|
uint32_t *width, uint32_t *height);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Allocate an AVVDPAUContext.
|
||||||
|
*
|
||||||
|
* @return Newly-allocated AVVDPAUContext or NULL on failure.
|
||||||
|
*/
|
||||||
|
AVVDPAUContext *av_vdpau_alloc_context(void);
|
||||||
|
|
||||||
|
#if FF_API_VDPAU_PROFILE
|
||||||
|
/**
|
||||||
|
* Get a decoder profile that should be used for initializing a VDPAU decoder.
|
||||||
|
* Should be called from the AVCodecContext.get_format() callback.
|
||||||
|
*
|
||||||
|
* @deprecated Use av_vdpau_bind_context() instead.
|
||||||
|
*
|
||||||
|
* @param avctx the codec context being used for decoding the stream
|
||||||
|
* @param profile a pointer into which the result will be written on success.
|
||||||
|
* The contents of profile are undefined if this function returns
|
||||||
|
* an error.
|
||||||
|
*
|
||||||
|
* @return 0 on success (non-negative), a negative AVERROR on failure.
|
||||||
|
*/
|
||||||
|
attribute_deprecated
|
||||||
|
int av_vdpau_get_profile(AVCodecContext *avctx, VdpDecoderProfile *profile);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if FF_API_CAP_VDPAU
|
||||||
|
/** @brief The videoSurface is used for rendering. */
|
||||||
|
#define FF_VDPAU_STATE_USED_FOR_RENDER 1
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief The videoSurface is needed for reference/prediction.
|
||||||
|
* The codec manipulates this.
|
||||||
|
*/
|
||||||
|
#define FF_VDPAU_STATE_USED_FOR_REFERENCE 2
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief This structure is used as a callback between the FFmpeg
|
||||||
|
* decoder (vd_) and presentation (vo_) module.
|
||||||
|
* This is used for defining a video frame containing surface,
|
||||||
|
* picture parameter, bitstream information etc which are passed
|
||||||
|
* between the FFmpeg decoder and its clients.
|
||||||
|
*/
|
||||||
|
struct vdpau_render_state {
|
||||||
|
VdpVideoSurface surface; ///< Used as rendered surface, never changed.
|
||||||
|
|
||||||
|
int state; ///< Holds FF_VDPAU_STATE_* values.
|
||||||
|
|
||||||
|
/** picture parameter information for all supported codecs */
|
||||||
|
union AVVDPAUPictureInfo info;
|
||||||
|
|
||||||
|
/** Describe size/location of the compressed video data.
|
||||||
|
Set to 0 when freeing bitstream_buffers. */
|
||||||
|
int bitstream_buffers_allocated;
|
||||||
|
int bitstream_buffers_used;
|
||||||
|
/** The user is responsible for freeing this buffer using av_freep(). */
|
||||||
|
VdpBitstreamBuffer *bitstream_buffers;
|
||||||
|
};
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* @}*/
|
||||||
|
|
||||||
|
#endif /* AVCODEC_VDPAU_H */
|
@ -0,0 +1,192 @@
|
|||||||
|
/*
|
||||||
|
*
|
||||||
|
* This file is part of FFmpeg.
|
||||||
|
*
|
||||||
|
* FFmpeg is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2.1 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* FFmpeg is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with FFmpeg; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef AVCODEC_VERSION_H
|
||||||
|
#define AVCODEC_VERSION_H
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @file
|
||||||
|
* @ingroup libavc
|
||||||
|
* Libavcodec version macros.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "libavutil/version.h"
|
||||||
|
|
||||||
|
#define LIBAVCODEC_VERSION_MAJOR 57
|
||||||
|
#define LIBAVCODEC_VERSION_MINOR 4
|
||||||
|
#define LIBAVCODEC_VERSION_MICRO 100
|
||||||
|
|
||||||
|
#define LIBAVCODEC_VERSION_INT AV_VERSION_INT(LIBAVCODEC_VERSION_MAJOR, \
|
||||||
|
LIBAVCODEC_VERSION_MINOR, \
|
||||||
|
LIBAVCODEC_VERSION_MICRO)
|
||||||
|
#define LIBAVCODEC_VERSION AV_VERSION(LIBAVCODEC_VERSION_MAJOR, \
|
||||||
|
LIBAVCODEC_VERSION_MINOR, \
|
||||||
|
LIBAVCODEC_VERSION_MICRO)
|
||||||
|
#define LIBAVCODEC_BUILD LIBAVCODEC_VERSION_INT
|
||||||
|
|
||||||
|
#define LIBAVCODEC_IDENT "Lavc" AV_STRINGIFY(LIBAVCODEC_VERSION)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* FF_API_* defines may be placed below to indicate public API that will be
|
||||||
|
* dropped at a future version bump. The defines themselves are not part of
|
||||||
|
* the public API and may change, break or disappear at any time.
|
||||||
|
*
|
||||||
|
* @note, when bumping the major version it is recommended to manually
|
||||||
|
* disable each FF_API_* in its own commit instead of disabling them all
|
||||||
|
* at once through the bump. This improves the git bisect-ability of the change.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef FF_API_VIMA_DECODER
|
||||||
|
#define FF_API_VIMA_DECODER (LIBAVCODEC_VERSION_MAJOR < 58)
|
||||||
|
#endif
|
||||||
|
#ifndef FF_API_AUDIO_CONVERT
|
||||||
|
#define FF_API_AUDIO_CONVERT (LIBAVCODEC_VERSION_MAJOR < 58)
|
||||||
|
#endif
|
||||||
|
#ifndef FF_API_AVCODEC_RESAMPLE
|
||||||
|
#define FF_API_AVCODEC_RESAMPLE FF_API_AUDIO_CONVERT
|
||||||
|
#endif
|
||||||
|
#ifndef FF_API_MISSING_SAMPLE
|
||||||
|
#define FF_API_MISSING_SAMPLE (LIBAVCODEC_VERSION_MAJOR < 58)
|
||||||
|
#endif
|
||||||
|
#ifndef FF_API_LOWRES
|
||||||
|
#define FF_API_LOWRES (LIBAVCODEC_VERSION_MAJOR < 58)
|
||||||
|
#endif
|
||||||
|
#ifndef FF_API_CAP_VDPAU
|
||||||
|
#define FF_API_CAP_VDPAU (LIBAVCODEC_VERSION_MAJOR < 58)
|
||||||
|
#endif
|
||||||
|
#ifndef FF_API_BUFS_VDPAU
|
||||||
|
#define FF_API_BUFS_VDPAU (LIBAVCODEC_VERSION_MAJOR < 58)
|
||||||
|
#endif
|
||||||
|
#ifndef FF_API_VOXWARE
|
||||||
|
#define FF_API_VOXWARE (LIBAVCODEC_VERSION_MAJOR < 58)
|
||||||
|
#endif
|
||||||
|
#ifndef FF_API_SET_DIMENSIONS
|
||||||
|
#define FF_API_SET_DIMENSIONS (LIBAVCODEC_VERSION_MAJOR < 58)
|
||||||
|
#endif
|
||||||
|
#ifndef FF_API_DEBUG_MV
|
||||||
|
#define FF_API_DEBUG_MV (LIBAVCODEC_VERSION_MAJOR < 58)
|
||||||
|
#endif
|
||||||
|
#ifndef FF_API_AC_VLC
|
||||||
|
#define FF_API_AC_VLC (LIBAVCODEC_VERSION_MAJOR < 58)
|
||||||
|
#endif
|
||||||
|
#ifndef FF_API_OLD_MSMPEG4
|
||||||
|
#define FF_API_OLD_MSMPEG4 (LIBAVCODEC_VERSION_MAJOR < 58)
|
||||||
|
#endif
|
||||||
|
#ifndef FF_API_ASPECT_EXTENDED
|
||||||
|
#define FF_API_ASPECT_EXTENDED (LIBAVCODEC_VERSION_MAJOR < 58)
|
||||||
|
#endif
|
||||||
|
#ifndef FF_API_ARCH_ALPHA
|
||||||
|
#define FF_API_ARCH_ALPHA (LIBAVCODEC_VERSION_MAJOR < 58)
|
||||||
|
#endif
|
||||||
|
#ifndef FF_API_XVMC
|
||||||
|
#define FF_API_XVMC (LIBAVCODEC_VERSION_MAJOR < 58)
|
||||||
|
#endif
|
||||||
|
#ifndef FF_API_ERROR_RATE
|
||||||
|
#define FF_API_ERROR_RATE (LIBAVCODEC_VERSION_MAJOR < 58)
|
||||||
|
#endif
|
||||||
|
#ifndef FF_API_QSCALE_TYPE
|
||||||
|
#define FF_API_QSCALE_TYPE (LIBAVCODEC_VERSION_MAJOR < 58)
|
||||||
|
#endif
|
||||||
|
#ifndef FF_API_MB_TYPE
|
||||||
|
#define FF_API_MB_TYPE (LIBAVCODEC_VERSION_MAJOR < 58)
|
||||||
|
#endif
|
||||||
|
#ifndef FF_API_MAX_BFRAMES
|
||||||
|
#define FF_API_MAX_BFRAMES (LIBAVCODEC_VERSION_MAJOR < 58)
|
||||||
|
#endif
|
||||||
|
#ifndef FF_API_NEG_LINESIZES
|
||||||
|
#define FF_API_NEG_LINESIZES (LIBAVCODEC_VERSION_MAJOR < 58)
|
||||||
|
#endif
|
||||||
|
#ifndef FF_API_EMU_EDGE
|
||||||
|
#define FF_API_EMU_EDGE (LIBAVCODEC_VERSION_MAJOR < 58)
|
||||||
|
#endif
|
||||||
|
#ifndef FF_API_ARCH_SH4
|
||||||
|
#define FF_API_ARCH_SH4 (LIBAVCODEC_VERSION_MAJOR < 58)
|
||||||
|
#endif
|
||||||
|
#ifndef FF_API_ARCH_SPARC
|
||||||
|
#define FF_API_ARCH_SPARC (LIBAVCODEC_VERSION_MAJOR < 58)
|
||||||
|
#endif
|
||||||
|
#ifndef FF_API_UNUSED_MEMBERS
|
||||||
|
#define FF_API_UNUSED_MEMBERS (LIBAVCODEC_VERSION_MAJOR < 58)
|
||||||
|
#endif
|
||||||
|
#ifndef FF_API_IDCT_XVIDMMX
|
||||||
|
#define FF_API_IDCT_XVIDMMX (LIBAVCODEC_VERSION_MAJOR < 58)
|
||||||
|
#endif
|
||||||
|
#ifndef FF_API_INPUT_PRESERVED
|
||||||
|
#define FF_API_INPUT_PRESERVED (LIBAVCODEC_VERSION_MAJOR < 58)
|
||||||
|
#endif
|
||||||
|
#ifndef FF_API_NORMALIZE_AQP
|
||||||
|
#define FF_API_NORMALIZE_AQP (LIBAVCODEC_VERSION_MAJOR < 58)
|
||||||
|
#endif
|
||||||
|
#ifndef FF_API_GMC
|
||||||
|
#define FF_API_GMC (LIBAVCODEC_VERSION_MAJOR < 58)
|
||||||
|
#endif
|
||||||
|
#ifndef FF_API_MV0
|
||||||
|
#define FF_API_MV0 (LIBAVCODEC_VERSION_MAJOR < 58)
|
||||||
|
#endif
|
||||||
|
#ifndef FF_API_CODEC_NAME
|
||||||
|
#define FF_API_CODEC_NAME (LIBAVCODEC_VERSION_MAJOR < 58)
|
||||||
|
#endif
|
||||||
|
#ifndef FF_API_AFD
|
||||||
|
#define FF_API_AFD (LIBAVCODEC_VERSION_MAJOR < 58)
|
||||||
|
#endif
|
||||||
|
#ifndef FF_API_VISMV
|
||||||
|
/* XXX: don't forget to drop the -vismv documentation */
|
||||||
|
#define FF_API_VISMV (LIBAVCODEC_VERSION_MAJOR < 58)
|
||||||
|
#endif
|
||||||
|
#ifndef FF_API_AUDIOENC_DELAY
|
||||||
|
#define FF_API_AUDIOENC_DELAY (LIBAVCODEC_VERSION_MAJOR < 58)
|
||||||
|
#endif
|
||||||
|
#ifndef FF_API_VAAPI_CONTEXT
|
||||||
|
#define FF_API_VAAPI_CONTEXT (LIBAVCODEC_VERSION_MAJOR < 58)
|
||||||
|
#endif
|
||||||
|
#ifndef FF_API_AVCTX_TIMEBASE
|
||||||
|
#define FF_API_AVCTX_TIMEBASE (LIBAVCODEC_VERSION_MAJOR < 59)
|
||||||
|
#endif
|
||||||
|
#ifndef FF_API_MPV_OPT
|
||||||
|
#define FF_API_MPV_OPT (LIBAVCODEC_VERSION_MAJOR < 59)
|
||||||
|
#endif
|
||||||
|
#ifndef FF_API_STREAM_CODEC_TAG
|
||||||
|
#define FF_API_STREAM_CODEC_TAG (LIBAVCODEC_VERSION_MAJOR < 59)
|
||||||
|
#endif
|
||||||
|
#ifndef FF_API_QUANT_BIAS
|
||||||
|
#define FF_API_QUANT_BIAS (LIBAVCODEC_VERSION_MAJOR < 59)
|
||||||
|
#endif
|
||||||
|
#ifndef FF_API_RC_STRATEGY
|
||||||
|
#define FF_API_RC_STRATEGY (LIBAVCODEC_VERSION_MAJOR < 59)
|
||||||
|
#endif
|
||||||
|
#ifndef FF_API_CODED_FRAME
|
||||||
|
#define FF_API_CODED_FRAME (LIBAVCODEC_VERSION_MAJOR < 59)
|
||||||
|
#endif
|
||||||
|
#ifndef FF_API_MOTION_EST
|
||||||
|
#define FF_API_MOTION_EST (LIBAVCODEC_VERSION_MAJOR < 59)
|
||||||
|
#endif
|
||||||
|
#ifndef FF_API_WITHOUT_PREFIX
|
||||||
|
#define FF_API_WITHOUT_PREFIX (LIBAVCODEC_VERSION_MAJOR < 59)
|
||||||
|
#endif
|
||||||
|
#ifndef FF_API_SIDEDATA_ONLY_PKT
|
||||||
|
#define FF_API_SIDEDATA_ONLY_PKT (LIBAVCODEC_VERSION_MAJOR < 59)
|
||||||
|
#endif
|
||||||
|
#ifndef FF_API_VDPAU_PROFILE
|
||||||
|
#define FF_API_VDPAU_PROFILE (LIBAVCODEC_VERSION_MAJOR < 59)
|
||||||
|
#endif
|
||||||
|
#ifndef FF_API_CONVERGENCE_DURATION
|
||||||
|
#define FF_API_CONVERGENCE_DURATION (LIBAVCODEC_VERSION_MAJOR < 59)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* AVCODEC_VERSION_H */
|
@ -0,0 +1,126 @@
|
|||||||
|
/*
|
||||||
|
* Videotoolbox hardware acceleration
|
||||||
|
*
|
||||||
|
* copyright (c) 2012 Sebastien Zwickert
|
||||||
|
*
|
||||||
|
* This file is part of FFmpeg.
|
||||||
|
*
|
||||||
|
* FFmpeg is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2.1 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* FFmpeg is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with FFmpeg; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef AVCODEC_VIDEOTOOLBOX_H
|
||||||
|
#define AVCODEC_VIDEOTOOLBOX_H
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @file
|
||||||
|
* @ingroup lavc_codec_hwaccel_videotoolbox
|
||||||
|
* Public libavcodec Videotoolbox header.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#define Picture QuickdrawPicture
|
||||||
|
#include <VideoToolbox/VideoToolbox.h>
|
||||||
|
#undef Picture
|
||||||
|
|
||||||
|
#include "libavcodec/avcodec.h"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This struct holds all the information that needs to be passed
|
||||||
|
* between the caller and libavcodec for initializing Videotoolbox decoding.
|
||||||
|
* Its size is not a part of the public ABI, it must be allocated with
|
||||||
|
* av_videotoolbox_alloc_context() and freed with av_free().
|
||||||
|
*/
|
||||||
|
typedef struct AVVideotoolboxContext {
|
||||||
|
/**
|
||||||
|
* Videotoolbox decompression session object.
|
||||||
|
* Created and freed the caller.
|
||||||
|
*/
|
||||||
|
VTDecompressionSessionRef session;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The output callback that must be passed to the session.
|
||||||
|
* Set by av_videottoolbox_default_init()
|
||||||
|
*/
|
||||||
|
VTDecompressionOutputCallback output_callback;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* CVPixelBuffer Format Type that Videotoolbox will use for decoded frames.
|
||||||
|
* set by the caller.
|
||||||
|
*/
|
||||||
|
OSType cv_pix_fmt_type;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* CoreMedia Format Description that Videotoolbox will use to create the decompression session.
|
||||||
|
* Set by the caller.
|
||||||
|
*/
|
||||||
|
CMVideoFormatDescriptionRef cm_fmt_desc;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* CoreMedia codec type that Videotoolbox will use to create the decompression session.
|
||||||
|
* Set by the caller.
|
||||||
|
*/
|
||||||
|
int cm_codec_type;
|
||||||
|
} AVVideotoolboxContext;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Allocate and initialize a Videotoolbox context.
|
||||||
|
*
|
||||||
|
* This function should be called from the get_format() callback when the caller
|
||||||
|
* selects the AV_PIX_FMT_VIDETOOLBOX format. The caller must then create
|
||||||
|
* the decoder object (using the output callback provided by libavcodec) that
|
||||||
|
* will be used for Videotoolbox-accelerated decoding.
|
||||||
|
*
|
||||||
|
* When decoding with Videotoolbox is finished, the caller must destroy the decoder
|
||||||
|
* object and free the Videotoolbox context using av_free().
|
||||||
|
*
|
||||||
|
* @return the newly allocated context or NULL on failure
|
||||||
|
*/
|
||||||
|
AVVideotoolboxContext *av_videotoolbox_alloc_context(void);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This is a convenience function that creates and sets up the Videotoolbox context using
|
||||||
|
* an internal implementation.
|
||||||
|
*
|
||||||
|
* @param avctx the corresponding codec context
|
||||||
|
*
|
||||||
|
* @return >= 0 on success, a negative AVERROR code on failure
|
||||||
|
*/
|
||||||
|
int av_videotoolbox_default_init(AVCodecContext *avctx);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This is a convenience function that creates and sets up the Videotoolbox context using
|
||||||
|
* an internal implementation.
|
||||||
|
*
|
||||||
|
* @param avctx the corresponding codec context
|
||||||
|
* @param vtctx the Videotoolbox context to use
|
||||||
|
*
|
||||||
|
* @return >= 0 on success, a negative AVERROR code on failure
|
||||||
|
*/
|
||||||
|
int av_videotoolbox_default_init2(AVCodecContext *avctx, AVVideotoolboxContext *vtctx);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This function must be called to free the Videotoolbox context initialized with
|
||||||
|
* av_videotoolbox_default_init().
|
||||||
|
*
|
||||||
|
* @param avctx the corresponding codec context
|
||||||
|
*/
|
||||||
|
void av_videotoolbox_default_free(AVCodecContext *avctx);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @}
|
||||||
|
*/
|
||||||
|
|
||||||
|
#endif /* AVCODEC_VIDEOTOOLBOX_H */
|
@ -0,0 +1,78 @@
|
|||||||
|
/*
|
||||||
|
*
|
||||||
|
* This file is part of FFmpeg.
|
||||||
|
*
|
||||||
|
* FFmpeg is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2.1 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* FFmpeg is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with FFmpeg; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @file
|
||||||
|
* A public API for Vorbis parsing
|
||||||
|
*
|
||||||
|
* Determines the duration for each packet.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef AVCODEC_VORBIS_PARSE_H
|
||||||
|
#define AVCODEC_VORBIS_PARSE_H
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
typedef struct AVVorbisParseContext AVVorbisParseContext;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Allocate and initialize the Vorbis parser using headers in the extradata.
|
||||||
|
*
|
||||||
|
* @param avctx codec context
|
||||||
|
* @param s Vorbis parser context
|
||||||
|
*/
|
||||||
|
AVVorbisParseContext *av_vorbis_parse_init(const uint8_t *extradata,
|
||||||
|
int extradata_size);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Free the parser and everything associated with it.
|
||||||
|
*/
|
||||||
|
void av_vorbis_parse_free(AVVorbisParseContext **s);
|
||||||
|
|
||||||
|
#define VORBIS_FLAG_HEADER 0x00000001
|
||||||
|
#define VORBIS_FLAG_COMMENT 0x00000002
|
||||||
|
#define VORBIS_FLAG_SETUP 0x00000004
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the duration for a Vorbis packet.
|
||||||
|
*
|
||||||
|
* If @p flags is @c NULL,
|
||||||
|
* special frames are considered invalid.
|
||||||
|
*
|
||||||
|
* @param s Vorbis parser context
|
||||||
|
* @param buf buffer containing a Vorbis frame
|
||||||
|
* @param buf_size size of the buffer
|
||||||
|
* @param flags flags for special frames
|
||||||
|
*/
|
||||||
|
int av_vorbis_parse_frame_flags(AVVorbisParseContext *s, const uint8_t *buf,
|
||||||
|
int buf_size, int *flags);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the duration for a Vorbis packet.
|
||||||
|
*
|
||||||
|
* @param s Vorbis parser context
|
||||||
|
* @param buf buffer containing a Vorbis frame
|
||||||
|
* @param buf_size size of the buffer
|
||||||
|
*/
|
||||||
|
int av_vorbis_parse_frame(AVVorbisParseContext *s, const uint8_t *buf,
|
||||||
|
int buf_size);
|
||||||
|
|
||||||
|
void av_vorbis_parse_reset(AVVorbisParseContext *s);
|
||||||
|
|
||||||
|
#endif /* AVCODEC_VORBIS_PARSE_H */
|
@ -0,0 +1,170 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2003 Ivan Kalvachev
|
||||||
|
*
|
||||||
|
* This file is part of FFmpeg.
|
||||||
|
*
|
||||||
|
* FFmpeg is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2.1 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* FFmpeg is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with FFmpeg; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef AVCODEC_XVMC_H
|
||||||
|
#define AVCODEC_XVMC_H
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @file
|
||||||
|
* @ingroup lavc_codec_hwaccel_xvmc
|
||||||
|
* Public libavcodec XvMC header.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <X11/extensions/XvMC.h>
|
||||||
|
|
||||||
|
#include "libavutil/attributes.h"
|
||||||
|
#include "version.h"
|
||||||
|
#include "avcodec.h"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @defgroup lavc_codec_hwaccel_xvmc XvMC
|
||||||
|
* @ingroup lavc_codec_hwaccel
|
||||||
|
*
|
||||||
|
* @{
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define AV_XVMC_ID 0x1DC711C0 /**< special value to ensure that regular pixel routines haven't corrupted the struct
|
||||||
|
the number is 1337 speak for the letters IDCT MCo (motion compensation) */
|
||||||
|
|
||||||
|
attribute_deprecated struct xvmc_pix_fmt {
|
||||||
|
/** The field contains the special constant value AV_XVMC_ID.
|
||||||
|
It is used as a test that the application correctly uses the API,
|
||||||
|
and that there is no corruption caused by pixel routines.
|
||||||
|
- application - set during initialization
|
||||||
|
- libavcodec - unchanged
|
||||||
|
*/
|
||||||
|
int xvmc_id;
|
||||||
|
|
||||||
|
/** Pointer to the block array allocated by XvMCCreateBlocks().
|
||||||
|
The array has to be freed by XvMCDestroyBlocks().
|
||||||
|
Each group of 64 values represents one data block of differential
|
||||||
|
pixel information (in MoCo mode) or coefficients for IDCT.
|
||||||
|
- application - set the pointer during initialization
|
||||||
|
- libavcodec - fills coefficients/pixel data into the array
|
||||||
|
*/
|
||||||
|
short* data_blocks;
|
||||||
|
|
||||||
|
/** Pointer to the macroblock description array allocated by
|
||||||
|
XvMCCreateMacroBlocks() and freed by XvMCDestroyMacroBlocks().
|
||||||
|
- application - set the pointer during initialization
|
||||||
|
- libavcodec - fills description data into the array
|
||||||
|
*/
|
||||||
|
XvMCMacroBlock* mv_blocks;
|
||||||
|
|
||||||
|
/** Number of macroblock descriptions that can be stored in the mv_blocks
|
||||||
|
array.
|
||||||
|
- application - set during initialization
|
||||||
|
- libavcodec - unchanged
|
||||||
|
*/
|
||||||
|
int allocated_mv_blocks;
|
||||||
|
|
||||||
|
/** Number of blocks that can be stored at once in the data_blocks array.
|
||||||
|
- application - set during initialization
|
||||||
|
- libavcodec - unchanged
|
||||||
|
*/
|
||||||
|
int allocated_data_blocks;
|
||||||
|
|
||||||
|
/** Indicate that the hardware would interpret data_blocks as IDCT
|
||||||
|
coefficients and perform IDCT on them.
|
||||||
|
- application - set during initialization
|
||||||
|
- libavcodec - unchanged
|
||||||
|
*/
|
||||||
|
int idct;
|
||||||
|
|
||||||
|
/** In MoCo mode it indicates that intra macroblocks are assumed to be in
|
||||||
|
unsigned format; same as the XVMC_INTRA_UNSIGNED flag.
|
||||||
|
- application - set during initialization
|
||||||
|
- libavcodec - unchanged
|
||||||
|
*/
|
||||||
|
int unsigned_intra;
|
||||||
|
|
||||||
|
/** Pointer to the surface allocated by XvMCCreateSurface().
|
||||||
|
It has to be freed by XvMCDestroySurface() on application exit.
|
||||||
|
It identifies the frame and its state on the video hardware.
|
||||||
|
- application - set during initialization
|
||||||
|
- libavcodec - unchanged
|
||||||
|
*/
|
||||||
|
XvMCSurface* p_surface;
|
||||||
|
|
||||||
|
/** Set by the decoder before calling ff_draw_horiz_band(),
|
||||||
|
needed by the XvMCRenderSurface function. */
|
||||||
|
//@{
|
||||||
|
/** Pointer to the surface used as past reference
|
||||||
|
- application - unchanged
|
||||||
|
- libavcodec - set
|
||||||
|
*/
|
||||||
|
XvMCSurface* p_past_surface;
|
||||||
|
|
||||||
|
/** Pointer to the surface used as future reference
|
||||||
|
- application - unchanged
|
||||||
|
- libavcodec - set
|
||||||
|
*/
|
||||||
|
XvMCSurface* p_future_surface;
|
||||||
|
|
||||||
|
/** top/bottom field or frame
|
||||||
|
- application - unchanged
|
||||||
|
- libavcodec - set
|
||||||
|
*/
|
||||||
|
unsigned int picture_structure;
|
||||||
|
|
||||||
|
/** XVMC_SECOND_FIELD - 1st or 2nd field in the sequence
|
||||||
|
- application - unchanged
|
||||||
|
- libavcodec - set
|
||||||
|
*/
|
||||||
|
unsigned int flags;
|
||||||
|
//}@
|
||||||
|
|
||||||
|
/** Number of macroblock descriptions in the mv_blocks array
|
||||||
|
that have already been passed to the hardware.
|
||||||
|
- application - zeroes it on get_buffer().
|
||||||
|
A successful ff_draw_horiz_band() may increment it
|
||||||
|
with filled_mb_block_num or zero both.
|
||||||
|
- libavcodec - unchanged
|
||||||
|
*/
|
||||||
|
int start_mv_blocks_num;
|
||||||
|
|
||||||
|
/** Number of new macroblock descriptions in the mv_blocks array (after
|
||||||
|
start_mv_blocks_num) that are filled by libavcodec and have to be
|
||||||
|
passed to the hardware.
|
||||||
|
- application - zeroes it on get_buffer() or after successful
|
||||||
|
ff_draw_horiz_band().
|
||||||
|
- libavcodec - increment with one of each stored MB
|
||||||
|
*/
|
||||||
|
int filled_mv_blocks_num;
|
||||||
|
|
||||||
|
/** Number of the next free data block; one data block consists of
|
||||||
|
64 short values in the data_blocks array.
|
||||||
|
All blocks before this one have already been claimed by placing their
|
||||||
|
position into the corresponding block description structure field,
|
||||||
|
that are part of the mv_blocks array.
|
||||||
|
- application - zeroes it on get_buffer().
|
||||||
|
A successful ff_draw_horiz_band() may zero it together
|
||||||
|
with start_mb_blocks_num.
|
||||||
|
- libavcodec - each decoded macroblock increases it by the number
|
||||||
|
of coded blocks it contains.
|
||||||
|
*/
|
||||||
|
int next_free_data_block_num;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @}
|
||||||
|
*/
|
||||||
|
|
||||||
|
#endif /* AVCODEC_XVMC_H */
|
@ -0,0 +1,509 @@
|
|||||||
|
/*
|
||||||
|
* This file is part of FFmpeg.
|
||||||
|
*
|
||||||
|
* FFmpeg is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2.1 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* FFmpeg is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with FFmpeg; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef AVDEVICE_AVDEVICE_H
|
||||||
|
#define AVDEVICE_AVDEVICE_H
|
||||||
|
|
||||||
|
#include "version.h"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @file
|
||||||
|
* @ingroup lavd
|
||||||
|
* Main libavdevice API header
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @defgroup lavd Special devices muxing/demuxing library
|
||||||
|
* @{
|
||||||
|
* Libavdevice is a complementary library to @ref libavf "libavformat". It
|
||||||
|
* provides various "special" platform-specific muxers and demuxers, e.g. for
|
||||||
|
* grabbing devices, audio capture and playback etc. As a consequence, the
|
||||||
|
* (de)muxers in libavdevice are of the AVFMT_NOFILE type (they use their own
|
||||||
|
* I/O functions). The filename passed to avformat_open_input() often does not
|
||||||
|
* refer to an actually existing file, but has some special device-specific
|
||||||
|
* meaning - e.g. for x11grab it is the display name.
|
||||||
|
*
|
||||||
|
* To use libavdevice, simply call avdevice_register_all() to register all
|
||||||
|
* compiled muxers and demuxers. They all use standard libavformat API.
|
||||||
|
* @}
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "libavutil/log.h"
|
||||||
|
#include "libavutil/opt.h"
|
||||||
|
#include "libavutil/dict.h"
|
||||||
|
#include "libavformat/avformat.h"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the LIBAVDEVICE_VERSION_INT constant.
|
||||||
|
*/
|
||||||
|
unsigned avdevice_version(void);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the libavdevice build-time configuration.
|
||||||
|
*/
|
||||||
|
const char *avdevice_configuration(void);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the libavdevice license.
|
||||||
|
*/
|
||||||
|
const char *avdevice_license(void);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initialize libavdevice and register all the input and output devices.
|
||||||
|
* @warning This function is not thread safe.
|
||||||
|
*/
|
||||||
|
void avdevice_register_all(void);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Audio input devices iterator.
|
||||||
|
*
|
||||||
|
* If d is NULL, returns the first registered input audio/video device,
|
||||||
|
* if d is non-NULL, returns the next registered input audio/video device after d
|
||||||
|
* or NULL if d is the last one.
|
||||||
|
*/
|
||||||
|
AVInputFormat *av_input_audio_device_next(AVInputFormat *d);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Video input devices iterator.
|
||||||
|
*
|
||||||
|
* If d is NULL, returns the first registered input audio/video device,
|
||||||
|
* if d is non-NULL, returns the next registered input audio/video device after d
|
||||||
|
* or NULL if d is the last one.
|
||||||
|
*/
|
||||||
|
AVInputFormat *av_input_video_device_next(AVInputFormat *d);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Audio output devices iterator.
|
||||||
|
*
|
||||||
|
* If d is NULL, returns the first registered output audio/video device,
|
||||||
|
* if d is non-NULL, returns the next registered output audio/video device after d
|
||||||
|
* or NULL if d is the last one.
|
||||||
|
*/
|
||||||
|
AVOutputFormat *av_output_audio_device_next(AVOutputFormat *d);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Video output devices iterator.
|
||||||
|
*
|
||||||
|
* If d is NULL, returns the first registered output audio/video device,
|
||||||
|
* if d is non-NULL, returns the next registered output audio/video device after d
|
||||||
|
* or NULL if d is the last one.
|
||||||
|
*/
|
||||||
|
AVOutputFormat *av_output_video_device_next(AVOutputFormat *d);
|
||||||
|
|
||||||
|
typedef struct AVDeviceRect {
|
||||||
|
int x; /**< x coordinate of top left corner */
|
||||||
|
int y; /**< y coordinate of top left corner */
|
||||||
|
int width; /**< width */
|
||||||
|
int height; /**< height */
|
||||||
|
} AVDeviceRect;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Message types used by avdevice_app_to_dev_control_message().
|
||||||
|
*/
|
||||||
|
enum AVAppToDevMessageType {
|
||||||
|
/**
|
||||||
|
* Dummy message.
|
||||||
|
*/
|
||||||
|
AV_APP_TO_DEV_NONE = MKBETAG('N','O','N','E'),
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Window size change message.
|
||||||
|
*
|
||||||
|
* Message is sent to the device every time the application changes the size
|
||||||
|
* of the window device renders to.
|
||||||
|
* Message should also be sent right after window is created.
|
||||||
|
*
|
||||||
|
* data: AVDeviceRect: new window size.
|
||||||
|
*/
|
||||||
|
AV_APP_TO_DEV_WINDOW_SIZE = MKBETAG('G','E','O','M'),
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Repaint request message.
|
||||||
|
*
|
||||||
|
* Message is sent to the device when window has to be repainted.
|
||||||
|
*
|
||||||
|
* data: AVDeviceRect: area required to be repainted.
|
||||||
|
* NULL: whole area is required to be repainted.
|
||||||
|
*/
|
||||||
|
AV_APP_TO_DEV_WINDOW_REPAINT = MKBETAG('R','E','P','A'),
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Request pause/play.
|
||||||
|
*
|
||||||
|
* Application requests pause/unpause playback.
|
||||||
|
* Mostly usable with devices that have internal buffer.
|
||||||
|
* By default devices are not paused.
|
||||||
|
*
|
||||||
|
* data: NULL
|
||||||
|
*/
|
||||||
|
AV_APP_TO_DEV_PAUSE = MKBETAG('P', 'A', 'U', ' '),
|
||||||
|
AV_APP_TO_DEV_PLAY = MKBETAG('P', 'L', 'A', 'Y'),
|
||||||
|
AV_APP_TO_DEV_TOGGLE_PAUSE = MKBETAG('P', 'A', 'U', 'T'),
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Volume control message.
|
||||||
|
*
|
||||||
|
* Set volume level. It may be device-dependent if volume
|
||||||
|
* is changed per stream or system wide. Per stream volume
|
||||||
|
* change is expected when possible.
|
||||||
|
*
|
||||||
|
* data: double: new volume with range of 0.0 - 1.0.
|
||||||
|
*/
|
||||||
|
AV_APP_TO_DEV_SET_VOLUME = MKBETAG('S', 'V', 'O', 'L'),
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Mute control messages.
|
||||||
|
*
|
||||||
|
* Change mute state. It may be device-dependent if mute status
|
||||||
|
* is changed per stream or system wide. Per stream mute status
|
||||||
|
* change is expected when possible.
|
||||||
|
*
|
||||||
|
* data: NULL.
|
||||||
|
*/
|
||||||
|
AV_APP_TO_DEV_MUTE = MKBETAG(' ', 'M', 'U', 'T'),
|
||||||
|
AV_APP_TO_DEV_UNMUTE = MKBETAG('U', 'M', 'U', 'T'),
|
||||||
|
AV_APP_TO_DEV_TOGGLE_MUTE = MKBETAG('T', 'M', 'U', 'T'),
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get volume/mute messages.
|
||||||
|
*
|
||||||
|
* Force the device to send AV_DEV_TO_APP_VOLUME_LEVEL_CHANGED or
|
||||||
|
* AV_DEV_TO_APP_MUTE_STATE_CHANGED command respectively.
|
||||||
|
*
|
||||||
|
* data: NULL.
|
||||||
|
*/
|
||||||
|
AV_APP_TO_DEV_GET_VOLUME = MKBETAG('G', 'V', 'O', 'L'),
|
||||||
|
AV_APP_TO_DEV_GET_MUTE = MKBETAG('G', 'M', 'U', 'T'),
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Message types used by avdevice_dev_to_app_control_message().
|
||||||
|
*/
|
||||||
|
enum AVDevToAppMessageType {
|
||||||
|
/**
|
||||||
|
* Dummy message.
|
||||||
|
*/
|
||||||
|
AV_DEV_TO_APP_NONE = MKBETAG('N','O','N','E'),
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create window buffer message.
|
||||||
|
*
|
||||||
|
* Device requests to create a window buffer. Exact meaning is device-
|
||||||
|
* and application-dependent. Message is sent before rendering first
|
||||||
|
* frame and all one-shot initializations should be done here.
|
||||||
|
* Application is allowed to ignore preferred window buffer size.
|
||||||
|
*
|
||||||
|
* @note: Application is obligated to inform about window buffer size
|
||||||
|
* with AV_APP_TO_DEV_WINDOW_SIZE message.
|
||||||
|
*
|
||||||
|
* data: AVDeviceRect: preferred size of the window buffer.
|
||||||
|
* NULL: no preferred size of the window buffer.
|
||||||
|
*/
|
||||||
|
AV_DEV_TO_APP_CREATE_WINDOW_BUFFER = MKBETAG('B','C','R','E'),
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Prepare window buffer message.
|
||||||
|
*
|
||||||
|
* Device requests to prepare a window buffer for rendering.
|
||||||
|
* Exact meaning is device- and application-dependent.
|
||||||
|
* Message is sent before rendering of each frame.
|
||||||
|
*
|
||||||
|
* data: NULL.
|
||||||
|
*/
|
||||||
|
AV_DEV_TO_APP_PREPARE_WINDOW_BUFFER = MKBETAG('B','P','R','E'),
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Display window buffer message.
|
||||||
|
*
|
||||||
|
* Device requests to display a window buffer.
|
||||||
|
* Message is sent when new frame is ready to be displayed.
|
||||||
|
* Usually buffers need to be swapped in handler of this message.
|
||||||
|
*
|
||||||
|
* data: NULL.
|
||||||
|
*/
|
||||||
|
AV_DEV_TO_APP_DISPLAY_WINDOW_BUFFER = MKBETAG('B','D','I','S'),
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Destroy window buffer message.
|
||||||
|
*
|
||||||
|
* Device requests to destroy a window buffer.
|
||||||
|
* Message is sent when device is about to be destroyed and window
|
||||||
|
* buffer is not required anymore.
|
||||||
|
*
|
||||||
|
* data: NULL.
|
||||||
|
*/
|
||||||
|
AV_DEV_TO_APP_DESTROY_WINDOW_BUFFER = MKBETAG('B','D','E','S'),
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Buffer fullness status messages.
|
||||||
|
*
|
||||||
|
* Device signals buffer overflow/underflow.
|
||||||
|
*
|
||||||
|
* data: NULL.
|
||||||
|
*/
|
||||||
|
AV_DEV_TO_APP_BUFFER_OVERFLOW = MKBETAG('B','O','F','L'),
|
||||||
|
AV_DEV_TO_APP_BUFFER_UNDERFLOW = MKBETAG('B','U','F','L'),
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Buffer readable/writable.
|
||||||
|
*
|
||||||
|
* Device informs that buffer is readable/writable.
|
||||||
|
* When possible, device informs how many bytes can be read/write.
|
||||||
|
*
|
||||||
|
* @warning Device may not inform when number of bytes than can be read/write changes.
|
||||||
|
*
|
||||||
|
* data: int64_t: amount of bytes available to read/write.
|
||||||
|
* NULL: amount of bytes available to read/write is not known.
|
||||||
|
*/
|
||||||
|
AV_DEV_TO_APP_BUFFER_READABLE = MKBETAG('B','R','D',' '),
|
||||||
|
AV_DEV_TO_APP_BUFFER_WRITABLE = MKBETAG('B','W','R',' '),
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Mute state change message.
|
||||||
|
*
|
||||||
|
* Device informs that mute state has changed.
|
||||||
|
*
|
||||||
|
* data: int: 0 for not muted state, non-zero for muted state.
|
||||||
|
*/
|
||||||
|
AV_DEV_TO_APP_MUTE_STATE_CHANGED = MKBETAG('C','M','U','T'),
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Volume level change message.
|
||||||
|
*
|
||||||
|
* Device informs that volume level has changed.
|
||||||
|
*
|
||||||
|
* data: double: new volume with range of 0.0 - 1.0.
|
||||||
|
*/
|
||||||
|
AV_DEV_TO_APP_VOLUME_LEVEL_CHANGED = MKBETAG('C','V','O','L'),
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Send control message from application to device.
|
||||||
|
*
|
||||||
|
* @param s device context.
|
||||||
|
* @param type message type.
|
||||||
|
* @param data message data. Exact type depends on message type.
|
||||||
|
* @param data_size size of message data.
|
||||||
|
* @return >= 0 on success, negative on error.
|
||||||
|
* AVERROR(ENOSYS) when device doesn't implement handler of the message.
|
||||||
|
*/
|
||||||
|
int avdevice_app_to_dev_control_message(struct AVFormatContext *s,
|
||||||
|
enum AVAppToDevMessageType type,
|
||||||
|
void *data, size_t data_size);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Send control message from device to application.
|
||||||
|
*
|
||||||
|
* @param s device context.
|
||||||
|
* @param type message type.
|
||||||
|
* @param data message data. Can be NULL.
|
||||||
|
* @param data_size size of message data.
|
||||||
|
* @return >= 0 on success, negative on error.
|
||||||
|
* AVERROR(ENOSYS) when application doesn't implement handler of the message.
|
||||||
|
*/
|
||||||
|
int avdevice_dev_to_app_control_message(struct AVFormatContext *s,
|
||||||
|
enum AVDevToAppMessageType type,
|
||||||
|
void *data, size_t data_size);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Following API allows user to probe device capabilities (supported codecs,
|
||||||
|
* pixel formats, sample formats, resolutions, channel counts, etc).
|
||||||
|
* It is build on top op AVOption API.
|
||||||
|
* Queried capabilities make it possible to set up converters of video or audio
|
||||||
|
* parameters that fit to the device.
|
||||||
|
*
|
||||||
|
* List of capabilities that can be queried:
|
||||||
|
* - Capabilities valid for both audio and video devices:
|
||||||
|
* - codec: supported audio/video codecs.
|
||||||
|
* type: AV_OPT_TYPE_INT (AVCodecID value)
|
||||||
|
* - Capabilities valid for audio devices:
|
||||||
|
* - sample_format: supported sample formats.
|
||||||
|
* type: AV_OPT_TYPE_INT (AVSampleFormat value)
|
||||||
|
* - sample_rate: supported sample rates.
|
||||||
|
* type: AV_OPT_TYPE_INT
|
||||||
|
* - channels: supported number of channels.
|
||||||
|
* type: AV_OPT_TYPE_INT
|
||||||
|
* - channel_layout: supported channel layouts.
|
||||||
|
* type: AV_OPT_TYPE_INT64
|
||||||
|
* - Capabilities valid for video devices:
|
||||||
|
* - pixel_format: supported pixel formats.
|
||||||
|
* type: AV_OPT_TYPE_INT (AVPixelFormat value)
|
||||||
|
* - window_size: supported window sizes (describes size of the window size presented to the user).
|
||||||
|
* type: AV_OPT_TYPE_IMAGE_SIZE
|
||||||
|
* - frame_size: supported frame sizes (describes size of provided video frames).
|
||||||
|
* type: AV_OPT_TYPE_IMAGE_SIZE
|
||||||
|
* - fps: supported fps values
|
||||||
|
* type: AV_OPT_TYPE_RATIONAL
|
||||||
|
*
|
||||||
|
* Value of the capability may be set by user using av_opt_set() function
|
||||||
|
* and AVDeviceCapabilitiesQuery object. Following queries will
|
||||||
|
* limit results to the values matching already set capabilities.
|
||||||
|
* For example, setting a codec may impact number of formats or fps values
|
||||||
|
* returned during next query. Setting invalid value may limit results to zero.
|
||||||
|
*
|
||||||
|
* Example of the usage basing on opengl output device:
|
||||||
|
*
|
||||||
|
* @code
|
||||||
|
* AVFormatContext *oc = NULL;
|
||||||
|
* AVDeviceCapabilitiesQuery *caps = NULL;
|
||||||
|
* AVOptionRanges *ranges;
|
||||||
|
* int ret;
|
||||||
|
*
|
||||||
|
* if ((ret = avformat_alloc_output_context2(&oc, NULL, "opengl", NULL)) < 0)
|
||||||
|
* goto fail;
|
||||||
|
* if (avdevice_capabilities_create(&caps, oc, NULL) < 0)
|
||||||
|
* goto fail;
|
||||||
|
*
|
||||||
|
* //query codecs
|
||||||
|
* if (av_opt_query_ranges(&ranges, caps, "codec", AV_OPT_MULTI_COMPONENT_RANGE)) < 0)
|
||||||
|
* goto fail;
|
||||||
|
* //pick codec here and set it
|
||||||
|
* av_opt_set(caps, "codec", AV_CODEC_ID_RAWVIDEO, 0);
|
||||||
|
*
|
||||||
|
* //query format
|
||||||
|
* if (av_opt_query_ranges(&ranges, caps, "pixel_format", AV_OPT_MULTI_COMPONENT_RANGE)) < 0)
|
||||||
|
* goto fail;
|
||||||
|
* //pick format here and set it
|
||||||
|
* av_opt_set(caps, "pixel_format", AV_PIX_FMT_YUV420P, 0);
|
||||||
|
*
|
||||||
|
* //query and set more capabilities
|
||||||
|
*
|
||||||
|
* fail:
|
||||||
|
* //clean up code
|
||||||
|
* avdevice_capabilities_free(&query, oc);
|
||||||
|
* avformat_free_context(oc);
|
||||||
|
* @endcode
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Structure describes device capabilities.
|
||||||
|
*
|
||||||
|
* It is used by devices in conjunction with av_device_capabilities AVOption table
|
||||||
|
* to implement capabilities probing API based on AVOption API. Should not be used directly.
|
||||||
|
*/
|
||||||
|
typedef struct AVDeviceCapabilitiesQuery {
|
||||||
|
const AVClass *av_class;
|
||||||
|
AVFormatContext *device_context;
|
||||||
|
enum AVCodecID codec;
|
||||||
|
enum AVSampleFormat sample_format;
|
||||||
|
enum AVPixelFormat pixel_format;
|
||||||
|
int sample_rate;
|
||||||
|
int channels;
|
||||||
|
int64_t channel_layout;
|
||||||
|
int window_width;
|
||||||
|
int window_height;
|
||||||
|
int frame_width;
|
||||||
|
int frame_height;
|
||||||
|
AVRational fps;
|
||||||
|
} AVDeviceCapabilitiesQuery;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* AVOption table used by devices to implement device capabilities API. Should not be used by a user.
|
||||||
|
*/
|
||||||
|
extern const AVOption av_device_capabilities[];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initialize capabilities probing API based on AVOption API.
|
||||||
|
*
|
||||||
|
* avdevice_capabilities_free() must be called when query capabilities API is
|
||||||
|
* not used anymore.
|
||||||
|
*
|
||||||
|
* @param[out] caps Device capabilities data. Pointer to a NULL pointer must be passed.
|
||||||
|
* @param s Context of the device.
|
||||||
|
* @param device_options An AVDictionary filled with device-private options.
|
||||||
|
* On return this parameter will be destroyed and replaced with a dict
|
||||||
|
* containing options that were not found. May be NULL.
|
||||||
|
* The same options must be passed later to avformat_write_header() for output
|
||||||
|
* devices or avformat_open_input() for input devices, or at any other place
|
||||||
|
* that affects device-private options.
|
||||||
|
*
|
||||||
|
* @return >= 0 on success, negative otherwise.
|
||||||
|
*/
|
||||||
|
int avdevice_capabilities_create(AVDeviceCapabilitiesQuery **caps, AVFormatContext *s,
|
||||||
|
AVDictionary **device_options);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Free resources created by avdevice_capabilities_create()
|
||||||
|
*
|
||||||
|
* @param caps Device capabilities data to be freed.
|
||||||
|
* @param s Context of the device.
|
||||||
|
*/
|
||||||
|
void avdevice_capabilities_free(AVDeviceCapabilitiesQuery **caps, AVFormatContext *s);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Structure describes basic parameters of the device.
|
||||||
|
*/
|
||||||
|
typedef struct AVDeviceInfo {
|
||||||
|
char *device_name; /**< device name, format depends on device */
|
||||||
|
char *device_description; /**< human friendly name */
|
||||||
|
} AVDeviceInfo;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* List of devices.
|
||||||
|
*/
|
||||||
|
typedef struct AVDeviceInfoList {
|
||||||
|
AVDeviceInfo **devices; /**< list of autodetected devices */
|
||||||
|
int nb_devices; /**< number of autodetected devices */
|
||||||
|
int default_device; /**< index of default device or -1 if no default */
|
||||||
|
} AVDeviceInfoList;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* List devices.
|
||||||
|
*
|
||||||
|
* Returns available device names and their parameters.
|
||||||
|
*
|
||||||
|
* @note: Some devices may accept system-dependent device names that cannot be
|
||||||
|
* autodetected. The list returned by this function cannot be assumed to
|
||||||
|
* be always completed.
|
||||||
|
*
|
||||||
|
* @param s device context.
|
||||||
|
* @param[out] device_list list of autodetected devices.
|
||||||
|
* @return count of autodetected devices, negative on error.
|
||||||
|
*/
|
||||||
|
int avdevice_list_devices(struct AVFormatContext *s, AVDeviceInfoList **device_list);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Convenient function to free result of avdevice_list_devices().
|
||||||
|
*
|
||||||
|
* @param devices device list to be freed.
|
||||||
|
*/
|
||||||
|
void avdevice_free_list_devices(AVDeviceInfoList **device_list);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* List devices.
|
||||||
|
*
|
||||||
|
* Returns available device names and their parameters.
|
||||||
|
* These are convinient wrappers for avdevice_list_devices().
|
||||||
|
* Device context is allocated and deallocated internally.
|
||||||
|
*
|
||||||
|
* @param device device format. May be NULL if device name is set.
|
||||||
|
* @param device_name device name. May be NULL if device format is set.
|
||||||
|
* @param device_options An AVDictionary filled with device-private options. May be NULL.
|
||||||
|
* The same options must be passed later to avformat_write_header() for output
|
||||||
|
* devices or avformat_open_input() for input devices, or at any other place
|
||||||
|
* that affects device-private options.
|
||||||
|
* @param[out] device_list list of autodetected devices
|
||||||
|
* @return count of autodetected devices, negative on error.
|
||||||
|
* @note device argument takes precedence over device_name when both are set.
|
||||||
|
*/
|
||||||
|
int avdevice_list_input_sources(struct AVInputFormat *device, const char *device_name,
|
||||||
|
AVDictionary *device_options, AVDeviceInfoList **device_list);
|
||||||
|
int avdevice_list_output_sinks(struct AVOutputFormat *device, const char *device_name,
|
||||||
|
AVDictionary *device_options, AVDeviceInfoList **device_list);
|
||||||
|
|
||||||
|
#endif /* AVDEVICE_AVDEVICE_H */
|
@ -0,0 +1,50 @@
|
|||||||
|
/*
|
||||||
|
* This file is part of FFmpeg.
|
||||||
|
*
|
||||||
|
* FFmpeg is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2.1 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* FFmpeg is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with FFmpeg; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef AVDEVICE_VERSION_H
|
||||||
|
#define AVDEVICE_VERSION_H
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @file
|
||||||
|
* @ingroup lavd
|
||||||
|
* Libavdevice version macros
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "libavutil/version.h"
|
||||||
|
|
||||||
|
#define LIBAVDEVICE_VERSION_MAJOR 57
|
||||||
|
#define LIBAVDEVICE_VERSION_MINOR 0
|
||||||
|
#define LIBAVDEVICE_VERSION_MICRO 100
|
||||||
|
|
||||||
|
#define LIBAVDEVICE_VERSION_INT AV_VERSION_INT(LIBAVDEVICE_VERSION_MAJOR, \
|
||||||
|
LIBAVDEVICE_VERSION_MINOR, \
|
||||||
|
LIBAVDEVICE_VERSION_MICRO)
|
||||||
|
#define LIBAVDEVICE_VERSION AV_VERSION(LIBAVDEVICE_VERSION_MAJOR, \
|
||||||
|
LIBAVDEVICE_VERSION_MINOR, \
|
||||||
|
LIBAVDEVICE_VERSION_MICRO)
|
||||||
|
#define LIBAVDEVICE_BUILD LIBAVDEVICE_VERSION_INT
|
||||||
|
|
||||||
|
#define LIBAVDEVICE_IDENT "Lavd" AV_STRINGIFY(LIBAVDEVICE_VERSION)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* FF_API_* defines may be placed below to indicate public API that will be
|
||||||
|
* dropped at a future version bump. The defines themselves are not part of
|
||||||
|
* the public API and may change, break or disappear at any time.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#endif /* AVDEVICE_VERSION_H */
|
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,28 @@
|
|||||||
|
/*
|
||||||
|
* Filter graphs
|
||||||
|
* copyright (c) 2007 Bobby Bingham
|
||||||
|
*
|
||||||
|
* This file is part of FFmpeg.
|
||||||
|
*
|
||||||
|
* FFmpeg is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2.1 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* FFmpeg is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with FFmpeg; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef AVFILTER_AVFILTERGRAPH_H
|
||||||
|
#define AVFILTER_AVFILTERGRAPH_H
|
||||||
|
|
||||||
|
#include "avfilter.h"
|
||||||
|
#include "libavutil/log.h"
|
||||||
|
|
||||||
|
#endif /* AVFILTER_AVFILTERGRAPH_H */
|
@ -0,0 +1,147 @@
|
|||||||
|
/*
|
||||||
|
* This file is part of FFmpeg.
|
||||||
|
*
|
||||||
|
* FFmpeg is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2.1 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* FFmpeg is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with FFmpeg; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef AVFILTER_BUFFERSINK_H
|
||||||
|
#define AVFILTER_BUFFERSINK_H
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @file
|
||||||
|
* @ingroup lavfi_buffersink
|
||||||
|
* memory buffer sink API for audio and video
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "avfilter.h"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @defgroup lavfi_buffersink Buffer sink API
|
||||||
|
* @ingroup lavfi
|
||||||
|
* @{
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get a frame with filtered data from sink and put it in frame.
|
||||||
|
*
|
||||||
|
* @param ctx pointer to a buffersink or abuffersink filter context.
|
||||||
|
* @param frame pointer to an allocated frame that will be filled with data.
|
||||||
|
* The data must be freed using av_frame_unref() / av_frame_free()
|
||||||
|
* @param flags a combination of AV_BUFFERSINK_FLAG_* flags
|
||||||
|
*
|
||||||
|
* @return >= 0 in for success, a negative AVERROR code for failure.
|
||||||
|
*/
|
||||||
|
int av_buffersink_get_frame_flags(AVFilterContext *ctx, AVFrame *frame, int flags);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tell av_buffersink_get_buffer_ref() to read video/samples buffer
|
||||||
|
* reference, but not remove it from the buffer. This is useful if you
|
||||||
|
* need only to read a video/samples buffer, without to fetch it.
|
||||||
|
*/
|
||||||
|
#define AV_BUFFERSINK_FLAG_PEEK 1
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tell av_buffersink_get_buffer_ref() not to request a frame from its input.
|
||||||
|
* If a frame is already buffered, it is read (and removed from the buffer),
|
||||||
|
* but if no frame is present, return AVERROR(EAGAIN).
|
||||||
|
*/
|
||||||
|
#define AV_BUFFERSINK_FLAG_NO_REQUEST 2
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Struct to use for initializing a buffersink context.
|
||||||
|
*/
|
||||||
|
typedef struct {
|
||||||
|
const enum AVPixelFormat *pixel_fmts; ///< list of allowed pixel formats, terminated by AV_PIX_FMT_NONE
|
||||||
|
} AVBufferSinkParams;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create an AVBufferSinkParams structure.
|
||||||
|
*
|
||||||
|
* Must be freed with av_free().
|
||||||
|
*/
|
||||||
|
AVBufferSinkParams *av_buffersink_params_alloc(void);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Struct to use for initializing an abuffersink context.
|
||||||
|
*/
|
||||||
|
typedef struct {
|
||||||
|
const enum AVSampleFormat *sample_fmts; ///< list of allowed sample formats, terminated by AV_SAMPLE_FMT_NONE
|
||||||
|
const int64_t *channel_layouts; ///< list of allowed channel layouts, terminated by -1
|
||||||
|
const int *channel_counts; ///< list of allowed channel counts, terminated by -1
|
||||||
|
int all_channel_counts; ///< if not 0, accept any channel count or layout
|
||||||
|
int *sample_rates; ///< list of allowed sample rates, terminated by -1
|
||||||
|
} AVABufferSinkParams;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create an AVABufferSinkParams structure.
|
||||||
|
*
|
||||||
|
* Must be freed with av_free().
|
||||||
|
*/
|
||||||
|
AVABufferSinkParams *av_abuffersink_params_alloc(void);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the frame size for an audio buffer sink.
|
||||||
|
*
|
||||||
|
* All calls to av_buffersink_get_buffer_ref will return a buffer with
|
||||||
|
* exactly the specified number of samples, or AVERROR(EAGAIN) if there is
|
||||||
|
* not enough. The last buffer at EOF will be padded with 0.
|
||||||
|
*/
|
||||||
|
void av_buffersink_set_frame_size(AVFilterContext *ctx, unsigned frame_size);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the frame rate of the input.
|
||||||
|
*/
|
||||||
|
AVRational av_buffersink_get_frame_rate(AVFilterContext *ctx);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get a frame with filtered data from sink and put it in frame.
|
||||||
|
*
|
||||||
|
* @param ctx pointer to a context of a buffersink or abuffersink AVFilter.
|
||||||
|
* @param frame pointer to an allocated frame that will be filled with data.
|
||||||
|
* The data must be freed using av_frame_unref() / av_frame_free()
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
* - >= 0 if a frame was successfully returned.
|
||||||
|
* - AVERROR(EAGAIN) if no frames are available at this point; more
|
||||||
|
* input frames must be added to the filtergraph to get more output.
|
||||||
|
* - AVERROR_EOF if there will be no more output frames on this sink.
|
||||||
|
* - A different negative AVERROR code in other failure cases.
|
||||||
|
*/
|
||||||
|
int av_buffersink_get_frame(AVFilterContext *ctx, AVFrame *frame);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Same as av_buffersink_get_frame(), but with the ability to specify the number
|
||||||
|
* of samples read. This function is less efficient than
|
||||||
|
* av_buffersink_get_frame(), because it copies the data around.
|
||||||
|
*
|
||||||
|
* @param ctx pointer to a context of the abuffersink AVFilter.
|
||||||
|
* @param frame pointer to an allocated frame that will be filled with data.
|
||||||
|
* The data must be freed using av_frame_unref() / av_frame_free()
|
||||||
|
* frame will contain exactly nb_samples audio samples, except at
|
||||||
|
* the end of stream, when it can contain less than nb_samples.
|
||||||
|
*
|
||||||
|
* @return The return codes have the same meaning as for
|
||||||
|
* av_buffersink_get_samples().
|
||||||
|
*
|
||||||
|
* @warning do not mix this function with av_buffersink_get_frame(). Use only one or
|
||||||
|
* the other with a single sink, not both.
|
||||||
|
*/
|
||||||
|
int av_buffersink_get_samples(AVFilterContext *ctx, AVFrame *frame, int nb_samples);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @}
|
||||||
|
*/
|
||||||
|
|
||||||
|
#endif /* AVFILTER_BUFFERSINK_H */
|
@ -0,0 +1,126 @@
|
|||||||
|
/*
|
||||||
|
*
|
||||||
|
* This file is part of FFmpeg.
|
||||||
|
*
|
||||||
|
* FFmpeg is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2.1 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* FFmpeg is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with FFmpeg; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef AVFILTER_BUFFERSRC_H
|
||||||
|
#define AVFILTER_BUFFERSRC_H
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @file
|
||||||
|
* @ingroup lavfi_buffersrc
|
||||||
|
* Memory buffer source API.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "libavcodec/avcodec.h"
|
||||||
|
#include "avfilter.h"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @defgroup lavfi_buffersrc Buffer source API
|
||||||
|
* @ingroup lavfi
|
||||||
|
* @{
|
||||||
|
*/
|
||||||
|
|
||||||
|
enum {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Do not check for format changes.
|
||||||
|
*/
|
||||||
|
AV_BUFFERSRC_FLAG_NO_CHECK_FORMAT = 1,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Immediately push the frame to the output.
|
||||||
|
*/
|
||||||
|
AV_BUFFERSRC_FLAG_PUSH = 4,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Keep a reference to the frame.
|
||||||
|
* If the frame if reference-counted, create a new reference; otherwise
|
||||||
|
* copy the frame data.
|
||||||
|
*/
|
||||||
|
AV_BUFFERSRC_FLAG_KEEP_REF = 8,
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the number of failed requests.
|
||||||
|
*
|
||||||
|
* A failed request is when the request_frame method is called while no
|
||||||
|
* frame is present in the buffer.
|
||||||
|
* The number is reset when a frame is added.
|
||||||
|
*/
|
||||||
|
unsigned av_buffersrc_get_nb_failed_requests(AVFilterContext *buffer_src);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add a frame to the buffer source.
|
||||||
|
*
|
||||||
|
* @param ctx an instance of the buffersrc filter
|
||||||
|
* @param frame frame to be added. If the frame is reference counted, this
|
||||||
|
* function will make a new reference to it. Otherwise the frame data will be
|
||||||
|
* copied.
|
||||||
|
*
|
||||||
|
* @return 0 on success, a negative AVERROR on error
|
||||||
|
*
|
||||||
|
* This function is equivalent to av_buffersrc_add_frame_flags() with the
|
||||||
|
* AV_BUFFERSRC_FLAG_KEEP_REF flag.
|
||||||
|
*/
|
||||||
|
int av_buffersrc_write_frame(AVFilterContext *ctx, const AVFrame *frame);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add a frame to the buffer source.
|
||||||
|
*
|
||||||
|
* @param ctx an instance of the buffersrc filter
|
||||||
|
* @param frame frame to be added. If the frame is reference counted, this
|
||||||
|
* function will take ownership of the reference(s) and reset the frame.
|
||||||
|
* Otherwise the frame data will be copied. If this function returns an error,
|
||||||
|
* the input frame is not touched.
|
||||||
|
*
|
||||||
|
* @return 0 on success, a negative AVERROR on error.
|
||||||
|
*
|
||||||
|
* @note the difference between this function and av_buffersrc_write_frame() is
|
||||||
|
* that av_buffersrc_write_frame() creates a new reference to the input frame,
|
||||||
|
* while this function takes ownership of the reference passed to it.
|
||||||
|
*
|
||||||
|
* This function is equivalent to av_buffersrc_add_frame_flags() without the
|
||||||
|
* AV_BUFFERSRC_FLAG_KEEP_REF flag.
|
||||||
|
*/
|
||||||
|
int av_buffersrc_add_frame(AVFilterContext *ctx, AVFrame *frame);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add a frame to the buffer source.
|
||||||
|
*
|
||||||
|
* By default, if the frame is reference-counted, this function will take
|
||||||
|
* ownership of the reference(s) and reset the frame. This can be controlled
|
||||||
|
* using the flags.
|
||||||
|
*
|
||||||
|
* If this function returns an error, the input frame is not touched.
|
||||||
|
*
|
||||||
|
* @param buffer_src pointer to a buffer source context
|
||||||
|
* @param frame a frame, or NULL to mark EOF
|
||||||
|
* @param flags a combination of AV_BUFFERSRC_FLAG_*
|
||||||
|
* @return >= 0 in case of success, a negative AVERROR code
|
||||||
|
* in case of failure
|
||||||
|
*/
|
||||||
|
int av_buffersrc_add_frame_flags(AVFilterContext *buffer_src,
|
||||||
|
AVFrame *frame, int flags);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @}
|
||||||
|
*/
|
||||||
|
|
||||||
|
#endif /* AVFILTER_BUFFERSRC_H */
|
@ -0,0 +1,71 @@
|
|||||||
|
/*
|
||||||
|
* Version macros.
|
||||||
|
*
|
||||||
|
* This file is part of FFmpeg.
|
||||||
|
*
|
||||||
|
* FFmpeg is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2.1 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* FFmpeg is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with FFmpeg; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef AVFILTER_VERSION_H
|
||||||
|
#define AVFILTER_VERSION_H
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @file
|
||||||
|
* @ingroup lavfi
|
||||||
|
* Libavfilter version macros
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "libavutil/version.h"
|
||||||
|
|
||||||
|
#define LIBAVFILTER_VERSION_MAJOR 6
|
||||||
|
#define LIBAVFILTER_VERSION_MINOR 10
|
||||||
|
#define LIBAVFILTER_VERSION_MICRO 100
|
||||||
|
|
||||||
|
#define LIBAVFILTER_VERSION_INT AV_VERSION_INT(LIBAVFILTER_VERSION_MAJOR, \
|
||||||
|
LIBAVFILTER_VERSION_MINOR, \
|
||||||
|
LIBAVFILTER_VERSION_MICRO)
|
||||||
|
#define LIBAVFILTER_VERSION AV_VERSION(LIBAVFILTER_VERSION_MAJOR, \
|
||||||
|
LIBAVFILTER_VERSION_MINOR, \
|
||||||
|
LIBAVFILTER_VERSION_MICRO)
|
||||||
|
#define LIBAVFILTER_BUILD LIBAVFILTER_VERSION_INT
|
||||||
|
|
||||||
|
#define LIBAVFILTER_IDENT "Lavfi" AV_STRINGIFY(LIBAVFILTER_VERSION)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* FF_API_* defines may be placed below to indicate public API that will be
|
||||||
|
* dropped at a future version bump. The defines themselves are not part of
|
||||||
|
* the public API and may change, break or disappear at any time.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef FF_API_OLD_FILTER_OPTS
|
||||||
|
#define FF_API_OLD_FILTER_OPTS (LIBAVFILTER_VERSION_MAJOR < 7)
|
||||||
|
#endif
|
||||||
|
#ifndef FF_API_OLD_FILTER_OPTS_ERROR
|
||||||
|
#define FF_API_OLD_FILTER_OPTS_ERROR (LIBAVFILTER_VERSION_MAJOR < 7)
|
||||||
|
#endif
|
||||||
|
#ifndef FF_API_AVFILTER_OPEN
|
||||||
|
#define FF_API_AVFILTER_OPEN (LIBAVFILTER_VERSION_MAJOR < 7)
|
||||||
|
#endif
|
||||||
|
#ifndef FF_API_AVFILTER_INIT_FILTER
|
||||||
|
#define FF_API_AVFILTER_INIT_FILTER (LIBAVFILTER_VERSION_MAJOR < 7)
|
||||||
|
#endif
|
||||||
|
#ifndef FF_API_OLD_FILTER_REGISTER
|
||||||
|
#define FF_API_OLD_FILTER_REGISTER (LIBAVFILTER_VERSION_MAJOR < 7)
|
||||||
|
#endif
|
||||||
|
#ifndef FF_API_NOCONST_GET_NAME
|
||||||
|
#define FF_API_NOCONST_GET_NAME (LIBAVFILTER_VERSION_MAJOR < 7)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* AVFILTER_VERSION_H */
|
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,680 @@
|
|||||||
|
/*
|
||||||
|
* copyright (c) 2001 Fabrice Bellard
|
||||||
|
*
|
||||||
|
* This file is part of FFmpeg.
|
||||||
|
*
|
||||||
|
* FFmpeg is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2.1 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* FFmpeg is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with FFmpeg; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
*/
|
||||||
|
#ifndef AVFORMAT_AVIO_H
|
||||||
|
#define AVFORMAT_AVIO_H
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @file
|
||||||
|
* @ingroup lavf_io
|
||||||
|
* Buffered I/O operations
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#include "libavutil/common.h"
|
||||||
|
#include "libavutil/dict.h"
|
||||||
|
#include "libavutil/log.h"
|
||||||
|
|
||||||
|
#include "libavformat/version.h"
|
||||||
|
|
||||||
|
#define AVIO_SEEKABLE_NORMAL 0x0001 /**< Seeking works like for a local file */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Callback for checking whether to abort blocking functions.
|
||||||
|
* AVERROR_EXIT is returned in this case by the interrupted
|
||||||
|
* function. During blocking operations, callback is called with
|
||||||
|
* opaque as parameter. If the callback returns 1, the
|
||||||
|
* blocking operation will be aborted.
|
||||||
|
*
|
||||||
|
* No members can be added to this struct without a major bump, if
|
||||||
|
* new elements have been added after this struct in AVFormatContext
|
||||||
|
* or AVIOContext.
|
||||||
|
*/
|
||||||
|
typedef struct AVIOInterruptCB {
|
||||||
|
int (*callback)(void*);
|
||||||
|
void *opaque;
|
||||||
|
} AVIOInterruptCB;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Directory entry types.
|
||||||
|
*/
|
||||||
|
enum AVIODirEntryType {
|
||||||
|
AVIO_ENTRY_UNKNOWN,
|
||||||
|
AVIO_ENTRY_BLOCK_DEVICE,
|
||||||
|
AVIO_ENTRY_CHARACTER_DEVICE,
|
||||||
|
AVIO_ENTRY_DIRECTORY,
|
||||||
|
AVIO_ENTRY_NAMED_PIPE,
|
||||||
|
AVIO_ENTRY_SYMBOLIC_LINK,
|
||||||
|
AVIO_ENTRY_SOCKET,
|
||||||
|
AVIO_ENTRY_FILE,
|
||||||
|
AVIO_ENTRY_SERVER,
|
||||||
|
AVIO_ENTRY_SHARE,
|
||||||
|
AVIO_ENTRY_WORKGROUP,
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Describes single entry of the directory.
|
||||||
|
*
|
||||||
|
* Only name and type fields are guaranteed be set.
|
||||||
|
* Rest of fields are protocol or/and platform dependent and might be unknown.
|
||||||
|
*/
|
||||||
|
typedef struct AVIODirEntry {
|
||||||
|
char *name; /**< Filename */
|
||||||
|
int type; /**< Type of the entry */
|
||||||
|
int utf8; /**< Set to 1 when name is encoded with UTF-8, 0 otherwise.
|
||||||
|
Name can be encoded with UTF-8 even though 0 is set. */
|
||||||
|
int64_t size; /**< File size in bytes, -1 if unknown. */
|
||||||
|
int64_t modification_timestamp; /**< Time of last modification in microseconds since unix
|
||||||
|
epoch, -1 if unknown. */
|
||||||
|
int64_t access_timestamp; /**< Time of last access in microseconds since unix epoch,
|
||||||
|
-1 if unknown. */
|
||||||
|
int64_t status_change_timestamp; /**< Time of last status change in microseconds since unix
|
||||||
|
epoch, -1 if unknown. */
|
||||||
|
int64_t user_id; /**< User ID of owner, -1 if unknown. */
|
||||||
|
int64_t group_id; /**< Group ID of owner, -1 if unknown. */
|
||||||
|
int64_t filemode; /**< Unix file mode, -1 if unknown. */
|
||||||
|
} AVIODirEntry;
|
||||||
|
|
||||||
|
typedef struct AVIODirContext {
|
||||||
|
struct URLContext *url_context;
|
||||||
|
} AVIODirContext;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Bytestream IO Context.
|
||||||
|
* New fields can be added to the end with minor version bumps.
|
||||||
|
* Removal, reordering and changes to existing fields require a major
|
||||||
|
* version bump.
|
||||||
|
* sizeof(AVIOContext) must not be used outside libav*.
|
||||||
|
*
|
||||||
|
* @note None of the function pointers in AVIOContext should be called
|
||||||
|
* directly, they should only be set by the client application
|
||||||
|
* when implementing custom I/O. Normally these are set to the
|
||||||
|
* function pointers specified in avio_alloc_context()
|
||||||
|
*/
|
||||||
|
typedef struct AVIOContext {
|
||||||
|
/**
|
||||||
|
* A class for private options.
|
||||||
|
*
|
||||||
|
* If this AVIOContext is created by avio_open2(), av_class is set and
|
||||||
|
* passes the options down to protocols.
|
||||||
|
*
|
||||||
|
* If this AVIOContext is manually allocated, then av_class may be set by
|
||||||
|
* the caller.
|
||||||
|
*
|
||||||
|
* warning -- this field can be NULL, be sure to not pass this AVIOContext
|
||||||
|
* to any av_opt_* functions in that case.
|
||||||
|
*/
|
||||||
|
const AVClass *av_class;
|
||||||
|
unsigned char *buffer; /**< Start of the buffer. */
|
||||||
|
int buffer_size; /**< Maximum buffer size */
|
||||||
|
unsigned char *buf_ptr; /**< Current position in the buffer */
|
||||||
|
unsigned char *buf_end; /**< End of the data, may be less than
|
||||||
|
buffer+buffer_size if the read function returned
|
||||||
|
less data than requested, e.g. for streams where
|
||||||
|
no more data has been received yet. */
|
||||||
|
void *opaque; /**< A private pointer, passed to the read/write/seek/...
|
||||||
|
functions. */
|
||||||
|
int (*read_packet)(void *opaque, uint8_t *buf, int buf_size);
|
||||||
|
int (*write_packet)(void *opaque, uint8_t *buf, int buf_size);
|
||||||
|
int64_t (*seek)(void *opaque, int64_t offset, int whence);
|
||||||
|
int64_t pos; /**< position in the file of the current buffer */
|
||||||
|
int must_flush; /**< true if the next seek should flush */
|
||||||
|
int eof_reached; /**< true if eof reached */
|
||||||
|
int write_flag; /**< true if open for writing */
|
||||||
|
int max_packet_size;
|
||||||
|
unsigned long checksum;
|
||||||
|
unsigned char *checksum_ptr;
|
||||||
|
unsigned long (*update_checksum)(unsigned long checksum, const uint8_t *buf, unsigned int size);
|
||||||
|
int error; /**< contains the error code or 0 if no error happened */
|
||||||
|
/**
|
||||||
|
* Pause or resume playback for network streaming protocols - e.g. MMS.
|
||||||
|
*/
|
||||||
|
int (*read_pause)(void *opaque, int pause);
|
||||||
|
/**
|
||||||
|
* Seek to a given timestamp in stream with the specified stream_index.
|
||||||
|
* Needed for some network streaming protocols which don't support seeking
|
||||||
|
* to byte position.
|
||||||
|
*/
|
||||||
|
int64_t (*read_seek)(void *opaque, int stream_index,
|
||||||
|
int64_t timestamp, int flags);
|
||||||
|
/**
|
||||||
|
* A combination of AVIO_SEEKABLE_ flags or 0 when the stream is not seekable.
|
||||||
|
*/
|
||||||
|
int seekable;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* max filesize, used to limit allocations
|
||||||
|
* This field is internal to libavformat and access from outside is not allowed.
|
||||||
|
*/
|
||||||
|
int64_t maxsize;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* avio_read and avio_write should if possible be satisfied directly
|
||||||
|
* instead of going through a buffer, and avio_seek will always
|
||||||
|
* call the underlying seek function directly.
|
||||||
|
*/
|
||||||
|
int direct;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Bytes read statistic
|
||||||
|
* This field is internal to libavformat and access from outside is not allowed.
|
||||||
|
*/
|
||||||
|
int64_t bytes_read;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* seek statistic
|
||||||
|
* This field is internal to libavformat and access from outside is not allowed.
|
||||||
|
*/
|
||||||
|
int seek_count;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* writeout statistic
|
||||||
|
* This field is internal to libavformat and access from outside is not allowed.
|
||||||
|
*/
|
||||||
|
int writeout_count;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Original buffer size
|
||||||
|
* used internally after probing and ensure seekback to reset the buffer size
|
||||||
|
* This field is internal to libavformat and access from outside is not allowed.
|
||||||
|
*/
|
||||||
|
int orig_buffer_size;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Threshold to favor readahead over seek.
|
||||||
|
* This is current internal only, do not use from outside.
|
||||||
|
*/
|
||||||
|
int short_seek_threshold;
|
||||||
|
} AVIOContext;
|
||||||
|
|
||||||
|
/* unbuffered I/O */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the name of the protocol that will handle the passed URL.
|
||||||
|
*
|
||||||
|
* NULL is returned if no protocol could be found for the given URL.
|
||||||
|
*
|
||||||
|
* @return Name of the protocol or NULL.
|
||||||
|
*/
|
||||||
|
const char *avio_find_protocol_name(const char *url);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return AVIO_FLAG_* access flags corresponding to the access permissions
|
||||||
|
* of the resource in url, or a negative value corresponding to an
|
||||||
|
* AVERROR code in case of failure. The returned access flags are
|
||||||
|
* masked by the value in flags.
|
||||||
|
*
|
||||||
|
* @note This function is intrinsically unsafe, in the sense that the
|
||||||
|
* checked resource may change its existence or permission status from
|
||||||
|
* one call to another. Thus you should not trust the returned value,
|
||||||
|
* unless you are sure that no other processes are accessing the
|
||||||
|
* checked resource.
|
||||||
|
*/
|
||||||
|
int avio_check(const char *url, int flags);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Move or rename a resource.
|
||||||
|
*
|
||||||
|
* @note url_src and url_dst should share the same protocol and authority.
|
||||||
|
*
|
||||||
|
* @param url_src url to resource to be moved
|
||||||
|
* @param url_dst new url to resource if the operation succeeded
|
||||||
|
* @return >=0 on success or negative on error.
|
||||||
|
*/
|
||||||
|
int avpriv_io_move(const char *url_src, const char *url_dst);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Delete a resource.
|
||||||
|
*
|
||||||
|
* @param url resource to be deleted.
|
||||||
|
* @return >=0 on success or negative on error.
|
||||||
|
*/
|
||||||
|
int avpriv_io_delete(const char *url);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Open directory for reading.
|
||||||
|
*
|
||||||
|
* @param s directory read context. Pointer to a NULL pointer must be passed.
|
||||||
|
* @param url directory to be listed.
|
||||||
|
* @param options A dictionary filled with protocol-private options. On return
|
||||||
|
* this parameter will be destroyed and replaced with a dictionary
|
||||||
|
* containing options that were not found. May be NULL.
|
||||||
|
* @return >=0 on success or negative on error.
|
||||||
|
*/
|
||||||
|
int avio_open_dir(AVIODirContext **s, const char *url, AVDictionary **options);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get next directory entry.
|
||||||
|
*
|
||||||
|
* Returned entry must be freed with avio_free_directory_entry(). In particular
|
||||||
|
* it may outlive AVIODirContext.
|
||||||
|
*
|
||||||
|
* @param s directory read context.
|
||||||
|
* @param[out] next next entry or NULL when no more entries.
|
||||||
|
* @return >=0 on success or negative on error. End of list is not considered an
|
||||||
|
* error.
|
||||||
|
*/
|
||||||
|
int avio_read_dir(AVIODirContext *s, AVIODirEntry **next);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Close directory.
|
||||||
|
*
|
||||||
|
* @note Entries created using avio_read_dir() are not deleted and must be
|
||||||
|
* freeded with avio_free_directory_entry().
|
||||||
|
*
|
||||||
|
* @param s directory read context.
|
||||||
|
* @return >=0 on success or negative on error.
|
||||||
|
*/
|
||||||
|
int avio_close_dir(AVIODirContext **s);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Free entry allocated by avio_read_dir().
|
||||||
|
*
|
||||||
|
* @param entry entry to be freed.
|
||||||
|
*/
|
||||||
|
void avio_free_directory_entry(AVIODirEntry **entry);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Allocate and initialize an AVIOContext for buffered I/O. It must be later
|
||||||
|
* freed with av_free().
|
||||||
|
*
|
||||||
|
* @param buffer Memory block for input/output operations via AVIOContext.
|
||||||
|
* The buffer must be allocated with av_malloc() and friends.
|
||||||
|
* It may be freed and replaced with a new buffer by libavformat.
|
||||||
|
* AVIOContext.buffer holds the buffer currently in use,
|
||||||
|
* which must be later freed with av_free().
|
||||||
|
* @param buffer_size The buffer size is very important for performance.
|
||||||
|
* For protocols with fixed blocksize it should be set to this blocksize.
|
||||||
|
* For others a typical size is a cache page, e.g. 4kb.
|
||||||
|
* @param write_flag Set to 1 if the buffer should be writable, 0 otherwise.
|
||||||
|
* @param opaque An opaque pointer to user-specific data.
|
||||||
|
* @param read_packet A function for refilling the buffer, may be NULL.
|
||||||
|
* @param write_packet A function for writing the buffer contents, may be NULL.
|
||||||
|
* The function may not change the input buffers content.
|
||||||
|
* @param seek A function for seeking to specified byte position, may be NULL.
|
||||||
|
*
|
||||||
|
* @return Allocated AVIOContext or NULL on failure.
|
||||||
|
*/
|
||||||
|
AVIOContext *avio_alloc_context(
|
||||||
|
unsigned char *buffer,
|
||||||
|
int buffer_size,
|
||||||
|
int write_flag,
|
||||||
|
void *opaque,
|
||||||
|
int (*read_packet)(void *opaque, uint8_t *buf, int buf_size),
|
||||||
|
int (*write_packet)(void *opaque, uint8_t *buf, int buf_size),
|
||||||
|
int64_t (*seek)(void *opaque, int64_t offset, int whence));
|
||||||
|
|
||||||
|
void avio_w8(AVIOContext *s, int b);
|
||||||
|
void avio_write(AVIOContext *s, const unsigned char *buf, int size);
|
||||||
|
void avio_wl64(AVIOContext *s, uint64_t val);
|
||||||
|
void avio_wb64(AVIOContext *s, uint64_t val);
|
||||||
|
void avio_wl32(AVIOContext *s, unsigned int val);
|
||||||
|
void avio_wb32(AVIOContext *s, unsigned int val);
|
||||||
|
void avio_wl24(AVIOContext *s, unsigned int val);
|
||||||
|
void avio_wb24(AVIOContext *s, unsigned int val);
|
||||||
|
void avio_wl16(AVIOContext *s, unsigned int val);
|
||||||
|
void avio_wb16(AVIOContext *s, unsigned int val);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Write a NULL-terminated string.
|
||||||
|
* @return number of bytes written.
|
||||||
|
*/
|
||||||
|
int avio_put_str(AVIOContext *s, const char *str);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Convert an UTF-8 string to UTF-16LE and write it.
|
||||||
|
* @param s the AVIOContext
|
||||||
|
* @param str NULL-terminated UTF-8 string
|
||||||
|
*
|
||||||
|
* @return number of bytes written.
|
||||||
|
*/
|
||||||
|
int avio_put_str16le(AVIOContext *s, const char *str);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Convert an UTF-8 string to UTF-16BE and write it.
|
||||||
|
* @param s the AVIOContext
|
||||||
|
* @param str NULL-terminated UTF-8 string
|
||||||
|
*
|
||||||
|
* @return number of bytes written.
|
||||||
|
*/
|
||||||
|
int avio_put_str16be(AVIOContext *s, const char *str);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Passing this as the "whence" parameter to a seek function causes it to
|
||||||
|
* return the filesize without seeking anywhere. Supporting this is optional.
|
||||||
|
* If it is not supported then the seek function will return <0.
|
||||||
|
*/
|
||||||
|
#define AVSEEK_SIZE 0x10000
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Oring this flag as into the "whence" parameter to a seek function causes it to
|
||||||
|
* seek by any means (like reopening and linear reading) or other normally unreasonable
|
||||||
|
* means that can be extremely slow.
|
||||||
|
* This may be ignored by the seek code.
|
||||||
|
*/
|
||||||
|
#define AVSEEK_FORCE 0x20000
|
||||||
|
|
||||||
|
/**
|
||||||
|
* fseek() equivalent for AVIOContext.
|
||||||
|
* @return new position or AVERROR.
|
||||||
|
*/
|
||||||
|
int64_t avio_seek(AVIOContext *s, int64_t offset, int whence);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Skip given number of bytes forward
|
||||||
|
* @return new position or AVERROR.
|
||||||
|
*/
|
||||||
|
int64_t avio_skip(AVIOContext *s, int64_t offset);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ftell() equivalent for AVIOContext.
|
||||||
|
* @return position or AVERROR.
|
||||||
|
*/
|
||||||
|
static av_always_inline int64_t avio_tell(AVIOContext *s)
|
||||||
|
{
|
||||||
|
return avio_seek(s, 0, SEEK_CUR);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the filesize.
|
||||||
|
* @return filesize or AVERROR
|
||||||
|
*/
|
||||||
|
int64_t avio_size(AVIOContext *s);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* feof() equivalent for AVIOContext.
|
||||||
|
* @return non zero if and only if end of file
|
||||||
|
*/
|
||||||
|
int avio_feof(AVIOContext *s);
|
||||||
|
#if FF_API_URL_FEOF
|
||||||
|
/**
|
||||||
|
* @deprecated use avio_feof()
|
||||||
|
*/
|
||||||
|
attribute_deprecated
|
||||||
|
int url_feof(AVIOContext *s);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/** @warning currently size is limited */
|
||||||
|
int avio_printf(AVIOContext *s, const char *fmt, ...) av_printf_format(2, 3);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Force flushing of buffered data.
|
||||||
|
*
|
||||||
|
* For write streams, force the buffered data to be immediately written to the output,
|
||||||
|
* without to wait to fill the internal buffer.
|
||||||
|
*
|
||||||
|
* For read streams, discard all currently buffered data, and advance the
|
||||||
|
* reported file position to that of the underlying stream. This does not
|
||||||
|
* read new data, and does not perform any seeks.
|
||||||
|
*/
|
||||||
|
void avio_flush(AVIOContext *s);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Read size bytes from AVIOContext into buf.
|
||||||
|
* @return number of bytes read or AVERROR
|
||||||
|
*/
|
||||||
|
int avio_read(AVIOContext *s, unsigned char *buf, int size);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @name Functions for reading from AVIOContext
|
||||||
|
* @{
|
||||||
|
*
|
||||||
|
* @note return 0 if EOF, so you cannot use it if EOF handling is
|
||||||
|
* necessary
|
||||||
|
*/
|
||||||
|
int avio_r8 (AVIOContext *s);
|
||||||
|
unsigned int avio_rl16(AVIOContext *s);
|
||||||
|
unsigned int avio_rl24(AVIOContext *s);
|
||||||
|
unsigned int avio_rl32(AVIOContext *s);
|
||||||
|
uint64_t avio_rl64(AVIOContext *s);
|
||||||
|
unsigned int avio_rb16(AVIOContext *s);
|
||||||
|
unsigned int avio_rb24(AVIOContext *s);
|
||||||
|
unsigned int avio_rb32(AVIOContext *s);
|
||||||
|
uint64_t avio_rb64(AVIOContext *s);
|
||||||
|
/**
|
||||||
|
* @}
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Read a string from pb into buf. The reading will terminate when either
|
||||||
|
* a NULL character was encountered, maxlen bytes have been read, or nothing
|
||||||
|
* more can be read from pb. The result is guaranteed to be NULL-terminated, it
|
||||||
|
* will be truncated if buf is too small.
|
||||||
|
* Note that the string is not interpreted or validated in any way, it
|
||||||
|
* might get truncated in the middle of a sequence for multi-byte encodings.
|
||||||
|
*
|
||||||
|
* @return number of bytes read (is always <= maxlen).
|
||||||
|
* If reading ends on EOF or error, the return value will be one more than
|
||||||
|
* bytes actually read.
|
||||||
|
*/
|
||||||
|
int avio_get_str(AVIOContext *pb, int maxlen, char *buf, int buflen);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Read a UTF-16 string from pb and convert it to UTF-8.
|
||||||
|
* The reading will terminate when either a null or invalid character was
|
||||||
|
* encountered or maxlen bytes have been read.
|
||||||
|
* @return number of bytes read (is always <= maxlen)
|
||||||
|
*/
|
||||||
|
int avio_get_str16le(AVIOContext *pb, int maxlen, char *buf, int buflen);
|
||||||
|
int avio_get_str16be(AVIOContext *pb, int maxlen, char *buf, int buflen);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @name URL open modes
|
||||||
|
* The flags argument to avio_open must be one of the following
|
||||||
|
* constants, optionally ORed with other flags.
|
||||||
|
* @{
|
||||||
|
*/
|
||||||
|
#define AVIO_FLAG_READ 1 /**< read-only */
|
||||||
|
#define AVIO_FLAG_WRITE 2 /**< write-only */
|
||||||
|
#define AVIO_FLAG_READ_WRITE (AVIO_FLAG_READ|AVIO_FLAG_WRITE) /**< read-write pseudo flag */
|
||||||
|
/**
|
||||||
|
* @}
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Use non-blocking mode.
|
||||||
|
* If this flag is set, operations on the context will return
|
||||||
|
* AVERROR(EAGAIN) if they can not be performed immediately.
|
||||||
|
* If this flag is not set, operations on the context will never return
|
||||||
|
* AVERROR(EAGAIN).
|
||||||
|
* Note that this flag does not affect the opening/connecting of the
|
||||||
|
* context. Connecting a protocol will always block if necessary (e.g. on
|
||||||
|
* network protocols) but never hang (e.g. on busy devices).
|
||||||
|
* Warning: non-blocking protocols is work-in-progress; this flag may be
|
||||||
|
* silently ignored.
|
||||||
|
*/
|
||||||
|
#define AVIO_FLAG_NONBLOCK 8
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Use direct mode.
|
||||||
|
* avio_read and avio_write should if possible be satisfied directly
|
||||||
|
* instead of going through a buffer, and avio_seek will always
|
||||||
|
* call the underlying seek function directly.
|
||||||
|
*/
|
||||||
|
#define AVIO_FLAG_DIRECT 0x8000
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create and initialize a AVIOContext for accessing the
|
||||||
|
* resource indicated by url.
|
||||||
|
* @note When the resource indicated by url has been opened in
|
||||||
|
* read+write mode, the AVIOContext can be used only for writing.
|
||||||
|
*
|
||||||
|
* @param s Used to return the pointer to the created AVIOContext.
|
||||||
|
* In case of failure the pointed to value is set to NULL.
|
||||||
|
* @param url resource to access
|
||||||
|
* @param flags flags which control how the resource indicated by url
|
||||||
|
* is to be opened
|
||||||
|
* @return >= 0 in case of success, a negative value corresponding to an
|
||||||
|
* AVERROR code in case of failure
|
||||||
|
*/
|
||||||
|
int avio_open(AVIOContext **s, const char *url, int flags);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create and initialize a AVIOContext for accessing the
|
||||||
|
* resource indicated by url.
|
||||||
|
* @note When the resource indicated by url has been opened in
|
||||||
|
* read+write mode, the AVIOContext can be used only for writing.
|
||||||
|
*
|
||||||
|
* @param s Used to return the pointer to the created AVIOContext.
|
||||||
|
* In case of failure the pointed to value is set to NULL.
|
||||||
|
* @param url resource to access
|
||||||
|
* @param flags flags which control how the resource indicated by url
|
||||||
|
* is to be opened
|
||||||
|
* @param int_cb an interrupt callback to be used at the protocols level
|
||||||
|
* @param options A dictionary filled with protocol-private options. On return
|
||||||
|
* this parameter will be destroyed and replaced with a dict containing options
|
||||||
|
* that were not found. May be NULL.
|
||||||
|
* @return >= 0 in case of success, a negative value corresponding to an
|
||||||
|
* AVERROR code in case of failure
|
||||||
|
*/
|
||||||
|
int avio_open2(AVIOContext **s, const char *url, int flags,
|
||||||
|
const AVIOInterruptCB *int_cb, AVDictionary **options);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Close the resource accessed by the AVIOContext s and free it.
|
||||||
|
* This function can only be used if s was opened by avio_open().
|
||||||
|
*
|
||||||
|
* The internal buffer is automatically flushed before closing the
|
||||||
|
* resource.
|
||||||
|
*
|
||||||
|
* @return 0 on success, an AVERROR < 0 on error.
|
||||||
|
* @see avio_closep
|
||||||
|
*/
|
||||||
|
int avio_close(AVIOContext *s);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Close the resource accessed by the AVIOContext *s, free it
|
||||||
|
* and set the pointer pointing to it to NULL.
|
||||||
|
* This function can only be used if s was opened by avio_open().
|
||||||
|
*
|
||||||
|
* The internal buffer is automatically flushed before closing the
|
||||||
|
* resource.
|
||||||
|
*
|
||||||
|
* @return 0 on success, an AVERROR < 0 on error.
|
||||||
|
* @see avio_close
|
||||||
|
*/
|
||||||
|
int avio_closep(AVIOContext **s);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Open a write only memory stream.
|
||||||
|
*
|
||||||
|
* @param s new IO context
|
||||||
|
* @return zero if no error.
|
||||||
|
*/
|
||||||
|
int avio_open_dyn_buf(AVIOContext **s);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the written size and a pointer to the buffer. The buffer
|
||||||
|
* must be freed with av_free().
|
||||||
|
* Padding of AV_INPUT_BUFFER_PADDING_SIZE is added to the buffer.
|
||||||
|
*
|
||||||
|
* @param s IO context
|
||||||
|
* @param pbuffer pointer to a byte buffer
|
||||||
|
* @return the length of the byte buffer
|
||||||
|
*/
|
||||||
|
int avio_close_dyn_buf(AVIOContext *s, uint8_t **pbuffer);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Iterate through names of available protocols.
|
||||||
|
*
|
||||||
|
* @param opaque A private pointer representing current protocol.
|
||||||
|
* It must be a pointer to NULL on first iteration and will
|
||||||
|
* be updated by successive calls to avio_enum_protocols.
|
||||||
|
* @param output If set to 1, iterate over output protocols,
|
||||||
|
* otherwise over input protocols.
|
||||||
|
*
|
||||||
|
* @return A static string containing the name of current protocol or NULL
|
||||||
|
*/
|
||||||
|
const char *avio_enum_protocols(void **opaque, int output);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Pause and resume playing - only meaningful if using a network streaming
|
||||||
|
* protocol (e.g. MMS).
|
||||||
|
*
|
||||||
|
* @param h IO context from which to call the read_pause function pointer
|
||||||
|
* @param pause 1 for pause, 0 for resume
|
||||||
|
*/
|
||||||
|
int avio_pause(AVIOContext *h, int pause);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Seek to a given timestamp relative to some component stream.
|
||||||
|
* Only meaningful if using a network streaming protocol (e.g. MMS.).
|
||||||
|
*
|
||||||
|
* @param h IO context from which to call the seek function pointers
|
||||||
|
* @param stream_index The stream index that the timestamp is relative to.
|
||||||
|
* If stream_index is (-1) the timestamp should be in AV_TIME_BASE
|
||||||
|
* units from the beginning of the presentation.
|
||||||
|
* If a stream_index >= 0 is used and the protocol does not support
|
||||||
|
* seeking based on component streams, the call will fail.
|
||||||
|
* @param timestamp timestamp in AVStream.time_base units
|
||||||
|
* or if there is no stream specified then in AV_TIME_BASE units.
|
||||||
|
* @param flags Optional combination of AVSEEK_FLAG_BACKWARD, AVSEEK_FLAG_BYTE
|
||||||
|
* and AVSEEK_FLAG_ANY. The protocol may silently ignore
|
||||||
|
* AVSEEK_FLAG_BACKWARD and AVSEEK_FLAG_ANY, but AVSEEK_FLAG_BYTE will
|
||||||
|
* fail if used and not supported.
|
||||||
|
* @return >= 0 on success
|
||||||
|
* @see AVInputFormat::read_seek
|
||||||
|
*/
|
||||||
|
int64_t avio_seek_time(AVIOContext *h, int stream_index,
|
||||||
|
int64_t timestamp, int flags);
|
||||||
|
|
||||||
|
/* Avoid a warning. The header can not be included because it breaks c++. */
|
||||||
|
struct AVBPrint;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Read contents of h into print buffer, up to max_size bytes, or up to EOF.
|
||||||
|
*
|
||||||
|
* @return 0 for success (max_size bytes read or EOF reached), negative error
|
||||||
|
* code otherwise
|
||||||
|
*/
|
||||||
|
int avio_read_to_bprint(AVIOContext *h, struct AVBPrint *pb, size_t max_size);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Accept and allocate a client context on a server context.
|
||||||
|
* @param s the server context
|
||||||
|
* @param c the client context, must be unallocated
|
||||||
|
* @return >= 0 on success or a negative value corresponding
|
||||||
|
* to an AVERROR on failure
|
||||||
|
*/
|
||||||
|
int avio_accept(AVIOContext *s, AVIOContext **c);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Perform one step of the protocol handshake to accept a new client.
|
||||||
|
* This function must be called on a client returned by avio_accept() before
|
||||||
|
* using it as a read/write context.
|
||||||
|
* It is separate from avio_accept() because it may block.
|
||||||
|
* A step of the handshake is defined by places where the application may
|
||||||
|
* decide to change the proceedings.
|
||||||
|
* For example, on a protocol with a request header and a reply header, each
|
||||||
|
* one can constitute a step because the application may use the parameters
|
||||||
|
* from the request to change parameters in the reply; or each individual
|
||||||
|
* chunk of the request can constitute a step.
|
||||||
|
* If the handshake is already finished, avio_handshake() does nothing and
|
||||||
|
* returns 0 immediately.
|
||||||
|
*
|
||||||
|
* @param c the client context to perform the handshake on
|
||||||
|
* @return 0 on a complete and successful handshake
|
||||||
|
* > 0 if the handshake progressed, but is not complete
|
||||||
|
* < 0 for an AVERROR code
|
||||||
|
*/
|
||||||
|
int avio_handshake(AVIOContext *c);
|
||||||
|
#endif /* AVFORMAT_AVIO_H */
|
@ -0,0 +1,72 @@
|
|||||||
|
/*
|
||||||
|
* Version macros.
|
||||||
|
*
|
||||||
|
* This file is part of FFmpeg.
|
||||||
|
*
|
||||||
|
* FFmpeg is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2.1 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* FFmpeg is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with FFmpeg; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef AVFORMAT_VERSION_H
|
||||||
|
#define AVFORMAT_VERSION_H
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @file
|
||||||
|
* @ingroup libavf
|
||||||
|
* Libavformat version macros
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "libavutil/version.h"
|
||||||
|
|
||||||
|
#define LIBAVFORMAT_VERSION_MAJOR 57
|
||||||
|
#define LIBAVFORMAT_VERSION_MINOR 3
|
||||||
|
#define LIBAVFORMAT_VERSION_MICRO 100
|
||||||
|
|
||||||
|
#define LIBAVFORMAT_VERSION_INT AV_VERSION_INT(LIBAVFORMAT_VERSION_MAJOR, \
|
||||||
|
LIBAVFORMAT_VERSION_MINOR, \
|
||||||
|
LIBAVFORMAT_VERSION_MICRO)
|
||||||
|
#define LIBAVFORMAT_VERSION AV_VERSION(LIBAVFORMAT_VERSION_MAJOR, \
|
||||||
|
LIBAVFORMAT_VERSION_MINOR, \
|
||||||
|
LIBAVFORMAT_VERSION_MICRO)
|
||||||
|
#define LIBAVFORMAT_BUILD LIBAVFORMAT_VERSION_INT
|
||||||
|
|
||||||
|
#define LIBAVFORMAT_IDENT "Lavf" AV_STRINGIFY(LIBAVFORMAT_VERSION)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* FF_API_* defines may be placed below to indicate public API that will be
|
||||||
|
* dropped at a future version bump. The defines themselves are not part of
|
||||||
|
* the public API and may change, break or disappear at any time.
|
||||||
|
*
|
||||||
|
* @note, when bumping the major version it is recommended to manually
|
||||||
|
* disable each FF_API_* in its own commit instead of disabling them all
|
||||||
|
* at once through the bump. This improves the git bisect-ability of the change.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
#ifndef FF_API_LAVF_BITEXACT
|
||||||
|
#define FF_API_LAVF_BITEXACT (LIBAVFORMAT_VERSION_MAJOR < 58)
|
||||||
|
#endif
|
||||||
|
#ifndef FF_API_LAVF_FRAC
|
||||||
|
#define FF_API_LAVF_FRAC (LIBAVFORMAT_VERSION_MAJOR < 58)
|
||||||
|
#endif
|
||||||
|
#ifndef FF_API_LAVF_CODEC_TB
|
||||||
|
#define FF_API_LAVF_CODEC_TB (LIBAVFORMAT_VERSION_MAJOR < 58)
|
||||||
|
#endif
|
||||||
|
#ifndef FF_API_URL_FEOF
|
||||||
|
#define FF_API_URL_FEOF (LIBAVFORMAT_VERSION_MAJOR < 58)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef FF_API_R_FRAME_RATE
|
||||||
|
#define FF_API_R_FRAME_RATE 1
|
||||||
|
#endif
|
||||||
|
#endif /* AVFORMAT_VERSION_H */
|
@ -0,0 +1,55 @@
|
|||||||
|
/*
|
||||||
|
* copyright (c) 2006 Mans Rullgard
|
||||||
|
*
|
||||||
|
* This file is part of FFmpeg.
|
||||||
|
*
|
||||||
|
* FFmpeg is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2.1 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* FFmpeg is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with FFmpeg; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef AVUTIL_ADLER32_H
|
||||||
|
#define AVUTIL_ADLER32_H
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
#include "attributes.h"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @file
|
||||||
|
* Public header for libavutil Adler32 hasher
|
||||||
|
*
|
||||||
|
* @defgroup lavu_adler32 Adler32
|
||||||
|
* @ingroup lavu_crypto
|
||||||
|
* @{
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Calculate the Adler32 checksum of a buffer.
|
||||||
|
*
|
||||||
|
* Passing the return value to a subsequent av_adler32_update() call
|
||||||
|
* allows the checksum of multiple buffers to be calculated as though
|
||||||
|
* they were concatenated.
|
||||||
|
*
|
||||||
|
* @param adler initial checksum value
|
||||||
|
* @param buf pointer to input buffer
|
||||||
|
* @param len size of input buffer
|
||||||
|
* @return updated checksum
|
||||||
|
*/
|
||||||
|
unsigned long av_adler32_update(unsigned long adler, const uint8_t *buf,
|
||||||
|
unsigned int len) av_pure;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @}
|
||||||
|
*/
|
||||||
|
|
||||||
|
#endif /* AVUTIL_ADLER32_H */
|
@ -0,0 +1,65 @@
|
|||||||
|
/*
|
||||||
|
* copyright (c) 2007 Michael Niedermayer <michaelni@gmx.at>
|
||||||
|
*
|
||||||
|
* This file is part of FFmpeg.
|
||||||
|
*
|
||||||
|
* FFmpeg is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2.1 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* FFmpeg is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with FFmpeg; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef AVUTIL_AES_H
|
||||||
|
#define AVUTIL_AES_H
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#include "attributes.h"
|
||||||
|
#include "version.h"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @defgroup lavu_aes AES
|
||||||
|
* @ingroup lavu_crypto
|
||||||
|
* @{
|
||||||
|
*/
|
||||||
|
|
||||||
|
extern const int av_aes_size;
|
||||||
|
|
||||||
|
struct AVAES;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Allocate an AVAES context.
|
||||||
|
*/
|
||||||
|
struct AVAES *av_aes_alloc(void);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initialize an AVAES context.
|
||||||
|
* @param key_bits 128, 192 or 256
|
||||||
|
* @param decrypt 0 for encryption, 1 for decryption
|
||||||
|
*/
|
||||||
|
int av_aes_init(struct AVAES *a, const uint8_t *key, int key_bits, int decrypt);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Encrypt or decrypt a buffer using a previously initialized context.
|
||||||
|
* @param count number of 16 byte blocks
|
||||||
|
* @param dst destination array, can be equal to src
|
||||||
|
* @param src source array, can be equal to dst
|
||||||
|
* @param iv initialization vector for CBC mode, if NULL then ECB will be used
|
||||||
|
* @param decrypt 0 for encryption, 1 for decryption
|
||||||
|
*/
|
||||||
|
void av_aes_crypt(struct AVAES *a, uint8_t *dst, const uint8_t *src, int count, uint8_t *iv, int decrypt);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @}
|
||||||
|
*/
|
||||||
|
|
||||||
|
#endif /* AVUTIL_AES_H */
|
@ -0,0 +1,168 @@
|
|||||||
|
/*
|
||||||
|
* copyright (c) 2006 Michael Niedermayer <michaelni@gmx.at>
|
||||||
|
*
|
||||||
|
* This file is part of FFmpeg.
|
||||||
|
*
|
||||||
|
* FFmpeg is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2.1 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* FFmpeg is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with FFmpeg; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @file
|
||||||
|
* Macro definitions for various function/variable attributes
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef AVUTIL_ATTRIBUTES_H
|
||||||
|
#define AVUTIL_ATTRIBUTES_H
|
||||||
|
|
||||||
|
#ifdef __GNUC__
|
||||||
|
# define AV_GCC_VERSION_AT_LEAST(x,y) (__GNUC__ > (x) || __GNUC__ == (x) && __GNUC_MINOR__ >= (y))
|
||||||
|
# define AV_GCC_VERSION_AT_MOST(x,y) (__GNUC__ < (x) || __GNUC__ == (x) && __GNUC_MINOR__ <= (y))
|
||||||
|
#else
|
||||||
|
# define AV_GCC_VERSION_AT_LEAST(x,y) 0
|
||||||
|
# define AV_GCC_VERSION_AT_MOST(x,y) 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef av_always_inline
|
||||||
|
#if AV_GCC_VERSION_AT_LEAST(3,1)
|
||||||
|
# define av_always_inline __attribute__((always_inline)) inline
|
||||||
|
#elif defined(_MSC_VER)
|
||||||
|
# define av_always_inline __forceinline
|
||||||
|
#else
|
||||||
|
# define av_always_inline inline
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef av_extern_inline
|
||||||
|
#if defined(__ICL) && __ICL >= 1210 || defined(__GNUC_STDC_INLINE__)
|
||||||
|
# define av_extern_inline extern inline
|
||||||
|
#else
|
||||||
|
# define av_extern_inline inline
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if AV_GCC_VERSION_AT_LEAST(3,4)
|
||||||
|
# define av_warn_unused_result __attribute__((warn_unused_result))
|
||||||
|
#else
|
||||||
|
# define av_warn_unused_result
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if AV_GCC_VERSION_AT_LEAST(3,1)
|
||||||
|
# define av_noinline __attribute__((noinline))
|
||||||
|
#elif defined(_MSC_VER)
|
||||||
|
# define av_noinline __declspec(noinline)
|
||||||
|
#else
|
||||||
|
# define av_noinline
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if AV_GCC_VERSION_AT_LEAST(3,1)
|
||||||
|
# define av_pure __attribute__((pure))
|
||||||
|
#else
|
||||||
|
# define av_pure
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if AV_GCC_VERSION_AT_LEAST(2,6)
|
||||||
|
# define av_const __attribute__((const))
|
||||||
|
#else
|
||||||
|
# define av_const
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if AV_GCC_VERSION_AT_LEAST(4,3)
|
||||||
|
# define av_cold __attribute__((cold))
|
||||||
|
#else
|
||||||
|
# define av_cold
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if AV_GCC_VERSION_AT_LEAST(4,1) && !defined(__llvm__)
|
||||||
|
# define av_flatten __attribute__((flatten))
|
||||||
|
#else
|
||||||
|
# define av_flatten
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if AV_GCC_VERSION_AT_LEAST(3,1)
|
||||||
|
# define attribute_deprecated __attribute__((deprecated))
|
||||||
|
#elif defined(_MSC_VER)
|
||||||
|
# define attribute_deprecated __declspec(deprecated)
|
||||||
|
#else
|
||||||
|
# define attribute_deprecated
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Disable warnings about deprecated features
|
||||||
|
* This is useful for sections of code kept for backward compatibility and
|
||||||
|
* scheduled for removal.
|
||||||
|
*/
|
||||||
|
#ifndef AV_NOWARN_DEPRECATED
|
||||||
|
#if AV_GCC_VERSION_AT_LEAST(4,6)
|
||||||
|
# define AV_NOWARN_DEPRECATED(code) \
|
||||||
|
_Pragma("GCC diagnostic push") \
|
||||||
|
_Pragma("GCC diagnostic ignored \"-Wdeprecated-declarations\"") \
|
||||||
|
code \
|
||||||
|
_Pragma("GCC diagnostic pop")
|
||||||
|
#elif defined(_MSC_VER)
|
||||||
|
# define AV_NOWARN_DEPRECATED(code) \
|
||||||
|
__pragma(warning(push)) \
|
||||||
|
__pragma(warning(disable : 4996)) \
|
||||||
|
code; \
|
||||||
|
__pragma(warning(pop))
|
||||||
|
#else
|
||||||
|
# define AV_NOWARN_DEPRECATED(code) code
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#if defined(__GNUC__)
|
||||||
|
# define av_unused __attribute__((unused))
|
||||||
|
#else
|
||||||
|
# define av_unused
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Mark a variable as used and prevent the compiler from optimizing it
|
||||||
|
* away. This is useful for variables accessed only from inline
|
||||||
|
* assembler without the compiler being aware.
|
||||||
|
*/
|
||||||
|
#if AV_GCC_VERSION_AT_LEAST(3,1)
|
||||||
|
# define av_used __attribute__((used))
|
||||||
|
#else
|
||||||
|
# define av_used
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if AV_GCC_VERSION_AT_LEAST(3,3)
|
||||||
|
# define av_alias __attribute__((may_alias))
|
||||||
|
#else
|
||||||
|
# define av_alias
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(__GNUC__) && !defined(__INTEL_COMPILER) && !defined(__clang__)
|
||||||
|
# define av_uninit(x) x=x
|
||||||
|
#else
|
||||||
|
# define av_uninit(x) x
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef __GNUC__
|
||||||
|
# define av_builtin_constant_p __builtin_constant_p
|
||||||
|
# define av_printf_format(fmtpos, attrpos) __attribute__((__format__(__printf__, fmtpos, attrpos)))
|
||||||
|
#else
|
||||||
|
# define av_builtin_constant_p(x) 0
|
||||||
|
# define av_printf_format(fmtpos, attrpos)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if AV_GCC_VERSION_AT_LEAST(2,5)
|
||||||
|
# define av_noreturn __attribute__((noreturn))
|
||||||
|
#else
|
||||||
|
# define av_noreturn
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* AVUTIL_ATTRIBUTES_H */
|
@ -0,0 +1,169 @@
|
|||||||
|
/*
|
||||||
|
* Audio FIFO
|
||||||
|
* Copyright (c) 2012 Justin Ruggles <justin.ruggles@gmail.com>
|
||||||
|
*
|
||||||
|
* This file is part of FFmpeg.
|
||||||
|
*
|
||||||
|
* FFmpeg is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2.1 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* FFmpeg is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with FFmpeg; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @file
|
||||||
|
* Audio FIFO Buffer
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef AVUTIL_AUDIO_FIFO_H
|
||||||
|
#define AVUTIL_AUDIO_FIFO_H
|
||||||
|
|
||||||
|
#include "avutil.h"
|
||||||
|
#include "fifo.h"
|
||||||
|
#include "samplefmt.h"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @addtogroup lavu_audio
|
||||||
|
* @{
|
||||||
|
*
|
||||||
|
* @defgroup lavu_audiofifo Audio FIFO Buffer
|
||||||
|
* @{
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Context for an Audio FIFO Buffer.
|
||||||
|
*
|
||||||
|
* - Operates at the sample level rather than the byte level.
|
||||||
|
* - Supports multiple channels with either planar or packed sample format.
|
||||||
|
* - Automatic reallocation when writing to a full buffer.
|
||||||
|
*/
|
||||||
|
typedef struct AVAudioFifo AVAudioFifo;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Free an AVAudioFifo.
|
||||||
|
*
|
||||||
|
* @param af AVAudioFifo to free
|
||||||
|
*/
|
||||||
|
void av_audio_fifo_free(AVAudioFifo *af);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Allocate an AVAudioFifo.
|
||||||
|
*
|
||||||
|
* @param sample_fmt sample format
|
||||||
|
* @param channels number of channels
|
||||||
|
* @param nb_samples initial allocation size, in samples
|
||||||
|
* @return newly allocated AVAudioFifo, or NULL on error
|
||||||
|
*/
|
||||||
|
AVAudioFifo *av_audio_fifo_alloc(enum AVSampleFormat sample_fmt, int channels,
|
||||||
|
int nb_samples);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reallocate an AVAudioFifo.
|
||||||
|
*
|
||||||
|
* @param af AVAudioFifo to reallocate
|
||||||
|
* @param nb_samples new allocation size, in samples
|
||||||
|
* @return 0 if OK, or negative AVERROR code on failure
|
||||||
|
*/
|
||||||
|
int av_audio_fifo_realloc(AVAudioFifo *af, int nb_samples);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Write data to an AVAudioFifo.
|
||||||
|
*
|
||||||
|
* The AVAudioFifo will be reallocated automatically if the available space
|
||||||
|
* is less than nb_samples.
|
||||||
|
*
|
||||||
|
* @see enum AVSampleFormat
|
||||||
|
* The documentation for AVSampleFormat describes the data layout.
|
||||||
|
*
|
||||||
|
* @param af AVAudioFifo to write to
|
||||||
|
* @param data audio data plane pointers
|
||||||
|
* @param nb_samples number of samples to write
|
||||||
|
* @return number of samples actually written, or negative AVERROR
|
||||||
|
* code on failure. If successful, the number of samples
|
||||||
|
* actually written will always be nb_samples.
|
||||||
|
*/
|
||||||
|
int av_audio_fifo_write(AVAudioFifo *af, void **data, int nb_samples);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Peek data from an AVAudioFifo.
|
||||||
|
*
|
||||||
|
* @see enum AVSampleFormat
|
||||||
|
* The documentation for AVSampleFormat describes the data layout.
|
||||||
|
*
|
||||||
|
* @param af AVAudioFifo to read from
|
||||||
|
* @param data audio data plane pointers
|
||||||
|
* @param nb_samples number of samples to peek
|
||||||
|
* @return number of samples actually peek, or negative AVERROR code
|
||||||
|
* on failure. The number of samples actually peek will not
|
||||||
|
* be greater than nb_samples, and will only be less than
|
||||||
|
* nb_samples if av_audio_fifo_size is less than nb_samples.
|
||||||
|
*/
|
||||||
|
int av_audio_fifo_peek(AVAudioFifo *af, void **data, int nb_samples);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Read data from an AVAudioFifo.
|
||||||
|
*
|
||||||
|
* @see enum AVSampleFormat
|
||||||
|
* The documentation for AVSampleFormat describes the data layout.
|
||||||
|
*
|
||||||
|
* @param af AVAudioFifo to read from
|
||||||
|
* @param data audio data plane pointers
|
||||||
|
* @param nb_samples number of samples to read
|
||||||
|
* @return number of samples actually read, or negative AVERROR code
|
||||||
|
* on failure. The number of samples actually read will not
|
||||||
|
* be greater than nb_samples, and will only be less than
|
||||||
|
* nb_samples if av_audio_fifo_size is less than nb_samples.
|
||||||
|
*/
|
||||||
|
int av_audio_fifo_read(AVAudioFifo *af, void **data, int nb_samples);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Drain data from an AVAudioFifo.
|
||||||
|
*
|
||||||
|
* Removes the data without reading it.
|
||||||
|
*
|
||||||
|
* @param af AVAudioFifo to drain
|
||||||
|
* @param nb_samples number of samples to drain
|
||||||
|
* @return 0 if OK, or negative AVERROR code on failure
|
||||||
|
*/
|
||||||
|
int av_audio_fifo_drain(AVAudioFifo *af, int nb_samples);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reset the AVAudioFifo buffer.
|
||||||
|
*
|
||||||
|
* This empties all data in the buffer.
|
||||||
|
*
|
||||||
|
* @param af AVAudioFifo to reset
|
||||||
|
*/
|
||||||
|
void av_audio_fifo_reset(AVAudioFifo *af);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the current number of samples in the AVAudioFifo available for reading.
|
||||||
|
*
|
||||||
|
* @param af the AVAudioFifo to query
|
||||||
|
* @return number of samples available for reading
|
||||||
|
*/
|
||||||
|
int av_audio_fifo_size(AVAudioFifo *af);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the current number of samples in the AVAudioFifo available for writing.
|
||||||
|
*
|
||||||
|
* @param af the AVAudioFifo to query
|
||||||
|
* @return number of samples available for writing
|
||||||
|
*/
|
||||||
|
int av_audio_fifo_space(AVAudioFifo *af);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @}
|
||||||
|
* @}
|
||||||
|
*/
|
||||||
|
|
||||||
|
#endif /* AVUTIL_AUDIO_FIFO_H */
|
@ -0,0 +1,66 @@
|
|||||||
|
/*
|
||||||
|
* copyright (c) 2010 Michael Niedermayer <michaelni@gmx.at>
|
||||||
|
*
|
||||||
|
* This file is part of FFmpeg.
|
||||||
|
*
|
||||||
|
* FFmpeg is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2.1 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* FFmpeg is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with FFmpeg; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @file
|
||||||
|
* simple assert() macros that are a bit more flexible than ISO C assert().
|
||||||
|
* @author Michael Niedermayer <michaelni@gmx.at>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef AVUTIL_AVASSERT_H
|
||||||
|
#define AVUTIL_AVASSERT_H
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include "avutil.h"
|
||||||
|
#include "log.h"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* assert() equivalent, that is always enabled.
|
||||||
|
*/
|
||||||
|
#define av_assert0(cond) do { \
|
||||||
|
if (!(cond)) { \
|
||||||
|
av_log(NULL, AV_LOG_PANIC, "Assertion %s failed at %s:%d\n", \
|
||||||
|
AV_STRINGIFY(cond), __FILE__, __LINE__); \
|
||||||
|
abort(); \
|
||||||
|
} \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* assert() equivalent, that does not lie in speed critical code.
|
||||||
|
* These asserts() thus can be enabled without fearing speedloss.
|
||||||
|
*/
|
||||||
|
#if defined(ASSERT_LEVEL) && ASSERT_LEVEL > 0
|
||||||
|
#define av_assert1(cond) av_assert0(cond)
|
||||||
|
#else
|
||||||
|
#define av_assert1(cond) ((void)0)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* assert() equivalent, that does lie in speed critical code.
|
||||||
|
*/
|
||||||
|
#if defined(ASSERT_LEVEL) && ASSERT_LEVEL > 1
|
||||||
|
#define av_assert2(cond) av_assert0(cond)
|
||||||
|
#else
|
||||||
|
#define av_assert2(cond) ((void)0)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* AVUTIL_AVASSERT_H */
|
@ -0,0 +1,7 @@
|
|||||||
|
/* Generated by ffconf */
|
||||||
|
#ifndef AVUTIL_AVCONFIG_H
|
||||||
|
#define AVUTIL_AVCONFIG_H
|
||||||
|
#define AV_HAVE_BIGENDIAN 0
|
||||||
|
#define AV_HAVE_FAST_UNALIGNED 1
|
||||||
|
#define AV_HAVE_INCOMPATIBLE_LIBAV_ABI 0
|
||||||
|
#endif /* AVUTIL_AVCONFIG_H */
|
@ -0,0 +1,395 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2007 Mans Rullgard
|
||||||
|
*
|
||||||
|
* This file is part of FFmpeg.
|
||||||
|
*
|
||||||
|
* FFmpeg is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2.1 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* FFmpeg is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with FFmpeg; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef AVUTIL_AVSTRING_H
|
||||||
|
#define AVUTIL_AVSTRING_H
|
||||||
|
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include "attributes.h"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @addtogroup lavu_string
|
||||||
|
* @{
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return non-zero if pfx is a prefix of str. If it is, *ptr is set to
|
||||||
|
* the address of the first character in str after the prefix.
|
||||||
|
*
|
||||||
|
* @param str input string
|
||||||
|
* @param pfx prefix to test
|
||||||
|
* @param ptr updated if the prefix is matched inside str
|
||||||
|
* @return non-zero if the prefix matches, zero otherwise
|
||||||
|
*/
|
||||||
|
int av_strstart(const char *str, const char *pfx, const char **ptr);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return non-zero if pfx is a prefix of str independent of case. If
|
||||||
|
* it is, *ptr is set to the address of the first character in str
|
||||||
|
* after the prefix.
|
||||||
|
*
|
||||||
|
* @param str input string
|
||||||
|
* @param pfx prefix to test
|
||||||
|
* @param ptr updated if the prefix is matched inside str
|
||||||
|
* @return non-zero if the prefix matches, zero otherwise
|
||||||
|
*/
|
||||||
|
int av_stristart(const char *str, const char *pfx, const char **ptr);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Locate the first case-independent occurrence in the string haystack
|
||||||
|
* of the string needle. A zero-length string needle is considered to
|
||||||
|
* match at the start of haystack.
|
||||||
|
*
|
||||||
|
* This function is a case-insensitive version of the standard strstr().
|
||||||
|
*
|
||||||
|
* @param haystack string to search in
|
||||||
|
* @param needle string to search for
|
||||||
|
* @return pointer to the located match within haystack
|
||||||
|
* or a null pointer if no match
|
||||||
|
*/
|
||||||
|
char *av_stristr(const char *haystack, const char *needle);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Locate the first occurrence of the string needle in the string haystack
|
||||||
|
* where not more than hay_length characters are searched. A zero-length
|
||||||
|
* string needle is considered to match at the start of haystack.
|
||||||
|
*
|
||||||
|
* This function is a length-limited version of the standard strstr().
|
||||||
|
*
|
||||||
|
* @param haystack string to search in
|
||||||
|
* @param needle string to search for
|
||||||
|
* @param hay_length length of string to search in
|
||||||
|
* @return pointer to the located match within haystack
|
||||||
|
* or a null pointer if no match
|
||||||
|
*/
|
||||||
|
char *av_strnstr(const char *haystack, const char *needle, size_t hay_length);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Copy the string src to dst, but no more than size - 1 bytes, and
|
||||||
|
* null-terminate dst.
|
||||||
|
*
|
||||||
|
* This function is the same as BSD strlcpy().
|
||||||
|
*
|
||||||
|
* @param dst destination buffer
|
||||||
|
* @param src source string
|
||||||
|
* @param size size of destination buffer
|
||||||
|
* @return the length of src
|
||||||
|
*
|
||||||
|
* @warning since the return value is the length of src, src absolutely
|
||||||
|
* _must_ be a properly 0-terminated string, otherwise this will read beyond
|
||||||
|
* the end of the buffer and possibly crash.
|
||||||
|
*/
|
||||||
|
size_t av_strlcpy(char *dst, const char *src, size_t size);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Append the string src to the string dst, but to a total length of
|
||||||
|
* no more than size - 1 bytes, and null-terminate dst.
|
||||||
|
*
|
||||||
|
* This function is similar to BSD strlcat(), but differs when
|
||||||
|
* size <= strlen(dst).
|
||||||
|
*
|
||||||
|
* @param dst destination buffer
|
||||||
|
* @param src source string
|
||||||
|
* @param size size of destination buffer
|
||||||
|
* @return the total length of src and dst
|
||||||
|
*
|
||||||
|
* @warning since the return value use the length of src and dst, these
|
||||||
|
* absolutely _must_ be a properly 0-terminated strings, otherwise this
|
||||||
|
* will read beyond the end of the buffer and possibly crash.
|
||||||
|
*/
|
||||||
|
size_t av_strlcat(char *dst, const char *src, size_t size);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Append output to a string, according to a format. Never write out of
|
||||||
|
* the destination buffer, and always put a terminating 0 within
|
||||||
|
* the buffer.
|
||||||
|
* @param dst destination buffer (string to which the output is
|
||||||
|
* appended)
|
||||||
|
* @param size total size of the destination buffer
|
||||||
|
* @param fmt printf-compatible format string, specifying how the
|
||||||
|
* following parameters are used
|
||||||
|
* @return the length of the string that would have been generated
|
||||||
|
* if enough space had been available
|
||||||
|
*/
|
||||||
|
size_t av_strlcatf(char *dst, size_t size, const char *fmt, ...) av_printf_format(3, 4);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the count of continuous non zero chars starting from the beginning.
|
||||||
|
*
|
||||||
|
* @param len maximum number of characters to check in the string, that
|
||||||
|
* is the maximum value which is returned by the function
|
||||||
|
*/
|
||||||
|
static inline size_t av_strnlen(const char *s, size_t len)
|
||||||
|
{
|
||||||
|
size_t i;
|
||||||
|
for (i = 0; i < len && s[i]; i++)
|
||||||
|
;
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Print arguments following specified format into a large enough auto
|
||||||
|
* allocated buffer. It is similar to GNU asprintf().
|
||||||
|
* @param fmt printf-compatible format string, specifying how the
|
||||||
|
* following parameters are used.
|
||||||
|
* @return the allocated string
|
||||||
|
* @note You have to free the string yourself with av_free().
|
||||||
|
*/
|
||||||
|
char *av_asprintf(const char *fmt, ...) av_printf_format(1, 2);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Convert a number to a av_malloced string.
|
||||||
|
*/
|
||||||
|
char *av_d2str(double d);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Unescape the given string until a non escaped terminating char,
|
||||||
|
* and return the token corresponding to the unescaped string.
|
||||||
|
*
|
||||||
|
* The normal \ and ' escaping is supported. Leading and trailing
|
||||||
|
* whitespaces are removed, unless they are escaped with '\' or are
|
||||||
|
* enclosed between ''.
|
||||||
|
*
|
||||||
|
* @param buf the buffer to parse, buf will be updated to point to the
|
||||||
|
* terminating char
|
||||||
|
* @param term a 0-terminated list of terminating chars
|
||||||
|
* @return the malloced unescaped string, which must be av_freed by
|
||||||
|
* the user, NULL in case of allocation failure
|
||||||
|
*/
|
||||||
|
char *av_get_token(const char **buf, const char *term);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Split the string into several tokens which can be accessed by
|
||||||
|
* successive calls to av_strtok().
|
||||||
|
*
|
||||||
|
* A token is defined as a sequence of characters not belonging to the
|
||||||
|
* set specified in delim.
|
||||||
|
*
|
||||||
|
* On the first call to av_strtok(), s should point to the string to
|
||||||
|
* parse, and the value of saveptr is ignored. In subsequent calls, s
|
||||||
|
* should be NULL, and saveptr should be unchanged since the previous
|
||||||
|
* call.
|
||||||
|
*
|
||||||
|
* This function is similar to strtok_r() defined in POSIX.1.
|
||||||
|
*
|
||||||
|
* @param s the string to parse, may be NULL
|
||||||
|
* @param delim 0-terminated list of token delimiters, must be non-NULL
|
||||||
|
* @param saveptr user-provided pointer which points to stored
|
||||||
|
* information necessary for av_strtok() to continue scanning the same
|
||||||
|
* string. saveptr is updated to point to the next character after the
|
||||||
|
* first delimiter found, or to NULL if the string was terminated
|
||||||
|
* @return the found token, or NULL when no token is found
|
||||||
|
*/
|
||||||
|
char *av_strtok(char *s, const char *delim, char **saveptr);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Locale-independent conversion of ASCII isdigit.
|
||||||
|
*/
|
||||||
|
static inline av_const int av_isdigit(int c)
|
||||||
|
{
|
||||||
|
return c >= '0' && c <= '9';
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Locale-independent conversion of ASCII isgraph.
|
||||||
|
*/
|
||||||
|
static inline av_const int av_isgraph(int c)
|
||||||
|
{
|
||||||
|
return c > 32 && c < 127;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Locale-independent conversion of ASCII isspace.
|
||||||
|
*/
|
||||||
|
static inline av_const int av_isspace(int c)
|
||||||
|
{
|
||||||
|
return c == ' ' || c == '\f' || c == '\n' || c == '\r' || c == '\t' ||
|
||||||
|
c == '\v';
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Locale-independent conversion of ASCII characters to uppercase.
|
||||||
|
*/
|
||||||
|
static inline av_const int av_toupper(int c)
|
||||||
|
{
|
||||||
|
if (c >= 'a' && c <= 'z')
|
||||||
|
c ^= 0x20;
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Locale-independent conversion of ASCII characters to lowercase.
|
||||||
|
*/
|
||||||
|
static inline av_const int av_tolower(int c)
|
||||||
|
{
|
||||||
|
if (c >= 'A' && c <= 'Z')
|
||||||
|
c ^= 0x20;
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Locale-independent conversion of ASCII isxdigit.
|
||||||
|
*/
|
||||||
|
static inline av_const int av_isxdigit(int c)
|
||||||
|
{
|
||||||
|
c = av_tolower(c);
|
||||||
|
return av_isdigit(c) || (c >= 'a' && c <= 'f');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Locale-independent case-insensitive compare.
|
||||||
|
* @note This means only ASCII-range characters are case-insensitive
|
||||||
|
*/
|
||||||
|
int av_strcasecmp(const char *a, const char *b);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Locale-independent case-insensitive compare.
|
||||||
|
* @note This means only ASCII-range characters are case-insensitive
|
||||||
|
*/
|
||||||
|
int av_strncasecmp(const char *a, const char *b, size_t n);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Thread safe basename.
|
||||||
|
* @param path the path, on DOS both \ and / are considered separators.
|
||||||
|
* @return pointer to the basename substring.
|
||||||
|
*/
|
||||||
|
const char *av_basename(const char *path);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Thread safe dirname.
|
||||||
|
* @param path the path, on DOS both \ and / are considered separators.
|
||||||
|
* @return the path with the separator replaced by the string terminator or ".".
|
||||||
|
* @note the function may change the input string.
|
||||||
|
*/
|
||||||
|
const char *av_dirname(char *path);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Match instances of a name in a comma-separated list of names.
|
||||||
|
* @param name Name to look for.
|
||||||
|
* @param names List of names.
|
||||||
|
* @return 1 on match, 0 otherwise.
|
||||||
|
*/
|
||||||
|
int av_match_name(const char *name, const char *names);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Append path component to the existing path.
|
||||||
|
* Path separator '/' is placed between when needed.
|
||||||
|
* Resulting string have to be freed with av_free().
|
||||||
|
* @param path base path
|
||||||
|
* @param component component to be appended
|
||||||
|
* @return new path or NULL on error.
|
||||||
|
*/
|
||||||
|
char *av_append_path_component(const char *path, const char *component);
|
||||||
|
|
||||||
|
enum AVEscapeMode {
|
||||||
|
AV_ESCAPE_MODE_AUTO, ///< Use auto-selected escaping mode.
|
||||||
|
AV_ESCAPE_MODE_BACKSLASH, ///< Use backslash escaping.
|
||||||
|
AV_ESCAPE_MODE_QUOTE, ///< Use single-quote escaping.
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Consider spaces special and escape them even in the middle of the
|
||||||
|
* string.
|
||||||
|
*
|
||||||
|
* This is equivalent to adding the whitespace characters to the special
|
||||||
|
* characters lists, except it is guaranteed to use the exact same list
|
||||||
|
* of whitespace characters as the rest of libavutil.
|
||||||
|
*/
|
||||||
|
#define AV_ESCAPE_FLAG_WHITESPACE (1 << 0)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Escape only specified special characters.
|
||||||
|
* Without this flag, escape also any characters that may be considered
|
||||||
|
* special by av_get_token(), such as the single quote.
|
||||||
|
*/
|
||||||
|
#define AV_ESCAPE_FLAG_STRICT (1 << 1)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Escape string in src, and put the escaped string in an allocated
|
||||||
|
* string in *dst, which must be freed with av_free().
|
||||||
|
*
|
||||||
|
* @param dst pointer where an allocated string is put
|
||||||
|
* @param src string to escape, must be non-NULL
|
||||||
|
* @param special_chars string containing the special characters which
|
||||||
|
* need to be escaped, can be NULL
|
||||||
|
* @param mode escape mode to employ, see AV_ESCAPE_MODE_* macros.
|
||||||
|
* Any unknown value for mode will be considered equivalent to
|
||||||
|
* AV_ESCAPE_MODE_BACKSLASH, but this behaviour can change without
|
||||||
|
* notice.
|
||||||
|
* @param flags flags which control how to escape, see AV_ESCAPE_FLAG_ macros
|
||||||
|
* @return the length of the allocated string, or a negative error code in case of error
|
||||||
|
* @see av_bprint_escape()
|
||||||
|
*/
|
||||||
|
int av_escape(char **dst, const char *src, const char *special_chars,
|
||||||
|
enum AVEscapeMode mode, int flags);
|
||||||
|
|
||||||
|
#define AV_UTF8_FLAG_ACCEPT_INVALID_BIG_CODES 1 ///< accept codepoints over 0x10FFFF
|
||||||
|
#define AV_UTF8_FLAG_ACCEPT_NON_CHARACTERS 2 ///< accept non-characters - 0xFFFE and 0xFFFF
|
||||||
|
#define AV_UTF8_FLAG_ACCEPT_SURROGATES 4 ///< accept UTF-16 surrogates codes
|
||||||
|
#define AV_UTF8_FLAG_EXCLUDE_XML_INVALID_CONTROL_CODES 8 ///< exclude control codes not accepted by XML
|
||||||
|
|
||||||
|
#define AV_UTF8_FLAG_ACCEPT_ALL \
|
||||||
|
AV_UTF8_FLAG_ACCEPT_INVALID_BIG_CODES|AV_UTF8_FLAG_ACCEPT_NON_CHARACTERS|AV_UTF8_FLAG_ACCEPT_SURROGATES
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Read and decode a single UTF-8 code point (character) from the
|
||||||
|
* buffer in *buf, and update *buf to point to the next byte to
|
||||||
|
* decode.
|
||||||
|
*
|
||||||
|
* In case of an invalid byte sequence, the pointer will be updated to
|
||||||
|
* the next byte after the invalid sequence and the function will
|
||||||
|
* return an error code.
|
||||||
|
*
|
||||||
|
* Depending on the specified flags, the function will also fail in
|
||||||
|
* case the decoded code point does not belong to a valid range.
|
||||||
|
*
|
||||||
|
* @note For speed-relevant code a carefully implemented use of
|
||||||
|
* GET_UTF8() may be preferred.
|
||||||
|
*
|
||||||
|
* @param codep pointer used to return the parsed code in case of success.
|
||||||
|
* The value in *codep is set even in case the range check fails.
|
||||||
|
* @param bufp pointer to the address the first byte of the sequence
|
||||||
|
* to decode, updated by the function to point to the
|
||||||
|
* byte next after the decoded sequence
|
||||||
|
* @param buf_end pointer to the end of the buffer, points to the next
|
||||||
|
* byte past the last in the buffer. This is used to
|
||||||
|
* avoid buffer overreads (in case of an unfinished
|
||||||
|
* UTF-8 sequence towards the end of the buffer).
|
||||||
|
* @param flags a collection of AV_UTF8_FLAG_* flags
|
||||||
|
* @return >= 0 in case a sequence was successfully read, a negative
|
||||||
|
* value in case of invalid sequence
|
||||||
|
*/
|
||||||
|
int av_utf8_decode(int32_t *codep, const uint8_t **bufp, const uint8_t *buf_end,
|
||||||
|
unsigned int flags);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if a name is in a list.
|
||||||
|
* @returns 0 if not found, or the 1 based index where it has been found in the
|
||||||
|
* list.
|
||||||
|
*/
|
||||||
|
int av_match_list(const char *name, const char *list, char separator);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @}
|
||||||
|
*/
|
||||||
|
|
||||||
|
#endif /* AVUTIL_AVSTRING_H */
|
@ -0,0 +1,343 @@
|
|||||||
|
/*
|
||||||
|
* copyright (c) 2006 Michael Niedermayer <michaelni@gmx.at>
|
||||||
|
*
|
||||||
|
* This file is part of FFmpeg.
|
||||||
|
*
|
||||||
|
* FFmpeg is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2.1 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* FFmpeg is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with FFmpeg; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef AVUTIL_AVUTIL_H
|
||||||
|
#define AVUTIL_AVUTIL_H
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @file
|
||||||
|
* external API header
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @mainpage
|
||||||
|
*
|
||||||
|
* @section ffmpeg_intro Introduction
|
||||||
|
*
|
||||||
|
* This document describes the usage of the different libraries
|
||||||
|
* provided by FFmpeg.
|
||||||
|
*
|
||||||
|
* @li @ref libavc "libavcodec" encoding/decoding library
|
||||||
|
* @li @ref lavfi "libavfilter" graph-based frame editing library
|
||||||
|
* @li @ref libavf "libavformat" I/O and muxing/demuxing library
|
||||||
|
* @li @ref lavd "libavdevice" special devices muxing/demuxing library
|
||||||
|
* @li @ref lavu "libavutil" common utility library
|
||||||
|
* @li @ref lswr "libswresample" audio resampling, format conversion and mixing
|
||||||
|
* @li @ref lpp "libpostproc" post processing library
|
||||||
|
* @li @ref libsws "libswscale" color conversion and scaling library
|
||||||
|
*
|
||||||
|
* @section ffmpeg_versioning Versioning and compatibility
|
||||||
|
*
|
||||||
|
* Each of the FFmpeg libraries contains a version.h header, which defines a
|
||||||
|
* major, minor and micro version number with the
|
||||||
|
* <em>LIBRARYNAME_VERSION_{MAJOR,MINOR,MICRO}</em> macros. The major version
|
||||||
|
* number is incremented with backward incompatible changes - e.g. removing
|
||||||
|
* parts of the public API, reordering public struct members, etc. The minor
|
||||||
|
* version number is incremented for backward compatible API changes or major
|
||||||
|
* new features - e.g. adding a new public function or a new decoder. The micro
|
||||||
|
* version number is incremented for smaller changes that a calling program
|
||||||
|
* might still want to check for - e.g. changing behavior in a previously
|
||||||
|
* unspecified situation.
|
||||||
|
*
|
||||||
|
* FFmpeg guarantees backward API and ABI compatibility for each library as long
|
||||||
|
* as its major version number is unchanged. This means that no public symbols
|
||||||
|
* will be removed or renamed. Types and names of the public struct members and
|
||||||
|
* values of public macros and enums will remain the same (unless they were
|
||||||
|
* explicitly declared as not part of the public API). Documented behavior will
|
||||||
|
* not change.
|
||||||
|
*
|
||||||
|
* In other words, any correct program that works with a given FFmpeg snapshot
|
||||||
|
* should work just as well without any changes with any later snapshot with the
|
||||||
|
* same major versions. This applies to both rebuilding the program against new
|
||||||
|
* FFmpeg versions or to replacing the dynamic FFmpeg libraries that a program
|
||||||
|
* links against.
|
||||||
|
*
|
||||||
|
* However, new public symbols may be added and new members may be appended to
|
||||||
|
* public structs whose size is not part of public ABI (most public structs in
|
||||||
|
* FFmpeg). New macros and enum values may be added. Behavior in undocumented
|
||||||
|
* situations may change slightly (and be documented). All those are accompanied
|
||||||
|
* by an entry in doc/APIchanges and incrementing either the minor or micro
|
||||||
|
* version number.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @defgroup lavu Common utility functions
|
||||||
|
*
|
||||||
|
* @brief
|
||||||
|
* libavutil contains the code shared across all the other FFmpeg
|
||||||
|
* libraries
|
||||||
|
*
|
||||||
|
* @note In order to use the functions provided by avutil you must include
|
||||||
|
* the specific header.
|
||||||
|
*
|
||||||
|
* @{
|
||||||
|
*
|
||||||
|
* @defgroup lavu_crypto Crypto and Hashing
|
||||||
|
*
|
||||||
|
* @{
|
||||||
|
* @}
|
||||||
|
*
|
||||||
|
* @defgroup lavu_math Maths
|
||||||
|
* @{
|
||||||
|
*
|
||||||
|
* @}
|
||||||
|
*
|
||||||
|
* @defgroup lavu_string String Manipulation
|
||||||
|
*
|
||||||
|
* @{
|
||||||
|
*
|
||||||
|
* @}
|
||||||
|
*
|
||||||
|
* @defgroup lavu_mem Memory Management
|
||||||
|
*
|
||||||
|
* @{
|
||||||
|
*
|
||||||
|
* @}
|
||||||
|
*
|
||||||
|
* @defgroup lavu_data Data Structures
|
||||||
|
* @{
|
||||||
|
*
|
||||||
|
* @}
|
||||||
|
*
|
||||||
|
* @defgroup lavu_audio Audio related
|
||||||
|
*
|
||||||
|
* @{
|
||||||
|
*
|
||||||
|
* @}
|
||||||
|
*
|
||||||
|
* @defgroup lavu_error Error Codes
|
||||||
|
*
|
||||||
|
* @{
|
||||||
|
*
|
||||||
|
* @}
|
||||||
|
*
|
||||||
|
* @defgroup lavu_log Logging Facility
|
||||||
|
*
|
||||||
|
* @{
|
||||||
|
*
|
||||||
|
* @}
|
||||||
|
*
|
||||||
|
* @defgroup lavu_misc Other
|
||||||
|
*
|
||||||
|
* @{
|
||||||
|
*
|
||||||
|
* @defgroup preproc_misc Preprocessor String Macros
|
||||||
|
*
|
||||||
|
* @{
|
||||||
|
*
|
||||||
|
* @}
|
||||||
|
*
|
||||||
|
* @defgroup version_utils Library Version Macros
|
||||||
|
*
|
||||||
|
* @{
|
||||||
|
*
|
||||||
|
* @}
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @addtogroup lavu_ver
|
||||||
|
* @{
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the LIBAVUTIL_VERSION_INT constant.
|
||||||
|
*/
|
||||||
|
unsigned avutil_version(void);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return an informative version string. This usually is the actual release
|
||||||
|
* version number or a git commit description. This string has no fixed format
|
||||||
|
* and can change any time. It should never be parsed by code.
|
||||||
|
*/
|
||||||
|
const char *av_version_info(void);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the libavutil build-time configuration.
|
||||||
|
*/
|
||||||
|
const char *avutil_configuration(void);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the libavutil license.
|
||||||
|
*/
|
||||||
|
const char *avutil_license(void);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @}
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @addtogroup lavu_media Media Type
|
||||||
|
* @brief Media Type
|
||||||
|
*/
|
||||||
|
|
||||||
|
enum AVMediaType {
|
||||||
|
AVMEDIA_TYPE_UNKNOWN = -1, ///< Usually treated as AVMEDIA_TYPE_DATA
|
||||||
|
AVMEDIA_TYPE_VIDEO,
|
||||||
|
AVMEDIA_TYPE_AUDIO,
|
||||||
|
AVMEDIA_TYPE_DATA, ///< Opaque data information usually continuous
|
||||||
|
AVMEDIA_TYPE_SUBTITLE,
|
||||||
|
AVMEDIA_TYPE_ATTACHMENT, ///< Opaque data information usually sparse
|
||||||
|
AVMEDIA_TYPE_NB
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return a string describing the media_type enum, NULL if media_type
|
||||||
|
* is unknown.
|
||||||
|
*/
|
||||||
|
const char *av_get_media_type_string(enum AVMediaType media_type);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @defgroup lavu_const Constants
|
||||||
|
* @{
|
||||||
|
*
|
||||||
|
* @defgroup lavu_enc Encoding specific
|
||||||
|
*
|
||||||
|
* @note those definition should move to avcodec
|
||||||
|
* @{
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define FF_LAMBDA_SHIFT 7
|
||||||
|
#define FF_LAMBDA_SCALE (1<<FF_LAMBDA_SHIFT)
|
||||||
|
#define FF_QP2LAMBDA 118 ///< factor to convert from H.263 QP to lambda
|
||||||
|
#define FF_LAMBDA_MAX (256*128-1)
|
||||||
|
|
||||||
|
#define FF_QUALITY_SCALE FF_LAMBDA_SCALE //FIXME maybe remove
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @}
|
||||||
|
* @defgroup lavu_time Timestamp specific
|
||||||
|
*
|
||||||
|
* FFmpeg internal timebase and timestamp definitions
|
||||||
|
*
|
||||||
|
* @{
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Undefined timestamp value
|
||||||
|
*
|
||||||
|
* Usually reported by demuxer that work on containers that do not provide
|
||||||
|
* either pts or dts.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define AV_NOPTS_VALUE ((int64_t)UINT64_C(0x8000000000000000))
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Internal time base represented as integer
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define AV_TIME_BASE 1000000
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Internal time base represented as fractional value
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define AV_TIME_BASE_Q (AVRational){1, AV_TIME_BASE}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @}
|
||||||
|
* @}
|
||||||
|
* @defgroup lavu_picture Image related
|
||||||
|
*
|
||||||
|
* AVPicture types, pixel formats and basic image planes manipulation.
|
||||||
|
*
|
||||||
|
* @{
|
||||||
|
*/
|
||||||
|
|
||||||
|
enum AVPictureType {
|
||||||
|
AV_PICTURE_TYPE_NONE = 0, ///< Undefined
|
||||||
|
AV_PICTURE_TYPE_I, ///< Intra
|
||||||
|
AV_PICTURE_TYPE_P, ///< Predicted
|
||||||
|
AV_PICTURE_TYPE_B, ///< Bi-dir predicted
|
||||||
|
AV_PICTURE_TYPE_S, ///< S(GMC)-VOP MPEG4
|
||||||
|
AV_PICTURE_TYPE_SI, ///< Switching Intra
|
||||||
|
AV_PICTURE_TYPE_SP, ///< Switching Predicted
|
||||||
|
AV_PICTURE_TYPE_BI, ///< BI type
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return a single letter to describe the given picture type
|
||||||
|
* pict_type.
|
||||||
|
*
|
||||||
|
* @param[in] pict_type the picture type @return a single character
|
||||||
|
* representing the picture type, '?' if pict_type is unknown
|
||||||
|
*/
|
||||||
|
char av_get_picture_type_char(enum AVPictureType pict_type);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @}
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "common.h"
|
||||||
|
#include "error.h"
|
||||||
|
#include "rational.h"
|
||||||
|
#include "version.h"
|
||||||
|
#include "macros.h"
|
||||||
|
#include "mathematics.h"
|
||||||
|
#include "log.h"
|
||||||
|
#include "pixfmt.h"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return x default pointer in case p is NULL.
|
||||||
|
*/
|
||||||
|
static inline void *av_x_if_null(const void *p, const void *x)
|
||||||
|
{
|
||||||
|
return (void *)(intptr_t)(p ? p : x);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Compute the length of an integer list.
|
||||||
|
*
|
||||||
|
* @param elsize size in bytes of each list element (only 1, 2, 4 or 8)
|
||||||
|
* @param term list terminator (usually 0 or -1)
|
||||||
|
* @param list pointer to the list
|
||||||
|
* @return length of the list, in elements, not counting the terminator
|
||||||
|
*/
|
||||||
|
unsigned av_int_list_length_for_size(unsigned elsize,
|
||||||
|
const void *list, uint64_t term) av_pure;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Compute the length of an integer list.
|
||||||
|
*
|
||||||
|
* @param term list terminator (usually 0 or -1)
|
||||||
|
* @param list pointer to the list
|
||||||
|
* @return length of the list, in elements, not counting the terminator
|
||||||
|
*/
|
||||||
|
#define av_int_list_length(list, term) \
|
||||||
|
av_int_list_length_for_size(sizeof(*(list)), list, term)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Open a file using a UTF-8 filename.
|
||||||
|
* The API of this function matches POSIX fopen(), errors are returned through
|
||||||
|
* errno.
|
||||||
|
*/
|
||||||
|
FILE *av_fopen_utf8(const char *path, const char *mode);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the fractional representation of the internal time base.
|
||||||
|
*/
|
||||||
|
AVRational av_get_time_base_q(void);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @}
|
||||||
|
* @}
|
||||||
|
*/
|
||||||
|
|
||||||
|
#endif /* AVUTIL_AVUTIL_H */
|
@ -0,0 +1,67 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2006 Ryan Martell. (rdm4@martellventures.com)
|
||||||
|
*
|
||||||
|
* This file is part of FFmpeg.
|
||||||
|
*
|
||||||
|
* FFmpeg is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2.1 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* FFmpeg is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with FFmpeg; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef AVUTIL_BASE64_H
|
||||||
|
#define AVUTIL_BASE64_H
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @defgroup lavu_base64 Base64
|
||||||
|
* @ingroup lavu_crypto
|
||||||
|
* @{
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Decode a base64-encoded string.
|
||||||
|
*
|
||||||
|
* @param out buffer for decoded data
|
||||||
|
* @param in null-terminated input string
|
||||||
|
* @param out_size size in bytes of the out buffer, must be at
|
||||||
|
* least 3/4 of the length of in
|
||||||
|
* @return number of bytes written, or a negative value in case of
|
||||||
|
* invalid input
|
||||||
|
*/
|
||||||
|
int av_base64_decode(uint8_t *out, const char *in, int out_size);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Encode data to base64 and null-terminate.
|
||||||
|
*
|
||||||
|
* @param out buffer for encoded data
|
||||||
|
* @param out_size size in bytes of the out buffer (including the
|
||||||
|
* null terminator), must be at least AV_BASE64_SIZE(in_size)
|
||||||
|
* @param in input buffer containing the data to encode
|
||||||
|
* @param in_size size in bytes of the in buffer
|
||||||
|
* @return out or NULL in case of error
|
||||||
|
*/
|
||||||
|
char *av_base64_encode(char *out, int out_size, const uint8_t *in, int in_size);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Calculate the output size needed to base64-encode x bytes to a
|
||||||
|
* null-terminated string.
|
||||||
|
*/
|
||||||
|
#define AV_BASE64_SIZE(x) (((x)+2) / 3 * 4 + 1)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @}
|
||||||
|
*/
|
||||||
|
|
||||||
|
#endif /* AVUTIL_BASE64_H */
|
@ -0,0 +1,87 @@
|
|||||||
|
/*
|
||||||
|
* Blowfish algorithm
|
||||||
|
* Copyright (c) 2012 Samuel Pitoiset
|
||||||
|
*
|
||||||
|
* This file is part of FFmpeg.
|
||||||
|
*
|
||||||
|
* FFmpeg is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2.1 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* FFmpeg is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with FFmpeg; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef AVUTIL_BLOWFISH_H
|
||||||
|
#define AVUTIL_BLOWFISH_H
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
#include "version.h"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @defgroup lavu_blowfish Blowfish
|
||||||
|
* @ingroup lavu_crypto
|
||||||
|
* @{
|
||||||
|
*/
|
||||||
|
|
||||||
|
#if FF_API_CRYPTO_CONTEXT
|
||||||
|
#define AV_BF_ROUNDS 16
|
||||||
|
|
||||||
|
typedef struct AVBlowfish {
|
||||||
|
uint32_t p[AV_BF_ROUNDS + 2];
|
||||||
|
uint32_t s[4][256];
|
||||||
|
} AVBlowfish;
|
||||||
|
#else
|
||||||
|
typedef struct AVBlowfish AVBlowfish;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Allocate an AVBlowfish context.
|
||||||
|
*/
|
||||||
|
AVBlowfish *av_blowfish_alloc(void);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initialize an AVBlowfish context.
|
||||||
|
*
|
||||||
|
* @param ctx an AVBlowfish context
|
||||||
|
* @param key a key
|
||||||
|
* @param key_len length of the key
|
||||||
|
*/
|
||||||
|
void av_blowfish_init(struct AVBlowfish *ctx, const uint8_t *key, int key_len);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Encrypt or decrypt a buffer using a previously initialized context.
|
||||||
|
*
|
||||||
|
* @param ctx an AVBlowfish context
|
||||||
|
* @param xl left four bytes halves of input to be encrypted
|
||||||
|
* @param xr right four bytes halves of input to be encrypted
|
||||||
|
* @param decrypt 0 for encryption, 1 for decryption
|
||||||
|
*/
|
||||||
|
void av_blowfish_crypt_ecb(struct AVBlowfish *ctx, uint32_t *xl, uint32_t *xr,
|
||||||
|
int decrypt);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Encrypt or decrypt a buffer using a previously initialized context.
|
||||||
|
*
|
||||||
|
* @param ctx an AVBlowfish context
|
||||||
|
* @param dst destination array, can be equal to src
|
||||||
|
* @param src source array, can be equal to dst
|
||||||
|
* @param count number of 8 byte blocks
|
||||||
|
* @param iv initialization vector for CBC mode, if NULL ECB will be used
|
||||||
|
* @param decrypt 0 for encryption, 1 for decryption
|
||||||
|
*/
|
||||||
|
void av_blowfish_crypt(struct AVBlowfish *ctx, uint8_t *dst, const uint8_t *src,
|
||||||
|
int count, uint8_t *iv, int decrypt);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @}
|
||||||
|
*/
|
||||||
|
|
||||||
|
#endif /* AVUTIL_BLOWFISH_H */
|
@ -0,0 +1,219 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2012 Nicolas George
|
||||||
|
*
|
||||||
|
* This file is part of FFmpeg.
|
||||||
|
*
|
||||||
|
* FFmpeg is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2.1 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* FFmpeg is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with FFmpeg; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef AVUTIL_BPRINT_H
|
||||||
|
#define AVUTIL_BPRINT_H
|
||||||
|
|
||||||
|
#include <stdarg.h>
|
||||||
|
|
||||||
|
#include "attributes.h"
|
||||||
|
#include "avstring.h"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Define a structure with extra padding to a fixed size
|
||||||
|
* This helps ensuring binary compatibility with future versions.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define FF_PAD_STRUCTURE(name, size, ...) \
|
||||||
|
struct ff_pad_helper_##name { __VA_ARGS__ }; \
|
||||||
|
typedef struct name { \
|
||||||
|
__VA_ARGS__ \
|
||||||
|
char reserved_padding[size - sizeof(struct ff_pad_helper_##name)]; \
|
||||||
|
} name;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Buffer to print data progressively
|
||||||
|
*
|
||||||
|
* The string buffer grows as necessary and is always 0-terminated.
|
||||||
|
* The content of the string is never accessed, and thus is
|
||||||
|
* encoding-agnostic and can even hold binary data.
|
||||||
|
*
|
||||||
|
* Small buffers are kept in the structure itself, and thus require no
|
||||||
|
* memory allocation at all (unless the contents of the buffer is needed
|
||||||
|
* after the structure goes out of scope). This is almost as lightweight as
|
||||||
|
* declaring a local "char buf[512]".
|
||||||
|
*
|
||||||
|
* The length of the string can go beyond the allocated size: the buffer is
|
||||||
|
* then truncated, but the functions still keep account of the actual total
|
||||||
|
* length.
|
||||||
|
*
|
||||||
|
* In other words, buf->len can be greater than buf->size and records the
|
||||||
|
* total length of what would have been to the buffer if there had been
|
||||||
|
* enough memory.
|
||||||
|
*
|
||||||
|
* Append operations do not need to be tested for failure: if a memory
|
||||||
|
* allocation fails, data stop being appended to the buffer, but the length
|
||||||
|
* is still updated. This situation can be tested with
|
||||||
|
* av_bprint_is_complete().
|
||||||
|
*
|
||||||
|
* The size_max field determines several possible behaviours:
|
||||||
|
*
|
||||||
|
* size_max = -1 (= UINT_MAX) or any large value will let the buffer be
|
||||||
|
* reallocated as necessary, with an amortized linear cost.
|
||||||
|
*
|
||||||
|
* size_max = 0 prevents writing anything to the buffer: only the total
|
||||||
|
* length is computed. The write operations can then possibly be repeated in
|
||||||
|
* a buffer with exactly the necessary size
|
||||||
|
* (using size_init = size_max = len + 1).
|
||||||
|
*
|
||||||
|
* size_max = 1 is automatically replaced by the exact size available in the
|
||||||
|
* structure itself, thus ensuring no dynamic memory allocation. The
|
||||||
|
* internal buffer is large enough to hold a reasonable paragraph of text,
|
||||||
|
* such as the current paragraph.
|
||||||
|
*/
|
||||||
|
|
||||||
|
FF_PAD_STRUCTURE(AVBPrint, 1024,
|
||||||
|
char *str; /**< string so far */
|
||||||
|
unsigned len; /**< length so far */
|
||||||
|
unsigned size; /**< allocated memory */
|
||||||
|
unsigned size_max; /**< maximum allocated memory */
|
||||||
|
char reserved_internal_buffer[1];
|
||||||
|
)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Convenience macros for special values for av_bprint_init() size_max
|
||||||
|
* parameter.
|
||||||
|
*/
|
||||||
|
#define AV_BPRINT_SIZE_UNLIMITED ((unsigned)-1)
|
||||||
|
#define AV_BPRINT_SIZE_AUTOMATIC 1
|
||||||
|
#define AV_BPRINT_SIZE_COUNT_ONLY 0
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Init a print buffer.
|
||||||
|
*
|
||||||
|
* @param buf buffer to init
|
||||||
|
* @param size_init initial size (including the final 0)
|
||||||
|
* @param size_max maximum size;
|
||||||
|
* 0 means do not write anything, just count the length;
|
||||||
|
* 1 is replaced by the maximum value for automatic storage;
|
||||||
|
* any large value means that the internal buffer will be
|
||||||
|
* reallocated as needed up to that limit; -1 is converted to
|
||||||
|
* UINT_MAX, the largest limit possible.
|
||||||
|
* Check also AV_BPRINT_SIZE_* macros.
|
||||||
|
*/
|
||||||
|
void av_bprint_init(AVBPrint *buf, unsigned size_init, unsigned size_max);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Init a print buffer using a pre-existing buffer.
|
||||||
|
*
|
||||||
|
* The buffer will not be reallocated.
|
||||||
|
*
|
||||||
|
* @param buf buffer structure to init
|
||||||
|
* @param buffer byte buffer to use for the string data
|
||||||
|
* @param size size of buffer
|
||||||
|
*/
|
||||||
|
void av_bprint_init_for_buffer(AVBPrint *buf, char *buffer, unsigned size);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Append a formatted string to a print buffer.
|
||||||
|
*/
|
||||||
|
void av_bprintf(AVBPrint *buf, const char *fmt, ...) av_printf_format(2, 3);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Append a formatted string to a print buffer.
|
||||||
|
*/
|
||||||
|
void av_vbprintf(AVBPrint *buf, const char *fmt, va_list vl_arg);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Append char c n times to a print buffer.
|
||||||
|
*/
|
||||||
|
void av_bprint_chars(AVBPrint *buf, char c, unsigned n);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Append data to a print buffer.
|
||||||
|
*
|
||||||
|
* param buf bprint buffer to use
|
||||||
|
* param data pointer to data
|
||||||
|
* param size size of data
|
||||||
|
*/
|
||||||
|
void av_bprint_append_data(AVBPrint *buf, const char *data, unsigned size);
|
||||||
|
|
||||||
|
struct tm;
|
||||||
|
/**
|
||||||
|
* Append a formatted date and time to a print buffer.
|
||||||
|
*
|
||||||
|
* param buf bprint buffer to use
|
||||||
|
* param fmt date and time format string, see strftime()
|
||||||
|
* param tm broken-down time structure to translate
|
||||||
|
*
|
||||||
|
* @note due to poor design of the standard strftime function, it may
|
||||||
|
* produce poor results if the format string expands to a very long text and
|
||||||
|
* the bprint buffer is near the limit stated by the size_max option.
|
||||||
|
*/
|
||||||
|
void av_bprint_strftime(AVBPrint *buf, const char *fmt, const struct tm *tm);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Allocate bytes in the buffer for external use.
|
||||||
|
*
|
||||||
|
* @param[in] buf buffer structure
|
||||||
|
* @param[in] size required size
|
||||||
|
* @param[out] mem pointer to the memory area
|
||||||
|
* @param[out] actual_size size of the memory area after allocation;
|
||||||
|
* can be larger or smaller than size
|
||||||
|
*/
|
||||||
|
void av_bprint_get_buffer(AVBPrint *buf, unsigned size,
|
||||||
|
unsigned char **mem, unsigned *actual_size);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reset the string to "" but keep internal allocated data.
|
||||||
|
*/
|
||||||
|
void av_bprint_clear(AVBPrint *buf);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test if the print buffer is complete (not truncated).
|
||||||
|
*
|
||||||
|
* It may have been truncated due to a memory allocation failure
|
||||||
|
* or the size_max limit (compare size and size_max if necessary).
|
||||||
|
*/
|
||||||
|
static inline int av_bprint_is_complete(const AVBPrint *buf)
|
||||||
|
{
|
||||||
|
return buf->len < buf->size;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Finalize a print buffer.
|
||||||
|
*
|
||||||
|
* The print buffer can no longer be used afterwards,
|
||||||
|
* but the len and size fields are still valid.
|
||||||
|
*
|
||||||
|
* @arg[out] ret_str if not NULL, used to return a permanent copy of the
|
||||||
|
* buffer contents, or NULL if memory allocation fails;
|
||||||
|
* if NULL, the buffer is discarded and freed
|
||||||
|
* @return 0 for success or error code (probably AVERROR(ENOMEM))
|
||||||
|
*/
|
||||||
|
int av_bprint_finalize(AVBPrint *buf, char **ret_str);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Escape the content in src and append it to dstbuf.
|
||||||
|
*
|
||||||
|
* @param dstbuf already inited destination bprint buffer
|
||||||
|
* @param src string containing the text to escape
|
||||||
|
* @param special_chars string containing the special characters which
|
||||||
|
* need to be escaped, can be NULL
|
||||||
|
* @param mode escape mode to employ, see AV_ESCAPE_MODE_* macros.
|
||||||
|
* Any unknown value for mode will be considered equivalent to
|
||||||
|
* AV_ESCAPE_MODE_BACKSLASH, but this behaviour can change without
|
||||||
|
* notice.
|
||||||
|
* @param flags flags which control how to escape, see AV_ESCAPE_FLAG_* macros
|
||||||
|
*/
|
||||||
|
void av_bprint_escape(AVBPrint *dstbuf, const char *src, const char *special_chars,
|
||||||
|
enum AVEscapeMode mode, int flags);
|
||||||
|
|
||||||
|
#endif /* AVUTIL_BPRINT_H */
|
@ -0,0 +1,109 @@
|
|||||||
|
/*
|
||||||
|
* copyright (c) 2006 Michael Niedermayer <michaelni@gmx.at>
|
||||||
|
*
|
||||||
|
* This file is part of FFmpeg.
|
||||||
|
*
|
||||||
|
* FFmpeg is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2.1 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* FFmpeg is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with FFmpeg; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @file
|
||||||
|
* byte swapping routines
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef AVUTIL_BSWAP_H
|
||||||
|
#define AVUTIL_BSWAP_H
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
#include "libavutil/avconfig.h"
|
||||||
|
#include "attributes.h"
|
||||||
|
|
||||||
|
#ifdef HAVE_AV_CONFIG_H
|
||||||
|
|
||||||
|
#include "config.h"
|
||||||
|
|
||||||
|
#if ARCH_AARCH64
|
||||||
|
# include "aarch64/bswap.h"
|
||||||
|
#elif ARCH_ARM
|
||||||
|
# include "arm/bswap.h"
|
||||||
|
#elif ARCH_AVR32
|
||||||
|
# include "avr32/bswap.h"
|
||||||
|
#elif ARCH_SH4
|
||||||
|
# include "sh4/bswap.h"
|
||||||
|
#elif ARCH_X86
|
||||||
|
# include "x86/bswap.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* HAVE_AV_CONFIG_H */
|
||||||
|
|
||||||
|
#define AV_BSWAP16C(x) (((x) << 8 & 0xff00) | ((x) >> 8 & 0x00ff))
|
||||||
|
#define AV_BSWAP32C(x) (AV_BSWAP16C(x) << 16 | AV_BSWAP16C((x) >> 16))
|
||||||
|
#define AV_BSWAP64C(x) (AV_BSWAP32C(x) << 32 | AV_BSWAP32C((x) >> 32))
|
||||||
|
|
||||||
|
#define AV_BSWAPC(s, x) AV_BSWAP##s##C(x)
|
||||||
|
|
||||||
|
#ifndef av_bswap16
|
||||||
|
static av_always_inline av_const uint16_t av_bswap16(uint16_t x)
|
||||||
|
{
|
||||||
|
x= (x>>8) | (x<<8);
|
||||||
|
return x;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef av_bswap32
|
||||||
|
static av_always_inline av_const uint32_t av_bswap32(uint32_t x)
|
||||||
|
{
|
||||||
|
return AV_BSWAP32C(x);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef av_bswap64
|
||||||
|
static inline uint64_t av_const av_bswap64(uint64_t x)
|
||||||
|
{
|
||||||
|
return (uint64_t)av_bswap32(x) << 32 | av_bswap32(x >> 32);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// be2ne ... big-endian to native-endian
|
||||||
|
// le2ne ... little-endian to native-endian
|
||||||
|
|
||||||
|
#if AV_HAVE_BIGENDIAN
|
||||||
|
#define av_be2ne16(x) (x)
|
||||||
|
#define av_be2ne32(x) (x)
|
||||||
|
#define av_be2ne64(x) (x)
|
||||||
|
#define av_le2ne16(x) av_bswap16(x)
|
||||||
|
#define av_le2ne32(x) av_bswap32(x)
|
||||||
|
#define av_le2ne64(x) av_bswap64(x)
|
||||||
|
#define AV_BE2NEC(s, x) (x)
|
||||||
|
#define AV_LE2NEC(s, x) AV_BSWAPC(s, x)
|
||||||
|
#else
|
||||||
|
#define av_be2ne16(x) av_bswap16(x)
|
||||||
|
#define av_be2ne32(x) av_bswap32(x)
|
||||||
|
#define av_be2ne64(x) av_bswap64(x)
|
||||||
|
#define av_le2ne16(x) (x)
|
||||||
|
#define av_le2ne32(x) (x)
|
||||||
|
#define av_le2ne64(x) (x)
|
||||||
|
#define AV_BE2NEC(s, x) AV_BSWAPC(s, x)
|
||||||
|
#define AV_LE2NEC(s, x) (x)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define AV_BE2NE16C(x) AV_BE2NEC(16, x)
|
||||||
|
#define AV_BE2NE32C(x) AV_BE2NEC(32, x)
|
||||||
|
#define AV_BE2NE64C(x) AV_BE2NEC(64, x)
|
||||||
|
#define AV_LE2NE16C(x) AV_LE2NEC(16, x)
|
||||||
|
#define AV_LE2NE32C(x) AV_LE2NEC(32, x)
|
||||||
|
#define AV_LE2NE64C(x) AV_LE2NEC(64, x)
|
||||||
|
|
||||||
|
#endif /* AVUTIL_BSWAP_H */
|
@ -0,0 +1,274 @@
|
|||||||
|
/*
|
||||||
|
* This file is part of FFmpeg.
|
||||||
|
*
|
||||||
|
* FFmpeg is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2.1 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* FFmpeg is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with FFmpeg; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @file
|
||||||
|
* @ingroup lavu_buffer
|
||||||
|
* refcounted data buffer API
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef AVUTIL_BUFFER_H
|
||||||
|
#define AVUTIL_BUFFER_H
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @defgroup lavu_buffer AVBuffer
|
||||||
|
* @ingroup lavu_data
|
||||||
|
*
|
||||||
|
* @{
|
||||||
|
* AVBuffer is an API for reference-counted data buffers.
|
||||||
|
*
|
||||||
|
* There are two core objects in this API -- AVBuffer and AVBufferRef. AVBuffer
|
||||||
|
* represents the data buffer itself; it is opaque and not meant to be accessed
|
||||||
|
* by the caller directly, but only through AVBufferRef. However, the caller may
|
||||||
|
* e.g. compare two AVBuffer pointers to check whether two different references
|
||||||
|
* are describing the same data buffer. AVBufferRef represents a single
|
||||||
|
* reference to an AVBuffer and it is the object that may be manipulated by the
|
||||||
|
* caller directly.
|
||||||
|
*
|
||||||
|
* There are two functions provided for creating a new AVBuffer with a single
|
||||||
|
* reference -- av_buffer_alloc() to just allocate a new buffer, and
|
||||||
|
* av_buffer_create() to wrap an existing array in an AVBuffer. From an existing
|
||||||
|
* reference, additional references may be created with av_buffer_ref().
|
||||||
|
* Use av_buffer_unref() to free a reference (this will automatically free the
|
||||||
|
* data once all the references are freed).
|
||||||
|
*
|
||||||
|
* The convention throughout this API and the rest of FFmpeg is such that the
|
||||||
|
* buffer is considered writable if there exists only one reference to it (and
|
||||||
|
* it has not been marked as read-only). The av_buffer_is_writable() function is
|
||||||
|
* provided to check whether this is true and av_buffer_make_writable() will
|
||||||
|
* automatically create a new writable buffer when necessary.
|
||||||
|
* Of course nothing prevents the calling code from violating this convention,
|
||||||
|
* however that is safe only when all the existing references are under its
|
||||||
|
* control.
|
||||||
|
*
|
||||||
|
* @note Referencing and unreferencing the buffers is thread-safe and thus
|
||||||
|
* may be done from multiple threads simultaneously without any need for
|
||||||
|
* additional locking.
|
||||||
|
*
|
||||||
|
* @note Two different references to the same buffer can point to different
|
||||||
|
* parts of the buffer (i.e. their AVBufferRef.data will not be equal).
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A reference counted buffer type. It is opaque and is meant to be used through
|
||||||
|
* references (AVBufferRef).
|
||||||
|
*/
|
||||||
|
typedef struct AVBuffer AVBuffer;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A reference to a data buffer.
|
||||||
|
*
|
||||||
|
* The size of this struct is not a part of the public ABI and it is not meant
|
||||||
|
* to be allocated directly.
|
||||||
|
*/
|
||||||
|
typedef struct AVBufferRef {
|
||||||
|
AVBuffer *buffer;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The data buffer. It is considered writable if and only if
|
||||||
|
* this is the only reference to the buffer, in which case
|
||||||
|
* av_buffer_is_writable() returns 1.
|
||||||
|
*/
|
||||||
|
uint8_t *data;
|
||||||
|
/**
|
||||||
|
* Size of data in bytes.
|
||||||
|
*/
|
||||||
|
int size;
|
||||||
|
} AVBufferRef;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Allocate an AVBuffer of the given size using av_malloc().
|
||||||
|
*
|
||||||
|
* @return an AVBufferRef of given size or NULL when out of memory
|
||||||
|
*/
|
||||||
|
AVBufferRef *av_buffer_alloc(int size);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Same as av_buffer_alloc(), except the returned buffer will be initialized
|
||||||
|
* to zero.
|
||||||
|
*/
|
||||||
|
AVBufferRef *av_buffer_allocz(int size);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Always treat the buffer as read-only, even when it has only one
|
||||||
|
* reference.
|
||||||
|
*/
|
||||||
|
#define AV_BUFFER_FLAG_READONLY (1 << 0)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create an AVBuffer from an existing array.
|
||||||
|
*
|
||||||
|
* If this function is successful, data is owned by the AVBuffer. The caller may
|
||||||
|
* only access data through the returned AVBufferRef and references derived from
|
||||||
|
* it.
|
||||||
|
* If this function fails, data is left untouched.
|
||||||
|
* @param data data array
|
||||||
|
* @param size size of data in bytes
|
||||||
|
* @param free a callback for freeing this buffer's data
|
||||||
|
* @param opaque parameter to be got for processing or passed to free
|
||||||
|
* @param flags a combination of AV_BUFFER_FLAG_*
|
||||||
|
*
|
||||||
|
* @return an AVBufferRef referring to data on success, NULL on failure.
|
||||||
|
*/
|
||||||
|
AVBufferRef *av_buffer_create(uint8_t *data, int size,
|
||||||
|
void (*free)(void *opaque, uint8_t *data),
|
||||||
|
void *opaque, int flags);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Default free callback, which calls av_free() on the buffer data.
|
||||||
|
* This function is meant to be passed to av_buffer_create(), not called
|
||||||
|
* directly.
|
||||||
|
*/
|
||||||
|
void av_buffer_default_free(void *opaque, uint8_t *data);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new reference to an AVBuffer.
|
||||||
|
*
|
||||||
|
* @return a new AVBufferRef referring to the same AVBuffer as buf or NULL on
|
||||||
|
* failure.
|
||||||
|
*/
|
||||||
|
AVBufferRef *av_buffer_ref(AVBufferRef *buf);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Free a given reference and automatically free the buffer if there are no more
|
||||||
|
* references to it.
|
||||||
|
*
|
||||||
|
* @param buf the reference to be freed. The pointer is set to NULL on return.
|
||||||
|
*/
|
||||||
|
void av_buffer_unref(AVBufferRef **buf);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return 1 if the caller may write to the data referred to by buf (which is
|
||||||
|
* true if and only if buf is the only reference to the underlying AVBuffer).
|
||||||
|
* Return 0 otherwise.
|
||||||
|
* A positive answer is valid until av_buffer_ref() is called on buf.
|
||||||
|
*/
|
||||||
|
int av_buffer_is_writable(const AVBufferRef *buf);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return the opaque parameter set by av_buffer_create.
|
||||||
|
*/
|
||||||
|
void *av_buffer_get_opaque(const AVBufferRef *buf);
|
||||||
|
|
||||||
|
int av_buffer_get_ref_count(const AVBufferRef *buf);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a writable reference from a given buffer reference, avoiding data copy
|
||||||
|
* if possible.
|
||||||
|
*
|
||||||
|
* @param buf buffer reference to make writable. On success, buf is either left
|
||||||
|
* untouched, or it is unreferenced and a new writable AVBufferRef is
|
||||||
|
* written in its place. On failure, buf is left untouched.
|
||||||
|
* @return 0 on success, a negative AVERROR on failure.
|
||||||
|
*/
|
||||||
|
int av_buffer_make_writable(AVBufferRef **buf);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reallocate a given buffer.
|
||||||
|
*
|
||||||
|
* @param buf a buffer reference to reallocate. On success, buf will be
|
||||||
|
* unreferenced and a new reference with the required size will be
|
||||||
|
* written in its place. On failure buf will be left untouched. *buf
|
||||||
|
* may be NULL, then a new buffer is allocated.
|
||||||
|
* @param size required new buffer size.
|
||||||
|
* @return 0 on success, a negative AVERROR on failure.
|
||||||
|
*
|
||||||
|
* @note the buffer is actually reallocated with av_realloc() only if it was
|
||||||
|
* initially allocated through av_buffer_realloc(NULL) and there is only one
|
||||||
|
* reference to it (i.e. the one passed to this function). In all other cases
|
||||||
|
* a new buffer is allocated and the data is copied.
|
||||||
|
*/
|
||||||
|
int av_buffer_realloc(AVBufferRef **buf, int size);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @}
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @defgroup lavu_bufferpool AVBufferPool
|
||||||
|
* @ingroup lavu_data
|
||||||
|
*
|
||||||
|
* @{
|
||||||
|
* AVBufferPool is an API for a lock-free thread-safe pool of AVBuffers.
|
||||||
|
*
|
||||||
|
* Frequently allocating and freeing large buffers may be slow. AVBufferPool is
|
||||||
|
* meant to solve this in cases when the caller needs a set of buffers of the
|
||||||
|
* same size (the most obvious use case being buffers for raw video or audio
|
||||||
|
* frames).
|
||||||
|
*
|
||||||
|
* At the beginning, the user must call av_buffer_pool_init() to create the
|
||||||
|
* buffer pool. Then whenever a buffer is needed, call av_buffer_pool_get() to
|
||||||
|
* get a reference to a new buffer, similar to av_buffer_alloc(). This new
|
||||||
|
* reference works in all aspects the same way as the one created by
|
||||||
|
* av_buffer_alloc(). However, when the last reference to this buffer is
|
||||||
|
* unreferenced, it is returned to the pool instead of being freed and will be
|
||||||
|
* reused for subsequent av_buffer_pool_get() calls.
|
||||||
|
*
|
||||||
|
* When the caller is done with the pool and no longer needs to allocate any new
|
||||||
|
* buffers, av_buffer_pool_uninit() must be called to mark the pool as freeable.
|
||||||
|
* Once all the buffers are released, it will automatically be freed.
|
||||||
|
*
|
||||||
|
* Allocating and releasing buffers with this API is thread-safe as long as
|
||||||
|
* either the default alloc callback is used, or the user-supplied one is
|
||||||
|
* thread-safe.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The buffer pool. This structure is opaque and not meant to be accessed
|
||||||
|
* directly. It is allocated with av_buffer_pool_init() and freed with
|
||||||
|
* av_buffer_pool_uninit().
|
||||||
|
*/
|
||||||
|
typedef struct AVBufferPool AVBufferPool;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Allocate and initialize a buffer pool.
|
||||||
|
*
|
||||||
|
* @param size size of each buffer in this pool
|
||||||
|
* @param alloc a function that will be used to allocate new buffers when the
|
||||||
|
* pool is empty. May be NULL, then the default allocator will be used
|
||||||
|
* (av_buffer_alloc()).
|
||||||
|
* @return newly created buffer pool on success, NULL on error.
|
||||||
|
*/
|
||||||
|
AVBufferPool *av_buffer_pool_init(int size, AVBufferRef* (*alloc)(int size));
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Mark the pool as being available for freeing. It will actually be freed only
|
||||||
|
* once all the allocated buffers associated with the pool are released. Thus it
|
||||||
|
* is safe to call this function while some of the allocated buffers are still
|
||||||
|
* in use.
|
||||||
|
*
|
||||||
|
* @param pool pointer to the pool to be freed. It will be set to NULL.
|
||||||
|
* @see av_buffer_pool_can_uninit()
|
||||||
|
*/
|
||||||
|
void av_buffer_pool_uninit(AVBufferPool **pool);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Allocate a new AVBuffer, reusing an old buffer from the pool when available.
|
||||||
|
* This function may be called simultaneously from multiple threads.
|
||||||
|
*
|
||||||
|
* @return a reference to the new buffer on success, NULL on error.
|
||||||
|
*/
|
||||||
|
AVBufferRef *av_buffer_pool_get(AVBufferPool *pool);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @}
|
||||||
|
*/
|
||||||
|
|
||||||
|
#endif /* AVUTIL_BUFFER_H */
|
@ -0,0 +1,70 @@
|
|||||||
|
/*
|
||||||
|
* An implementation of the CAMELLIA algorithm as mentioned in RFC3713
|
||||||
|
* Copyright (c) 2014 Supraja Meedinti
|
||||||
|
*
|
||||||
|
* This file is part of FFmpeg.
|
||||||
|
*
|
||||||
|
* FFmpeg is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2.1 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* FFmpeg is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with FFmpeg; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef AVUTIL_CAMELLIA_H
|
||||||
|
#define AVUTIL_CAMELLIA_H
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @file
|
||||||
|
* @brief Public header for libavutil CAMELLIA algorithm
|
||||||
|
* @defgroup lavu_camellia CAMELLIA
|
||||||
|
* @ingroup lavu_crypto
|
||||||
|
* @{
|
||||||
|
*/
|
||||||
|
|
||||||
|
extern const int av_camellia_size;
|
||||||
|
|
||||||
|
struct AVCAMELLIA;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Allocate an AVCAMELLIA context
|
||||||
|
* To free the struct: av_free(ptr)
|
||||||
|
*/
|
||||||
|
struct AVCAMELLIA *av_camellia_alloc(void);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initialize an AVCAMELLIA context.
|
||||||
|
*
|
||||||
|
* @param ctx an AVCAMELLIA context
|
||||||
|
* @param key a key of 16, 24, 32 bytes used for encryption/decryption
|
||||||
|
* @param key_bits number of keybits: possible are 128, 192, 256
|
||||||
|
*/
|
||||||
|
int av_camellia_init(struct AVCAMELLIA *ctx, const uint8_t *key, int key_bits);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Encrypt or decrypt a buffer using a previously initialized context
|
||||||
|
*
|
||||||
|
* @param ctx an AVCAMELLIA context
|
||||||
|
* @param dst destination array, can be equal to src
|
||||||
|
* @param src source array, can be equal to dst
|
||||||
|
* @param count number of 16 byte blocks
|
||||||
|
* @paran iv initialization vector for CBC mode, NULL for ECB mode
|
||||||
|
* @param decrypt 0 for encryption, 1 for decryption
|
||||||
|
*/
|
||||||
|
void av_camellia_crypt(struct AVCAMELLIA *ctx, uint8_t *dst, const uint8_t *src, int count, uint8_t* iv, int decrypt);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @}
|
||||||
|
*/
|
||||||
|
#endif /* AVUTIL_CAMELLIA_H */
|
@ -0,0 +1,79 @@
|
|||||||
|
/*
|
||||||
|
* An implementation of the CAST128 algorithm as mentioned in RFC2144
|
||||||
|
* Copyright (c) 2014 Supraja Meedinti
|
||||||
|
*
|
||||||
|
* This file is part of FFmpeg.
|
||||||
|
*
|
||||||
|
* FFmpeg is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2.1 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* FFmpeg is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with FFmpeg; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef AVUTIL_CAST5_H
|
||||||
|
#define AVUTIL_CAST5_H
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @file
|
||||||
|
* @brief Public header for libavutil CAST5 algorithm
|
||||||
|
* @defgroup lavu_cast5 CAST5
|
||||||
|
* @ingroup lavu_crypto
|
||||||
|
* @{
|
||||||
|
*/
|
||||||
|
|
||||||
|
extern const int av_cast5_size;
|
||||||
|
|
||||||
|
struct AVCAST5;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Allocate an AVCAST5 context
|
||||||
|
* To free the struct: av_free(ptr)
|
||||||
|
*/
|
||||||
|
struct AVCAST5 *av_cast5_alloc(void);
|
||||||
|
/**
|
||||||
|
* Initialize an AVCAST5 context.
|
||||||
|
*
|
||||||
|
* @param ctx an AVCAST5 context
|
||||||
|
* @param key a key of 5,6,...16 bytes used for encryption/decryption
|
||||||
|
* @param key_bits number of keybits: possible are 40,48,...,128
|
||||||
|
*/
|
||||||
|
int av_cast5_init(struct AVCAST5 *ctx, const uint8_t *key, int key_bits);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Encrypt or decrypt a buffer using a previously initialized context, ECB mode only
|
||||||
|
*
|
||||||
|
* @param ctx an AVCAST5 context
|
||||||
|
* @param dst destination array, can be equal to src
|
||||||
|
* @param src source array, can be equal to dst
|
||||||
|
* @param count number of 8 byte blocks
|
||||||
|
* @param decrypt 0 for encryption, 1 for decryption
|
||||||
|
*/
|
||||||
|
void av_cast5_crypt(struct AVCAST5 *ctx, uint8_t *dst, const uint8_t *src, int count, int decrypt);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Encrypt or decrypt a buffer using a previously initialized context
|
||||||
|
*
|
||||||
|
* @param ctx an AVCAST5 context
|
||||||
|
* @param dst destination array, can be equal to src
|
||||||
|
* @param src source array, can be equal to dst
|
||||||
|
* @param count number of 8 byte blocks
|
||||||
|
* @param iv initialization vector for CBC mode, NULL for ECB mode
|
||||||
|
* @param decrypt 0 for encryption, 1 for decryption
|
||||||
|
*/
|
||||||
|
void av_cast5_crypt2(struct AVCAST5 *ctx, uint8_t *dst, const uint8_t *src, int count, uint8_t *iv, int decrypt);
|
||||||
|
/**
|
||||||
|
* @}
|
||||||
|
*/
|
||||||
|
#endif /* AVUTIL_CAST5_H */
|
@ -0,0 +1,223 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2006 Michael Niedermayer <michaelni@gmx.at>
|
||||||
|
* Copyright (c) 2008 Peter Ross
|
||||||
|
*
|
||||||
|
* This file is part of FFmpeg.
|
||||||
|
*
|
||||||
|
* FFmpeg is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2.1 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* FFmpeg is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with FFmpeg; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef AVUTIL_CHANNEL_LAYOUT_H
|
||||||
|
#define AVUTIL_CHANNEL_LAYOUT_H
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @file
|
||||||
|
* audio channel layout utility functions
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @addtogroup lavu_audio
|
||||||
|
* @{
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @defgroup channel_masks Audio channel masks
|
||||||
|
*
|
||||||
|
* A channel layout is a 64-bits integer with a bit set for every channel.
|
||||||
|
* The number of bits set must be equal to the number of channels.
|
||||||
|
* The value 0 means that the channel layout is not known.
|
||||||
|
* @note this data structure is not powerful enough to handle channels
|
||||||
|
* combinations that have the same channel multiple times, such as
|
||||||
|
* dual-mono.
|
||||||
|
*
|
||||||
|
* @{
|
||||||
|
*/
|
||||||
|
#define AV_CH_FRONT_LEFT 0x00000001
|
||||||
|
#define AV_CH_FRONT_RIGHT 0x00000002
|
||||||
|
#define AV_CH_FRONT_CENTER 0x00000004
|
||||||
|
#define AV_CH_LOW_FREQUENCY 0x00000008
|
||||||
|
#define AV_CH_BACK_LEFT 0x00000010
|
||||||
|
#define AV_CH_BACK_RIGHT 0x00000020
|
||||||
|
#define AV_CH_FRONT_LEFT_OF_CENTER 0x00000040
|
||||||
|
#define AV_CH_FRONT_RIGHT_OF_CENTER 0x00000080
|
||||||
|
#define AV_CH_BACK_CENTER 0x00000100
|
||||||
|
#define AV_CH_SIDE_LEFT 0x00000200
|
||||||
|
#define AV_CH_SIDE_RIGHT 0x00000400
|
||||||
|
#define AV_CH_TOP_CENTER 0x00000800
|
||||||
|
#define AV_CH_TOP_FRONT_LEFT 0x00001000
|
||||||
|
#define AV_CH_TOP_FRONT_CENTER 0x00002000
|
||||||
|
#define AV_CH_TOP_FRONT_RIGHT 0x00004000
|
||||||
|
#define AV_CH_TOP_BACK_LEFT 0x00008000
|
||||||
|
#define AV_CH_TOP_BACK_CENTER 0x00010000
|
||||||
|
#define AV_CH_TOP_BACK_RIGHT 0x00020000
|
||||||
|
#define AV_CH_STEREO_LEFT 0x20000000 ///< Stereo downmix.
|
||||||
|
#define AV_CH_STEREO_RIGHT 0x40000000 ///< See AV_CH_STEREO_LEFT.
|
||||||
|
#define AV_CH_WIDE_LEFT 0x0000000080000000ULL
|
||||||
|
#define AV_CH_WIDE_RIGHT 0x0000000100000000ULL
|
||||||
|
#define AV_CH_SURROUND_DIRECT_LEFT 0x0000000200000000ULL
|
||||||
|
#define AV_CH_SURROUND_DIRECT_RIGHT 0x0000000400000000ULL
|
||||||
|
#define AV_CH_LOW_FREQUENCY_2 0x0000000800000000ULL
|
||||||
|
|
||||||
|
/** Channel mask value used for AVCodecContext.request_channel_layout
|
||||||
|
to indicate that the user requests the channel order of the decoder output
|
||||||
|
to be the native codec channel order. */
|
||||||
|
#define AV_CH_LAYOUT_NATIVE 0x8000000000000000ULL
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @}
|
||||||
|
* @defgroup channel_mask_c Audio channel layouts
|
||||||
|
* @{
|
||||||
|
* */
|
||||||
|
#define AV_CH_LAYOUT_MONO (AV_CH_FRONT_CENTER)
|
||||||
|
#define AV_CH_LAYOUT_STEREO (AV_CH_FRONT_LEFT|AV_CH_FRONT_RIGHT)
|
||||||
|
#define AV_CH_LAYOUT_2POINT1 (AV_CH_LAYOUT_STEREO|AV_CH_LOW_FREQUENCY)
|
||||||
|
#define AV_CH_LAYOUT_2_1 (AV_CH_LAYOUT_STEREO|AV_CH_BACK_CENTER)
|
||||||
|
#define AV_CH_LAYOUT_SURROUND (AV_CH_LAYOUT_STEREO|AV_CH_FRONT_CENTER)
|
||||||
|
#define AV_CH_LAYOUT_3POINT1 (AV_CH_LAYOUT_SURROUND|AV_CH_LOW_FREQUENCY)
|
||||||
|
#define AV_CH_LAYOUT_4POINT0 (AV_CH_LAYOUT_SURROUND|AV_CH_BACK_CENTER)
|
||||||
|
#define AV_CH_LAYOUT_4POINT1 (AV_CH_LAYOUT_4POINT0|AV_CH_LOW_FREQUENCY)
|
||||||
|
#define AV_CH_LAYOUT_2_2 (AV_CH_LAYOUT_STEREO|AV_CH_SIDE_LEFT|AV_CH_SIDE_RIGHT)
|
||||||
|
#define AV_CH_LAYOUT_QUAD (AV_CH_LAYOUT_STEREO|AV_CH_BACK_LEFT|AV_CH_BACK_RIGHT)
|
||||||
|
#define AV_CH_LAYOUT_5POINT0 (AV_CH_LAYOUT_SURROUND|AV_CH_SIDE_LEFT|AV_CH_SIDE_RIGHT)
|
||||||
|
#define AV_CH_LAYOUT_5POINT1 (AV_CH_LAYOUT_5POINT0|AV_CH_LOW_FREQUENCY)
|
||||||
|
#define AV_CH_LAYOUT_5POINT0_BACK (AV_CH_LAYOUT_SURROUND|AV_CH_BACK_LEFT|AV_CH_BACK_RIGHT)
|
||||||
|
#define AV_CH_LAYOUT_5POINT1_BACK (AV_CH_LAYOUT_5POINT0_BACK|AV_CH_LOW_FREQUENCY)
|
||||||
|
#define AV_CH_LAYOUT_6POINT0 (AV_CH_LAYOUT_5POINT0|AV_CH_BACK_CENTER)
|
||||||
|
#define AV_CH_LAYOUT_6POINT0_FRONT (AV_CH_LAYOUT_2_2|AV_CH_FRONT_LEFT_OF_CENTER|AV_CH_FRONT_RIGHT_OF_CENTER)
|
||||||
|
#define AV_CH_LAYOUT_HEXAGONAL (AV_CH_LAYOUT_5POINT0_BACK|AV_CH_BACK_CENTER)
|
||||||
|
#define AV_CH_LAYOUT_6POINT1 (AV_CH_LAYOUT_5POINT1|AV_CH_BACK_CENTER)
|
||||||
|
#define AV_CH_LAYOUT_6POINT1_BACK (AV_CH_LAYOUT_5POINT1_BACK|AV_CH_BACK_CENTER)
|
||||||
|
#define AV_CH_LAYOUT_6POINT1_FRONT (AV_CH_LAYOUT_6POINT0_FRONT|AV_CH_LOW_FREQUENCY)
|
||||||
|
#define AV_CH_LAYOUT_7POINT0 (AV_CH_LAYOUT_5POINT0|AV_CH_BACK_LEFT|AV_CH_BACK_RIGHT)
|
||||||
|
#define AV_CH_LAYOUT_7POINT0_FRONT (AV_CH_LAYOUT_5POINT0|AV_CH_FRONT_LEFT_OF_CENTER|AV_CH_FRONT_RIGHT_OF_CENTER)
|
||||||
|
#define AV_CH_LAYOUT_7POINT1 (AV_CH_LAYOUT_5POINT1|AV_CH_BACK_LEFT|AV_CH_BACK_RIGHT)
|
||||||
|
#define AV_CH_LAYOUT_7POINT1_WIDE (AV_CH_LAYOUT_5POINT1|AV_CH_FRONT_LEFT_OF_CENTER|AV_CH_FRONT_RIGHT_OF_CENTER)
|
||||||
|
#define AV_CH_LAYOUT_7POINT1_WIDE_BACK (AV_CH_LAYOUT_5POINT1_BACK|AV_CH_FRONT_LEFT_OF_CENTER|AV_CH_FRONT_RIGHT_OF_CENTER)
|
||||||
|
#define AV_CH_LAYOUT_OCTAGONAL (AV_CH_LAYOUT_5POINT0|AV_CH_BACK_LEFT|AV_CH_BACK_CENTER|AV_CH_BACK_RIGHT)
|
||||||
|
#define AV_CH_LAYOUT_HEXADECAGONAL (AV_CH_LAYOUT_OCTAGONAL|AV_CH_WIDE_LEFT|AV_CH_WIDE_RIGHT|AV_CH_TOP_BACK_LEFT|AV_CH_TOP_BACK_RIGHT|AV_CH_TOP_BACK_CENTER|AV_CH_TOP_FRONT_CENTER|AV_CH_TOP_FRONT_LEFT|AV_CH_TOP_FRONT_RIGHT)
|
||||||
|
#define AV_CH_LAYOUT_STEREO_DOWNMIX (AV_CH_STEREO_LEFT|AV_CH_STEREO_RIGHT)
|
||||||
|
|
||||||
|
enum AVMatrixEncoding {
|
||||||
|
AV_MATRIX_ENCODING_NONE,
|
||||||
|
AV_MATRIX_ENCODING_DOLBY,
|
||||||
|
AV_MATRIX_ENCODING_DPLII,
|
||||||
|
AV_MATRIX_ENCODING_DPLIIX,
|
||||||
|
AV_MATRIX_ENCODING_DPLIIZ,
|
||||||
|
AV_MATRIX_ENCODING_DOLBYEX,
|
||||||
|
AV_MATRIX_ENCODING_DOLBYHEADPHONE,
|
||||||
|
AV_MATRIX_ENCODING_NB
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return a channel layout id that matches name, or 0 if no match is found.
|
||||||
|
*
|
||||||
|
* name can be one or several of the following notations,
|
||||||
|
* separated by '+' or '|':
|
||||||
|
* - the name of an usual channel layout (mono, stereo, 4.0, quad, 5.0,
|
||||||
|
* 5.0(side), 5.1, 5.1(side), 7.1, 7.1(wide), downmix);
|
||||||
|
* - the name of a single channel (FL, FR, FC, LFE, BL, BR, FLC, FRC, BC,
|
||||||
|
* SL, SR, TC, TFL, TFC, TFR, TBL, TBC, TBR, DL, DR);
|
||||||
|
* - a number of channels, in decimal, optionally followed by 'c', yielding
|
||||||
|
* the default channel layout for that number of channels (@see
|
||||||
|
* av_get_default_channel_layout);
|
||||||
|
* - a channel layout mask, in hexadecimal starting with "0x" (see the
|
||||||
|
* AV_CH_* macros).
|
||||||
|
*
|
||||||
|
* @warning Starting from the next major bump the trailing character
|
||||||
|
* 'c' to specify a number of channels will be required, while a
|
||||||
|
* channel layout mask could also be specified as a decimal number
|
||||||
|
* (if and only if not followed by "c").
|
||||||
|
*
|
||||||
|
* Example: "stereo+FC" = "2c+FC" = "2c+1c" = "0x7"
|
||||||
|
*/
|
||||||
|
uint64_t av_get_channel_layout(const char *name);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return a description of a channel layout.
|
||||||
|
* If nb_channels is <= 0, it is guessed from the channel_layout.
|
||||||
|
*
|
||||||
|
* @param buf put here the string containing the channel layout
|
||||||
|
* @param buf_size size in bytes of the buffer
|
||||||
|
*/
|
||||||
|
void av_get_channel_layout_string(char *buf, int buf_size, int nb_channels, uint64_t channel_layout);
|
||||||
|
|
||||||
|
struct AVBPrint;
|
||||||
|
/**
|
||||||
|
* Append a description of a channel layout to a bprint buffer.
|
||||||
|
*/
|
||||||
|
void av_bprint_channel_layout(struct AVBPrint *bp, int nb_channels, uint64_t channel_layout);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the number of channels in the channel layout.
|
||||||
|
*/
|
||||||
|
int av_get_channel_layout_nb_channels(uint64_t channel_layout);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return default channel layout for a given number of channels.
|
||||||
|
*/
|
||||||
|
int64_t av_get_default_channel_layout(int nb_channels);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the index of a channel in channel_layout.
|
||||||
|
*
|
||||||
|
* @param channel a channel layout describing exactly one channel which must be
|
||||||
|
* present in channel_layout.
|
||||||
|
*
|
||||||
|
* @return index of channel in channel_layout on success, a negative AVERROR
|
||||||
|
* on error.
|
||||||
|
*/
|
||||||
|
int av_get_channel_layout_channel_index(uint64_t channel_layout,
|
||||||
|
uint64_t channel);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the channel with the given index in channel_layout.
|
||||||
|
*/
|
||||||
|
uint64_t av_channel_layout_extract_channel(uint64_t channel_layout, int index);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the name of a given channel.
|
||||||
|
*
|
||||||
|
* @return channel name on success, NULL on error.
|
||||||
|
*/
|
||||||
|
const char *av_get_channel_name(uint64_t channel);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the description of a given channel.
|
||||||
|
*
|
||||||
|
* @param channel a channel layout with a single channel
|
||||||
|
* @return channel description on success, NULL on error
|
||||||
|
*/
|
||||||
|
const char *av_get_channel_description(uint64_t channel);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the value and name of a standard channel layout.
|
||||||
|
*
|
||||||
|
* @param[in] index index in an internal list, starting at 0
|
||||||
|
* @param[out] layout channel layout mask
|
||||||
|
* @param[out] name name of the layout
|
||||||
|
* @return 0 if the layout exists,
|
||||||
|
* <0 if index is beyond the limits
|
||||||
|
*/
|
||||||
|
int av_get_standard_channel_layout(unsigned index, uint64_t *layout,
|
||||||
|
const char **name);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @}
|
||||||
|
* @}
|
||||||
|
*/
|
||||||
|
|
||||||
|
#endif /* AVUTIL_CHANNEL_LAYOUT_H */
|
@ -0,0 +1,508 @@
|
|||||||
|
/*
|
||||||
|
* copyright (c) 2006 Michael Niedermayer <michaelni@gmx.at>
|
||||||
|
*
|
||||||
|
* This file is part of FFmpeg.
|
||||||
|
*
|
||||||
|
* FFmpeg is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2.1 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* FFmpeg is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with FFmpeg; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @file
|
||||||
|
* common internal and external API header
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef AVUTIL_COMMON_H
|
||||||
|
#define AVUTIL_COMMON_H
|
||||||
|
|
||||||
|
#if defined(__cplusplus) && !defined(__STDC_CONSTANT_MACROS) && !defined(UINT64_C)
|
||||||
|
#error missing -D__STDC_CONSTANT_MACROS / #define __STDC_CONSTANT_MACROS
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <errno.h>
|
||||||
|
#include <inttypes.h>
|
||||||
|
#include <limits.h>
|
||||||
|
#include <math.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include "attributes.h"
|
||||||
|
#include "version.h"
|
||||||
|
#include "libavutil/avconfig.h"
|
||||||
|
|
||||||
|
#if AV_HAVE_BIGENDIAN
|
||||||
|
# define AV_NE(be, le) (be)
|
||||||
|
#else
|
||||||
|
# define AV_NE(be, le) (le)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
//rounded division & shift
|
||||||
|
#define RSHIFT(a,b) ((a) > 0 ? ((a) + ((1<<(b))>>1))>>(b) : ((a) + ((1<<(b))>>1)-1)>>(b))
|
||||||
|
/* assume b>0 */
|
||||||
|
#define ROUNDED_DIV(a,b) (((a)>0 ? (a) + ((b)>>1) : (a) - ((b)>>1))/(b))
|
||||||
|
/* assume a>0 and b>0 */
|
||||||
|
#define FF_CEIL_RSHIFT(a,b) (!av_builtin_constant_p(b) ? -((-(a)) >> (b)) \
|
||||||
|
: ((a) + (1<<(b)) - 1) >> (b))
|
||||||
|
#define FFUDIV(a,b) (((a)>0 ?(a):(a)-(b)+1) / (b))
|
||||||
|
#define FFUMOD(a,b) ((a)-(b)*FFUDIV(a,b))
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Absolute value, Note, INT_MIN / INT64_MIN result in undefined behavior as they
|
||||||
|
* are not representable as absolute values of their type. This is the same
|
||||||
|
* as with *abs()
|
||||||
|
* @see FFNABS()
|
||||||
|
*/
|
||||||
|
#define FFABS(a) ((a) >= 0 ? (a) : (-(a)))
|
||||||
|
#define FFSIGN(a) ((a) > 0 ? 1 : -1)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Negative Absolute value.
|
||||||
|
* this works for all integers of all types.
|
||||||
|
* As with many macros, this evaluates its argument twice, it thus must not have
|
||||||
|
* a sideeffect, that is FFNABS(x++) has undefined behavior.
|
||||||
|
*/
|
||||||
|
#define FFNABS(a) ((a) <= 0 ? (a) : (-(a)))
|
||||||
|
|
||||||
|
#define FFMAX(a,b) ((a) > (b) ? (a) : (b))
|
||||||
|
#define FFMAX3(a,b,c) FFMAX(FFMAX(a,b),c)
|
||||||
|
#define FFMIN(a,b) ((a) > (b) ? (b) : (a))
|
||||||
|
#define FFMIN3(a,b,c) FFMIN(FFMIN(a,b),c)
|
||||||
|
|
||||||
|
#define FFSWAP(type,a,b) do{type SWAP_tmp= b; b= a; a= SWAP_tmp;}while(0)
|
||||||
|
#define FF_ARRAY_ELEMS(a) (sizeof(a) / sizeof((a)[0]))
|
||||||
|
#define FFALIGN(x, a) (((x)+(a)-1)&~((a)-1))
|
||||||
|
|
||||||
|
/* misc math functions */
|
||||||
|
|
||||||
|
#ifdef HAVE_AV_CONFIG_H
|
||||||
|
# include "config.h"
|
||||||
|
# include "intmath.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Pull in unguarded fallback defines at the end of this file. */
|
||||||
|
#include "common.h"
|
||||||
|
|
||||||
|
#ifndef av_log2
|
||||||
|
av_const int av_log2(unsigned v);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef av_log2_16bit
|
||||||
|
av_const int av_log2_16bit(unsigned v);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Clip a signed integer value into the amin-amax range.
|
||||||
|
* @param a value to clip
|
||||||
|
* @param amin minimum value of the clip range
|
||||||
|
* @param amax maximum value of the clip range
|
||||||
|
* @return clipped value
|
||||||
|
*/
|
||||||
|
static av_always_inline av_const int av_clip_c(int a, int amin, int amax)
|
||||||
|
{
|
||||||
|
#if defined(HAVE_AV_CONFIG_H) && defined(ASSERT_LEVEL) && ASSERT_LEVEL >= 2
|
||||||
|
if (amin > amax) abort();
|
||||||
|
#endif
|
||||||
|
if (a < amin) return amin;
|
||||||
|
else if (a > amax) return amax;
|
||||||
|
else return a;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Clip a signed 64bit integer value into the amin-amax range.
|
||||||
|
* @param a value to clip
|
||||||
|
* @param amin minimum value of the clip range
|
||||||
|
* @param amax maximum value of the clip range
|
||||||
|
* @return clipped value
|
||||||
|
*/
|
||||||
|
static av_always_inline av_const int64_t av_clip64_c(int64_t a, int64_t amin, int64_t amax)
|
||||||
|
{
|
||||||
|
#if defined(HAVE_AV_CONFIG_H) && defined(ASSERT_LEVEL) && ASSERT_LEVEL >= 2
|
||||||
|
if (amin > amax) abort();
|
||||||
|
#endif
|
||||||
|
if (a < amin) return amin;
|
||||||
|
else if (a > amax) return amax;
|
||||||
|
else return a;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Clip a signed integer value into the 0-255 range.
|
||||||
|
* @param a value to clip
|
||||||
|
* @return clipped value
|
||||||
|
*/
|
||||||
|
static av_always_inline av_const uint8_t av_clip_uint8_c(int a)
|
||||||
|
{
|
||||||
|
if (a&(~0xFF)) return (-a)>>31;
|
||||||
|
else return a;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Clip a signed integer value into the -128,127 range.
|
||||||
|
* @param a value to clip
|
||||||
|
* @return clipped value
|
||||||
|
*/
|
||||||
|
static av_always_inline av_const int8_t av_clip_int8_c(int a)
|
||||||
|
{
|
||||||
|
if ((a+0x80U) & ~0xFF) return (a>>31) ^ 0x7F;
|
||||||
|
else return a;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Clip a signed integer value into the 0-65535 range.
|
||||||
|
* @param a value to clip
|
||||||
|
* @return clipped value
|
||||||
|
*/
|
||||||
|
static av_always_inline av_const uint16_t av_clip_uint16_c(int a)
|
||||||
|
{
|
||||||
|
if (a&(~0xFFFF)) return (-a)>>31;
|
||||||
|
else return a;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Clip a signed integer value into the -32768,32767 range.
|
||||||
|
* @param a value to clip
|
||||||
|
* @return clipped value
|
||||||
|
*/
|
||||||
|
static av_always_inline av_const int16_t av_clip_int16_c(int a)
|
||||||
|
{
|
||||||
|
if ((a+0x8000U) & ~0xFFFF) return (a>>31) ^ 0x7FFF;
|
||||||
|
else return a;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Clip a signed 64-bit integer value into the -2147483648,2147483647 range.
|
||||||
|
* @param a value to clip
|
||||||
|
* @return clipped value
|
||||||
|
*/
|
||||||
|
static av_always_inline av_const int32_t av_clipl_int32_c(int64_t a)
|
||||||
|
{
|
||||||
|
if ((a+0x80000000u) & ~UINT64_C(0xFFFFFFFF)) return (int32_t)((a>>63) ^ 0x7FFFFFFF);
|
||||||
|
else return (int32_t)a;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Clip a signed integer into the -(2^p),(2^p-1) range.
|
||||||
|
* @param a value to clip
|
||||||
|
* @param p bit position to clip at
|
||||||
|
* @return clipped value
|
||||||
|
*/
|
||||||
|
static av_always_inline av_const int av_clip_intp2_c(int a, int p)
|
||||||
|
{
|
||||||
|
if ((a + (1 << p)) & ~((2 << p) - 1))
|
||||||
|
return (a >> 31) ^ ((1 << p) - 1);
|
||||||
|
else
|
||||||
|
return a;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Clip a signed integer to an unsigned power of two range.
|
||||||
|
* @param a value to clip
|
||||||
|
* @param p bit position to clip at
|
||||||
|
* @return clipped value
|
||||||
|
*/
|
||||||
|
static av_always_inline av_const unsigned av_clip_uintp2_c(int a, int p)
|
||||||
|
{
|
||||||
|
if (a & ~((1<<p) - 1)) return -a >> 31 & ((1<<p) - 1);
|
||||||
|
else return a;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Clear high bits from an unsigned integer starting with specific bit position
|
||||||
|
* @param a value to clip
|
||||||
|
* @param p bit position to clip at
|
||||||
|
* @return clipped value
|
||||||
|
*/
|
||||||
|
static av_always_inline av_const unsigned av_mod_uintp2_c(unsigned a, unsigned p)
|
||||||
|
{
|
||||||
|
return a & ((1 << p) - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add two signed 32-bit values with saturation.
|
||||||
|
*
|
||||||
|
* @param a one value
|
||||||
|
* @param b another value
|
||||||
|
* @return sum with signed saturation
|
||||||
|
*/
|
||||||
|
static av_always_inline int av_sat_add32_c(int a, int b)
|
||||||
|
{
|
||||||
|
return av_clipl_int32((int64_t)a + b);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add a doubled value to another value with saturation at both stages.
|
||||||
|
*
|
||||||
|
* @param a first value
|
||||||
|
* @param b value doubled and added to a
|
||||||
|
* @return sum with signed saturation
|
||||||
|
*/
|
||||||
|
static av_always_inline int av_sat_dadd32_c(int a, int b)
|
||||||
|
{
|
||||||
|
return av_sat_add32(a, av_sat_add32(b, b));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Clip a float value into the amin-amax range.
|
||||||
|
* @param a value to clip
|
||||||
|
* @param amin minimum value of the clip range
|
||||||
|
* @param amax maximum value of the clip range
|
||||||
|
* @return clipped value
|
||||||
|
*/
|
||||||
|
static av_always_inline av_const float av_clipf_c(float a, float amin, float amax)
|
||||||
|
{
|
||||||
|
#if defined(HAVE_AV_CONFIG_H) && defined(ASSERT_LEVEL) && ASSERT_LEVEL >= 2
|
||||||
|
if (amin > amax) abort();
|
||||||
|
#endif
|
||||||
|
if (a < amin) return amin;
|
||||||
|
else if (a > amax) return amax;
|
||||||
|
else return a;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Clip a double value into the amin-amax range.
|
||||||
|
* @param a value to clip
|
||||||
|
* @param amin minimum value of the clip range
|
||||||
|
* @param amax maximum value of the clip range
|
||||||
|
* @return clipped value
|
||||||
|
*/
|
||||||
|
static av_always_inline av_const double av_clipd_c(double a, double amin, double amax)
|
||||||
|
{
|
||||||
|
#if defined(HAVE_AV_CONFIG_H) && defined(ASSERT_LEVEL) && ASSERT_LEVEL >= 2
|
||||||
|
if (amin > amax) abort();
|
||||||
|
#endif
|
||||||
|
if (a < amin) return amin;
|
||||||
|
else if (a > amax) return amax;
|
||||||
|
else return a;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Compute ceil(log2(x)).
|
||||||
|
* @param x value used to compute ceil(log2(x))
|
||||||
|
* @return computed ceiling of log2(x)
|
||||||
|
*/
|
||||||
|
static av_always_inline av_const int av_ceil_log2_c(int x)
|
||||||
|
{
|
||||||
|
return av_log2((x - 1) << 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Count number of bits set to one in x
|
||||||
|
* @param x value to count bits of
|
||||||
|
* @return the number of bits set to one in x
|
||||||
|
*/
|
||||||
|
static av_always_inline av_const int av_popcount_c(uint32_t x)
|
||||||
|
{
|
||||||
|
x -= (x >> 1) & 0x55555555;
|
||||||
|
x = (x & 0x33333333) + ((x >> 2) & 0x33333333);
|
||||||
|
x = (x + (x >> 4)) & 0x0F0F0F0F;
|
||||||
|
x += x >> 8;
|
||||||
|
return (x + (x >> 16)) & 0x3F;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Count number of bits set to one in x
|
||||||
|
* @param x value to count bits of
|
||||||
|
* @return the number of bits set to one in x
|
||||||
|
*/
|
||||||
|
static av_always_inline av_const int av_popcount64_c(uint64_t x)
|
||||||
|
{
|
||||||
|
return av_popcount((uint32_t)x) + av_popcount((uint32_t)(x >> 32));
|
||||||
|
}
|
||||||
|
|
||||||
|
#define MKTAG(a,b,c,d) ((a) | ((b) << 8) | ((c) << 16) | ((unsigned)(d) << 24))
|
||||||
|
#define MKBETAG(a,b,c,d) ((d) | ((c) << 8) | ((b) << 16) | ((unsigned)(a) << 24))
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Convert a UTF-8 character (up to 4 bytes) to its 32-bit UCS-4 encoded form.
|
||||||
|
*
|
||||||
|
* @param val Output value, must be an lvalue of type uint32_t.
|
||||||
|
* @param GET_BYTE Expression reading one byte from the input.
|
||||||
|
* Evaluated up to 7 times (4 for the currently
|
||||||
|
* assigned Unicode range). With a memory buffer
|
||||||
|
* input, this could be *ptr++.
|
||||||
|
* @param ERROR Expression to be evaluated on invalid input,
|
||||||
|
* typically a goto statement.
|
||||||
|
*
|
||||||
|
* @warning ERROR should not contain a loop control statement which
|
||||||
|
* could interact with the internal while loop, and should force an
|
||||||
|
* exit from the macro code (e.g. through a goto or a return) in order
|
||||||
|
* to prevent undefined results.
|
||||||
|
*/
|
||||||
|
#define GET_UTF8(val, GET_BYTE, ERROR)\
|
||||||
|
val= GET_BYTE;\
|
||||||
|
{\
|
||||||
|
uint32_t top = (val & 128) >> 1;\
|
||||||
|
if ((val & 0xc0) == 0x80 || val >= 0xFE)\
|
||||||
|
ERROR\
|
||||||
|
while (val & top) {\
|
||||||
|
int tmp= GET_BYTE - 128;\
|
||||||
|
if(tmp>>6)\
|
||||||
|
ERROR\
|
||||||
|
val= (val<<6) + tmp;\
|
||||||
|
top <<= 5;\
|
||||||
|
}\
|
||||||
|
val &= (top << 1) - 1;\
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Convert a UTF-16 character (2 or 4 bytes) to its 32-bit UCS-4 encoded form.
|
||||||
|
*
|
||||||
|
* @param val Output value, must be an lvalue of type uint32_t.
|
||||||
|
* @param GET_16BIT Expression returning two bytes of UTF-16 data converted
|
||||||
|
* to native byte order. Evaluated one or two times.
|
||||||
|
* @param ERROR Expression to be evaluated on invalid input,
|
||||||
|
* typically a goto statement.
|
||||||
|
*/
|
||||||
|
#define GET_UTF16(val, GET_16BIT, ERROR)\
|
||||||
|
val = GET_16BIT;\
|
||||||
|
{\
|
||||||
|
unsigned int hi = val - 0xD800;\
|
||||||
|
if (hi < 0x800) {\
|
||||||
|
val = GET_16BIT - 0xDC00;\
|
||||||
|
if (val > 0x3FFU || hi > 0x3FFU)\
|
||||||
|
ERROR\
|
||||||
|
val += (hi<<10) + 0x10000;\
|
||||||
|
}\
|
||||||
|
}\
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @def PUT_UTF8(val, tmp, PUT_BYTE)
|
||||||
|
* Convert a 32-bit Unicode character to its UTF-8 encoded form (up to 4 bytes long).
|
||||||
|
* @param val is an input-only argument and should be of type uint32_t. It holds
|
||||||
|
* a UCS-4 encoded Unicode character that is to be converted to UTF-8. If
|
||||||
|
* val is given as a function it is executed only once.
|
||||||
|
* @param tmp is a temporary variable and should be of type uint8_t. It
|
||||||
|
* represents an intermediate value during conversion that is to be
|
||||||
|
* output by PUT_BYTE.
|
||||||
|
* @param PUT_BYTE writes the converted UTF-8 bytes to any proper destination.
|
||||||
|
* It could be a function or a statement, and uses tmp as the input byte.
|
||||||
|
* For example, PUT_BYTE could be "*output++ = tmp;" PUT_BYTE will be
|
||||||
|
* executed up to 4 times for values in the valid UTF-8 range and up to
|
||||||
|
* 7 times in the general case, depending on the length of the converted
|
||||||
|
* Unicode character.
|
||||||
|
*/
|
||||||
|
#define PUT_UTF8(val, tmp, PUT_BYTE)\
|
||||||
|
{\
|
||||||
|
int bytes, shift;\
|
||||||
|
uint32_t in = val;\
|
||||||
|
if (in < 0x80) {\
|
||||||
|
tmp = in;\
|
||||||
|
PUT_BYTE\
|
||||||
|
} else {\
|
||||||
|
bytes = (av_log2(in) + 4) / 5;\
|
||||||
|
shift = (bytes - 1) * 6;\
|
||||||
|
tmp = (256 - (256 >> bytes)) | (in >> shift);\
|
||||||
|
PUT_BYTE\
|
||||||
|
while (shift >= 6) {\
|
||||||
|
shift -= 6;\
|
||||||
|
tmp = 0x80 | ((in >> shift) & 0x3f);\
|
||||||
|
PUT_BYTE\
|
||||||
|
}\
|
||||||
|
}\
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @def PUT_UTF16(val, tmp, PUT_16BIT)
|
||||||
|
* Convert a 32-bit Unicode character to its UTF-16 encoded form (2 or 4 bytes).
|
||||||
|
* @param val is an input-only argument and should be of type uint32_t. It holds
|
||||||
|
* a UCS-4 encoded Unicode character that is to be converted to UTF-16. If
|
||||||
|
* val is given as a function it is executed only once.
|
||||||
|
* @param tmp is a temporary variable and should be of type uint16_t. It
|
||||||
|
* represents an intermediate value during conversion that is to be
|
||||||
|
* output by PUT_16BIT.
|
||||||
|
* @param PUT_16BIT writes the converted UTF-16 data to any proper destination
|
||||||
|
* in desired endianness. It could be a function or a statement, and uses tmp
|
||||||
|
* as the input byte. For example, PUT_BYTE could be "*output++ = tmp;"
|
||||||
|
* PUT_BYTE will be executed 1 or 2 times depending on input character.
|
||||||
|
*/
|
||||||
|
#define PUT_UTF16(val, tmp, PUT_16BIT)\
|
||||||
|
{\
|
||||||
|
uint32_t in = val;\
|
||||||
|
if (in < 0x10000) {\
|
||||||
|
tmp = in;\
|
||||||
|
PUT_16BIT\
|
||||||
|
} else {\
|
||||||
|
tmp = 0xD800 | ((in - 0x10000) >> 10);\
|
||||||
|
PUT_16BIT\
|
||||||
|
tmp = 0xDC00 | ((in - 0x10000) & 0x3FF);\
|
||||||
|
PUT_16BIT\
|
||||||
|
}\
|
||||||
|
}\
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#include "mem.h"
|
||||||
|
|
||||||
|
#ifdef HAVE_AV_CONFIG_H
|
||||||
|
# include "internal.h"
|
||||||
|
#endif /* HAVE_AV_CONFIG_H */
|
||||||
|
|
||||||
|
#endif /* AVUTIL_COMMON_H */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The following definitions are outside the multiple inclusion guard
|
||||||
|
* to ensure they are immediately available in intmath.h.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef av_ceil_log2
|
||||||
|
# define av_ceil_log2 av_ceil_log2_c
|
||||||
|
#endif
|
||||||
|
#ifndef av_clip
|
||||||
|
# define av_clip av_clip_c
|
||||||
|
#endif
|
||||||
|
#ifndef av_clip64
|
||||||
|
# define av_clip64 av_clip64_c
|
||||||
|
#endif
|
||||||
|
#ifndef av_clip_uint8
|
||||||
|
# define av_clip_uint8 av_clip_uint8_c
|
||||||
|
#endif
|
||||||
|
#ifndef av_clip_int8
|
||||||
|
# define av_clip_int8 av_clip_int8_c
|
||||||
|
#endif
|
||||||
|
#ifndef av_clip_uint16
|
||||||
|
# define av_clip_uint16 av_clip_uint16_c
|
||||||
|
#endif
|
||||||
|
#ifndef av_clip_int16
|
||||||
|
# define av_clip_int16 av_clip_int16_c
|
||||||
|
#endif
|
||||||
|
#ifndef av_clipl_int32
|
||||||
|
# define av_clipl_int32 av_clipl_int32_c
|
||||||
|
#endif
|
||||||
|
#ifndef av_clip_intp2
|
||||||
|
# define av_clip_intp2 av_clip_intp2_c
|
||||||
|
#endif
|
||||||
|
#ifndef av_clip_uintp2
|
||||||
|
# define av_clip_uintp2 av_clip_uintp2_c
|
||||||
|
#endif
|
||||||
|
#ifndef av_mod_uintp2
|
||||||
|
# define av_mod_uintp2 av_mod_uintp2_c
|
||||||
|
#endif
|
||||||
|
#ifndef av_sat_add32
|
||||||
|
# define av_sat_add32 av_sat_add32_c
|
||||||
|
#endif
|
||||||
|
#ifndef av_sat_dadd32
|
||||||
|
# define av_sat_dadd32 av_sat_dadd32_c
|
||||||
|
#endif
|
||||||
|
#ifndef av_clipf
|
||||||
|
# define av_clipf av_clipf_c
|
||||||
|
#endif
|
||||||
|
#ifndef av_clipd
|
||||||
|
# define av_clipd av_clipd_c
|
||||||
|
#endif
|
||||||
|
#ifndef av_popcount
|
||||||
|
# define av_popcount av_popcount_c
|
||||||
|
#endif
|
||||||
|
#ifndef av_popcount64
|
||||||
|
# define av_popcount64 av_popcount64_c
|
||||||
|
#endif
|
@ -0,0 +1,115 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2000, 2001, 2002 Fabrice Bellard
|
||||||
|
*
|
||||||
|
* This file is part of FFmpeg.
|
||||||
|
*
|
||||||
|
* FFmpeg is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2.1 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* FFmpeg is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with FFmpeg; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef AVUTIL_CPU_H
|
||||||
|
#define AVUTIL_CPU_H
|
||||||
|
|
||||||
|
#include "attributes.h"
|
||||||
|
|
||||||
|
#define AV_CPU_FLAG_FORCE 0x80000000 /* force usage of selected flags (OR) */
|
||||||
|
|
||||||
|
/* lower 16 bits - CPU features */
|
||||||
|
#define AV_CPU_FLAG_MMX 0x0001 ///< standard MMX
|
||||||
|
#define AV_CPU_FLAG_MMXEXT 0x0002 ///< SSE integer functions or AMD MMX ext
|
||||||
|
#define AV_CPU_FLAG_MMX2 0x0002 ///< SSE integer functions or AMD MMX ext
|
||||||
|
#define AV_CPU_FLAG_3DNOW 0x0004 ///< AMD 3DNOW
|
||||||
|
#define AV_CPU_FLAG_SSE 0x0008 ///< SSE functions
|
||||||
|
#define AV_CPU_FLAG_SSE2 0x0010 ///< PIV SSE2 functions
|
||||||
|
#define AV_CPU_FLAG_SSE2SLOW 0x40000000 ///< SSE2 supported, but usually not faster
|
||||||
|
///< than regular MMX/SSE (e.g. Core1)
|
||||||
|
#define AV_CPU_FLAG_3DNOWEXT 0x0020 ///< AMD 3DNowExt
|
||||||
|
#define AV_CPU_FLAG_SSE3 0x0040 ///< Prescott SSE3 functions
|
||||||
|
#define AV_CPU_FLAG_SSE3SLOW 0x20000000 ///< SSE3 supported, but usually not faster
|
||||||
|
///< than regular MMX/SSE (e.g. Core1)
|
||||||
|
#define AV_CPU_FLAG_SSSE3 0x0080 ///< Conroe SSSE3 functions
|
||||||
|
#define AV_CPU_FLAG_ATOM 0x10000000 ///< Atom processor, some SSSE3 instructions are slower
|
||||||
|
#define AV_CPU_FLAG_SSE4 0x0100 ///< Penryn SSE4.1 functions
|
||||||
|
#define AV_CPU_FLAG_SSE42 0x0200 ///< Nehalem SSE4.2 functions
|
||||||
|
#define AV_CPU_FLAG_AVX 0x4000 ///< AVX functions: requires OS support even if YMM registers aren't used
|
||||||
|
#define AV_CPU_FLAG_AVXSLOW 0x8000000 ///< AVX supported, but slow when using YMM registers (e.g. Bulldozer)
|
||||||
|
#define AV_CPU_FLAG_XOP 0x0400 ///< Bulldozer XOP functions
|
||||||
|
#define AV_CPU_FLAG_FMA4 0x0800 ///< Bulldozer FMA4 functions
|
||||||
|
#define AV_CPU_FLAG_CMOV 0x1000 ///< supports cmov instruction
|
||||||
|
#define AV_CPU_FLAG_AVX2 0x8000 ///< AVX2 functions: requires OS support even if YMM registers aren't used
|
||||||
|
#define AV_CPU_FLAG_FMA3 0x10000 ///< Haswell FMA3 functions
|
||||||
|
#define AV_CPU_FLAG_BMI1 0x20000 ///< Bit Manipulation Instruction Set 1
|
||||||
|
#define AV_CPU_FLAG_BMI2 0x40000 ///< Bit Manipulation Instruction Set 2
|
||||||
|
|
||||||
|
#define AV_CPU_FLAG_ALTIVEC 0x0001 ///< standard
|
||||||
|
#define AV_CPU_FLAG_VSX 0x0002 ///< ISA 2.06
|
||||||
|
#define AV_CPU_FLAG_POWER8 0x0004 ///< ISA 2.07
|
||||||
|
|
||||||
|
#define AV_CPU_FLAG_ARMV5TE (1 << 0)
|
||||||
|
#define AV_CPU_FLAG_ARMV6 (1 << 1)
|
||||||
|
#define AV_CPU_FLAG_ARMV6T2 (1 << 2)
|
||||||
|
#define AV_CPU_FLAG_VFP (1 << 3)
|
||||||
|
#define AV_CPU_FLAG_VFPV3 (1 << 4)
|
||||||
|
#define AV_CPU_FLAG_NEON (1 << 5)
|
||||||
|
#define AV_CPU_FLAG_ARMV8 (1 << 6)
|
||||||
|
#define AV_CPU_FLAG_SETEND (1 <<16)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the flags which specify extensions supported by the CPU.
|
||||||
|
* The returned value is affected by av_force_cpu_flags() if that was used
|
||||||
|
* before. So av_get_cpu_flags() can easily be used in a application to
|
||||||
|
* detect the enabled cpu flags.
|
||||||
|
*/
|
||||||
|
int av_get_cpu_flags(void);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Disables cpu detection and forces the specified flags.
|
||||||
|
* -1 is a special case that disables forcing of specific flags.
|
||||||
|
*/
|
||||||
|
void av_force_cpu_flags(int flags);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set a mask on flags returned by av_get_cpu_flags().
|
||||||
|
* This function is mainly useful for testing.
|
||||||
|
* Please use av_force_cpu_flags() and av_get_cpu_flags() instead which are more flexible
|
||||||
|
*
|
||||||
|
* @warning this function is not thread safe.
|
||||||
|
*/
|
||||||
|
attribute_deprecated void av_set_cpu_flags_mask(int mask);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parse CPU flags from a string.
|
||||||
|
*
|
||||||
|
* The returned flags contain the specified flags as well as related unspecified flags.
|
||||||
|
*
|
||||||
|
* This function exists only for compatibility with libav.
|
||||||
|
* Please use av_parse_cpu_caps() when possible.
|
||||||
|
* @return a combination of AV_CPU_* flags, negative on error.
|
||||||
|
*/
|
||||||
|
attribute_deprecated
|
||||||
|
int av_parse_cpu_flags(const char *s);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parse CPU caps from a string and update the given AV_CPU_* flags based on that.
|
||||||
|
*
|
||||||
|
* @return negative on error.
|
||||||
|
*/
|
||||||
|
int av_parse_cpu_caps(unsigned *flags, const char *s);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return the number of logical CPU cores present.
|
||||||
|
*/
|
||||||
|
int av_cpu_count(void);
|
||||||
|
|
||||||
|
#endif /* AVUTIL_CPU_H */
|
@ -0,0 +1,86 @@
|
|||||||
|
/*
|
||||||
|
* copyright (c) 2006 Michael Niedermayer <michaelni@gmx.at>
|
||||||
|
*
|
||||||
|
* This file is part of FFmpeg.
|
||||||
|
*
|
||||||
|
* FFmpeg is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2.1 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* FFmpeg is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with FFmpeg; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef AVUTIL_CRC_H
|
||||||
|
#define AVUTIL_CRC_H
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stddef.h>
|
||||||
|
#include "attributes.h"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @defgroup lavu_crc32 CRC32
|
||||||
|
* @ingroup lavu_crypto
|
||||||
|
* @{
|
||||||
|
*/
|
||||||
|
|
||||||
|
typedef uint32_t AVCRC;
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
AV_CRC_8_ATM,
|
||||||
|
AV_CRC_16_ANSI,
|
||||||
|
AV_CRC_16_CCITT,
|
||||||
|
AV_CRC_32_IEEE,
|
||||||
|
AV_CRC_32_IEEE_LE, /*< reversed bitorder version of AV_CRC_32_IEEE */
|
||||||
|
AV_CRC_16_ANSI_LE, /*< reversed bitorder version of AV_CRC_16_ANSI */
|
||||||
|
AV_CRC_24_IEEE = 12,
|
||||||
|
AV_CRC_MAX, /*< Not part of public API! Do not use outside libavutil. */
|
||||||
|
}AVCRCId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initialize a CRC table.
|
||||||
|
* @param ctx must be an array of size sizeof(AVCRC)*257 or sizeof(AVCRC)*1024
|
||||||
|
* @param le If 1, the lowest bit represents the coefficient for the highest
|
||||||
|
* exponent of the corresponding polynomial (both for poly and
|
||||||
|
* actual CRC).
|
||||||
|
* If 0, you must swap the CRC parameter and the result of av_crc
|
||||||
|
* if you need the standard representation (can be simplified in
|
||||||
|
* most cases to e.g. bswap16):
|
||||||
|
* av_bswap32(crc << (32-bits))
|
||||||
|
* @param bits number of bits for the CRC
|
||||||
|
* @param poly generator polynomial without the x**bits coefficient, in the
|
||||||
|
* representation as specified by le
|
||||||
|
* @param ctx_size size of ctx in bytes
|
||||||
|
* @return <0 on failure
|
||||||
|
*/
|
||||||
|
int av_crc_init(AVCRC *ctx, int le, int bits, uint32_t poly, int ctx_size);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get an initialized standard CRC table.
|
||||||
|
* @param crc_id ID of a standard CRC
|
||||||
|
* @return a pointer to the CRC table or NULL on failure
|
||||||
|
*/
|
||||||
|
const AVCRC *av_crc_get_table(AVCRCId crc_id);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Calculate the CRC of a block.
|
||||||
|
* @param crc CRC of previous blocks if any or initial value for CRC
|
||||||
|
* @return CRC updated with the data from the given block
|
||||||
|
*
|
||||||
|
* @see av_crc_init() "le" parameter
|
||||||
|
*/
|
||||||
|
uint32_t av_crc(const AVCRC *ctx, uint32_t crc,
|
||||||
|
const uint8_t *buffer, size_t length) av_pure;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @}
|
||||||
|
*/
|
||||||
|
|
||||||
|
#endif /* AVUTIL_CRC_H */
|
@ -0,0 +1,196 @@
|
|||||||
|
/*
|
||||||
|
*
|
||||||
|
* This file is part of FFmpeg.
|
||||||
|
*
|
||||||
|
* FFmpeg is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2.1 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* FFmpeg is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with FFmpeg; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @file
|
||||||
|
* Public dictionary API.
|
||||||
|
* @deprecated
|
||||||
|
* AVDictionary is provided for compatibility with libav. It is both in
|
||||||
|
* implementation as well as API inefficient. It does not scale and is
|
||||||
|
* extremely slow with large dictionaries.
|
||||||
|
* It is recommended that new code uses our tree container from tree.c/h
|
||||||
|
* where applicable, which uses AVL trees to achieve O(log n) performance.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef AVUTIL_DICT_H
|
||||||
|
#define AVUTIL_DICT_H
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#include "version.h"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @addtogroup lavu_dict AVDictionary
|
||||||
|
* @ingroup lavu_data
|
||||||
|
*
|
||||||
|
* @brief Simple key:value store
|
||||||
|
*
|
||||||
|
* @{
|
||||||
|
* Dictionaries are used for storing key:value pairs. To create
|
||||||
|
* an AVDictionary, simply pass an address of a NULL pointer to
|
||||||
|
* av_dict_set(). NULL can be used as an empty dictionary wherever
|
||||||
|
* a pointer to an AVDictionary is required.
|
||||||
|
* Use av_dict_get() to retrieve an entry or iterate over all
|
||||||
|
* entries and finally av_dict_free() to free the dictionary
|
||||||
|
* and all its contents.
|
||||||
|
*
|
||||||
|
@code
|
||||||
|
AVDictionary *d = NULL; // "create" an empty dictionary
|
||||||
|
AVDictionaryEntry *t = NULL;
|
||||||
|
|
||||||
|
av_dict_set(&d, "foo", "bar", 0); // add an entry
|
||||||
|
|
||||||
|
char *k = av_strdup("key"); // if your strings are already allocated,
|
||||||
|
char *v = av_strdup("value"); // you can avoid copying them like this
|
||||||
|
av_dict_set(&d, k, v, AV_DICT_DONT_STRDUP_KEY | AV_DICT_DONT_STRDUP_VAL);
|
||||||
|
|
||||||
|
while (t = av_dict_get(d, "", t, AV_DICT_IGNORE_SUFFIX)) {
|
||||||
|
<....> // iterate over all entries in d
|
||||||
|
}
|
||||||
|
av_dict_free(&d);
|
||||||
|
@endcode
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define AV_DICT_MATCH_CASE 1 /**< Only get an entry with exact-case key match. Only relevant in av_dict_get(). */
|
||||||
|
#define AV_DICT_IGNORE_SUFFIX 2 /**< Return first entry in a dictionary whose first part corresponds to the search key,
|
||||||
|
ignoring the suffix of the found key string. Only relevant in av_dict_get(). */
|
||||||
|
#define AV_DICT_DONT_STRDUP_KEY 4 /**< Take ownership of a key that's been
|
||||||
|
allocated with av_malloc() or another memory allocation function. */
|
||||||
|
#define AV_DICT_DONT_STRDUP_VAL 8 /**< Take ownership of a value that's been
|
||||||
|
allocated with av_malloc() or another memory allocation function. */
|
||||||
|
#define AV_DICT_DONT_OVERWRITE 16 ///< Don't overwrite existing entries.
|
||||||
|
#define AV_DICT_APPEND 32 /**< If the entry already exists, append to it. Note that no
|
||||||
|
delimiter is added, the strings are simply concatenated. */
|
||||||
|
|
||||||
|
typedef struct AVDictionaryEntry {
|
||||||
|
char *key;
|
||||||
|
char *value;
|
||||||
|
} AVDictionaryEntry;
|
||||||
|
|
||||||
|
typedef struct AVDictionary AVDictionary;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get a dictionary entry with matching key.
|
||||||
|
*
|
||||||
|
* The returned entry key or value must not be changed, or it will
|
||||||
|
* cause undefined behavior.
|
||||||
|
*
|
||||||
|
* To iterate through all the dictionary entries, you can set the matching key
|
||||||
|
* to the null string "" and set the AV_DICT_IGNORE_SUFFIX flag.
|
||||||
|
*
|
||||||
|
* @param prev Set to the previous matching element to find the next.
|
||||||
|
* If set to NULL the first matching element is returned.
|
||||||
|
* @param key matching key
|
||||||
|
* @param flags a collection of AV_DICT_* flags controlling how the entry is retrieved
|
||||||
|
* @return found entry or NULL in case no matching entry was found in the dictionary
|
||||||
|
*/
|
||||||
|
AVDictionaryEntry *av_dict_get(const AVDictionary *m, const char *key,
|
||||||
|
const AVDictionaryEntry *prev, int flags);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get number of entries in dictionary.
|
||||||
|
*
|
||||||
|
* @param m dictionary
|
||||||
|
* @return number of entries in dictionary
|
||||||
|
*/
|
||||||
|
int av_dict_count(const AVDictionary *m);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the given entry in *pm, overwriting an existing entry.
|
||||||
|
*
|
||||||
|
* Note: If AV_DICT_DONT_STRDUP_KEY or AV_DICT_DONT_STRDUP_VAL is set,
|
||||||
|
* these arguments will be freed on error.
|
||||||
|
*
|
||||||
|
* @param pm pointer to a pointer to a dictionary struct. If *pm is NULL
|
||||||
|
* a dictionary struct is allocated and put in *pm.
|
||||||
|
* @param key entry key to add to *pm (will be av_strduped depending on flags)
|
||||||
|
* @param value entry value to add to *pm (will be av_strduped depending on flags).
|
||||||
|
* Passing a NULL value will cause an existing entry to be deleted.
|
||||||
|
* @return >= 0 on success otherwise an error code <0
|
||||||
|
*/
|
||||||
|
int av_dict_set(AVDictionary **pm, const char *key, const char *value, int flags);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Convenience wrapper for av_dict_set that converts the value to a string
|
||||||
|
* and stores it.
|
||||||
|
*
|
||||||
|
* Note: If AV_DICT_DONT_STRDUP_KEY is set, key will be freed on error.
|
||||||
|
*/
|
||||||
|
int av_dict_set_int(AVDictionary **pm, const char *key, int64_t value, int flags);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parse the key/value pairs list and add the parsed entries to a dictionary.
|
||||||
|
*
|
||||||
|
* In case of failure, all the successfully set entries are stored in
|
||||||
|
* *pm. You may need to manually free the created dictionary.
|
||||||
|
*
|
||||||
|
* @param key_val_sep a 0-terminated list of characters used to separate
|
||||||
|
* key from value
|
||||||
|
* @param pairs_sep a 0-terminated list of characters used to separate
|
||||||
|
* two pairs from each other
|
||||||
|
* @param flags flags to use when adding to dictionary.
|
||||||
|
* AV_DICT_DONT_STRDUP_KEY and AV_DICT_DONT_STRDUP_VAL
|
||||||
|
* are ignored since the key/value tokens will always
|
||||||
|
* be duplicated.
|
||||||
|
* @return 0 on success, negative AVERROR code on failure
|
||||||
|
*/
|
||||||
|
int av_dict_parse_string(AVDictionary **pm, const char *str,
|
||||||
|
const char *key_val_sep, const char *pairs_sep,
|
||||||
|
int flags);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Copy entries from one AVDictionary struct into another.
|
||||||
|
* @param dst pointer to a pointer to a AVDictionary struct. If *dst is NULL,
|
||||||
|
* this function will allocate a struct for you and put it in *dst
|
||||||
|
* @param src pointer to source AVDictionary struct
|
||||||
|
* @param flags flags to use when setting entries in *dst
|
||||||
|
* @note metadata is read using the AV_DICT_IGNORE_SUFFIX flag
|
||||||
|
*/
|
||||||
|
void av_dict_copy(AVDictionary **dst, const AVDictionary *src, int flags);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Free all the memory allocated for an AVDictionary struct
|
||||||
|
* and all keys and values.
|
||||||
|
*/
|
||||||
|
void av_dict_free(AVDictionary **m);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get dictionary entries as a string.
|
||||||
|
*
|
||||||
|
* Create a string containing dictionary's entries.
|
||||||
|
* Such string may be passed back to av_dict_parse_string().
|
||||||
|
* @note String is escaped with backslashes ('\').
|
||||||
|
*
|
||||||
|
* @param[in] m dictionary
|
||||||
|
* @param[out] buffer Pointer to buffer that will be allocated with string containg entries.
|
||||||
|
* Buffer must be freed by the caller when is no longer needed.
|
||||||
|
* @param[in] key_val_sep character used to separate key from value
|
||||||
|
* @param[in] pairs_sep character used to separate two pairs from each other
|
||||||
|
* @return >= 0 on success, negative on error
|
||||||
|
* @warning Separators cannot be neither '\\' nor '\0'. They also cannot be the same.
|
||||||
|
*/
|
||||||
|
int av_dict_get_string(const AVDictionary *m, char **buffer,
|
||||||
|
const char key_val_sep, const char pairs_sep);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @}
|
||||||
|
*/
|
||||||
|
|
||||||
|
#endif /* AVUTIL_DICT_H */
|
@ -0,0 +1,86 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2014 Vittorio Giovara <vittorio.giovara@gmail.com>
|
||||||
|
*
|
||||||
|
* This file is part of FFmpeg.
|
||||||
|
*
|
||||||
|
* FFmpeg is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2.1 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* FFmpeg is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with FFmpeg; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef AVUTIL_DISPLAY_H
|
||||||
|
#define AVUTIL_DISPLAY_H
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The display transformation matrix specifies an affine transformation that
|
||||||
|
* should be applied to video frames for correct presentation. It is compatible
|
||||||
|
* with the matrices stored in the ISO/IEC 14496-12 container format.
|
||||||
|
*
|
||||||
|
* The data is a 3x3 matrix represented as a 9-element array:
|
||||||
|
*
|
||||||
|
* | a b u |
|
||||||
|
* (a, b, u, c, d, v, x, y, w) -> | c d v |
|
||||||
|
* | x y w |
|
||||||
|
*
|
||||||
|
* All numbers are stored in native endianness, as 16.16 fixed-point values,
|
||||||
|
* except for u, v and w, which are stored as 2.30 fixed-point values.
|
||||||
|
*
|
||||||
|
* The transformation maps a point (p, q) in the source (pre-transformation)
|
||||||
|
* frame to the point (p', q') in the destination (post-transformation) frame as
|
||||||
|
* follows:
|
||||||
|
* | a b u |
|
||||||
|
* (p, q, 1) . | c d v | = z * (p', q', 1)
|
||||||
|
* | x y w |
|
||||||
|
*
|
||||||
|
* The transformation can also be more explicitly written in components as
|
||||||
|
* follows:
|
||||||
|
* p' = (a * p + c * q + x) / z;
|
||||||
|
* q' = (b * p + d * q + y) / z;
|
||||||
|
* z = u * p + v * q + w
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Extract the rotation component of the transformation matrix.
|
||||||
|
*
|
||||||
|
* @param matrix the transformation matrix
|
||||||
|
* @return the angle (in degrees) by which the transformation rotates the frame
|
||||||
|
* counterclockwise. The angle will be in range [-180.0, 180.0],
|
||||||
|
* or NaN if the matrix is singular.
|
||||||
|
*
|
||||||
|
* @note floating point numbers are inherently inexact, so callers are
|
||||||
|
* recommended to round the return value to nearest integer before use.
|
||||||
|
*/
|
||||||
|
double av_display_rotation_get(const int32_t matrix[9]);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initialize a transformation matrix describing a pure counterclockwise
|
||||||
|
* rotation by the specified angle (in degrees).
|
||||||
|
*
|
||||||
|
* @param matrix an allocated transformation matrix (will be fully overwritten
|
||||||
|
* by this function)
|
||||||
|
* @param angle rotation angle in degrees.
|
||||||
|
*/
|
||||||
|
void av_display_rotation_set(int32_t matrix[9], double angle);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Flip the input matrix horizontally and/or vertically.
|
||||||
|
*
|
||||||
|
* @param matrix an allocated transformation matrix
|
||||||
|
* @param hflip whether the matrix should be flipped horizontally
|
||||||
|
* @param vflip whether the matrix should be flipped vertically
|
||||||
|
*/
|
||||||
|
void av_display_matrix_flip(int32_t matrix[9], int hflip, int vflip);
|
||||||
|
|
||||||
|
#endif /* AVUTIL_DISPLAY_H */
|
@ -0,0 +1,115 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2014 Tim Walker <tdskywalker@gmail.com>
|
||||||
|
*
|
||||||
|
* This file is part of FFmpeg.
|
||||||
|
*
|
||||||
|
* FFmpeg is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2.1 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* FFmpeg is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with FFmpeg; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef AVUTIL_DOWNMIX_INFO_H
|
||||||
|
#define AVUTIL_DOWNMIX_INFO_H
|
||||||
|
|
||||||
|
#include "frame.h"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @file
|
||||||
|
* audio downmix medatata
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @addtogroup lavu_audio
|
||||||
|
* @{
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @defgroup downmix_info Audio downmix metadata
|
||||||
|
* @{
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Possible downmix types.
|
||||||
|
*/
|
||||||
|
enum AVDownmixType {
|
||||||
|
AV_DOWNMIX_TYPE_UNKNOWN, /**< Not indicated. */
|
||||||
|
AV_DOWNMIX_TYPE_LORO, /**< Lo/Ro 2-channel downmix (Stereo). */
|
||||||
|
AV_DOWNMIX_TYPE_LTRT, /**< Lt/Rt 2-channel downmix, Dolby Surround compatible. */
|
||||||
|
AV_DOWNMIX_TYPE_DPLII, /**< Lt/Rt 2-channel downmix, Dolby Pro Logic II compatible. */
|
||||||
|
AV_DOWNMIX_TYPE_NB /**< Number of downmix types. Not part of ABI. */
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This structure describes optional metadata relevant to a downmix procedure.
|
||||||
|
*
|
||||||
|
* All fields are set by the decoder to the value indicated in the audio
|
||||||
|
* bitstream (if present), or to a "sane" default otherwise.
|
||||||
|
*/
|
||||||
|
typedef struct AVDownmixInfo {
|
||||||
|
/**
|
||||||
|
* Type of downmix preferred by the mastering engineer.
|
||||||
|
*/
|
||||||
|
enum AVDownmixType preferred_downmix_type;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Absolute scale factor representing the nominal level of the center
|
||||||
|
* channel during a regular downmix.
|
||||||
|
*/
|
||||||
|
double center_mix_level;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Absolute scale factor representing the nominal level of the center
|
||||||
|
* channel during an Lt/Rt compatible downmix.
|
||||||
|
*/
|
||||||
|
double center_mix_level_ltrt;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Absolute scale factor representing the nominal level of the surround
|
||||||
|
* channels during a regular downmix.
|
||||||
|
*/
|
||||||
|
double surround_mix_level;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Absolute scale factor representing the nominal level of the surround
|
||||||
|
* channels during an Lt/Rt compatible downmix.
|
||||||
|
*/
|
||||||
|
double surround_mix_level_ltrt;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Absolute scale factor representing the level at which the LFE data is
|
||||||
|
* mixed into L/R channels during downmixing.
|
||||||
|
*/
|
||||||
|
double lfe_mix_level;
|
||||||
|
} AVDownmixInfo;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get a frame's AV_FRAME_DATA_DOWNMIX_INFO side data for editing.
|
||||||
|
*
|
||||||
|
* If the side data is absent, it is created and added to the frame.
|
||||||
|
*
|
||||||
|
* @param frame the frame for which the side data is to be obtained or created
|
||||||
|
*
|
||||||
|
* @return the AVDownmixInfo structure to be edited by the caller, or NULL if
|
||||||
|
* the structure cannot be allocated.
|
||||||
|
*/
|
||||||
|
AVDownmixInfo *av_downmix_info_update_side_data(AVFrame *frame);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @}
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @}
|
||||||
|
*/
|
||||||
|
|
||||||
|
#endif /* AVUTIL_DOWNMIX_INFO_H */
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in new issue