Compare commits

...

18 Commits

Author SHA1 Message Date
PeizeLin
a56bad8bbb
Fix std::array<T,0> (#848)
* Fix std::array<T,0>

* Add unittests for std::array<T,0>

* update std::array
2025-01-19 21:00:41 -08:00
sjrdc
b4703c47ec Bump XCode versions 2025-01-19 19:00:00 -08:00
psykose
2c647d87d4 fix building tests when char is unsigned
when char is unsigned it's uint8_t which doesn't match the type declared
for the key of the map, so it fails with

error: non-constant-expression cannot be narrowed from type
'typename std::enable_if<std::is_integral<char>::value && sizeof(char) == sizeof(char), char>::type'
(aka 'char') to 'const signed char' in initializer list

etc
2024-12-23 18:09:09 -08:00
Diego Mateos
f7deca361c More robust __cplusplus check
Similar to the same check done a few lines above for c++17
2024-12-23 18:07:48 -08:00
Douglas Scofield
cb6c6ac1f0 create pkgconfig file during build 2024-12-23 18:03:55 -08:00
Shane Grant
864c2fc370 Merge branch 'sjrdc-master' 2024-12-22 12:24:11 -08:00
sjrdc
66d74f8cb9 Fix linux CI #846
- Does not address Mac/windows builds
2024-12-22 12:22:49 -08:00
Lukas Hübner
d1fcec807b Fix some typos (spelling) 2023-06-14 20:18:40 -07:00
Khem Raj
f3e31f32f7 sandbox: Do not use int8_t in std::uniform_int_distribution
Newer versions of libc++ has dropped supporting this usecase since its
an UB see.

https://reviews.llvm.org/D114920?id=400571

Fixes

uniform_int_distribution.h:162:5: error: static assertion failed due to requirement '__libcpp_random_is_valid_inttype<char>::value': IntType must be a supported integer type
    static_assert(__libcpp_random_is_valid_inttype<_IntType>::value, "IntType must be a supported integer type");
    ^             ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/mnt/b/yoe/master/build/tmp/work/core2-64-yoe-linux-musl/libcereal/1.3.2+gitAUTOINC+ebef1e9298-r0/git/sandbox/performance.cpp:261:9: note: in instantiation of template class 'std::uniform_int_distribution<char>' requested here
    c = std::uniform_int_distribution<char>(' ', '~')(gen);
        ^
/mnt/b/yoe/master/build/tmp/work/core2-64-yoe-linux-musl/libcereal/1.3.2+gitAUTOINC+ebef1e9298-r0/git/sandbox/performance.cpp:261:9: error: type 'std::uniform_int_distribution<char>' does not provide a call operator
    c = std::uniform_int_distribution<char>(' ', '~')(gen);
        ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2 errors generated.

Signed-off-by: Khem Raj <raj.khem@gmail.com>
2023-04-23 20:09:18 -07:00
astralaster
83b6fa06a0 Add ARCH_INDEPENDENT flag in CMakeLists.txt
If this package is flagged as ARCH_IDENPENDENT by cmake it is possible to consume the generated cmake files for compiling both 32bit and 64bit projects. Otherwise cmake will complain:
CMake Error at CMakeLists.txt:12 (find_package):
  Could not find a configuration file for package "cereal" that is compatible
  with requested version "".

  The following configuration files were considered but not accepted:

   cmake/cereal/cerealConfig.cmake, version: 1.3.2 (64bit)

Ive also added a version check to retain the compability with cmake
older than 3.14.

For more info about this flag look here:
https://cmake.org/cmake/help/latest/module/CMakePackageConfigHelpers.html
2023-04-23 20:03:11 -07:00
Alex Fan
b2d68c522b auto enable SKIP_PORTABILITY_TEST
also avoid unused CMake variable warning
2023-04-23 19:45:01 -07:00
Jan Niklas Hasse
ddd4672447 Remove extra ; after member function definition
Triggered by -Wextra-semi.
2022-03-27 14:54:17 -07:00
Luca Ciucci
5b37553aa9 ST renamed to AlignedStorage 2022-03-14 13:29:59 -07:00
Luca Ciucci
343473b752 Update .gitignore
`.vs/` folder is created by Visual Studio and it is not needed.
2022-03-14 13:29:59 -07:00
CHP
45e40375b6
Fix long long json serialization (#728)
* Fix long long json serialization

* Update pod.hpp
2022-03-14 13:29:42 -07:00
Shane Grant
ebef1e9298 Correct patch version for 1.3.2 2022-02-27 19:46:32 -08:00
Shane Grant
6e1c66a94c Add CMake options for building doc and sandbox
relates #739
2022-02-27 19:43:25 -08:00
Michael R. Crusoe
39d202053d Make doxygen docs reproducible 2022-02-27 19:28:28 -08:00
25 changed files with 260 additions and 130 deletions

View File

@ -10,18 +10,18 @@ jobs:
include: include:
- CMAKE_OPTIONS: '-DWITH_WERROR=OFF -DSKIP_PORTABILITY_TEST=ON -DSKIP_PERFORMANCE_COMPARISON=ON' - CMAKE_OPTIONS: '-DWITH_WERROR=OFF -DSKIP_PORTABILITY_TEST=ON -DSKIP_PERFORMANCE_COMPARISON=ON'
COMPILER: 'clang++' COMPILER: 'clang++'
XCODE_VERSION: 11 XCODE_VERSION: 15
NAME: macos-latest-clang-xcode11 NAME: macos-latest-clang-xcode15
- CMAKE_OPTIONS: '-DWITH_WERROR=OFF -DSKIP_PORTABILITY_TEST=ON -DSKIP_PERFORMANCE_COMPARISON=ON' - CMAKE_OPTIONS: '-DWITH_WERROR=OFF -DSKIP_PORTABILITY_TEST=ON -DSKIP_PERFORMANCE_COMPARISON=ON'
COMPILER: 'clang++' COMPILER: 'clang++'
XCODE_VERSION: 12 XCODE_VERSION: 16
NAME: macos-latest-clang-xcode12 NAME: macos-latest-clang-xcode16
name: ${{ matrix.name }} name: ${{ matrix.name }}
steps: steps:
- name: Checkout code - name: Checkout code
uses: actions/checkout@v2 uses: actions/checkout@v4
- uses: maxim-lobanov/setup-xcode@v1 - uses: maxim-lobanov/setup-xcode@v1
with: with:

View File

@ -4,7 +4,6 @@ on: [push, pull_request]
jobs: jobs:
test_cereal_linux: test_cereal_linux:
runs-on: ubuntu-latest runs-on: ubuntu-latest
container: ${{ matrix.CONTAINER }}
strategy: strategy:
fail-fast: false fail-fast: false
matrix: matrix:
@ -164,75 +163,75 @@ jobs:
name: ${{ matrix.name }} name: ${{ matrix.name }}
steps: steps:
- name: Checkout code - name: Check out the repo
uses: actions/checkout@v2 uses: actions/checkout@v4
- name: install deps and test - name: install deps and test
shell: bash uses: addnab/docker-run-action@v3
env: with:
CMAKE_OPTIONS: ${{ matrix.CMAKE_OPTIONS }} image: ${{ matrix.CONTAINER }}
COMPILER: ${{ matrix.COMPILER }} options: -v ${{ github.workspace }}:/var/workspace
EXTRA_APT_PACKAGES: ${{ matrix.EXTRA_APT_PACKAGES }} shell: bash
LLVM_APT_SOURCE: ${{ matrix.LLVM_APT_SOURCE }} run: |
run: | set -ex
set -ex apt-get update -y
apt-get update -y DEBIAN_FRONTEND=noninteractive TZ=America/Los_Angeles apt-get install -y software-properties-common wget python3-pip make apt-transport-https
DEBIAN_FRONTEND=noninteractive TZ=America/Los_Angeles apt-get install -y software-properties-common wget python3-pip make apt-transport-https
# Add apt repositories for older Ubuntu # Add apt repositories for older Ubuntu
. /etc/os-release . /etc/os-release
if [[ "${VERSION_ID}" == "16.04" ]]; then if [[ "${VERSION_ID}" == "16.04" ]]; then
add-apt-repository ppa:ubuntu-toolchain-r/test -y add-apt-repository ppa:ubuntu-toolchain-r/test -y
add-apt-repository ppa:mhier/libboost-latest -y add-apt-repository ppa:mhier/libboost-latest -y
fi
if [[ "${LLVM_APT_SOURCE}" != "" ]]; then
wget -qO - https://apt.llvm.org/llvm-snapshot.gpg.key | apt-key add -
add-apt-repository "${LLVM_APT_SOURCE}"
fi
apt-get update -y
# Install apt packages
apt-get install libboost-serialization-dev libboost-dev ${EXTRA_APT_PACKAGES} -y
pip3 install cmake
# Set compiler and env variables
export CXX=${COMPILER}
${CXX} --version
DEPS_DIR="${PWD}/deps"
mkdir -p "${DEPS_DIR}"
pushd "${DEPS_DIR}"
JOBS=2
# Install the right version of libc++
LLVM_INSTALL=${DEPS_DIR}/llvm/install
# if in linux and compiler clang and llvm not installed
if [[ "${CXX}" == "clang"* && -n "$(ls -A ${LLVM_INSTALL})" ]]; then
if [[ "${CXX}" == "clang++-3.6" ]]; then LLVM_VERSION="3.6.2";
elif [[ "${CXX}" == "clang++-3.7" ]]; then LLVM_VERSION="3.7.1";
elif [[ "${CXX}" == "clang++-3.8" ]]; then LLVM_VERSION="3.8.1";
elif [[ "${CXX}" == "clang++-3.9" ]]; then LLVM_VERSION="3.9.1";
fi fi
LLVM_URL="http://llvm.org/releases/${LLVM_VERSION}/llvm-${LLVM_VERSION}.src.tar.xz"
LIBCXX_URL="http://llvm.org/releases/${LLVM_VERSION}/libcxx-${LLVM_VERSION}.src.tar.xz"
LIBCXXABI_URL="http://llvm.org/releases/${LLVM_VERSION}/libcxxabi-${LLVM_VERSION}.src.tar.xz"
mkdir -p llvm llvm/build llvm/projects/libcxx llvm/projects/libcxxabi
wget -O - ${LLVM_URL} | tar --strip-components=1 -xJ -C llvm
wget -O - ${LIBCXX_URL} | tar --strip-components=1 -xJ -C llvm/projects/libcxx
wget -O - ${LIBCXXABI_URL} | tar --strip-components=1 -xJ -C llvm/projects/libcxxabi
(cd llvm/build && cmake .. -DCMAKE_INSTALL_PREFIX=${LLVM_INSTALL})
(cd llvm/build/projects/libcxx && make install -j2)
(cd llvm/build/projects/libcxxabi && make install -j2)
export CXXFLAGS="-isystem ${LLVM_INSTALL}/include/c++/v1"
export LDFLAGS="-L ${LLVM_INSTALL}/lib -l c++ -l c++abi"
export LD_LIBRARY_PATH="${LD_LIBRARY_PATH}:${LLVM_INSTALL}/lib"
fi
popd if [[ "${{ matrix.LLVM_APT_SOURCE }}" != "" ]]; then
wget -qO - https://apt.llvm.org/llvm-snapshot.gpg.key | apt-key add -
add-apt-repository "${{ matrix.LLVM_APT_SOURCE }}"
fi
# Build cereal and test apt-get update -y
cmake --version
mkdir build && cd build # Install apt packages
cmake ${CMAKE_OPTIONS} .. && make -j4 VERBOSE=1 apt-get install libboost-serialization-dev libboost-dev ${{ matrix.EXTRA_APT_PACKAGES }} -y
ctest . --output-on-failure pip3 install --upgrade "pip < 21.0"
pip3 install cmake
# Set compiler and env variables
cd /var/workspace
export CXX=${{ matrix.COMPILER }}
${CXX} --version
DEPS_DIR="${PWD}/deps"
mkdir -p "${DEPS_DIR}"
pushd "${DEPS_DIR}"
JOBS=2
# Install the right version of libc++
LLVM_INSTALL=${DEPS_DIR}/llvm/install
# if in linux and compiler clang and llvm not installed
if [[ "${CXX}" == "clang"* && -n "$(ls -A ${LLVM_INSTALL})" ]]; then
if [[ "${CXX}" == "clang++-3.6" ]]; then LLVM_VERSION="3.6.2";
elif [[ "${CXX}" == "clang++-3.7" ]]; then LLVM_VERSION="3.7.1";
elif [[ "${CXX}" == "clang++-3.8" ]]; then LLVM_VERSION="3.8.1";
elif [[ "${CXX}" == "clang++-3.9" ]]; then LLVM_VERSION="3.9.1";
fi
LLVM_URL="http://llvm.org/releases/${LLVM_VERSION}/llvm-${LLVM_VERSION}.src.tar.xz"
LIBCXX_URL="http://llvm.org/releases/${LLVM_VERSION}/libcxx-${LLVM_VERSION}.src.tar.xz"
LIBCXXABI_URL="http://llvm.org/releases/${LLVM_VERSION}/libcxxabi-${LLVM_VERSION}.src.tar.xz"
mkdir -p llvm llvm/build llvm/projects/libcxx llvm/projects/libcxxabi
wget -O - ${LLVM_URL} | tar --strip-components=1 -xJ -C llvm
wget -O - ${LIBCXX_URL} | tar --strip-components=1 -xJ -C llvm/projects/libcxx
wget -O - ${LIBCXXABI_URL} | tar --strip-components=1 -xJ -C llvm/projects/libcxxabi
(cd llvm/build && cmake .. -DCMAKE_INSTALL_PREFIX=${LLVM_INSTALL})
(cd llvm/build/projects/libcxx && make install -j2)
(cd llvm/build/projects/libcxxabi && make install -j2)
export CXXFLAGS="-isystem ${LLVM_INSTALL}/include/c++/v1"
export LDFLAGS="-L ${LLVM_INSTALL}/lib -l c++ -l c++abi"
export LD_LIBRARY_PATH="${LD_LIBRARY_PATH}:${LLVM_INSTALL}/lib"
fi
popd
# Build cereal and test
cmake --version
mkdir build && cd build
cmake ${{ matrix.CMAKE_OPTIONS }} .. && make -j4 VERBOSE=1
ctest . --output-on-failure

2
.gitignore vendored
View File

@ -28,6 +28,8 @@
*.pdb *.pdb
*.idb *.idb
*\build_* *\build_*
.vs/
CMakeSettings.json
# misc files mostly used for testing # misc files mostly used for testing
out.txt out.txt

View File

@ -1,17 +1,23 @@
cmake_minimum_required(VERSION 3.6...3.15) cmake_minimum_required(VERSION 3.6...3.15)
project(cereal LANGUAGES CXX VERSION 1.3.1) project(cereal LANGUAGES CXX VERSION 1.3.2)
if(PROJECT_SOURCE_DIR STREQUAL CMAKE_SOURCE_DIR) if(PROJECT_SOURCE_DIR STREQUAL CMAKE_SOURCE_DIR)
set(CEREAL_MASTER_PROJECT ON) set(CEREAL_MASTER_PROJECT ON)
endif() endif()
option(SKIP_PORTABILITY_TEST "Skip portability (32 bit) tests" OFF)
if(APPLE) include(CheckCXXCompilerFlag)
option(SKIP_PORTABILITY_TEST "Skip portability (32 bit) tests" ON) set(CMAKE_REQUIRED_FLAGS "-m32")
check_cxx_compiler_flag("-m32" COMPILER_SUPPORT_M32)
unset(CMAKE_REQUIRED_FLAGS)
if(NOT COMPILER_SUPPORT_M32)
set(SKIP_PORTABILITY_TEST ON CACHE BOOL "Skip portability (32 bit) tests" FORCE)
endif() endif()
option(SKIP_PERFORMANCE_COMPARISON "Skip building performance comparison (requires boost)" OFF) option(BUILD_DOC "Build documentation" ON)
option(BUILD_SANDBOX "Build sandbox examples" ON)
option(SKIP_PERFORMANCE_COMPARISON "Skip building performance sandbox comparison (requires boost)" OFF)
# TODO: should not be needed! CK # TODO: should not be needed! CK
if(NOT CMAKE_VERSION VERSION_LESS 3.0) # installing cereal requires INTERFACE lib if(NOT CMAKE_VERSION VERSION_LESS 3.0) # installing cereal requires INTERFACE lib
@ -85,9 +91,15 @@ if(CEREAL_INSTALL)
${configFile} ${configFile}
INSTALL_DESTINATION ${configInstallDestination} INSTALL_DESTINATION ${configInstallDestination}
) )
write_basic_package_version_file( if(${CMAKE_VERSION} VERSION_GREATER 3.13)
${versionFile} write_basic_package_version_file("${versionFile}" COMPATIBILITY SameMajorVersion ARCH_INDEPENDENT)
COMPATIBILITY SameMajorVersion else()
write_basic_package_version_file("${versionFile}" COMPATIBILITY SameMajorVersion)
endif()
configure_file(
${CMAKE_CURRENT_SOURCE_DIR}/${PROJECT_NAME}.pc.in
${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}.pc
@ONLY
) )
install(FILES ${configFile} ${versionFile} DESTINATION ${configInstallDestination}) install(FILES ${configFile} ${versionFile} DESTINATION ${configInstallDestination})
@ -96,6 +108,10 @@ if(CEREAL_INSTALL)
NAMESPACE "cereal::" NAMESPACE "cereal::"
DESTINATION ${configInstallDestination} DESTINATION ${configInstallDestination}
) )
install(
FILES ${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}.pc
DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/pkgconfig
)
endif() endif()
@ -116,6 +132,12 @@ if(BUILD_TESTS)
add_subdirectory(unittests) add_subdirectory(unittests)
endif() endif()
add_subdirectory(sandbox)
add_subdirectory(doc) if(BUILD_SANDBOX)
add_subdirectory(sandbox)
endif()
if(BUILD_DOC)
add_subdirectory(doc)
endif()

8
cereal.pc.in Normal file
View File

@ -0,0 +1,8 @@
prefix=@CMAKE_INSTALL_PREFIX@
includedir=${prefix}/@CMAKE_INSTALL_INCLUDEDIR@
Name: @PROJECT_NAME@
Description: cereal is a header-only C++11 serialization library
URL: https://uscilab.github.io/cereal/
Version: @PROJECT_VERSION@
Cflags: -I"${includedir}"

View File

@ -119,7 +119,7 @@ INLINE_INHERITED_MEMB = NO
# path before files name in the file list and in the header files. If set # path before files name in the file list and in the header files. If set
# to NO the shortest path that makes the file name unique will be used. # to NO the shortest path that makes the file name unique will be used.
FULL_PATH_NAMES = YES FULL_PATH_NAMES = NO
# If the FULL_PATH_NAMES tag is set to YES then the STRIP_FROM_PATH tag # If the FULL_PATH_NAMES tag is set to YES then the STRIP_FROM_PATH tag
# can be used to strip a user-defined part of the path. Stripping is # can be used to strip a user-defined part of the path. Stripping is
@ -130,7 +130,7 @@ FULL_PATH_NAMES = YES
# relative paths, which will be relative from the directory where doxygen is # relative paths, which will be relative from the directory where doxygen is
# started. # started.
STRIP_FROM_PATH = STRIP_FROM_PATH = @PROJECT_SOURCE_DIR@
# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of # The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of
# the path mentioned in the documentation of a class, which tells # the path mentioned in the documentation of a class, which tells

View File

@ -188,7 +188,7 @@ namespace cereal
auto base64string = base64::encode( reinterpret_cast<const unsigned char *>( data ), size ); auto base64string = base64::encode( reinterpret_cast<const unsigned char *>( data ), size );
saveValue( base64string ); saveValue( base64string );
}; }
//! @} //! @}
/*! @name Internal Functionality /*! @name Internal Functionality
@ -261,6 +261,13 @@ namespace cereal
//! Saves a nullptr to the current node //! Saves a nullptr to the current node
void saveValue(std::nullptr_t) { itsWriter.Null(); } void saveValue(std::nullptr_t) { itsWriter.Null(); }
template <class T> inline
typename std::enable_if<!std::is_same<T, int64_t>::value && std::is_same<T, long long>::value, void>::type
saveValue(T val) { itsWriter.Int64(val); }
template <class T> inline
typename std::enable_if<!std::is_same<T, uint64_t>::value && std::is_same<T, unsigned long long>::value, void>::type
saveValue(T val) { itsWriter.Uint64(val); }
private: private:
// Some compilers/OS have difficulty disambiguating the above for various flavors of longs, so we provide // Some compilers/OS have difficulty disambiguating the above for various flavors of longs, so we provide
// special overloads to handle these cases. // special overloads to handle these cases.
@ -310,6 +317,8 @@ namespace cereal
!std::is_same<T, unsigned long>::value, !std::is_same<T, unsigned long>::value,
!std::is_same<T, std::int64_t>::value, !std::is_same<T, std::int64_t>::value,
!std::is_same<T, std::uint64_t>::value, !std::is_same<T, std::uint64_t>::value,
!std::is_same<T, long long>::value,
!std::is_same<T, unsigned long long>::value,
(sizeof(T) >= sizeof(long double) || sizeof(T) >= sizeof(long long))> = traits::sfinae> inline (sizeof(T) >= sizeof(long double) || sizeof(T) >= sizeof(long long))> = traits::sfinae> inline
void saveValue(T const & t) void saveValue(T const & t)
{ {
@ -465,7 +474,7 @@ namespace cereal
std::memcpy( data, decoded.data(), decoded.size() ); std::memcpy( data, decoded.data(), decoded.size() );
itsNextName = nullptr; itsNextName = nullptr;
}; }
private: private:
//! @} //! @}
@ -659,6 +668,12 @@ namespace cereal
//! Loads a nullptr from the current node //! Loads a nullptr from the current node
void loadValue(std::nullptr_t&) { search(); CEREAL_RAPIDJSON_ASSERT(itsIteratorStack.back().value().IsNull()); ++itsIteratorStack.back(); } void loadValue(std::nullptr_t&) { search(); CEREAL_RAPIDJSON_ASSERT(itsIteratorStack.back().value().IsNull()); ++itsIteratorStack.back(); }
template <class T> inline
typename std::enable_if<!std::is_same<T, int64_t>::value && std::is_same<T, long long>::value, void>::type
loadValue(T & val) { search(); val = itsIteratorStack.back().value().GetInt64(); ++itsIteratorStack.back(); }
template <class T> inline
typename std::enable_if<!std::is_same<T, uint64_t>::value && std::is_same<T, unsigned long long>::value, void>::type
loadValue(T & val) { search(); val = itsIteratorStack.back().value().GetUint64(); ++itsIteratorStack.back(); }
// Special cases to handle various flavors of long, which tend to conflict with // 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. // the int32_t or int64_t on various compiler/OS combinations. MSVC doesn't need any of this.
#ifndef _MSC_VER #ifndef _MSC_VER
@ -714,6 +729,8 @@ namespace cereal
!std::is_same<T, unsigned long>::value, !std::is_same<T, unsigned long>::value,
!std::is_same<T, std::int64_t>::value, !std::is_same<T, std::int64_t>::value,
!std::is_same<T, std::uint64_t>::value, !std::is_same<T, std::uint64_t>::value,
!std::is_same<T, long long>::value,
!std::is_same<T, unsigned long long>::value,
(sizeof(T) >= sizeof(long double) || sizeof(T) >= sizeof(long long))> = traits::sfinae> (sizeof(T) >= sizeof(long double) || sizeof(T) >= sizeof(long long))> = traits::sfinae>
inline void loadValue(T & val) inline void loadValue(T & val)
{ {

View File

@ -136,7 +136,7 @@ namespace cereal
*/ */
//! @{ //! @{
//! Sets the precision used for floaing point numbers //! Sets the precision used for floating point numbers
Options & precision( int value ){ itsPrecision = value; return * this; } Options & precision( int value ){ itsPrecision = value; return * this; }
//! Whether to indent each line of XML //! Whether to indent each line of XML
Options & indent( bool enable ){ itsIndent = enable; return *this; } Options & indent( bool enable ){ itsIndent = enable; return *this; }

View File

@ -176,7 +176,7 @@ namespace cereal
a serialization function. Classes with no data members are considered to be 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. Be warned that if this is enabled and you attempt to serialize an
empty class with improperly formed serialize or load/save functions, no empty class with improperly formed serialize or load/save functions, no
static error will occur - the error will propogate silently and your static error will occur - the error will propagate silently and your
intended serialization functions may not be called. You can manually intended serialization functions may not be called. You can manually
ensure that your classes that have custom serialization are correct ensure that your classes that have custom serialization are correct
by using the traits is_output_serializable and is_input_serializable by using the traits is_output_serializable and is_input_serializable
@ -391,7 +391,7 @@ namespace cereal
point to the same data. point to the same data.
@internal @internal
@param sharedPointer The shared pointer itself (the adress is taked via get()). @param sharedPointer The shared pointer itself (the address is taken via get()).
The archive takes a copy to prevent the memory location to be freed The archive takes a copy to prevent the memory location to be freed
as long as the address is used as id. This is needed to prevent CVE-2020-11105. as long as the address is used as id. This is needed to prevent CVE-2020-11105.
@return A key that uniquely identifies the pointer */ @return A key that uniquely identifies the pointer */
@ -820,7 +820,7 @@ namespace cereal
@internal @internal
@param id The unique id that was serialized for the polymorphic type @param id The unique id that was serialized for the polymorphic type
@return The string identifier for the tyep */ @return The string identifier for the type */
inline std::string getPolymorphicName(std::uint32_t const id) inline std::string getPolymorphicName(std::uint32_t const id)
{ {
auto name = itsPolymorphicTypeMap.find( id ); auto name = itsPolymorphicTypeMap.find( id );
@ -837,7 +837,7 @@ namespace cereal
@internal @internal
@param id The unique identifier for the polymorphic type @param id The unique identifier for the polymorphic type
@param name The name associated with the tyep */ @param name The name associated with the type */
inline void registerPolymorphicName(std::uint32_t const id, std::string const & name) inline void registerPolymorphicName(std::uint32_t const id, std::string const & name)
{ {
std::uint32_t const stripped_id = id & ~detail::msb_32bit; std::uint32_t const stripped_id = id & ~detail::msb_32bit;

View File

@ -64,7 +64,7 @@
#define CEREAL_BIND_TO_ARCHIVES_UNUSED_FUNCTION static void unused() { (void)b; } #define CEREAL_BIND_TO_ARCHIVES_UNUSED_FUNCTION static void unused() { (void)b; }
#endif #endif
//! Binds a polymorhic type to all registered archives //! Binds a polymorphic type to all registered archives
/*! This binds a polymorphic type to all compatible registered archives that /*! This binds a polymorphic type to all compatible registered archives that
have been registered with CEREAL_REGISTER_ARCHIVE. This must be called have been registered with CEREAL_REGISTER_ARCHIVE. This must be called
after all archives are registered (usually after the archives themselves after all archives are registered (usually after the archives themselves
@ -277,8 +277,8 @@ namespace cereal
// Find all chainable unregistered relations // Find all chainable unregistered relations
/* The strategy here is to process only the nodes in the class hierarchy graph that have been /* The strategy here is to process only the nodes in the class hierarchy graph that have been
affected by the new insertion. The aglorithm iteratively processes a node an ensures that it affected by the new insertion. The algorithm iteratively processes a node an ensures that it
is updated with all new shortest length paths. It then rocesses the parents of the active node, is updated with all new shortest length paths. It then processes the parents of the active node,
with the knowledge that all children have already been processed. with the knowledge that all children have already been processed.
Note that for the following, we'll use the nomenclature of parent and child to not confuse with Note that for the following, we'll use the nomenclature of parent and child to not confuse with
@ -335,7 +335,7 @@ namespace cereal
auto parentChildPath = checkRelation( parent, child ); auto parentChildPath = checkRelation( parent, child );
// Search all paths from the child to its own children (finalChild), // Search all paths from the child to its own children (finalChild),
// looking for a shorter parth from parent to finalChild // looking for a shorter path from parent to finalChild
for( auto const & finalChildPair : baseMap[child] ) for( auto const & finalChildPair : baseMap[child] )
{ {
const auto finalChild = finalChildPair.first; const auto finalChild = finalChildPair.first;
@ -812,7 +812,7 @@ namespace cereal
Since the compiler needs to check all possible overloads, the Since the compiler needs to check all possible overloads, the
other overloads created via CEREAL_REGISTER_ARCHIVE, which will have other overloads created via CEREAL_REGISTER_ARCHIVE, which will have
lower precedence due to requring a conversion from int to (Archive*), lower precedence due to requiring a conversion from int to (Archive*),
will cause their return types to be instantiated through the static object will cause their return types to be instantiated through the static object
mechanisms even though they are never called. mechanisms even though they are never called.

View File

@ -141,7 +141,7 @@
#endif #endif
//! Checks if C++14 is available //! Checks if C++14 is available
#if __cplusplus >= 201402L #if (__cplusplus >= 201402L || (defined(_MSVC_LANG) && _MSVC_LANG >= 201402L))
#define CEREAL_HAS_CPP14 #define CEREAL_HAS_CPP14
#endif #endif

View File

@ -42,7 +42,7 @@ namespace cereal
&& std::is_arithmetic<T>::value, void>::type && std::is_arithmetic<T>::value, void>::type
CEREAL_SAVE_FUNCTION_NAME( Archive & ar, std::array<T, N> const & array ) CEREAL_SAVE_FUNCTION_NAME( Archive & ar, std::array<T, N> const & array )
{ {
ar( binary_data( array.data(), sizeof(array) ) ); ar( binary_data( array.data(), N*sizeof(T) ) );
} }
//! Loading for std::array primitive types //! Loading for std::array primitive types
@ -52,7 +52,7 @@ namespace cereal
&& std::is_arithmetic<T>::value, void>::type && std::is_arithmetic<T>::value, void>::type
CEREAL_LOAD_FUNCTION_NAME( Archive & ar, std::array<T, N> & array ) CEREAL_LOAD_FUNCTION_NAME( Archive & ar, std::array<T, N> & array )
{ {
ar( binary_data( array.data(), sizeof(array) ) ); ar( binary_data( array.data(), N*sizeof(T) ) );
} }
//! Saving for std::array all other types //! Saving for std::array all other types

View File

@ -286,7 +286,7 @@ namespace cereal
{ {
// Storage type for the pointer - since we can't default construct this type, // 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 // we'll allocate it using std::aligned_storage and use a custom deleter
using ST = typename std::aligned_storage<sizeof(T), CEREAL_ALIGNOF(T)>::type; using AlignedStorage = typename std::aligned_storage<sizeof(T), CEREAL_ALIGNOF(T)>::type;
// Valid flag - set to true once construction finishes // Valid flag - set to true once construction finishes
// This prevents us from calling the destructor on // This prevents us from calling the destructor on
@ -296,13 +296,13 @@ namespace cereal
// Allocate our storage, which we will treat as // Allocate our storage, which we will treat as
// uninitialized until initialized with placement new // uninitialized until initialized with placement new
using NonConstT = typename std::remove_const<T>::type; using NonConstT = typename std::remove_const<T>::type;
std::shared_ptr<NonConstT> ptr(reinterpret_cast<NonConstT *>(new ST()), std::shared_ptr<NonConstT> ptr(reinterpret_cast<NonConstT *>(new AlignedStorage()),
[=]( NonConstT * t ) [=]( NonConstT * t )
{ {
if( *valid ) if( *valid )
t->~T(); t->~T();
delete reinterpret_cast<ST *>( t ); delete reinterpret_cast<AlignedStorage*>( t );
} ); } );
// Register the pointer // Register the pointer
@ -377,11 +377,11 @@ namespace cereal
using NonConstT = typename std::remove_const<T>::type; using NonConstT = typename std::remove_const<T>::type;
// Storage type for the pointer - since we can't default construct this type, // Storage type for the pointer - since we can't default construct this type,
// we'll allocate it using std::aligned_storage // we'll allocate it using std::aligned_storage
using ST = typename std::aligned_storage<sizeof(NonConstT), CEREAL_ALIGNOF(NonConstT)>::type; using AlignedStorage = typename std::aligned_storage<sizeof(NonConstT), CEREAL_ALIGNOF(NonConstT)>::type;
// Allocate storage - note the ST type so that deleter is correct if // Allocate storage - note the AlignedStorage type so that deleter is correct if
// an exception is thrown before we are initialized // an exception is thrown before we are initialized
std::unique_ptr<ST> stPtr( new ST() ); std::unique_ptr<AlignedStorage> stPtr( new AlignedStorage() );
// Use wrapper to enter into "data" nvp of ptr_wrapper // Use wrapper to enter into "data" nvp of ptr_wrapper
memory_detail::LoadAndConstructLoadWrapper<Archive, NonConstT> loadWrapper( reinterpret_cast<NonConstT *>( stPtr.get() ) ); memory_detail::LoadAndConstructLoadWrapper<Archive, NonConstT> loadWrapper( reinterpret_cast<NonConstT *>( stPtr.get() ) );

View File

@ -42,7 +42,7 @@
//! The minor version //! The minor version
#define CEREAL_VERSION_MINOR 3 #define CEREAL_VERSION_MINOR 3
//! The patch version //! The patch version
#define CEREAL_VERSION_PATCH 0 #define CEREAL_VERSION_PATCH 2
//! The full version as a single number //! The full version as a single number
#define CEREAL_VERSION (CEREAL_VERSION_MAJOR * 10000 \ #define CEREAL_VERSION (CEREAL_VERSION_MAJOR * 10000 \

View File

@ -258,7 +258,7 @@ random_value(std::mt19937 & gen)
{ {
std::string s(std::uniform_int_distribution<int>(3, 30)(gen), ' '); std::string s(std::uniform_int_distribution<int>(3, 30)(gen), ' ');
for(char & c : s) for(char & c : s)
c = std::uniform_int_distribution<char>(' ', '~')(gen); c = static_cast<char>( std::uniform_int_distribution<int>(' ', '~')(gen) );
return s; return s;
} }
@ -277,7 +277,7 @@ std::string random_binary_string(std::mt19937 & gen)
{ {
std::string s(N, ' '); std::string s(N, ' ');
for(auto & c : s ) for(auto & c : s )
c = std::uniform_int_distribution<char>('0', '1')(gen); c = static_cast<char>( std::uniform_int_distribution<int>( '0', '1' )(gen) );
return s; return s;
} }

View File

@ -714,7 +714,7 @@ int main()
std::ifstream ss("xml_ordering.out"); std::ifstream ss("xml_ordering.out");
cereal::XMLInputArchive ar(ss); cereal::XMLInputArchive ar(ss);
// Output prodered out of order, try to load in order 1 2 3 4 // Output out of order, try to load in order 1 2 3 4
double one; double one;
double two; double two;
double three; double three;

View File

@ -77,7 +77,7 @@ CEREAL_SETUP_ARCHIVE_TRAITS(Archive, Archive)
struct Test struct Test
{ {
template <class Archive> template <class Archive>
void serialzize( Archive & ) void serialize( Archive & )
{ {
std::cout << "hey there" << std::endl; std::cout << "hey there" << std::endl;
} }

View File

@ -31,22 +31,26 @@ TEST_SUITE_BEGIN("array");
TEST_CASE("binary_array") TEST_CASE("binary_array")
{ {
test_array<cereal::BinaryInputArchive, cereal::BinaryOutputArchive>(); test_array<cereal::BinaryInputArchive, cereal::BinaryOutputArchive, 0>();
test_array<cereal::BinaryInputArchive, cereal::BinaryOutputArchive, 100>();
} }
TEST_CASE("portable_binary_array") TEST_CASE("portable_binary_array")
{ {
test_array<cereal::PortableBinaryInputArchive, cereal::PortableBinaryOutputArchive>(); test_array<cereal::PortableBinaryInputArchive, cereal::PortableBinaryOutputArchive, 0>();
test_array<cereal::PortableBinaryInputArchive, cereal::PortableBinaryOutputArchive, 100>();
} }
TEST_CASE("xml_array") TEST_CASE("xml_array")
{ {
test_array<cereal::XMLInputArchive, cereal::XMLOutputArchive>(); test_array<cereal::XMLInputArchive, cereal::XMLOutputArchive, 0>();
test_array<cereal::XMLInputArchive, cereal::XMLOutputArchive, 100>();
} }
TEST_CASE("json_array") TEST_CASE("json_array")
{ {
test_array<cereal::JSONInputArchive, cereal::JSONOutputArchive>(); test_array<cereal::JSONInputArchive, cereal::JSONOutputArchive, 0>();
test_array<cereal::JSONInputArchive, cereal::JSONOutputArchive, 100>();
} }
TEST_SUITE_END(); TEST_SUITE_END();

View File

@ -28,7 +28,7 @@
#define CEREAL_TEST_ARRAY_H_ #define CEREAL_TEST_ARRAY_H_
#include "common.hpp" #include "common.hpp"
template <class IArchive, class OArchive> inline template <class IArchive, class OArchive, size_t N> inline
void test_array() void test_array()
{ {
std::random_device rd; std::random_device rd;
@ -36,23 +36,23 @@ void test_array()
for(int ii=0; ii<100; ++ii) for(int ii=0; ii<100; ++ii)
{ {
std::array<int, 100> o_podarray; std::array<int, N> o_podarray;
for(auto & elem : o_podarray) for(auto & elem : o_podarray)
elem = random_value<int>(gen); elem = random_value<int>(gen);
std::array<StructInternalSerialize, 100> o_iserarray; std::array<StructInternalSerialize, N> o_iserarray;
for(auto & elem : o_iserarray) for(auto & elem : o_iserarray)
elem = StructInternalSerialize( random_value<int>(gen), random_value<int>(gen) ); elem = StructInternalSerialize( random_value<int>(gen), random_value<int>(gen) );
std::array<StructInternalSplit, 100> o_isplarray; std::array<StructInternalSplit, N> o_isplarray;
for(auto & elem : o_isplarray) for(auto & elem : o_isplarray)
elem = StructInternalSplit( random_value<int>(gen), random_value<int>(gen) ); elem = StructInternalSplit( random_value<int>(gen), random_value<int>(gen) );
std::array<StructExternalSerialize, 100> o_eserarray; std::array<StructExternalSerialize, N> o_eserarray;
for(auto & elem : o_eserarray) for(auto & elem : o_eserarray)
elem = StructExternalSerialize( random_value<int>(gen), random_value<int>(gen) ); elem = StructExternalSerialize( random_value<int>(gen), random_value<int>(gen) );
std::array<StructExternalSplit, 100> o_esplarray; std::array<StructExternalSplit, N> o_esplarray;
for(auto & elem : o_esplarray) for(auto & elem : o_esplarray)
elem = StructExternalSplit( random_value<int>(gen), random_value<int>(gen) ); elem = StructExternalSplit( random_value<int>(gen), random_value<int>(gen) );
@ -67,11 +67,11 @@ void test_array()
oar(o_esplarray); oar(o_esplarray);
} }
std::array<int, 100> i_podarray; std::array<int, N> i_podarray;
std::array<StructInternalSerialize, 100> i_iserarray; std::array<StructInternalSerialize, N> i_iserarray;
std::array<StructInternalSplit, 100> i_isplarray; std::array<StructInternalSplit, N> i_isplarray;
std::array<StructExternalSerialize, 100> i_eserarray; std::array<StructExternalSerialize, N> i_eserarray;
std::array<StructExternalSplit, 100> i_esplarray; std::array<StructExternalSplit, N> i_esplarray;
std::istringstream is(os.str()); std::istringstream is(os.str());
{ {

View File

@ -62,7 +62,7 @@ void test_map()
std::map<int8_t, StructExternalSplit> o_esplmap; std::map<int8_t, StructExternalSplit> o_esplmap;
for(int j=0; j<100; ++j) for(int j=0; j<100; ++j)
o_esplmap.insert({random_value<char>(gen), { random_value<int>(gen), random_value<int>(gen) }}); o_esplmap.insert({random_value<int8_t>(gen), { random_value<int>(gen), random_value<int>(gen) }});
std::ostringstream os; std::ostringstream os;
{ {

View File

@ -71,7 +71,7 @@ void test_multimap()
std::multimap<int8_t, StructExternalSplit> o_esplmultimap; std::multimap<int8_t, StructExternalSplit> o_esplmultimap;
for(int j=0; j<100; ++j) for(int j=0; j<100; ++j)
{ {
auto key = random_value<char>(gen); auto key = random_value<int8_t>(gen);
o_esplmultimap.insert({key, { random_value<int>(gen), random_value<int>(gen) }}); o_esplmultimap.insert({key, { random_value<int>(gen), random_value<int>(gen) }});
o_esplmultimap.insert({key, { random_value<int>(gen), random_value<int>(gen) }}); o_esplmultimap.insert({key, { random_value<int>(gen), random_value<int>(gen) }});
} }

View File

@ -49,4 +49,14 @@ TEST_CASE("json_pod")
test_pod<cereal::JSONInputArchive, cereal::JSONOutputArchive>(); test_pod<cereal::JSONInputArchive, cereal::JSONOutputArchive>();
} }
TEST_CASE("xml_pod_serialization")
{
test_pod_serialization<cereal::XMLInputArchive, cereal::XMLOutputArchive>();
}
TEST_CASE("json_pod_serialization")
{
test_pod_serialization<cereal::JSONInputArchive, cereal::JSONOutputArchive>();
}
TEST_SUITE_END(); TEST_SUITE_END();

View File

@ -144,4 +144,72 @@ void test_pod()
} }
} }
template <class IArchive, class OArchive, class T1, class T2>
void test_pod_serialization(std::mt19937& gen)
{
T1 const o_t1 = random_value<T1>(gen);
T2 const o_t2 = o_t1;
std::ostringstream os1;
{
OArchive oar(os1);
oar(o_t1);
}
std::ostringstream os2;
{
OArchive oar(os2);
oar(o_t2);
}
CHECK_EQ(os1.str(), os2.str());
T1 i_t1 = T1();
T2 i_t2 = T2();
CHECK_EQ(os1.str(), os2.str());
std::istringstream is1(os1.str());
{
IArchive iar(is1);
iar(i_t1);
}
CHECK_EQ(o_t1, i_t1);
std::istringstream is2(os2.str());
{
IArchive iar(is2);
iar(i_t2);
}
CHECK_EQ(o_t2, i_t2);
}
template <class IArchive, class OArchive>
void test_pod_serialization()
{
std::random_device rd;
std::mt19937 gen(rd());
for (size_t i = 0; i < 100; ++i) {
test_pod_serialization<IArchive, OArchive, int8_t, int16_t>(gen);
test_pod_serialization<IArchive, OArchive, uint8_t, uint16_t>(gen);
test_pod_serialization<IArchive, OArchive, int8_t, int32_t>(gen);
test_pod_serialization<IArchive, OArchive, uint8_t, uint32_t>(gen);
test_pod_serialization<IArchive, OArchive, int8_t, int64_t>(gen);
test_pod_serialization<IArchive, OArchive, uint8_t, uint64_t>(gen);
test_pod_serialization<IArchive, OArchive, int8_t, long>(gen);
test_pod_serialization<IArchive, OArchive, uint8_t, unsigned long>(gen);
test_pod_serialization<IArchive, OArchive, int8_t, long long>(gen);
test_pod_serialization<IArchive, OArchive, uint8_t, unsigned long long>(
gen);
test_pod_serialization<IArchive, OArchive, int8_t, int>(gen);
test_pod_serialization<IArchive, OArchive, uint8_t, unsigned int>(gen);
test_pod_serialization<IArchive, OArchive, int8_t, short>(gen);
test_pod_serialization<IArchive, OArchive, uint8_t, unsigned short>(gen);
}
}
#endif // CEREAL_TEST_POD_H_ #endif // CEREAL_TEST_POD_H_

View File

@ -54,7 +54,7 @@ void test_unordered_map()
std::unordered_map<int8_t, StructExternalSplit> o_esplunordered_map; std::unordered_map<int8_t, StructExternalSplit> o_esplunordered_map;
for(int j=0; j<100; ++j) for(int j=0; j<100; ++j)
o_esplunordered_map.insert({random_value<char>(gen), { random_value<int>(gen), random_value<int>(gen) }}); o_esplunordered_map.insert({random_value<int8_t>(gen), { random_value<int>(gen), random_value<int>(gen) }});
std::ostringstream os; std::ostringstream os;
{ {

View File

@ -71,7 +71,7 @@ void test_unordered_multimap()
std::unordered_multimap<int8_t, StructExternalSplit> o_esplunordered_multimap; std::unordered_multimap<int8_t, StructExternalSplit> o_esplunordered_multimap;
for(int j=0; j<100; ++j) for(int j=0; j<100; ++j)
{ {
auto key = random_value<char>(gen); auto key = random_value<int8_t>(gen);
o_esplunordered_multimap.insert({key, { random_value<int>(gen), random_value<int>(gen) }}); o_esplunordered_multimap.insert({key, { random_value<int>(gen), random_value<int>(gen) }});
o_esplunordered_multimap.insert({key, { random_value<int>(gen), random_value<int>(gen) }}); o_esplunordered_multimap.insert({key, { random_value<int>(gen), random_value<int>(gen) }});
} }