Compare commits

..

No commits in common. "master" and "v1.2.1" have entirely different histories.

206 changed files with 8180 additions and 18344 deletions

View File

@ -1,45 +0,0 @@
name: cereal mac ci
on: [push, pull_request]
jobs:
test_cereal_macos:
runs-on: macos-latest
strategy:
fail-fast: false
matrix:
include:
- CMAKE_OPTIONS: '-DWITH_WERROR=OFF -DSKIP_PORTABILITY_TEST=ON -DSKIP_PERFORMANCE_COMPARISON=ON'
COMPILER: 'clang++'
XCODE_VERSION: 15
NAME: macos-latest-clang-xcode15
- CMAKE_OPTIONS: '-DWITH_WERROR=OFF -DSKIP_PORTABILITY_TEST=ON -DSKIP_PERFORMANCE_COMPARISON=ON'
COMPILER: 'clang++'
XCODE_VERSION: 16
NAME: macos-latest-clang-xcode16
name: ${{ matrix.name }}
steps:
- name: Checkout code
uses: actions/checkout@v4
- uses: maxim-lobanov/setup-xcode@v1
with:
xcode-version: ${{ matrix.XCODE_VERSION }}
- name: build and test
shell: bash
env:
CMAKE_OPTIONS: ${{ matrix.CMAKE_OPTIONS }}
COMPILER: ${{ matrix.COMPILER }}
run: |
set -ex
# Set compiler and env variables
export CXX=${COMPILER}
${CXX} --version
# Build cereal and test
cmake --version
mkdir build && cd build
cmake ${CMAKE_OPTIONS} .. && make -j4 VERBOSE=1
ctest . --output-on-failure

View File

@ -1,237 +0,0 @@
name: cereal linux ci
on: [push, pull_request]
jobs:
test_cereal_linux:
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
include:
- CMAKE_OPTIONS: '-DSKIP_PORTABILITY_TEST=ON -DSKIP_PERFORMANCE_COMPARISON=ON'
COMPILER: 'g++-4.7'
EXTRA_APT_PACKAGES: 'g++-4.7'
CONTAINER: ubuntu:16.04
NAME: ubuntu-16.04-g++4.7
- CMAKE_OPTIONS: '-DSKIP_PORTABILITY_TEST=ON -DSKIP_PERFORMANCE_COMPARISON=ON'
COMPILER: 'g++-4.8'
EXTRA_APT_PACKAGES: 'g++-4.8'
CONTAINER: ubuntu:16.04
NAME: ubuntu-16.04-g++4.8
- CMAKE_OPTIONS: '-DSKIP_PORTABILITY_TEST=ON -DSKIP_PERFORMANCE_COMPARISON=ON'
COMPILER: 'g++-4.9'
EXTRA_APT_PACKAGES: 'g++-4.9'
CONTAINER: ubuntu:16.04
NAME: ubuntu-16.04-g++4.9
- CMAKE_OPTIONS: '-DSKIP_PORTABILITY_TEST=ON'
COMPILER: 'g++-5'
EXTRA_APT_PACKAGES: 'g++-5'
CONTAINER: ubuntu:16.04
NAME: ubuntu-16.04-g++4.5
- COMPILER: 'g++-5'
EXTRA_APT_PACKAGES: 'gcc-multilib g++-5-multilib linux-libc-dev'
CONTAINER: ubuntu:16.04
NAME: ubuntu-16.04-g++5-multilib
- CMAKE_OPTIONS: '-DSKIP_PORTABILITY_TEST=ON'
COMPILER: 'g++-6'
EXTRA_APT_PACKAGES: 'g++-6'
CONTAINER: ubuntu:16.04
NAME: ubuntu-16.04-g++6
- CMAKE_OPTIONS: '-DSKIP_PORTABILITY_TEST=ON -DCMAKE_CXX_STANDARD=17'
COMPILER: 'g++-7'
EXTRA_APT_PACKAGES: 'g++-7'
CONTAINER: ubuntu:16.04
NAME: ubuntu-16.04-g++7
- CMAKE_OPTIONS: '-DSKIP_PORTABILITY_TEST=ON -DCMAKE_CXX_STANDARD=17'
COMPILER: 'g++-8'
EXTRA_APT_PACKAGES: 'g++-8'
CONTAINER: ubuntu:16.04
NAME: ubuntu-16.04-g++8
- CMAKE_OPTIONS: '-DSKIP_PORTABILITY_TEST=ON -DCMAKE_CXX_STANDARD=17'
COMPILER: 'g++-9'
EXTRA_APT_PACKAGES: 'g++-9'
CONTAINER: ubuntu:20.04
NAME: ubuntu-20.04-g++9
- CMAKE_OPTIONS: '-DSKIP_PORTABILITY_TEST=ON -DCMAKE_CXX_STANDARD=17'
COMPILER: 'g++-10'
EXTRA_APT_PACKAGES: 'g++-10'
CONTAINER: ubuntu:20.04
NAME: ubuntu-20.04-g++10
- CMAKE_OPTIONS: '-DSKIP_PORTABILITY_TEST=ON'
COMPILER: 'clang++-3.5'
EXTRA_APT_PACKAGES: 'clang-3.5'
LLVM_APT_SOURCE: 'deb http://apt.llvm.org/precise/ llvm-toolchain-precise-3.5 main'
CONTAINER: ubuntu:16.04
NAME: ubuntu-16.04-clang-3.5
- CMAKE_OPTIONS: '-DSKIP_PORTABILITY_TEST=ON'
COMPILER: 'clang++-3.6'
EXTRA_APT_PACKAGES: 'clang-3.6'
LLVM_APT_SOURCE: 'deb http://apt.llvm.org/precise/ llvm-toolchain-precise-3.6 main'
CONTAINER: ubuntu:16.04
NAME: ubuntu-16.04-clang-3.6
- CMAKE_OPTIONS: '-DSKIP_PORTABILITY_TEST=ON'
COMPILER: 'clang++-3.7'
EXTRA_APT_PACKAGES: 'clang-3.7'
LLVM_APT_SOURCE: 'deb http://apt.llvm.org/precise/ llvm-toolchain-precise-3.7 main'
CONTAINER: ubuntu:16.04
NAME: ubuntu-16.04-clang-3.7
- CMAKE_OPTIONS: '-DSKIP_PORTABILITY_TEST=ON'
COMPILER: 'clang++-3.8'
EXTRA_APT_PACKAGES: 'clang-3.8'
LLVM_APT_SOURCE: 'deb http://apt.llvm.org/precise/ llvm-toolchain-precise-3.8 main'
CONTAINER: ubuntu:16.04
NAME: ubuntu-16.04-clang-3.8
- CMAKE_OPTIONS: '-DSKIP_PORTABILITY_TEST=ON'
COMPILER: 'clang++-3.9'
EXTRA_APT_PACKAGES: 'clang-3.9'
LLVM_APT_SOURCE: 'deb http://apt.llvm.org/precise/ llvm-toolchain-precise-3.9 main'
CONTAINER: ubuntu:16.04
NAME: ubuntu-16.04-clang-3.9
- CMAKE_OPTIONS: '-DSKIP_PORTABILITY_TEST=ON'
COMPILER: 'clang++-4.0'
EXTRA_APT_PACKAGES: 'clang-4.0 g++-5'
LLVM_APT_SOURCE: 'deb http://apt.llvm.org/trusty/ llvm-toolchain-trusty-4.0 main'
CONTAINER: ubuntu:16.04
NAME: ubuntu-16.04-clang-4.0
- CMAKE_OPTIONS: '-DSKIP_PORTABILITY_TEST=ON'
COMPILER: 'clang++-5.0'
EXTRA_APT_PACKAGES: 'clang-5.0 g++-7'
LLVM_APT_SOURCE: 'deb http://apt.llvm.org/xenial/ llvm-toolchain-xenial-5.0 main'
CONTAINER: ubuntu:16.04
NAME: ubuntu-16.04-clang-5.0
- CMAKE_OPTIONS: '-DSKIP_PORTABILITY_TEST=ON -DCMAKE_CXX_STANDARD=17'
COMPILER: 'clang++-5.0'
EXTRA_APT_PACKAGES: 'clang-5.0 g++-7'
LLVM_APT_SOURCE: 'deb http://apt.llvm.org/xenial/ llvm-toolchain-xenial-5.0 main'
CONTAINER: ubuntu:16.04
NAME: ubuntu-16.04-clang-5.0-cpp17
- CMAKE_OPTIONS: '-DSKIP_PORTABILITY_TEST=ON -DCMAKE_CXX_STANDARD=17'
COMPILER: 'clang++-7'
EXTRA_APT_PACKAGES: 'clang-7 g++-7'
LLVM_APT_SOURCE: 'deb http://apt.llvm.org/xenial/ llvm-toolchain-xenial-7 main'
CONTAINER: ubuntu:16.04
NAME: ubuntu-16.04-clang-7-cpp17
- CMAKE_OPTIONS: '-DSKIP_PORTABILITY_TEST=ON -DCMAKE_CXX_STANDARD=17 -DCLANG_USE_LIBCPP=ON -DSKIP_PERFORMANCE_COMPARISON=ON'
COMPILER: 'clang++-8'
EXTRA_APT_PACKAGES: 'clang-8 g++-8 libc++-8-dev libc++abi-8-dev'
LLVM_APT_SOURCE: 'deb http://apt.llvm.org/xenial/ llvm-toolchain-xenial-8 main'
CONTAINER: ubuntu:16.04
NAME: ubuntu-16.04-clang-8-cpp17
- CMAKE_OPTIONS: '-DSKIP_PORTABILITY_TEST=ON -DCMAKE_CXX_STANDARD=17'
COMPILER: 'clang++-9'
EXTRA_APT_PACKAGES: 'clang-9'
CONTAINER: ubuntu:20.04
NAME: ubuntu-20.04-clang-9-cpp17
- CMAKE_OPTIONS: '-DSKIP_PORTABILITY_TEST=ON -DCMAKE_CXX_STANDARD=17'
COMPILER: 'clang++-10'
EXTRA_APT_PACKAGES: 'clang-10'
CONTAINER: ubuntu:20.04
NAME: ubuntu-20.04-clang-10-cpp17
- CMAKE_OPTIONS: '-DSKIP_PORTABILITY_TEST=ON -DCMAKE_CXX_STANDARD=17'
COMPILER: 'clang++-11'
EXTRA_APT_PACKAGES: 'clang-11'
CONTAINER: ubuntu:20.04
NAME: ubuntu-20.04-clang-11-cpp17
- CMAKE_OPTIONS: '-DSKIP_PORTABILITY_TEST=ON -DCMAKE_CXX_STANDARD=17'
COMPILER: 'clang++-12'
EXTRA_APT_PACKAGES: 'clang-12'
CONTAINER: ubuntu:20.04
NAME: ubuntu-20.04-clang-12-cpp17
name: ${{ matrix.name }}
steps:
- name: Check out the repo
uses: actions/checkout@v4
- name: install deps and test
uses: addnab/docker-run-action@v3
with:
image: ${{ matrix.CONTAINER }}
options: -v ${{ github.workspace }}:/var/workspace
shell: bash
run: |
set -ex
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
# Add apt repositories for older Ubuntu
. /etc/os-release
if [[ "${VERSION_ID}" == "16.04" ]]; then
add-apt-repository ppa:ubuntu-toolchain-r/test -y
add-apt-repository ppa:mhier/libboost-latest -y
fi
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
apt-get update -y
# Install apt packages
apt-get install libboost-serialization-dev libboost-dev ${{ matrix.EXTRA_APT_PACKAGES }} -y
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

8
.gitignore vendored
View File

@ -18,18 +18,14 @@
*.suo *.suo
*.user *.user
*/x64 */x64
*\Debug* */Debug*
*\Release* */Release*
*.log *.log
*.tlog* *.tlog*
*.obj *.obj
*.VC.db *.VC.db
*.VC.VC.opendb *.VC.VC.opendb
*.pdb *.pdb
*.idb
*\build_*
.vs/
CMakeSettings.json
# misc files mostly used for testing # misc files mostly used for testing
out.txt out.txt

View File

@ -1,269 +1,50 @@
# Portions of this file based on https://github.com/Microsoft/GSL/blob/master/.travis.yml
language: cpp language: cpp
os: linux
dist: trusty
sudo: false
group: beta
addons: compiler:
apt: # TODO: Clang is currently giving issues
sources: &default_sources #- clang
- ubuntu-toolchain-r-test - gcc
- libboost-latest
packages: &default_packages
- libboost-serialization-dev
- libboost-dev
matrix: before_install:
include: # Always install g++4.8.1
- sudo add-apt-repository -y ppa:ubuntu-toolchain-r/test
# |---------- LINUX GCC ----------| # Install recent version of Boost
- compiler: g++-4.7 - sudo add-apt-repository -y ppa:boost-latest/ppa
env: ["CMAKE_OPTIONS='-DSKIP_PORTABILITY_TEST=ON'", "COMPILER=g++-4.7"]
addons:
apt:
sources: *default_sources
packages: ['g++-4.7', *default_packages]
- compiler: g++-4.8 # clang 3.3
env: ["CMAKE_OPTIONS='-DSKIP_PORTABILITY_TEST=ON'", "COMPILER=g++-4.8"] - if [ "$CXX" == "clang++" ]; then sudo add-apt-repository -y ppa:h-rayflood/llvm; fi
addons:
apt:
sources: *default_sources
packages: ['g++-4.8', *default_packages]
- compiler: g++-4.9 - sudo apt-get update -qq
env: ["CMAKE_OPTIONS='-DSKIP_PORTABILITY_TEST=ON'", "COMPILER=g++-4.9"]
addons:
apt:
sources: *default_sources
packages: ['g++-4.9', *default_packages]
- compiler: g++-5
env: ["CMAKE_OPTIONS='-DSKIP_PORTABILITY_TEST=ON'", "COMPILER=g++-5"]
addons:
apt:
sources: *default_sources
packages: ['g++-5', *default_packages]
- compiler: g++-5
name: "g++-5 multilib"
env: ["COMPILER=g++-5"]
addons:
apt:
sources: *default_sources
packages: ['gcc-multilib g++-5-multilib linux-libc-dev', *default_packages]
- compiler: g++-6
env: ["CMAKE_OPTIONS='-DSKIP_PORTABILITY_TEST=ON'", "COMPILER=g++-6"]
addons:
apt:
sources: *default_sources
packages: ['g++-6', *default_packages]
- compiler: g++-7
name: "g++-7 c++17"
env: ["CMAKE_OPTIONS='-DSKIP_PORTABILITY_TEST=ON -DCMAKE_CXX_STANDARD=17'", "COMPILER=g++-7"]
addons:
apt:
sources: *default_sources
packages: ['g++-7', *default_packages]
# |---------- LINUX GCC ----------|
- dist: xenial
compiler: g++-8
name: "g++-8 c++17"
env: ["CMAKE_OPTIONS='-DSKIP_PORTABILITY_TEST=ON -DCMAKE_CXX_STANDARD=17'", "COMPILER=g++-8"]
addons:
apt:
sources: *default_sources
packages: ['g++-8', *default_packages]
# |---------- LINUX CLANG ----------|
- compiler: clang++-3.5
env: ["CMAKE_OPTIONS='-DSKIP_PORTABILITY_TEST=ON'", "COMPILER=clang++-3.5"]
addons:
apt:
sources: [*default_sources, llvm-toolchain-precise-3.5]
packages: ['clang-3.5', *default_packages]
- compiler: clang++-3.6
env: ["CMAKE_OPTIONS='-DSKIP_PORTABILITY_TEST=ON'", "COMPILER=clang++-3.6"]
addons:
apt:
sources: [*default_sources, llvm-toolchain-precise-3.6]
packages: ['clang-3.6', *default_packages]
- compiler: clang++-3.7
env: ["CMAKE_OPTIONS='-DSKIP_PORTABILITY_TEST=ON'", "COMPILER=clang++-3.7"]
addons:
apt:
sources: [*default_sources, llvm-toolchain-precise-3.7]
packages: ['clang-3.7', *default_packages]
- compiler: clang++-3.8
env: ["CMAKE_OPTIONS='-DSKIP_PORTABILITY_TEST=ON'", "COMPILER=clang++-3.8"]
addons:
apt:
sources: [*default_sources, llvm-toolchain-precise-3.8]
packages: ['clang-3.8', *default_packages]
- compiler: clang++-3.9
env: ["CMAKE_OPTIONS='-DSKIP_PORTABILITY_TEST=ON'", "COMPILER=clang++-3.9"]
addons:
apt:
sources: [*default_sources, llvm-toolchain-precise-3.9]
packages: ['clang-3.9', *default_packages]
- compiler: clang++-4.0
env: ["CMAKE_OPTIONS='-DSKIP_PORTABILITY_TEST=ON'", "COMPILER=clang++-4.0"]
addons:
apt:
sources: [*default_sources, llvm-toolchain-trusty-4.0]
packages: ['clang-4.0', 'g++-5', *default_packages]
- compiler: clang++-5.0
env: ["CMAKE_OPTIONS='-DSKIP_PORTABILITY_TEST=ON'", "COMPILER=clang++-5.0"]
addons: &clang50
apt:
packages:
- clang-5.0
- g++-7
- *default_packages
sources:
- *default_sources
- llvm-toolchain-trusty-5.0
- sourceline: 'deb http://apt.llvm.org/trusty/ llvm-toolchain-trusty-5.0 main'
key_url: 'https://apt.llvm.org/llvm-snapshot.gpg.key'
- env: ["CMAKE_OPTIONS='-DSKIP_PORTABILITY_TEST=ON -DCMAKE_CXX_STANDARD=17'", "COMPILER=clang++-5.0"]
name: "clang++-5.0 c++17"
addons: *clang50
- compiler: clang++-7
name: "clang++-7 c++17"
env: ["CMAKE_OPTIONS='-DSKIP_PORTABILITY_TEST=ON -DCMAKE_CXX_STANDARD=17'", "COMPILER=clang++-7"]
addons:
apt:
packages:
- clang-7
- g++-7
- *default_packages
sources:
- *default_sources
- llvm-toolchain-trusty-7
- compiler: clang++-8
name: "clang++-8 c++17 libc++"
env: ["CMAKE_OPTIONS='-DSKIP_PORTABILITY_TEST=ON -DCMAKE_CXX_STANDARD=17 -DCLANG_USE_LIBCPP=ON -DSKIP_PERFORMANCE_COMPARISON=ON'", "COMPILER=clang++-8"]
addons:
apt:
packages:
- clang-8
- g++-8
- libc++-8-dev
- libc++abi-8-dev
- *default_packages
sources:
- *default_sources
- llvm-toolchain-trusty-8
# # |---------- LINUX CLANG (32-bit) ----------|
# # Doesn't work.
# - compiler: clang++
# addons:
# apt:
# sources: [*default_sources]
# packages: ['clang', 'gcc-multilib', 'g++-multilib', *default_packages]
# |---------- OSX CLANG ----------|
- compiler: clang++
os: osx
osx_image: xcode7.3
env: COMPILER=clang++
- compiler: clang++
os: osx
osx_image: xcode8
env: COMPILER=clang++
# # Missing CMake
# - compiler: clang++
# os: osx
# osx_image: xcode8.1
- compiler: clang++
os: osx
osx_image: xcode8.2
env: COMPILER=clang++
- compiler: clang++
os: osx
osx_image: xcode8.3
env: COMPILER=clang++
- compiler: clang++
env: ["CMAKE_OPTIONS='-DWITH_WERROR=OFF'"]
os: osx
osx_image: xcode9
env: COMPILER=clang++
- compiler: clang++
env: ["CMAKE_OPTIONS='-DWITH_WERROR=OFF'"]
os: osx
osx_image: xcode10
env: COMPILER=clang++
install: install:
# Set the ${CXX} variable properly - sudo apt-get install cmake
- export CXX=${COMPILER} - sudo apt-get install libboost1.54-all-dev
- ${CXX} --version
# Dependencies required by the CI are installed in ${TRAVIS_BUILD_DIR}/deps/ # Always install valgrind
- DEPS_DIR="${TRAVIS_BUILD_DIR}/deps" - sudo apt-get install valgrind
- mkdir -p "${DEPS_DIR}"
- cd "${DEPS_DIR}"
- JOBS=2 # Always install g++4.8.1
- sudo apt-get install -qq g++-4.8
- sudo apt-get install -qq g++-4.8-multilib
- if [ "$CXX" = "g++" ]; then export CMAKE_CXX_COMPILER="g++-4.8"; fi
- if [ "$CXX" = "g++" ]; then export CXX="g++-4.8"; fi
# [linux]: Install the right version of libc++ # clang 3.3
- | - if [ "$CXX" == "clang++" ]; then sudo apt-get install --allow-unauthenticated -qq clang-3.3; fi
LLVM_INSTALL=${DEPS_DIR}/llvm/install - if [ "$CXX" == "clang++" ]; then export CMAKE_CXX_COMPILER="clang++-3.3"; fi
# if in linux and compiler clang and llvm not installed - if [ "$CXX" == "clang++" ]; then export CXX="clang++-3.3"; fi
if [[ "${TRAVIS_OS_NAME}" == "linux" && "${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
travis_retry wget -O - ${LLVM_URL} | tar --strip-components=1 -xJ -C llvm
travis_retry wget -O - ${LIBCXX_URL} | tar --strip-components=1 -xJ -C llvm/projects/libcxx
travis_retry 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
script: script:
- cd "${TRAVIS_BUILD_DIR}" - mkdir build
- if [[ "${COMPILERCC}" != "" ]]; then export CC="${COMPILERCC}"; fi - cd build
- if [[ "${COMPILER}" != "" ]]; then export CXX="${COMPILER}"; fi - cmake ..
- $CXX --version - make
- cmake --version
- mkdir build && cd build after_script:
- cmake ${CMAKE_OPTIONS} .. && make -j4 - ctest .
- ctest . --output-on-failure # - make valgrind
branches: branches:
only: only:
- master - develop

View File

@ -1,143 +1,75 @@
cmake_minimum_required(VERSION 3.6...3.15) cmake_minimum_required (VERSION 2.6.2)
project (cereal)
project(cereal LANGUAGES CXX VERSION 1.3.2) option(SKIP_PORTABILITY_TEST "Skip portability tests" OFF)
if(PROJECT_SOURCE_DIR STREQUAL CMAKE_SOURCE_DIR)
set(CEREAL_MASTER_PROJECT ON)
endif()
option(SKIP_PORTABILITY_TEST "Skip portability (32 bit) tests" OFF)
include(CheckCXXCompilerFlag)
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()
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
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
option(JUST_INSTALL_CEREAL "Don't do anything besides installing the library" OFF) option(JUST_INSTALL_CEREAL "Don't do anything besides installing the library" OFF)
endif() endif()
set(CEREAL_THREAD_LIBS)
if(UNIX)
option(THREAD_SAFE "Use mutexes to ensure thread safety" OFF) option(THREAD_SAFE "Use mutexes to ensure thread safety" OFF)
if(THREAD_SAFE) if(THREAD_SAFE)
message(STATUS "Use mutexes")
add_definitions(-DCEREAL_THREAD_SAFE=1) add_definitions(-DCEREAL_THREAD_SAFE=1)
set(CEREAL_THREAD_LIBS pthread) set(CEREAL_THREAD_LIBS "pthread")
endif()
endif()
if(MSVC)
add_compile_options(/bigobj /W3 /WX)
else() else()
add_compile_options(-Wall -Wextra -pedantic -Wshadow -Wold-style-cast) set(CEREAL_THREAD_LIBS "")
option(WITH_WERROR "Compile with '-Werror' C++ compiler flag" ON)
if(WITH_WERROR)
add_compile_options(-Werror)
endif()
option(CLANG_USE_LIBCPP "Use libc++ for clang compilation" OFF)
if(APPLE OR CLANG_USE_LIBCPP)
message(STATUS "Use libc++")
add_compile_options(-stdlib=libc++)
# TODO: use add_link_options(-stdlib=libc++ -lc++abi") bud this needs cmake 3.13! CK
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -stdlib=libc++ -lc++abi")
endif() endif()
if(NOT MSVC)
set(CMAKE_CXX_FLAGS "-Wall -Werror -g -Wextra -Wshadow -pedantic ${CMAKE_CXX_FLAGS}")
if(CMAKE_VERSION VERSION_LESS 3.1)
set(CMAKE_CXX_FLAGS "-std=c++11 ${CMAKE_CXX_FLAGS}")
else()
if(NOT DEFINED CMAKE_CXX_STANDARD OR CMAKE_CXX_STANDARD STREQUAL "98") if(NOT DEFINED CMAKE_CXX_STANDARD OR CMAKE_CXX_STANDARD STREQUAL "98")
set(CMAKE_CXX_STANDARD 11) set(CMAKE_CXX_STANDARD 11)
endif() endif()
set(CMAKE_CXX_STANDARD_REQUIRED ON) set(CMAKE_CXX_STANDARD_REQUIRED ON)
endif() endif()
endif()
if(NOT CMAKE_VERSION VERSION_LESS 3.0)
add_library(cereal INTERFACE) add_library(cereal INTERFACE)
add_library(cereal::cereal ALIAS cereal)
target_include_directories(cereal INTERFACE target_include_directories(cereal INTERFACE
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include> $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
$<INSTALL_INTERFACE:include> $<INSTALL_INTERFACE:include>
) )
list(APPEND CEREAL_THREAD_LIBS cereal::cereal) install(TARGETS cereal EXPORT cereal
DESTINATION lib) # ignored
if(NOT CMAKE_VERSION VERSION_LESS 3.8) install(EXPORT cereal FILE cereal-config.cmake
target_compile_features(cereal INTERFACE cxx_std_11) DESTINATION share/cmake/cereal)
install(DIRECTORY include/cereal DESTINATION include)
endif() endif()
option(CEREAL_INSTALL "Generate the install target" ${CEREAL_MASTER_PROJECT})
if(CEREAL_INSTALL)
include(GNUInstallDirs)
include(CMakePackageConfigHelpers)
install(TARGETS cereal EXPORT ${PROJECT_NAME}Targets)
install(DIRECTORY include/cereal DESTINATION ${CMAKE_INSTALL_INCLUDEDIR})
set(configFile ${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}Config.cmake)
set(versionFile ${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}ConfigVersion.cmake)
set(configInstallDestination ${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME})
configure_package_config_file(
${CMAKE_CURRENT_SOURCE_DIR}/Config.cmake.in
${configFile}
INSTALL_DESTINATION ${configInstallDestination}
)
if(${CMAKE_VERSION} VERSION_GREATER 3.13)
write_basic_package_version_file("${versionFile}" COMPATIBILITY SameMajorVersion ARCH_INDEPENDENT)
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(
EXPORT ${PROJECT_NAME}Targets
NAMESPACE "cereal::"
DESTINATION ${configInstallDestination}
)
install(
FILES ${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}.pc
DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/pkgconfig
)
endif()
if(JUST_INSTALL_CEREAL) if(JUST_INSTALL_CEREAL)
return() return()
endif() endif()
include_directories(./include)
if(NOT SKIP_PERFORMANCE_COMPARISON) find_package(Boost COMPONENTS serialization unit_test_framework)
# Boost serialization for performance sandbox
find_package(Boost REQUIRED COMPONENTS serialization)
endif()
if(Boost_FOUND)
option(BUILD_TESTS "Build tests" ${CEREAL_MASTER_PROJECT}) include_directories(SYSTEM ${Boost_INCLUDE_DIRS})
if(BUILD_TESTS)
enable_testing() enable_testing()
add_subdirectory(unittests) add_subdirectory(unittests)
endif() endif(Boost_FOUND)
if(BUILD_SANDBOX)
add_subdirectory(sandbox) add_subdirectory(sandbox)
endif()
find_package(Doxygen)
if(DOXYGEN_FOUND)
if(BUILD_DOC) configure_file("${CMAKE_CURRENT_SOURCE_DIR}/doc/doxygen.in" "${CMAKE_CURRENT_BINARY_DIR}/doxygen.cfg" @ONLY)
add_subdirectory(doc) add_custom_target(doc
endif() COMMAND ${DOXYGEN_EXECUTABLE} "${CMAKE_CURRENT_BINARY_DIR}/doxygen.cfg"
WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}"
COMMENT "Generating API documentation with Doxygen" VERBATIM
)
configure_file("${CMAKE_CURRENT_SOURCE_DIR}/scripts/updatedoc.in" "${CMAKE_CURRENT_BINARY_DIR}/updatedoc.sh" @ONLY)
add_custom_target(update-doc
COMMAND "${CMAKE_CURRENT_BINARY_DIR}/updatedoc.sh"
DEPENDS doc
COMMENT "Copying documentation to gh-pages branch" VERBATIM
)
endif(DOXYGEN_FOUND)

View File

@ -1,3 +0,0 @@
@PACKAGE_INIT@
include("${CMAKE_CURRENT_LIST_DIR}/@PROJECT_NAME@Targets.cmake")

View File

@ -1,4 +1,4 @@
Copyright (c) 2013-2022, Randolph Voorhies, Shane Grant Copyright (c) 2014, Randolph Voorhies, Shane Grant
All rights reserved. All rights reserved.
Redistribution and use in source and binary forms, with or without Redistribution and use in source and binary forms, with or without
@ -8,14 +8,14 @@ modification, are permitted provided that the following conditions are met:
* Redistributions in binary form must reproduce the above copyright * Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution. documentation and/or other materials provided with the distribution.
* Neither the name of the copyright holder nor the * Neither the name of cereal nor the
names of its contributors may be used to endorse or promote products names of its contributors may be used to endorse or promote products
derived from this software without specific prior written permission. derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 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 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DISCLAIMED. IN NO EVENT SHALL RANDOLPH VOORHIES OR SHANE GRANT BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND

View File

@ -1,15 +1,15 @@
cereal - A C++11 library for serialization cereal - A C++11 library for serialization
========================================== ==========================================
<img src="https://uscilab.github.io/cereal/assets/img/cerealboxside.png" align="right"/><p>cereal is a header-only C++11 serialization library. cereal takes arbitrary data types and reversibly turns them into different representations, such as compact binary encodings, XML, or JSON. cereal was designed to be fast, light-weight, and easy to extend - it has no external dependencies and can be easily bundled with other code or used standalone.</p> <img src="http://uscilab.github.io/cereal/assets/img/cerealboxside.png" align="right"/><p>cereal is a header-only C++11 serialization library. cereal takes arbitrary data types and reversibly turns them into different representations, such as compact binary encodings, XML, or JSON. cereal was designed to be fast, light-weight, and easy to extend - it has no external dependencies and can be easily bundled with other code or used standalone.</p>
### cereal has great documentation ### cereal has great documentation
Looking for more information on how cereal works and its documentation? Visit [cereal's web page](https://USCiLab.github.io/cereal) to get the latest information. Looking for more information on how cereal works and its documentation? Visit [cereal's web page](http://USCiLab.github.com/cereal) to get the latest information.
### cereal is easy to use ### cereal is easy to use
Installation and use of of cereal is fully documented on the [main web page](https://USCiLab.github.io/cereal), but this is a quick and dirty version: Installation and use of of cereal is fully documented on the [main web page](http://USCiLab.github.com/cereal), but this is a quick and dirty version:
* Download cereal and place the headers somewhere your code can see them * Download cereal and place the headers somewhere your code can see them
* Write serialization functions for your custom types or use the built in support for the standard library cereal provides * Write serialization functions for your custom types or use the built in support for the standard library cereal provides
@ -77,9 +77,7 @@ cereal is licensed under the [BSD license](http://opensource.org/licenses/BSD-3-
## cereal build status ## cereal build status
* [![Linux build status](https://github.com/USCiLab/cereal/actions/workflows/ci.yml/badge.svg)](https://github.com/USCiLab/cereal/actions/workflows/ci.yml) * develop : [![Build Status](https://travis-ci.org/USCiLab/cereal.png?branch=develop)](https://travis-ci.org/USCiLab/cereal)
* [![Mac build status](https://github.com/USCiLab/cereal/actions/workflows/ci-macos.yml/badge.svg)](https://github.com/USCiLab/cereal/actions/workflows/ci-macos.yml)
* [![Windows build status](https://ci.appveyor.com/api/projects/status/91aou6smj36or0vb/branch/master?svg=true)](https://ci.appveyor.com/project/AzothAmmo/cereal/branch/master)
--- ---

View File

@ -1,55 +0,0 @@
# can use variables like {build} and {branch}
version: 1.3.{build}
pull_requests:
do_not_increment_build_number: true
branches:
only:
- master
configuration:
- Debug
- Release
environment:
matrix:
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2013
VS_VERSION_MAJOR: 12
BOOST_ROOT: C:\Libraries\boost_1_58_0
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015
VS_VERSION_MAJOR: 14
BOOST_ROOT: C:\Libraries\boost_1_60_0
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017
VS_VERSION_MAJOR: 15
BOOST_ROOT: C:\Libraries\boost_1_66_0
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2019
VS_VERSION_MAJOR: 16
BOOST_ROOT: C:\Libraries\boost_1_73_0
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2022
VS_VERSION_MAJOR: 17
BOOST_ROOT: C:\Libraries\boost_1_73_0
matrix:
exclude:
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2019
platform: Win32
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2022
platform: Win32
platform:
- Win32
- x64
before_build: "scripts\\appveyor.bat"
build:
parallel: true
project: build/cereal.sln
verbosity: minimal
test_script: "scripts\\appveyor.bat test"
artifacts:
- path: build\Testing
- path: out

View File

@ -1,8 +0,0 @@
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

@ -1,18 +0,0 @@
find_package(Doxygen)
if(DOXYGEN_FOUND)
configure_file("${CMAKE_CURRENT_SOURCE_DIR}/doxygen.in" "${CMAKE_CURRENT_BINARY_DIR}/doxygen.cfg" @ONLY)
add_custom_target(doc
COMMAND ${DOXYGEN_EXECUTABLE} "${CMAKE_CURRENT_BINARY_DIR}/doxygen.cfg"
WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/.."
COMMENT "Generating API documentation with Doxygen" VERBATIM
)
configure_file("${CMAKE_CURRENT_SOURCE_DIR}/../scripts/updatedoc.in" "${CMAKE_CURRENT_BINARY_DIR}/updatedoc.sh" @ONLY)
add_custom_target(update-doc
COMMAND "${CMAKE_CURRENT_BINARY_DIR}/updatedoc.sh"
DEPENDS doc
COMMENT "Copying documentation to gh-pages branch" VERBATIM
)
endif()

View File

@ -52,7 +52,7 @@ PROJECT_LOGO =
# If a relative path is entered, it will be relative to the location # If a relative path is entered, it will be relative to the location
# where doxygen was started. If left blank the current directory will be used. # where doxygen was started. If left blank the current directory will be used.
OUTPUT_DIRECTORY = @CMAKE_CURRENT_BINARY_DIR@/ OUTPUT_DIRECTORY = doc
# If the CREATE_SUBDIRS tag is set to YES, then doxygen will create # If the CREATE_SUBDIRS tag is set to YES, then doxygen will create
# 4096 sub-directories (in 2 levels) under the output directory of each output # 4096 sub-directories (in 2 levels) under the output directory of each output
@ -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 = NO FULL_PATH_NAMES = YES
# 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 = NO
# 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 = @PROJECT_SOURCE_DIR@ STRIP_FROM_PATH =
# 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
@ -595,7 +595,7 @@ FILE_VERSION_FILTER =
# You can optionally specify a file name after the option, if omitted # You can optionally specify a file name after the option, if omitted
# DoxygenLayout.xml will be used as the name of the layout file. # DoxygenLayout.xml will be used as the name of the layout file.
LAYOUT_FILE = "@CMAKE_CURRENT_SOURCE_DIR@/DoxygenLayout.xml" LAYOUT_FILE = "@CMAKE_CURRENT_SOURCE_DIR@/doc/DoxygenLayout.xml"
# The CITE_BIB_FILES tag can be used to specify one or more bib files # The CITE_BIB_FILES tag can be used to specify one or more bib files
# containing the references data. This must be a list of .bib files. The # containing the references data. This must be a list of .bib files. The
@ -668,7 +668,7 @@ WARN_LOGFILE =
# directories like "/usr/src/myproject". Separate the files or directories # directories like "/usr/src/myproject". Separate the files or directories
# with spaces. # with spaces.
INPUT = @CMAKE_CURRENT_SOURCE_DIR@/../include @CMAKE_CURRENT_SOURCE_DIR@/ INPUT = @CMAKE_CURRENT_SOURCE_DIR@/include @CMAKE_CURRENT_SOURCE_DIR@/doc #include doc
# This tag can be used to specify the character encoding of the source files # This tag can be used to specify the character encoding of the source files
# that doxygen parses. Internally doxygen uses the UTF-8 encoding, which is # that doxygen parses. Internally doxygen uses the UTF-8 encoding, which is
@ -701,7 +701,7 @@ RECURSIVE = YES
# Note that relative paths are relative to the directory from which doxygen is # Note that relative paths are relative to the directory from which doxygen is
# run. # run.
EXCLUDE = @CMAKE_CURRENT_SOURCE_DIR@/../external EXCLUDE = external
# The EXCLUDE_SYMLINKS tag can be used to select whether or not files or # The EXCLUDE_SYMLINKS tag can be used to select whether or not files or
# directories that are symbolic links (a Unix file system feature) are excluded # directories that are symbolic links (a Unix file system feature) are excluded
@ -911,7 +911,7 @@ HTML_HEADER =
# each generated HTML page. If it is left blank doxygen will generate a # each generated HTML page. If it is left blank doxygen will generate a
# standard footer. # standard footer.
HTML_FOOTER ="@CMAKE_CURRENT_SOURCE_DIR@/footer.html" HTML_FOOTER ="@CMAKE_CURRENT_SOURCE_DIR@/doc/footer.html"
# The HTML_STYLESHEET tag can be used to specify a user-defined cascading # The HTML_STYLESHEET tag can be used to specify a user-defined cascading
# style sheet that is used by each HTML page. It can be used to # style sheet that is used by each HTML page. It can be used to
@ -1476,13 +1476,13 @@ XML_OUTPUT = xml
# which can be used by a validating XML parser to check the # which can be used by a validating XML parser to check the
# syntax of the XML files. # syntax of the XML files.
# XML_SCHEMA = XML_SCHEMA =
# The XML_DTD tag can be used to specify an XML DTD, # The XML_DTD tag can be used to specify an XML DTD,
# which can be used by a validating XML parser to check the # which can be used by a validating XML parser to check the
# syntax of the XML files. # syntax of the XML files.
# XML_DTD = XML_DTD =
# If the XML_PROGRAMLISTING tag is set to YES Doxygen will # If the XML_PROGRAMLISTING tag is set to YES Doxygen will
# dump the program listings (including syntax highlighting # dump the program listings (including syntax highlighting
@ -1626,7 +1626,7 @@ TAGFILES =
# When a file name is specified after GENERATE_TAGFILE, doxygen will create # When a file name is specified after GENERATE_TAGFILE, doxygen will create
# a tag file that is based on the input files it reads. # a tag file that is based on the input files it reads.
GENERATE_TAGFILE = cereal.doxytags GENERATE_TAGFILE =
# If the ALLEXTERNALS tag is set to YES all external classes will be listed # If the ALLEXTERNALS tag is set to YES all external classes will be listed
# in the class index. If set to NO only the inherited external classes # in the class index. If set to NO only the inherited external classes

View File

@ -1,5 +1,5 @@
/*! \file access.hpp /*! \file access.hpp
\brief Access control and default construction */ \brief Access control, default construction, and serialization disambiguation */
/* /*
Copyright (c) 2014, Randolph Voorhies, Shane Grant Copyright (c) 2014, Randolph Voorhies, Shane Grant
All rights reserved. All rights reserved.
@ -11,14 +11,14 @@
* Redistributions in binary form must reproduce the above copyright * Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution. documentation and/or other materials provided with the distribution.
* Neither the name of the copyright holder nor the * Neither the name of cereal nor the
names of its contributors may be used to endorse or promote products names of its contributors may be used to endorse or promote products
derived from this software without specific prior written permission. derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 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 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DISCLAIMED. IN NO EVENT SHALL RANDOLPH VOORHIES OR SHANE GRANT BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
@ -34,9 +34,8 @@
#include <cstdint> #include <cstdint>
#include <functional> #include <functional>
#include "cereal/macros.hpp" #include <cereal/macros.hpp>
#include "cereal/specialize.hpp" #include <cereal/details/helpers.hpp>
#include "cereal/details/helpers.hpp"
namespace cereal namespace cereal
{ {
@ -111,7 +110,6 @@ namespace cereal
// forward decl for construct // forward decl for construct
//! @cond PRIVATE_NEVERDEFINED //! @cond PRIVATE_NEVERDEFINED
namespace memory_detail{ template <class Ar, class T> struct LoadAndConstructLoadWrapper; } namespace memory_detail{ template <class Ar, class T> struct LoadAndConstructLoadWrapper; }
namespace boost_variant_detail{ template <class Ar, class T> struct LoadAndConstructLoadWrapper; }
//! @endcond //! @endcond
//! Used to construct types with no default constructor //! Used to construct types with no default constructor
@ -204,8 +202,7 @@ namespace cereal
} }
private: private:
template <class Ar, class TT> friend struct ::cereal::memory_detail::LoadAndConstructLoadWrapper; template <class A, class B> friend struct ::cereal::memory_detail::LoadAndConstructLoadWrapper;
template <class Ar, class TT> friend struct ::cereal::boost_variant_detail::LoadAndConstructLoadWrapper;
construct( T * p ) : itsPtr( p ), itsEnableSharedRestoreFunction( [](){} ), itsValid( false ) {} construct( T * p ) : itsPtr( p ), itsEnableSharedRestoreFunction( [](){} ), itsValid( false ) {}
construct( T * p, std::function<void()> enableSharedFunc ) : // g++4.7 ice with default lambda to std func construct( T * p, std::function<void()> enableSharedFunc ) : // g++4.7 ice with default lambda to std func
@ -334,6 +331,106 @@ namespace cereal
} }
}; // end class access }; // 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 // Deferred Implementation, see construct for more information
template <class T> template <class ... Args> inline template <class T> template <class ... Args> inline

View File

@ -12,14 +12,14 @@
* Redistributions in binary form must reproduce the above copyright * Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution. documentation and/or other materials provided with the distribution.
* Neither the name of the copyright holder nor the * Neither the name of cereal nor the
names of its contributors may be used to endorse or promote products names of its contributors may be used to endorse or promote products
derived from this software without specific prior written permission. derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 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 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DISCLAIMED. IN NO EVENT SHALL RANDOLPH VOORHIES OR SHANE GRANT BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
@ -30,7 +30,7 @@
#ifndef CEREAL_ARCHIVES_ADAPTERS_HPP_ #ifndef CEREAL_ARCHIVES_ADAPTERS_HPP_
#define CEREAL_ARCHIVES_ADAPTERS_HPP_ #define CEREAL_ARCHIVES_ADAPTERS_HPP_
#include "cereal/details/helpers.hpp" #include <cereal/details/helpers.hpp>
#include <utility> #include <utility>
namespace cereal namespace cereal

View File

@ -11,14 +11,14 @@
* Redistributions in binary form must reproduce the above copyright * Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution. documentation and/or other materials provided with the distribution.
* Neither the name of the copyright holder nor the * Neither the name of cereal nor the
names of its contributors may be used to endorse or promote products names of its contributors may be used to endorse or promote products
derived from this software without specific prior written permission. derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 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 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DISCLAIMED. IN NO EVENT SHALL RANDOLPH VOORHIES OR SHANE GRANT BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
@ -29,7 +29,7 @@
#ifndef CEREAL_ARCHIVES_BINARY_HPP_ #ifndef CEREAL_ARCHIVES_BINARY_HPP_
#define CEREAL_ARCHIVES_BINARY_HPP_ #define CEREAL_ARCHIVES_BINARY_HPP_
#include "cereal/cereal.hpp" #include <cereal/cereal.hpp>
#include <sstream> #include <sstream>
namespace cereal namespace cereal
@ -62,9 +62,9 @@ namespace cereal
~BinaryOutputArchive() CEREAL_NOEXCEPT = default; ~BinaryOutputArchive() CEREAL_NOEXCEPT = default;
//! Writes size bytes of data to the output stream //! Writes size bytes of data to the output stream
void saveBinary( const void * data, std::streamsize size ) void saveBinary( const void * data, std::size_t size )
{ {
auto const writtenSize = itsStream.rdbuf()->sputn( reinterpret_cast<const char*>( data ), size ); auto const writtenSize = static_cast<std::size_t>( itsStream.rdbuf()->sputn( reinterpret_cast<const char*>( data ), size ) );
if(writtenSize != size) if(writtenSize != size)
throw Exception("Failed to write " + std::to_string(size) + " bytes to output stream! Wrote " + std::to_string(writtenSize)); throw Exception("Failed to write " + std::to_string(size) + " bytes to output stream! Wrote " + std::to_string(writtenSize));
@ -97,9 +97,9 @@ namespace cereal
~BinaryInputArchive() CEREAL_NOEXCEPT = default; ~BinaryInputArchive() CEREAL_NOEXCEPT = default;
//! Reads size bytes of data from the input stream //! Reads size bytes of data from the input stream
void loadBinary( void * const data, std::streamsize size ) void loadBinary( void * const data, std::size_t size )
{ {
auto const readSize = itsStream.rdbuf()->sgetn( reinterpret_cast<char*>( data ), size ); auto const readSize = static_cast<std::size_t>( itsStream.rdbuf()->sgetn( reinterpret_cast<char*>( data ), size ) );
if(readSize != size) if(readSize != size)
throw Exception("Failed to read " + std::to_string(size) + " bytes from input stream! Read " + std::to_string(readSize)); throw Exception("Failed to read " + std::to_string(size) + " bytes from input stream! Read " + std::to_string(readSize));
@ -148,14 +148,14 @@ namespace cereal
template <class T> inline template <class T> inline
void CEREAL_SAVE_FUNCTION_NAME(BinaryOutputArchive & ar, BinaryData<T> const & bd) void CEREAL_SAVE_FUNCTION_NAME(BinaryOutputArchive & ar, BinaryData<T> const & bd)
{ {
ar.saveBinary( bd.data, static_cast<std::streamsize>( bd.size ) ); ar.saveBinary( bd.data, static_cast<std::size_t>( bd.size ) );
} }
//! Loading binary data //! Loading binary data
template <class T> inline template <class T> inline
void CEREAL_LOAD_FUNCTION_NAME(BinaryInputArchive & ar, BinaryData<T> & bd) void CEREAL_LOAD_FUNCTION_NAME(BinaryInputArchive & ar, BinaryData<T> & bd)
{ {
ar.loadBinary(bd.data, static_cast<std::streamsize>( bd.size ) ); ar.loadBinary(bd.data, static_cast<std::size_t>(bd.size));
} }
} // namespace cereal } // namespace cereal

View File

@ -11,14 +11,14 @@
* Redistributions in binary form must reproduce the above copyright * Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution. documentation and/or other materials provided with the distribution.
* Neither the name of the copyright holder nor the * Neither the name of cereal nor the
names of its contributors may be used to endorse or promote products names of its contributors may be used to endorse or promote products
derived from this software without specific prior written permission. derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 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 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DISCLAIMED. IN NO EVENT SHALL RANDOLPH VOORHIES OR SHANE GRANT BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
@ -29,8 +29,8 @@
#ifndef CEREAL_ARCHIVES_JSON_HPP_ #ifndef CEREAL_ARCHIVES_JSON_HPP_
#define CEREAL_ARCHIVES_JSON_HPP_ #define CEREAL_ARCHIVES_JSON_HPP_
#include "cereal/cereal.hpp" #include <cereal/cereal.hpp>
#include "cereal/details/util.hpp" #include <cereal/details/util.hpp>
namespace cereal namespace cereal
{ {
@ -40,11 +40,6 @@ namespace cereal
{ RapidJSONException( const char * what_ ) : Exception( what_ ) {} }; { RapidJSONException( const char * what_ ) : Exception( what_ ) {} };
} }
// Inform rapidjson that assert will throw
#ifndef CEREAL_RAPIDJSON_ASSERT_THROWS
#define CEREAL_RAPIDJSON_ASSERT_THROWS
#endif // CEREAL_RAPIDJSON_ASSERT_THROWS
// Override rapidjson assertions to throw exceptions by default // Override rapidjson assertions to throw exceptions by default
#ifndef CEREAL_RAPIDJSON_ASSERT #ifndef CEREAL_RAPIDJSON_ASSERT
#define CEREAL_RAPIDJSON_ASSERT(x) if(!(x)){ \ #define CEREAL_RAPIDJSON_ASSERT(x) if(!(x)){ \
@ -52,20 +47,14 @@ namespace cereal
#endif // RAPIDJSON_ASSERT #endif // RAPIDJSON_ASSERT
// Enable support for parsing of nan, inf, -inf // Enable support for parsing of nan, inf, -inf
#ifndef CEREAL_RAPIDJSON_WRITE_DEFAULT_FLAGS
#define CEREAL_RAPIDJSON_WRITE_DEFAULT_FLAGS kWriteNanAndInfFlag #define CEREAL_RAPIDJSON_WRITE_DEFAULT_FLAGS kWriteNanAndInfFlag
#endif
// Enable support for parsing of nan, inf, -inf
#ifndef CEREAL_RAPIDJSON_PARSE_DEFAULT_FLAGS
#define CEREAL_RAPIDJSON_PARSE_DEFAULT_FLAGS kParseFullPrecisionFlag | kParseNanAndInfFlag #define CEREAL_RAPIDJSON_PARSE_DEFAULT_FLAGS kParseFullPrecisionFlag | kParseNanAndInfFlag
#endif
#include "cereal/external/rapidjson/prettywriter.h" #include <cereal/external/rapidjson/prettywriter.h>
#include "cereal/external/rapidjson/ostreamwrapper.h" #include <cereal/external/rapidjson/ostreamwrapper.h>
#include "cereal/external/rapidjson/istreamwrapper.h" #include <cereal/external/rapidjson/istreamwrapper.h>
#include "cereal/external/rapidjson/document.h" #include <cereal/external/rapidjson/document.h>
#include "cereal/external/base64.hpp" #include <cereal/external/base64.hpp>
#include <limits> #include <limits>
#include <sstream> #include <sstream>
@ -107,8 +96,8 @@ namespace cereal
{ {
enum class NodeType { StartObject, InObject, StartArray, InArray }; enum class NodeType { StartObject, InObject, StartArray, InArray };
using WriteStream = CEREAL_RAPIDJSON_NAMESPACE::OStreamWrapper; using WriteStream = rapidjson::OStreamWrapper;
using JSONWriter = CEREAL_RAPIDJSON_NAMESPACE::PrettyWriter<WriteStream>; using JSONWriter = rapidjson::PrettyWriter<WriteStream>;
public: public:
/*! @name Common Functionality /*! @name Common Functionality
@ -188,7 +177,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
@ -220,13 +209,11 @@ namespace cereal
{ {
case NodeType::StartArray: case NodeType::StartArray:
itsWriter.StartArray(); itsWriter.StartArray();
// fall through
case NodeType::InArray: case NodeType::InArray:
itsWriter.EndArray(); itsWriter.EndArray();
break; break;
case NodeType::StartObject: case NodeType::StartObject:
itsWriter.StartObject(); itsWriter.StartObject();
// fall through
case NodeType::InObject: case NodeType::InObject:
itsWriter.EndObject(); itsWriter.EndObject();
break; break;
@ -255,19 +242,12 @@ namespace cereal
//! Saves a double to the current node //! Saves a double to the current node
void saveValue(double d) { itsWriter.Double(d); } void saveValue(double d) { itsWriter.Double(d); }
//! Saves a string to the current node //! Saves a string to the current node
void saveValue(std::string const & s) { itsWriter.String(s.c_str(), static_cast<CEREAL_RAPIDJSON_NAMESPACE::SizeType>( s.size() )); } 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 //! Saves a const char * to the current node
void saveValue(char const * s) { itsWriter.String(s); } void saveValue(char const * s) { itsWriter.String(s); }
//! 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.
@ -293,19 +273,19 @@ namespace cereal
void saveLong(T lu){ saveValue( static_cast<std::uint64_t>( lu ) ); } void saveLong(T lu){ saveValue( static_cast<std::uint64_t>( lu ) ); }
public: public:
#if defined(_MSC_VER) && _MSC_VER < 1916 #ifdef _MSC_VER
//! MSVC only long overload to current node //! MSVC only long overload to current node
void saveValue( unsigned long lu ){ saveLong( lu ); }; void saveValue( unsigned long lu ){ saveLong( lu ); };
#else // _MSC_VER #else // _MSC_VER
//! Serialize a long if it would not be caught otherwise //! Serialize a long if it would not be caught otherwise
template <class T, traits::EnableIf<std::is_same<T, long>::value, template <class T, traits::EnableIf<std::is_same<T, long>::value,
!std::is_same<T, int>::value, !std::is_same<T, std::int32_t>::value,
!std::is_same<T, std::int64_t>::value> = traits::sfinae> inline !std::is_same<T, std::int64_t>::value> = traits::sfinae> inline
void saveValue( T t ){ saveLong( t ); } void saveValue( T t ){ saveLong( t ); }
//! Serialize an unsigned long if it would not be caught otherwise //! Serialize an unsigned long if it would not be caught otherwise
template <class T, traits::EnableIf<std::is_same<T, unsigned long>::value, template <class T, traits::EnableIf<std::is_same<T, unsigned long>::value,
!std::is_same<T, unsigned>::value, !std::is_same<T, std::uint32_t>::value,
!std::is_same<T, std::uint64_t>::value> = traits::sfinae> inline !std::is_same<T, std::uint64_t>::value> = traits::sfinae> inline
void saveValue( T t ){ saveLong( t ); } void saveValue( T t ){ saveLong( t ); }
#endif // _MSC_VER #endif // _MSC_VER
@ -317,8 +297,6 @@ 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)
{ {
@ -428,11 +406,11 @@ namespace cereal
class JSONInputArchive : public InputArchive<JSONInputArchive>, public traits::TextArchive class JSONInputArchive : public InputArchive<JSONInputArchive>, public traits::TextArchive
{ {
private: private:
using ReadStream = CEREAL_RAPIDJSON_NAMESPACE::IStreamWrapper; using ReadStream = rapidjson::IStreamWrapper;
typedef CEREAL_RAPIDJSON_NAMESPACE::GenericValue<CEREAL_RAPIDJSON_NAMESPACE::UTF8<>> JSONValue; typedef rapidjson::GenericValue<rapidjson::UTF8<>> JSONValue;
typedef JSONValue::ConstMemberIterator MemberIterator; typedef JSONValue::ConstMemberIterator MemberIterator;
typedef JSONValue::ConstValueIterator ValueIterator; typedef JSONValue::ConstValueIterator ValueIterator;
typedef CEREAL_RAPIDJSON_NAMESPACE::Document::GenericValue GenericValue; typedef rapidjson::Document::GenericValue GenericValue;
public: public:
/*! @name Common Functionality /*! @name Common Functionality
@ -474,7 +452,7 @@ namespace cereal
std::memcpy( data, decoded.data(), decoded.size() ); std::memcpy( data, decoded.data(), decoded.size() );
itsNextName = nullptr; itsNextName = nullptr;
} };
private: private:
//! @} //! @}
@ -492,18 +470,12 @@ namespace cereal
Iterator() : itsIndex( 0 ), itsType(Null_) {} Iterator() : itsIndex( 0 ), itsType(Null_) {}
Iterator(MemberIterator begin, MemberIterator end) : Iterator(MemberIterator begin, MemberIterator end) :
itsMemberItBegin(begin), itsMemberItEnd(end), itsIndex(0), itsSize(std::distance(begin, end)), itsType(Member) itsMemberItBegin(begin), itsMemberItEnd(end), itsIndex(0), itsType(Member)
{ { }
if( itsSize == 0 )
itsType = Null_;
}
Iterator(ValueIterator begin, ValueIterator end) : Iterator(ValueIterator begin, ValueIterator end) :
itsValueItBegin(begin), itsIndex(0), itsSize(std::distance(begin, end)), itsType(Value) itsValueItBegin(begin), itsValueItEnd(end), itsIndex(0), itsType(Value)
{ { }
if( itsSize == 0 )
itsType = Null_;
}
//! Advance to the next node //! Advance to the next node
Iterator & operator++() Iterator & operator++()
@ -515,14 +487,11 @@ namespace cereal
//! Get the value of the current node //! Get the value of the current node
GenericValue const & value() GenericValue const & value()
{ {
if( itsIndex >= itsSize )
throw cereal::Exception("No more objects in input");
switch(itsType) switch(itsType)
{ {
case Value : return itsValueItBegin[itsIndex]; case Value : return itsValueItBegin[itsIndex];
case Member: return itsMemberItBegin[itsIndex].value; case Member: return itsMemberItBegin[itsIndex].value;
default: throw cereal::Exception("JSONInputArchive internal error: null or empty iterator to object or array!"); default: throw cereal::Exception("Invalid Iterator Type!");
} }
} }
@ -557,8 +526,8 @@ namespace cereal
private: private:
MemberIterator itsMemberItBegin, itsMemberItEnd; //!< The member iterator (object) MemberIterator itsMemberItBegin, itsMemberItEnd; //!< The member iterator (object)
ValueIterator itsValueItBegin; //!< The value iterator (array) ValueIterator itsValueItBegin, itsValueItEnd; //!< The value iterator (array)
size_t itsIndex, itsSize; //!< The current index of this iterator 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 enum Type {Value, Member, Null_} itsType; //!< Whether this holds values (array) or members (objects) or nothing
}; };
@ -573,20 +542,18 @@ namespace cereal
@throws Exception if an expectedName is given and not found */ @throws Exception if an expectedName is given and not found */
inline void search() inline void search()
{ {
// store pointer to itsNextName locally and reset to nullptr in case search() throws
auto localNextName = itsNextName;
itsNextName = nullptr;
// The name an NVP provided with setNextName() // The name an NVP provided with setNextName()
if( localNextName ) if( itsNextName )
{ {
// The actual name of the current node // The actual name of the current node
auto const actualName = itsIteratorStack.back().name(); 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 // Do a search if we don't see a name coming up, or if the names don't match
if( !actualName || std::strcmp( localNextName, actualName ) != 0 ) if( !actualName || std::strcmp( itsNextName, actualName ) != 0 )
itsIteratorStack.back().search( localNextName ); itsIteratorStack.back().search( itsNextName );
} }
itsNextName = nullptr;
} }
public: public:
@ -668,12 +635,6 @@ 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
@ -729,8 +690,6 @@ 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)
{ {
@ -754,7 +713,7 @@ namespace cereal
const char * itsNextName; //!< Next name set by NVP const char * itsNextName; //!< Next name set by NVP
ReadStream itsReadStream; //!< Rapidjson write stream ReadStream itsReadStream; //!< Rapidjson write stream
std::vector<Iterator> itsIteratorStack; //!< 'Stack' of rapidJSON iterators std::vector<Iterator> itsIteratorStack; //!< 'Stack' of rapidJSON iterators
CEREAL_RAPIDJSON_NAMESPACE::Document itsDocument; //!< Rapidjson document rapidjson::Document itsDocument; //!< Rapidjson document
}; };
// ###################################################################### // ######################################################################
@ -786,31 +745,6 @@ namespace cereal
void epilogue( JSONInputArchive &, NameValuePair<T> const & ) void epilogue( JSONInputArchive &, NameValuePair<T> const & )
{ } { }
// ######################################################################
//! Prologue for deferred data for JSON archives
/*! Do nothing for the defer wrapper */
template <class T> inline
void prologue( JSONOutputArchive &, DeferredData<T> const & )
{ }
//! Prologue for deferred data for JSON archives
template <class T> inline
void prologue( JSONInputArchive &, DeferredData<T> const & )
{ }
// ######################################################################
//! Epilogue for deferred for JSON archives
/*! NVPs do not start or finish nodes - they just set up the names */
template <class T> inline
void epilogue( JSONOutputArchive &, DeferredData<T> const & )
{ }
//! Epilogue for deferred for JSON archives
/*! Do nothing for the defer wrapper */
template <class T> inline
void epilogue( JSONInputArchive &, DeferredData<T> const & )
{ }
// ###################################################################### // ######################################################################
//! Prologue for SizeTags for JSON archives //! Prologue for SizeTags for JSON archives
/*! SizeTags are strictly ignored for JSON, they just indicate /*! SizeTags are strictly ignored for JSON, they just indicate

View File

@ -11,14 +11,14 @@
* Redistributions in binary form must reproduce the above copyright * Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution. documentation and/or other materials provided with the distribution.
* Neither the name of the copyright holder nor the * Neither the name of cereal nor the
names of its contributors may be used to endorse or promote products names of its contributors may be used to endorse or promote products
derived from this software without specific prior written permission. derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 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 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DISCLAIMED. IN NO EVENT SHALL RANDOLPH VOORHIES OR SHANE GRANT BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
@ -29,7 +29,7 @@
#ifndef CEREAL_ARCHIVES_PORTABLE_BINARY_HPP_ #ifndef CEREAL_ARCHIVES_PORTABLE_BINARY_HPP_
#define CEREAL_ARCHIVES_PORTABLE_BINARY_HPP_ #define CEREAL_ARCHIVES_PORTABLE_BINARY_HPP_
#include "cereal/cereal.hpp" #include <cereal/cereal.hpp>
#include <sstream> #include <sstream>
#include <limits> #include <limits>
@ -128,19 +128,19 @@ namespace cereal
~PortableBinaryOutputArchive() CEREAL_NOEXCEPT = default; ~PortableBinaryOutputArchive() CEREAL_NOEXCEPT = default;
//! Writes size bytes of data to the output stream //! Writes size bytes of data to the output stream
template <std::streamsize DataSize> inline template <std::size_t DataSize> inline
void saveBinary( const void * data, std::streamsize size ) void saveBinary( const void * data, std::size_t size )
{ {
std::streamsize writtenSize = 0; std::size_t writtenSize = 0;
if( itsConvertEndianness ) if( itsConvertEndianness )
{ {
for( std::streamsize i = 0; i < size; i += DataSize ) for( std::size_t i = 0; i < size; i += DataSize )
for( std::streamsize j = 0; j < DataSize; ++j ) for( std::size_t j = 0; j < DataSize; ++j )
writtenSize += itsStream.rdbuf()->sputn( reinterpret_cast<const char*>( data ) + DataSize - j - 1 + i, 1 ); writtenSize += static_cast<std::size_t>( itsStream.rdbuf()->sputn( reinterpret_cast<const char*>( data ) + DataSize - j - 1 + i, 1 ) );
} }
else else
writtenSize = itsStream.rdbuf()->sputn( reinterpret_cast<const char*>( data ), size ); writtenSize = static_cast<std::size_t>( itsStream.rdbuf()->sputn( reinterpret_cast<const char*>( data ), size ) );
if(writtenSize != size) if(writtenSize != size)
throw Exception("Failed to write " + std::to_string(size) + " bytes to output stream! Wrote " + std::to_string(writtenSize)); throw Exception("Failed to write " + std::to_string(size) + " bytes to output stream! Wrote " + std::to_string(writtenSize));
@ -235,11 +235,11 @@ namespace cereal
/*! @param data The data to save /*! @param data The data to save
@param size The number of bytes in the data @param size The number of bytes in the data
@tparam DataSize T The size of the actual type of the data elements being loaded */ @tparam DataSize T The size of the actual type of the data elements being loaded */
template <std::streamsize DataSize> inline template <std::size_t DataSize> inline
void loadBinary( void * const data, std::streamsize size ) void loadBinary( void * const data, std::size_t size )
{ {
// load data // load data
auto const readSize = itsStream.rdbuf()->sgetn( reinterpret_cast<char*>( data ), size ); auto const readSize = static_cast<std::size_t>( itsStream.rdbuf()->sgetn( reinterpret_cast<char*>( data ), size ) );
if(readSize != size) if(readSize != size)
throw Exception("Failed to read " + std::to_string(size) + " bytes from input stream! Read " + std::to_string(readSize)); throw Exception("Failed to read " + std::to_string(size) + " bytes from input stream! Read " + std::to_string(readSize));
@ -248,7 +248,7 @@ namespace cereal
if( itsConvertEndianness ) if( itsConvertEndianness )
{ {
std::uint8_t * ptr = reinterpret_cast<std::uint8_t*>( data ); std::uint8_t * ptr = reinterpret_cast<std::uint8_t*>( data );
for( std::streamsize i = 0; i < size; i += DataSize ) for( std::size_t i = 0; i < size; i += DataSize )
portable_binary_detail::swap_bytes<DataSize>( ptr + i ); portable_binary_detail::swap_bytes<DataSize>( ptr + i );
} }
} }
@ -308,7 +308,7 @@ namespace cereal
(std::is_floating_point<TT>::value && std::numeric_limits<TT>::is_iec559), (std::is_floating_point<TT>::value && std::numeric_limits<TT>::is_iec559),
"Portable binary only supports IEEE 754 standardized floating point" ); "Portable binary only supports IEEE 754 standardized floating point" );
ar.template saveBinary<sizeof(TT)>( bd.data, static_cast<std::streamsize>( bd.size ) ); ar.template saveBinary<sizeof(TT)>( bd.data, static_cast<std::size_t>( bd.size ) );
} }
//! Loading binary data from portable binary //! Loading binary data from portable binary
@ -320,7 +320,7 @@ namespace cereal
(std::is_floating_point<TT>::value && std::numeric_limits<TT>::is_iec559), (std::is_floating_point<TT>::value && std::numeric_limits<TT>::is_iec559),
"Portable binary only supports IEEE 754 standardized floating point" ); "Portable binary only supports IEEE 754 standardized floating point" );
ar.template loadBinary<sizeof(TT)>( bd.data, static_cast<std::streamsize>( bd.size ) ); ar.template loadBinary<sizeof(TT)>( bd.data, static_cast<std::size_t>( bd.size ) );
} }
} // namespace cereal } // namespace cereal

View File

@ -11,14 +11,14 @@
* Redistributions in binary form must reproduce the above copyright * Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution. documentation and/or other materials provided with the distribution.
* Neither the name of the copyright holder nor the * Neither the name of cereal nor the
names of its contributors may be used to endorse or promote products names of its contributors may be used to endorse or promote products
derived from this software without specific prior written permission. derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 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 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DISCLAIMED. IN NO EVENT SHALL RANDOLPH VOORHIES OR SHANE GRANT BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
@ -28,12 +28,12 @@
*/ */
#ifndef CEREAL_ARCHIVES_XML_HPP_ #ifndef CEREAL_ARCHIVES_XML_HPP_
#define CEREAL_ARCHIVES_XML_HPP_ #define CEREAL_ARCHIVES_XML_HPP_
#include "cereal/cereal.hpp" #include <cereal/cereal.hpp>
#include "cereal/details/util.hpp" #include <cereal/details/util.hpp>
#include "cereal/external/rapidxml/rapidxml.hpp" #include <cereal/external/rapidxml/rapidxml.hpp>
#include "cereal/external/rapidxml/rapidxml_print.hpp" #include <cereal/external/rapidxml/rapidxml_print.hpp>
#include "cereal/external/base64.hpp" #include <cereal/external/base64.hpp>
#include <sstream> #include <sstream>
#include <stack> #include <stack>
@ -101,58 +101,31 @@ namespace cereal
//! @{ //! @{
//! A class containing various advanced options for the XML archive //! A class containing various advanced options for the XML archive
/*! Options can either be directly passed to the constructor, or chained using the
modifier functions for an interface analogous to named parameters */
class Options class Options
{ {
public: public:
//! Default options //! Default options
static Options Default(){ return 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 //! Specify specific options for the XMLOutputArchive
/*! @param precision_ The precision used for floating point numbers /*! @param precision The precision used for floating point numbers
@param indent_ Whether to indent each line of XML @param indent Whether to indent each line of XML
@param outputType_ Whether to output the type of each serialized object as an attribute @param outputType Whether to output the type of each serialized object as an attribute */
@param sizeAttributes_ Whether dynamically sized containers output the size=dynamic attribute */ explicit Options( int precision = std::numeric_limits<double>::max_digits10,
explicit Options( int precision_ = std::numeric_limits<double>::max_digits10, bool indent = true,
bool indent_ = true, bool outputType = false ) :
bool outputType_ = false, itsPrecision( precision ),
bool sizeAttributes_ = true ) : itsIndent( indent ),
itsPrecision( precision_ ), itsOutputType( outputType ) { }
itsIndent( indent_ ),
itsOutputType( outputType_ ),
itsSizeAttributes( sizeAttributes_ )
{ }
/*! @name Option Modifiers
An interface for setting option settings analogous to named parameters.
@code{cpp}
cereal::XMLOutputArchive ar( myStream,
cereal::XMLOutputArchive::Options()
.indent(true)
.sizeAttributes(false) );
@endcode
*/
//! @{
//! Sets the precision used for floating point numbers
Options & precision( int value ){ itsPrecision = value; return * this; }
//! Whether to indent each line of XML
Options & indent( bool enable ){ itsIndent = enable; return *this; }
//! Whether to output the type of each serialized object as an attribute
Options & outputType( bool enable ){ itsOutputType = enable; return *this; }
//! Whether dynamically sized containers (e.g. vector) output the size=dynamic attribute
Options & sizeAttributes( bool enable ){ itsSizeAttributes = enable; return *this; }
//! @}
private: private:
friend class XMLOutputArchive; friend class XMLOutputArchive;
int itsPrecision; int itsPrecision;
bool itsIndent; bool itsIndent;
bool itsOutputType; bool itsOutputType;
bool itsSizeAttributes;
}; };
//! Construct, outputting to the provided stream upon destruction //! Construct, outputting to the provided stream upon destruction
@ -164,8 +137,7 @@ namespace cereal
OutputArchive<XMLOutputArchive>(this), OutputArchive<XMLOutputArchive>(this),
itsStream(stream), itsStream(stream),
itsOutputType( options.itsOutputType ), itsOutputType( options.itsOutputType ),
itsIndent( options.itsIndent ), itsIndent( options.itsIndent )
itsSizeAttributes(options.itsSizeAttributes)
{ {
// rapidxml will delete all allocations when xml_document is cleared // rapidxml will delete all allocations when xml_document is cleared
auto node = itsXML.allocate_node( rapidxml::node_declaration ); auto node = itsXML.allocate_node( rapidxml::node_declaration );
@ -210,7 +182,7 @@ namespace cereal
itsNodes.top().node->append_attribute( itsXML.allocate_attribute( "type", "cereal binary data" ) ); itsNodes.top().node->append_attribute( itsXML.allocate_attribute( "type", "cereal binary data" ) );
finishNode(); finishNode();
} };
//! @} //! @}
/*! @name Internal Functionality /*! @name Internal Functionality
@ -317,8 +289,6 @@ namespace cereal
itsNodes.top().node->append_attribute( itsXML.allocate_attribute( namePtr, valuePtr ) ); itsNodes.top().node->append_attribute( itsXML.allocate_attribute( namePtr, valuePtr ) );
} }
bool hasSizeAttributes() const { return itsSizeAttributes; }
protected: protected:
//! A struct that contains metadata about a node //! A struct that contains metadata about a node
struct NodeInfo struct NodeInfo
@ -360,7 +330,6 @@ namespace cereal
std::ostringstream itsOS; //!< Used to format strings internally std::ostringstream itsOS; //!< Used to format strings internally
bool itsOutputType; //!< Controls whether type information is printed bool itsOutputType; //!< Controls whether type information is printed
bool itsIndent; //!< Controls whether indenting is used bool itsIndent; //!< Controls whether indenting is used
bool itsSizeAttributes; //!< Controls whether lists have a size attribute
}; // XMLOutputArchive }; // XMLOutputArchive
// ###################################################################### // ######################################################################
@ -467,7 +436,7 @@ namespace cereal
std::memcpy( data, decoded.data(), decoded.size() ); std::memcpy( data, decoded.data(), decoded.size() );
finishNode(); finishNode();
} };
//! @} //! @}
/*! @name Internal Functionality /*! @name Internal Functionality
@ -789,42 +758,14 @@ namespace cereal
void epilogue( XMLInputArchive &, NameValuePair<T> const & ) void epilogue( XMLInputArchive &, NameValuePair<T> const & )
{ } { }
// ######################################################################
//! Prologue for deferred data for XML archives
/*! Do nothing for the defer wrapper */
template <class T> inline
void prologue( XMLOutputArchive &, DeferredData<T> const & )
{ }
//! Prologue for deferred data for XML archives
template <class T> inline
void prologue( XMLInputArchive &, DeferredData<T> const & )
{ }
// ######################################################################
//! Epilogue for deferred for XML archives
/*! NVPs do not start or finish nodes - they just set up the names */
template <class T> inline
void epilogue( XMLOutputArchive &, DeferredData<T> const & )
{ }
//! Epilogue for deferred for XML archives
/*! Do nothing for the defer wrapper */
template <class T> inline
void epilogue( XMLInputArchive &, DeferredData<T> const & )
{ }
// ###################################################################### // ######################################################################
//! Prologue for SizeTags for XML output archives //! Prologue for SizeTags for XML output archives
/*! SizeTags do not start or finish nodes */ /*! SizeTags do not start or finish nodes */
template <class T> inline template <class T> inline
void prologue( XMLOutputArchive & ar, SizeTag<T> const & ) void prologue( XMLOutputArchive & ar, SizeTag<T> const & )
{
if (ar.hasSizeAttributes())
{ {
ar.appendAttribute( "size", "dynamic" ); ar.appendAttribute( "size", "dynamic" );
} }
}
template <class T> inline template <class T> inline
void prologue( XMLInputArchive &, SizeTag<T> const & ) void prologue( XMLInputArchive &, SizeTag<T> const & )

View File

@ -11,14 +11,14 @@
* Redistributions in binary form must reproduce the above copyright * Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution. documentation and/or other materials provided with the distribution.
* Neither the name of the copyright holder nor the * Neither the name of cereal nor the
names of its contributors may be used to endorse or promote products names of its contributors may be used to endorse or promote products
derived from this software without specific prior written permission. derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 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 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DISCLAIMED. IN NO EVENT SHALL RANDOLPH VOORHIES OR SHANE GRANT BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
@ -32,7 +32,6 @@
#include <type_traits> #include <type_traits>
#include <string> #include <string>
#include <memory> #include <memory>
#include <functional>
#include <unordered_map> #include <unordered_map>
#include <unordered_set> #include <unordered_set>
#include <vector> #include <vector>
@ -40,10 +39,10 @@
#include <cstdint> #include <cstdint>
#include <functional> #include <functional>
#include "cereal/macros.hpp" #include <cereal/macros.hpp>
#include "cereal/details/traits.hpp" #include <cereal/details/traits.hpp>
#include "cereal/details/helpers.hpp" #include <cereal/details/helpers.hpp>
#include "cereal/types/base_class.hpp" #include <cereal/types/base_class.hpp>
namespace cereal namespace cereal
{ {
@ -98,59 +97,6 @@ namespace cereal
return {std::forward<T>(sz)}; return {std::forward<T>(sz)};
} }
// ######################################################################
//! Marks data for deferred serialization
/*! cereal performs a recursive depth-first traversal of data it serializes. When
serializing smart pointers to large, nested, or cyclical data structures, it
is possible to encounter a stack overflow from excessive recursion when following
a chain of pointers.
Deferment can help in these situations if the data can be serialized separately from
the pointers used to traverse the structure. For example, a graph structure can have its
nodes serialized before its edges:
@code{.cpp}
struct MyEdge
{
std::shared_ptr<MyNode> connection;
int some_value;
template<class Archive>
void serialize(Archive & archive)
{
// when we serialize an edge, we'll defer serializing the associated node
archive( cereal::defer( connection ),
some_value );
}
};
struct MyGraphStructure
{
std::vector<MyEdge> edges;
std::vector<MyNodes> nodes;
template<class Archive>
void serialize(Archive & archive)
{
// because of the deferment, we ensure all nodes are fully serialized
// before any connection pointers to those nodes are serialized
archive( edges, nodes );
// we have to explicitly inform the archive when it is safe to serialize
// the deferred data
archive.serializeDeferments();
}
};
@endcode
@relates DeferredData
@ingroup Utility */
template <class T> inline
DeferredData<T> defer( T && value )
{
return {std::forward<T>(value)};
}
// ###################################################################### // ######################################################################
//! Called before a type is serialized to set up any special archive state //! Called before a type is serialized to set up any special archive state
//! for processing some type //! for processing some type
@ -176,7 +122,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 propagate silently and your static error will occur - the error will propogate 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
@ -199,14 +145,6 @@ namespace cereal
instantiate_polymorphic_binding( T*, Archive*, BindingTag, adl_tag ); \ instantiate_polymorphic_binding( T*, Archive*, BindingTag, adl_tag ); \
} } /* end namespaces */ } } /* end namespaces */
//! Helper macro to omit unused warning
#if defined(__GNUC__)
// GCC / clang don't want the function
#define CEREAL_UNUSED_FUNCTION
#else
#define CEREAL_UNUSED_FUNCTION static void unused() { (void)version; }
#endif
// ###################################################################### // ######################################################################
//! Defines a class version for some type //! Defines a class version for some type
/*! Versioning information is optional and adds some small amount of /*! Versioning information is optional and adds some small amount of
@ -258,26 +196,6 @@ namespace cereal
Interfaces for other forms of serialization functions is similar. This Interfaces for other forms of serialization functions is similar. This
macro should be placed at global scope. macro should be placed at global scope.
@ingroup Utility */ @ingroup Utility */
//! On C++17, define the StaticObject as inline to merge the definitions across TUs
//! This prevents multiple definition errors when this macro appears in a header file
//! included in multiple TUs.
#ifdef CEREAL_HAS_CPP17
#define CEREAL_CLASS_VERSION(TYPE, VERSION_NUMBER) \
namespace cereal { namespace detail { \
template <> struct Version<TYPE> \
{ \
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 inline const std::uint32_t version = registerVersion(); \
CEREAL_UNUSED_FUNCTION \
}; /* end Version */ \
} } // end namespaces
#else
#define CEREAL_CLASS_VERSION(TYPE, VERSION_NUMBER) \ #define CEREAL_CLASS_VERSION(TYPE, VERSION_NUMBER) \
namespace cereal { namespace detail { \ namespace cereal { namespace detail { \
template <> struct Version<TYPE> \ template <> struct Version<TYPE> \
@ -289,14 +207,12 @@ namespace cereal
std::type_index(typeid(TYPE)).hash_code(), VERSION_NUMBER ); \ std::type_index(typeid(TYPE)).hash_code(), VERSION_NUMBER ); \
return VERSION_NUMBER; \ return VERSION_NUMBER; \
} \ } \
CEREAL_UNUSED_FUNCTION \ static void unused() { (void)version; } \
}; /* end Version */ \ }; /* end Version */ \
const std::uint32_t Version<TYPE>::version = \ const std::uint32_t Version<TYPE>::version = \
Version<TYPE>::registerVersion(); \ Version<TYPE>::registerVersion(); \
} } // end namespaces } } // end namespaces
#endif
// ###################################################################### // ######################################################################
//! The base output archive class //! The base output archive class
/*! This is the base output archive for all output archives. If you create /*! This is the base output archive for all output archives. If you create
@ -334,33 +250,11 @@ namespace cereal
return *self; return *self;
} }
//! Serializes any data marked for deferment using defer
/*! This will cause any data wrapped in DeferredData to be immediately serialized */
void serializeDeferments()
{
for( auto & deferment : itsDeferments )
deferment();
}
/*! @name Boost Transition Layer /*! @name Boost Transition Layer
Functionality that mirrors the syntax for Boost. This is useful if you are transitioning 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(). */ a large project from Boost to cereal. The preferred interface for cereal is using operator(). */
//! @{ //! @{
//! Indicates this archive is not intended for loading
/*! This ensures compatibility with boost archive types. If you are transitioning
from boost, you can check this value within a member or external serialize function
(i.e., Archive::is_loading::value) to disable behavior specific to loading, until
you can transition to split save/load or save_minimal/load_minimal functions */
using is_loading = std::false_type;
//! Indicates this archive is intended for saving
/*! This ensures compatibility with boost archive types. If you are transitioning
from boost, you can check this value within a member or external serialize function
(i.e., Archive::is_saving::value) to enable behavior specific to loading, until
you can transition to split save/load or save_minimal/load_minimal functions */
using is_saving = std::true_type;
//! Serializes passed in data //! Serializes passed in data
/*! This is a boost compatability layer and is not the preferred way of using /*! 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 cereal. If you are transitioning from boost, use this until you can
@ -391,17 +285,12 @@ namespace cereal
point to the same data. point to the same data.
@internal @internal
@param sharedPointer The shared pointer itself (the address is taken via get()). @param addr The address (see shared_ptr get()) pointed to by the shared pointer
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.
@return A key that uniquely identifies the pointer */ @return A key that uniquely identifies the pointer */
inline std::uint32_t registerSharedPointer(const std::shared_ptr<const void>& sharedPointer) inline std::uint32_t registerSharedPointer( void const * addr )
{ {
void const * addr = sharedPointer.get();
// Handle null pointers by just returning 0 // Handle null pointers by just returning 0
if(addr == 0) return 0; if(addr == 0) return 0;
itsSharedPointerStorage.push_back(sharedPointer);
auto id = itsSharedPointerMap.find( addr ); auto id = itsSharedPointerMap.find( addr );
if( id == itsSharedPointerMap.end() ) if( id == itsSharedPointerMap.end() )
@ -476,17 +365,6 @@ namespace cereal
return *self; return *self;
} }
std::vector<std::function<void(void)>> itsDeferments;
template <class T> inline
ArchiveType & processImpl(DeferredData<T> const & d)
{
std::function<void(void)> deferment( [this, d](){ self->process( d.value ); } );
itsDeferments.emplace_back( std::move(deferment) );
return *self;
}
//! Helper macro that expands the requirements for activating an overload //! Helper macro that expands the requirements for activating an overload
/*! Requirements: /*! Requirements:
Has the requested serialization function Has the requested serialization function
@ -591,7 +469,8 @@ namespace cereal
/*! If this is the first time this class has been serialized, we will record its /*! If this is the first time this class has been serialized, we will record its
version number and serialize that. version number and serialize that.
@tparam T The type of the class being serialized */ @tparam T The type of the class being serialized
@param version The version number associated with it */
template <class T> inline template <class T> inline
std::uint32_t registerClassVersion() std::uint32_t registerClassVersion()
{ {
@ -672,10 +551,6 @@ namespace cereal
//! Maps from addresses to pointer ids //! Maps from addresses to pointer ids
std::unordered_map<void const *, std::uint32_t> itsSharedPointerMap; std::unordered_map<void const *, std::uint32_t> itsSharedPointerMap;
//! Copy of shared pointers used in #itsSharedPointerMap to make sure they are kept alive
// during lifetime of itsSharedPointerMap to prevent CVE-2020-11105.
std::vector<std::shared_ptr<const void>> itsSharedPointerStorage;
//! The id to be given to the next pointer //! The id to be given to the next pointer
std::uint32_t itsCurrentPointerId; std::uint32_t itsCurrentPointerId;
@ -731,33 +606,11 @@ namespace cereal
return *self; return *self;
} }
//! Serializes any data marked for deferment using defer
/*! This will cause any data wrapped in DeferredData to be immediately serialized */
void serializeDeferments()
{
for( auto & deferment : itsDeferments )
deferment();
}
/*! @name Boost Transition Layer /*! @name Boost Transition Layer
Functionality that mirrors the syntax for Boost. This is useful if you are transitioning 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(). */ a large project from Boost to cereal. The preferred interface for cereal is using operator(). */
//! @{ //! @{
//! Indicates this archive is intended for loading
/*! This ensures compatibility with boost archive types. If you are transitioning
from boost, you can check this value within a member or external serialize function
(i.e., Archive::is_loading::value) to enable behavior specific to loading, until
you can transition to split save/load or save_minimal/load_minimal functions */
using is_loading = std::true_type;
//! Indicates this archive is not intended for saving
/*! This ensures compatibility with boost archive types. If you are transitioning
from boost, you can check this value within a member or external serialize function
(i.e., Archive::is_saving::value) to disable behavior specific to loading, until
you can transition to split save/load or save_minimal/load_minimal functions */
using is_saving = std::false_type;
//! Serializes passed in data //! Serializes passed in data
/*! This is a boost compatability layer and is not the preferred way of using /*! 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 cereal. If you are transitioning from boost, use this until you can
@ -786,7 +639,6 @@ namespace cereal
/*! This is used to retrieve a previously registered shared_ptr /*! This is used to retrieve a previously registered shared_ptr
which has already been loaded. which has already been loaded.
@internal
@param id The unique id that was serialized for the pointer @param id The unique id that was serialized for the pointer
@return A shared pointer to the data @return A shared pointer to the data
@throw Exception if the id does not exist */ @throw Exception if the id does not exist */
@ -805,7 +657,6 @@ namespace cereal
/*! After a shared pointer has been allocated for the first time, it should /*! After a shared pointer has been allocated for the first time, it should
be registered with its loaded id for future references to it. be registered with its loaded id for future references to it.
@internal
@param id The unique identifier for the shared pointer @param id The unique identifier for the shared pointer
@param ptr The actual shared pointer */ @param ptr The actual shared pointer */
inline void registerSharedPointer(std::uint32_t const id, std::shared_ptr<void> ptr) inline void registerSharedPointer(std::uint32_t const id, std::shared_ptr<void> ptr)
@ -818,9 +669,8 @@ namespace cereal
/*! This is used to retrieve a string previously registered during /*! This is used to retrieve a string previously registered during
a polymorphic load. a polymorphic load.
@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 type */ @return The string identifier for the tyep */
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 );
@ -835,9 +685,8 @@ namespace cereal
/*! After a polymorphic type has been loaded for the first time, it should /*! After a polymorphic type has been loaded for the first time, it should
be registered with its loaded id for future references to it. be registered with its loaded id for future references to it.
@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 type */ @param name The name associated with the tyep */
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;
@ -885,17 +734,6 @@ namespace cereal
return *self; return *self;
} }
std::vector<std::function<void(void)>> itsDeferments;
template <class T> inline
ArchiveType & processImpl(DeferredData<T> const & d)
{
std::function<void(void)> deferment( [this, d](){ self->process( d.value ); } );
itsDeferments.emplace_back( std::move(deferment) );
return *self;
}
//! Helper macro that expands the requirements for activating an overload //! Helper macro that expands the requirements for activating an overload
/*! Requirements: /*! Requirements:
Has the requested serialization function Has the requested serialization function
@ -1009,7 +847,8 @@ namespace cereal
/*! If this is the first time this class has been serialized, we will record its /*! If this is the first time this class has been serialized, we will record its
version number and serialize that. version number and serialize that.
@tparam T The type of the class being serialized */ @tparam T The type of the class being serialized
@param version The version number associated with it */
template <class T> inline template <class T> inline
std::uint32_t loadClassVersion() std::uint32_t loadClassVersion()
{ {
@ -1115,6 +954,6 @@ namespace cereal
} // namespace cereal } // namespace cereal
// This include needs to come after things such as binary_data, make_nvp, etc // This include needs to come after things such as binary_data, make_nvp, etc
#include "cereal/types/common.hpp" #include <cereal/types/common.hpp>
#endif // CEREAL_CEREAL_HPP_ #endif // CEREAL_CEREAL_HPP_

View File

@ -12,14 +12,14 @@
* Redistributions in binary form must reproduce the above copyright * Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution. documentation and/or other materials provided with the distribution.
* Neither the name of the copyright holder nor the * Neither the name of cereal nor the
names of its contributors may be used to endorse or promote products names of its contributors may be used to endorse or promote products
derived from this software without specific prior written permission. derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 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 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DISCLAIMED. IN NO EVENT SHALL RANDOLPH VOORHIES OR SHANE GRANT BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
@ -37,8 +37,8 @@
#include <unordered_map> #include <unordered_map>
#include <stdexcept> #include <stdexcept>
#include "cereal/macros.hpp" #include <cereal/macros.hpp>
#include "cereal/details/static_object.hpp" #include <cereal/details/static_object.hpp>
namespace cereal namespace cereal
{ {
@ -55,10 +55,8 @@ namespace cereal
//! The size type used by cereal //! The size type used by cereal
/*! To ensure compatability between 32, 64, etc bit machines, we need to use /*! 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 a fixed size type instead of size_t, which may vary from machine to
machine. machine. */
using size_type = uint64_t;
The default value for CEREAL_SIZE_TYPE is specified in cereal/macros.hpp */
using size_type = CEREAL_SIZE_TYPE;
// forward decls // forward decls
class BinaryOutputArchive; class BinaryOutputArchive;
@ -68,10 +66,8 @@ namespace cereal
namespace detail namespace detail
{ {
struct NameValuePairCore {}; //!< Traits struct for NVPs struct NameValuePairCore {}; //!< Traits struct for NVPs
struct DeferredDataCore {}; //!< Traits struct for DeferredData
} }
// ######################################################################
//! For holding name value pairs //! For holding name value pairs
/*! This pairs a name (some string) with some value such that an archive /*! This pairs a name (some string) with some value such that an archive
can potentially take advantage of the pairing. can potentially take advantage of the pairing.
@ -212,7 +208,7 @@ namespace cereal
{ {
//! Internally store the pointer as a void *, keeping const if created with //! Internally store the pointer as a void *, keeping const if created with
//! a const pointer //! a const pointer
using PT = typename std::conditional<std::is_const<typename std::remove_pointer<typename std::remove_reference<T>::type>::type>::value, using PT = typename std::conditional<std::is_const<typename std::remove_pointer<T>::type>::value,
const void *, const void *,
void *>::type; void *>::type;
@ -222,43 +218,6 @@ namespace cereal
uint64_t size; //!< size in bytes uint64_t size; //!< size in bytes
}; };
// ######################################################################
//! A wrapper around data that should be serialized after all non-deferred data
/*! This class is used to demarcate data that can only be safely serialized after
any data not wrapped in this class.
@internal */
template <class T>
class DeferredData : detail::DeferredDataCore
{
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::DeferredDataCore, T>::value,
"Cannot defer DeferredData" );
DeferredData & operator=( DeferredData const & ) = delete;
public:
//! Constructs a new NameValuePair
/*! @param v The value to defer. 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 DeferredData 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 */
DeferredData( T && v ) : value(std::forward<T>(v)) {}
Type value;
};
// ###################################################################### // ######################################################################
namespace detail namespace detail
{ {
@ -295,7 +254,7 @@ namespace cereal
struct adl_tag; struct adl_tag;
// used during saving pointers // used during saving pointers
static const uint32_t msb_32bit = 0x80000000; static const int32_t msb_32bit = 0x80000000;
static const int32_t msb2_32bit = 0x40000000; static const int32_t msb2_32bit = 0x40000000;
} }

View File

@ -12,14 +12,14 @@
* Redistributions in binary form must reproduce the above copyright * Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution. documentation and/or other materials provided with the distribution.
* Neither the name of the copyright holder nor the * Neither the name of cereal nor the
names of its contributors may be used to endorse or promote products names of its contributors may be used to endorse or promote products
derived from this software without specific prior written permission. derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 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 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DISCLAIMED. IN NO EVENT SHALL RANDOLPH VOORHIES OR SHANE GRANT BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
@ -45,58 +45,32 @@
#ifndef CEREAL_DETAILS_POLYMORPHIC_IMPL_HPP_ #ifndef CEREAL_DETAILS_POLYMORPHIC_IMPL_HPP_
#define CEREAL_DETAILS_POLYMORPHIC_IMPL_HPP_ #define CEREAL_DETAILS_POLYMORPHIC_IMPL_HPP_
#include "cereal/details/polymorphic_impl_fwd.hpp" #include <cereal/details/polymorphic_impl_fwd.hpp>
#include "cereal/details/static_object.hpp" #include <cereal/details/static_object.hpp>
#include "cereal/types/memory.hpp" #include <cereal/types/memory.hpp>
#include "cereal/types/string.hpp" #include <cereal/types/string.hpp>
#include <functional> #include <functional>
#include <typeindex> #include <typeindex>
#include <map> #include <map>
#include <limits>
#include <set>
#include <stack>
//! Helper macro to omit unused warning //! Binds a polymorhic type to all registered archives
#if defined(__GNUC__)
// GCC / clang don't want the function
#define CEREAL_BIND_TO_ARCHIVES_UNUSED_FUNCTION
#else
#define CEREAL_BIND_TO_ARCHIVES_UNUSED_FUNCTION static void unused() { (void)b; }
#endif
//! 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
have been included). */ have been included). */
#ifdef CEREAL_HAS_CPP17
#define CEREAL_BIND_TO_ARCHIVES(...) \
namespace cereal { \
namespace detail { \
template<> \
struct init_binding<__VA_ARGS__> { \
static inline bind_to_archives<__VA_ARGS__> const & b= \
::cereal::detail::StaticObject< \
bind_to_archives<__VA_ARGS__> \
>::getInstance().bind(); \
CEREAL_BIND_TO_ARCHIVES_UNUSED_FUNCTION \
}; \
}} /* end namespaces */
#else
#define CEREAL_BIND_TO_ARCHIVES(...) \ #define CEREAL_BIND_TO_ARCHIVES(...) \
namespace cereal { \ namespace cereal { \
namespace detail { \ namespace detail { \
template<> \ template<> \
struct init_binding<__VA_ARGS__> { \ struct init_binding<__VA_ARGS__> { \
static bind_to_archives<__VA_ARGS__> const & b; \ static bind_to_archives<__VA_ARGS__> const & b; \
CEREAL_BIND_TO_ARCHIVES_UNUSED_FUNCTION \ static void unused() { (void)b; } \
}; \ }; \
bind_to_archives<__VA_ARGS__> const & init_binding<__VA_ARGS__>::b = \ bind_to_archives<__VA_ARGS__> const & init_binding<__VA_ARGS__>::b = \
::cereal::detail::StaticObject< \ ::cereal::detail::StaticObject< \
bind_to_archives<__VA_ARGS__> \ bind_to_archives<__VA_ARGS__> \
>::getInstance().bind(); \ >::getInstance().bind(); \
}} /* end namespaces */ }} /* end namespaces */
#endif
namespace cereal namespace cereal
{ {
@ -138,12 +112,8 @@ namespace cereal
all registered mappings between base and derived types. */ all registered mappings between base and derived types. */
struct PolymorphicCasters struct PolymorphicCasters
{ {
//! Maps from a derived type index to a set of chainable casters
using DerivedCasterMap = std::unordered_map<std::type_index, std::vector<PolymorphicCaster const *>>;
//! Maps from base type index to a map from derived type index to caster //! Maps from base type index to a map from derived type index to caster
std::unordered_map<std::type_index, DerivedCasterMap> map; std::map<std::type_index, std::map<std::type_index, std::vector<PolymorphicCaster const*>>> map;
std::multimap<std::type_index, std::type_index> reverseMap;
//! Error message used for unregistered polymorphic casts //! Error message used for unregistered polymorphic casts
#define UNREGISTERED_POLYMORPHIC_CAST_EXCEPTION(LoadSave) \ #define UNREGISTERED_POLYMORPHIC_CAST_EXCEPTION(LoadSave) \
@ -152,26 +122,24 @@ namespace cereal
"Make sure you either serialize the base class at some point via cereal::base_class or cereal::virtual_base_class.\n" \ "Make sure you either serialize the base class at some point via cereal::base_class or cereal::virtual_base_class.\n" \
"Alternatively, manually register the association with CEREAL_REGISTER_POLYMORPHIC_RELATION."); "Alternatively, manually register the association with CEREAL_REGISTER_POLYMORPHIC_RELATION.");
//! Checks if the mapping object that can perform the upcast or downcast exists, and returns it if so //! Checks if the mapping object that can perform the upcast or downcast
/*! Uses the type index from the base and derived class to find the matching /*! Uses the type index from the base and derived class to find the matching
registered caster. If no matching caster exists, the bool in the pair will be false and the vector registered caster. If no matching caster exists, returns false. */
reference should not be used. */ static bool exists( std::type_index const & baseIndex, std::type_index const & derivedIndex )
static std::pair<bool, std::vector<PolymorphicCaster const *> const &>
lookup_if_exists( std::type_index const & baseIndex, std::type_index const & derivedIndex )
{ {
// First phase of lookup - match base type index // First phase of lookup - match base type index
auto const & baseMap = StaticObject<PolymorphicCasters>::getInstance().map; auto const & baseMap = StaticObject<PolymorphicCasters>::getInstance().map;
auto baseIter = baseMap.find( baseIndex ); auto baseIter = baseMap.find( baseIndex );
if (baseIter == baseMap.end()) if (baseIter == baseMap.end())
return {false, {}}; return false;
// Second phase - find a match from base to derived // Second phase - find a match from base to derived
auto const & derivedMap = baseIter->second; auto & derivedMap = baseIter->second;
auto derivedIter = derivedMap.find( derivedIndex ); auto derivedIter = derivedMap.find( derivedIndex );
if (derivedIter == derivedMap.end()) if (derivedIter == derivedMap.end())
return {false, {}}; return false;
return {true, derivedIter->second}; return true;
} }
//! Gets the mapping object that can perform the upcast or downcast //! Gets the mapping object that can perform the upcast or downcast
@ -189,7 +157,7 @@ namespace cereal
exceptionFunc(); exceptionFunc();
// Second phase - find a match from base to derived // Second phase - find a match from base to derived
auto const & derivedMap = baseIter->second; auto & derivedMap = baseIter->second;
auto derivedIter = derivedMap.find( derivedIndex ); auto derivedIter = derivedMap.find( derivedIndex );
if( derivedIter == derivedMap.end() ) if( derivedIter == derivedMap.end() )
exceptionFunc(); exceptionFunc();
@ -203,8 +171,8 @@ namespace cereal
{ {
auto const & mapping = lookup( baseInfo, typeid(Derived), [&](){ UNREGISTERED_POLYMORPHIC_CAST_EXCEPTION(save) } ); auto const & mapping = lookup( baseInfo, typeid(Derived), [&](){ UNREGISTERED_POLYMORPHIC_CAST_EXCEPTION(save) } );
for( auto const * dmap : mapping ) for( auto const * map : mapping )
dptr = dmap->downcast( dptr ); dptr = map->downcast( dptr );
return static_cast<Derived const *>( dptr ); return static_cast<Derived const *>( dptr );
} }
@ -218,8 +186,8 @@ namespace cereal
auto const & mapping = lookup( baseInfo, typeid(Derived), [&](){ UNREGISTERED_POLYMORPHIC_CAST_EXCEPTION(load) } ); auto const & mapping = lookup( baseInfo, typeid(Derived), [&](){ UNREGISTERED_POLYMORPHIC_CAST_EXCEPTION(load) } );
void * uptr = dptr; void * uptr = dptr;
for( auto mIter = mapping.rbegin(), mEnd = mapping.rend(); mIter != mEnd; ++mIter ) for( auto const * map : mapping )
uptr = (*mIter)->upcast( uptr ); uptr = map->upcast( uptr );
return uptr; return uptr;
} }
@ -231,8 +199,8 @@ namespace cereal
auto const & mapping = lookup( baseInfo, typeid(Derived), [&](){ UNREGISTERED_POLYMORPHIC_CAST_EXCEPTION(load) } ); auto const & mapping = lookup( baseInfo, typeid(Derived), [&](){ UNREGISTERED_POLYMORPHIC_CAST_EXCEPTION(load) } );
std::shared_ptr<void> uptr = dptr; std::shared_ptr<void> uptr = dptr;
for( auto mIter = mapping.rbegin(), mEnd = mapping.rend(); mIter != mEnd; ++mIter ) for( auto const * map : mapping )
uptr = (*mIter)->upcast( uptr ); uptr = map->upcast( uptr );
return uptr; return uptr;
} }
@ -240,14 +208,6 @@ namespace cereal
#undef UNREGISTERED_POLYMORPHIC_CAST_EXCEPTION #undef UNREGISTERED_POLYMORPHIC_CAST_EXCEPTION
}; };
#ifdef CEREAL_OLDER_GCC
#define CEREAL_EMPLACE_MAP(map, key, value) \
map.insert( std::make_pair(std::move(key), std::move(value)) );
#else // NOT CEREAL_OLDER_GCC
#define CEREAL_EMPLACE_MAP(map, key, value) \
map.emplace( key, value );
#endif // NOT_CEREAL_OLDER_GCC
//! Strongly typed derivation of PolymorphicCaster //! Strongly typed derivation of PolymorphicCaster
template <class Base, class Derived> template <class Base, class Derived>
struct PolymorphicVirtualCaster : PolymorphicCaster struct PolymorphicVirtualCaster : PolymorphicCaster
@ -258,155 +218,72 @@ namespace cereal
assuming dynamic type information is available */ assuming dynamic type information is available */
PolymorphicVirtualCaster() PolymorphicVirtualCaster()
{ {
const auto baseKey = std::type_index(typeid(Base));
const auto derivedKey = std::type_index(typeid(Derived));
// First insert the relation Base->Derived
const auto lock = StaticObject<PolymorphicCasters>::lock(); const auto lock = StaticObject<PolymorphicCasters>::lock();
auto & baseMap = StaticObject<PolymorphicCasters>::getInstance().map; auto & baseMap = StaticObject<PolymorphicCasters>::getInstance().map;
auto baseKey = std::type_index(typeid(Base));
auto lb = baseMap.lower_bound(baseKey);
{ {
auto & derivedMap = baseMap.insert( {baseKey, PolymorphicCasters::DerivedCasterMap{}} ).first->second; auto & derivedMap = baseMap.insert( lb, {baseKey, {}} )->second;
auto & derivedVec = derivedMap.insert( {derivedKey, {}} ).first->second; auto derivedKey = std::type_index(typeid(Derived));
auto lbd = derivedMap.lower_bound(derivedKey);
auto & derivedVec = derivedMap.insert( lbd, { std::move(derivedKey), {}} )->second;
derivedVec.push_back( this ); derivedVec.push_back( this );
} }
// Insert reverse relation Derived->Base
auto & reverseMap = StaticObject<PolymorphicCasters>::getInstance().reverseMap;
CEREAL_EMPLACE_MAP(reverseMap, derivedKey, baseKey);
// 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 std::map<std::type_index, std::pair<std::type_index, std::vector<PolymorphicCaster const *>>> unregisteredRelations;
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 processes the parents of the active node,
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
the inserted base derived relationship */
{ {
// Checks whether there is a path from parent->child and returns a <dist, path> pair auto checkRelation = [](std::type_index const & baseInfo, std::type_index const & derivedInfo)
// dist is set to MAX if the path does not exist
auto checkRelation = [](std::type_index const & parentInfo, std::type_index const & childInfo) ->
std::pair<size_t, std::vector<PolymorphicCaster const *> const &>
{ {
auto result = PolymorphicCasters::lookup_if_exists( parentInfo, childInfo ); const bool exists = PolymorphicCasters::exists( baseInfo, derivedInfo );
if( result.first ) return std::make_pair( exists, exists ? PolymorphicCasters::lookup( baseInfo, derivedInfo, [](){} ) :
{ std::vector<PolymorphicCaster const *>{} );
auto const & path = result.second;
return {path.size(), path};
}
else
return {(std::numeric_limits<size_t>::max)(), {}};
}; };
std::stack<std::type_index> parentStack; // Holds the parent nodes to be processed for( auto baseIt : baseMap )
std::vector<std::type_index> dirtySet; // Marks child nodes that have been changed for( auto derivedIt : baseIt.second )
std::unordered_set<std::type_index> processedParents; // Marks parent nodes that have been processed
// Checks if a child has been marked dirty
auto isDirty = [&](std::type_index const & c)
{ {
auto const dirtySetSize = dirtySet.size(); for( auto otherBaseIt : baseMap )
for( size_t i = 0; i < dirtySetSize; ++i )
if( dirtySet[i] == c )
return true;
return false;
};
// Begin processing the base key and mark derived as dirty
parentStack.push( baseKey );
dirtySet.emplace_back( derivedKey );
while( !parentStack.empty() )
{ {
using Relations = std::unordered_multimap<std::type_index, std::pair<std::type_index, std::vector<PolymorphicCaster const *>>>; if( baseIt.first == otherBaseIt.first ) // only interested in chained relations
Relations unregisteredRelations; // Defer insertions until after main loop to prevent iterator invalidation
const auto parent = parentStack.top();
parentStack.pop();
// Update paths to all children marked dirty
for( auto const & childPair : baseMap[parent] )
{
const auto child = childPair.first;
if( isDirty( child ) && baseMap.count( child ) )
{
auto parentChildPath = checkRelation( parent, child );
// Search all paths from the child to its own children (finalChild),
// looking for a shorter path from parent to finalChild
for( auto const & finalChildPair : baseMap[child] )
{
const auto finalChild = finalChildPair.first;
auto parentFinalChildPath = checkRelation( parent, finalChild );
auto childFinalChildPath = checkRelation( child, finalChild );
const size_t newLength = 1u + parentChildPath.first;
if( newLength < parentFinalChildPath.first )
{
std::vector<PolymorphicCaster const *> path = parentChildPath.second;
path.insert( path.end(), childFinalChildPath.second.begin(), childFinalChildPath.second.end() );
// Check to see if we have a previous uncommitted path in unregisteredRelations
// that is shorter. If so, ignore this path
auto hintRange = unregisteredRelations.equal_range( parent );
auto hint = hintRange.first;
for( ; hint != hintRange.second; ++hint )
if( hint->second.first == finalChild )
break;
const bool uncommittedExists = hint != unregisteredRelations.end();
if( uncommittedExists && (hint->second.second.size() <= newLength) )
continue; continue;
auto newPath = std::pair<std::type_index, std::vector<PolymorphicCaster const *>>{finalChild, std::move(path)}; // Check if there exists a mapping otherBase -> base -> derived that is shorter than
// any existing otherBase -> derived direct mapping
auto otherBaseItToDerived = checkRelation( otherBaseIt.first, derivedIt.first );
auto baseToDerived = checkRelation( baseIt.first, derivedIt.first );
auto otherBaseToBase = checkRelation( otherBaseIt.first, baseIt.first );
const size_t newLength = otherBaseToBase.second.size() + baseToDerived.second.size();
const bool isShorterOrFirstPath = !otherBaseItToDerived.first || (newLength < derivedIt.second.size());
if( isShorterOrFirstPath &&
baseToDerived.first &&
otherBaseToBase.first )
{
std::vector<PolymorphicCaster const *> path = otherBaseToBase.second;
path.insert( path.end(), baseToDerived.second.begin(), baseToDerived.second.end() );
// Insert the new path if it doesn't exist, otherwise this will just lookup where to do the
// replacement
#ifdef CEREAL_OLDER_GCC #ifdef CEREAL_OLDER_GCC
auto old = unregisteredRelations.insert( hint, std::make_pair(parent, newPath) ); unregisteredRelations.insert( std::make_pair(otherBaseIt.first,
std::pair<std::type_index, std::vector<PolymorphicCaster const *>>{derivedIt.first, std::move(path)}) );
#else // NOT CEREAL_OLDER_GCC #else // NOT CEREAL_OLDER_GCC
auto old = unregisteredRelations.emplace_hint( hint, parent, newPath ); unregisteredRelations.emplace( otherBaseIt.first,
std::pair<std::type_index, std::vector<PolymorphicCaster const *>>{derivedIt.first, std::move(path)} );
#endif // NOT CEREAL_OLDER_GCC #endif // NOT CEREAL_OLDER_GCC
// If there was an uncommitted path, we need to perform a replacement
if( uncommittedExists )
old->second = newPath;
} }
} // end loop over child's children } // end otherBaseIt
} // end if dirty and child has children } // end derivedIt
} // end loop over children } // end chain lookup
// Insert chained relations // Insert chained relations
for( auto const & it : unregisteredRelations ) for( auto it : unregisteredRelations )
{ {
auto & derivedMap = baseMap.find( it.first )->second; auto & derivedMap = baseMap.find( it.first )->second;
derivedMap[it.second.first] = it.second.second; derivedMap[it.second.first] = it.second.second;
CEREAL_EMPLACE_MAP(reverseMap, it.second.first, it.first );
}
// Mark current parent as modified
dirtySet.emplace_back( parent );
// Insert all parents of the current parent node that haven't yet been processed
auto parentRange = reverseMap.equal_range( parent );
for( auto pIter = parentRange.first; pIter != parentRange.second; ++pIter )
{
const auto pParent = pIter->second;
if( !processedParents.count( pParent ) )
{
parentStack.push( pParent );
processedParents.insert( pParent );
} }
} }
} // end loop over parent stack
} // end chainable relations
} // end PolymorphicVirtualCaster()
#undef CEREAL_EMPLACE_MAP
//! Performs the proper downcast with the templated types //! Performs the proper downcast with the templated types
void const * downcast( void const * const ptr ) const override void const * downcast( void const * const ptr ) const override
@ -669,7 +546,7 @@ namespace cereal
auto ptr = PolymorphicCasters::template downcast<T>( dptr, baseInfo ); auto ptr = PolymorphicCasters::template downcast<T>( dptr, baseInfo );
#if defined(_MSC_VER) && _MSC_VER < 1916 && !defined(__clang__) #ifdef _MSC_VER
savePolymorphicSharedPtr( ar, ptr, ::cereal::traits::has_shared_from_this<T>::type() ); // MSVC doesn't like typename here savePolymorphicSharedPtr( ar, ptr, ::cereal::traits::has_shared_from_this<T>::type() ); // MSVC doesn't like typename here
#else // not _MSC_VER #else // not _MSC_VER
savePolymorphicSharedPtr( ar, ptr, typename ::cereal::traits::has_shared_from_this<T>::type() ); savePolymorphicSharedPtr( ar, ptr, typename ::cereal::traits::has_shared_from_this<T>::type() );
@ -695,23 +572,9 @@ namespace cereal
//! of instantiate_polymorphic_binding //! of instantiate_polymorphic_binding
struct adl_tag {}; struct adl_tag {};
//! Tag for init_binding, bind_to_archives and instantiate_polymorphic_binding. //! Tag for init_binding, bind_to_archives and instantiate_polymorphic_binding. Due to the use of anonymous
//! For C++14 and below, we must instantiate a unique StaticObject per TU that is //! namespace it becomes a different type in each translation unit.
//! otherwise identical -- otherwise we get multiple definition problems (ODR violations).
//! To achieve this, put a tag in an anonymous namespace and use it as a template argument.
//!
//! For C++17, we can use static inline global variables to unify these definitions across
//! all TUs in the same shared object (DLL). The tag is therefore not necessary.
//! For convenience, keep it to not complicate other code, but don't put it in
//! an anonymous namespace. Now the template instantiations will correspond
//! to the same type, and since they are marked inline with C++17, they will be merged
//! across all TUs.
#ifdef CEREAL_HAS_CPP17
struct polymorphic_binding_tag {};
#else
namespace { struct polymorphic_binding_tag {}; } namespace { struct polymorphic_binding_tag {}; }
#endif
//! Causes the static object bindings between an archive type and a serializable type T //! Causes the static object bindings between an archive type and a serializable type T
template <class Archive, class T> template <class Archive, class T>
@ -782,7 +645,7 @@ namespace cereal
//! Binding for non abstract types //! Binding for non abstract types
void bind(std::false_type) const void bind(std::false_type) const
{ {
instantiate_polymorphic_binding(static_cast<T*>(nullptr), 0, Tag{}, adl_tag{}); instantiate_polymorphic_binding((T*) 0, 0, Tag{}, adl_tag{});
} }
//! Binding for abstract types //! Binding for abstract types
@ -812,7 +675,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 requiring a conversion from int to (Archive*), lower precedence due to requring 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

@ -12,14 +12,14 @@
* Redistributions in binary form must reproduce the above copyright * Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution. documentation and/or other materials provided with the distribution.
* Neither the name of the copyright holder nor the * Neither the name of cereal nor the
names of its contributors may be used to endorse or promote products names of its contributors may be used to endorse or promote products
derived from this software without specific prior written permission. derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 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 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DISCLAIMED. IN NO EVENT SHALL RANDOLPH VOORHIES OR SHANE GRANT BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND

View File

@ -11,13 +11,13 @@
* Redistributions in binary form must reproduce the above copyright * Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution. documentation and/or other materials provided with the distribution.
* Neither the name of the copyright holder nor the * Neither the name of cereal nor the
names of its contributors may be used to endorse or promote products names of its contributors may be used to endorse or promote products
derived from this software without specific prior written permission. derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 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 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DISCLAIMED. IN NO EVENT SHALL RANDOLPH VOORHIES OR SHANE GRANT BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
@ -28,7 +28,7 @@
#ifndef CEREAL_DETAILS_STATIC_OBJECT_HPP_ #ifndef CEREAL_DETAILS_STATIC_OBJECT_HPP_
#define CEREAL_DETAILS_STATIC_OBJECT_HPP_ #define CEREAL_DETAILS_STATIC_OBJECT_HPP_
#include "cereal/macros.hpp" #include <cereal/macros.hpp>
#if CEREAL_THREAD_SAFE #if CEREAL_THREAD_SAFE
#include <mutex> #include <mutex>
@ -44,11 +44,11 @@
License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
http://www.boost.org/LICENSE_1_0.txt) */ http://www.boost.org/LICENSE_1_0.txt) */
#if defined(_MSC_VER) && !defined(__clang__) #ifdef _MSC_VER
# define CEREAL_DLL_EXPORT __declspec(dllexport) # define CEREAL_DLL_EXPORT __declspec(dllexport)
# define CEREAL_USED # define CEREAL_USED
#else // clang or gcc #else // clang or gcc
# define CEREAL_DLL_EXPORT __attribute__ ((visibility("default"))) # define CEREAL_DLL_EXPORT
# define CEREAL_USED __attribute__ ((__used__)) # define CEREAL_USED __attribute__ ((__used__))
#endif #endif
@ -67,12 +67,13 @@ namespace cereal
class CEREAL_DLL_EXPORT StaticObject class CEREAL_DLL_EXPORT StaticObject
{ {
private: private:
//! Forces instantiation at pre-execution time
static void instantiate( T const & ) {}
static T & create() static T & create()
{ {
static T t; static T t;
//! Forces instantiation at pre-execution time instantiate(instance);
(void)instance;
return t; return t;
} }
@ -94,8 +95,6 @@ namespace cereal
std::unique_lock<std::mutex> lock; std::unique_lock<std::mutex> lock;
#else #else
public: public:
LockGuard() = default;
LockGuard(LockGuard const &) = default; // prevents implicit copy ctor warning
~LockGuard() CEREAL_NOEXCEPT {} // prevents variable not used ~LockGuard() CEREAL_NOEXCEPT {} // prevents variable not used
#endif #endif
}; };
@ -110,7 +109,6 @@ namespace cereal
static LockGuard lock() static LockGuard lock()
{ {
#if CEREAL_THREAD_SAFE #if CEREAL_THREAD_SAFE
static std::mutex instanceMutex;
return LockGuard{instanceMutex}; return LockGuard{instanceMutex};
#else #else
return LockGuard{}; return LockGuard{};
@ -119,9 +117,15 @@ namespace cereal
private: private:
static T & instance; static T & instance;
#if CEREAL_THREAD_SAFE
static std::mutex instanceMutex;
#endif
}; };
template <class T> T & StaticObject<T>::instance = StaticObject<T>::create(); template <class T> T & StaticObject<T>::instance = StaticObject<T>::create();
#if CEREAL_THREAD_SAFE
template <class T> std::mutex StaticObject<T>::instanceMutex;
#endif
} // namespace detail } // namespace detail
} // namespace cereal } // namespace cereal

View File

@ -12,14 +12,14 @@
* Redistributions in binary form must reproduce the above copyright * Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution. documentation and/or other materials provided with the distribution.
* Neither the name of the copyright holder nor the * Neither the name of cereal nor the
names of its contributors may be used to endorse or promote products names of its contributors may be used to endorse or promote products
derived from this software without specific prior written permission. derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 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 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DISCLAIMED. IN NO EVENT SHALL RANDOLPH VOORHIES OR SHANE GRANT BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
@ -39,8 +39,8 @@
#include <type_traits> #include <type_traits>
#include <typeindex> #include <typeindex>
#include "cereal/macros.hpp" #include <cereal/macros.hpp>
#include "cereal/access.hpp" #include <cereal/access.hpp>
namespace cereal namespace cereal
{ {
@ -800,18 +800,6 @@ namespace cereal
See notes from member load_minimal implementation. See notes from member load_minimal implementation.
Note that there should be an additional const check on load_minimal after the valid check,
but this currently interferes with many valid uses of minimal serialization. It has been
removed (see #565 on github) and previously was:
@code
static_assert( check::const_valid || !check::exists,
"cereal detected an invalid serialization type parameter in non-member " #test_name ". "
#test_name " non-member functions must accept their serialization type by non-const reference" );
@endcode
See #132, #436, #263, and #565 on https://github.com/USCiLab/cereal for more details.
@param test_name The name to give the test (e.g. load_minimal or versioned_load_minimal) @param test_name The name to give the test (e.g. load_minimal or versioned_load_minimal)
@param save_name The corresponding name the save test would have (e.g. save_minimal or versioned_save_minimal) @param save_name The corresponding name the save test would have (e.g. save_minimal or versioned_save_minimal)
@param versioned Either blank or the macro CEREAL_MAKE_VERSIONED_TEST */ @param versioned Either blank or the macro CEREAL_MAKE_VERSIONED_TEST */
@ -859,6 +847,9 @@ namespace cereal
static_assert( check::valid || !check::exists, "cereal detected different types in corresponding non-member " \ static_assert( check::valid || !check::exists, "cereal detected different types in corresponding non-member " \
#test_name " and " #save_name " functions. \n " \ #test_name " and " #save_name " functions. \n " \
"the paramater to " #test_name " must be a constant reference to the type that " #save_name " returns." ); \ "the paramater to " #test_name " must be a constant reference to the type that " #save_name " returns." ); \
static_assert( check::const_valid || !check::exists, \
"cereal detected an invalid serialization type parameter in non-member " #test_name ". " \
#test_name " non-member functions must accept their serialization type by non-const reference" ); \
}; \ }; \
} /* namespace detail */ \ } /* namespace detail */ \
\ \
@ -878,29 +869,17 @@ namespace cereal
#undef CEREAL_MAKE_HAS_NON_MEMBER_LOAD_MINIMAL_TEST #undef CEREAL_MAKE_HAS_NON_MEMBER_LOAD_MINIMAL_TEST
// ###################################################################### // ######################################################################
namespace detail //! Member load and construct check
{
// const stripped away before reaching here, prevents errors on conversion from
// construct<const T> to construct<T>
template<typename T, typename A> template<typename T, typename A>
struct has_member_load_and_construct_impl : std::integral_constant<bool, struct has_member_load_and_construct : std::integral_constant<bool,
std::is_same<decltype( access::load_and_construct<T>( std::declval<A&>(), std::declval< ::cereal::construct<T>&>() ) ), void>::value> std::is_same<decltype( access::load_and_construct<T>( std::declval<A&>(), std::declval< ::cereal::construct<T>&>() ) ), void>::value>
{ }; { };
template<typename T, typename A> // ######################################################################
struct has_member_versioned_load_and_construct_impl : std::integral_constant<bool,
std::is_same<decltype( access::load_and_construct<T>( std::declval<A&>(), std::declval< ::cereal::construct<T>&>(), 0 ) ), void>::value>
{ };
} // namespace detail
//! Member load and construct check
template<typename T, typename A>
struct has_member_load_and_construct : detail::has_member_load_and_construct_impl<typename std::remove_const<T>::type, A>
{ };
//! Member load and construct check (versioned) //! Member load and construct check (versioned)
template<typename T, typename A> template<typename T, typename A>
struct has_member_versioned_load_and_construct : detail::has_member_versioned_load_and_construct_impl<typename std::remove_const<T>::type, A> struct has_member_versioned_load_and_construct : std::integral_constant<bool,
std::is_same<decltype( access::load_and_construct<T>( std::declval<A&>(), std::declval< ::cereal::construct<T>&>(), 0 ) ), void>::value>
{ }; { };
// ###################################################################### // ######################################################################
@ -922,8 +901,7 @@ namespace cereal
}; \ }; \
} /* end namespace detail */ \ } /* end namespace detail */ \
template <class T, class A> \ template <class T, class A> \
struct has_non_member_##test_name : \ struct has_non_member_##test_name : std::integral_constant<bool, detail::has_non_member_##test_name##_impl<T, A>::value> {};
std::integral_constant<bool, detail::has_non_member_##test_name##_impl<typename std::remove_const<T>::type, A>::value> {};
// ###################################################################### // ######################################################################
//! Non member load and construct check //! Non member load and construct check
@ -1202,9 +1180,9 @@ namespace cereal
struct shared_from_this_wrapper struct shared_from_this_wrapper
{ {
template <class U> template <class U>
static auto (check)( U const & t ) -> decltype( ::cereal::access::shared_from_this(t), std::true_type() ); static auto check( U const & t ) -> decltype( ::cereal::access::shared_from_this(t), std::true_type() );
static auto (check)( ... ) -> decltype( std::false_type() ); static auto check( ... ) -> decltype( std::false_type() );
template <class U> template <class U>
static auto get( U const & t ) -> decltype( t.shared_from_this() ); static auto get( U const & t ) -> decltype( t.shared_from_this() );
@ -1213,7 +1191,7 @@ namespace cereal
//! Determine if T or any base class of T has inherited from std::enable_shared_from_this //! Determine if T or any base class of T has inherited from std::enable_shared_from_this
template<class T> template<class T>
struct has_shared_from_this : decltype((detail::shared_from_this_wrapper::check)(std::declval<T>())) struct has_shared_from_this : decltype(detail::shared_from_this_wrapper::check(std::declval<T>()))
{ }; { };
//! Get the type of the base class of T which inherited from std::enable_shared_from_this //! Get the type of the base class of T which inherited from std::enable_shared_from_this

View File

@ -12,14 +12,14 @@
* Redistributions in binary form must reproduce the above copyright * Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution. documentation and/or other materials provided with the distribution.
* Neither the name of the copyright holder nor the * Neither the name of cereal nor the
names of its contributors may be used to endorse or promote products names of its contributors may be used to endorse or promote products
derived from this software without specific prior written permission. derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 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 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DISCLAIMED. IN NO EVENT SHALL RANDOLPH VOORHIES OR SHANE GRANT BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND

View File

@ -1,21 +0,0 @@
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

View File

@ -25,11 +25,6 @@
#ifndef CEREAL_EXTERNAL_BASE64_HPP_ #ifndef CEREAL_EXTERNAL_BASE64_HPP_
#define CEREAL_EXTERNAL_BASE64_HPP_ #define CEREAL_EXTERNAL_BASE64_HPP_
#ifdef __GNUC__
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wconversion"
#endif
#include <string> #include <string>
namespace cereal namespace cereal
@ -55,10 +50,10 @@ namespace cereal
while (in_len--) { while (in_len--) {
char_array_3[i++] = *(bytes_to_encode++); char_array_3[i++] = *(bytes_to_encode++);
if (i == 3) { if (i == 3) {
char_array_4[0] = static_cast<unsigned char>((char_array_3[0] & 0xfc) >> 2); char_array_4[0] = (unsigned char) ((char_array_3[0] & 0xfc) >> 2);
char_array_4[1] = static_cast<unsigned char>( ( ( char_array_3[0] & 0x03 ) << 4 ) + ( ( char_array_3[1] & 0xf0 ) >> 4 ) ); char_array_4[1] = (unsigned char) ( ( ( char_array_3[0] & 0x03 ) << 4 ) + ( ( char_array_3[1] & 0xf0 ) >> 4 ) );
char_array_4[2] = static_cast<unsigned char>( ( ( char_array_3[1] & 0x0f ) << 2 ) + ( ( char_array_3[2] & 0xc0 ) >> 6 ) ); char_array_4[2] = (unsigned char) ( ( ( char_array_3[1] & 0x0f ) << 2 ) + ( ( char_array_3[2] & 0xc0 ) >> 6 ) );
char_array_4[3] = static_cast<unsigned char>( char_array_3[2] & 0x3f ); char_array_4[3] = (unsigned char) ( char_array_3[2] & 0x3f );
for(i = 0; (i <4) ; i++) for(i = 0; (i <4) ; i++)
ret += chars[char_array_4[i]]; ret += chars[char_array_4[i]];
@ -81,9 +76,11 @@ namespace cereal
while((i++ < 3)) while((i++ < 3))
ret += '='; ret += '=';
} }
return ret; return ret;
} }
inline std::string decode(std::string const& encoded_string) { inline std::string decode(std::string const& encoded_string) {
@ -98,7 +95,7 @@ namespace cereal
char_array_4[i++] = encoded_string[in_]; in_++; char_array_4[i++] = encoded_string[in_]; in_++;
if (i ==4) { if (i ==4) {
for (i = 0; i <4; i++) for (i = 0; i <4; i++)
char_array_4[i] = static_cast<unsigned char>(chars.find( char_array_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[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[1] = ((char_array_4[1] & 0xf) << 4) + ((char_array_4[2] & 0x3c) >> 2);
@ -115,7 +112,7 @@ namespace cereal
char_array_4[j] = 0; char_array_4[j] = 0;
for (j = 0; j <4; j++) for (j = 0; j <4; j++)
char_array_4[j] = static_cast<unsigned char>(chars.find( char_array_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[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[1] = ((char_array_4[1] & 0xf) << 4) + ((char_array_4[2] & 0x3c) >> 2);
@ -128,7 +125,5 @@ namespace cereal
} }
} // namespace base64 } // namespace base64
} // namespace cereal } // namespace cereal
#ifdef __GNUC__
#pragma GCC diagnostic pop
#endif
#endif // CEREAL_EXTERNAL_BASE64_HPP_ #endif // CEREAL_EXTERNAL_BASE64_HPP_

View File

@ -1,13 +0,0 @@
Tencent is pleased to support the open source community by making RapidJSON available.
Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
Licensed under the MIT License (the "License"); you may not use this file except
in compliance with the License. You may obtain a copy of the License at
http://opensource.org/licenses/MIT
Unless required by applicable law or agreed to in writing, software distributed
under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
CONDITIONS OF ANY KIND, either express or implied. See the License for the
specific language governing permissions and limitations under the License.

View File

@ -52,19 +52,6 @@ concept Allocator {
\endcode \endcode
*/ */
/*! \def CEREAL_RAPIDJSON_ALLOCATOR_DEFAULT_CHUNK_CAPACITY
\ingroup CEREAL_RAPIDJSON_CONFIG
\brief User-defined kDefaultChunkCapacity definition.
User can define this as any \c size that is a power of 2.
*/
#ifndef CEREAL_RAPIDJSON_ALLOCATOR_DEFAULT_CHUNK_CAPACITY
#define CEREAL_RAPIDJSON_ALLOCATOR_DEFAULT_CHUNK_CAPACITY (64 * 1024)
#endif
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
// CrtAllocator // CrtAllocator
@ -249,7 +236,7 @@ private:
*/ */
bool AddChunk(size_t capacity) { bool AddChunk(size_t capacity) {
if (!baseAllocator_) if (!baseAllocator_)
ownBaseAllocator_ = baseAllocator_ = CEREAL_RAPIDJSON_NEW(BaseAllocator)(); ownBaseAllocator_ = baseAllocator_ = CEREAL_RAPIDJSON_NEW(BaseAllocator());
if (ChunkHeader* chunk = reinterpret_cast<ChunkHeader*>(baseAllocator_->Malloc(CEREAL_RAPIDJSON_ALIGN(sizeof(ChunkHeader)) + capacity))) { if (ChunkHeader* chunk = reinterpret_cast<ChunkHeader*>(baseAllocator_->Malloc(CEREAL_RAPIDJSON_ALIGN(sizeof(ChunkHeader)) + capacity))) {
chunk->capacity = capacity; chunk->capacity = capacity;
chunk->size = 0; chunk->size = 0;
@ -261,7 +248,7 @@ private:
return false; return false;
} }
static const int kDefaultChunkCapacity = CEREAL_RAPIDJSON_ALLOCATOR_DEFAULT_CHUNK_CAPACITY; //!< Default chunk capacity. static const int kDefaultChunkCapacity = 64 * 1024; //!< Default chunk capacity.
//! Chunk header for perpending to each chunk. //! Chunk header for perpending to each chunk.
/*! Chunks are stored as a singly linked list. /*! Chunks are stored as a singly linked list.

View File

@ -1,78 +0,0 @@
// Tencent is pleased to support the open source community by making RapidJSON available.
//
// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
//
// Licensed under the MIT License (the "License"); you may not use this file except
// in compliance with the License. You may obtain a copy of the License at
//
// http://opensource.org/licenses/MIT
//
// Unless required by applicable law or agreed to in writing, software distributed
// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
// CONDITIONS OF ANY KIND, either express or implied. See the License for the
// specific language governing permissions and limitations under the License.
#ifndef CEREAL_RAPIDJSON_CURSORSTREAMWRAPPER_H_
#define CEREAL_RAPIDJSON_CURSORSTREAMWRAPPER_H_
#include "stream.h"
#if defined(__GNUC__)
CEREAL_RAPIDJSON_DIAG_PUSH
CEREAL_RAPIDJSON_DIAG_OFF(effc++)
#endif
#if defined(_MSC_VER) && _MSC_VER <= 1800
CEREAL_RAPIDJSON_DIAG_PUSH
CEREAL_RAPIDJSON_DIAG_OFF(4702) // unreachable code
CEREAL_RAPIDJSON_DIAG_OFF(4512) // assignment operator could not be generated
#endif
CEREAL_RAPIDJSON_NAMESPACE_BEGIN
//! Cursor stream wrapper for counting line and column number if error exists.
/*!
\tparam InputStream Any stream that implements Stream Concept
*/
template <typename InputStream, typename Encoding = UTF8<> >
class CursorStreamWrapper : public GenericStreamWrapper<InputStream, Encoding> {
public:
typedef typename Encoding::Ch Ch;
CursorStreamWrapper(InputStream& is):
GenericStreamWrapper<InputStream, Encoding>(is), line_(1), col_(0) {}
// counting line and column number
Ch Take() {
Ch ch = this->is_.Take();
if(ch == '\n') {
line_ ++;
col_ = 0;
} else {
col_ ++;
}
return ch;
}
//! Get the error line number, if error exists.
size_t GetLine() const { return line_; }
//! Get the error column number, if error exists.
size_t GetColumn() const { return col_; }
private:
size_t line_; //!< Current Line
size_t col_; //!< Current Column
};
#if defined(_MSC_VER) && _MSC_VER <= 1800
CEREAL_RAPIDJSON_DIAG_POP
#endif
#if defined(__GNUC__)
CEREAL_RAPIDJSON_DIAG_POP
#endif
CEREAL_RAPIDJSON_NAMESPACE_END
#endif // CEREAL_RAPIDJSON_CURSORSTREAMWRAPPER_H_

View File

@ -24,26 +24,28 @@
#include "encodedstream.h" #include "encodedstream.h"
#include <new> // placement new #include <new> // placement new
#include <limits> #include <limits>
#ifdef __cpp_lib_three_way_comparison
#include <compare>
#endif
CEREAL_RAPIDJSON_DIAG_PUSH CEREAL_RAPIDJSON_DIAG_PUSH
#ifdef __clang__ #ifdef _MSC_VER
CEREAL_RAPIDJSON_DIAG_OFF(padded)
CEREAL_RAPIDJSON_DIAG_OFF(switch-enum)
CEREAL_RAPIDJSON_DIAG_OFF(c++98-compat)
#elif defined(_MSC_VER)
CEREAL_RAPIDJSON_DIAG_OFF(4127) // conditional expression is constant CEREAL_RAPIDJSON_DIAG_OFF(4127) // conditional expression is constant
CEREAL_RAPIDJSON_DIAG_OFF(4244) // conversion from kXxxFlags to 'uint16_t', possible loss of data CEREAL_RAPIDJSON_DIAG_OFF(4244) // conversion from kXxxFlags to 'uint16_t', possible loss of data
#endif #endif
#ifdef __clang__
CEREAL_RAPIDJSON_DIAG_OFF(padded)
CEREAL_RAPIDJSON_DIAG_OFF(switch-enum)
CEREAL_RAPIDJSON_DIAG_OFF(c++98-compat)
#endif
#ifdef __GNUC__ #ifdef __GNUC__
CEREAL_RAPIDJSON_DIAG_OFF(effc++) CEREAL_RAPIDJSON_DIAG_OFF(effc++)
#if __GNUC__ >= 6
CEREAL_RAPIDJSON_DIAG_OFF(terminate) // ignore throwing CEREAL_RAPIDJSON_ASSERT in CEREAL_RAPIDJSON_NOEXCEPT functions
#endif
#endif // __GNUC__ #endif // __GNUC__
#ifndef CEREAL_RAPIDJSON_NOMEMBERITERATORCLASS #ifndef CEREAL_RAPIDJSON_NOMEMBERITERATORCLASS
#include <iterator> // std::random_access_iterator_tag #include <iterator> // std::iterator, std::random_access_iterator_tag
#endif #endif
#if CEREAL_RAPIDJSON_HAS_CXX11_RVALUE_REFS #if CEREAL_RAPIDJSON_HAS_CXX11_RVALUE_REFS
@ -69,12 +71,6 @@ template <typename Encoding, typename Allocator>
struct GenericMember { struct GenericMember {
GenericValue<Encoding, Allocator> name; //!< name of member (must be a string) GenericValue<Encoding, Allocator> name; //!< name of member (must be a string)
GenericValue<Encoding, Allocator> value; //!< value of member. GenericValue<Encoding, Allocator> value; //!< value of member.
// swap() for std::sort() and other potential use in STL.
friend inline void swap(GenericMember& a, GenericMember& b) CEREAL_RAPIDJSON_NOEXCEPT {
a.name.Swap(b.name);
a.value.Swap(b.value);
}
}; };
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
@ -102,13 +98,16 @@ struct GenericMember {
\see GenericMember, GenericValue::MemberIterator, GenericValue::ConstMemberIterator \see GenericMember, GenericValue::MemberIterator, GenericValue::ConstMemberIterator
*/ */
template <bool Const, typename Encoding, typename Allocator> template <bool Const, typename Encoding, typename Allocator>
class GenericMemberIterator { class GenericMemberIterator
: public std::iterator<std::random_access_iterator_tag
, typename internal::MaybeAddConst<Const,GenericMember<Encoding,Allocator> >::Type> {
friend class GenericValue<Encoding,Allocator>; friend class GenericValue<Encoding,Allocator>;
template <bool, typename, typename> friend class GenericMemberIterator; template <bool, typename, typename> friend class GenericMemberIterator;
typedef GenericMember<Encoding,Allocator> PlainType; typedef GenericMember<Encoding,Allocator> PlainType;
typedef typename internal::MaybeAddConst<Const,PlainType>::Type ValueType; typedef typename internal::MaybeAddConst<Const,PlainType>::Type ValueType;
typedef std::iterator<std::random_access_iterator_tag,ValueType> BaseType;
public: public:
//! Iterator type itself //! Iterator type itself
@ -118,21 +117,12 @@ public:
//! Non-constant iterator type //! Non-constant iterator type
typedef GenericMemberIterator<false,Encoding,Allocator> NonConstIterator; typedef GenericMemberIterator<false,Encoding,Allocator> NonConstIterator;
/** \name std::iterator_traits support */
//@{
typedef ValueType value_type;
typedef ValueType * pointer;
typedef ValueType & reference;
typedef std::ptrdiff_t difference_type;
typedef std::random_access_iterator_tag iterator_category;
//@}
//! Pointer to (const) GenericMember //! Pointer to (const) GenericMember
typedef pointer Pointer; typedef typename BaseType::pointer Pointer;
//! Reference to (const) GenericMember //! Reference to (const) GenericMember
typedef reference Reference; typedef typename BaseType::reference Reference;
//! Signed integer type (e.g. \c ptrdiff_t) //! Signed integer type (e.g. \c ptrdiff_t)
typedef difference_type DifferenceType; typedef typename BaseType::difference_type DifferenceType;
//! Default constructor (singular value) //! Default constructor (singular value)
/*! Creates an iterator pointing to no element. /*! Creates an iterator pointing to no element.
@ -178,16 +168,12 @@ public:
//! @name relations //! @name relations
//@{ //@{
template <bool Const_> bool operator==(const GenericMemberIterator<Const_, Encoding, Allocator>& that) const { return ptr_ == that.ptr_; } bool operator==(ConstIterator that) const { return ptr_ == that.ptr_; }
template <bool Const_> bool operator!=(const GenericMemberIterator<Const_, Encoding, Allocator>& that) const { return ptr_ != that.ptr_; } bool operator!=(ConstIterator that) const { return ptr_ != that.ptr_; }
template <bool Const_> bool operator<=(const GenericMemberIterator<Const_, Encoding, Allocator>& that) const { return ptr_ <= that.ptr_; } bool operator<=(ConstIterator that) const { return ptr_ <= that.ptr_; }
template <bool Const_> bool operator>=(const GenericMemberIterator<Const_, Encoding, Allocator>& that) const { return ptr_ >= that.ptr_; } bool operator>=(ConstIterator that) const { return ptr_ >= that.ptr_; }
template <bool Const_> bool operator< (const GenericMemberIterator<Const_, Encoding, Allocator>& that) const { return ptr_ < that.ptr_; } bool operator< (ConstIterator that) const { return ptr_ < that.ptr_; }
template <bool Const_> bool operator> (const GenericMemberIterator<Const_, Encoding, Allocator>& that) const { return ptr_ > that.ptr_; } bool operator> (ConstIterator that) const { return ptr_ > that.ptr_; }
#ifdef __cpp_lib_three_way_comparison
template <bool Const_> std::strong_ordering operator<=>(const GenericMemberIterator<Const_, Encoding, Allocator>& that) const { return ptr_ <=> that.ptr_; }
#endif
//@} //@}
//! @name dereference //! @name dereference
@ -212,17 +198,17 @@ private:
// class-based member iterator implementation disabled, use plain pointers // class-based member iterator implementation disabled, use plain pointers
template <bool Const, typename Encoding, typename Allocator> template <bool Const, typename Encoding, typename Allocator>
class GenericMemberIterator; struct GenericMemberIterator;
//! non-const GenericMemberIterator //! non-const GenericMemberIterator
template <typename Encoding, typename Allocator> template <typename Encoding, typename Allocator>
class GenericMemberIterator<false,Encoding,Allocator> { struct GenericMemberIterator<false,Encoding,Allocator> {
//! use plain pointer as iterator type //! use plain pointer as iterator type
typedef GenericMember<Encoding,Allocator>* Iterator; typedef GenericMember<Encoding,Allocator>* Iterator;
}; };
//! const GenericMemberIterator //! const GenericMemberIterator
template <typename Encoding, typename Allocator> template <typename Encoding, typename Allocator>
class GenericMemberIterator<true,Encoding,Allocator> { struct GenericMemberIterator<true,Encoding,Allocator> {
//! use plain const pointer as iterator type //! use plain const pointer as iterator type
typedef const GenericMember<Encoding,Allocator>* Iterator; typedef const GenericMember<Encoding,Allocator>* Iterator;
}; };
@ -314,7 +300,7 @@ struct GenericStringRef {
*/ */
#endif #endif
explicit GenericStringRef(const CharType* str) explicit GenericStringRef(const CharType* str)
: s(str), length(NotNullStrLen(str)) {} : s(str), length(internal::StrLen(str)){ CEREAL_RAPIDJSON_ASSERT(s != 0); }
//! Create constant string reference from pointer and length //! Create constant string reference from pointer and length
#ifndef __clang__ // -Wdocumentation #ifndef __clang__ // -Wdocumentation
@ -326,10 +312,12 @@ struct GenericStringRef {
*/ */
#endif #endif
GenericStringRef(const CharType* str, SizeType len) GenericStringRef(const CharType* str, SizeType len)
: s(CEREAL_RAPIDJSON_LIKELY(str) ? str : emptyString), length(len) { CEREAL_RAPIDJSON_ASSERT(str != 0 || len == 0u); } : s(str), length(len) { CEREAL_RAPIDJSON_ASSERT(s != 0); }
GenericStringRef(const GenericStringRef& rhs) : s(rhs.s), length(rhs.length) {} GenericStringRef(const GenericStringRef& rhs) : s(rhs.s), length(rhs.length) {}
GenericStringRef& operator=(const GenericStringRef& rhs) { s = rhs.s; length = rhs.length; }
//! implicit conversion to plain CharType pointer //! implicit conversion to plain CharType pointer
operator const Ch *() const { return s; } operator const Ch *() const { return s; }
@ -337,24 +325,11 @@ struct GenericStringRef {
const SizeType length; //!< length of the string (excluding the trailing NULL terminator) const SizeType length; //!< length of the string (excluding the trailing NULL terminator)
private: private:
SizeType NotNullStrLen(const CharType* str) {
CEREAL_RAPIDJSON_ASSERT(str != 0);
return internal::StrLen(str);
}
/// Empty string - used when passing in a NULL pointer
static const Ch emptyString[];
//! Disallow construction from non-const array //! Disallow construction from non-const array
template<SizeType N> template<SizeType N>
GenericStringRef(CharType (&str)[N]) /* = delete */; GenericStringRef(CharType (&str)[N]) /* = delete */;
//! Copy assignment operator not permitted - immutable type
GenericStringRef& operator=(const GenericStringRef& rhs) /* = delete */;
}; };
template<typename CharType>
const CharType GenericStringRef<CharType>::emptyString[] = { CharType() };
//! Mark a character pointer as constant string //! Mark a character pointer as constant string
/*! Mark a plain character pointer as a "string literal". This function /*! Mark a plain character pointer as a "string literal". This function
can be used to avoid copying a character string to be referenced as a can be used to avoid copying a character string to be referenced as a
@ -369,7 +344,7 @@ const CharType GenericStringRef<CharType>::emptyString[] = { CharType() };
*/ */
template<typename CharType> template<typename CharType>
inline GenericStringRef<CharType> StringRef(const CharType* str) { inline GenericStringRef<CharType> StringRef(const CharType* str) {
return GenericStringRef<CharType>(str); return GenericStringRef<CharType>(str, internal::StrLen(str));
} }
//! Mark a character pointer as constant string //! Mark a character pointer as constant string
@ -459,26 +434,6 @@ struct TypeHelper<ValueType, unsigned> {
static ValueType& Set(ValueType& v, unsigned data, typename ValueType::AllocatorType&) { return v.SetUint(data); } static ValueType& Set(ValueType& v, unsigned data, typename ValueType::AllocatorType&) { return v.SetUint(data); }
}; };
#ifdef _MSC_VER
CEREAL_RAPIDJSON_STATIC_ASSERT(sizeof(long) == sizeof(int));
template<typename ValueType>
struct TypeHelper<ValueType, long> {
static bool Is(const ValueType& v) { return v.IsInt(); }
static long Get(const ValueType& v) { return v.GetInt(); }
static ValueType& Set(ValueType& v, long data) { return v.SetInt(data); }
static ValueType& Set(ValueType& v, long data, typename ValueType::AllocatorType&) { return v.SetInt(data); }
};
CEREAL_RAPIDJSON_STATIC_ASSERT(sizeof(unsigned long) == sizeof(unsigned));
template<typename ValueType>
struct TypeHelper<ValueType, unsigned long> {
static bool Is(const ValueType& v) { return v.IsUint(); }
static unsigned long Get(const ValueType& v) { return v.GetUint(); }
static ValueType& Set(ValueType& v, unsigned long data) { return v.SetUint(data); }
static ValueType& Set(ValueType& v, unsigned long data, typename ValueType::AllocatorType&) { return v.SetUint(data); }
};
#endif
template<typename ValueType> template<typename ValueType>
struct TypeHelper<ValueType, int64_t> { struct TypeHelper<ValueType, int64_t> {
static bool Is(const ValueType& v) { return v.IsInt64(); } static bool Is(const ValueType& v) { return v.IsInt64(); }
@ -552,7 +507,7 @@ struct TypeHelper<ValueType, typename ValueType::Object> {
static bool Is(const ValueType& v) { return v.IsObject(); } static bool Is(const ValueType& v) { return v.IsObject(); }
static ObjectType Get(ValueType& v) { return v.GetObject(); } static ObjectType Get(ValueType& v) { return v.GetObject(); }
static ValueType& Set(ValueType& v, ObjectType data) { return v = data; } static ValueType& Set(ValueType& v, ObjectType data) { return v = data; }
static ValueType& Set(ValueType& v, ObjectType data, typename ValueType::AllocatorType&) { return v = data; } static ValueType& Set(ValueType& v, ObjectType data, typename ValueType::AllocatorType&) { v = data; }
}; };
template<typename ValueType> template<typename ValueType>
@ -635,11 +590,11 @@ public:
\note Default content for number is zero. \note Default content for number is zero.
*/ */
explicit GenericValue(Type type) CEREAL_RAPIDJSON_NOEXCEPT : data_() { explicit GenericValue(Type type) CEREAL_RAPIDJSON_NOEXCEPT : data_() {
static const uint16_t defaultFlags[] = { static const uint16_t defaultFlags[7] = {
kNullFlag, kFalseFlag, kTrueFlag, kObjectFlag, kArrayFlag, kShortStringFlag, kNullFlag, kFalseFlag, kTrueFlag, kObjectFlag, kArrayFlag, kShortStringFlag,
kNumberAnyFlag kNumberAnyFlag
}; };
CEREAL_RAPIDJSON_NOEXCEPT_ASSERT(type >= kNullType && type <= kNumberType); CEREAL_RAPIDJSON_ASSERT(type <= kNumberType);
data_.f.flags = defaultFlags[type]; data_.f.flags = defaultFlags[type];
// Use ShortString to store empty string. // Use ShortString to store empty string.
@ -652,50 +607,10 @@ public:
\tparam SourceAllocator allocator of \c rhs \tparam SourceAllocator allocator of \c rhs
\param rhs Value to copy from (read-only) \param rhs Value to copy from (read-only)
\param allocator Allocator for allocating copied elements and buffers. Commonly use GenericDocument::GetAllocator(). \param allocator Allocator for allocating copied elements and buffers. Commonly use GenericDocument::GetAllocator().
\param copyConstStrings Force copying of constant strings (e.g. referencing an in-situ buffer)
\see CopyFrom() \see CopyFrom()
*/ */
template< typename SourceAllocator > template< typename SourceAllocator >
GenericValue(const GenericValue<Encoding,SourceAllocator>& rhs, Allocator& allocator, bool copyConstStrings = false) { GenericValue(const GenericValue<Encoding, SourceAllocator>& rhs, Allocator & allocator);
switch (rhs.GetType()) {
case kObjectType: {
SizeType count = rhs.data_.o.size;
Member* lm = reinterpret_cast<Member*>(allocator.Malloc(count * sizeof(Member)));
const typename GenericValue<Encoding,SourceAllocator>::Member* rm = rhs.GetMembersPointer();
for (SizeType i = 0; i < count; i++) {
new (&lm[i].name) GenericValue(rm[i].name, allocator, copyConstStrings);
new (&lm[i].value) GenericValue(rm[i].value, allocator, copyConstStrings);
}
data_.f.flags = kObjectFlag;
data_.o.size = data_.o.capacity = count;
SetMembersPointer(lm);
}
break;
case kArrayType: {
SizeType count = rhs.data_.a.size;
GenericValue* le = reinterpret_cast<GenericValue*>(allocator.Malloc(count * sizeof(GenericValue)));
const GenericValue<Encoding,SourceAllocator>* re = rhs.GetElementsPointer();
for (SizeType i = 0; i < count; i++)
new (&le[i]) GenericValue(re[i], allocator, copyConstStrings);
data_.f.flags = kArrayFlag;
data_.a.size = data_.a.capacity = count;
SetElementsPointer(le);
}
break;
case kStringType:
if (rhs.data_.f.flags == kConstStringFlag && !copyConstStrings) {
data_.f.flags = rhs.data_.f.flags;
data_ = *reinterpret_cast<const Data*>(&rhs.data_);
}
else
SetStringRaw(StringRef(rhs.GetString(), rhs.GetStringLength()), allocator);
break;
default:
data_.f.flags = rhs.data_.f.flags;
data_ = *reinterpret_cast<const Data*>(&rhs.data_);
break;
}
}
//! Constructor for boolean value. //! Constructor for boolean value.
/*! \param b Boolean value /*! \param b Boolean value
@ -757,9 +672,6 @@ public:
//! Constructor for double value. //! Constructor for double value.
explicit GenericValue(double d) CEREAL_RAPIDJSON_NOEXCEPT : data_() { data_.n.d = d; data_.f.flags = kNumberDoubleFlag; } explicit GenericValue(double d) CEREAL_RAPIDJSON_NOEXCEPT : data_() { data_.n.d = d; data_.f.flags = kNumberDoubleFlag; }
//! Constructor for float value.
explicit GenericValue(float f) CEREAL_RAPIDJSON_NOEXCEPT : data_() { data_.n.d = static_cast<double>(f); data_.f.flags = kNumberDoubleFlag; }
//! Constructor for constant string (i.e. do not make a copy of string) //! Constructor for constant string (i.e. do not make a copy of string)
GenericValue(const Ch* s, SizeType length) CEREAL_RAPIDJSON_NOEXCEPT : data_() { SetStringRaw(StringRef(s, length)); } GenericValue(const Ch* s, SizeType length) CEREAL_RAPIDJSON_NOEXCEPT : data_() { SetStringRaw(StringRef(s, length)); }
@ -841,10 +753,9 @@ public:
/*! \param rhs Source of the assignment. It will become a null value after assignment. /*! \param rhs Source of the assignment. It will become a null value after assignment.
*/ */
GenericValue& operator=(GenericValue& rhs) CEREAL_RAPIDJSON_NOEXCEPT { GenericValue& operator=(GenericValue& rhs) CEREAL_RAPIDJSON_NOEXCEPT {
if (CEREAL_RAPIDJSON_LIKELY(this != &rhs)) { CEREAL_RAPIDJSON_ASSERT(this != &rhs);
this->~GenericValue(); this->~GenericValue();
RawAssign(rhs); RawAssign(rhs);
}
return *this; return *this;
} }
@ -889,13 +800,12 @@ public:
\tparam SourceAllocator Allocator type of \c rhs \tparam SourceAllocator Allocator type of \c rhs
\param rhs Value to copy from (read-only) \param rhs Value to copy from (read-only)
\param allocator Allocator to use for copying \param allocator Allocator to use for copying
\param copyConstStrings Force copying of constant strings (e.g. referencing an in-situ buffer)
*/ */
template <typename SourceAllocator> template <typename SourceAllocator>
GenericValue& CopyFrom(const GenericValue<Encoding, SourceAllocator>& rhs, Allocator& allocator, bool copyConstStrings = false) { GenericValue& CopyFrom(const GenericValue<Encoding, SourceAllocator>& rhs, Allocator& allocator) {
CEREAL_RAPIDJSON_ASSERT(static_cast<void*>(this) != static_cast<void const*>(&rhs)); CEREAL_RAPIDJSON_ASSERT(static_cast<void*>(this) != static_cast<void const*>(&rhs));
this->~GenericValue(); this->~GenericValue();
new (this) GenericValue(rhs, allocator, copyConstStrings); new (this) GenericValue(rhs, allocator);
return *this; return *this;
} }
@ -936,7 +846,7 @@ public:
//! Equal-to operator //! Equal-to operator
/*! /*!
\note If an object contains duplicated named member, comparing equality with any object is always \c false. \note If an object contains duplicated named member, comparing equality with any object is always \c false.
\note Complexity is quadratic in Object's member number and linear for the rest (number of all values in the subtree and total lengths of all strings). \note Linear time complexity (number of all values in the subtree and total lengths of all strings).
*/ */
template <typename SourceAllocator> template <typename SourceAllocator>
bool operator==(const GenericValue<Encoding, SourceAllocator>& rhs) const { bool operator==(const GenericValue<Encoding, SourceAllocator>& rhs) const {
@ -1045,14 +955,14 @@ public:
uint64_t u = GetUint64(); uint64_t u = GetUint64();
volatile double d = static_cast<double>(u); volatile double d = static_cast<double>(u);
return (d >= 0.0) return (d >= 0.0)
&& (d < static_cast<double>((std::numeric_limits<uint64_t>::max)())) && (d < static_cast<double>(std::numeric_limits<uint64_t>::max()))
&& (u == static_cast<uint64_t>(d)); && (u == static_cast<uint64_t>(d));
} }
if (IsInt64()) { if (IsInt64()) {
int64_t i = GetInt64(); int64_t i = GetInt64();
volatile double d = static_cast<double>(i); volatile double d = static_cast<double>(i);
return (d >= static_cast<double>((std::numeric_limits<int64_t>::min)())) return (d >= static_cast<double>(std::numeric_limits<int64_t>::min()))
&& (d < static_cast<double>((std::numeric_limits<int64_t>::max)())) && (d < static_cast<double>(std::numeric_limits<int64_t>::max()))
&& (i == static_cast<int64_t>(d)); && (i == static_cast<int64_t>(d));
} }
return true; // double, int, uint are always lossless return true; // double, int, uint are always lossless
@ -1069,8 +979,8 @@ public:
bool IsLosslessFloat() const { bool IsLosslessFloat() const {
if (!IsNumber()) return false; if (!IsNumber()) return false;
double a = GetDouble(); double a = GetDouble();
if (a < static_cast<double>(-(std::numeric_limits<float>::max)()) if (a < static_cast<double>(-std::numeric_limits<float>::max())
|| a > static_cast<double>((std::numeric_limits<float>::max)())) || a > static_cast<double>(std::numeric_limits<float>::max()))
return false; return false;
double b = static_cast<double>(static_cast<float>(a)); double b = static_cast<double>(static_cast<float>(a));
return a >= b && a <= b; // Prevent -Wfloat-equal return a >= b && a <= b; // Prevent -Wfloat-equal
@ -1105,9 +1015,6 @@ public:
//! Get the number of members in the object. //! Get the number of members in the object.
SizeType MemberCount() const { CEREAL_RAPIDJSON_ASSERT(IsObject()); return data_.o.size; } SizeType MemberCount() const { CEREAL_RAPIDJSON_ASSERT(IsObject()); return data_.o.size; }
//! Get the capacity of object.
SizeType MemberCapacity() const { CEREAL_RAPIDJSON_ASSERT(IsObject()); return data_.o.capacity; }
//! Check whether the object is empty. //! Check whether the object is empty.
bool ObjectEmpty() const { CEREAL_RAPIDJSON_ASSERT(IsObject()); return data_.o.size == 0; } bool ObjectEmpty() const { CEREAL_RAPIDJSON_ASSERT(IsObject()); return data_.o.size == 0; }
@ -1176,21 +1083,6 @@ public:
/*! \pre IsObject() == true */ /*! \pre IsObject() == true */
MemberIterator MemberEnd() { CEREAL_RAPIDJSON_ASSERT(IsObject()); return MemberIterator(GetMembersPointer() + data_.o.size); } MemberIterator MemberEnd() { CEREAL_RAPIDJSON_ASSERT(IsObject()); return MemberIterator(GetMembersPointer() + data_.o.size); }
//! Request the object to have enough capacity to store members.
/*! \param newCapacity The capacity that the object at least need to have.
\param allocator Allocator for reallocating memory. It must be the same one as used before. Commonly use GenericDocument::GetAllocator().
\return The value itself for fluent API.
\note Linear time complexity.
*/
GenericValue& MemberReserve(SizeType newCapacity, Allocator &allocator) {
CEREAL_RAPIDJSON_ASSERT(IsObject());
if (newCapacity > data_.o.capacity) {
SetMembersPointer(reinterpret_cast<Member*>(allocator.Realloc(GetMembersPointer(), data_.o.capacity * sizeof(Member), newCapacity * sizeof(Member))));
data_.o.capacity = newCapacity;
}
return *this;
}
//! Check whether a member exists in the object. //! Check whether a member exists in the object.
/*! /*!
\param name Member name to be searched. \param name Member name to be searched.
@ -1296,8 +1188,17 @@ public:
CEREAL_RAPIDJSON_ASSERT(name.IsString()); CEREAL_RAPIDJSON_ASSERT(name.IsString());
ObjectData& o = data_.o; ObjectData& o = data_.o;
if (o.size >= o.capacity) if (o.size >= o.capacity) {
MemberReserve(o.capacity == 0 ? kDefaultObjectCapacity : (o.capacity + (o.capacity + 1) / 2), allocator); if (o.capacity == 0) {
o.capacity = kDefaultObjectCapacity;
SetMembersPointer(reinterpret_cast<Member*>(allocator.Malloc(o.capacity * sizeof(Member))));
}
else {
SizeType oldCapacity = o.capacity;
o.capacity += (oldCapacity + 1) / 2; // grow by factor 1.5
SetMembersPointer(reinterpret_cast<Member*>(allocator.Realloc(GetMembersPointer(), oldCapacity * sizeof(Member), o.capacity * sizeof(Member))));
}
}
Member* members = GetMembersPointer(); Member* members = GetMembersPointer();
members[o.size].name.RawAssign(name); members[o.size].name.RawAssign(name);
members[o.size].value.RawAssign(value); members[o.size].value.RawAssign(value);
@ -1524,7 +1425,7 @@ public:
MemberIterator pos = MemberBegin() + (first - MemberBegin()); MemberIterator pos = MemberBegin() + (first - MemberBegin());
for (MemberIterator itr = pos; itr != last; ++itr) for (MemberIterator itr = pos; itr != last; ++itr)
itr->~Member(); itr->~Member();
std::memmove(static_cast<void*>(&*pos), &*last, static_cast<size_t>(MemberEnd() - last) * sizeof(Member)); std::memmove(&*pos, &*last, static_cast<size_t>(MemberEnd() - last) * sizeof(Member));
data_.o.size -= static_cast<SizeType>(last - first); data_.o.size -= static_cast<SizeType>(last - first);
return pos; return pos;
} }
@ -1728,7 +1629,7 @@ public:
ValueIterator pos = Begin() + (first - Begin()); ValueIterator pos = Begin() + (first - Begin());
for (ValueIterator itr = pos; itr != last; ++itr) for (ValueIterator itr = pos; itr != last; ++itr)
itr->~GenericValue(); itr->~GenericValue();
std::memmove(static_cast<void*>(pos), last, static_cast<size_t>(End() - last) * sizeof(GenericValue)); std::memmove(pos, last, static_cast<size_t>(End() - last) * sizeof(GenericValue));
data_.a.size -= static_cast<SizeType>(last - first); data_.a.size -= static_cast<SizeType>(last - first);
return pos; return pos;
} }
@ -1770,7 +1671,7 @@ public:
GenericValue& SetInt64(int64_t i64) { this->~GenericValue(); new (this) GenericValue(i64); 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& SetUint64(uint64_t u64) { this->~GenericValue(); new (this) GenericValue(u64); return *this; }
GenericValue& SetDouble(double d) { this->~GenericValue(); new (this) GenericValue(d); return *this; } GenericValue& SetDouble(double d) { this->~GenericValue(); new (this) GenericValue(d); return *this; }
GenericValue& SetFloat(float f) { this->~GenericValue(); new (this) GenericValue(static_cast<double>(f)); return *this; } GenericValue& SetFloat(float f) { this->~GenericValue(); new (this) GenericValue(f); return *this; }
//@} //@}
@ -1809,7 +1710,7 @@ public:
\return The value itself for fluent API. \return The value itself for fluent API.
\post IsString() == true && GetString() != s && strcmp(GetString(),s) == 0 && GetStringLength() == length \post IsString() == true && GetString() != s && strcmp(GetString(),s) == 0 && GetStringLength() == length
*/ */
GenericValue& SetString(const Ch* s, SizeType length, Allocator& allocator) { return SetString(StringRef(s, length), allocator); } GenericValue& SetString(const Ch* s, SizeType length, Allocator& allocator) { this->~GenericValue(); SetStringRaw(StringRef(s, length), allocator); return *this; }
//! Set this value as a string by copying from source string. //! Set this value as a string by copying from source string.
/*! \param s source string. /*! \param s source string.
@ -1817,15 +1718,7 @@ public:
\return The value itself for fluent API. \return The value itself for fluent API.
\post IsString() == true && GetString() != s && strcmp(GetString(),s) == 0 && GetStringLength() == length \post IsString() == true && GetString() != s && strcmp(GetString(),s) == 0 && GetStringLength() == length
*/ */
GenericValue& SetString(const Ch* s, Allocator& allocator) { return SetString(StringRef(s), allocator); } GenericValue& SetString(const Ch* s, Allocator& allocator) { return SetString(s, internal::StrLen(s), allocator); }
//! Set this value as a string by copying from source string.
/*! \param s source string reference
\param allocator Allocator for allocating copied buffer. Commonly use GenericDocument::GetAllocator().
\return The value itself for fluent API.
\post IsString() == true && GetString() != s.s && strcmp(GetString(),s) == 0 && GetStringLength() == length
*/
GenericValue& SetString(StringRefType s, Allocator& allocator) { this->~GenericValue(); SetStringRaw(s, allocator); return *this; }
#if CEREAL_RAPIDJSON_HAS_STDSTRING #if CEREAL_RAPIDJSON_HAS_STDSTRING
//! Set this value as a string by copying from source string. //! Set this value as a string by copying from source string.
@ -1835,7 +1728,7 @@ public:
\post IsString() == true && GetString() != s.data() && strcmp(GetString(),s.data() == 0 && GetStringLength() == s.size() \post IsString() == true && GetString() != s.data() && strcmp(GetString(),s.data() == 0 && GetStringLength() == s.size()
\note Requires the definition of the preprocessor symbol \ref CEREAL_RAPIDJSON_HAS_STDSTRING. \note Requires the definition of the preprocessor symbol \ref CEREAL_RAPIDJSON_HAS_STDSTRING.
*/ */
GenericValue& SetString(const std::basic_string<Ch>& s, Allocator& allocator) { return SetString(StringRef(s), allocator); } GenericValue& SetString(const std::basic_string<Ch>& s, Allocator& allocator) { return SetString(s.data(), SizeType(s.size()), allocator); }
#endif #endif
//@} //@}
@ -2043,7 +1936,7 @@ private:
if (count) { if (count) {
GenericValue* e = static_cast<GenericValue*>(allocator.Malloc(count * sizeof(GenericValue))); GenericValue* e = static_cast<GenericValue*>(allocator.Malloc(count * sizeof(GenericValue)));
SetElementsPointer(e); SetElementsPointer(e);
std::memcpy(static_cast<void*>(e), values, count * sizeof(GenericValue)); std::memcpy(e, values, count * sizeof(GenericValue));
} }
else else
SetElementsPointer(0); SetElementsPointer(0);
@ -2056,7 +1949,7 @@ private:
if (count) { if (count) {
Member* m = static_cast<Member*>(allocator.Malloc(count * sizeof(Member))); Member* m = static_cast<Member*>(allocator.Malloc(count * sizeof(Member)));
SetMembersPointer(m); SetMembersPointer(m);
std::memcpy(static_cast<void*>(m), members, count * sizeof(Member)); std::memcpy(m, members, count * sizeof(Member));
} }
else else
SetMembersPointer(0); SetMembersPointer(0);
@ -2145,7 +2038,7 @@ public:
GenericValue<Encoding, Allocator>(type), allocator_(allocator), ownAllocator_(0), stack_(stackAllocator, stackCapacity), parseResult_() GenericValue<Encoding, Allocator>(type), allocator_(allocator), ownAllocator_(0), stack_(stackAllocator, stackCapacity), parseResult_()
{ {
if (!allocator_) if (!allocator_)
ownAllocator_ = allocator_ = CEREAL_RAPIDJSON_NEW(Allocator)(); ownAllocator_ = allocator_ = CEREAL_RAPIDJSON_NEW(Allocator());
} }
//! Constructor //! Constructor
@ -2158,7 +2051,7 @@ public:
allocator_(allocator), ownAllocator_(0), stack_(stackAllocator, stackCapacity), parseResult_() allocator_(allocator), ownAllocator_(0), stack_(stackAllocator, stackCapacity), parseResult_()
{ {
if (!allocator_) if (!allocator_)
ownAllocator_ = allocator_ = CEREAL_RAPIDJSON_NEW(Allocator)(); ownAllocator_ = allocator_ = CEREAL_RAPIDJSON_NEW(Allocator());
} }
#if CEREAL_RAPIDJSON_HAS_CXX11_RVALUE_REFS #if CEREAL_RAPIDJSON_HAS_CXX11_RVALUE_REFS
@ -2219,10 +2112,6 @@ public:
return *this; return *this;
} }
// Allow Swap with ValueType.
// Refer to Effective C++ 3rd Edition/Item 33: Avoid hiding inherited names.
using ValueType::Swap;
//! free-standing swap function helper //! free-standing swap function helper
/*! /*!
Helper function to enable support for common swap implementation pattern based on \c std::swap: Helper function to enable support for common swap implementation pattern based on \c std::swap:
@ -2354,7 +2243,7 @@ public:
template <unsigned parseFlags, typename SourceEncoding> template <unsigned parseFlags, typename SourceEncoding>
GenericDocument& Parse(const typename SourceEncoding::Ch* str, size_t length) { GenericDocument& Parse(const typename SourceEncoding::Ch* str, size_t length) {
CEREAL_RAPIDJSON_ASSERT(!(parseFlags & kParseInsituFlag)); CEREAL_RAPIDJSON_ASSERT(!(parseFlags & kParseInsituFlag));
MemoryStream ms(reinterpret_cast<const char*>(str), length * sizeof(typename SourceEncoding::Ch)); MemoryStream ms(static_cast<const char*>(str), length * sizeof(typename SourceEncoding::Ch));
EncodedInputStream<SourceEncoding, MemoryStream> is(ms); EncodedInputStream<SourceEncoding, MemoryStream> is(ms);
ParseStream<parseFlags, SourceEncoding>(is); ParseStream<parseFlags, SourceEncoding>(is);
return *this; return *this;
@ -2391,7 +2280,7 @@ public:
//!@name Handling parse errors //!@name Handling parse errors
//!@{ //!@{
//! Whether a parse error has occurred in the last parsing. //! Whether a parse error has occured in the last parsing.
bool HasParseError() const { return parseResult_.IsError(); } bool HasParseError() const { return parseResult_.IsError(); }
//! Get the \ref ParseErrorCode of last parsing. //! Get the \ref ParseErrorCode of last parsing.
@ -2512,6 +2401,35 @@ private:
//! GenericDocument with UTF8 encoding //! GenericDocument with UTF8 encoding
typedef GenericDocument<UTF8<> > Document; typedef GenericDocument<UTF8<> > Document;
// defined here due to the dependency on GenericDocument
template <typename Encoding, typename Allocator>
template <typename SourceAllocator>
inline
GenericValue<Encoding,Allocator>::GenericValue(const GenericValue<Encoding,SourceAllocator>& rhs, Allocator& allocator)
{
switch (rhs.GetType()) {
case kObjectType:
case kArrayType: { // perform deep copy via SAX Handler
GenericDocument<Encoding,Allocator> d(&allocator);
rhs.Accept(d);
RawAssign(*d.stack_.template Pop<GenericValue>(1));
}
break;
case kStringType:
if (rhs.data_.f.flags == kConstStringFlag) {
data_.f.flags = rhs.data_.f.flags;
data_ = *reinterpret_cast<const Data*>(&rhs.data_);
} else {
SetStringRaw(StringRef(rhs.GetString(), rhs.GetStringLength()), allocator);
}
break;
default:
data_.f.flags = rhs.data_.f.flags;
data_ = *reinterpret_cast<const Data*>(&rhs.data_);
break;
}
}
//! Helper class for accessing Value of array type. //! Helper class for accessing Value of array type.
/*! /*!
Instance of this helper class is obtained by \c GenericValue::GetArray(). Instance of this helper class is obtained by \c GenericValue::GetArray().
@ -2592,7 +2510,6 @@ public:
~GenericObject() {} ~GenericObject() {}
SizeType MemberCount() const { return value_.MemberCount(); } SizeType MemberCount() const { return value_.MemberCount(); }
SizeType MemberCapacity() const { return value_.MemberCapacity(); }
bool ObjectEmpty() const { return value_.ObjectEmpty(); } bool ObjectEmpty() const { return value_.ObjectEmpty(); }
template <typename T> ValueType& operator[](T* name) const { return value_[name]; } template <typename T> ValueType& operator[](T* name) const { return value_[name]; }
template <typename SourceAllocator> ValueType& operator[](const GenericValue<EncodingType, SourceAllocator>& name) const { return value_[name]; } template <typename SourceAllocator> ValueType& operator[](const GenericValue<EncodingType, SourceAllocator>& name) const { return value_[name]; }
@ -2601,7 +2518,6 @@ public:
#endif #endif
MemberIterator MemberBegin() const { return value_.MemberBegin(); } MemberIterator MemberBegin() const { return value_.MemberBegin(); }
MemberIterator MemberEnd() const { return value_.MemberEnd(); } MemberIterator MemberEnd() const { return value_.MemberEnd(); }
GenericObject MemberReserve(SizeType newCapacity, AllocatorType &allocator) const { value_.MemberReserve(newCapacity, allocator); return *this; }
bool HasMember(const Ch* name) const { return value_.HasMember(name); } bool HasMember(const Ch* name) const { return value_.HasMember(name); }
#if CEREAL_RAPIDJSON_HAS_STDSTRING #if CEREAL_RAPIDJSON_HAS_STDSTRING
bool HasMember(const std::basic_string<Ch>& name) const { return value_.HasMember(name); } bool HasMember(const std::basic_string<Ch>& name) const { return value_.HasMember(name); }
@ -2627,7 +2543,7 @@ public:
GenericObject AddMember(StringRefType name, ValueType& value, AllocatorType& allocator) const { value_.AddMember(name, value, allocator); return *this; } GenericObject AddMember(StringRefType name, ValueType& value, AllocatorType& allocator) const { value_.AddMember(name, value, allocator); return *this; }
GenericObject AddMember(StringRefType name, StringRefType value, AllocatorType& allocator) const { value_.AddMember(name, value, allocator); return *this; } GenericObject AddMember(StringRefType name, StringRefType value, AllocatorType& allocator) const { value_.AddMember(name, value, allocator); return *this; }
template <typename T> CEREAL_RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T>, internal::IsGenericValue<T> >), (GenericObject)) AddMember(StringRefType name, T value, AllocatorType& allocator) const { value_.AddMember(name, value, allocator); return *this; } template <typename T> CEREAL_RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T>, internal::IsGenericValue<T> >), (GenericObject)) AddMember(StringRefType name, T value, AllocatorType& allocator) const { value_.AddMember(name, value, allocator); return *this; }
void RemoveAllMembers() { value_.RemoveAllMembers(); } void RemoveAllMembers() { return value_.RemoveAllMembers(); }
bool RemoveMember(const Ch* name) const { return value_.RemoveMember(name); } bool RemoveMember(const Ch* name) const { return value_.RemoveMember(name); }
#if CEREAL_RAPIDJSON_HAS_STDSTRING #if CEREAL_RAPIDJSON_HAS_STDSTRING
bool RemoveMember(const std::basic_string<Ch>& name) const { return value_.RemoveMember(name); } bool RemoveMember(const std::basic_string<Ch>& name) const { return value_.RemoveMember(name); }

View File

@ -200,7 +200,7 @@ private:
// xx xx xx xx UTF-8 // xx xx xx xx UTF-8
if (!hasBOM_) { if (!hasBOM_) {
int pattern = (c[0] ? 1 : 0) | (c[1] ? 2 : 0) | (c[2] ? 4 : 0) | (c[3] ? 8 : 0); unsigned pattern = (c[0] ? 1 : 0) | (c[1] ? 2 : 0) | (c[2] ? 4 : 0) | (c[3] ? 8 : 0);
switch (pattern) { switch (pattern) {
case 0x08: type_ = kUTF32BE; break; case 0x08: type_ = kUTF32BE; break;
case 0x0A: type_ = kUTF16BE; break; case 0x0A: type_ = kUTF16BE; break;

View File

@ -17,7 +17,7 @@
#include "rapidjson.h" #include "rapidjson.h"
#if defined(_MSC_VER) && !defined(__clang__) #ifdef _MSC_VER
CEREAL_RAPIDJSON_DIAG_PUSH CEREAL_RAPIDJSON_DIAG_PUSH
CEREAL_RAPIDJSON_DIAG_OFF(4244) // conversion from 'type1' to 'type2', possible loss of data CEREAL_RAPIDJSON_DIAG_OFF(4244) // conversion from 'type1' to 'type2', possible loss of data
CEREAL_RAPIDJSON_DIAG_OFF(4702) // unreachable code CEREAL_RAPIDJSON_DIAG_OFF(4702) // unreachable code
@ -144,9 +144,9 @@ struct UTF8 {
template <typename InputStream> template <typename InputStream>
static bool Decode(InputStream& is, unsigned* codepoint) { static bool Decode(InputStream& is, unsigned* codepoint) {
#define CEREAL_RAPIDJSON_COPY() c = is.Take(); *codepoint = (*codepoint << 6) | (static_cast<unsigned char>(c) & 0x3Fu) #define COPY() c = is.Take(); *codepoint = (*codepoint << 6) | (static_cast<unsigned char>(c) & 0x3Fu)
#define CEREAL_RAPIDJSON_TRANS(mask) result &= ((GetRange(static_cast<unsigned char>(c)) & mask) != 0) #define TRANS(mask) result &= ((GetRange(static_cast<unsigned char>(c)) & mask) != 0)
#define CEREAL_RAPIDJSON_TAIL() CEREAL_RAPIDJSON_COPY(); CEREAL_RAPIDJSON_TRANS(0x70) #define TAIL() COPY(); TRANS(0x70)
typename InputStream::Ch c = is.Take(); typename InputStream::Ch c = is.Take();
if (!(c & 0x80)) { if (!(c & 0x80)) {
*codepoint = static_cast<unsigned char>(c); *codepoint = static_cast<unsigned char>(c);
@ -157,48 +157,48 @@ struct UTF8 {
if (type >= 32) { if (type >= 32) {
*codepoint = 0; *codepoint = 0;
} else { } else {
*codepoint = (0xFFu >> type) & static_cast<unsigned char>(c); *codepoint = (0xFF >> type) & static_cast<unsigned char>(c);
} }
bool result = true; bool result = true;
switch (type) { switch (type) {
case 2: CEREAL_RAPIDJSON_TAIL(); return result; case 2: TAIL(); return result;
case 3: CEREAL_RAPIDJSON_TAIL(); CEREAL_RAPIDJSON_TAIL(); return result; case 3: TAIL(); TAIL(); return result;
case 4: CEREAL_RAPIDJSON_COPY(); CEREAL_RAPIDJSON_TRANS(0x50); CEREAL_RAPIDJSON_TAIL(); return result; case 4: COPY(); TRANS(0x50); TAIL(); return result;
case 5: CEREAL_RAPIDJSON_COPY(); CEREAL_RAPIDJSON_TRANS(0x10); CEREAL_RAPIDJSON_TAIL(); CEREAL_RAPIDJSON_TAIL(); return result; case 5: COPY(); TRANS(0x10); TAIL(); TAIL(); return result;
case 6: CEREAL_RAPIDJSON_TAIL(); CEREAL_RAPIDJSON_TAIL(); CEREAL_RAPIDJSON_TAIL(); return result; case 6: TAIL(); TAIL(); TAIL(); return result;
case 10: CEREAL_RAPIDJSON_COPY(); CEREAL_RAPIDJSON_TRANS(0x20); CEREAL_RAPIDJSON_TAIL(); return result; case 10: COPY(); TRANS(0x20); TAIL(); return result;
case 11: CEREAL_RAPIDJSON_COPY(); CEREAL_RAPIDJSON_TRANS(0x60); CEREAL_RAPIDJSON_TAIL(); CEREAL_RAPIDJSON_TAIL(); return result; case 11: COPY(); TRANS(0x60); TAIL(); TAIL(); return result;
default: return false; default: return false;
} }
#undef CEREAL_RAPIDJSON_COPY #undef COPY
#undef CEREAL_RAPIDJSON_TRANS #undef TRANS
#undef CEREAL_RAPIDJSON_TAIL #undef TAIL
} }
template <typename InputStream, typename OutputStream> template <typename InputStream, typename OutputStream>
static bool Validate(InputStream& is, OutputStream& os) { static bool Validate(InputStream& is, OutputStream& os) {
#define CEREAL_RAPIDJSON_COPY() os.Put(c = is.Take()) #define COPY() os.Put(c = is.Take())
#define CEREAL_RAPIDJSON_TRANS(mask) result &= ((GetRange(static_cast<unsigned char>(c)) & mask) != 0) #define TRANS(mask) result &= ((GetRange(static_cast<unsigned char>(c)) & mask) != 0)
#define CEREAL_RAPIDJSON_TAIL() CEREAL_RAPIDJSON_COPY(); CEREAL_RAPIDJSON_TRANS(0x70) #define TAIL() COPY(); TRANS(0x70)
Ch c; Ch c;
CEREAL_RAPIDJSON_COPY(); COPY();
if (!(c & 0x80)) if (!(c & 0x80))
return true; return true;
bool result = true; bool result = true;
switch (GetRange(static_cast<unsigned char>(c))) { switch (GetRange(static_cast<unsigned char>(c))) {
case 2: CEREAL_RAPIDJSON_TAIL(); return result; case 2: TAIL(); return result;
case 3: CEREAL_RAPIDJSON_TAIL(); CEREAL_RAPIDJSON_TAIL(); return result; case 3: TAIL(); TAIL(); return result;
case 4: CEREAL_RAPIDJSON_COPY(); CEREAL_RAPIDJSON_TRANS(0x50); CEREAL_RAPIDJSON_TAIL(); return result; case 4: COPY(); TRANS(0x50); TAIL(); return result;
case 5: CEREAL_RAPIDJSON_COPY(); CEREAL_RAPIDJSON_TRANS(0x10); CEREAL_RAPIDJSON_TAIL(); CEREAL_RAPIDJSON_TAIL(); return result; case 5: COPY(); TRANS(0x10); TAIL(); TAIL(); return result;
case 6: CEREAL_RAPIDJSON_TAIL(); CEREAL_RAPIDJSON_TAIL(); CEREAL_RAPIDJSON_TAIL(); return result; case 6: TAIL(); TAIL(); TAIL(); return result;
case 10: CEREAL_RAPIDJSON_COPY(); CEREAL_RAPIDJSON_TRANS(0x20); CEREAL_RAPIDJSON_TAIL(); return result; case 10: COPY(); TRANS(0x20); TAIL(); return result;
case 11: CEREAL_RAPIDJSON_COPY(); CEREAL_RAPIDJSON_TRANS(0x60); CEREAL_RAPIDJSON_TAIL(); CEREAL_RAPIDJSON_TAIL(); return result; case 11: COPY(); TRANS(0x60); TAIL(); TAIL(); return result;
default: return false; default: return false;
} }
#undef CEREAL_RAPIDJSON_COPY #undef COPY
#undef CEREAL_RAPIDJSON_TRANS #undef TRANS
#undef CEREAL_RAPIDJSON_TAIL #undef TAIL
} }
static unsigned char GetRange(unsigned char c) { static unsigned char GetRange(unsigned char c) {
@ -283,7 +283,7 @@ struct UTF16 {
CEREAL_RAPIDJSON_ASSERT(codepoint <= 0x10FFFF); CEREAL_RAPIDJSON_ASSERT(codepoint <= 0x10FFFF);
unsigned v = codepoint - 0x10000; unsigned v = codepoint - 0x10000;
os.Put(static_cast<typename OutputStream::Ch>((v >> 10) | 0xD800)); os.Put(static_cast<typename OutputStream::Ch>((v >> 10) | 0xD800));
os.Put(static_cast<typename OutputStream::Ch>((v & 0x3FF) | 0xDC00)); os.Put((v & 0x3FF) | 0xDC00);
} }
} }
@ -299,7 +299,7 @@ struct UTF16 {
CEREAL_RAPIDJSON_ASSERT(codepoint <= 0x10FFFF); CEREAL_RAPIDJSON_ASSERT(codepoint <= 0x10FFFF);
unsigned v = codepoint - 0x10000; unsigned v = codepoint - 0x10000;
PutUnsafe(os, static_cast<typename OutputStream::Ch>((v >> 10) | 0xD800)); PutUnsafe(os, static_cast<typename OutputStream::Ch>((v >> 10) | 0xD800));
PutUnsafe(os, static_cast<typename OutputStream::Ch>((v & 0x3FF) | 0xDC00)); PutUnsafe(os, (v & 0x3FF) | 0xDC00);
} }
} }
@ -384,7 +384,7 @@ struct UTF16BE : UTF16<CharType> {
static CharType Take(InputByteStream& is) { static CharType Take(InputByteStream& is) {
CEREAL_RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1); CEREAL_RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1);
unsigned c = static_cast<unsigned>(static_cast<uint8_t>(is.Take())) << 8; unsigned c = static_cast<unsigned>(static_cast<uint8_t>(is.Take())) << 8;
c |= static_cast<unsigned>(static_cast<uint8_t>(is.Take())); c |= static_cast<uint8_t>(is.Take());
return static_cast<CharType>(c); return static_cast<CharType>(c);
} }
@ -620,28 +620,28 @@ struct AutoUTF {
#define CEREAL_RAPIDJSON_ENCODINGS_FUNC(x) UTF8<Ch>::x, UTF16LE<Ch>::x, UTF16BE<Ch>::x, UTF32LE<Ch>::x, UTF32BE<Ch>::x #define CEREAL_RAPIDJSON_ENCODINGS_FUNC(x) UTF8<Ch>::x, UTF16LE<Ch>::x, UTF16BE<Ch>::x, UTF32LE<Ch>::x, UTF32BE<Ch>::x
template<typename OutputStream> template<typename OutputStream>
static CEREAL_RAPIDJSON_FORCEINLINE void Encode(OutputStream& os, unsigned codepoint) { CEREAL_RAPIDJSON_FORCEINLINE static void Encode(OutputStream& os, unsigned codepoint) {
typedef void (*EncodeFunc)(OutputStream&, unsigned); typedef void (*EncodeFunc)(OutputStream&, unsigned);
static const EncodeFunc f[] = { CEREAL_RAPIDJSON_ENCODINGS_FUNC(Encode) }; static const EncodeFunc f[] = { CEREAL_RAPIDJSON_ENCODINGS_FUNC(Encode) };
(*f[os.GetType()])(os, codepoint); (*f[os.GetType()])(os, codepoint);
} }
template<typename OutputStream> template<typename OutputStream>
static CEREAL_RAPIDJSON_FORCEINLINE void EncodeUnsafe(OutputStream& os, unsigned codepoint) { CEREAL_RAPIDJSON_FORCEINLINE static void EncodeUnsafe(OutputStream& os, unsigned codepoint) {
typedef void (*EncodeFunc)(OutputStream&, unsigned); typedef void (*EncodeFunc)(OutputStream&, unsigned);
static const EncodeFunc f[] = { CEREAL_RAPIDJSON_ENCODINGS_FUNC(EncodeUnsafe) }; static const EncodeFunc f[] = { CEREAL_RAPIDJSON_ENCODINGS_FUNC(EncodeUnsafe) };
(*f[os.GetType()])(os, codepoint); (*f[os.GetType()])(os, codepoint);
} }
template <typename InputStream> template <typename InputStream>
static CEREAL_RAPIDJSON_FORCEINLINE bool Decode(InputStream& is, unsigned* codepoint) { CEREAL_RAPIDJSON_FORCEINLINE static bool Decode(InputStream& is, unsigned* codepoint) {
typedef bool (*DecodeFunc)(InputStream&, unsigned*); typedef bool (*DecodeFunc)(InputStream&, unsigned*);
static const DecodeFunc f[] = { CEREAL_RAPIDJSON_ENCODINGS_FUNC(Decode) }; static const DecodeFunc f[] = { CEREAL_RAPIDJSON_ENCODINGS_FUNC(Decode) };
return (*f[is.GetType()])(is, codepoint); return (*f[is.GetType()])(is, codepoint);
} }
template <typename InputStream, typename OutputStream> template <typename InputStream, typename OutputStream>
static CEREAL_RAPIDJSON_FORCEINLINE bool Validate(InputStream& is, OutputStream& os) { CEREAL_RAPIDJSON_FORCEINLINE static bool Validate(InputStream& is, OutputStream& os) {
typedef bool (*ValidateFunc)(InputStream&, OutputStream&); typedef bool (*ValidateFunc)(InputStream&, OutputStream&);
static const ValidateFunc f[] = { CEREAL_RAPIDJSON_ENCODINGS_FUNC(Validate) }; static const ValidateFunc f[] = { CEREAL_RAPIDJSON_ENCODINGS_FUNC(Validate) };
return (*f[is.GetType()])(is, os); return (*f[is.GetType()])(is, os);
@ -658,7 +658,7 @@ template<typename SourceEncoding, typename TargetEncoding>
struct Transcoder { struct Transcoder {
//! Take one Unicode codepoint from source encoding, convert it to target encoding and put it to the output stream. //! Take one Unicode codepoint from source encoding, convert it to target encoding and put it to the output stream.
template<typename InputStream, typename OutputStream> template<typename InputStream, typename OutputStream>
static CEREAL_RAPIDJSON_FORCEINLINE bool Transcode(InputStream& is, OutputStream& os) { CEREAL_RAPIDJSON_FORCEINLINE static bool Transcode(InputStream& is, OutputStream& os) {
unsigned codepoint; unsigned codepoint;
if (!SourceEncoding::Decode(is, &codepoint)) if (!SourceEncoding::Decode(is, &codepoint))
return false; return false;
@ -667,7 +667,7 @@ struct Transcoder {
} }
template<typename InputStream, typename OutputStream> template<typename InputStream, typename OutputStream>
static CEREAL_RAPIDJSON_FORCEINLINE bool TranscodeUnsafe(InputStream& is, OutputStream& os) { CEREAL_RAPIDJSON_FORCEINLINE static bool TranscodeUnsafe(InputStream& is, OutputStream& os) {
unsigned codepoint; unsigned codepoint;
if (!SourceEncoding::Decode(is, &codepoint)) if (!SourceEncoding::Decode(is, &codepoint))
return false; return false;
@ -677,7 +677,7 @@ struct Transcoder {
//! Validate one Unicode codepoint from an encoded stream. //! Validate one Unicode codepoint from an encoded stream.
template<typename InputStream, typename OutputStream> template<typename InputStream, typename OutputStream>
static CEREAL_RAPIDJSON_FORCEINLINE bool Validate(InputStream& is, OutputStream& os) { CEREAL_RAPIDJSON_FORCEINLINE static bool Validate(InputStream& is, OutputStream& os) {
return Transcode(is, os); // Since source/target encoding is different, must transcode. return Transcode(is, os); // Since source/target encoding is different, must transcode.
} }
}; };
@ -690,26 +690,26 @@ inline void PutUnsafe(Stream& stream, typename Stream::Ch c);
template<typename Encoding> template<typename Encoding>
struct Transcoder<Encoding, Encoding> { struct Transcoder<Encoding, Encoding> {
template<typename InputStream, typename OutputStream> template<typename InputStream, typename OutputStream>
static CEREAL_RAPIDJSON_FORCEINLINE bool Transcode(InputStream& is, OutputStream& os) { CEREAL_RAPIDJSON_FORCEINLINE static bool Transcode(InputStream& is, OutputStream& os) {
os.Put(is.Take()); // Just copy one code unit. This semantic is different from primary template class. os.Put(is.Take()); // Just copy one code unit. This semantic is different from primary template class.
return true; return true;
} }
template<typename InputStream, typename OutputStream> template<typename InputStream, typename OutputStream>
static CEREAL_RAPIDJSON_FORCEINLINE bool TranscodeUnsafe(InputStream& is, OutputStream& os) { CEREAL_RAPIDJSON_FORCEINLINE static bool TranscodeUnsafe(InputStream& is, OutputStream& os) {
PutUnsafe(os, is.Take()); // Just copy one code unit. This semantic is different from primary template class. PutUnsafe(os, is.Take()); // Just copy one code unit. This semantic is different from primary template class.
return true; return true;
} }
template<typename InputStream, typename OutputStream> template<typename InputStream, typename OutputStream>
static CEREAL_RAPIDJSON_FORCEINLINE bool Validate(InputStream& is, OutputStream& os) { CEREAL_RAPIDJSON_FORCEINLINE static bool Validate(InputStream& is, OutputStream& os) {
return Encoding::Validate(is, os); // source/target encoding are the same return Encoding::Validate(is, os); // source/target encoding are the same
} }
}; };
CEREAL_RAPIDJSON_NAMESPACE_END CEREAL_RAPIDJSON_NAMESPACE_END
#if defined(__GNUC__) || (defined(_MSC_VER) && !defined(__clang__)) #if defined(__GNUC__) || defined(_MSC_VER)
CEREAL_RAPIDJSON_DIAG_POP CEREAL_RAPIDJSON_DIAG_POP
#endif #endif

View File

@ -104,8 +104,6 @@ enum ParseErrorCode {
\see GenericReader::Parse, GenericDocument::Parse \see GenericReader::Parse, GenericDocument::Parse
*/ */
struct ParseResult { struct ParseResult {
//!! Unspecified boolean type
typedef bool (ParseResult::*BooleanType)() const;
public: public:
//! Default constructor, no error. //! Default constructor, no error.
ParseResult() : code_(kParseErrorNone), offset_(0) {} ParseResult() : code_(kParseErrorNone), offset_(0) {}
@ -117,8 +115,8 @@ public:
//! Get the error offset, if \ref IsError(), 0 otherwise. //! Get the error offset, if \ref IsError(), 0 otherwise.
size_t Offset() const { return offset_; } size_t Offset() const { return offset_; }
//! Explicit conversion to \c bool, returns \c true, iff !\ref IsError(). //! Conversion to \c bool, returns \c true, iff !\ref IsError().
operator BooleanType() const { return !IsError() ? &ParseResult::IsError : NULL; } operator bool() const { return !IsError(); }
//! Whether the result is an error. //! Whether the result is an error.
bool IsError() const { return code_ != kParseErrorNone; } bool IsError() const { return code_ != kParseErrorNone; }
@ -126,10 +124,6 @@ public:
bool operator==(ParseErrorCode code) const { return code_ == code; } bool operator==(ParseErrorCode code) const { return code_ == code; }
friend bool operator==(ParseErrorCode code, const ParseResult & err) { return code == err.code_; } friend bool operator==(ParseErrorCode code, const ParseResult & err) { return code == err.code_; }
bool operator!=(const ParseResult& that) const { return !(*this == that); }
bool operator!=(ParseErrorCode code) const { return !(*this == code); }
friend bool operator!=(ParseErrorCode code, const ParseResult & err) { return err != code; }
//! Reset error code. //! Reset error code.
void Clear() { Set(kParseErrorNone); } void Clear() { Set(kParseErrorNone); }
//! Update error code and offset. //! Update error code and offset.

View File

@ -59,7 +59,7 @@ public:
// For encoding detection only. // For encoding detection only.
const Ch* Peek4() const { const Ch* Peek4() const {
return (current_ + 4 - !eof_ <= bufferLast_) ? current_ : 0; return (current_ + 4 <= bufferLast_) ? current_ : 0;
} }
private: private:
@ -68,7 +68,7 @@ private:
++current_; ++current_;
else if (!eof_) { else if (!eof_) {
count_ += readCount_; count_ += readCount_;
readCount_ = std::fread(buffer_, 1, bufferSize_, fp_); readCount_ = fread(buffer_, 1, bufferSize_, fp_);
bufferLast_ = buffer_ + readCount_ - 1; bufferLast_ = buffer_ + readCount_ - 1;
current_ = buffer_; current_ = buffer_;

View File

@ -25,7 +25,7 @@ CEREAL_RAPIDJSON_DIAG_OFF(unreachable-code)
CEREAL_RAPIDJSON_NAMESPACE_BEGIN CEREAL_RAPIDJSON_NAMESPACE_BEGIN
//! Wrapper of C file stream for output using fwrite(). //! Wrapper of C file stream for input using fread().
/*! /*!
\note implements Stream concept \note implements Stream concept
*/ */
@ -62,7 +62,7 @@ public:
void Flush() { void Flush() {
if (current_ != buffer_) { if (current_ != buffer_) {
size_t result = std::fwrite(buffer_, 1, static_cast<size_t>(current_ - buffer_), fp_); size_t result = fwrite(buffer_, 1, static_cast<size_t>(current_ - buffer_), fp_);
if (result < static_cast<size_t>(current_ - buffer_)) { if (result < static_cast<size_t>(current_ - buffer_)) {
// failure deliberately ignored at this time // failure deliberately ignored at this time
// added to avoid warn_unused_result build errors // added to avoid warn_unused_result build errors

View File

@ -17,7 +17,7 @@
#include "../rapidjson.h" #include "../rapidjson.h"
#if defined(_MSC_VER) && !__INTEL_COMPILER && defined(_M_AMD64) #if defined(_MSC_VER) && defined(_M_AMD64)
#include <intrin.h> // for _umul128 #include <intrin.h> // for _umul128
#pragma intrinsic(_umul128) #pragma intrinsic(_umul128)
#endif #endif
@ -133,7 +133,7 @@ public:
CEREAL_RAPIDJSON_ASSERT(count_ + offset <= kCapacity); CEREAL_RAPIDJSON_ASSERT(count_ + offset <= kCapacity);
if (interShift == 0) { if (interShift == 0) {
std::memmove(digits_ + offset, digits_, count_ * sizeof(Type)); std::memmove(&digits_[count_ - 1 + offset], &digits_[count_ - 1], count_ * sizeof(Type));
count_ += offset; count_ += offset;
} }
else { else {

View File

@ -20,9 +20,8 @@
#define CEREAL_RAPIDJSON_DIYFP_H_ #define CEREAL_RAPIDJSON_DIYFP_H_
#include "../rapidjson.h" #include "../rapidjson.h"
#include <limits>
#if defined(_MSC_VER) && defined(_M_AMD64) && !defined(__INTEL_COMPILER) #if defined(_MSC_VER) && defined(_M_AMD64)
#include <intrin.h> #include <intrin.h>
#pragma intrinsic(_BitScanReverse64) #pragma intrinsic(_BitScanReverse64)
#pragma intrinsic(_umul128) #pragma intrinsic(_umul128)
@ -100,7 +99,6 @@ struct DiyFp {
} }
DiyFp Normalize() const { DiyFp Normalize() const {
CEREAL_RAPIDJSON_ASSERT(f != 0); // https://stackoverflow.com/a/26809183/291737
#if defined(_MSC_VER) && defined(_M_AMD64) #if defined(_MSC_VER) && defined(_M_AMD64)
unsigned long index; unsigned long index;
_BitScanReverse64(&index, f); _BitScanReverse64(&index, f);
@ -143,15 +141,6 @@ struct DiyFp {
double d; double d;
uint64_t u64; uint64_t u64;
}u; }u;
CEREAL_RAPIDJSON_ASSERT(f <= kDpHiddenBit + kDpSignificandMask);
if (e < kDpDenormalExponent) {
// Underflow.
return 0.0;
}
if (e >= kDpMaxExponent) {
// Overflow.
return std::numeric_limits<double>::infinity();
}
const uint64_t be = (e == kDpDenormalExponent && (f & kDpHiddenBit) == 0) ? 0 : const uint64_t be = (e == kDpDenormalExponent && (f & kDpHiddenBit) == 0) ? 0 :
static_cast<uint64_t>(e + kDpExponentBias); static_cast<uint64_t>(e + kDpExponentBias);
u.u64 = (f & kDpSignificandMask) | (be << kDpSignificandSize); u.u64 = (f & kDpSignificandMask) | (be << kDpSignificandSize);
@ -231,7 +220,6 @@ inline DiyFp GetCachedPowerByIndex(size_t index) {
641, 667, 694, 720, 747, 774, 800, 827, 853, 880, 641, 667, 694, 720, 747, 774, 800, 827, 853, 880,
907, 933, 960, 986, 1013, 1039, 1066 907, 933, 960, 986, 1013, 1039, 1066
}; };
CEREAL_RAPIDJSON_ASSERT(index < 87);
return DiyFp(kCachedPowers_F[index], kCachedPowers_E[index]); return DiyFp(kCachedPowers_F[index], kCachedPowers_E[index]);
} }
@ -250,8 +238,7 @@ inline DiyFp GetCachedPower(int e, int* K) {
} }
inline DiyFp GetCachedPower10(int exp, int *outExp) { inline DiyFp GetCachedPower10(int exp, int *outExp) {
CEREAL_RAPIDJSON_ASSERT(exp >= -348); unsigned index = (static_cast<unsigned>(exp) + 348u) / 8u;
unsigned index = static_cast<unsigned>(exp + 348) / 8u;
*outExp = -348 + static_cast<int>(index) * 8; *outExp = -348 + static_cast<int>(index) * 8;
return GetCachedPowerByIndex(index); return GetCachedPowerByIndex(index);
} }

View File

@ -41,7 +41,7 @@ inline void GrisuRound(char* buffer, int len, uint64_t delta, uint64_t rest, uin
} }
} }
inline int CountDecimalDigit32(uint32_t n) { inline unsigned CountDecimalDigit32(uint32_t n) {
// Simple pure C++ implementation was faster than __builtin_clz version in this situation. // Simple pure C++ implementation was faster than __builtin_clz version in this situation.
if (n < 10) return 1; if (n < 10) return 1;
if (n < 100) return 2; if (n < 100) return 2;
@ -63,7 +63,7 @@ inline void DigitGen(const DiyFp& W, const DiyFp& Mp, uint64_t delta, char* buff
const DiyFp wp_w = Mp - W; const DiyFp wp_w = Mp - W;
uint32_t p1 = static_cast<uint32_t>(Mp.f >> -one.e); uint32_t p1 = static_cast<uint32_t>(Mp.f >> -one.e);
uint64_t p2 = Mp.f & (one.f - 1); uint64_t p2 = Mp.f & (one.f - 1);
int kappa = CountDecimalDigit32(p1); // kappa in [0, 9] unsigned kappa = CountDecimalDigit32(p1); // kappa in [0, 9]
*len = 0; *len = 0;
while (kappa > 0) { while (kappa > 0) {
@ -102,8 +102,8 @@ inline void DigitGen(const DiyFp& W, const DiyFp& Mp, uint64_t delta, char* buff
kappa--; kappa--;
if (p2 < delta) { if (p2 < delta) {
*K += kappa; *K += kappa;
int index = -kappa; int index = -static_cast<int>(kappa);
GrisuRound(buffer, *len, delta, p2, one.f, wp_w.f * (index < 9 ? kPow10[index] : 0)); GrisuRound(buffer, *len, delta, p2, one.f, wp_w.f * (index < 9 ? kPow10[-static_cast<int>(kappa)] : 0));
return; return;
} }
} }

View File

@ -48,13 +48,13 @@ public:
int IntegerExponent() const { return (IsNormal() ? Exponent() : kDenormalExponent) - kSignificandSize; } int IntegerExponent() const { return (IsNormal() ? Exponent() : kDenormalExponent) - kSignificandSize; }
uint64_t ToBias() const { return (u_ & kSignMask) ? ~u_ + 1 : u_ | kSignMask; } uint64_t ToBias() const { return (u_ & kSignMask) ? ~u_ + 1 : u_ | kSignMask; }
static int EffectiveSignificandSize(int order) { static unsigned EffectiveSignificandSize(int order) {
if (order >= -1021) if (order >= -1021)
return 53; return 53;
else if (order <= -1074) else if (order <= -1074)
return 0; return 0;
else else
return order + 1074; return static_cast<unsigned>(order) + 1074;
} }
private: private:

View File

@ -37,8 +37,6 @@ inline const char* GetDigitsLut() {
} }
inline char* u32toa(uint32_t value, char* buffer) { inline char* u32toa(uint32_t value, char* buffer) {
CEREAL_RAPIDJSON_ASSERT(buffer != 0);
const char* cDigitsLut = GetDigitsLut(); const char* cDigitsLut = GetDigitsLut();
if (value < 10000) { if (value < 10000) {
@ -113,7 +111,6 @@ inline char* u32toa(uint32_t value, char* buffer) {
} }
inline char* i32toa(int32_t value, char* buffer) { inline char* i32toa(int32_t value, char* buffer) {
CEREAL_RAPIDJSON_ASSERT(buffer != 0);
uint32_t u = static_cast<uint32_t>(value); uint32_t u = static_cast<uint32_t>(value);
if (value < 0) { if (value < 0) {
*buffer++ = '-'; *buffer++ = '-';
@ -124,7 +121,6 @@ inline char* i32toa(int32_t value, char* buffer) {
} }
inline char* u64toa(uint64_t value, char* buffer) { inline char* u64toa(uint64_t value, char* buffer) {
CEREAL_RAPIDJSON_ASSERT(buffer != 0);
const char* cDigitsLut = GetDigitsLut(); const char* cDigitsLut = GetDigitsLut();
const uint64_t kTen8 = 100000000; const uint64_t kTen8 = 100000000;
const uint64_t kTen9 = kTen8 * 10; const uint64_t kTen9 = kTen8 * 10;
@ -211,8 +207,9 @@ inline char* u64toa(uint64_t value, char* buffer) {
*buffer++ = cDigitsLut[d3 + 1]; *buffer++ = cDigitsLut[d3 + 1];
if (value >= kTen9) if (value >= kTen9)
*buffer++ = cDigitsLut[d4]; *buffer++ = cDigitsLut[d4];
if (value >= kTen8)
*buffer++ = cDigitsLut[d4 + 1]; *buffer++ = cDigitsLut[d4 + 1];
*buffer++ = cDigitsLut[d5]; *buffer++ = cDigitsLut[d5];
*buffer++ = cDigitsLut[d5 + 1]; *buffer++ = cDigitsLut[d5 + 1];
*buffer++ = cDigitsLut[d6]; *buffer++ = cDigitsLut[d6];
@ -292,7 +289,6 @@ inline char* u64toa(uint64_t value, char* buffer) {
} }
inline char* i64toa(int64_t value, char* buffer) { inline char* i64toa(int64_t value, char* buffer) {
CEREAL_RAPIDJSON_ASSERT(buffer != 0);
uint64_t u = static_cast<uint64_t>(value); uint64_t u = static_cast<uint64_t>(value);
if (value < 0) { if (value < 0) {
*buffer++ = '-'; *buffer++ = '-';

View File

@ -21,8 +21,7 @@
CEREAL_RAPIDJSON_DIAG_PUSH CEREAL_RAPIDJSON_DIAG_PUSH
CEREAL_RAPIDJSON_DIAG_OFF(effc++) CEREAL_RAPIDJSON_DIAG_OFF(effc++)
#endif #endif
#if defined(_MSC_VER)
#if defined(_MSC_VER) && !defined(__clang__)
CEREAL_RAPIDJSON_DIAG_PUSH CEREAL_RAPIDJSON_DIAG_PUSH
CEREAL_RAPIDJSON_DIAG_OFF(6334) CEREAL_RAPIDJSON_DIAG_OFF(6334)
#endif #endif
@ -175,11 +174,7 @@ template <typename T> struct RemoveSfinaeTag<SfinaeTag&(*)(T)> { typedef T Type;
CEREAL_RAPIDJSON_NAMESPACE_END CEREAL_RAPIDJSON_NAMESPACE_END
//@endcond //@endcond
#if defined(_MSC_VER) && !defined(__clang__) #if defined(__GNUC__) || defined(_MSC_VER)
CEREAL_RAPIDJSON_DIAG_POP
#endif
#ifdef __GNUC__
CEREAL_RAPIDJSON_DIAG_POP CEREAL_RAPIDJSON_DIAG_POP
#endif #endif

View File

@ -24,17 +24,16 @@ CEREAL_RAPIDJSON_DIAG_PUSH
CEREAL_RAPIDJSON_DIAG_OFF(padded) CEREAL_RAPIDJSON_DIAG_OFF(padded)
CEREAL_RAPIDJSON_DIAG_OFF(switch-enum) CEREAL_RAPIDJSON_DIAG_OFF(switch-enum)
CEREAL_RAPIDJSON_DIAG_OFF(implicit-fallthrough) CEREAL_RAPIDJSON_DIAG_OFF(implicit-fallthrough)
#elif defined(_MSC_VER)
CEREAL_RAPIDJSON_DIAG_PUSH
CEREAL_RAPIDJSON_DIAG_OFF(4512) // assignment operator could not be generated
#endif #endif
#ifdef __GNUC__ #ifdef __GNUC__
CEREAL_RAPIDJSON_DIAG_PUSH CEREAL_RAPIDJSON_DIAG_PUSH
CEREAL_RAPIDJSON_DIAG_OFF(effc++) CEREAL_RAPIDJSON_DIAG_OFF(effc++)
#if __GNUC__ >= 7
CEREAL_RAPIDJSON_DIAG_OFF(implicit-fallthrough)
#endif #endif
#ifdef _MSC_VER
CEREAL_RAPIDJSON_DIAG_PUSH
CEREAL_RAPIDJSON_DIAG_OFF(4512) // assignment operator could not be generated
#endif #endif
#ifndef CEREAL_RAPIDJSON_REGEX_VERBOSE #ifndef CEREAL_RAPIDJSON_REGEX_VERBOSE
@ -44,40 +43,12 @@ CEREAL_RAPIDJSON_DIAG_OFF(implicit-fallthrough)
CEREAL_RAPIDJSON_NAMESPACE_BEGIN CEREAL_RAPIDJSON_NAMESPACE_BEGIN
namespace internal { namespace internal {
///////////////////////////////////////////////////////////////////////////////
// DecodedStream
template <typename SourceStream, typename Encoding>
class DecodedStream {
public:
DecodedStream(SourceStream& ss) : ss_(ss), codepoint_() { Decode(); }
unsigned Peek() { return codepoint_; }
unsigned Take() {
unsigned c = codepoint_;
if (c) // No further decoding when '\0'
Decode();
return c;
}
private:
void Decode() {
if (!Encoding::Decode(ss_, &codepoint_))
codepoint_ = 0;
}
SourceStream& ss_;
unsigned codepoint_;
};
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
// GenericRegex // GenericRegex
static const SizeType kRegexInvalidState = ~SizeType(0); //!< Represents an invalid index in GenericRegex::State::out, out1 static const SizeType kRegexInvalidState = ~SizeType(0); //!< Represents an invalid index in GenericRegex::State::out, out1
static const SizeType kRegexInvalidRange = ~SizeType(0); static const SizeType kRegexInvalidRange = ~SizeType(0);
template <typename Encoding, typename Allocator>
class GenericRegexSearch;
//! Regular expression engine with subset of ECMAscript grammar. //! Regular expression engine with subset of ECMAscript grammar.
/*! /*!
Supported regular expression syntax: Supported regular expression syntax:
@ -113,29 +84,45 @@ class GenericRegexSearch;
template <typename Encoding, typename Allocator = CrtAllocator> template <typename Encoding, typename Allocator = CrtAllocator>
class GenericRegex { class GenericRegex {
public: public:
typedef Encoding EncodingType;
typedef typename Encoding::Ch Ch; typedef typename Encoding::Ch Ch;
template <typename, typename> friend class GenericRegexSearch;
GenericRegex(const Ch* source, Allocator* allocator = 0) : GenericRegex(const Ch* source, Allocator* allocator = 0) :
ownAllocator_(allocator ? 0 : CEREAL_RAPIDJSON_NEW(Allocator)()), allocator_(allocator ? allocator : ownAllocator_), states_(allocator, 256), ranges_(allocator, 256), root_(kRegexInvalidState), stateCount_(), rangeCount_(),
states_(allocator_, 256), ranges_(allocator_, 256), root_(kRegexInvalidState), stateCount_(), rangeCount_(), stateSet_(), state0_(allocator, 0), state1_(allocator, 0), anchorBegin_(), anchorEnd_()
anchorBegin_(), anchorEnd_()
{ {
GenericStringStream<Encoding> ss(source); GenericStringStream<Encoding> ss(source);
DecodedStream<GenericStringStream<Encoding>, Encoding> ds(ss); DecodedStream<GenericStringStream<Encoding> > ds(ss);
Parse(ds); Parse(ds);
} }
~GenericRegex() ~GenericRegex() {
{ Allocator::Free(stateSet_);
CEREAL_RAPIDJSON_DELETE(ownAllocator_);
} }
bool IsValid() const { bool IsValid() const {
return root_ != kRegexInvalidState; return root_ != kRegexInvalidState;
} }
template <typename InputStream>
bool Match(InputStream& is) const {
return SearchWithAnchoring(is, true, true);
}
bool Match(const Ch* s) const {
GenericStringStream<Encoding> is(s);
return Match(is);
}
template <typename InputStream>
bool Search(InputStream& is) const {
return SearchWithAnchoring(is, anchorBegin_, anchorEnd_);
}
bool Search(const Ch* s) const {
GenericStringStream<Encoding> is(s);
return Search(is);
}
private: private:
enum Operator { enum Operator {
kZeroOrOne, kZeroOrOne,
@ -170,6 +157,28 @@ private:
SizeType minIndex; SizeType minIndex;
}; };
template <typename SourceStream>
class DecodedStream {
public:
DecodedStream(SourceStream& ss) : ss_(ss), codepoint_() { Decode(); }
unsigned Peek() { return codepoint_; }
unsigned Take() {
unsigned c = codepoint_;
if (c) // No further decoding when '\0'
Decode();
return c;
}
private:
void Decode() {
if (!Encoding::Decode(ss_, &codepoint_))
codepoint_ = 0;
}
SourceStream& ss_;
unsigned codepoint_;
};
State& GetState(SizeType index) { State& GetState(SizeType index) {
CEREAL_RAPIDJSON_ASSERT(index < stateCount_); CEREAL_RAPIDJSON_ASSERT(index < stateCount_);
return states_.template Bottom<State>()[index]; return states_.template Bottom<State>()[index];
@ -191,10 +200,11 @@ private:
} }
template <typename InputStream> template <typename InputStream>
void Parse(DecodedStream<InputStream, Encoding>& ds) { void Parse(DecodedStream<InputStream>& ds) {
Stack<Allocator> operandStack(allocator_, 256); // Frag Allocator allocator;
Stack<Allocator> operatorStack(allocator_, 256); // Operator Stack<Allocator> operandStack(&allocator, 256); // Frag
Stack<Allocator> atomCountStack(allocator_, 256); // unsigned (Atom per parenthesis) Stack<Allocator> operatorStack(&allocator, 256); // Operator
Stack<Allocator> atomCountStack(&allocator, 256); // unsigned (Atom per parenthesis)
*atomCountStack.template Push<unsigned>() = 0; *atomCountStack.template Push<unsigned>() = 0;
@ -317,6 +327,14 @@ private:
printf("\n"); printf("\n");
#endif #endif
} }
// Preallocate buffer for SearchWithAnchoring()
CEREAL_RAPIDJSON_ASSERT(stateSet_ == 0);
if (stateCount_ > 0) {
stateSet_ = static_cast<unsigned*>(states_.GetAllocator().Malloc(GetStateSetSize()));
state0_.template Reserve<SizeType>(stateCount_);
state1_.template Reserve<SizeType>(stateCount_);
}
} }
SizeType NewState(SizeType out, SizeType out1, unsigned codepoint) { SizeType NewState(SizeType out, SizeType out1, unsigned codepoint) {
@ -395,7 +413,8 @@ private:
} }
return false; return false;
case kOneOrMore: default:
CEREAL_RAPIDJSON_ASSERT(op == kOneOrMore);
if (operandStack.GetSize() >= sizeof(Frag)) { if (operandStack.GetSize() >= sizeof(Frag)) {
Frag e = *operandStack.template Pop<Frag>(1); Frag e = *operandStack.template Pop<Frag>(1);
SizeType s = NewState(kRegexInvalidState, e.start, 0); SizeType s = NewState(kRegexInvalidState, e.start, 0);
@ -404,10 +423,6 @@ private:
return true; return true;
} }
return false; return false;
default:
// syntax error (e.g. unclosed kLeftParenthesis)
return false;
} }
} }
@ -468,7 +483,7 @@ private:
} }
template <typename InputStream> template <typename InputStream>
bool ParseUnsigned(DecodedStream<InputStream, Encoding>& ds, unsigned* u) { bool ParseUnsigned(DecodedStream<InputStream>& ds, unsigned* u) {
unsigned r = 0; unsigned r = 0;
if (ds.Peek() < '0' || ds.Peek() > '9') if (ds.Peek() < '0' || ds.Peek() > '9')
return false; return false;
@ -482,7 +497,7 @@ private:
} }
template <typename InputStream> template <typename InputStream>
bool ParseRange(DecodedStream<InputStream, Encoding>& ds, SizeType* range) { bool ParseRange(DecodedStream<InputStream>& ds, SizeType* range) {
bool isBegin = true; bool isBegin = true;
bool negate = false; bool negate = false;
int step = 0; int step = 0;
@ -560,7 +575,7 @@ private:
} }
template <typename InputStream> template <typename InputStream>
bool CharacterEscape(DecodedStream<InputStream, Encoding>& ds, unsigned* escapedCodepoint) { bool CharacterEscape(DecodedStream<InputStream>& ds, unsigned* escapedCodepoint) {
unsigned codepoint; unsigned codepoint;
switch (codepoint = ds.Take()) { switch (codepoint = ds.Take()) {
case '^': case '^':
@ -588,8 +603,72 @@ private:
} }
} }
Allocator* ownAllocator_; template <typename InputStream>
Allocator* allocator_; bool SearchWithAnchoring(InputStream& is, bool anchorBegin, bool anchorEnd) const {
CEREAL_RAPIDJSON_ASSERT(IsValid());
DecodedStream<InputStream> ds(is);
state0_.Clear();
Stack<Allocator> *current = &state0_, *next = &state1_;
const size_t stateSetSize = GetStateSetSize();
std::memset(stateSet_, 0, stateSetSize);
bool matched = AddState(*current, root_);
unsigned codepoint;
while (!current->Empty() && (codepoint = ds.Take()) != 0) {
std::memset(stateSet_, 0, stateSetSize);
next->Clear();
matched = false;
for (const SizeType* s = current->template Bottom<SizeType>(); s != current->template End<SizeType>(); ++s) {
const State& sr = GetState(*s);
if (sr.codepoint == codepoint ||
sr.codepoint == kAnyCharacterClass ||
(sr.codepoint == kRangeCharacterClass && MatchRange(sr.rangeStart, codepoint)))
{
matched = AddState(*next, sr.out) || matched;
if (!anchorEnd && matched)
return true;
}
if (!anchorBegin)
AddState(*next, root_);
}
internal::Swap(current, next);
}
return matched;
}
size_t GetStateSetSize() const {
return (stateCount_ + 31) / 32 * 4;
}
// Return whether the added states is a match state
bool AddState(Stack<Allocator>& l, SizeType index) const {
CEREAL_RAPIDJSON_ASSERT(index != kRegexInvalidState);
const State& s = GetState(index);
if (s.out1 != kRegexInvalidState) { // Split
bool matched = AddState(l, s.out);
return AddState(l, s.out1) || matched;
}
else if (!(stateSet_[index >> 5] & (1 << (index & 31)))) {
stateSet_[index >> 5] |= (1 << (index & 31));
*l.template PushUnsafe<SizeType>() = index;
}
return s.out == kRegexInvalidState; // by using PushUnsafe() above, we can ensure s is not validated due to reallocation.
}
bool MatchRange(SizeType rangeIndex, unsigned codepoint) const {
bool yes = (GetRange(rangeIndex).start & kRangeNegationFlag) == 0;
while (rangeIndex != kRegexInvalidRange) {
const Range& r = GetRange(rangeIndex);
if (codepoint >= (r.start & ~kRangeNegationFlag) && codepoint <= r.end)
return yes;
rangeIndex = r.next;
}
return !yes;
}
Stack<Allocator> states_; Stack<Allocator> states_;
Stack<Allocator> ranges_; Stack<Allocator> ranges_;
SizeType root_; SizeType root_;
@ -599,141 +678,23 @@ private:
static const unsigned kInfinityQuantifier = ~0u; static const unsigned kInfinityQuantifier = ~0u;
// For SearchWithAnchoring() // For SearchWithAnchoring()
uint32_t* stateSet_; // allocated by states_.GetAllocator()
mutable Stack<Allocator> state0_;
mutable Stack<Allocator> state1_;
bool anchorBegin_; bool anchorBegin_;
bool anchorEnd_; bool anchorEnd_;
}; };
template <typename RegexType, typename Allocator = CrtAllocator>
class GenericRegexSearch {
public:
typedef typename RegexType::EncodingType Encoding;
typedef typename Encoding::Ch Ch;
GenericRegexSearch(const RegexType& regex, Allocator* allocator = 0) :
regex_(regex), allocator_(allocator), ownAllocator_(0),
state0_(allocator, 0), state1_(allocator, 0), stateSet_()
{
CEREAL_RAPIDJSON_ASSERT(regex_.IsValid());
if (!allocator_)
ownAllocator_ = allocator_ = CEREAL_RAPIDJSON_NEW(Allocator)();
stateSet_ = static_cast<unsigned*>(allocator_->Malloc(GetStateSetSize()));
state0_.template Reserve<SizeType>(regex_.stateCount_);
state1_.template Reserve<SizeType>(regex_.stateCount_);
}
~GenericRegexSearch() {
Allocator::Free(stateSet_);
CEREAL_RAPIDJSON_DELETE(ownAllocator_);
}
template <typename InputStream>
bool Match(InputStream& is) {
return SearchWithAnchoring(is, true, true);
}
bool Match(const Ch* s) {
GenericStringStream<Encoding> is(s);
return Match(is);
}
template <typename InputStream>
bool Search(InputStream& is) {
return SearchWithAnchoring(is, regex_.anchorBegin_, regex_.anchorEnd_);
}
bool Search(const Ch* s) {
GenericStringStream<Encoding> is(s);
return Search(is);
}
private:
typedef typename RegexType::State State;
typedef typename RegexType::Range Range;
template <typename InputStream>
bool SearchWithAnchoring(InputStream& is, bool anchorBegin, bool anchorEnd) {
DecodedStream<InputStream, Encoding> ds(is);
state0_.Clear();
Stack<Allocator> *current = &state0_, *next = &state1_;
const size_t stateSetSize = GetStateSetSize();
std::memset(stateSet_, 0, stateSetSize);
bool matched = AddState(*current, regex_.root_);
unsigned codepoint;
while (!current->Empty() && (codepoint = ds.Take()) != 0) {
std::memset(stateSet_, 0, stateSetSize);
next->Clear();
matched = false;
for (const SizeType* s = current->template Bottom<SizeType>(); s != current->template End<SizeType>(); ++s) {
const State& sr = regex_.GetState(*s);
if (sr.codepoint == codepoint ||
sr.codepoint == RegexType::kAnyCharacterClass ||
(sr.codepoint == RegexType::kRangeCharacterClass && MatchRange(sr.rangeStart, codepoint)))
{
matched = AddState(*next, sr.out) || matched;
if (!anchorEnd && matched)
return true;
}
if (!anchorBegin)
AddState(*next, regex_.root_);
}
internal::Swap(current, next);
}
return matched;
}
size_t GetStateSetSize() const {
return (regex_.stateCount_ + 31) / 32 * 4;
}
// Return whether the added states is a match state
bool AddState(Stack<Allocator>& l, SizeType index) {
CEREAL_RAPIDJSON_ASSERT(index != kRegexInvalidState);
const State& s = regex_.GetState(index);
if (s.out1 != kRegexInvalidState) { // Split
bool matched = AddState(l, s.out);
return AddState(l, s.out1) || matched;
}
else if (!(stateSet_[index >> 5] & (1u << (index & 31)))) {
stateSet_[index >> 5] |= (1u << (index & 31));
*l.template PushUnsafe<SizeType>() = index;
}
return s.out == kRegexInvalidState; // by using PushUnsafe() above, we can ensure s is not validated due to reallocation.
}
bool MatchRange(SizeType rangeIndex, unsigned codepoint) const {
bool yes = (regex_.GetRange(rangeIndex).start & RegexType::kRangeNegationFlag) == 0;
while (rangeIndex != kRegexInvalidRange) {
const Range& r = regex_.GetRange(rangeIndex);
if (codepoint >= (r.start & ~RegexType::kRangeNegationFlag) && codepoint <= r.end)
return yes;
rangeIndex = r.next;
}
return !yes;
}
const RegexType& regex_;
Allocator* allocator_;
Allocator* ownAllocator_;
Stack<Allocator> state0_;
Stack<Allocator> state1_;
uint32_t* stateSet_;
};
typedef GenericRegex<UTF8<> > Regex; typedef GenericRegex<UTF8<> > Regex;
typedef GenericRegexSearch<Regex> RegexSearch;
} // namespace internal } // namespace internal
CEREAL_RAPIDJSON_NAMESPACE_END CEREAL_RAPIDJSON_NAMESPACE_END
#ifdef __GNUC__ #ifdef __clang__
CEREAL_RAPIDJSON_DIAG_POP CEREAL_RAPIDJSON_DIAG_POP
#endif #endif
#if defined(__clang__) || defined(_MSC_VER) #ifdef _MSC_VER
CEREAL_RAPIDJSON_DIAG_POP CEREAL_RAPIDJSON_DIAG_POP
#endif #endif

View File

@ -17,7 +17,6 @@
#include "../allocators.h" #include "../allocators.h"
#include "swap.h" #include "swap.h"
#include <cstddef>
#if defined(__clang__) #if defined(__clang__)
CEREAL_RAPIDJSON_DIAG_PUSH CEREAL_RAPIDJSON_DIAG_PUSH
@ -101,7 +100,7 @@ public:
void ShrinkToFit() { void ShrinkToFit() {
if (Empty()) { if (Empty()) {
// If the stack is empty, completely deallocate the memory. // If the stack is empty, completely deallocate the memory.
Allocator::Free(stack_); // NOLINT (+clang-analyzer-unix.Malloc) Allocator::Free(stack_);
stack_ = 0; stack_ = 0;
stackTop_ = 0; stackTop_ = 0;
stackEnd_ = 0; stackEnd_ = 0;
@ -115,7 +114,7 @@ public:
template<typename T> template<typename T>
CEREAL_RAPIDJSON_FORCEINLINE void Reserve(size_t count = 1) { CEREAL_RAPIDJSON_FORCEINLINE void Reserve(size_t count = 1) {
// Expand the stack if needed // Expand the stack if needed
if (CEREAL_RAPIDJSON_UNLIKELY(static_cast<std::ptrdiff_t>(sizeof(T) * count) > (stackEnd_ - stackTop_))) if (CEREAL_RAPIDJSON_UNLIKELY(stackTop_ + sizeof(T) * count > stackEnd_))
Expand<T>(count); Expand<T>(count);
} }
@ -127,8 +126,7 @@ public:
template<typename T> template<typename T>
CEREAL_RAPIDJSON_FORCEINLINE T* PushUnsafe(size_t count = 1) { CEREAL_RAPIDJSON_FORCEINLINE T* PushUnsafe(size_t count = 1) {
CEREAL_RAPIDJSON_ASSERT(stackTop_); CEREAL_RAPIDJSON_ASSERT(stackTop_ + sizeof(T) * count <= stackEnd_);
CEREAL_RAPIDJSON_ASSERT(static_cast<std::ptrdiff_t>(sizeof(T) * count) <= (stackEnd_ - stackTop_));
T* ret = reinterpret_cast<T*>(stackTop_); T* ret = reinterpret_cast<T*>(stackTop_);
stackTop_ += sizeof(T) * count; stackTop_ += sizeof(T) * count;
return ret; return ret;
@ -185,7 +183,7 @@ private:
size_t newCapacity; size_t newCapacity;
if (stack_ == 0) { if (stack_ == 0) {
if (!allocator_) if (!allocator_)
ownAllocator_ = allocator_ = CEREAL_RAPIDJSON_NEW(Allocator)(); ownAllocator_ = allocator_ = CEREAL_RAPIDJSON_NEW(Allocator());
newCapacity = initialCapacity_; newCapacity = initialCapacity_;
} else { } else {
newCapacity = GetCapacity(); newCapacity = GetCapacity();

View File

@ -16,7 +16,6 @@
#define CEREAL_RAPIDJSON_INTERNAL_STRFUNC_H_ #define CEREAL_RAPIDJSON_INTERNAL_STRFUNC_H_
#include "../stream.h" #include "../stream.h"
#include <cwchar>
CEREAL_RAPIDJSON_NAMESPACE_BEGIN CEREAL_RAPIDJSON_NAMESPACE_BEGIN
namespace internal { namespace internal {
@ -29,27 +28,14 @@ namespace internal {
*/ */
template <typename Ch> template <typename Ch>
inline SizeType StrLen(const Ch* s) { inline SizeType StrLen(const Ch* s) {
CEREAL_RAPIDJSON_ASSERT(s != 0);
const Ch* p = s; const Ch* p = s;
while (*p) ++p; while (*p) ++p;
return SizeType(p - s); return SizeType(p - s);
} }
template <>
inline SizeType StrLen(const char* s) {
return SizeType(std::strlen(s));
}
template <>
inline SizeType StrLen(const wchar_t* s) {
return SizeType(std::wcslen(s));
}
//! Returns number of code points in a encoded string. //! Returns number of code points in a encoded string.
template<typename Encoding> template<typename Encoding>
bool CountStringCodePoint(const typename Encoding::Ch* s, SizeType length, SizeType* outCount) { bool CountStringCodePoint(const typename Encoding::Ch* s, SizeType length, SizeType* outCount) {
CEREAL_RAPIDJSON_ASSERT(s != 0);
CEREAL_RAPIDJSON_ASSERT(outCount != 0);
GenericStringStream<Encoding> is(s); GenericStringStream<Encoding> is(s);
const typename Encoding::Ch* end = s + length; const typename Encoding::Ch* end = s + length;
SizeType count = 0; SizeType count = 0;

View File

@ -19,8 +19,6 @@
#include "biginteger.h" #include "biginteger.h"
#include "diyfp.h" #include "diyfp.h"
#include "pow10.h" #include "pow10.h"
#include <climits>
#include <limits>
CEREAL_RAPIDJSON_NAMESPACE_BEGIN CEREAL_RAPIDJSON_NAMESPACE_BEGIN
namespace internal { namespace internal {
@ -128,46 +126,46 @@ inline bool StrtodFast(double d, int p, double* result) {
} }
// Compute an approximation and see if it is within 1/2 ULP // Compute an approximation and see if it is within 1/2 ULP
inline bool StrtodDiyFp(const char* decimals, int dLen, int dExp, double* result) { inline bool StrtodDiyFp(const char* decimals, size_t length, size_t decimalPosition, int exp, double* result) {
uint64_t significand = 0; uint64_t significand = 0;
int i = 0; // 2^64 - 1 = 18446744073709551615, 1844674407370955161 = 0x1999999999999999 size_t i = 0; // 2^64 - 1 = 18446744073709551615, 1844674407370955161 = 0x1999999999999999
for (; i < dLen; i++) { for (; i < length; i++) {
if (significand > CEREAL_RAPIDJSON_UINT64_C2(0x19999999, 0x99999999) || if (significand > CEREAL_RAPIDJSON_UINT64_C2(0x19999999, 0x99999999) ||
(significand == CEREAL_RAPIDJSON_UINT64_C2(0x19999999, 0x99999999) && decimals[i] > '5')) (significand == CEREAL_RAPIDJSON_UINT64_C2(0x19999999, 0x99999999) && decimals[i] > '5'))
break; break;
significand = significand * 10u + static_cast<unsigned>(decimals[i] - '0'); significand = significand * 10u + static_cast<unsigned>(decimals[i] - '0');
} }
if (i < dLen && decimals[i] >= '5') // Rounding if (i < length && decimals[i] >= '5') // Rounding
significand++; significand++;
int remaining = dLen - i; size_t remaining = length - i;
const int kUlpShift = 3; const unsigned kUlpShift = 3;
const int kUlp = 1 << kUlpShift; const unsigned kUlp = 1 << kUlpShift;
int64_t error = (remaining == 0) ? 0 : kUlp / 2; int64_t error = (remaining == 0) ? 0 : kUlp / 2;
DiyFp v(significand, 0); DiyFp v(significand, 0);
v = v.Normalize(); v = v.Normalize();
error <<= -v.e; error <<= -v.e;
dExp += remaining; const int dExp = static_cast<int>(decimalPosition) - static_cast<int>(i) + exp;
int actualExp; int actualExp;
DiyFp cachedPower = GetCachedPower10(dExp, &actualExp); DiyFp cachedPower = GetCachedPower10(dExp, &actualExp);
if (actualExp != dExp) { if (actualExp != dExp) {
static const DiyFp kPow10[] = { static const DiyFp kPow10[] = {
DiyFp(CEREAL_RAPIDJSON_UINT64_C2(0xa0000000, 0x00000000), -60), // 10^1 DiyFp(CEREAL_RAPIDJSON_UINT64_C2(0xa0000000, 00000000), -60), // 10^1
DiyFp(CEREAL_RAPIDJSON_UINT64_C2(0xc8000000, 0x00000000), -57), // 10^2 DiyFp(CEREAL_RAPIDJSON_UINT64_C2(0xc8000000, 00000000), -57), // 10^2
DiyFp(CEREAL_RAPIDJSON_UINT64_C2(0xfa000000, 0x00000000), -54), // 10^3 DiyFp(CEREAL_RAPIDJSON_UINT64_C2(0xfa000000, 00000000), -54), // 10^3
DiyFp(CEREAL_RAPIDJSON_UINT64_C2(0x9c400000, 0x00000000), -50), // 10^4 DiyFp(CEREAL_RAPIDJSON_UINT64_C2(0x9c400000, 00000000), -50), // 10^4
DiyFp(CEREAL_RAPIDJSON_UINT64_C2(0xc3500000, 0x00000000), -47), // 10^5 DiyFp(CEREAL_RAPIDJSON_UINT64_C2(0xc3500000, 00000000), -47), // 10^5
DiyFp(CEREAL_RAPIDJSON_UINT64_C2(0xf4240000, 0x00000000), -44), // 10^6 DiyFp(CEREAL_RAPIDJSON_UINT64_C2(0xf4240000, 00000000), -44), // 10^6
DiyFp(CEREAL_RAPIDJSON_UINT64_C2(0x98968000, 0x00000000), -40) // 10^7 DiyFp(CEREAL_RAPIDJSON_UINT64_C2(0x98968000, 00000000), -40) // 10^7
}; };
int adjustment = dExp - actualExp; int adjustment = dExp - actualExp - 1;
CEREAL_RAPIDJSON_ASSERT(adjustment >= 1 && adjustment < 8); CEREAL_RAPIDJSON_ASSERT(adjustment >= 0 && adjustment < 7);
v = v * kPow10[adjustment - 1]; v = v * kPow10[adjustment];
if (dLen + adjustment > 19) // has more digits than decimal digits in 64-bit if (length + static_cast<unsigned>(adjustment)> 19u) // has more digits than decimal digits in 64-bit
error += kUlp / 2; error += kUlp / 2;
} }
@ -179,17 +177,17 @@ inline bool StrtodDiyFp(const char* decimals, int dLen, int dExp, double* result
v = v.Normalize(); v = v.Normalize();
error <<= oldExp - v.e; error <<= oldExp - v.e;
const int effectiveSignificandSize = Double::EffectiveSignificandSize(64 + v.e); const unsigned effectiveSignificandSize = Double::EffectiveSignificandSize(64 + v.e);
int precisionSize = 64 - effectiveSignificandSize; unsigned precisionSize = 64 - effectiveSignificandSize;
if (precisionSize + kUlpShift >= 64) { if (precisionSize + kUlpShift >= 64) {
int scaleExp = (precisionSize + kUlpShift) - 63; unsigned scaleExp = (precisionSize + kUlpShift) - 63;
v.f >>= scaleExp; v.f >>= scaleExp;
v.e += scaleExp; v.e += scaleExp;
error = (error >> scaleExp) + 1 + kUlp; error = (error >> scaleExp) + 1 + static_cast<int>(kUlp);
precisionSize -= scaleExp; precisionSize -= scaleExp;
} }
DiyFp rounded(v.f >> precisionSize, v.e + precisionSize); DiyFp rounded(v.f >> precisionSize, v.e + static_cast<int>(precisionSize));
const uint64_t precisionBits = (v.f & ((uint64_t(1) << precisionSize) - 1)) * kUlp; const uint64_t precisionBits = (v.f & ((uint64_t(1) << precisionSize) - 1)) * kUlp;
const uint64_t halfWay = (uint64_t(1) << (precisionSize - 1)) * kUlp; const uint64_t halfWay = (uint64_t(1) << (precisionSize - 1)) * kUlp;
if (precisionBits >= halfWay + static_cast<unsigned>(error)) { if (precisionBits >= halfWay + static_cast<unsigned>(error)) {
@ -205,9 +203,9 @@ inline bool StrtodDiyFp(const char* decimals, int dLen, int dExp, double* result
return halfWay - static_cast<unsigned>(error) >= precisionBits || precisionBits >= halfWay + static_cast<unsigned>(error); return halfWay - static_cast<unsigned>(error) >= precisionBits || precisionBits >= halfWay + static_cast<unsigned>(error);
} }
inline double StrtodBigInteger(double approx, const char* decimals, int dLen, int dExp) { inline double StrtodBigInteger(double approx, const char* decimals, size_t length, size_t decimalPosition, int exp) {
CEREAL_RAPIDJSON_ASSERT(dLen >= 0); const BigInteger dInt(decimals, length);
const BigInteger dInt(decimals, static_cast<unsigned>(dLen)); const int dExp = static_cast<int>(decimalPosition) - static_cast<int>(length) + exp;
Double a(approx); Double a(approx);
int cmp = CheckWithinHalfULP(a.Value(), dInt, dExp); int cmp = CheckWithinHalfULP(a.Value(), dInt, dExp);
if (cmp < 0) if (cmp < 0)
@ -227,61 +225,42 @@ inline double StrtodFullPrecision(double d, int p, const char* decimals, size_t
CEREAL_RAPIDJSON_ASSERT(d >= 0.0); CEREAL_RAPIDJSON_ASSERT(d >= 0.0);
CEREAL_RAPIDJSON_ASSERT(length >= 1); CEREAL_RAPIDJSON_ASSERT(length >= 1);
double result = 0.0; double result;
if (StrtodFast(d, p, &result)) if (StrtodFast(d, p, &result))
return result; return result;
CEREAL_RAPIDJSON_ASSERT(length <= INT_MAX);
int dLen = static_cast<int>(length);
CEREAL_RAPIDJSON_ASSERT(length >= decimalPosition);
CEREAL_RAPIDJSON_ASSERT(length - decimalPosition <= INT_MAX);
int dExpAdjust = static_cast<int>(length - decimalPosition);
CEREAL_RAPIDJSON_ASSERT(exp >= INT_MIN + dExpAdjust);
int dExp = exp - dExpAdjust;
// Make sure length+dExp does not overflow
CEREAL_RAPIDJSON_ASSERT(dExp <= INT_MAX - dLen);
// Trim leading zeros // Trim leading zeros
while (dLen > 0 && *decimals == '0') { while (*decimals == '0' && length > 1) {
dLen--; length--;
decimals++; decimals++;
decimalPosition--;
} }
// Trim trailing zeros // Trim trailing zeros
while (dLen > 0 && decimals[dLen - 1] == '0') { while (decimals[length - 1] == '0' && length > 1) {
dLen--; length--;
dExp++; decimalPosition--;
} exp++;
if (dLen == 0) { // Buffer only contains zeros.
return 0.0;
} }
// Trim right-most digits // Trim right-most digits
const int kMaxDecimalDigit = 767 + 1; const int kMaxDecimalDigit = 780;
if (dLen > kMaxDecimalDigit) { if (static_cast<int>(length) > kMaxDecimalDigit) {
dExp += dLen - kMaxDecimalDigit; int delta = (static_cast<int>(length) - kMaxDecimalDigit);
dLen = kMaxDecimalDigit; exp += delta;
decimalPosition -= static_cast<unsigned>(delta);
length = kMaxDecimalDigit;
} }
// If too small, underflow to zero. // If too small, underflow to zero
// Any x <= 10^-324 is interpreted as zero. if (int(length) + exp < -324)
if (dLen + dExp <= -324)
return 0.0; return 0.0;
// If too large, overflow to infinity. if (StrtodDiyFp(decimals, length, decimalPosition, exp, &result))
// Any x >= 10^309 is interpreted as +infinity.
if (dLen + dExp > 309)
return std::numeric_limits<double>::infinity();
if (StrtodDiyFp(decimals, dLen, dExp, &result))
return result; return result;
// Use approximation from StrtodDiyFp and make adjustment with BigInteger comparison // Use approximation from StrtodDiyFp and make adjustment with BigInteger comparison
return StrtodBigInteger(result, decimals, dLen, dExp); return StrtodBigInteger(result, decimals, length, decimalPosition, exp);
} }
} // namespace internal } // namespace internal

View File

@ -17,14 +17,16 @@
#include "stream.h" #include "stream.h"
#include <iosfwd> #include <iosfwd>
#include <ios>
#ifdef __clang__ #ifdef __clang__
CEREAL_RAPIDJSON_DIAG_PUSH CEREAL_RAPIDJSON_DIAG_PUSH
CEREAL_RAPIDJSON_DIAG_OFF(padded) CEREAL_RAPIDJSON_DIAG_OFF(padded)
#elif defined(_MSC_VER) #endif
#ifdef _MSC_VER
CEREAL_RAPIDJSON_DIAG_PUSH CEREAL_RAPIDJSON_DIAG_PUSH
CEREAL_RAPIDJSON_DIAG_OFF(4351) // new behavior: elements of array 'array' will be default initialized CEREAL_RAPIDJSON_DIAG_OFF(4351) // new behavior: elements of array 'array' will be default initialized
CEREAL_RAPIDJSON_DIAG_OFF(4127) // ignore assert(false) for triggering exception
#endif #endif
CEREAL_RAPIDJSON_NAMESPACE_BEGIN CEREAL_RAPIDJSON_NAMESPACE_BEGIN
@ -49,71 +51,57 @@ template <typename StreamType>
class BasicIStreamWrapper { class BasicIStreamWrapper {
public: public:
typedef typename StreamType::char_type Ch; typedef typename StreamType::char_type Ch;
BasicIStreamWrapper(StreamType& stream) : stream_(stream), count_(), peekBuffer_() {}
//! Constructor. Ch Peek() const {
/*! typename StreamType::int_type c = stream_.peek();
\param stream stream opened for read. return CEREAL_RAPIDJSON_LIKELY(c != StreamType::traits_type::eof()) ? static_cast<Ch>(c) : '\0';
*/
BasicIStreamWrapper(StreamType &stream) : stream_(stream), buffer_(peekBuffer_), bufferSize_(4), bufferLast_(0), current_(buffer_), readCount_(0), count_(0), eof_(false) {
Read();
} }
//! Constructor. Ch Take() {
/*! typename StreamType::int_type c = stream_.get();
\param stream stream opened for read. if (CEREAL_RAPIDJSON_LIKELY(c != StreamType::traits_type::eof())) {
\param buffer user-supplied buffer. count_++;
\param bufferSize size of buffer in bytes. Must >=4 bytes. return static_cast<Ch>(c);
*/ }
BasicIStreamWrapper(StreamType &stream, char* buffer, size_t bufferSize) : stream_(stream), buffer_(buffer), bufferSize_(bufferSize), bufferLast_(0), current_(buffer_), readCount_(0), count_(0), eof_(false) { else
CEREAL_RAPIDJSON_ASSERT(bufferSize >= 4); return '\0';
Read();
} }
Ch Peek() const { return *current_; } // tellg() may return -1 when failed. So we count by ourself.
Ch Take() { Ch c = *current_; Read(); return c; } size_t Tell() const { return count_; }
size_t Tell() const { return count_ + static_cast<size_t>(current_ - buffer_); }
// Not implemented Ch* PutBegin() { CEREAL_RAPIDJSON_ASSERT(false); return 0; }
void Put(Ch) { CEREAL_RAPIDJSON_ASSERT(false); } void Put(Ch) { CEREAL_RAPIDJSON_ASSERT(false); }
void Flush() { CEREAL_RAPIDJSON_ASSERT(false); } void Flush() { CEREAL_RAPIDJSON_ASSERT(false); }
Ch* PutBegin() { CEREAL_RAPIDJSON_ASSERT(false); return 0; }
size_t PutEnd(Ch*) { CEREAL_RAPIDJSON_ASSERT(false); return 0; } size_t PutEnd(Ch*) { CEREAL_RAPIDJSON_ASSERT(false); return 0; }
// For encoding detection only. // For encoding detection only.
const Ch* Peek4() const { const Ch* Peek4() const {
return (current_ + 4 - !eof_ <= bufferLast_) ? current_ : 0; CEREAL_RAPIDJSON_ASSERT(sizeof(Ch) == 1); // Only usable for byte stream.
int i;
bool hasError = false;
for (i = 0; i < 4; ++i) {
typename StreamType::int_type c = stream_.get();
if (c == StreamType::traits_type::eof()) {
hasError = true;
stream_.clear();
break;
}
peekBuffer_[i] = static_cast<Ch>(c);
}
for (--i; i >= 0; --i)
stream_.putback(peekBuffer_[i]);
return !hasError ? peekBuffer_ : 0;
} }
private: private:
BasicIStreamWrapper();
BasicIStreamWrapper(const BasicIStreamWrapper&); BasicIStreamWrapper(const BasicIStreamWrapper&);
BasicIStreamWrapper& operator=(const BasicIStreamWrapper&); BasicIStreamWrapper& operator=(const BasicIStreamWrapper&);
void Read() {
if (current_ < bufferLast_)
++current_;
else if (!eof_) {
count_ += readCount_;
readCount_ = bufferSize_;
bufferLast_ = buffer_ + readCount_ - 1;
current_ = buffer_;
if (!stream_.read(buffer_, static_cast<std::streamsize>(bufferSize_))) {
readCount_ = static_cast<size_t>(stream_.gcount());
*(bufferLast_ = buffer_ + readCount_) = '\0';
eof_ = true;
}
}
}
StreamType& stream_; StreamType& stream_;
Ch peekBuffer_[4], *buffer_; size_t count_; //!< Number of characters read. Note:
size_t bufferSize_; mutable Ch peekBuffer_[4];
Ch *bufferLast_;
Ch *current_;
size_t readCount_;
size_t count_; //!< Number of characters read
bool eof_;
}; };
typedef BasicIStreamWrapper<std::istream> IStreamWrapper; typedef BasicIStreamWrapper<std::istream> IStreamWrapper;

View File

@ -23,6 +23,11 @@ CEREAL_RAPIDJSON_DIAG_OFF(unreachable-code)
CEREAL_RAPIDJSON_DIAG_OFF(missing-noreturn) CEREAL_RAPIDJSON_DIAG_OFF(missing-noreturn)
#endif #endif
#ifdef _MSC_VER
CEREAL_RAPIDJSON_DIAG_PUSH
CEREAL_RAPIDJSON_DIAG_OFF( 4127 ) // ignore assert(false) for triggering exception
#endif
CEREAL_RAPIDJSON_NAMESPACE_BEGIN CEREAL_RAPIDJSON_NAMESPACE_BEGIN
//! Represents an in-memory input byte stream. //! Represents an in-memory input byte stream.
@ -64,7 +69,7 @@ struct MemoryStream {
CEREAL_RAPIDJSON_NAMESPACE_END CEREAL_RAPIDJSON_NAMESPACE_END
#ifdef __clang__ #if defined(__clang__) || defined(_MSC_VER)
CEREAL_RAPIDJSON_DIAG_POP CEREAL_RAPIDJSON_DIAG_POP
#endif #endif

View File

@ -1,29 +0,0 @@
ISO C9x compliant stdint.h for Microsoft Visual Studio
Based on ISO/IEC 9899:TC2 Committee draft (May 6, 2005) WG14/N1124
Copyright (c) 2006-2013 Alexander Chemeris
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
2. 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.
3. Neither the name of the product 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 AUTHOR ``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 THE AUTHOR 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.

View File

@ -21,7 +21,9 @@
#ifdef __clang__ #ifdef __clang__
CEREAL_RAPIDJSON_DIAG_PUSH CEREAL_RAPIDJSON_DIAG_PUSH
CEREAL_RAPIDJSON_DIAG_OFF(switch-enum) CEREAL_RAPIDJSON_DIAG_OFF(switch-enum)
#elif defined(_MSC_VER) #endif
#ifdef _MSC_VER
CEREAL_RAPIDJSON_DIAG_PUSH CEREAL_RAPIDJSON_DIAG_PUSH
CEREAL_RAPIDJSON_DIAG_OFF(4512) // assignment operator could not be generated CEREAL_RAPIDJSON_DIAG_OFF(4512) // assignment operator could not be generated
#endif #endif
@ -163,12 +165,7 @@ public:
GenericPointer(const Token* tokens, size_t tokenCount) : allocator_(), ownAllocator_(), nameBuffer_(), tokens_(const_cast<Token*>(tokens)), tokenCount_(tokenCount), parseErrorOffset_(), parseErrorCode_(kPointerParseErrorNone) {} GenericPointer(const Token* tokens, size_t tokenCount) : allocator_(), ownAllocator_(), nameBuffer_(), tokens_(const_cast<Token*>(tokens)), tokenCount_(tokenCount), parseErrorOffset_(), parseErrorCode_(kPointerParseErrorNone) {}
//! Copy constructor. //! Copy constructor.
GenericPointer(const GenericPointer& rhs) : allocator_(rhs.allocator_), ownAllocator_(), nameBuffer_(), tokens_(), tokenCount_(), parseErrorOffset_(), parseErrorCode_(kPointerParseErrorNone) { GenericPointer(const GenericPointer& rhs, Allocator* allocator = 0) : allocator_(allocator), ownAllocator_(), nameBuffer_(), tokens_(), tokenCount_(), parseErrorOffset_(), parseErrorCode_(kPointerParseErrorNone) {
*this = rhs;
}
//! Copy constructor.
GenericPointer(const GenericPointer& rhs, Allocator* allocator) : allocator_(allocator), ownAllocator_(), nameBuffer_(), tokens_(), tokenCount_(), parseErrorOffset_(), parseErrorCode_(kPointerParseErrorNone) {
*this = rhs; *this = rhs;
} }
@ -200,36 +197,6 @@ public:
return *this; return *this;
} }
//! Swap the content of this pointer with an other.
/*!
\param other The pointer to swap with.
\note Constant complexity.
*/
GenericPointer& Swap(GenericPointer& other) CEREAL_RAPIDJSON_NOEXCEPT {
internal::Swap(allocator_, other.allocator_);
internal::Swap(ownAllocator_, other.ownAllocator_);
internal::Swap(nameBuffer_, other.nameBuffer_);
internal::Swap(tokens_, other.tokens_);
internal::Swap(tokenCount_, other.tokenCount_);
internal::Swap(parseErrorOffset_, other.parseErrorOffset_);
internal::Swap(parseErrorCode_, other.parseErrorCode_);
return *this;
}
//! free-standing swap function helper
/*!
Helper function to enable support for common swap implementation pattern based on \c std::swap:
\code
void swap(MyClass& a, MyClass& b) {
using std::swap;
swap(a.pointer, b.pointer);
// ...
}
\endcode
\see Swap()
*/
friend inline void swap(GenericPointer& a, GenericPointer& b) CEREAL_RAPIDJSON_NOEXCEPT { a.Swap(b); }
//@} //@}
//!@name Append token //!@name Append token
@ -273,7 +240,7 @@ public:
template <typename T> template <typename T>
CEREAL_RAPIDJSON_DISABLEIF_RETURN((internal::NotExpr<internal::IsSame<typename internal::RemoveConst<T>::Type, Ch> >), (GenericPointer)) CEREAL_RAPIDJSON_DISABLEIF_RETURN((internal::NotExpr<internal::IsSame<typename internal::RemoveConst<T>::Type, Ch> >), (GenericPointer))
Append(T* name, Allocator* allocator = 0) const { Append(T* name, Allocator* allocator = 0) const {
return Append(name, internal::StrLen(name), allocator); return Append(name, StrLen(name), allocator);
} }
#if CEREAL_RAPIDJSON_HAS_STDSTRING #if CEREAL_RAPIDJSON_HAS_STDSTRING
@ -307,7 +274,7 @@ public:
else { else {
Ch name[21]; Ch name[21];
for (size_t i = 0; i <= length; i++) for (size_t i = 0; i <= length; i++)
name[i] = static_cast<Ch>(buffer[i]); name[i] = buffer[i];
Token token = { name, length, index }; Token token = { name, length, index };
return Append(token, allocator); return Append(token, allocator);
} }
@ -386,33 +353,6 @@ public:
*/ */
bool operator!=(const GenericPointer& rhs) const { return !(*this == rhs); } bool operator!=(const GenericPointer& rhs) const { return !(*this == rhs); }
//! Less than operator.
/*!
\note Invalid pointers are always greater than valid ones.
*/
bool operator<(const GenericPointer& rhs) const {
if (!IsValid())
return false;
if (!rhs.IsValid())
return true;
if (tokenCount_ != rhs.tokenCount_)
return tokenCount_ < rhs.tokenCount_;
for (size_t i = 0; i < tokenCount_; i++) {
if (tokens_[i].index != rhs.tokens_[i].index)
return tokens_[i].index < rhs.tokens_[i].index;
if (tokens_[i].length != rhs.tokens_[i].length)
return tokens_[i].length < rhs.tokens_[i].length;
if (int cmp = std::memcmp(tokens_[i].name, rhs.tokens_[i].name, sizeof(Ch) * tokens_[i].length))
return cmp < 0;
}
return false;
}
//@} //@}
//!@name Stringify //!@name Stringify
@ -592,14 +532,14 @@ public:
*/ */
ValueType& GetWithDefault(ValueType& root, const ValueType& defaultValue, typename ValueType::AllocatorType& allocator) const { ValueType& GetWithDefault(ValueType& root, const ValueType& defaultValue, typename ValueType::AllocatorType& allocator) const {
bool alreadyExist; bool alreadyExist;
ValueType& v = Create(root, allocator, &alreadyExist); Value& v = Create(root, allocator, &alreadyExist);
return alreadyExist ? v : v.CopyFrom(defaultValue, allocator); return alreadyExist ? v : v.CopyFrom(defaultValue, allocator);
} }
//! Query a value in a subtree with default null-terminated string. //! Query a value in a subtree with default null-terminated string.
ValueType& GetWithDefault(ValueType& root, const Ch* defaultValue, typename ValueType::AllocatorType& allocator) const { ValueType& GetWithDefault(ValueType& root, const Ch* defaultValue, typename ValueType::AllocatorType& allocator) const {
bool alreadyExist; bool alreadyExist;
ValueType& v = Create(root, allocator, &alreadyExist); Value& v = Create(root, allocator, &alreadyExist);
return alreadyExist ? v : v.SetString(defaultValue, allocator); return alreadyExist ? v : v.SetString(defaultValue, allocator);
} }
@ -607,7 +547,7 @@ public:
//! Query a value in a subtree with default std::basic_string. //! Query a value in a subtree with default std::basic_string.
ValueType& GetWithDefault(ValueType& root, const std::basic_string<Ch>& defaultValue, typename ValueType::AllocatorType& allocator) const { ValueType& GetWithDefault(ValueType& root, const std::basic_string<Ch>& defaultValue, typename ValueType::AllocatorType& allocator) const {
bool alreadyExist; bool alreadyExist;
ValueType& v = Create(root, allocator, &alreadyExist); Value& v = Create(root, allocator, &alreadyExist);
return alreadyExist ? v : v.SetString(defaultValue, allocator); return alreadyExist ? v : v.SetString(defaultValue, allocator);
} }
#endif #endif
@ -818,7 +758,7 @@ private:
*/ */
Ch* CopyFromRaw(const GenericPointer& rhs, size_t extraToken = 0, size_t extraNameBufferSize = 0) { Ch* CopyFromRaw(const GenericPointer& rhs, size_t extraToken = 0, size_t extraNameBufferSize = 0) {
if (!allocator_) // allocator is independently owned. if (!allocator_) // allocator is independently owned.
ownAllocator_ = allocator_ = CEREAL_RAPIDJSON_NEW(Allocator)(); ownAllocator_ = allocator_ = CEREAL_RAPIDJSON_NEW(Allocator());
size_t nameBufferSize = rhs.tokenCount_; // null terminators for tokens size_t nameBufferSize = rhs.tokenCount_; // null terminators for tokens
for (Token *t = rhs.tokens_; t != rhs.tokens_ + rhs.tokenCount_; ++t) for (Token *t = rhs.tokens_; t != rhs.tokens_ + rhs.tokenCount_; ++t)
@ -866,7 +806,7 @@ private:
// Create own allocator if user did not supply. // Create own allocator if user did not supply.
if (!allocator_) if (!allocator_)
ownAllocator_ = allocator_ = CEREAL_RAPIDJSON_NEW(Allocator)(); ownAllocator_ = allocator_ = CEREAL_RAPIDJSON_NEW(Allocator());
// Count number of '/' as tokenCount // Count number of '/' as tokenCount
tokenCount_ = 0; tokenCount_ = 0;
@ -1089,8 +1029,8 @@ private:
unsigned char u = static_cast<unsigned char>(c); unsigned char u = static_cast<unsigned char>(c);
static const char hexDigits[16] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' }; static const char hexDigits[16] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
os_.Put('%'); os_.Put('%');
os_.Put(static_cast<typename OutputStream::Ch>(hexDigits[u >> 4])); os_.Put(hexDigits[u >> 4]);
os_.Put(static_cast<typename OutputStream::Ch>(hexDigits[u & 15])); os_.Put(hexDigits[u & 15]);
} }
private: private:
OutputStream& os_; OutputStream& os_;
@ -1407,7 +1347,11 @@ bool EraseValueByPointer(T& root, const CharType(&source)[N]) {
CEREAL_RAPIDJSON_NAMESPACE_END CEREAL_RAPIDJSON_NAMESPACE_END
#if defined(__clang__) || defined(_MSC_VER) #ifdef __clang__
CEREAL_RAPIDJSON_DIAG_POP
#endif
#ifdef _MSC_VER
CEREAL_RAPIDJSON_DIAG_POP CEREAL_RAPIDJSON_DIAG_POP
#endif #endif

View File

@ -22,11 +22,6 @@ CEREAL_RAPIDJSON_DIAG_PUSH
CEREAL_RAPIDJSON_DIAG_OFF(effc++) CEREAL_RAPIDJSON_DIAG_OFF(effc++)
#endif #endif
#if defined(__clang__)
CEREAL_RAPIDJSON_DIAG_PUSH
CEREAL_RAPIDJSON_DIAG_OFF(c++98-compat)
#endif
CEREAL_RAPIDJSON_NAMESPACE_BEGIN CEREAL_RAPIDJSON_NAMESPACE_BEGIN
//! Combination of PrettyWriter format flags. //! Combination of PrettyWriter format flags.
@ -39,7 +34,7 @@ enum PrettyFormatOptions {
//! Writer with indentation and spacing. //! Writer with indentation and spacing.
/*! /*!
\tparam OutputStream Type of output os. \tparam OutputStream Type of ouptut os.
\tparam SourceEncoding Encoding of source string. \tparam SourceEncoding Encoding of source string.
\tparam TargetEncoding Encoding of output stream. \tparam TargetEncoding Encoding of output stream.
\tparam StackAllocator Type of allocator for allocating memory of stack. \tparam StackAllocator Type of allocator for allocating memory of stack.
@ -47,7 +42,7 @@ enum PrettyFormatOptions {
template<typename OutputStream, typename SourceEncoding = UTF8<>, typename TargetEncoding = UTF8<>, typename StackAllocator = CrtAllocator, unsigned writeFlags = kWriteDefaultFlags> template<typename OutputStream, typename SourceEncoding = UTF8<>, typename TargetEncoding = UTF8<>, typename StackAllocator = CrtAllocator, unsigned writeFlags = kWriteDefaultFlags>
class PrettyWriter : public Writer<OutputStream, SourceEncoding, TargetEncoding, StackAllocator, writeFlags> { class PrettyWriter : public Writer<OutputStream, SourceEncoding, TargetEncoding, StackAllocator, writeFlags> {
public: public:
typedef Writer<OutputStream, SourceEncoding, TargetEncoding, StackAllocator, writeFlags> Base; typedef Writer<OutputStream, SourceEncoding, TargetEncoding, StackAllocator> Base;
typedef typename Base::Ch Ch; typedef typename Base::Ch Ch;
//! Constructor //! Constructor
@ -62,11 +57,6 @@ public:
explicit PrettyWriter(StackAllocator* allocator = 0, size_t levelDepth = Base::kDefaultLevelDepth) : explicit PrettyWriter(StackAllocator* allocator = 0, size_t levelDepth = Base::kDefaultLevelDepth) :
Base(allocator, levelDepth), indentChar_(' '), indentCharCount_(4) {} Base(allocator, levelDepth), indentChar_(' '), indentCharCount_(4) {}
#if CEREAL_RAPIDJSON_HAS_CXX11_RVALUE_REFS
PrettyWriter(PrettyWriter&& rhs) :
Base(std::forward<PrettyWriter>(rhs)), indentChar_(rhs.indentChar_), indentCharCount_(rhs.indentCharCount_), formatOptions_(rhs.formatOptions_) {}
#endif
//! Set custom indentation. //! Set custom indentation.
/*! \param indentChar Character for indentation. Must be whitespace character (' ', '\\t', '\\n', '\\r'). /*! \param indentChar Character for indentation. Must be whitespace character (' ', '\\t', '\\n', '\\r').
\param indentCharCount Number of indent characters for each indentation level. \param indentCharCount Number of indent characters for each indentation level.
@ -92,26 +82,24 @@ public:
*/ */
//@{ //@{
bool Null() { PrettyPrefix(kNullType); return Base::EndValue(Base::WriteNull()); } bool Null() { PrettyPrefix(kNullType); return Base::WriteNull(); }
bool Bool(bool b) { PrettyPrefix(b ? kTrueType : kFalseType); return Base::EndValue(Base::WriteBool(b)); } bool Bool(bool b) { PrettyPrefix(b ? kTrueType : kFalseType); return Base::WriteBool(b); }
bool Int(int i) { PrettyPrefix(kNumberType); return Base::EndValue(Base::WriteInt(i)); } bool Int(int i) { PrettyPrefix(kNumberType); return Base::WriteInt(i); }
bool Uint(unsigned u) { PrettyPrefix(kNumberType); return Base::EndValue(Base::WriteUint(u)); } bool Uint(unsigned u) { PrettyPrefix(kNumberType); return Base::WriteUint(u); }
bool Int64(int64_t i64) { PrettyPrefix(kNumberType); return Base::EndValue(Base::WriteInt64(i64)); } bool Int64(int64_t i64) { PrettyPrefix(kNumberType); return Base::WriteInt64(i64); }
bool Uint64(uint64_t u64) { PrettyPrefix(kNumberType); return Base::EndValue(Base::WriteUint64(u64)); } bool Uint64(uint64_t u64) { PrettyPrefix(kNumberType); return Base::WriteUint64(u64); }
bool Double(double d) { PrettyPrefix(kNumberType); return Base::EndValue(Base::WriteDouble(d)); } bool Double(double d) { PrettyPrefix(kNumberType); return Base::WriteDouble(d); }
bool RawNumber(const Ch* str, SizeType length, bool copy = false) { bool RawNumber(const Ch* str, SizeType length, bool copy = false) {
CEREAL_RAPIDJSON_ASSERT(str != 0);
(void)copy; (void)copy;
PrettyPrefix(kNumberType); PrettyPrefix(kNumberType);
return Base::EndValue(Base::WriteString(str, length)); return Base::WriteString(str, length);
} }
bool String(const Ch* str, SizeType length, bool copy = false) { bool String(const Ch* str, SizeType length, bool copy = false) {
CEREAL_RAPIDJSON_ASSERT(str != 0);
(void)copy; (void)copy;
PrettyPrefix(kStringType); PrettyPrefix(kStringType);
return Base::EndValue(Base::WriteString(str, length)); return Base::WriteString(str, length);
} }
#if CEREAL_RAPIDJSON_HAS_STDSTRING #if CEREAL_RAPIDJSON_HAS_STDSTRING
@ -136,21 +124,19 @@ public:
bool EndObject(SizeType memberCount = 0) { bool EndObject(SizeType memberCount = 0) {
(void)memberCount; (void)memberCount;
CEREAL_RAPIDJSON_ASSERT(Base::level_stack_.GetSize() >= sizeof(typename Base::Level)); // not inside an Object CEREAL_RAPIDJSON_ASSERT(Base::level_stack_.GetSize() >= sizeof(typename Base::Level));
CEREAL_RAPIDJSON_ASSERT(!Base::level_stack_.template Top<typename Base::Level>()->inArray); // currently inside an Array, not Object CEREAL_RAPIDJSON_ASSERT(!Base::level_stack_.template Top<typename Base::Level>()->inArray);
CEREAL_RAPIDJSON_ASSERT(0 == Base::level_stack_.template Top<typename Base::Level>()->valueCount % 2); // Object has a Key without a Value
bool empty = Base::level_stack_.template Pop<typename Base::Level>(1)->valueCount == 0; bool empty = Base::level_stack_.template Pop<typename Base::Level>(1)->valueCount == 0;
if (!empty) { if (!empty) {
Base::os_->Put('\n'); Base::os_->Put('\n');
WriteIndent(); WriteIndent();
} }
bool ret = Base::EndValue(Base::WriteEndObject()); bool ret = Base::WriteEndObject();
(void)ret; (void)ret;
CEREAL_RAPIDJSON_ASSERT(ret == true); CEREAL_RAPIDJSON_ASSERT(ret == true);
if (Base::level_stack_.Empty()) // end of json text if (Base::level_stack_.Empty()) // end of json text
Base::Flush(); Base::os_->Flush();
return true; return true;
} }
@ -170,11 +156,11 @@ public:
Base::os_->Put('\n'); Base::os_->Put('\n');
WriteIndent(); WriteIndent();
} }
bool ret = Base::EndValue(Base::WriteEndArray()); bool ret = Base::WriteEndArray();
(void)ret; (void)ret;
CEREAL_RAPIDJSON_ASSERT(ret == true); CEREAL_RAPIDJSON_ASSERT(ret == true);
if (Base::level_stack_.Empty()) // end of json text if (Base::level_stack_.Empty()) // end of json text
Base::Flush(); Base::os_->Flush();
return true; return true;
} }
@ -198,11 +184,7 @@ public:
\param type Type of the root of json. \param type Type of the root of json.
\note When using PrettyWriter::RawValue(), the result json may not be indented correctly. \note When using PrettyWriter::RawValue(), the result json may not be indented correctly.
*/ */
bool RawValue(const Ch* json, size_t length, Type type) { bool RawValue(const Ch* json, size_t length, Type type) { PrettyPrefix(type); return Base::WriteRawValue(json, length); }
CEREAL_RAPIDJSON_ASSERT(json != 0);
PrettyPrefix(type);
return Base::EndValue(Base::WriteRawValue(json, length));
}
protected: protected:
void PrettyPrefix(Type type) { void PrettyPrefix(Type type) {
@ -251,7 +233,7 @@ protected:
void WriteIndent() { void WriteIndent() {
size_t count = (Base::level_stack_.GetSize() / sizeof(typename Base::Level)) * indentCharCount_; size_t count = (Base::level_stack_.GetSize() / sizeof(typename Base::Level)) * indentCharCount_;
PutN(*Base::os_, static_cast<typename OutputStream::Ch>(indentChar_), count); PutN(*Base::os_, static_cast<typename TargetEncoding::Ch>(indentChar_), count);
} }
Ch indentChar_; Ch indentChar_;
@ -266,10 +248,6 @@ private:
CEREAL_RAPIDJSON_NAMESPACE_END CEREAL_RAPIDJSON_NAMESPACE_END
#if defined(__clang__)
CEREAL_RAPIDJSON_DIAG_POP
#endif
#ifdef __GNUC__ #ifdef __GNUC__
CEREAL_RAPIDJSON_DIAG_POP CEREAL_RAPIDJSON_DIAG_POP
#endif #endif

View File

@ -26,7 +26,7 @@
Some RapidJSON features are configurable to adapt the library to a wide Some RapidJSON features are configurable to adapt the library to a wide
variety of platforms, environments and usage scenarios. Most of the variety of platforms, environments and usage scenarios. Most of the
features can be configured in terms of overridden or predefined features can be configured in terms of overriden or predefined
preprocessor macros at compile-time. preprocessor macros at compile-time.
Some additional customization is available in the \ref CEREAL_RAPIDJSON_ERRORS APIs. Some additional customization is available in the \ref CEREAL_RAPIDJSON_ERRORS APIs.
@ -49,11 +49,6 @@
// token stringification // token stringification
#define CEREAL_RAPIDJSON_STRINGIFY(x) CEREAL_RAPIDJSON_DO_STRINGIFY(x) #define CEREAL_RAPIDJSON_STRINGIFY(x) CEREAL_RAPIDJSON_DO_STRINGIFY(x)
#define CEREAL_RAPIDJSON_DO_STRINGIFY(x) #x #define CEREAL_RAPIDJSON_DO_STRINGIFY(x) #x
// token concatenation
#define CEREAL_RAPIDJSON_JOIN(X, Y) CEREAL_RAPIDJSON_DO_JOIN(X, Y)
#define CEREAL_RAPIDJSON_DO_JOIN(X, Y) CEREAL_RAPIDJSON_DO_JOIN2(X, Y)
#define CEREAL_RAPIDJSON_DO_JOIN2(X, Y) X##Y
//!@endcond //!@endcond
/*! \def CEREAL_RAPIDJSON_MAJOR_VERSION /*! \def CEREAL_RAPIDJSON_MAJOR_VERSION
@ -73,8 +68,8 @@
\brief Version of RapidJSON in "<major>.<minor>.<patch>" string format. \brief Version of RapidJSON in "<major>.<minor>.<patch>" string format.
*/ */
#define CEREAL_RAPIDJSON_MAJOR_VERSION 1 #define CEREAL_RAPIDJSON_MAJOR_VERSION 1
#define CEREAL_RAPIDJSON_MINOR_VERSION 1 #define CEREAL_RAPIDJSON_MINOR_VERSION 0
#define CEREAL_RAPIDJSON_PATCH_VERSION 0 #define CEREAL_RAPIDJSON_PATCH_VERSION 2
#define CEREAL_RAPIDJSON_VERSION_STRING \ #define CEREAL_RAPIDJSON_VERSION_STRING \
CEREAL_RAPIDJSON_STRINGIFY(CEREAL_RAPIDJSON_MAJOR_VERSION.CEREAL_RAPIDJSON_MINOR_VERSION.CEREAL_RAPIDJSON_PATCH_VERSION) CEREAL_RAPIDJSON_STRINGIFY(CEREAL_RAPIDJSON_MAJOR_VERSION.CEREAL_RAPIDJSON_MINOR_VERSION.CEREAL_RAPIDJSON_PATCH_VERSION)
@ -219,7 +214,7 @@
# elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ # elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
# define CEREAL_RAPIDJSON_ENDIAN CEREAL_RAPIDJSON_BIGENDIAN # define CEREAL_RAPIDJSON_ENDIAN CEREAL_RAPIDJSON_BIGENDIAN
# else # else
# error Unknown machine endianness detected. User needs to define CEREAL_RAPIDJSON_ENDIAN. # error Unknown machine endianess detected. User needs to define CEREAL_RAPIDJSON_ENDIAN.
# endif // __BYTE_ORDER__ # endif // __BYTE_ORDER__
// Detect with GLIBC's endian.h // Detect with GLIBC's endian.h
# elif defined(__GLIBC__) # elif defined(__GLIBC__)
@ -229,7 +224,7 @@
# elif (__BYTE_ORDER == __BIG_ENDIAN) # elif (__BYTE_ORDER == __BIG_ENDIAN)
# define CEREAL_RAPIDJSON_ENDIAN CEREAL_RAPIDJSON_BIGENDIAN # define CEREAL_RAPIDJSON_ENDIAN CEREAL_RAPIDJSON_BIGENDIAN
# else # else
# error Unknown machine endianness detected. User needs to define CEREAL_RAPIDJSON_ENDIAN. # error Unknown machine endianess detected. User needs to define CEREAL_RAPIDJSON_ENDIAN.
# endif // __GLIBC__ # endif // __GLIBC__
// Detect with _LITTLE_ENDIAN and _BIG_ENDIAN macro // Detect with _LITTLE_ENDIAN and _BIG_ENDIAN macro
# elif defined(_LITTLE_ENDIAN) && !defined(_BIG_ENDIAN) # elif defined(_LITTLE_ENDIAN) && !defined(_BIG_ENDIAN)
@ -241,12 +236,12 @@
# define CEREAL_RAPIDJSON_ENDIAN CEREAL_RAPIDJSON_BIGENDIAN # define CEREAL_RAPIDJSON_ENDIAN CEREAL_RAPIDJSON_BIGENDIAN
# elif defined(__i386__) || defined(__alpha__) || defined(__ia64) || defined(__ia64__) || defined(_M_IX86) || defined(_M_IA64) || defined(_M_ALPHA) || defined(__amd64) || defined(__amd64__) || defined(_M_AMD64) || defined(__x86_64) || defined(__x86_64__) || defined(_M_X64) || defined(__bfin__) # elif defined(__i386__) || defined(__alpha__) || defined(__ia64) || defined(__ia64__) || defined(_M_IX86) || defined(_M_IA64) || defined(_M_ALPHA) || defined(__amd64) || defined(__amd64__) || defined(_M_AMD64) || defined(__x86_64) || defined(__x86_64__) || defined(_M_X64) || defined(__bfin__)
# define CEREAL_RAPIDJSON_ENDIAN CEREAL_RAPIDJSON_LITTLEENDIAN # define CEREAL_RAPIDJSON_ENDIAN CEREAL_RAPIDJSON_LITTLEENDIAN
# elif defined(_MSC_VER) && (defined(_M_ARM) || defined(_M_ARM64)) # elif defined(_MSC_VER) && defined(_M_ARM)
# define CEREAL_RAPIDJSON_ENDIAN CEREAL_RAPIDJSON_LITTLEENDIAN # define CEREAL_RAPIDJSON_ENDIAN CEREAL_RAPIDJSON_LITTLEENDIAN
# elif defined(CEREAL_RAPIDJSON_DOXYGEN_RUNNING) # elif defined(CEREAL_RAPIDJSON_DOXYGEN_RUNNING)
# define CEREAL_RAPIDJSON_ENDIAN # define CEREAL_RAPIDJSON_ENDIAN
# else # else
# error Unknown machine endianness detected. User needs to define CEREAL_RAPIDJSON_ENDIAN. # error Unknown machine endianess detected. User needs to define CEREAL_RAPIDJSON_ENDIAN.
# endif # endif
#endif // CEREAL_RAPIDJSON_ENDIAN #endif // CEREAL_RAPIDJSON_ENDIAN
@ -269,11 +264,16 @@
/*! \ingroup CEREAL_RAPIDJSON_CONFIG /*! \ingroup CEREAL_RAPIDJSON_CONFIG
\param x pointer to align \param x pointer to align
Some machines require strict data alignment. The default is 8 bytes. Some machines require strict data alignment. Currently the default uses 4 bytes
alignment on 32-bit platforms and 8 bytes alignment for 64-bit platforms.
User can customize by defining the CEREAL_RAPIDJSON_ALIGN function macro. User can customize by defining the CEREAL_RAPIDJSON_ALIGN function macro.
*/ */
#ifndef CEREAL_RAPIDJSON_ALIGN #ifndef CEREAL_RAPIDJSON_ALIGN
#define CEREAL_RAPIDJSON_ALIGN(x) (((x) + static_cast<size_t>(7u)) & ~static_cast<size_t>(7u)) #if CEREAL_RAPIDJSON_64BIT == 1
#define CEREAL_RAPIDJSON_ALIGN(x) (((x) + static_cast<uint64_t>(7u)) & ~static_cast<uint64_t>(7u))
#else
#define CEREAL_RAPIDJSON_ALIGN(x) (((x) + 3u) & ~3u)
#endif
#endif #endif
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
@ -320,17 +320,17 @@
#endif #endif
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
// CEREAL_RAPIDJSON_SSE2/CEREAL_RAPIDJSON_SSE42/CEREAL_RAPIDJSON_NEON/CEREAL_RAPIDJSON_SIMD // CEREAL_RAPIDJSON_SSE2/CEREAL_RAPIDJSON_SSE42/CEREAL_RAPIDJSON_SIMD
/*! \def CEREAL_RAPIDJSON_SIMD /*! \def CEREAL_RAPIDJSON_SIMD
\ingroup CEREAL_RAPIDJSON_CONFIG \ingroup CEREAL_RAPIDJSON_CONFIG
\brief Enable SSE2/SSE4.2/Neon optimization. \brief Enable SSE2/SSE4.2 optimization.
RapidJSON supports optimized implementations for some parsing operations RapidJSON supports optimized implementations for some parsing operations
based on the SSE2, SSE4.2 or NEon SIMD extensions on modern Intel based on the SSE2 or SSE4.2 SIMD extensions on modern Intel-compatible
or ARM compatible processors. processors.
To enable these optimizations, three different symbols can be defined; To enable these optimizations, two different symbols can be defined;
\code \code
// Enable SSE2 optimization. // Enable SSE2 optimization.
#define CEREAL_RAPIDJSON_SSE2 #define CEREAL_RAPIDJSON_SSE2
@ -339,17 +339,13 @@
#define CEREAL_RAPIDJSON_SSE42 #define CEREAL_RAPIDJSON_SSE42
\endcode \endcode
// Enable ARM Neon optimization. \c CEREAL_RAPIDJSON_SSE42 takes precedence, if both are defined.
#define CEREAL_RAPIDJSON_NEON
\endcode
\c CEREAL_RAPIDJSON_SSE42 takes precedence over SSE2, if both are defined.
If any of these symbols is defined, RapidJSON defines the macro If any of these symbols is defined, RapidJSON defines the macro
\c CEREAL_RAPIDJSON_SIMD to indicate the availability of the optimized code. \c CEREAL_RAPIDJSON_SIMD to indicate the availability of the optimized code.
*/ */
#if defined(CEREAL_RAPIDJSON_SSE2) || defined(CEREAL_RAPIDJSON_SSE42) \ #if defined(CEREAL_RAPIDJSON_SSE2) || defined(CEREAL_RAPIDJSON_SSE42) \
|| defined(CEREAL_RAPIDJSON_NEON) || defined(CEREAL_RAPIDJSON_DOXYGEN_RUNNING) || defined(CEREAL_RAPIDJSON_DOXYGEN_RUNNING)
#define CEREAL_RAPIDJSON_SIMD #define CEREAL_RAPIDJSON_SIMD
#endif #endif
@ -409,15 +405,7 @@ CEREAL_RAPIDJSON_NAMESPACE_END
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
// CEREAL_RAPIDJSON_STATIC_ASSERT // CEREAL_RAPIDJSON_STATIC_ASSERT
// Prefer C++11 static_assert, if available // Adopt from boost
#ifndef CEREAL_RAPIDJSON_STATIC_ASSERT
#if __cplusplus >= 201103L || ( defined(_MSC_VER) && _MSC_VER >= 1800 )
#define CEREAL_RAPIDJSON_STATIC_ASSERT(x) \
static_assert(x, CEREAL_RAPIDJSON_STRINGIFY(x))
#endif // C++11
#endif // CEREAL_RAPIDJSON_STATIC_ASSERT
// Adopt C++03 implementation from boost
#ifndef CEREAL_RAPIDJSON_STATIC_ASSERT #ifndef CEREAL_RAPIDJSON_STATIC_ASSERT
#ifndef __clang__ #ifndef __clang__
//!@cond CEREAL_RAPIDJSON_HIDDEN_FROM_DOXYGEN //!@cond CEREAL_RAPIDJSON_HIDDEN_FROM_DOXYGEN
@ -425,10 +413,14 @@ CEREAL_RAPIDJSON_NAMESPACE_END
CEREAL_RAPIDJSON_NAMESPACE_BEGIN CEREAL_RAPIDJSON_NAMESPACE_BEGIN
template <bool x> struct STATIC_ASSERTION_FAILURE; template <bool x> struct STATIC_ASSERTION_FAILURE;
template <> struct STATIC_ASSERTION_FAILURE<true> { enum { value = 1 }; }; template <> struct STATIC_ASSERTION_FAILURE<true> { enum { value = 1 }; };
template <size_t x> struct StaticAssertTest {}; template<int x> struct StaticAssertTest {};
CEREAL_RAPIDJSON_NAMESPACE_END CEREAL_RAPIDJSON_NAMESPACE_END
#if defined(__GNUC__) || defined(__clang__) #define CEREAL_RAPIDJSON_JOIN(X, Y) CEREAL_RAPIDJSON_DO_JOIN(X, Y)
#define CEREAL_RAPIDJSON_DO_JOIN(X, Y) CEREAL_RAPIDJSON_DO_JOIN2(X, Y)
#define CEREAL_RAPIDJSON_DO_JOIN2(X, Y) X##Y
#if defined(__GNUC__)
#define CEREAL_RAPIDJSON_STATIC_ASSERT_UNUSED_ATTRIBUTE __attribute__((unused)) #define CEREAL_RAPIDJSON_STATIC_ASSERT_UNUSED_ATTRIBUTE __attribute__((unused))
#else #else
#define CEREAL_RAPIDJSON_STATIC_ASSERT_UNUSED_ATTRIBUTE #define CEREAL_RAPIDJSON_STATIC_ASSERT_UNUSED_ATTRIBUTE
@ -446,7 +438,7 @@ CEREAL_RAPIDJSON_NAMESPACE_END
typedef ::CEREAL_RAPIDJSON_NAMESPACE::StaticAssertTest< \ typedef ::CEREAL_RAPIDJSON_NAMESPACE::StaticAssertTest< \
sizeof(::CEREAL_RAPIDJSON_NAMESPACE::STATIC_ASSERTION_FAILURE<bool(x) >)> \ sizeof(::CEREAL_RAPIDJSON_NAMESPACE::STATIC_ASSERTION_FAILURE<bool(x) >)> \
CEREAL_RAPIDJSON_JOIN(StaticAssertTypedef, __LINE__) CEREAL_RAPIDJSON_STATIC_ASSERT_UNUSED_ATTRIBUTE CEREAL_RAPIDJSON_JOIN(StaticAssertTypedef, __LINE__) CEREAL_RAPIDJSON_STATIC_ASSERT_UNUSED_ATTRIBUTE
#endif // CEREAL_RAPIDJSON_STATIC_ASSERT #endif
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
// CEREAL_RAPIDJSON_LIKELY, CEREAL_RAPIDJSON_UNLIKELY // CEREAL_RAPIDJSON_LIKELY, CEREAL_RAPIDJSON_UNLIKELY
@ -538,14 +530,13 @@ CEREAL_RAPIDJSON_NAMESPACE_END
#ifndef CEREAL_RAPIDJSON_HAS_CXX11_RVALUE_REFS #ifndef CEREAL_RAPIDJSON_HAS_CXX11_RVALUE_REFS
#if defined(__clang__) #if defined(__clang__)
#if __has_feature(cxx_rvalue_references) && \ #if __has_feature(cxx_rvalue_references) && \
(defined(_MSC_VER) || defined(_LIBCPP_VERSION) || defined(__GLIBCXX__) && __GLIBCXX__ >= 20080306) (defined(_LIBCPP_VERSION) || defined(__GLIBCXX__) && __GLIBCXX__ >= 20080306)
#define CEREAL_RAPIDJSON_HAS_CXX11_RVALUE_REFS 1 #define CEREAL_RAPIDJSON_HAS_CXX11_RVALUE_REFS 1
#else #else
#define CEREAL_RAPIDJSON_HAS_CXX11_RVALUE_REFS 0 #define CEREAL_RAPIDJSON_HAS_CXX11_RVALUE_REFS 0
#endif #endif
#elif (defined(CEREAL_RAPIDJSON_GNUC) && (CEREAL_RAPIDJSON_GNUC >= CEREAL_RAPIDJSON_VERSION_CODE(4,3,0)) && defined(__GXX_EXPERIMENTAL_CXX0X__)) || \ #elif (defined(CEREAL_RAPIDJSON_GNUC) && (CEREAL_RAPIDJSON_GNUC >= CEREAL_RAPIDJSON_VERSION_CODE(4,3,0)) && defined(__GXX_EXPERIMENTAL_CXX0X__)) || \
(defined(_MSC_VER) && _MSC_VER >= 1600) || \ (defined(_MSC_VER) && _MSC_VER >= 1600)
(defined(__SUNPRO_CC) && __SUNPRO_CC >= 0x5140 && defined(__GXX_EXPERIMENTAL_CXX0X__))
#define CEREAL_RAPIDJSON_HAS_CXX11_RVALUE_REFS 1 #define CEREAL_RAPIDJSON_HAS_CXX11_RVALUE_REFS 1
#else #else
@ -556,9 +547,8 @@ CEREAL_RAPIDJSON_NAMESPACE_END
#ifndef CEREAL_RAPIDJSON_HAS_CXX11_NOEXCEPT #ifndef CEREAL_RAPIDJSON_HAS_CXX11_NOEXCEPT
#if defined(__clang__) #if defined(__clang__)
#define CEREAL_RAPIDJSON_HAS_CXX11_NOEXCEPT __has_feature(cxx_noexcept) #define CEREAL_RAPIDJSON_HAS_CXX11_NOEXCEPT __has_feature(cxx_noexcept)
#elif (defined(CEREAL_RAPIDJSON_GNUC) && (CEREAL_RAPIDJSON_GNUC >= CEREAL_RAPIDJSON_VERSION_CODE(4,6,0)) && defined(__GXX_EXPERIMENTAL_CXX0X__)) || \ #elif (defined(CEREAL_RAPIDJSON_GNUC) && (CEREAL_RAPIDJSON_GNUC >= CEREAL_RAPIDJSON_VERSION_CODE(4,6,0)) && defined(__GXX_EXPERIMENTAL_CXX0X__))
(defined(_MSC_VER) && _MSC_VER >= 1900) || \ // (defined(_MSC_VER) && _MSC_VER >= ????) // not yet supported
(defined(__SUNPRO_CC) && __SUNPRO_CC >= 0x5140 && defined(__GXX_EXPERIMENTAL_CXX0X__))
#define CEREAL_RAPIDJSON_HAS_CXX11_NOEXCEPT 1 #define CEREAL_RAPIDJSON_HAS_CXX11_NOEXCEPT 1
#else #else
#define CEREAL_RAPIDJSON_HAS_CXX11_NOEXCEPT 0 #define CEREAL_RAPIDJSON_HAS_CXX11_NOEXCEPT 0
@ -572,19 +562,14 @@ CEREAL_RAPIDJSON_NAMESPACE_END
// no automatic detection, yet // no automatic detection, yet
#ifndef CEREAL_RAPIDJSON_HAS_CXX11_TYPETRAITS #ifndef CEREAL_RAPIDJSON_HAS_CXX11_TYPETRAITS
#if (defined(_MSC_VER) && _MSC_VER >= 1700)
#define CEREAL_RAPIDJSON_HAS_CXX11_TYPETRAITS 1
#else
#define CEREAL_RAPIDJSON_HAS_CXX11_TYPETRAITS 0 #define CEREAL_RAPIDJSON_HAS_CXX11_TYPETRAITS 0
#endif #endif
#endif
#ifndef CEREAL_RAPIDJSON_HAS_CXX11_RANGE_FOR #ifndef CEREAL_RAPIDJSON_HAS_CXX11_RANGE_FOR
#if defined(__clang__) #if defined(__clang__)
#define CEREAL_RAPIDJSON_HAS_CXX11_RANGE_FOR __has_feature(cxx_range_for) #define CEREAL_RAPIDJSON_HAS_CXX11_RANGE_FOR __has_feature(cxx_range_for)
#elif (defined(CEREAL_RAPIDJSON_GNUC) && (CEREAL_RAPIDJSON_GNUC >= CEREAL_RAPIDJSON_VERSION_CODE(4,6,0)) && defined(__GXX_EXPERIMENTAL_CXX0X__)) || \ #elif (defined(CEREAL_RAPIDJSON_GNUC) && (CEREAL_RAPIDJSON_GNUC >= CEREAL_RAPIDJSON_VERSION_CODE(4,3,0)) && defined(__GXX_EXPERIMENTAL_CXX0X__)) || \
(defined(_MSC_VER) && _MSC_VER >= 1700) || \ (defined(_MSC_VER) && _MSC_VER >= 1700)
(defined(__SUNPRO_CC) && __SUNPRO_CC >= 0x5140 && defined(__GXX_EXPERIMENTAL_CXX0X__))
#define CEREAL_RAPIDJSON_HAS_CXX11_RANGE_FOR 1 #define CEREAL_RAPIDJSON_HAS_CXX11_RANGE_FOR 1
#else #else
#define CEREAL_RAPIDJSON_HAS_CXX11_RANGE_FOR 0 #define CEREAL_RAPIDJSON_HAS_CXX11_RANGE_FOR 0
@ -593,38 +578,12 @@ CEREAL_RAPIDJSON_NAMESPACE_END
//!@endcond //!@endcond
//! Assertion (in non-throwing contexts).
/*! \ingroup CEREAL_RAPIDJSON_CONFIG
Some functions provide a \c noexcept guarantee, if the compiler supports it.
In these cases, the \ref CEREAL_RAPIDJSON_ASSERT macro cannot be overridden to
throw an exception. This macro adds a separate customization point for
such cases.
Defaults to C \c assert() (as \ref CEREAL_RAPIDJSON_ASSERT), if \c noexcept is
supported, and to \ref CEREAL_RAPIDJSON_ASSERT otherwise.
*/
///////////////////////////////////////////////////////////////////////////////
// CEREAL_RAPIDJSON_NOEXCEPT_ASSERT
#ifndef CEREAL_RAPIDJSON_NOEXCEPT_ASSERT
#ifdef CEREAL_RAPIDJSON_ASSERT_THROWS
#if CEREAL_RAPIDJSON_HAS_CXX11_NOEXCEPT
#define CEREAL_RAPIDJSON_NOEXCEPT_ASSERT(x)
#else
#define CEREAL_RAPIDJSON_NOEXCEPT_ASSERT(x) CEREAL_RAPIDJSON_ASSERT(x)
#endif // CEREAL_RAPIDJSON_HAS_CXX11_NOEXCEPT
#else
#define CEREAL_RAPIDJSON_NOEXCEPT_ASSERT(x) CEREAL_RAPIDJSON_ASSERT(x)
#endif // CEREAL_RAPIDJSON_ASSERT_THROWS
#endif // CEREAL_RAPIDJSON_NOEXCEPT_ASSERT
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
// new/delete // new/delete
#ifndef CEREAL_RAPIDJSON_NEW #ifndef CEREAL_RAPIDJSON_NEW
///! customization point for global \c new ///! customization point for global \c new
#define CEREAL_RAPIDJSON_NEW(TypeName) new TypeName #define CEREAL_RAPIDJSON_NEW(x) new x
#endif #endif
#ifndef CEREAL_RAPIDJSON_DELETE #ifndef CEREAL_RAPIDJSON_DELETE
///! customization point for global \c delete ///! customization point for global \c delete

View File

@ -33,8 +33,12 @@
#include <nmmintrin.h> #include <nmmintrin.h>
#elif defined(CEREAL_RAPIDJSON_SSE2) #elif defined(CEREAL_RAPIDJSON_SSE2)
#include <emmintrin.h> #include <emmintrin.h>
#elif defined(CEREAL_RAPIDJSON_NEON) #endif
#include <arm_neon.h>
#ifdef _MSC_VER
CEREAL_RAPIDJSON_DIAG_PUSH
CEREAL_RAPIDJSON_DIAG_OFF(4127) // conditional expression is constant
CEREAL_RAPIDJSON_DIAG_OFF(4702) // unreachable code
#endif #endif
#ifdef __clang__ #ifdef __clang__
@ -42,10 +46,6 @@ CEREAL_RAPIDJSON_DIAG_PUSH
CEREAL_RAPIDJSON_DIAG_OFF(old-style-cast) CEREAL_RAPIDJSON_DIAG_OFF(old-style-cast)
CEREAL_RAPIDJSON_DIAG_OFF(padded) CEREAL_RAPIDJSON_DIAG_OFF(padded)
CEREAL_RAPIDJSON_DIAG_OFF(switch-enum) CEREAL_RAPIDJSON_DIAG_OFF(switch-enum)
#elif defined(_MSC_VER)
CEREAL_RAPIDJSON_DIAG_PUSH
CEREAL_RAPIDJSON_DIAG_OFF(4127) // conditional expression is constant
CEREAL_RAPIDJSON_DIAG_OFF(4702) // unreachable code
#endif #endif
#ifdef __GNUC__ #ifdef __GNUC__
@ -299,9 +299,16 @@ inline const char *SkipWhitespace_SIMD(const char* p) {
for (;; p += 16) { for (;; p += 16) {
const __m128i s = _mm_load_si128(reinterpret_cast<const __m128i *>(p)); const __m128i s = _mm_load_si128(reinterpret_cast<const __m128i *>(p));
const int r = _mm_cmpistri(w, s, _SIDD_UBYTE_OPS | _SIDD_CMP_EQUAL_ANY | _SIDD_LEAST_SIGNIFICANT | _SIDD_NEGATIVE_POLARITY); const int r = _mm_cvtsi128_si32(_mm_cmpistrm(w, s, _SIDD_UBYTE_OPS | _SIDD_CMP_EQUAL_ANY | _SIDD_BIT_MASK | _SIDD_NEGATIVE_POLARITY));
if (r != 16) // some of characters is non-whitespace if (r != 0) { // some of characters is non-whitespace
return p + r; #ifdef _MSC_VER // Find the index of first non-whitespace
unsigned long offset;
_BitScanForward(&offset, r);
return p + offset;
#else
return p + __builtin_ffs(r) - 1;
#endif
}
} }
} }
@ -318,9 +325,16 @@ inline const char *SkipWhitespace_SIMD(const char* p, const char* end) {
for (; p <= end - 16; p += 16) { for (; p <= end - 16; p += 16) {
const __m128i s = _mm_loadu_si128(reinterpret_cast<const __m128i *>(p)); const __m128i s = _mm_loadu_si128(reinterpret_cast<const __m128i *>(p));
const int r = _mm_cmpistri(w, s, _SIDD_UBYTE_OPS | _SIDD_CMP_EQUAL_ANY | _SIDD_LEAST_SIGNIFICANT | _SIDD_NEGATIVE_POLARITY); const int r = _mm_cvtsi128_si32(_mm_cmpistrm(w, s, _SIDD_UBYTE_OPS | _SIDD_CMP_EQUAL_ANY | _SIDD_BIT_MASK | _SIDD_NEGATIVE_POLARITY));
if (r != 16) // some of characters is non-whitespace if (r != 0) { // some of characters is non-whitespace
return p + r; #ifdef _MSC_VER // Find the index of first non-whitespace
unsigned long offset;
_BitScanForward(&offset, r);
return p + offset;
#else
return p + __builtin_ffs(r) - 1;
#endif
}
} }
return SkipWhitespace(p, end); return SkipWhitespace(p, end);
@ -411,92 +425,7 @@ inline const char *SkipWhitespace_SIMD(const char* p, const char* end) {
return SkipWhitespace(p, end); return SkipWhitespace(p, end);
} }
#elif defined(CEREAL_RAPIDJSON_NEON) #endif // CEREAL_RAPIDJSON_SSE2
//! Skip whitespace with ARM Neon instructions, testing 16 8-byte characters at once.
inline const char *SkipWhitespace_SIMD(const char* p) {
// Fast return for single non-whitespace
if (*p == ' ' || *p == '\n' || *p == '\r' || *p == '\t')
++p;
else
return p;
// 16-byte align to the next boundary
const char* nextAligned = reinterpret_cast<const char*>((reinterpret_cast<size_t>(p) + 15) & static_cast<size_t>(~15));
while (p != nextAligned)
if (*p == ' ' || *p == '\n' || *p == '\r' || *p == '\t')
++p;
else
return p;
const uint8x16_t w0 = vmovq_n_u8(' ');
const uint8x16_t w1 = vmovq_n_u8('\n');
const uint8x16_t w2 = vmovq_n_u8('\r');
const uint8x16_t w3 = vmovq_n_u8('\t');
for (;; p += 16) {
const uint8x16_t s = vld1q_u8(reinterpret_cast<const uint8_t *>(p));
uint8x16_t x = vceqq_u8(s, w0);
x = vorrq_u8(x, vceqq_u8(s, w1));
x = vorrq_u8(x, vceqq_u8(s, w2));
x = vorrq_u8(x, vceqq_u8(s, w3));
x = vmvnq_u8(x); // Negate
x = vrev64q_u8(x); // Rev in 64
uint64_t low = vgetq_lane_u64(reinterpret_cast<uint64x2_t>(x), 0); // extract
uint64_t high = vgetq_lane_u64(reinterpret_cast<uint64x2_t>(x), 1); // extract
if (low == 0) {
if (high != 0) {
int lz =__builtin_clzll(high);;
return p + 8 + (lz >> 3);
}
} else {
int lz = __builtin_clzll(low);;
return p + (lz >> 3);
}
}
}
inline const char *SkipWhitespace_SIMD(const char* p, const char* end) {
// Fast return for single non-whitespace
if (p != end && (*p == ' ' || *p == '\n' || *p == '\r' || *p == '\t'))
++p;
else
return p;
const uint8x16_t w0 = vmovq_n_u8(' ');
const uint8x16_t w1 = vmovq_n_u8('\n');
const uint8x16_t w2 = vmovq_n_u8('\r');
const uint8x16_t w3 = vmovq_n_u8('\t');
for (; p <= end - 16; p += 16) {
const uint8x16_t s = vld1q_u8(reinterpret_cast<const uint8_t *>(p));
uint8x16_t x = vceqq_u8(s, w0);
x = vorrq_u8(x, vceqq_u8(s, w1));
x = vorrq_u8(x, vceqq_u8(s, w2));
x = vorrq_u8(x, vceqq_u8(s, w3));
x = vmvnq_u8(x); // Negate
x = vrev64q_u8(x); // Rev in 64
uint64_t low = vgetq_lane_u64(reinterpret_cast<uint64x2_t>(x), 0); // extract
uint64_t high = vgetq_lane_u64(reinterpret_cast<uint64x2_t>(x), 1); // extract
if (low == 0) {
if (high != 0) {
int lz = __builtin_clzll(high);
return p + 8 + (lz >> 3);
}
} else {
int lz = __builtin_clzll(low);
return p + (lz >> 3);
}
}
return SkipWhitespace(p, end);
}
#endif // CEREAL_RAPIDJSON_NEON
#ifdef CEREAL_RAPIDJSON_SIMD #ifdef CEREAL_RAPIDJSON_SIMD
//! Template function specialization for InsituStringStream //! Template function specialization for InsituStringStream
@ -542,8 +471,7 @@ public:
/*! \param stackAllocator Optional allocator for allocating stack memory. (Only use for non-destructive parsing) /*! \param stackAllocator 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) \param stackCapacity stack capacity in bytes for storing a single decoded string. (Only use for non-destructive parsing)
*/ */
GenericReader(StackAllocator* stackAllocator = 0, size_t stackCapacity = kDefaultStackCapacity) : GenericReader(StackAllocator* stackAllocator = 0, size_t stackCapacity = kDefaultStackCapacity) : stack_(stackAllocator, stackCapacity), parseResult_() {}
stack_(stackAllocator, stackCapacity), parseResult_(), state_(IterativeParsingStartState) {}
//! Parse JSON text. //! Parse JSON text.
/*! \tparam parseFlags Combination of \ref ParseFlag. /*! \tparam parseFlags Combination of \ref ParseFlag.
@ -599,84 +527,7 @@ public:
return Parse<kParseDefaultFlags>(is, handler); return Parse<kParseDefaultFlags>(is, handler);
} }
//! Initialize JSON text token-by-token parsing //! Whether a parse error has occured in the last parsing.
/*!
*/
void IterativeParseInit() {
parseResult_.Clear();
state_ = IterativeParsingStartState;
}
//! Parse one token from JSON text
/*! \tparam InputStream Type of input stream, implementing Stream concept
\tparam Handler Type of handler, implementing Handler concept.
\param is Input stream to be parsed.
\param handler The handler to receive events.
\return Whether the parsing is successful.
*/
template <unsigned parseFlags, typename InputStream, typename Handler>
bool IterativeParseNext(InputStream& is, Handler& handler) {
while (CEREAL_RAPIDJSON_LIKELY(is.Peek() != '\0')) {
SkipWhitespaceAndComments<parseFlags>(is);
Token t = Tokenize(is.Peek());
IterativeParsingState n = Predict(state_, t);
IterativeParsingState d = Transit<parseFlags>(state_, t, n, is, handler);
// If we've finished or hit an error...
if (CEREAL_RAPIDJSON_UNLIKELY(IsIterativeParsingCompleteState(d))) {
// Report errors.
if (d == IterativeParsingErrorState) {
HandleError(state_, is);
return false;
}
// Transition to the finish state.
CEREAL_RAPIDJSON_ASSERT(d == IterativeParsingFinishState);
state_ = d;
// If StopWhenDone is not set...
if (!(parseFlags & kParseStopWhenDoneFlag)) {
// ... and extra non-whitespace data is found...
SkipWhitespaceAndComments<parseFlags>(is);
if (is.Peek() != '\0') {
// ... this is considered an error.
HandleError(state_, is);
return false;
}
}
// Success! We are done!
return true;
}
// Transition to the new state.
state_ = d;
// If we parsed anything other than a delimiter, we invoked the handler, so we can return true now.
if (!IsIterativeParsingDelimiterState(n))
return true;
}
// We reached the end of file.
stack_.Clear();
if (state_ != IterativeParsingFinishState) {
HandleError(state_, is);
return false;
}
return true;
}
//! Check if token-by-token parsing JSON text is complete
/*! \return Whether the JSON has been fully decoded.
*/
CEREAL_RAPIDJSON_FORCEINLINE bool IterativeParseComplete() const {
return IsIterativeParsingCompleteState(state_);
}
//! Whether a parse error has occurred in the last parsing.
bool HasParseError() const { return parseResult_.IsError(); } bool HasParseError() const { return parseResult_.IsError(); }
//! Get the \ref ParseErrorCode of last parsing. //! Get the \ref ParseErrorCode of last parsing.
@ -724,7 +575,7 @@ private:
} }
} }
else if (CEREAL_RAPIDJSON_LIKELY(Consume(is, '/'))) else if (CEREAL_RAPIDJSON_LIKELY(Consume(is, '/')))
while (is.Peek() != '\0' && is.Take() != '\n') {} while (is.Peek() != '\0' && is.Take() != '\n');
else else
CEREAL_RAPIDJSON_PARSE_ERROR(kParseErrorUnspecificSyntaxError, is.Tell()); CEREAL_RAPIDJSON_PARSE_ERROR(kParseErrorUnspecificSyntaxError, is.Tell());
@ -899,7 +750,7 @@ private:
return false; return false;
} }
// Helper function to parse four hexadecimal digits in \uXXXX in ParseString(). // Helper function to parse four hexidecimal digits in \uXXXX in ParseString().
template<typename InputStream> template<typename InputStream>
unsigned ParseHex4(InputStream& is, size_t escapeOffset) { unsigned ParseHex4(InputStream& is, size_t escapeOffset) {
unsigned codepoint = 0; unsigned codepoint = 0;
@ -1006,7 +857,7 @@ private:
Ch c = is.Peek(); Ch c = is.Peek();
if (CEREAL_RAPIDJSON_UNLIKELY(c == '\\')) { // Escape if (CEREAL_RAPIDJSON_UNLIKELY(c == '\\')) { // Escape
size_t escapeOffset = is.Tell(); // For invalid escaping, report the initial '\\' as error offset size_t escapeOffset = is.Tell(); // For invalid escaping, report the inital '\\' as error offset
is.Take(); is.Take();
Ch e = is.Peek(); Ch e = is.Peek();
if ((sizeof(Ch) == 1 || unsigned(e) < 256) && CEREAL_RAPIDJSON_LIKELY(escape[static_cast<unsigned char>(e)])) { if ((sizeof(Ch) == 1 || unsigned(e) < 256) && CEREAL_RAPIDJSON_LIKELY(escape[static_cast<unsigned char>(e)])) {
@ -1041,7 +892,7 @@ private:
if (c == '\0') if (c == '\0')
CEREAL_RAPIDJSON_PARSE_ERROR(kParseErrorStringMissQuotationMark, is.Tell()); CEREAL_RAPIDJSON_PARSE_ERROR(kParseErrorStringMissQuotationMark, is.Tell());
else else
CEREAL_RAPIDJSON_PARSE_ERROR(kParseErrorStringInvalidEncoding, is.Tell()); CEREAL_RAPIDJSON_PARSE_ERROR(kParseErrorStringEscapeInvalid, is.Tell());
} }
else { else {
size_t offset = is.Tell(); size_t offset = is.Tell();
@ -1076,7 +927,7 @@ private:
// The rest of string using SIMD // The rest of string using SIMD
static const char dquote[16] = { '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"' }; static const char dquote[16] = { '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"' };
static const char bslash[16] = { '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\' }; static const char bslash[16] = { '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\' };
static const char space[16] = { 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F }; static const char space[16] = { 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19 };
const __m128i dq = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&dquote[0])); const __m128i dq = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&dquote[0]));
const __m128i bs = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&bslash[0])); const __m128i bs = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&bslash[0]));
const __m128i sp = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&space[0])); const __m128i sp = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&space[0]));
@ -1085,7 +936,7 @@ private:
const __m128i s = _mm_load_si128(reinterpret_cast<const __m128i *>(p)); const __m128i s = _mm_load_si128(reinterpret_cast<const __m128i *>(p));
const __m128i t1 = _mm_cmpeq_epi8(s, dq); const __m128i t1 = _mm_cmpeq_epi8(s, dq);
const __m128i t2 = _mm_cmpeq_epi8(s, bs); const __m128i t2 = _mm_cmpeq_epi8(s, bs);
const __m128i t3 = _mm_cmpeq_epi8(_mm_max_epu8(s, sp), sp); // s < 0x20 <=> max(s, 0x1F) == 0x1F const __m128i t3 = _mm_cmpeq_epi8(_mm_max_epu8(s, sp), sp); // s < 0x20 <=> max(s, 0x19) == 0x19
const __m128i x = _mm_or_si128(_mm_or_si128(t1, t2), t3); const __m128i x = _mm_or_si128(_mm_or_si128(t1, t2), t3);
unsigned short r = static_cast<unsigned short>(_mm_movemask_epi8(x)); unsigned short r = static_cast<unsigned short>(_mm_movemask_epi8(x));
if (CEREAL_RAPIDJSON_UNLIKELY(r != 0)) { // some of characters is escaped if (CEREAL_RAPIDJSON_UNLIKELY(r != 0)) { // some of characters is escaped
@ -1097,13 +948,11 @@ private:
#else #else
length = static_cast<SizeType>(__builtin_ffs(r) - 1); length = static_cast<SizeType>(__builtin_ffs(r) - 1);
#endif #endif
if (length != 0) {
char* q = reinterpret_cast<char*>(os.Push(length)); char* q = reinterpret_cast<char*>(os.Push(length));
for (size_t i = 0; i < length; i++) for (size_t i = 0; i < length; i++)
q[i] = p[i]; q[i] = p[i];
p += length; p += length;
}
break; break;
} }
_mm_storeu_si128(reinterpret_cast<__m128i *>(os.Push(16)), s); _mm_storeu_si128(reinterpret_cast<__m128i *>(os.Push(16)), s);
@ -1139,7 +988,7 @@ private:
// The rest of string using SIMD // The rest of string using SIMD
static const char dquote[16] = { '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"' }; static const char dquote[16] = { '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"' };
static const char bslash[16] = { '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\' }; static const char bslash[16] = { '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\' };
static const char space[16] = { 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F }; static const char space[16] = { 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19 };
const __m128i dq = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&dquote[0])); const __m128i dq = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&dquote[0]));
const __m128i bs = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&bslash[0])); const __m128i bs = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&bslash[0]));
const __m128i sp = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&space[0])); const __m128i sp = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&space[0]));
@ -1148,7 +997,7 @@ private:
const __m128i s = _mm_load_si128(reinterpret_cast<const __m128i *>(p)); const __m128i s = _mm_load_si128(reinterpret_cast<const __m128i *>(p));
const __m128i t1 = _mm_cmpeq_epi8(s, dq); const __m128i t1 = _mm_cmpeq_epi8(s, dq);
const __m128i t2 = _mm_cmpeq_epi8(s, bs); const __m128i t2 = _mm_cmpeq_epi8(s, bs);
const __m128i t3 = _mm_cmpeq_epi8(_mm_max_epu8(s, sp), sp); // s < 0x20 <=> max(s, 0x1F) == 0x1F const __m128i t3 = _mm_cmpeq_epi8(_mm_max_epu8(s, sp), sp); // s < 0x20 <=> max(s, 0x19) == 0x19
const __m128i x = _mm_or_si128(_mm_or_si128(t1, t2), t3); const __m128i x = _mm_or_si128(_mm_or_si128(t1, t2), t3);
unsigned short r = static_cast<unsigned short>(_mm_movemask_epi8(x)); unsigned short r = static_cast<unsigned short>(_mm_movemask_epi8(x));
if (CEREAL_RAPIDJSON_UNLIKELY(r != 0)) { // some of characters is escaped if (CEREAL_RAPIDJSON_UNLIKELY(r != 0)) { // some of characters is escaped
@ -1187,7 +1036,7 @@ private:
// The rest of string using SIMD // The rest of string using SIMD
static const char dquote[16] = { '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"' }; static const char dquote[16] = { '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"' };
static const char bslash[16] = { '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\' }; static const char bslash[16] = { '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\' };
static const char space[16] = { 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F }; static const char space[16] = { 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19 };
const __m128i dq = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&dquote[0])); const __m128i dq = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&dquote[0]));
const __m128i bs = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&bslash[0])); const __m128i bs = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&bslash[0]));
const __m128i sp = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&space[0])); const __m128i sp = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&space[0]));
@ -1196,7 +1045,7 @@ private:
const __m128i s = _mm_load_si128(reinterpret_cast<const __m128i *>(p)); const __m128i s = _mm_load_si128(reinterpret_cast<const __m128i *>(p));
const __m128i t1 = _mm_cmpeq_epi8(s, dq); const __m128i t1 = _mm_cmpeq_epi8(s, dq);
const __m128i t2 = _mm_cmpeq_epi8(s, bs); const __m128i t2 = _mm_cmpeq_epi8(s, bs);
const __m128i t3 = _mm_cmpeq_epi8(_mm_max_epu8(s, sp), sp); // s < 0x20 <=> max(s, 0x1F) == 0x1F const __m128i t3 = _mm_cmpeq_epi8(_mm_max_epu8(s, sp), sp); // s < 0x20 <=> max(s, 0x19) == 0x19
const __m128i x = _mm_or_si128(_mm_or_si128(t1, t2), t3); const __m128i x = _mm_or_si128(_mm_or_si128(t1, t2), t3);
unsigned short r = static_cast<unsigned short>(_mm_movemask_epi8(x)); unsigned short r = static_cast<unsigned short>(_mm_movemask_epi8(x));
if (CEREAL_RAPIDJSON_UNLIKELY(r != 0)) { // some of characters is escaped if (CEREAL_RAPIDJSON_UNLIKELY(r != 0)) { // some of characters is escaped
@ -1215,180 +1064,7 @@ private:
is.src_ = is.dst_ = p; is.src_ = is.dst_ = p;
} }
#elif defined(CEREAL_RAPIDJSON_NEON) #endif
// StringStream -> StackStream<char>
static CEREAL_RAPIDJSON_FORCEINLINE void ScanCopyUnescapedString(StringStream& is, StackStream<char>& os) {
const char* p = is.src_;
// Scan one by one until alignment (unaligned load may cross page boundary and cause crash)
const char* nextAligned = reinterpret_cast<const char*>((reinterpret_cast<size_t>(p) + 15) & static_cast<size_t>(~15));
while (p != nextAligned)
if (CEREAL_RAPIDJSON_UNLIKELY(*p == '\"') || CEREAL_RAPIDJSON_UNLIKELY(*p == '\\') || CEREAL_RAPIDJSON_UNLIKELY(static_cast<unsigned>(*p) < 0x20)) {
is.src_ = p;
return;
}
else
os.Put(*p++);
// The rest of string using SIMD
const uint8x16_t s0 = vmovq_n_u8('"');
const uint8x16_t s1 = vmovq_n_u8('\\');
const uint8x16_t s2 = vmovq_n_u8('\b');
const uint8x16_t s3 = vmovq_n_u8(32);
for (;; p += 16) {
const uint8x16_t s = vld1q_u8(reinterpret_cast<const uint8_t *>(p));
uint8x16_t x = vceqq_u8(s, s0);
x = vorrq_u8(x, vceqq_u8(s, s1));
x = vorrq_u8(x, vceqq_u8(s, s2));
x = vorrq_u8(x, vcltq_u8(s, s3));
x = vrev64q_u8(x); // Rev in 64
uint64_t low = vgetq_lane_u64(reinterpret_cast<uint64x2_t>(x), 0); // extract
uint64_t high = vgetq_lane_u64(reinterpret_cast<uint64x2_t>(x), 1); // extract
SizeType length = 0;
bool escaped = false;
if (low == 0) {
if (high != 0) {
unsigned lz = (unsigned)__builtin_clzll(high);;
length = 8 + (lz >> 3);
escaped = true;
}
} else {
unsigned lz = (unsigned)__builtin_clzll(low);;
length = lz >> 3;
escaped = true;
}
if (CEREAL_RAPIDJSON_UNLIKELY(escaped)) { // some of characters is escaped
if (length != 0) {
char* q = reinterpret_cast<char*>(os.Push(length));
for (size_t i = 0; i < length; i++)
q[i] = p[i];
p += length;
}
break;
}
vst1q_u8(reinterpret_cast<uint8_t *>(os.Push(16)), s);
}
is.src_ = p;
}
// InsituStringStream -> InsituStringStream
static CEREAL_RAPIDJSON_FORCEINLINE void ScanCopyUnescapedString(InsituStringStream& is, InsituStringStream& os) {
CEREAL_RAPIDJSON_ASSERT(&is == &os);
(void)os;
if (is.src_ == is.dst_) {
SkipUnescapedString(is);
return;
}
char* p = is.src_;
char *q = is.dst_;
// Scan one by one until alignment (unaligned load may cross page boundary and cause crash)
const char* nextAligned = reinterpret_cast<const char*>((reinterpret_cast<size_t>(p) + 15) & static_cast<size_t>(~15));
while (p != nextAligned)
if (CEREAL_RAPIDJSON_UNLIKELY(*p == '\"') || CEREAL_RAPIDJSON_UNLIKELY(*p == '\\') || CEREAL_RAPIDJSON_UNLIKELY(static_cast<unsigned>(*p) < 0x20)) {
is.src_ = p;
is.dst_ = q;
return;
}
else
*q++ = *p++;
// The rest of string using SIMD
const uint8x16_t s0 = vmovq_n_u8('"');
const uint8x16_t s1 = vmovq_n_u8('\\');
const uint8x16_t s2 = vmovq_n_u8('\b');
const uint8x16_t s3 = vmovq_n_u8(32);
for (;; p += 16, q += 16) {
const uint8x16_t s = vld1q_u8(reinterpret_cast<uint8_t *>(p));
uint8x16_t x = vceqq_u8(s, s0);
x = vorrq_u8(x, vceqq_u8(s, s1));
x = vorrq_u8(x, vceqq_u8(s, s2));
x = vorrq_u8(x, vcltq_u8(s, s3));
x = vrev64q_u8(x); // Rev in 64
uint64_t low = vgetq_lane_u64(reinterpret_cast<uint64x2_t>(x), 0); // extract
uint64_t high = vgetq_lane_u64(reinterpret_cast<uint64x2_t>(x), 1); // extract
SizeType length = 0;
bool escaped = false;
if (low == 0) {
if (high != 0) {
unsigned lz = (unsigned)__builtin_clzll(high);
length = 8 + (lz >> 3);
escaped = true;
}
} else {
unsigned lz = (unsigned)__builtin_clzll(low);
length = lz >> 3;
escaped = true;
}
if (CEREAL_RAPIDJSON_UNLIKELY(escaped)) { // some of characters is escaped
for (const char* pend = p + length; p != pend; ) {
*q++ = *p++;
}
break;
}
vst1q_u8(reinterpret_cast<uint8_t *>(q), s);
}
is.src_ = p;
is.dst_ = q;
}
// When read/write pointers are the same for insitu stream, just skip unescaped characters
static CEREAL_RAPIDJSON_FORCEINLINE void SkipUnescapedString(InsituStringStream& is) {
CEREAL_RAPIDJSON_ASSERT(is.src_ == is.dst_);
char* p = is.src_;
// Scan one by one until alignment (unaligned load may cross page boundary and cause crash)
const char* nextAligned = reinterpret_cast<const char*>((reinterpret_cast<size_t>(p) + 15) & static_cast<size_t>(~15));
for (; p != nextAligned; p++)
if (CEREAL_RAPIDJSON_UNLIKELY(*p == '\"') || CEREAL_RAPIDJSON_UNLIKELY(*p == '\\') || CEREAL_RAPIDJSON_UNLIKELY(static_cast<unsigned>(*p) < 0x20)) {
is.src_ = is.dst_ = p;
return;
}
// The rest of string using SIMD
const uint8x16_t s0 = vmovq_n_u8('"');
const uint8x16_t s1 = vmovq_n_u8('\\');
const uint8x16_t s2 = vmovq_n_u8('\b');
const uint8x16_t s3 = vmovq_n_u8(32);
for (;; p += 16) {
const uint8x16_t s = vld1q_u8(reinterpret_cast<uint8_t *>(p));
uint8x16_t x = vceqq_u8(s, s0);
x = vorrq_u8(x, vceqq_u8(s, s1));
x = vorrq_u8(x, vceqq_u8(s, s2));
x = vorrq_u8(x, vcltq_u8(s, s3));
x = vrev64q_u8(x); // Rev in 64
uint64_t low = vgetq_lane_u64(reinterpret_cast<uint64x2_t>(x), 0); // extract
uint64_t high = vgetq_lane_u64(reinterpret_cast<uint64x2_t>(x), 1); // extract
if (low == 0) {
if (high != 0) {
int lz = __builtin_clzll(high);
p += 8 + (lz >> 3);
break;
}
} else {
int lz = __builtin_clzll(low);
p += lz >> 3;
break;
}
}
is.src_ = is.dst_ = p;
}
#endif // CEREAL_RAPIDJSON_NEON
template<typename InputStream, bool backup, bool pushOnTake> template<typename InputStream, bool backup, bool pushOnTake>
class NumberStream; class NumberStream;
@ -1399,6 +1075,7 @@ private:
typedef typename InputStream::Ch Ch; typedef typename InputStream::Ch Ch;
NumberStream(GenericReader& reader, InputStream& s) : is(s) { (void)reader; } NumberStream(GenericReader& reader, InputStream& s) : is(s) { (void)reader; }
~NumberStream() {}
CEREAL_RAPIDJSON_FORCEINLINE Ch Peek() const { return is.Peek(); } CEREAL_RAPIDJSON_FORCEINLINE Ch Peek() const { return is.Peek(); }
CEREAL_RAPIDJSON_FORCEINLINE Ch TakePush() { return is.Take(); } CEREAL_RAPIDJSON_FORCEINLINE Ch TakePush() { return is.Take(); }
@ -1420,6 +1097,7 @@ private:
typedef NumberStream<InputStream, false, false> Base; typedef NumberStream<InputStream, false, false> Base;
public: public:
NumberStream(GenericReader& reader, InputStream& s) : Base(reader, s), stackStream(reader.stack_) {} NumberStream(GenericReader& reader, InputStream& s) : Base(reader, s), stackStream(reader.stack_) {}
~NumberStream() {}
CEREAL_RAPIDJSON_FORCEINLINE Ch TakePush() { CEREAL_RAPIDJSON_FORCEINLINE Ch TakePush() {
stackStream.Put(static_cast<char>(Base::is.Peek())); stackStream.Put(static_cast<char>(Base::is.Peek()));
@ -1446,6 +1124,7 @@ private:
typedef NumberStream<InputStream, true, false> Base; typedef NumberStream<InputStream, true, false> Base;
public: public:
NumberStream(GenericReader& reader, InputStream& is) : Base(reader, is) {} NumberStream(GenericReader& reader, InputStream& is) : Base(reader, is) {}
~NumberStream() {}
CEREAL_RAPIDJSON_FORCEINLINE Ch Take() { return Base::TakePush(); } CEREAL_RAPIDJSON_FORCEINLINE Ch Take() { return Base::TakePush(); }
}; };
@ -1506,28 +1185,19 @@ private:
} }
// Parse NaN or Infinity here // Parse NaN or Infinity here
else if ((parseFlags & kParseNanAndInfFlag) && CEREAL_RAPIDJSON_LIKELY((s.Peek() == 'I' || s.Peek() == 'N'))) { else if ((parseFlags & kParseNanAndInfFlag) && CEREAL_RAPIDJSON_LIKELY((s.Peek() == 'I' || s.Peek() == 'N'))) {
if (Consume(s, 'N')) { useNanOrInf = true;
if (Consume(s, 'a') && Consume(s, 'N')) { if (CEREAL_RAPIDJSON_LIKELY(Consume(s, 'N') && Consume(s, 'a') && Consume(s, 'N'))) {
d = std::numeric_limits<double>::quiet_NaN(); d = std::numeric_limits<double>::quiet_NaN();
useNanOrInf = true;
} }
} else if (CEREAL_RAPIDJSON_LIKELY(Consume(s, 'I') && Consume(s, 'n') && Consume(s, 'f'))) {
else if (CEREAL_RAPIDJSON_LIKELY(Consume(s, 'I'))) {
if (Consume(s, 'n') && Consume(s, 'f')) {
d = (minus ? -std::numeric_limits<double>::infinity() : std::numeric_limits<double>::infinity()); d = (minus ? -std::numeric_limits<double>::infinity() : std::numeric_limits<double>::infinity());
useNanOrInf = true;
if (CEREAL_RAPIDJSON_UNLIKELY(s.Peek() == 'i' && !(Consume(s, 'i') && Consume(s, 'n') if (CEREAL_RAPIDJSON_UNLIKELY(s.Peek() == 'i' && !(Consume(s, 'i') && Consume(s, 'n')
&& Consume(s, 'i') && Consume(s, 't') && Consume(s, 'y')))) { && Consume(s, 'i') && Consume(s, 't') && Consume(s, 'y'))))
CEREAL_RAPIDJSON_PARSE_ERROR(kParseErrorValueInvalid, s.Tell()); CEREAL_RAPIDJSON_PARSE_ERROR(kParseErrorValueInvalid, s.Tell());
} }
} else
}
if (CEREAL_RAPIDJSON_UNLIKELY(!useNanOrInf)) {
CEREAL_RAPIDJSON_PARSE_ERROR(kParseErrorValueInvalid, s.Tell()); CEREAL_RAPIDJSON_PARSE_ERROR(kParseErrorValueInvalid, s.Tell());
} }
}
else else
CEREAL_RAPIDJSON_PARSE_ERROR(kParseErrorValueInvalid, s.Tell()); CEREAL_RAPIDJSON_PARSE_ERROR(kParseErrorValueInvalid, s.Tell());
@ -1561,6 +1231,8 @@ private:
// Force double for big integer // Force double for big integer
if (useDouble) { if (useDouble) {
while (CEREAL_RAPIDJSON_LIKELY(s.Peek() >= '0' && s.Peek() <= '9')) { while (CEREAL_RAPIDJSON_LIKELY(s.Peek() >= '0' && s.Peek() <= '9')) {
if (CEREAL_RAPIDJSON_UNLIKELY(d >= 1.7976931348623157e307)) // DBL_MAX / 10.0
CEREAL_RAPIDJSON_PARSE_ERROR(kParseErrorNumberTooBig, startOffset);
d = d * 10 + (s.TakePush() - '0'); d = d * 10 + (s.TakePush() - '0');
} }
} }
@ -1630,18 +1302,9 @@ private:
if (CEREAL_RAPIDJSON_LIKELY(s.Peek() >= '0' && s.Peek() <= '9')) { if (CEREAL_RAPIDJSON_LIKELY(s.Peek() >= '0' && s.Peek() <= '9')) {
exp = static_cast<int>(s.Take() - '0'); exp = static_cast<int>(s.Take() - '0');
if (expMinus) { if (expMinus) {
// (exp + expFrac) must not underflow int => we're detecting when -exp gets
// dangerously close to INT_MIN (a pessimistic next digit 9 would push it into
// underflow territory):
//
// -(exp * 10 + 9) + expFrac >= INT_MIN
// <=> exp <= (expFrac - INT_MIN - 9) / 10
CEREAL_RAPIDJSON_ASSERT(expFrac <= 0);
int maxExp = (expFrac + 2147483639) / 10;
while (CEREAL_RAPIDJSON_LIKELY(s.Peek() >= '0' && s.Peek() <= '9')) { while (CEREAL_RAPIDJSON_LIKELY(s.Peek() >= '0' && s.Peek() <= '9')) {
exp = exp * 10 + static_cast<int>(s.Take() - '0'); exp = exp * 10 + static_cast<int>(s.Take() - '0');
if (CEREAL_RAPIDJSON_UNLIKELY(exp > maxExp)) { if (exp >= 214748364) { // Issue #313: prevent overflow exponent
while (CEREAL_RAPIDJSON_UNLIKELY(s.Peek() >= '0' && s.Peek() <= '9')) // Consume the rest of exponent while (CEREAL_RAPIDJSON_UNLIKELY(s.Peek() >= '0' && s.Peek() <= '9')) // Consume the rest of exponent
s.Take(); s.Take();
} }
@ -1700,13 +1363,6 @@ private:
else else
d = internal::StrtodNormalPrecision(d, p); d = internal::StrtodNormalPrecision(d, p);
// Use > max, instead of == inf, to fix bogus warning -Wfloat-equal
if (d > (std::numeric_limits<double>::max)()) {
// Overflow
// TODO: internal::StrtodX should report overflow (or underflow)
CEREAL_RAPIDJSON_PARSE_ERROR(kParseErrorNumberTooBig, startOffset);
}
cont = handler.Double(minus ? -d : d); cont = handler.Double(minus ? -d : d);
} }
else if (useNanOrInf) { else if (useNanOrInf) {
@ -1752,32 +1408,30 @@ private:
// States // States
enum IterativeParsingState { enum IterativeParsingState {
IterativeParsingFinishState = 0, // sink states at top IterativeParsingStartState = 0,
IterativeParsingErrorState, // sink states at top IterativeParsingFinishState,
IterativeParsingStartState, IterativeParsingErrorState,
// Object states // Object states
IterativeParsingObjectInitialState, IterativeParsingObjectInitialState,
IterativeParsingMemberKeyState, IterativeParsingMemberKeyState,
IterativeParsingKeyValueDelimiterState,
IterativeParsingMemberValueState, IterativeParsingMemberValueState,
IterativeParsingMemberDelimiterState,
IterativeParsingObjectFinishState, IterativeParsingObjectFinishState,
// Array states // Array states
IterativeParsingArrayInitialState, IterativeParsingArrayInitialState,
IterativeParsingElementState, IterativeParsingElementState,
IterativeParsingElementDelimiterState,
IterativeParsingArrayFinishState, IterativeParsingArrayFinishState,
// Single value state // Single value state
IterativeParsingValueState, IterativeParsingValueState
// Delimiter states (at bottom)
IterativeParsingElementDelimiterState,
IterativeParsingMemberDelimiterState,
IterativeParsingKeyValueDelimiterState,
cIterativeParsingStateCount
}; };
enum { cIterativeParsingStateCount = IterativeParsingValueState + 1 };
// Tokens // Tokens
enum Token { enum Token {
LeftBracketToken = 0, LeftBracketToken = 0,
@ -1798,7 +1452,7 @@ private:
kTokenCount kTokenCount
}; };
CEREAL_RAPIDJSON_FORCEINLINE Token Tokenize(Ch c) const { CEREAL_RAPIDJSON_FORCEINLINE Token Tokenize(Ch c) {
//!@cond CEREAL_RAPIDJSON_HIDDEN_FROM_DOXYGEN //!@cond CEREAL_RAPIDJSON_HIDDEN_FROM_DOXYGEN
#define N NumberToken #define N NumberToken
@ -1825,21 +1479,9 @@ private:
return NumberToken; return NumberToken;
} }
CEREAL_RAPIDJSON_FORCEINLINE IterativeParsingState Predict(IterativeParsingState state, Token token) const { CEREAL_RAPIDJSON_FORCEINLINE IterativeParsingState Predict(IterativeParsingState state, Token token) {
// current state x one lookahead token -> new state // current state x one lookahead token -> new state
static const char G[cIterativeParsingStateCount][kTokenCount] = { static const char G[cIterativeParsingStateCount][kTokenCount] = {
// Finish(sink state)
{
IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState,
IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState,
IterativeParsingErrorState
},
// Error(sink state)
{
IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState,
IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState,
IterativeParsingErrorState
},
// Start // Start
{ {
IterativeParsingArrayInitialState, // Left bracket IterativeParsingArrayInitialState, // Left bracket
@ -1854,6 +1496,18 @@ private:
IterativeParsingValueState, // Null IterativeParsingValueState, // Null
IterativeParsingValueState // Number IterativeParsingValueState // Number
}, },
// Finish(sink state)
{
IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState,
IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState,
IterativeParsingErrorState
},
// Error(sink state)
{
IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState,
IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState,
IterativeParsingErrorState
},
// ObjectInitial // ObjectInitial
{ {
IterativeParsingErrorState, // Left bracket IterativeParsingErrorState, // Left bracket
@ -1882,6 +1536,20 @@ private:
IterativeParsingErrorState, // Null IterativeParsingErrorState, // Null
IterativeParsingErrorState // Number IterativeParsingErrorState // Number
}, },
// KeyValueDelimiter
{
IterativeParsingArrayInitialState, // Left bracket(push MemberValue state)
IterativeParsingErrorState, // Right bracket
IterativeParsingObjectInitialState, // Left curly bracket(push MemberValue state)
IterativeParsingErrorState, // Right curly bracket
IterativeParsingErrorState, // Comma
IterativeParsingErrorState, // Colon
IterativeParsingMemberValueState, // String
IterativeParsingMemberValueState, // False
IterativeParsingMemberValueState, // True
IterativeParsingMemberValueState, // Null
IterativeParsingMemberValueState // Number
},
// MemberValue // MemberValue
{ {
IterativeParsingErrorState, // Left bracket IterativeParsingErrorState, // Left bracket
@ -1896,6 +1564,20 @@ private:
IterativeParsingErrorState, // Null IterativeParsingErrorState, // Null
IterativeParsingErrorState // Number IterativeParsingErrorState // Number
}, },
// MemberDelimiter
{
IterativeParsingErrorState, // Left bracket
IterativeParsingErrorState, // Right bracket
IterativeParsingErrorState, // Left curly bracket
IterativeParsingObjectFinishState, // Right curly bracket
IterativeParsingErrorState, // Comma
IterativeParsingErrorState, // Colon
IterativeParsingMemberKeyState, // String
IterativeParsingErrorState, // False
IterativeParsingErrorState, // True
IterativeParsingErrorState, // Null
IterativeParsingErrorState // Number
},
// ObjectFinish(sink state) // ObjectFinish(sink state)
{ {
IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState,
@ -1930,18 +1612,6 @@ private:
IterativeParsingErrorState, // Null IterativeParsingErrorState, // Null
IterativeParsingErrorState // Number IterativeParsingErrorState // Number
}, },
// ArrayFinish(sink state)
{
IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState,
IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState,
IterativeParsingErrorState
},
// Single Value (sink state)
{
IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState,
IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState,
IterativeParsingErrorState
},
// ElementDelimiter // ElementDelimiter
{ {
IterativeParsingArrayInitialState, // Left bracket(push Element state) IterativeParsingArrayInitialState, // Left bracket(push Element state)
@ -1956,34 +1626,18 @@ private:
IterativeParsingElementState, // Null IterativeParsingElementState, // Null
IterativeParsingElementState // Number IterativeParsingElementState // Number
}, },
// MemberDelimiter // ArrayFinish(sink state)
{ {
IterativeParsingErrorState, // Left bracket IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState,
IterativeParsingErrorState, // Right bracket IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState,
IterativeParsingErrorState, // Left curly bracket IterativeParsingErrorState
IterativeParsingObjectFinishState, // Right curly bracket
IterativeParsingErrorState, // Comma
IterativeParsingErrorState, // Colon
IterativeParsingMemberKeyState, // String
IterativeParsingErrorState, // False
IterativeParsingErrorState, // True
IterativeParsingErrorState, // Null
IterativeParsingErrorState // Number
}, },
// KeyValueDelimiter // Single Value (sink state)
{ {
IterativeParsingArrayInitialState, // Left bracket(push MemberValue state) IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState,
IterativeParsingErrorState, // Right bracket IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState,
IterativeParsingObjectInitialState, // Left curly bracket(push MemberValue state) IterativeParsingErrorState
IterativeParsingErrorState, // Right curly bracket }
IterativeParsingErrorState, // Comma
IterativeParsingErrorState, // Colon
IterativeParsingMemberValueState, // String
IterativeParsingMemberValueState, // False
IterativeParsingMemberValueState, // True
IterativeParsingMemberValueState, // Null
IterativeParsingMemberValueState // Number
},
}; // End of G }; // End of G
return static_cast<IterativeParsingState>(G[state][token]); return static_cast<IterativeParsingState>(G[state][token]);
@ -2164,14 +1818,6 @@ private:
} }
} }
CEREAL_RAPIDJSON_FORCEINLINE bool IsIterativeParsingDelimiterState(IterativeParsingState s) const {
return s >= IterativeParsingElementDelimiterState;
}
CEREAL_RAPIDJSON_FORCEINLINE bool IsIterativeParsingCompleteState(IterativeParsingState s) const {
return s <= IterativeParsingErrorState;
}
template <unsigned parseFlags, typename InputStream, typename Handler> template <unsigned parseFlags, typename InputStream, typename Handler>
ParseResult IterativeParse(InputStream& is, Handler& handler) { ParseResult IterativeParse(InputStream& is, Handler& handler) {
parseResult_.Clear(); parseResult_.Clear();
@ -2210,7 +1856,6 @@ private:
static const size_t kDefaultStackCapacity = 256; //!< Default stack capacity in bytes for storing a single decoded string. static const size_t kDefaultStackCapacity = 256; //!< Default stack capacity in bytes for storing a single decoded string.
internal::Stack<StackAllocator> stack_; //!< A stack for storing decoded string temporarily during non-destructive parsing. internal::Stack<StackAllocator> stack_; //!< A stack for storing decoded string temporarily during non-destructive parsing.
ParseResult parseResult_; ParseResult parseResult_;
IterativeParsingState state_;
}; // class GenericReader }; // class GenericReader
//! Reader with UTF8 encoding and default allocator. //! Reader with UTF8 encoding and default allocator.
@ -2218,7 +1863,7 @@ typedef GenericReader<UTF8<>, UTF8<> > Reader;
CEREAL_RAPIDJSON_NAMESPACE_END CEREAL_RAPIDJSON_NAMESPACE_END
#if defined(__clang__) || defined(_MSC_VER) #ifdef __clang__
CEREAL_RAPIDJSON_DIAG_POP CEREAL_RAPIDJSON_DIAG_POP
#endif #endif
@ -2227,4 +1872,8 @@ CEREAL_RAPIDJSON_DIAG_POP
CEREAL_RAPIDJSON_DIAG_POP CEREAL_RAPIDJSON_DIAG_POP
#endif #endif
#ifdef _MSC_VER
CEREAL_RAPIDJSON_DIAG_POP
#endif
#endif // CEREAL_RAPIDJSON_READER_H_ #endif // CEREAL_RAPIDJSON_READER_H_

File diff suppressed because it is too large Load Diff

View File

@ -100,50 +100,6 @@ inline void PutN(Stream& stream, Ch c, size_t n) {
PutUnsafe(stream, c); PutUnsafe(stream, c);
} }
///////////////////////////////////////////////////////////////////////////////
// GenericStreamWrapper
//! A Stream Wrapper
/*! \tThis string stream is a wrapper for any stream by just forwarding any
\treceived message to the origin stream.
\note implements Stream concept
*/
#if defined(_MSC_VER) && _MSC_VER <= 1800
CEREAL_RAPIDJSON_DIAG_PUSH
CEREAL_RAPIDJSON_DIAG_OFF(4702) // unreachable code
CEREAL_RAPIDJSON_DIAG_OFF(4512) // assignment operator could not be generated
#endif
template <typename InputStream, typename Encoding = UTF8<> >
class GenericStreamWrapper {
public:
typedef typename Encoding::Ch Ch;
GenericStreamWrapper(InputStream& is): is_(is) {}
Ch Peek() const { return is_.Peek(); }
Ch Take() { return is_.Take(); }
size_t Tell() { return is_.Tell(); }
Ch* PutBegin() { return is_.PutBegin(); }
void Put(Ch ch) { is_.Put(ch); }
void Flush() { is_.Flush(); }
size_t PutEnd(Ch* ch) { return is_.PutEnd(ch); }
// wrapper for MemoryStream
const Ch* Peek4() const { return is_.Peek4(); }
// wrapper for AutoUTFInputStream
UTFType GetType() const { return is_.GetType(); }
bool HasBOM() const { return is_.HasBOM(); }
protected:
InputStream& is_;
};
#if defined(_MSC_VER) && _MSC_VER <= 1800
CEREAL_RAPIDJSON_DIAG_POP
#endif
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
// StringStream // StringStream

View File

@ -78,12 +78,8 @@ public:
return stack_.template Bottom<Ch>(); return stack_.template Bottom<Ch>();
} }
//! Get the size of string in bytes in the string buffer.
size_t GetSize() const { return stack_.GetSize(); } size_t GetSize() const { return stack_.GetSize(); }
//! Get the length of string in Ch in the string buffer.
size_t GetLength() const { return stack_.GetSize() / sizeof(Ch); }
static const size_t kDefaultCapacity = 256; static const size_t kDefaultCapacity = 256;
mutable internal::Stack<Allocator> stack_; mutable internal::Stack<Allocator> stack_;

View File

@ -16,7 +16,6 @@
#define CEREAL_RAPIDJSON_WRITER_H_ #define CEREAL_RAPIDJSON_WRITER_H_
#include "stream.h" #include "stream.h"
#include "internal/meta.h"
#include "internal/stack.h" #include "internal/stack.h"
#include "internal/strfunc.h" #include "internal/strfunc.h"
#include "internal/dtoa.h" #include "internal/dtoa.h"
@ -32,18 +31,17 @@
#include <nmmintrin.h> #include <nmmintrin.h>
#elif defined(CEREAL_RAPIDJSON_SSE2) #elif defined(CEREAL_RAPIDJSON_SSE2)
#include <emmintrin.h> #include <emmintrin.h>
#elif defined(CEREAL_RAPIDJSON_NEON) #endif
#include <arm_neon.h>
#ifdef _MSC_VER
CEREAL_RAPIDJSON_DIAG_PUSH
CEREAL_RAPIDJSON_DIAG_OFF(4127) // conditional expression is constant
#endif #endif
#ifdef __clang__ #ifdef __clang__
CEREAL_RAPIDJSON_DIAG_PUSH CEREAL_RAPIDJSON_DIAG_PUSH
CEREAL_RAPIDJSON_DIAG_OFF(padded) CEREAL_RAPIDJSON_DIAG_OFF(padded)
CEREAL_RAPIDJSON_DIAG_OFF(unreachable-code) CEREAL_RAPIDJSON_DIAG_OFF(unreachable-code)
CEREAL_RAPIDJSON_DIAG_OFF(c++98-compat)
#elif defined(_MSC_VER)
CEREAL_RAPIDJSON_DIAG_PUSH
CEREAL_RAPIDJSON_DIAG_OFF(4127) // conditional expression is constant
#endif #endif
CEREAL_RAPIDJSON_NAMESPACE_BEGIN CEREAL_RAPIDJSON_NAMESPACE_BEGIN
@ -65,7 +63,7 @@ CEREAL_RAPIDJSON_NAMESPACE_BEGIN
enum WriteFlag { enum WriteFlag {
kWriteNoFlags = 0, //!< No flags are set. kWriteNoFlags = 0, //!< No flags are set.
kWriteValidateEncodingFlag = 1, //!< Validate encoding of JSON strings. kWriteValidateEncodingFlag = 1, //!< Validate encoding of JSON strings.
kWriteNanAndInfFlag = 2, //!< Allow writing of Infinity, -Infinity and NaN. kWriteNanAndInfFlag = 2, //!< Allow writing of Inf, -Inf and NaN.
kWriteDefaultFlags = CEREAL_RAPIDJSON_WRITE_DEFAULT_FLAGS //!< Default write flags. Can be customized by defining CEREAL_RAPIDJSON_WRITE_DEFAULT_FLAGS kWriteDefaultFlags = CEREAL_RAPIDJSON_WRITE_DEFAULT_FLAGS //!< Default write flags. Can be customized by defining CEREAL_RAPIDJSON_WRITE_DEFAULT_FLAGS
}; };
@ -105,13 +103,6 @@ public:
Writer(StackAllocator* allocator = 0, size_t levelDepth = kDefaultLevelDepth) : Writer(StackAllocator* allocator = 0, size_t levelDepth = kDefaultLevelDepth) :
os_(0), level_stack_(allocator, levelDepth * sizeof(Level)), maxDecimalPlaces_(kDefaultMaxDecimalPlaces), hasRoot_(false) {} os_(0), level_stack_(allocator, levelDepth * sizeof(Level)), maxDecimalPlaces_(kDefaultMaxDecimalPlaces), hasRoot_(false) {}
#if CEREAL_RAPIDJSON_HAS_CXX11_RVALUE_REFS
Writer(Writer&& rhs) :
os_(rhs.os_), level_stack_(std::move(rhs.level_stack_)), maxDecimalPlaces_(rhs.maxDecimalPlaces_), hasRoot_(rhs.hasRoot_) {
rhs.os_ = 0;
}
#endif
//! Reset the writer with a new stream. //! Reset the writer with a new stream.
/*! /*!
This function reset the writer with a new stream and default settings, This function reset the writer with a new stream and default settings,
@ -193,14 +184,12 @@ public:
bool Double(double d) { Prefix(kNumberType); return EndValue(WriteDouble(d)); } bool Double(double d) { Prefix(kNumberType); return EndValue(WriteDouble(d)); }
bool RawNumber(const Ch* str, SizeType length, bool copy = false) { bool RawNumber(const Ch* str, SizeType length, bool copy = false) {
CEREAL_RAPIDJSON_ASSERT(str != 0);
(void)copy; (void)copy;
Prefix(kNumberType); Prefix(kNumberType);
return EndValue(WriteString(str, length)); return EndValue(WriteString(str, length));
} }
bool String(const Ch* str, SizeType length, bool copy = false) { bool String(const Ch* str, SizeType length, bool copy = false) {
CEREAL_RAPIDJSON_ASSERT(str != 0);
(void)copy; (void)copy;
Prefix(kStringType); Prefix(kStringType);
return EndValue(WriteString(str, length)); return EndValue(WriteString(str, length));
@ -220,18 +209,10 @@ public:
bool Key(const Ch* str, SizeType length, bool copy = false) { return String(str, length, copy); } bool Key(const Ch* str, SizeType length, bool copy = false) { return String(str, length, copy); }
#if CEREAL_RAPIDJSON_HAS_STDSTRING
bool Key(const std::basic_string<Ch>& str)
{
return Key(str.data(), SizeType(str.size()));
}
#endif
bool EndObject(SizeType memberCount = 0) { bool EndObject(SizeType memberCount = 0) {
(void)memberCount; (void)memberCount;
CEREAL_RAPIDJSON_ASSERT(level_stack_.GetSize() >= sizeof(Level)); // not inside an Object CEREAL_RAPIDJSON_ASSERT(level_stack_.GetSize() >= sizeof(Level));
CEREAL_RAPIDJSON_ASSERT(!level_stack_.template Top<Level>()->inArray); // currently inside an Array, not Object CEREAL_RAPIDJSON_ASSERT(!level_stack_.template Top<Level>()->inArray);
CEREAL_RAPIDJSON_ASSERT(0 == level_stack_.template Top<Level>()->valueCount % 2); // Object has a Key without a Value
level_stack_.template Pop<Level>(1); level_stack_.template Pop<Level>(1);
return EndValue(WriteEndObject()); return EndValue(WriteEndObject());
} }
@ -255,8 +236,8 @@ public:
//@{ //@{
//! Simpler but slower overload. //! Simpler but slower overload.
bool String(const Ch* const& str) { return String(str, internal::StrLen(str)); } bool String(const Ch* str) { return String(str, internal::StrLen(str)); }
bool Key(const Ch* const& str) { return Key(str, internal::StrLen(str)); } bool Key(const Ch* str) { return Key(str, internal::StrLen(str)); }
//@} //@}
@ -268,19 +249,7 @@ public:
\param length Length of the json. \param length Length of the json.
\param type Type of the root of json. \param type Type of the root of json.
*/ */
bool RawValue(const Ch* json, size_t length, Type type) { bool RawValue(const Ch* json, size_t length, Type type) { Prefix(type); return EndValue(WriteRawValue(json, length)); }
CEREAL_RAPIDJSON_ASSERT(json != 0);
Prefix(type);
return EndValue(WriteRawValue(json, length));
}
//! Flush the output stream.
/*!
Allows the user to flush the output stream immediately.
*/
void Flush() {
os_->Flush();
}
protected: protected:
//! Information for each nested level //! Information for each nested level
@ -314,7 +283,7 @@ protected:
const char* end = internal::i32toa(i, buffer); const char* end = internal::i32toa(i, buffer);
PutReserve(*os_, static_cast<size_t>(end - buffer)); PutReserve(*os_, static_cast<size_t>(end - buffer));
for (const char* p = buffer; p != end; ++p) for (const char* p = buffer; p != end; ++p)
PutUnsafe(*os_, static_cast<typename OutputStream::Ch>(*p)); PutUnsafe(*os_, static_cast<typename TargetEncoding::Ch>(*p));
return true; return true;
} }
@ -323,7 +292,7 @@ protected:
const char* end = internal::u32toa(u, buffer); const char* end = internal::u32toa(u, buffer);
PutReserve(*os_, static_cast<size_t>(end - buffer)); PutReserve(*os_, static_cast<size_t>(end - buffer));
for (const char* p = buffer; p != end; ++p) for (const char* p = buffer; p != end; ++p)
PutUnsafe(*os_, static_cast<typename OutputStream::Ch>(*p)); PutUnsafe(*os_, static_cast<typename TargetEncoding::Ch>(*p));
return true; return true;
} }
@ -332,7 +301,7 @@ protected:
const char* end = internal::i64toa(i64, buffer); const char* end = internal::i64toa(i64, buffer);
PutReserve(*os_, static_cast<size_t>(end - buffer)); PutReserve(*os_, static_cast<size_t>(end - buffer));
for (const char* p = buffer; p != end; ++p) for (const char* p = buffer; p != end; ++p)
PutUnsafe(*os_, static_cast<typename OutputStream::Ch>(*p)); PutUnsafe(*os_, static_cast<typename TargetEncoding::Ch>(*p));
return true; return true;
} }
@ -341,7 +310,7 @@ protected:
char* end = internal::u64toa(u64, buffer); char* end = internal::u64toa(u64, buffer);
PutReserve(*os_, static_cast<size_t>(end - buffer)); PutReserve(*os_, static_cast<size_t>(end - buffer));
for (char* p = buffer; p != end; ++p) for (char* p = buffer; p != end; ++p)
PutUnsafe(*os_, static_cast<typename OutputStream::Ch>(*p)); PutUnsafe(*os_, static_cast<typename TargetEncoding::Ch>(*p));
return true; return true;
} }
@ -369,12 +338,12 @@ protected:
char* end = internal::dtoa(d, buffer, maxDecimalPlaces_); char* end = internal::dtoa(d, buffer, maxDecimalPlaces_);
PutReserve(*os_, static_cast<size_t>(end - buffer)); PutReserve(*os_, static_cast<size_t>(end - buffer));
for (char* p = buffer; p != end; ++p) for (char* p = buffer; p != end; ++p)
PutUnsafe(*os_, static_cast<typename OutputStream::Ch>(*p)); PutUnsafe(*os_, static_cast<typename TargetEncoding::Ch>(*p));
return true; return true;
} }
bool WriteString(const Ch* str, SizeType length) { bool WriteString(const Ch* str, SizeType length) {
static const typename OutputStream::Ch hexDigits[16] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' }; static const typename TargetEncoding::Ch hexDigits[16] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
static const char escape[256] = { static const char escape[256] = {
#define Z16 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 #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 //0 1 2 3 4 5 6 7 8 9 A B C D E F
@ -430,7 +399,7 @@ protected:
else if ((sizeof(Ch) == 1 || static_cast<unsigned>(c) < 256) && CEREAL_RAPIDJSON_UNLIKELY(escape[static_cast<unsigned char>(c)])) { else if ((sizeof(Ch) == 1 || static_cast<unsigned>(c) < 256) && CEREAL_RAPIDJSON_UNLIKELY(escape[static_cast<unsigned char>(c)])) {
is.Take(); is.Take();
PutUnsafe(*os_, '\\'); PutUnsafe(*os_, '\\');
PutUnsafe(*os_, static_cast<typename OutputStream::Ch>(escape[static_cast<unsigned char>(c)])); PutUnsafe(*os_, static_cast<typename TargetEncoding::Ch>(escape[static_cast<unsigned char>(c)]));
if (escape[static_cast<unsigned char>(c)] == 'u') { if (escape[static_cast<unsigned char>(c)] == 'u') {
PutUnsafe(*os_, '0'); PutUnsafe(*os_, '0');
PutUnsafe(*os_, '0'); PutUnsafe(*os_, '0');
@ -458,13 +427,9 @@ protected:
bool WriteRawValue(const Ch* json, size_t length) { bool WriteRawValue(const Ch* json, size_t length) {
PutReserve(*os_, length); PutReserve(*os_, length);
GenericStringStream<SourceEncoding> is(json); for (size_t i = 0; i < length; i++) {
while (CEREAL_RAPIDJSON_LIKELY(is.Tell() < length)) { CEREAL_RAPIDJSON_ASSERT(json[i] != '\0');
CEREAL_RAPIDJSON_ASSERT(is.Peek() != '\0'); PutUnsafe(*os_, json[i]);
if (CEREAL_RAPIDJSON_UNLIKELY(!(writeFlags & kWriteValidateEncodingFlag ?
Transcoder<SourceEncoding, TargetEncoding>::Validate(is, *os_) :
Transcoder<SourceEncoding, TargetEncoding>::TranscodeUnsafe(is, *os_))))
return false;
} }
return true; return true;
} }
@ -492,7 +457,7 @@ protected:
// Flush the value if it is the top level one. // Flush the value if it is the top level one.
bool EndValue(bool ret) { bool EndValue(bool ret) {
if (CEREAL_RAPIDJSON_UNLIKELY(level_stack_.Empty())) // end of json text if (CEREAL_RAPIDJSON_UNLIKELY(level_stack_.Empty())) // end of json text
Flush(); os_->Flush();
return ret; return ret;
} }
@ -596,7 +561,7 @@ inline bool Writer<StringBuffer>::ScanWriteUnescapedString(StringStream& is, siz
// The rest of string using SIMD // The rest of string using SIMD
static const char dquote[16] = { '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"' }; static const char dquote[16] = { '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"' };
static const char bslash[16] = { '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\' }; static const char bslash[16] = { '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\' };
static const char space[16] = { 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F }; static const char space[16] = { 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19 };
const __m128i dq = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&dquote[0])); const __m128i dq = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&dquote[0]));
const __m128i bs = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&bslash[0])); const __m128i bs = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&bslash[0]));
const __m128i sp = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&space[0])); const __m128i sp = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&space[0]));
@ -605,7 +570,7 @@ inline bool Writer<StringBuffer>::ScanWriteUnescapedString(StringStream& is, siz
const __m128i s = _mm_load_si128(reinterpret_cast<const __m128i *>(p)); const __m128i s = _mm_load_si128(reinterpret_cast<const __m128i *>(p));
const __m128i t1 = _mm_cmpeq_epi8(s, dq); const __m128i t1 = _mm_cmpeq_epi8(s, dq);
const __m128i t2 = _mm_cmpeq_epi8(s, bs); const __m128i t2 = _mm_cmpeq_epi8(s, bs);
const __m128i t3 = _mm_cmpeq_epi8(_mm_max_epu8(s, sp), sp); // s < 0x20 <=> max(s, 0x1F) == 0x1F const __m128i t3 = _mm_cmpeq_epi8(_mm_max_epu8(s, sp), sp); // s < 0x20 <=> max(s, 0x19) == 0x19
const __m128i x = _mm_or_si128(_mm_or_si128(t1, t2), t3); const __m128i x = _mm_or_si128(_mm_or_si128(t1, t2), t3);
unsigned short r = static_cast<unsigned short>(_mm_movemask_epi8(x)); unsigned short r = static_cast<unsigned short>(_mm_movemask_epi8(x));
if (CEREAL_RAPIDJSON_UNLIKELY(r != 0)) { // some of characters is escaped if (CEREAL_RAPIDJSON_UNLIKELY(r != 0)) { // some of characters is escaped
@ -630,79 +595,15 @@ inline bool Writer<StringBuffer>::ScanWriteUnescapedString(StringStream& is, siz
is.src_ = p; is.src_ = p;
return CEREAL_RAPIDJSON_LIKELY(is.Tell() < length); return CEREAL_RAPIDJSON_LIKELY(is.Tell() < length);
} }
#elif defined(CEREAL_RAPIDJSON_NEON) #endif // defined(CEREAL_RAPIDJSON_SSE2) || defined(CEREAL_RAPIDJSON_SSE42)
template<>
inline bool Writer<StringBuffer>::ScanWriteUnescapedString(StringStream& is, size_t length) {
if (length < 16)
return CEREAL_RAPIDJSON_LIKELY(is.Tell() < length);
if (!CEREAL_RAPIDJSON_LIKELY(is.Tell() < length))
return false;
const char* p = is.src_;
const char* end = is.head_ + length;
const char* nextAligned = reinterpret_cast<const char*>((reinterpret_cast<size_t>(p) + 15) & static_cast<size_t>(~15));
const char* endAligned = reinterpret_cast<const char*>(reinterpret_cast<size_t>(end) & static_cast<size_t>(~15));
if (nextAligned > end)
return true;
while (p != nextAligned)
if (*p < 0x20 || *p == '\"' || *p == '\\') {
is.src_ = p;
return CEREAL_RAPIDJSON_LIKELY(is.Tell() < length);
}
else
os_->PutUnsafe(*p++);
// The rest of string using SIMD
const uint8x16_t s0 = vmovq_n_u8('"');
const uint8x16_t s1 = vmovq_n_u8('\\');
const uint8x16_t s2 = vmovq_n_u8('\b');
const uint8x16_t s3 = vmovq_n_u8(32);
for (; p != endAligned; p += 16) {
const uint8x16_t s = vld1q_u8(reinterpret_cast<const uint8_t *>(p));
uint8x16_t x = vceqq_u8(s, s0);
x = vorrq_u8(x, vceqq_u8(s, s1));
x = vorrq_u8(x, vceqq_u8(s, s2));
x = vorrq_u8(x, vcltq_u8(s, s3));
x = vrev64q_u8(x); // Rev in 64
uint64_t low = vgetq_lane_u64(reinterpret_cast<uint64x2_t>(x), 0); // extract
uint64_t high = vgetq_lane_u64(reinterpret_cast<uint64x2_t>(x), 1); // extract
SizeType len = 0;
bool escaped = false;
if (low == 0) {
if (high != 0) {
unsigned lz = (unsigned)__builtin_clzll(high);
len = 8 + (lz >> 3);
escaped = true;
}
} else {
unsigned lz = (unsigned)__builtin_clzll(low);
len = lz >> 3;
escaped = true;
}
if (CEREAL_RAPIDJSON_UNLIKELY(escaped)) { // some of characters is escaped
char* q = reinterpret_cast<char*>(os_->PushUnsafe(len));
for (size_t i = 0; i < len; i++)
q[i] = p[i];
p += len;
break;
}
vst1q_u8(reinterpret_cast<uint8_t *>(os_->PushUnsafe(16)), s);
}
is.src_ = p;
return CEREAL_RAPIDJSON_LIKELY(is.Tell() < length);
}
#endif // CEREAL_RAPIDJSON_NEON
CEREAL_RAPIDJSON_NAMESPACE_END CEREAL_RAPIDJSON_NAMESPACE_END
#if defined(_MSC_VER) || defined(__clang__) #ifdef _MSC_VER
CEREAL_RAPIDJSON_DIAG_POP
#endif
#ifdef __clang__
CEREAL_RAPIDJSON_DIAG_POP CEREAL_RAPIDJSON_DIAG_POP
#endif #endif

View File

@ -85,7 +85,7 @@ namespace rapidxml
//! Gets human readable description of error. //! Gets human readable description of error.
//! \return Pointer to null terminated description of the error. //! \return Pointer to null terminated description of the error.
virtual const char *what() const CEREAL_NOEXCEPT override virtual const char *what() const throw()
{ {
return m_what; return m_what;
} }
@ -317,7 +317,7 @@ namespace rapidxml
const Ch *tmp = p; const Ch *tmp = p;
while (*tmp) while (*tmp)
++tmp; ++tmp;
return static_cast<std::size_t>(tmp - p); return tmp - p;
} }
// Compare strings for equality // Compare strings for equality
@ -387,7 +387,7 @@ namespace rapidxml
//! If required, you can tweak <code>CEREAL_RAPIDXML_STATIC_POOL_SIZE</code>, <code>CEREAL_RAPIDXML_DYNAMIC_POOL_SIZE</code> and <code>CEREAL_RAPIDXML_ALIGNMENT</code> //! If required, you can tweak <code>CEREAL_RAPIDXML_STATIC_POOL_SIZE</code>, <code>CEREAL_RAPIDXML_DYNAMIC_POOL_SIZE</code> and <code>CEREAL_RAPIDXML_ALIGNMENT</code>
//! to obtain best wasted memory to performance compromise. //! to obtain best wasted memory to performance compromise.
//! To do it, define their values before rapidxml.hpp file is included. //! To do it, define their values before rapidxml.hpp file is included.
//! \tparam Ch Character type of created nodes. //! \param Ch Character type of created nodes.
template<class Ch = char> template<class Ch = char>
class memory_pool class memory_pool
{ {
@ -656,7 +656,7 @@ namespace rapidxml
//! Base class for xml_node and xml_attribute implementing common functions: //! Base class for xml_node and xml_attribute implementing common functions:
//! name(), name_size(), value(), value_size() and parent(). //! name(), name_size(), value(), value_size() and parent().
//! \tparam Ch Character type to use //! \param Ch Character type to use
template<class Ch = char> template<class Ch = char>
class xml_base class xml_base
{ {
@ -729,7 +729,7 @@ namespace rapidxml
//! <br><br> //! <br><br>
//! Size of name must be specified separately, because name does not have to be zero terminated. //! Size of name must be specified separately, because name does not have to be zero terminated.
//! Use name(const Ch *) function to have the length automatically calculated (string must be zero terminated). //! Use name(const Ch *) function to have the length automatically calculated (string must be zero terminated).
//! \param name_ Name of node to set. Does not have to be zero terminated. //! \param name Name of node to set. Does not have to be zero terminated.
//! \param size Size of name, in characters. This does not include zero terminator, if one is present. //! \param size Size of name, in characters. This does not include zero terminator, if one is present.
void name(const Ch *name_, std::size_t size) void name(const Ch *name_, std::size_t size)
{ {
@ -739,7 +739,7 @@ namespace rapidxml
//! Sets name of node to a zero-terminated string. //! Sets name of node to a zero-terminated string.
//! See also \ref ownership_of_strings and xml_node::name(const Ch *, std::size_t). //! See also \ref ownership_of_strings and xml_node::name(const Ch *, std::size_t).
//! \param name_ Name of node to set. Must be zero terminated. //! \param name Name of node to set. Must be zero terminated.
void name(const Ch *name_) void name(const Ch *name_)
{ {
this->name(name_, internal::measure(name_)); this->name(name_, internal::measure(name_));
@ -759,7 +759,7 @@ namespace rapidxml
//! <br><br> //! <br><br>
//! If an element has a child node of type node_data, it will take precedence over element value when printing. //! If an element has a child node of type node_data, it will take precedence over element value when printing.
//! If you want to manipulate data of elements using values, use parser flag rapidxml::parse_no_data_nodes to prevent creation of data nodes by the parser. //! If you want to manipulate data of elements using values, use parser flag rapidxml::parse_no_data_nodes to prevent creation of data nodes by the parser.
//! \param value_ value of node to set. Does not have to be zero terminated. //! \param value value of node to set. Does not have to be zero terminated.
//! \param size Size of value, in characters. This does not include zero terminator, if one is present. //! \param size Size of value, in characters. This does not include zero terminator, if one is present.
void value(const Ch *value_, std::size_t size) void value(const Ch *value_, std::size_t size)
{ {
@ -769,7 +769,7 @@ namespace rapidxml
//! Sets value of node to a zero-terminated string. //! Sets value of node to a zero-terminated string.
//! See also \ref ownership_of_strings and xml_node::value(const Ch *, std::size_t). //! See also \ref ownership_of_strings and xml_node::value(const Ch *, std::size_t).
//! \param value_ Vame of node to set. Must be zero terminated. //! \param value Vame of node to set. Must be zero terminated.
void value(const Ch *value_) void value(const Ch *value_)
{ {
this->value(value_, internal::measure(value_)); this->value(value_, internal::measure(value_));
@ -806,7 +806,7 @@ namespace rapidxml
//! Each attribute has name and value strings, which are available through name() and value() functions (inherited from xml_base). //! Each attribute has name and value strings, which are available through name() and value() functions (inherited from xml_base).
//! Note that after parse, both name and value of attribute will point to interior of source text used for parsing. //! Note that after parse, both name and value of attribute will point to interior of source text used for parsing.
//! Thus, this text must persist in memory for the lifetime of attribute. //! Thus, this text must persist in memory for the lifetime of attribute.
//! \tparam Ch Character type to use. //! \param Ch Character type to use.
template<class Ch = char> template<class Ch = char>
class xml_attribute: public xml_base<Ch> class xml_attribute: public xml_base<Ch>
{ {
@ -862,8 +862,8 @@ namespace rapidxml
} }
//! Gets next attribute, optionally matching attribute name. //! Gets next attribute, optionally matching attribute name.
//! \param name_ Name of attribute to find, or 0 to return next attribute regardless of its name; this string doesn't have to be zero-terminated if name_size is non-zero //! \param name Name of attribute to find, or 0 to return next attribute regardless of its name; this string doesn't have to be zero-terminated if name_size is non-zero
//! \param name_size_ Size of name, in characters, or 0 to have size calculated automatically from string //! \param name_size Size of name, in characters, or 0 to have size calculated automatically from string
//! \param case_sensitive Should name comparison be case-sensitive; non case-sensitive comparison works properly only for ASCII characters //! \param case_sensitive Should name comparison be case-sensitive; non case-sensitive comparison works properly only for ASCII characters
//! \return Pointer to found attribute, or 0 if not found. //! \return Pointer to found attribute, or 0 if not found.
xml_attribute<Ch> *next_attribute(const Ch *name_ = 0, std::size_t name_size_ = 0, bool case_sensitive = true) const xml_attribute<Ch> *next_attribute(const Ch *name_ = 0, std::size_t name_size_ = 0, bool case_sensitive = true) const
@ -898,7 +898,7 @@ namespace rapidxml
//! <br><br> //! <br><br>
//! Note that after parse, both name and value of node, if any, will point interior of source text used for parsing. //! Note that after parse, both name and value of node, if any, will point interior of source text used for parsing.
//! Thus, this text must persist in the memory for the lifetime of node. //! Thus, this text must persist in the memory for the lifetime of node.
//! \tparam Ch Character type to use. //! \param Ch Character type to use.
template<class Ch = char> template<class Ch = char>
class xml_node: public xml_base<Ch> class xml_node: public xml_base<Ch>
{ {
@ -910,7 +910,7 @@ namespace rapidxml
//! Constructs an empty node with the specified type. //! Constructs an empty node with the specified type.
//! Consider using memory_pool of appropriate document to allocate nodes manually. //! Consider using memory_pool of appropriate document to allocate nodes manually.
//! \param type_ Type of node to construct. //! \param type Type of node to construct.
xml_node(node_type type_) xml_node(node_type type_)
: m_type(type_) : m_type(type_)
, m_first_node(0) , m_first_node(0)
@ -942,8 +942,8 @@ namespace rapidxml
} }
//! Gets first child node, optionally matching node name. //! Gets first child node, optionally matching node name.
//! \param name_ Name of child to find, or 0 to return first child regardless of its name; this string doesn't have to be zero-terminated if name_size is non-zero //! \param name Name of child to find, or 0 to return first child regardless of its name; this string doesn't have to be zero-terminated if name_size is non-zero
//! \param name_size_ Size of name, in characters, or 0 to have size calculated automatically from string //! \param name_size Size of name, in characters, or 0 to have size calculated automatically from string
//! \param case_sensitive Should name comparison be case-sensitive; non case-sensitive comparison works properly only for ASCII characters //! \param case_sensitive Should name comparison be case-sensitive; non case-sensitive comparison works properly only for ASCII characters
//! \return Pointer to found child, or 0 if not found. //! \return Pointer to found child, or 0 if not found.
xml_node<Ch> *first_node(const Ch *name_ = 0, std::size_t name_size_ = 0, bool case_sensitive = true) const xml_node<Ch> *first_node(const Ch *name_ = 0, std::size_t name_size_ = 0, bool case_sensitive = true) const
@ -1010,8 +1010,8 @@ namespace rapidxml
//! Gets next sibling node, optionally matching node name. //! Gets next sibling node, optionally matching node name.
//! Behaviour is undefined if node has no parent. //! Behaviour is undefined if node has no parent.
//! Use parent() to test if node has a parent. //! Use parent() to test if node has a parent.
//! \param name_ Name of sibling to find, or 0 to return next sibling regardless of its name; this string doesn't have to be zero-terminated if name_size is non-zero //! \param name Name of sibling to find, or 0 to return next sibling regardless of its name; this string doesn't have to be zero-terminated if name_size is non-zero
//! \param name_size_ Size of name, in characters, or 0 to have size calculated automatically from string //! \param name_size Size of name, in characters, or 0 to have size calculated automatically from string
//! \param case_sensitive Should name comparison be case-sensitive; non case-sensitive comparison works properly only for ASCII characters //! \param case_sensitive Should name comparison be case-sensitive; non case-sensitive comparison works properly only for ASCII characters
//! \return Pointer to found sibling, or 0 if not found. //! \return Pointer to found sibling, or 0 if not found.
xml_node<Ch> *next_sibling(const Ch *name_ = 0, std::size_t name_size_ = 0, bool case_sensitive = true) const xml_node<Ch> *next_sibling(const Ch *name_ = 0, std::size_t name_size_ = 0, bool case_sensitive = true) const
@ -1031,8 +1031,8 @@ namespace rapidxml
} }
//! Gets first attribute of node, optionally matching attribute name. //! Gets first attribute of node, optionally matching attribute name.
//! \param name_ Name of attribute to find, or 0 to return first attribute regardless of its name; this string doesn't have to be zero-terminated if name_size is non-zero //! \param name Name of attribute to find, or 0 to return first attribute regardless of its name; this string doesn't have to be zero-terminated if name_size is non-zero
//! \param name_size_ Size of name, in characters, or 0 to have size calculated automatically from string //! \param name_size Size of name, in characters, or 0 to have size calculated automatically from string
//! \param case_sensitive Should name comparison be case-sensitive; non case-sensitive comparison works properly only for ASCII characters //! \param case_sensitive Should name comparison be case-sensitive; non case-sensitive comparison works properly only for ASCII characters
//! \return Pointer to found attribute, or 0 if not found. //! \return Pointer to found attribute, or 0 if not found.
xml_attribute<Ch> *first_attribute(const Ch *name_ = 0, std::size_t name_size_ = 0, bool case_sensitive = true) const xml_attribute<Ch> *first_attribute(const Ch *name_ = 0, std::size_t name_size_ = 0, bool case_sensitive = true) const
@ -1074,7 +1074,7 @@ namespace rapidxml
// Node modification // Node modification
//! Sets type of node. //! Sets type of node.
//! \param type_ Type of node to set. //! \param type Type of node to set.
void type(node_type type_) void type(node_type type_)
{ {
m_type = type_; m_type = type_;
@ -1366,7 +1366,7 @@ namespace rapidxml
//! parse() function allocates memory for nodes and attributes by using functions of xml_document, //! parse() function allocates memory for nodes and attributes by using functions of xml_document,
//! which are inherited from memory_pool. //! which are inherited from memory_pool.
//! To access root node of the document, use the document itself, as if it was an xml_node. //! To access root node of the document, use the document itself, as if it was an xml_node.
//! \tparam Ch Character type to use. //! \param Ch Character type to use.
template<class Ch = char> template<class Ch = char>
class xml_document: public xml_node<Ch>, public memory_pool<Ch> class xml_document: public xml_node<Ch>, public memory_pool<Ch>
{ {
@ -1527,7 +1527,7 @@ namespace rapidxml
{ {
// Insert 8-bit ASCII character // Insert 8-bit ASCII character
// Todo: possibly verify that code is less than 256 and use replacement char otherwise? // Todo: possibly verify that code is less than 256 and use replacement char otherwise?
text[0] = static_cast<Ch>(code); text[0] = static_cast<unsigned char>(code);
text += 1; text += 1;
} }
else else
@ -1535,28 +1535,28 @@ namespace rapidxml
// Insert UTF8 sequence // Insert UTF8 sequence
if (code < 0x80) // 1 byte sequence if (code < 0x80) // 1 byte sequence
{ {
text[0] = static_cast<Ch>(code); text[0] = static_cast<unsigned char>(code);
text += 1; text += 1;
} }
else if (code < 0x800) // 2 byte sequence else if (code < 0x800) // 2 byte sequence
{ {
text[1] = static_cast<Ch>((code | 0x80) & 0xBF); code >>= 6; text[1] = static_cast<unsigned char>((code | 0x80) & 0xBF); code >>= 6;
text[0] = static_cast<Ch>(code | 0xC0); text[0] = static_cast<unsigned char>(code | 0xC0);
text += 2; text += 2;
} }
else if (code < 0x10000) // 3 byte sequence else if (code < 0x10000) // 3 byte sequence
{ {
text[2] = static_cast<Ch>((code | 0x80) & 0xBF); code >>= 6; text[2] = static_cast<unsigned char>((code | 0x80) & 0xBF); code >>= 6;
text[1] = static_cast<Ch>((code | 0x80) & 0xBF); code >>= 6; text[1] = static_cast<unsigned char>((code | 0x80) & 0xBF); code >>= 6;
text[0] = static_cast<Ch>(code | 0xE0); text[0] = static_cast<unsigned char>(code | 0xE0);
text += 3; text += 3;
} }
else if (code < 0x110000) // 4 byte sequence else if (code < 0x110000) // 4 byte sequence
{ {
text[3] = static_cast<Ch>((code | 0x80) & 0xBF); code >>= 6; text[3] = static_cast<unsigned char>((code | 0x80) & 0xBF); code >>= 6;
text[2] = static_cast<Ch>((code | 0x80) & 0xBF); code >>= 6; text[2] = static_cast<unsigned char>((code | 0x80) & 0xBF); code >>= 6;
text[1] = static_cast<Ch>((code | 0x80) & 0xBF); code >>= 6; text[1] = static_cast<unsigned char>((code | 0x80) & 0xBF); code >>= 6;
text[0] = static_cast<Ch>(code | 0xF0); text[0] = static_cast<unsigned char>(code | 0xF0);
text += 4; text += 4;
} }
else // Invalid, only codes up to 0x10FFFF are allowed in Unicode else // Invalid, only codes up to 0x10FFFF are allowed in Unicode
@ -1812,7 +1812,7 @@ namespace rapidxml
// Create comment node // Create comment node
xml_node<Ch> *comment = this->allocate_node(node_comment); xml_node<Ch> *comment = this->allocate_node(node_comment);
comment->value(value_, static_cast<std::size_t>(text - value_)); comment->value(value_, text - value_);
// Place zero terminator after comment value // Place zero terminator after comment value
if (!(Flags & parse_no_string_terminators)) if (!(Flags & parse_no_string_terminators))
@ -1871,7 +1871,7 @@ namespace rapidxml
{ {
// Create a new doctype node // Create a new doctype node
xml_node<Ch> *doctype = this->allocate_node(node_doctype); xml_node<Ch> *doctype = this->allocate_node(node_doctype);
doctype->value(value_, static_cast<std::size_t>(text - value_)); doctype->value(value_, text - value_);
// Place zero terminator after value // Place zero terminator after value
if (!(Flags & parse_no_string_terminators)) if (!(Flags & parse_no_string_terminators))
@ -1903,7 +1903,7 @@ namespace rapidxml
skip<node_name_pred, Flags>(text); skip<node_name_pred, Flags>(text);
if (text == name_) if (text == name_)
CEREAL_RAPIDXML_PARSE_ERROR("expected PI target", text); CEREAL_RAPIDXML_PARSE_ERROR("expected PI target", text);
pi->name(name_, static_cast<std::size_t>(text - name_)); pi->name(name_, text - name_);
// Skip whitespace between pi target and pi // Skip whitespace between pi target and pi
skip<whitespace_pred, Flags>(text); skip<whitespace_pred, Flags>(text);
@ -1920,7 +1920,7 @@ namespace rapidxml
} }
// Set pi value (verbatim, no entity expansion or whitespace normalization) // Set pi value (verbatim, no entity expansion or whitespace normalization)
pi->value(value_, static_cast<std::size_t>(text - value_)); pi->value(value_, text - value_);
// Place zero terminator after name and value // Place zero terminator after name and value
if (!(Flags & parse_no_string_terminators)) if (!(Flags & parse_no_string_terminators))
@ -1987,14 +1987,14 @@ namespace rapidxml
if (!(Flags & parse_no_data_nodes)) if (!(Flags & parse_no_data_nodes))
{ {
xml_node<Ch> *data = this->allocate_node(node_data); xml_node<Ch> *data = this->allocate_node(node_data);
data->value(value_, static_cast<std::size_t>(end - value_)); data->value(value_, end - value_);
node->append_node(data); node->append_node(data);
} }
// Add data to parent node if no data exists yet // Add data to parent node if no data exists yet
if (!(Flags & parse_no_element_values)) if (!(Flags & parse_no_element_values))
if (*node->value() == Ch('\0')) if (*node->value() == Ch('\0'))
node->value(value_, static_cast<std::size_t>(end - value_)); node->value(value_, end - value_);
// Place zero terminator after value // Place zero terminator after value
if (!(Flags & parse_no_string_terminators)) if (!(Flags & parse_no_string_terminators))
@ -2037,7 +2037,7 @@ namespace rapidxml
// Create new cdata node // Create new cdata node
xml_node<Ch> *cdata = this->allocate_node(node_cdata); xml_node<Ch> *cdata = this->allocate_node(node_cdata);
cdata->value(value_, static_cast<std::size_t>(text - value_)); cdata->value(value_, text - value_);
// Place zero terminator after value // Place zero terminator after value
if (!(Flags & parse_no_string_terminators)) if (!(Flags & parse_no_string_terminators))
@ -2059,7 +2059,7 @@ namespace rapidxml
skip<node_name_pred, Flags>(text); skip<node_name_pred, Flags>(text);
if (text == name_) if (text == name_)
CEREAL_RAPIDXML_PARSE_ERROR("expected element name", text); CEREAL_RAPIDXML_PARSE_ERROR("expected element name", text);
element->name(name_, static_cast<std::size_t>(text - name_)); element->name(name_, text - name_);
// Skip whitespace between element name and attributes or > // Skip whitespace between element name and attributes or >
skip<whitespace_pred, Flags>(text); skip<whitespace_pred, Flags>(text);
@ -2216,7 +2216,7 @@ namespace rapidxml
// Skip and validate closing tag name // Skip and validate closing tag name
Ch *closing_name = text; Ch *closing_name = text;
skip<node_name_pred, Flags>(text); skip<node_name_pred, Flags>(text);
if (!internal::compare(node->name(), node->name_size(), closing_name, static_cast<std::size_t>(text - closing_name), true)) if (!internal::compare(node->name(), node->name_size(), closing_name, text - closing_name, true))
CEREAL_RAPIDXML_PARSE_ERROR("invalid closing tag name", text); CEREAL_RAPIDXML_PARSE_ERROR("invalid closing tag name", text);
} }
else else
@ -2232,7 +2232,7 @@ namespace rapidxml
if (contents_end && contents_end != contents_start) if (contents_end && contents_end != contents_start)
{ {
node->value(contents_start, static_cast<std::size_t>(contents_end - contents_start)); node->value(contents_start, contents_end - contents_start);
node->value()[node->value_size()] = Ch('\0'); node->value()[node->value_size()] = Ch('\0');
} }
return; // Node closed, finished parsing contents return; // Node closed, finished parsing contents
@ -2275,7 +2275,7 @@ namespace rapidxml
// Create new attribute // Create new attribute
xml_attribute<Ch> *attribute = this->allocate_attribute(); xml_attribute<Ch> *attribute = this->allocate_attribute();
attribute->name(name_, static_cast<std::size_t>(text - name_)); attribute->name(name_, text - name_);
node->append_attribute(attribute); node->append_attribute(attribute);
// Skip whitespace after attribute name // Skip whitespace after attribute name
@ -2308,7 +2308,7 @@ namespace rapidxml
end = skip_and_expand_character_refs<attribute_value_pred<Ch('"')>, attribute_value_pure_pred<Ch('"')>, AttFlags>(text, false); end = skip_and_expand_character_refs<attribute_value_pred<Ch('"')>, attribute_value_pure_pred<Ch('"')>, AttFlags>(text, false);
// Set attribute value // Set attribute value
attribute->value(value_, static_cast<std::size_t>(end - value_)); attribute->value(value_, end - value_);
// Make sure that end quote is present // Make sure that end quote is present
if (*text != quote) if (*text != quote)

View File

@ -363,12 +363,10 @@ namespace rapidxml
out = print_pi_node(out, node, flags, indent); out = print_pi_node(out, node, flags, indent);
break; break;
#ifndef __GNUC__
// Unknown // Unknown
default: default:
assert(0); assert(0);
break; break;
#endif
} }
// If indenting not disabled, add line break after node // If indenting not disabled, add line break after node

View File

@ -25,14 +25,14 @@
* Redistributions in binary form must reproduce the above copyright * Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution. documentation and/or other materials provided with the distribution.
* Neither the name of the copyright holder nor the * Neither the name of cereal nor the
names of its contributors may be used to endorse or promote products names of its contributors may be used to endorse or promote products
derived from this software without specific prior written permission. derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 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 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DISCLAIMED. IN NO EVENT SHALL RANDOLPH VOORHIES OR SHANE GRANT BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
@ -51,25 +51,11 @@
Note that even with this enabled you must still ensure that Note that even with this enabled you must still ensure that
archives are accessed by only one thread at a time; it is safe archives are accessed by only one thread at a time; it is safe
to use multiple archives in parallel, but not to access one archive to use multiple archives in paralel, but not to access one archive
from many places simultaneously. */ from many places simultaneously. */
#define CEREAL_THREAD_SAFE 0 #define CEREAL_THREAD_SAFE 0
#endif // CEREAL_THREAD_SAFE #endif // CEREAL_THREAD_SAFE
#ifndef CEREAL_SIZE_TYPE
//! Determines the data type used for size_type
/*! cereal uses size_type to ensure that the serialized size of
dynamic containers is compatible across different architectures
(e.g. 32 vs 64 bit), which may use different underlying types for
std::size_t.
More information can be found in cereal/details/helpers.hpp.
If you choose to modify this type, ensure that you use a fixed
size type (e.g. uint32_t). */
#define CEREAL_SIZE_TYPE uint64_t
#endif // CEREAL_SIZE_TYPE
// ###################################################################### // ######################################################################
#ifndef CEREAL_SERIALIZE_FUNCTION_NAME #ifndef CEREAL_SERIALIZE_FUNCTION_NAME
//! The serialization/deserialization function name to search for. //! The serialization/deserialization function name to search for.
@ -132,25 +118,4 @@
#endif // end !defined(CEREAL_HAS_NOEXCEPT) #endif // end !defined(CEREAL_HAS_NOEXCEPT)
#endif // ifndef CEREAL_NOEXCEPT #endif // ifndef CEREAL_NOEXCEPT
// ######################################################################
//! Checks if C++17 is available
//! NOTE: clang v5 has a bug with inline variables, so disable C++17 on that compiler
#if (__cplusplus >= 201703L || (defined(_MSVC_LANG) && _MSVC_LANG >= 201703L)) \
&& (!defined(__clang__) || __clang_major__ > 5)
#define CEREAL_HAS_CPP17
#endif
//! Checks if C++14 is available
#if (__cplusplus >= 201402L || (defined(_MSVC_LANG) && _MSVC_LANG >= 201402L))
#define CEREAL_HAS_CPP14
#endif
// ######################################################################
//! Defines the CEREAL_ALIGNOF macro to use instead of alignof
#if defined(_MSC_VER) && _MSC_VER < 1900
#define CEREAL_ALIGNOF __alignof
#else // not MSVC 2013 or older
#define CEREAL_ALIGNOF alignof
#endif // end MSVC check
#endif // CEREAL_MACROS_HPP_ #endif // CEREAL_MACROS_HPP_

View File

@ -1,139 +0,0 @@
/*! \file specialize.hpp
\brief 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 the copyright holder 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 THE COPYRIGHT HOLDER OR CONTRIBUTORS 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_SPECIALIZE_HPP_
#define CEREAL_SPECIALIZE_HPP_
namespace cereal
{
// Forward declaration of access class that users can become friends with
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> {}; }
}
#endif

View File

@ -12,14 +12,14 @@
* Redistributions in binary form must reproduce the above copyright * Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution. documentation and/or other materials provided with the distribution.
* Neither the name of the copyright holder nor the * Neither the name of cereal nor the
names of its contributors may be used to endorse or promote products names of its contributors may be used to endorse or promote products
derived from this software without specific prior written permission. derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 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 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DISCLAIMED. IN NO EVENT SHALL RANDOLPH VOORHIES OR SHANE GRANT BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
@ -30,7 +30,7 @@
#ifndef CEREAL_TYPES_ARRAY_HPP_ #ifndef CEREAL_TYPES_ARRAY_HPP_
#define CEREAL_TYPES_ARRAY_HPP_ #define CEREAL_TYPES_ARRAY_HPP_
#include "cereal/cereal.hpp" #include <cereal/cereal.hpp>
#include <array> #include <array>
namespace cereal namespace cereal
@ -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(), N*sizeof(T) ) ); ar( binary_data( array.data(), sizeof(array) ) );
} }
//! 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(), N*sizeof(T) ) ); ar( binary_data( array.data(), sizeof(array) ) );
} }
//! Saving for std::array all other types //! Saving for std::array all other types

View File

@ -1,55 +0,0 @@
/*! \file atomic.hpp
\brief Support for types found in \<atomic\>
\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 the copyright holder 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 THE COPYRIGHT HOLDER OR CONTRIBUTORS 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_ATOMIC_HPP_
#define CEREAL_TYPES_ATOMIC_HPP_
#include <cereal/cereal.hpp>
#include <atomic>
namespace cereal
{
//! Serializing (save) for std::atomic
template <class Archive, class T> inline
void CEREAL_SAVE_FUNCTION_NAME( Archive & ar, std::atomic<T> const & a )
{
ar( CEREAL_NVP_("atomic_data", a.load()) );
}
//! Serializing (load) for std::atomic
template <class Archive, class T> inline
void CEREAL_LOAD_FUNCTION_NAME( Archive & ar, std::atomic<T> & a )
{
T tmp;
ar( CEREAL_NVP_("atomic_data", tmp) );
a.store( tmp );
}
} // namespace cereal
#endif // CEREAL_TYPES_ATOMIC_HPP_

View File

@ -12,14 +12,14 @@
* Redistributions in binary form must reproduce the above copyright * Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution. documentation and/or other materials provided with the distribution.
* Neither the name of the copyright holder nor the * Neither the name of cereal nor the
names of its contributors may be used to endorse or promote products names of its contributors may be used to endorse or promote products
derived from this software without specific prior written permission. derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 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 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DISCLAIMED. IN NO EVENT SHALL RANDOLPH VOORHIES OR SHANE GRANT BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
@ -30,8 +30,8 @@
#ifndef CEREAL_TYPES_BASE_CLASS_HPP_ #ifndef CEREAL_TYPES_BASE_CLASS_HPP_
#define CEREAL_TYPES_BASE_CLASS_HPP_ #define CEREAL_TYPES_BASE_CLASS_HPP_
#include "cereal/details/traits.hpp" #include <cereal/details/traits.hpp>
#include "cereal/details/polymorphic_impl_fwd.hpp" #include <cereal/details/polymorphic_impl_fwd.hpp>
namespace cereal namespace cereal
{ {
@ -63,8 +63,7 @@ namespace cereal
This also automatically registers polymorphic relation between the base and derived class, assuming they This also automatically registers polymorphic relation between the base and derived class, assuming they
are indeed polymorphic. Note this is not the same as polymorphic type registration. For more information are indeed polymorphic. Note this is not the same as polymorphic type registration. For more information
see the documentation on polymorphism. If using a polymorphic class, be sure to include support for see the documentation on polymorphism.
polymorphism (cereal/types/polymorphic.hpp).
\sa virtual_base_class \sa virtual_base_class
@ -121,8 +120,7 @@ namespace cereal
This also automatically registers polymorphic relation between the base and derived class, assuming they This also automatically registers polymorphic relation between the base and derived class, assuming they
are indeed polymorphic. Note this is not the same as polymorphic type registration. For more information are indeed polymorphic. Note this is not the same as polymorphic type registration. For more information
see the documentation on polymorphism. If using a polymorphic class, be sure to include support for see the documentation on polymorphism.
polymorphism (cereal/types/polymorphic.hpp).
\sa base_class \sa base_class

View File

@ -12,14 +12,14 @@
* Redistributions in binary form must reproduce the above copyright * Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution. documentation and/or other materials provided with the distribution.
* Neither the name of the copyright holder nor the * Neither the name of cereal nor the
names of its contributors may be used to endorse or promote products names of its contributors may be used to endorse or promote products
derived from this software without specific prior written permission. derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 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 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DISCLAIMED. IN NO EVENT SHALL RANDOLPH VOORHIES OR SHANE GRANT BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
@ -30,8 +30,8 @@
#ifndef CEREAL_TYPES_BITSET_HPP_ #ifndef CEREAL_TYPES_BITSET_HPP_
#define CEREAL_TYPES_BITSET_HPP_ #define CEREAL_TYPES_BITSET_HPP_
#include "cereal/cereal.hpp" #include <cereal/cereal.hpp>
#include "cereal/types/string.hpp" #include <cereal/types/string.hpp>
#include <bitset> #include <bitset>
namespace cereal namespace cereal
@ -67,7 +67,7 @@ namespace cereal
if( bits[i] ) if( bits[i] )
chunk |= mask; chunk |= mask;
mask = static_cast<std::uint8_t>(mask >> 1); mask >>= 1;
// output current chunk when mask is empty (8 bits) // output current chunk when mask is empty (8 bits)
if( mask == 0 ) if( mask == 0 )
@ -148,8 +148,6 @@ namespace cereal
std::uint8_t chunk = 0; std::uint8_t chunk = 0;
std::uint8_t mask = 0; std::uint8_t mask = 0;
bits.reset();
// Load one chunk at a time, rotating through the chunk // Load one chunk at a time, rotating through the chunk
// to set bits in the bitset // to set bits in the bitset
for( std::size_t i = 0; i < N; ++i ) for( std::size_t i = 0; i < N; ++i )
@ -163,7 +161,7 @@ namespace cereal
if( chunk & mask ) if( chunk & mask )
bits[i] = 1; bits[i] = 1;
mask = static_cast<std::uint8_t>(mask >> 1); mask >>= 1;
} }
break; break;
} }

View File

@ -12,14 +12,14 @@
* Redistributions in binary form must reproduce the above copyright * Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution. documentation and/or other materials provided with the distribution.
* Neither the name of the copyright holder nor the * Neither the name of cereal nor the
names of its contributors may be used to endorse or promote products names of its contributors may be used to endorse or promote products
derived from this software without specific prior written permission. derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 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 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DISCLAIMED. IN NO EVENT SHALL RANDOLPH VOORHIES OR SHANE GRANT BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
@ -30,20 +30,13 @@
#ifndef CEREAL_TYPES_BOOST_VARIANT_HPP_ #ifndef CEREAL_TYPES_BOOST_VARIANT_HPP_
#define CEREAL_TYPES_BOOST_VARIANT_HPP_ #define CEREAL_TYPES_BOOST_VARIANT_HPP_
//! @internal #include <cereal/cereal.hpp>
#if defined(_MSC_VER) && _MSC_VER < 1911 #include <boost/variant.hpp>
#define CEREAL_CONSTEXPR_LAMBDA #include <boost/mpl/size.hpp>
#else // MSVC 2017 or newer, all other compilers
#define CEREAL_CONSTEXPR_LAMBDA constexpr
#endif
#include "cereal/cereal.hpp"
#include <boost/variant/variant_fwd.hpp>
#include <boost/variant/static_visitor.hpp>
namespace cereal namespace cereal
{ {
namespace boost_variant_detail namespace variant_detail
{ {
//! @internal //! @internal
template <class Archive> template <class Archive>
@ -61,104 +54,53 @@ namespace cereal
}; };
//! @internal //! @internal
template <class Archive, class T> template<int N, class Variant, class ... Args, class Archive>
struct LoadAndConstructLoadWrapper typename std::enable_if<N == boost::mpl::size<typename Variant::types>::value, void>::type
load_variant(Archive & /*ar*/, int /*target*/, Variant & /*variant*/)
{ {
using ST = typename std::aligned_storage<sizeof(T), CEREAL_ALIGNOF(T)>::type; throw ::cereal::Exception("Error traversing variant during load");
LoadAndConstructLoadWrapper() :
construct( reinterpret_cast<T *>( &st ) )
{ }
~LoadAndConstructLoadWrapper()
{
if (construct.itsValid)
{
construct->~T();
} }
}
void CEREAL_SERIALIZE_FUNCTION_NAME( Archive & ar )
{
::cereal::detail::Construct<T, Archive>::load_andor_construct( ar, construct );
}
ST st;
::cereal::construct<T> construct;
};
//! @internal //! @internal
template <class T> struct load_variant_wrapper; 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
//! Avoid serializing variant void_ type load_variant(Archive & ar, int target, Variant & variant)
/*! @internal */
template <>
struct load_variant_wrapper<boost::detail::variant::void_>
{ {
template <class Variant, class Archive> if(N == target)
static void load_variant( Archive &, Variant & )
{ }
};
//! @internal
template <class T>
struct load_variant_wrapper
{ {
// default constructible H value;
template <class Archive, class Variant>
static void load_variant_impl( Archive & ar, Variant & variant, std::true_type )
{
T value;
ar( CEREAL_NVP_("data", value) ); ar( CEREAL_NVP_("data", value) );
variant = std::move(value); variant = value;
}
else
load_variant<N+1, Variant, T...>(ar, target, variant);
} }
// not default constructible } // namespace variant_detail
template<class Variant, class Archive>
static void load_variant_impl(Archive & ar, Variant & variant, std::false_type )
{
LoadAndConstructLoadWrapper<Archive, T> loadWrapper;
ar( CEREAL_NVP_("data", loadWrapper) );
variant = std::move(*loadWrapper.construct.ptr());
}
//! @internal
template<class Variant, class Archive>
static void load_variant(Archive & ar, Variant & variant)
{
load_variant_impl( ar, variant, typename std::is_default_constructible<T>::type() );
}
};
} // namespace boost_variant_detail
//! Saving for boost::variant //! Saving for boost::variant
template <class Archive, typename ... VariantTypes> inline template <class Archive, typename VariantType1, typename... VariantTypes> inline
void CEREAL_SAVE_FUNCTION_NAME( Archive & ar, boost::variant<VariantTypes...> const & variant ) void CEREAL_SAVE_FUNCTION_NAME( Archive & ar, boost::variant<VariantType1, VariantTypes...> const & variant )
{ {
int32_t which = variant.which(); int32_t which = variant.which();
ar( CEREAL_NVP_("which", which) ); ar( CEREAL_NVP_("which", which) );
boost_variant_detail::variant_save_visitor<Archive> visitor(ar); variant_detail::variant_save_visitor<Archive> visitor(ar);
variant.apply_visitor(visitor); variant.apply_visitor(visitor);
} }
//! Loading for boost::variant //! Loading for boost::variant
template <class Archive, typename ... VariantTypes> inline template <class Archive, typename VariantType1, typename... VariantTypes> inline
void CEREAL_LOAD_FUNCTION_NAME( Archive & ar, boost::variant<VariantTypes...> & variant ) void CEREAL_LOAD_FUNCTION_NAME( Archive & ar, boost::variant<VariantType1, VariantTypes...> & variant )
{ {
typedef typename boost::variant<VariantType1, VariantTypes...>::types types;
int32_t which; int32_t which;
ar( CEREAL_NVP_("which", which) ); ar( CEREAL_NVP_("which", which) );
if(which >= boost::mpl::size<types>::value)
using LoadFuncType = void(*)(Archive &, boost::variant<VariantTypes...> &);
CEREAL_CONSTEXPR_LAMBDA LoadFuncType loadFuncArray[] = {&boost_variant_detail::load_variant_wrapper<VariantTypes>::load_variant...};
if(which >= int32_t(sizeof(loadFuncArray)/sizeof(loadFuncArray[0])))
throw Exception("Invalid 'which' selector when deserializing boost::variant"); throw Exception("Invalid 'which' selector when deserializing boost::variant");
loadFuncArray[which](ar, variant); variant_detail::load_variant<0, boost::variant<VariantType1, VariantTypes...>, VariantType1, VariantTypes...>(ar, which, variant);
} }
} // namespace cereal } // namespace cereal
#undef CEREAL_CONSTEXPR_LAMBDA
#endif // CEREAL_TYPES_BOOST_VARIANT_HPP_ #endif // CEREAL_TYPES_BOOST_VARIANT_HPP_

View File

@ -12,14 +12,14 @@
* Redistributions in binary form must reproduce the above copyright * Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution. documentation and/or other materials provided with the distribution.
* Neither the name of the copyright holder nor the * Neither the name of cereal nor the
names of its contributors may be used to endorse or promote products names of its contributors may be used to endorse or promote products
derived from this software without specific prior written permission. derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 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 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DISCLAIMED. IN NO EVENT SHALL RANDOLPH VOORHIES OR SHANE GRANT BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND

View File

@ -12,14 +12,14 @@
* Redistributions in binary form must reproduce the above copyright * Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution. documentation and/or other materials provided with the distribution.
* Neither the name of the copyright holder nor the * Neither the name of cereal nor the
names of its contributors may be used to endorse or promote products names of its contributors may be used to endorse or promote products
derived from this software without specific prior written permission. derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 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 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DISCLAIMED. IN NO EVENT SHALL RANDOLPH VOORHIES OR SHANE GRANT BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
@ -30,7 +30,7 @@
#ifndef CEREAL_TYPES_COMMON_HPP_ #ifndef CEREAL_TYPES_COMMON_HPP_
#define CEREAL_TYPES_COMMON_HPP_ #define CEREAL_TYPES_COMMON_HPP_
#include "cereal/cereal.hpp" #include <cereal/cereal.hpp>
namespace cereal namespace cereal
{ {

View File

@ -12,14 +12,14 @@
* Redistributions in binary form must reproduce the above copyright * Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution. documentation and/or other materials provided with the distribution.
* Neither the name of the copyright holder nor the * Neither the name of cereal nor the
names of its contributors may be used to endorse or promote products names of its contributors may be used to endorse or promote products
derived from this software without specific prior written permission. derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 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 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DISCLAIMED. IN NO EVENT SHALL RANDOLPH VOORHIES OR SHANE GRANT BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND

View File

@ -13,14 +13,14 @@
* Redistributions in binary form must reproduce the above copyright * Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution. documentation and/or other materials provided with the distribution.
* Neither the name of the copyright holder nor the * Neither the name of cereal nor the
names of its contributors may be used to endorse or promote products names of its contributors may be used to endorse or promote products
derived from this software without specific prior written permission. derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 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 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DISCLAIMED. IN NO EVENT SHALL RANDOLPH VOORHIES OR SHANE GRANT BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
@ -31,7 +31,7 @@
#ifndef CEREAL_CONCEPTS_PAIR_ASSOCIATIVE_CONTAINER_HPP_ #ifndef CEREAL_CONCEPTS_PAIR_ASSOCIATIVE_CONTAINER_HPP_
#define CEREAL_CONCEPTS_PAIR_ASSOCIATIVE_CONTAINER_HPP_ #define CEREAL_CONCEPTS_PAIR_ASSOCIATIVE_CONTAINER_HPP_
#include "cereal/cereal.hpp" #include <cereal/cereal.hpp>
namespace cereal namespace cereal
{ {

View File

@ -12,14 +12,14 @@
* Redistributions in binary form must reproduce the above copyright * Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution. documentation and/or other materials provided with the distribution.
* Neither the name of the copyright holder nor the * Neither the name of cereal nor the
names of its contributors may be used to endorse or promote products names of its contributors may be used to endorse or promote products
derived from this software without specific prior written permission. derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 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 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DISCLAIMED. IN NO EVENT SHALL RANDOLPH VOORHIES OR SHANE GRANT BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
@ -30,7 +30,7 @@
#ifndef CEREAL_TYPES_DEQUE_HPP_ #ifndef CEREAL_TYPES_DEQUE_HPP_
#define CEREAL_TYPES_DEQUE_HPP_ #define CEREAL_TYPES_DEQUE_HPP_
#include "cereal/cereal.hpp" #include <cereal/cereal.hpp>
#include <deque> #include <deque>
namespace cereal namespace cereal

View File

@ -12,14 +12,14 @@
* Redistributions in binary form must reproduce the above copyright * Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution. documentation and/or other materials provided with the distribution.
* Neither the name of the copyright holder nor the * Neither the name of cereal nor the
names of its contributors may be used to endorse or promote products names of its contributors may be used to endorse or promote products
derived from this software without specific prior written permission. derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 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 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DISCLAIMED. IN NO EVENT SHALL RANDOLPH VOORHIES OR SHANE GRANT BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
@ -30,7 +30,7 @@
#ifndef CEREAL_TYPES_FORWARD_LIST_HPP_ #ifndef CEREAL_TYPES_FORWARD_LIST_HPP_
#define CEREAL_TYPES_FORWARD_LIST_HPP_ #define CEREAL_TYPES_FORWARD_LIST_HPP_
#include "cereal/cereal.hpp" #include <cereal/cereal.hpp>
#include <forward_list> #include <forward_list>
namespace cereal namespace cereal

View File

@ -12,14 +12,14 @@
* Redistributions in binary form must reproduce the above copyright * Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution. documentation and/or other materials provided with the distribution.
* Neither the name of the copyright holder nor the * Neither the name of cereal nor the
names of its contributors may be used to endorse or promote products names of its contributors may be used to endorse or promote products
derived from this software without specific prior written permission. derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 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 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DISCLAIMED. IN NO EVENT SHALL RANDOLPH VOORHIES OR SHANE GRANT BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND

View File

@ -12,14 +12,14 @@
* Redistributions in binary form must reproduce the above copyright * Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution. documentation and/or other materials provided with the distribution.
* Neither the name of the copyright holder nor the * Neither the name of cereal nor the
names of its contributors may be used to endorse or promote products names of its contributors may be used to endorse or promote products
derived from this software without specific prior written permission. derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 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 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DISCLAIMED. IN NO EVENT SHALL RANDOLPH VOORHIES OR SHANE GRANT BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
@ -30,7 +30,7 @@
#ifndef CEREAL_TYPES_LIST_HPP_ #ifndef CEREAL_TYPES_LIST_HPP_
#define CEREAL_TYPES_LIST_HPP_ #define CEREAL_TYPES_LIST_HPP_
#include "cereal/cereal.hpp" #include <cereal/cereal.hpp>
#include <list> #include <list>
namespace cereal namespace cereal

View File

@ -12,14 +12,14 @@
* Redistributions in binary form must reproduce the above copyright * Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution. documentation and/or other materials provided with the distribution.
* Neither the name of the copyright holder nor the * Neither the name of cereal nor the
names of its contributors may be used to endorse or promote products names of its contributors may be used to endorse or promote products
derived from this software without specific prior written permission. derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 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 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DISCLAIMED. IN NO EVENT SHALL RANDOLPH VOORHIES OR SHANE GRANT BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
@ -30,7 +30,7 @@
#ifndef CEREAL_TYPES_MAP_HPP_ #ifndef CEREAL_TYPES_MAP_HPP_
#define CEREAL_TYPES_MAP_HPP_ #define CEREAL_TYPES_MAP_HPP_
#include "cereal/types/concepts/pair_associative_container.hpp" #include <cereal/types/concepts/pair_associative_container.hpp>
#include <map> #include <map>
#endif // CEREAL_TYPES_MAP_HPP_ #endif // CEREAL_TYPES_MAP_HPP_

View File

@ -12,14 +12,14 @@
* Redistributions in binary form must reproduce the above copyright * Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution. documentation and/or other materials provided with the distribution.
* Neither the name of the copyright holder nor the * Neither the name of cereal nor the
names of its contributors may be used to endorse or promote products names of its contributors may be used to endorse or promote products
derived from this software without specific prior written permission. derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 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 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DISCLAIMED. IN NO EVENT SHALL RANDOLPH VOORHIES OR SHANE GRANT BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
@ -30,10 +30,17 @@
#ifndef CEREAL_TYPES_SHARED_PTR_HPP_ #ifndef CEREAL_TYPES_SHARED_PTR_HPP_
#define CEREAL_TYPES_SHARED_PTR_HPP_ #define CEREAL_TYPES_SHARED_PTR_HPP_
#include "cereal/cereal.hpp" #include <cereal/cereal.hpp>
#include <memory> #include <memory>
#include <cstring> #include <cstring>
// Work around MSVC not having alignof
#if defined(_MSC_VER) && _MSC_VER < 1900
#define CEREAL_ALIGNOF __alignof
#else // not MSVC 2013 or older
#define CEREAL_ALIGNOF alignof
#endif // end MSVC check
namespace cereal namespace cereal
{ {
namespace memory_detail namespace memory_detail
@ -47,7 +54,6 @@ namespace cereal
PtrWrapper(T && p) : ptr(std::forward<T>(p)) {} PtrWrapper(T && p) : ptr(std::forward<T>(p)) {}
T & ptr; T & ptr;
PtrWrapper( PtrWrapper const & ) = default;
PtrWrapper & operator=( PtrWrapper const & ) = delete; PtrWrapper & operator=( PtrWrapper const & ) = delete;
}; };
@ -104,11 +110,6 @@ namespace cereal
portion of the class and replace it after whatever happens to modify it (e.g. the 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). user performing construction or the wrapper shared_ptr in saving).
Note that this goes into undefined behavior territory, but as of the initial writing
of this, all standard library implementations of std::enable_shared_from_this are
compatible with this memory manipulation. It is entirely possible that this may someday
break or may not work with convoluted use cases.
Example usage: Example usage:
@code{.cpp} @code{.cpp}
@ -152,8 +153,7 @@ namespace cereal
{ {
if( !itsRestored ) if( !itsRestored )
{ {
// void * cast needed when type has no trivial copy-assignment std::memcpy( itsPtr, &itsState, sizeof(ParentType) );
std::memcpy( static_cast<void *>(itsPtr), &itsState, sizeof(ParentType) );
itsRestored = true; itsRestored = true;
} }
} }
@ -263,7 +263,7 @@ namespace cereal
{ {
auto & ptr = wrapper.ptr; auto & ptr = wrapper.ptr;
uint32_t id = ar.registerSharedPointer( ptr ); uint32_t id = ar.registerSharedPointer( ptr.get() );
ar( CEREAL_NVP_("id", id) ); ar( CEREAL_NVP_("id", id) );
if( id & detail::msb_32bit ) if( id & detail::msb_32bit )
@ -278,6 +278,8 @@ namespace cereal
typename std::enable_if<traits::has_load_and_construct<T, Archive>::value, void>::type 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 ) CEREAL_LOAD_FUNCTION_NAME( Archive & ar, memory_detail::PtrWrapper<std::shared_ptr<T> &> & wrapper )
{ {
auto & ptr = wrapper.ptr;
uint32_t id; uint32_t id;
ar( CEREAL_NVP_("id", id) ); ar( CEREAL_NVP_("id", id) );
@ -286,7 +288,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 AlignedStorage = typename std::aligned_storage<sizeof(T), CEREAL_ALIGNOF(T)>::type; using ST = 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
@ -295,28 +297,26 @@ 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; ptr.reset( reinterpret_cast<T *>( new ST() ),
std::shared_ptr<NonConstT> ptr(reinterpret_cast<NonConstT *>(new AlignedStorage()), [=]( T * t )
[=]( NonConstT * t )
{ {
if( *valid ) if( *valid )
t->~T(); t->~T();
delete reinterpret_cast<AlignedStorage*>( t ); delete reinterpret_cast<ST *>( t );
} ); } );
// Register the pointer // Register the pointer
ar.registerSharedPointer( id, ptr ); ar.registerSharedPointer( id, ptr );
// Perform the actual loading and allocation // Perform the actual loading and allocation
memory_detail::loadAndConstructSharedPtr( ar, ptr.get(), typename ::cereal::traits::has_shared_from_this<NonConstT>::type() ); memory_detail::loadAndConstructSharedPtr( ar, ptr.get(), typename ::cereal::traits::has_shared_from_this<T>::type() );
// Mark pointer as valid (initialized) // Mark pointer as valid (initialized)
*valid = true; *valid = true;
wrapper.ptr = std::move(ptr);
} }
else else
wrapper.ptr = std::static_pointer_cast<T>(ar.getSharedPointer(id)); ptr = std::static_pointer_cast<T>(ar.getSharedPointer(id));
} }
//! Loading std::shared_ptr, case when no user load and construct (wrapper implementation) //! Loading std::shared_ptr, case when no user load and construct (wrapper implementation)
@ -325,20 +325,20 @@ namespace cereal
typename std::enable_if<!traits::has_load_and_construct<T, Archive>::value, void>::type 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 ) CEREAL_LOAD_FUNCTION_NAME( Archive & ar, memory_detail::PtrWrapper<std::shared_ptr<T> &> & wrapper )
{ {
auto & ptr = wrapper.ptr;
uint32_t id; uint32_t id;
ar( CEREAL_NVP_("id", id) ); ar( CEREAL_NVP_("id", id) );
if( id & detail::msb_32bit ) if( id & detail::msb_32bit )
{ {
using NonConstT = typename std::remove_const<T>::type; ptr.reset( detail::Construct<T, Archive>::load_andor_construct() );
std::shared_ptr<NonConstT> ptr( detail::Construct<NonConstT, Archive>::load_andor_construct() );
ar.registerSharedPointer( id, ptr ); ar.registerSharedPointer( id, ptr );
ar( CEREAL_NVP_("data", *ptr) ); ar( CEREAL_NVP_("data", *ptr) );
wrapper.ptr = std::move(ptr);
} }
else else
wrapper.ptr = std::static_pointer_cast<T>(ar.getSharedPointer(id)); ptr = std::static_pointer_cast<T>(ar.getSharedPointer(id));
} }
//! Saving std::unique_ptr (wrapper implementation) //! Saving std::unique_ptr (wrapper implementation)
@ -374,17 +374,16 @@ namespace cereal
if( isValid ) if( isValid )
{ {
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 AlignedStorage = typename std::aligned_storage<sizeof(NonConstT), CEREAL_ALIGNOF(NonConstT)>::type; using ST = typename std::aligned_storage<sizeof(T), CEREAL_ALIGNOF(T)>::type;
// Allocate storage - note the AlignedStorage type so that deleter is correct if // Allocate storage - note the ST 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<AlignedStorage> stPtr( new AlignedStorage() ); std::unique_ptr<ST> stPtr( new ST() );
// 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, T> loadWrapper( reinterpret_cast<T *>( stPtr.get() ) );
// Initialize storage // Initialize storage
ar( CEREAL_NVP_("data", loadWrapper) ); ar( CEREAL_NVP_("data", loadWrapper) );
@ -405,21 +404,22 @@ namespace cereal
uint8_t isValid; uint8_t isValid;
ar( CEREAL_NVP_("valid", isValid) ); ar( CEREAL_NVP_("valid", isValid) );
auto & ptr = wrapper.ptr;
if( isValid ) if( isValid )
{ {
using NonConstT = typename std::remove_const<T>::type; ptr.reset( detail::Construct<T, Archive>::load_andor_construct() );
std::unique_ptr<NonConstT, D> ptr( detail::Construct<NonConstT, Archive>::load_andor_construct() );
ar( CEREAL_NVP_( "data", *ptr ) ); ar( CEREAL_NVP_( "data", *ptr ) );
wrapper.ptr = std::move(ptr);
} }
else else
{ {
wrapper.ptr.reset( nullptr ); ptr.reset( nullptr );
} }
} }
} // namespace cereal } // namespace cereal
// automatically include polymorphic support // automatically include polymorphic support
#include "cereal/types/polymorphic.hpp" #include <cereal/types/polymorphic.hpp>
#undef CEREAL_ALIGNOF
#endif // CEREAL_TYPES_SHARED_PTR_HPP_ #endif // CEREAL_TYPES_SHARED_PTR_HPP_

View File

@ -1,65 +0,0 @@
/*! \file optional.hpp
\brief Support for std::optional
\ingroup STLSupport */
/*
Copyright (c) 2017, Juan Pedro Bolivar Puente
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 the copyright holder 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 THE COPYRIGHT HOLDER OR CONTRIBUTORS 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_STD_OPTIONAL_
#define CEREAL_TYPES_STD_OPTIONAL_
#include "cereal/cereal.hpp"
#include <optional>
namespace cereal {
//! Saving for std::optional
template <class Archive, typename T> inline
void CEREAL_SAVE_FUNCTION_NAME(Archive& ar, const std::optional<T>& optional)
{
if(!optional) {
ar(CEREAL_NVP_("nullopt", true));
} else {
ar(CEREAL_NVP_("nullopt", false),
CEREAL_NVP_("data", *optional));
}
}
//! Loading for std::optional
template <class Archive, typename T> inline
void CEREAL_LOAD_FUNCTION_NAME(Archive& ar, std::optional<T>& optional)
{
bool nullopt;
ar(CEREAL_NVP_("nullopt", nullopt));
if (nullopt) {
optional = std::nullopt;
} else {
optional.emplace();
ar(CEREAL_NVP_("data", *optional));
}
}
} // namespace cereal
#endif // CEREAL_TYPES_STD_OPTIONAL_

View File

@ -12,14 +12,14 @@
* Redistributions in binary form must reproduce the above copyright * Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution. documentation and/or other materials provided with the distribution.
* Neither the name of the copyright holder nor the * Neither the name of cereal nor the
names of its contributors may be used to endorse or promote products names of its contributors may be used to endorse or promote products
derived from this software without specific prior written permission. derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 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 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DISCLAIMED. IN NO EVENT SHALL RANDOLPH VOORHIES OR SHANE GRANT BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
@ -30,15 +30,15 @@
#ifndef CEREAL_TYPES_POLYMORPHIC_HPP_ #ifndef CEREAL_TYPES_POLYMORPHIC_HPP_
#define CEREAL_TYPES_POLYMORPHIC_HPP_ #define CEREAL_TYPES_POLYMORPHIC_HPP_
#include "cereal/cereal.hpp" #include <cereal/cereal.hpp>
#include "cereal/types/memory.hpp" #include <cereal/types/memory.hpp>
#include "cereal/details/util.hpp" #include <cereal/details/util.hpp>
#include "cereal/details/helpers.hpp" #include <cereal/details/helpers.hpp>
#include "cereal/details/traits.hpp" #include <cereal/details/traits.hpp>
#include "cereal/details/polymorphic_impl.hpp" #include <cereal/details/polymorphic_impl.hpp>
#if defined(_MSC_VER) && _MSC_VER < 1916 #ifdef _MSC_VER
#define CEREAL_STATIC_CONSTEXPR static #define CEREAL_STATIC_CONSTEXPR static
#else #else
#define CEREAL_STATIC_CONSTEXPR static constexpr #define CEREAL_STATIC_CONSTEXPR static constexpr
@ -168,16 +168,14 @@
#define CEREAL_FORCE_DYNAMIC_INIT(LibName) \ #define CEREAL_FORCE_DYNAMIC_INIT(LibName) \
namespace cereal { \ namespace cereal { \
namespace detail { \ namespace detail { \
void CEREAL_DLL_EXPORT dynamic_init_dummy_##LibName(); \ void dynamic_init_dummy_##LibName(); \
} /* end detail */ \ } /* end detail */ \
} /* end cereal */ \
namespace { \ namespace { \
struct dynamic_init_##LibName { \ void dynamic_init_##LibName() \
dynamic_init_##LibName() { \ { \
::cereal::detail::dynamic_init_dummy_##LibName(); \ ::cereal::detail::dynamic_init_dummy_##LibName(); \
} \ } \
} dynamic_init_instance_##LibName; \ } } /* end namespaces */
} /* end anonymous namespace */
namespace cereal namespace cereal
{ {

View File

@ -12,14 +12,14 @@
* Redistributions in binary form must reproduce the above copyright * Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution. documentation and/or other materials provided with the distribution.
* Neither the name of the copyright holder nor the * Neither the name of cereal nor the
names of its contributors may be used to endorse or promote products names of its contributors may be used to endorse or promote products
derived from this software without specific prior written permission. derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 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 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DISCLAIMED. IN NO EVENT SHALL RANDOLPH VOORHIES OR SHANE GRANT BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
@ -30,13 +30,13 @@
#ifndef CEREAL_TYPES_QUEUE_HPP_ #ifndef CEREAL_TYPES_QUEUE_HPP_
#define CEREAL_TYPES_QUEUE_HPP_ #define CEREAL_TYPES_QUEUE_HPP_
#include "cereal/details/helpers.hpp" #include <cereal/details/helpers.hpp>
#include <queue> #include <queue>
// The default container for queue is deque, so let's include that too // The default container for queue is deque, so let's include that too
#include "cereal/types/deque.hpp" #include <cereal/types/deque.hpp>
// The default comparator for queue is less // The default comparator for queue is less
#include "cereal/types/functional.hpp" #include <cereal/types/functional.hpp>
namespace cereal namespace cereal
{ {

View File

@ -12,14 +12,14 @@
* Redistributions in binary form must reproduce the above copyright * Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution. documentation and/or other materials provided with the distribution.
* Neither the name of the copyright holder nor the * Neither the name of cereal nor the
names of its contributors may be used to endorse or promote products names of its contributors may be used to endorse or promote products
derived from this software without specific prior written permission. derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 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 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DISCLAIMED. IN NO EVENT SHALL RANDOLPH VOORHIES OR SHANE GRANT BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
@ -30,7 +30,7 @@
#ifndef CEREAL_TYPES_SET_HPP_ #ifndef CEREAL_TYPES_SET_HPP_
#define CEREAL_TYPES_SET_HPP_ #define CEREAL_TYPES_SET_HPP_
#include "cereal/cereal.hpp" #include <cereal/cereal.hpp>
#include <set> #include <set>
namespace cereal namespace cereal

View File

@ -12,14 +12,14 @@
* Redistributions in binary form must reproduce the above copyright * Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution. documentation and/or other materials provided with the distribution.
* Neither the name of the copyright holder nor the * Neither the name of cereal nor the
names of its contributors may be used to endorse or promote products names of its contributors may be used to endorse or promote products
derived from this software without specific prior written permission. derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 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 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DISCLAIMED. IN NO EVENT SHALL RANDOLPH VOORHIES OR SHANE GRANT BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
@ -30,11 +30,11 @@
#ifndef CEREAL_TYPES_STACK_HPP_ #ifndef CEREAL_TYPES_STACK_HPP_
#define CEREAL_TYPES_STACK_HPP_ #define CEREAL_TYPES_STACK_HPP_
#include "cereal/cereal.hpp" #include <cereal/cereal.hpp>
#include <stack> #include <stack>
// The default container for stack is deque, so let's include that too // The default container for stack is deque, so let's include that too
#include "cereal/types/deque.hpp" #include <cereal/types/deque.hpp>
namespace cereal namespace cereal
{ {

View File

@ -12,14 +12,14 @@
* Redistributions in binary form must reproduce the above copyright * Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution. documentation and/or other materials provided with the distribution.
* Neither the name of the copyright holder nor the * Neither the name of cereal nor the
names of its contributors may be used to endorse or promote products names of its contributors may be used to endorse or promote products
derived from this software without specific prior written permission. derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 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 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DISCLAIMED. IN NO EVENT SHALL RANDOLPH VOORHIES OR SHANE GRANT BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
@ -30,7 +30,7 @@
#ifndef CEREAL_TYPES_STRING_HPP_ #ifndef CEREAL_TYPES_STRING_HPP_
#define CEREAL_TYPES_STRING_HPP_ #define CEREAL_TYPES_STRING_HPP_
#include "cereal/cereal.hpp" #include <cereal/cereal.hpp>
#include <string> #include <string>
namespace cereal namespace cereal

View File

@ -12,14 +12,14 @@
* Redistributions in binary form must reproduce the above copyright * Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution. documentation and/or other materials provided with the distribution.
* Neither the name of the copyright holder nor the * Neither the name of cereal nor the
names of its contributors may be used to endorse or promote products names of its contributors may be used to endorse or promote products
derived from this software without specific prior written permission. derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 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 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DISCLAIMED. IN NO EVENT SHALL RANDOLPH VOORHIES OR SHANE GRANT BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
@ -30,7 +30,7 @@
#ifndef CEREAL_TYPES_TUPLE_HPP_ #ifndef CEREAL_TYPES_TUPLE_HPP_
#define CEREAL_TYPES_TUPLE_HPP_ #define CEREAL_TYPES_TUPLE_HPP_
#include "cereal/cereal.hpp" #include <cereal/cereal.hpp>
#include <tuple> #include <tuple>
namespace cereal namespace cereal
@ -38,7 +38,7 @@ namespace cereal
namespace tuple_detail namespace tuple_detail
{ {
//! Creates a c string from a sequence of characters //! Creates a c string from a sequence of characters
/*! The c string created will always be prefixed by "tuple_element" /*! The c string created will alwas be prefixed by "tuple_element"
Based on code from: http://stackoverflow/a/20973438/710791 Based on code from: http://stackoverflow/a/20973438/710791
@internal */ @internal */
template<char...Cs> template<char...Cs>
@ -63,7 +63,7 @@ namespace cereal
template <size_t Q, size_t R, char ... C> template <size_t Q, size_t R, char ... C>
struct to_string_impl struct to_string_impl
{ {
using type = typename to_string_impl<Q/10, Q%10, static_cast<char>(R+std::size_t{'0'}), C...>::type; using type = typename to_string_impl<Q/10, Q%10, R+'0', C...>::type;
}; };
//! Base case with no quotient //! Base case with no quotient
@ -71,7 +71,7 @@ namespace cereal
template <size_t R, char ... C> template <size_t R, char ... C>
struct to_string_impl<0, R, C...> struct to_string_impl<0, R, C...>
{ {
using type = char_seq_to_c_str<static_cast<char>(R+std::size_t{'0'}), C...>; using type = char_seq_to_c_str<R+'0', C...>;
}; };
//! Generates a c string for a given index of a tuple //! Generates a c string for a given index of a tuple
@ -84,7 +84,7 @@ namespace cereal
struct tuple_element_name struct tuple_element_name
{ {
using type = typename to_string_impl<T/10, T%10>::type; using type = typename to_string_impl<T/10, T%10>::type;
static const typename type::arr_type c_str(){ return type::str; } static const typename type::arr_type c_str(){ return type::str; };
}; };
// unwinds a tuple to save it // unwinds a tuple to save it

View File

@ -12,14 +12,14 @@
* Redistributions in binary form must reproduce the above copyright * Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution. documentation and/or other materials provided with the distribution.
* Neither the name of the copyright holder nor the * Neither the name of cereal nor the
names of its contributors may be used to endorse or promote products names of its contributors may be used to endorse or promote products
derived from this software without specific prior written permission. derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 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 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DISCLAIMED. IN NO EVENT SHALL RANDOLPH VOORHIES OR SHANE GRANT BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
@ -30,7 +30,7 @@
#ifndef CEREAL_TYPES_UNORDERED_MAP_HPP_ #ifndef CEREAL_TYPES_UNORDERED_MAP_HPP_
#define CEREAL_TYPES_UNORDERED_MAP_HPP_ #define CEREAL_TYPES_UNORDERED_MAP_HPP_
#include "cereal/types/concepts/pair_associative_container.hpp" #include <cereal/types/concepts/pair_associative_container.hpp>
#include <unordered_map> #include <unordered_map>
#endif // CEREAL_TYPES_UNORDERED_MAP_HPP_ #endif // CEREAL_TYPES_UNORDERED_MAP_HPP_

View File

@ -12,14 +12,14 @@
* Redistributions in binary form must reproduce the above copyright * Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution. documentation and/or other materials provided with the distribution.
* Neither the name of the copyright holder nor the * Neither the name of cereal nor the
names of its contributors may be used to endorse or promote products names of its contributors may be used to endorse or promote products
derived from this software without specific prior written permission. derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 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 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DISCLAIMED. IN NO EVENT SHALL RANDOLPH VOORHIES OR SHANE GRANT BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
@ -30,7 +30,7 @@
#ifndef CEREAL_TYPES_UNORDERED_SET_HPP_ #ifndef CEREAL_TYPES_UNORDERED_SET_HPP_
#define CEREAL_TYPES_UNORDERED_SET_HPP_ #define CEREAL_TYPES_UNORDERED_SET_HPP_
#include "cereal/cereal.hpp" #include <cereal/cereal.hpp>
#include <unordered_set> #include <unordered_set>
namespace cereal namespace cereal

View File

@ -12,14 +12,14 @@
* Redistributions in binary form must reproduce the above copyright * Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution. documentation and/or other materials provided with the distribution.
* Neither the name of the copyright holder nor the * Neither the name of cereal nor the
names of its contributors may be used to endorse or promote products names of its contributors may be used to endorse or promote products
derived from this software without specific prior written permission. derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 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 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DISCLAIMED. IN NO EVENT SHALL RANDOLPH VOORHIES OR SHANE GRANT BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
@ -30,7 +30,7 @@
#ifndef CEREAL_TYPES_UTILITY_HPP_ #ifndef CEREAL_TYPES_UTILITY_HPP_
#define CEREAL_TYPES_UTILITY_HPP_ #define CEREAL_TYPES_UTILITY_HPP_
#include "cereal/cereal.hpp" #include <cereal/cereal.hpp>
#include <utility> #include <utility>
namespace cereal namespace cereal

View File

@ -20,7 +20,7 @@ derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 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 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DISCLAIMED. IN NO EVENT SHALL RANDOLPH VOORHIES OR SHANE GRANT BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
@ -32,7 +32,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef CEREAL_TYPES_VALARRAY_HPP_ #ifndef CEREAL_TYPES_VALARRAY_HPP_
#define CEREAL_TYPES_VALARRAY_HPP_ #define CEREAL_TYPES_VALARRAY_HPP_
#include "cereal/cereal.hpp" #include <cereal/cereal.hpp>
#include <valarray> #include <valarray>
namespace cereal namespace cereal

View File

@ -1,108 +0,0 @@
/*! \file variant.hpp
\brief Support for std::variant
\ingroup STLSupport */
/*
Copyright (c) 2014, 2017, Randolph Voorhies, Shane Grant, Juan Pedro
Bolivar Puente. 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 the copyright holder 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 THE COPYRIGHT HOLDER OR CONTRIBUTORS 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_STD_VARIANT_HPP_
#define CEREAL_TYPES_STD_VARIANT_HPP_
#include "cereal/cereal.hpp"
#include <variant>
#include <cstdint>
namespace cereal
{
namespace variant_detail
{
//! @internal
template <class Archive>
struct variant_save_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 Archive>
typename std::enable_if<N == std::variant_size_v<Variant>, 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 Archive>
typename std::enable_if<N < std::variant_size_v<Variant>, void>::type
load_variant(Archive & ar, int target, Variant & variant)
{
if(N == target)
{
variant.template emplace<N>();
ar( CEREAL_NVP_("data", std::get<N>(variant)) );
}
else
load_variant<N+1>(ar, target, variant);
}
} // namespace variant_detail
//! Saving for std::variant
template <class Archive, typename VariantType1, typename... VariantTypes> inline
void CEREAL_SAVE_FUNCTION_NAME( Archive & ar, std::variant<VariantType1, VariantTypes...> const & variant )
{
std::int32_t index = static_cast<std::int32_t>(variant.index());
ar( CEREAL_NVP_("index", index) );
variant_detail::variant_save_visitor<Archive> visitor(ar);
std::visit(visitor, variant);
}
//! Loading for std::variant
template <class Archive, typename... VariantTypes> inline
void CEREAL_LOAD_FUNCTION_NAME( Archive & ar, std::variant<VariantTypes...> & variant )
{
using variant_t = typename std::variant<VariantTypes...>;
std::int32_t index;
ar( CEREAL_NVP_("index", index) );
if(index >= static_cast<std::int32_t>(std::variant_size_v<variant_t>))
throw Exception("Invalid 'index' selector when deserializing std::variant");
variant_detail::load_variant<0>(ar, index, variant);
}
//! Serializing a std::monostate
template <class Archive>
void CEREAL_SERIALIZE_FUNCTION_NAME( Archive &, std::monostate const & ) {}
} // namespace cereal
#endif // CEREAL_TYPES_STD_VARIANT_HPP_

View File

@ -12,14 +12,14 @@
* Redistributions in binary form must reproduce the above copyright * Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution. documentation and/or other materials provided with the distribution.
* Neither the name of the copyright holder nor the * Neither the name of cereal nor the
names of its contributors may be used to endorse or promote products names of its contributors may be used to endorse or promote products
derived from this software without specific prior written permission. derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 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 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DISCLAIMED. IN NO EVENT SHALL RANDOLPH VOORHIES OR SHANE GRANT BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
@ -30,7 +30,7 @@
#ifndef CEREAL_TYPES_VECTOR_HPP_ #ifndef CEREAL_TYPES_VECTOR_HPP_
#define CEREAL_TYPES_VECTOR_HPP_ #define CEREAL_TYPES_VECTOR_HPP_
#include "cereal/cereal.hpp" #include <cereal/cereal.hpp>
#include <vector> #include <vector>
namespace cereal namespace cereal
@ -60,8 +60,8 @@ namespace cereal
//! Serialization for non-arithmetic vector types //! Serialization for non-arithmetic vector types
template <class Archive, class T, class A> inline template <class Archive, class T, class A> inline
typename std::enable_if<(!traits::is_output_serializable<BinaryData<T>, Archive>::value 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 || !std::is_arithmetic<T>::value, void>::type
CEREAL_SAVE_FUNCTION_NAME( Archive & ar, std::vector<T, A> const & vector ) 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( make_size_tag( static_cast<size_type>(vector.size()) ) ); // number of elements
@ -71,8 +71,8 @@ namespace cereal
//! Serialization for non-arithmetic vector types //! Serialization for non-arithmetic vector types
template <class Archive, class T, class A> inline template <class Archive, class T, class A> inline
typename std::enable_if<(!traits::is_input_serializable<BinaryData<T>, Archive>::value 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 || !std::is_arithmetic<T>::value, void>::type
CEREAL_LOAD_FUNCTION_NAME( Archive & ar, std::vector<T, A> & vector ) CEREAL_LOAD_FUNCTION_NAME( Archive & ar, std::vector<T, A> & vector )
{ {
size_type size; size_type size;
@ -88,7 +88,7 @@ namespace cereal
void CEREAL_SAVE_FUNCTION_NAME( Archive & ar, std::vector<bool, A> const & vector ) 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 ar( make_size_tag( static_cast<size_type>(vector.size()) ) ); // number of elements
for(const auto v : vector) for(auto && v : vector)
ar( static_cast<bool>(v) ); ar( static_cast<bool>(v) );
} }

View File

@ -1,52 +0,0 @@
/*! \file version.hpp
\brief Macros to detect cereal version
These macros can assist in determining the version of cereal. Be
warned that cereal is not guaranteed to be compatible across
different versions. For more information on releases of cereal,
see https://github.com/USCiLab/cereal/releases.
\ingroup utility */
/*
Copyright (c) 2018, 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 the copyright holder 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 THE COPYRIGHT HOLDER OR CONTRIBUTORS 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_VERSION_HPP_
#define CEREAL_VERSION_HPP_
//! The major version
#define CEREAL_VERSION_MAJOR 1
//! The minor version
#define CEREAL_VERSION_MINOR 3
//! The patch version
#define CEREAL_VERSION_PATCH 2
//! The full version as a single number
#define CEREAL_VERSION (CEREAL_VERSION_MAJOR * 10000 \
+ CEREAL_VERSION_MINOR * 100 \
+ CEREAL_VERSION_PATCH)
#endif // CEREAL_VERSION_HPP_

View File

@ -1,22 +1,14 @@
add_subdirectory(sandbox_shared_lib) add_subdirectory(sandbox_shared_lib)
add_executable(sandbox sandbox.cpp) add_executable(sandbox sandbox.cpp)
target_link_libraries(sandbox ${CEREAL_THREAD_LIBS})
add_executable(sandbox_json sandbox_json.cpp) add_executable(sandbox_json sandbox_json.cpp)
target_link_libraries(sandbox_json ${CEREAL_THREAD_LIBS})
add_executable(sandbox_rtti sandbox_rtti.cpp) add_executable(sandbox_rtti sandbox_rtti.cpp)
target_link_libraries(sandbox_rtti ${CEREAL_THREAD_LIBS})
add_executable(sandbox_vs sandbox_vs.cpp) add_executable(sandbox_vs sandbox_vs.cpp)
target_link_libraries(sandbox_vs sandbox_vs_dll) target_link_libraries(sandbox_vs sandbox_vs_dll)
include_directories(sandbox_shared_lib)
if(Boost_FOUND AND NOT SKIP_PERFORMANCE_COMPARISON) if(Boost_FOUND)
add_executable(performance performance.cpp) add_executable(performance performance.cpp)
if(MSVC) target_link_libraries(performance ${Boost_LIBRARIES})
set_target_properties(performance PROPERTIES COMPILE_DEFINITIONS "BOOST_SERIALIZATION_DYN_LINK") endif(Boost_FOUND)
endif()
target_include_directories(performance PUBLIC ${Boost_INCLUDE_DIRS})
target_link_libraries(performance ${CEREAL_THREAD_LIBS} ${Boost_LIBRARIES})
endif()

View File

@ -9,14 +9,14 @@
* Redistributions in binary form must reproduce the above copyright * Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution. documentation and/or other materials provided with the distribution.
* Neither the name of the copyright holder nor the * Neither the name of cereal nor the
names of its contributors may be used to endorse or promote products names of its contributors may be used to endorse or promote products
derived from this software without specific prior written permission. derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 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 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DISCLAIMED. IN NO EVENT SHALL RANDOLPH VOORHIES AND SHANE GRANT BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
@ -29,9 +29,6 @@
# pragma warning(disable : 4244 4267) # pragma warning(disable : 4244 4267)
#endif #endif
// fix for old versions of boost + deprecated auto_ptr
#define BOOST_NO_AUTO_PTR
#include <sstream> #include <sstream>
#include <iostream> #include <iostream>
#include <chrono> #include <chrono>
@ -258,7 +255,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 = static_cast<char>( std::uniform_int_distribution<int>(' ', '~')(gen) ); c = std::uniform_int_distribution<char>(' ', '~')(gen);
return s; return s;
} }
@ -277,7 +274,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 = static_cast<char>( std::uniform_int_distribution<int>( '0', '1' )(gen) ); c = std::uniform_int_distribution<char>('0', '1')(gen);
return s; return s;
} }

View File

@ -9,14 +9,14 @@
* Redistributions in binary form must reproduce the above copyright * Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution. documentation and/or other materials provided with the distribution.
* Neither the name of the copyright holder nor the * Neither the name of cereal nor the
names of its contributors may be used to endorse or promote products names of its contributors may be used to endorse or promote products
derived from this software without specific prior written permission. derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 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 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DISCLAIMED. IN NO EVENT SHALL RANDOLPH VOORHIES AND SHANE GRANT BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
@ -65,8 +65,6 @@ class Base
public: public:
int x; int x;
virtual ~Base() {}
}; };
class Derived : public Base class Derived : public Base
@ -79,7 +77,6 @@ class Derived : public Base
y = d; y = d;
x = b; x = b;
} }
virtual ~Derived() {}
template <class Archive> template <class Archive>
void save( Archive & ar ) const void save( Archive & ar ) const
@ -389,8 +386,7 @@ void test_unordered_loads()
cereal::make_nvp( name3, i_vecbool3 ), cereal::make_nvp( name3, i_vecbool3 ),
cereal::make_nvp( name1, i_int1 ), cereal::make_nvp( name1, i_int1 ),
cereal::make_nvp( name5, i_int5 ), cereal::make_nvp( name5, i_int5 ),
i_int6, i_int6 );
i_un7 );
} }
} }
} }
@ -655,9 +651,9 @@ int main()
iar( d1 ); iar( d1 );
assert( d1->x == 4 && d1->y == 3 ); assert( d1->x == 4 && d1->y == 3 );
iar( d2 ); iar( d2 );
assert( dynamic_cast<Derived*>(d2.get())->x == 5 && dynamic_cast<Derived*>(d2.get())->y == 4 ); assert( ((Derived*)d2.get())->x == 5 && ((Derived*)d2.get())->y == 4 );
iar( d3 ); iar( d3 );
assert( dynamic_cast<Derived*>(d3.get())->x == 6 && dynamic_cast<Derived*>(d3.get())->y == 5 ); assert( ((Derived*)d3.get())->x == 6 && ((Derived*)d3.get())->y == 5 );
} }
{ {
@ -714,7 +710,7 @@ int main()
std::ifstream ss("xml_ordering.out"); std::ifstream ss("xml_ordering.out");
cereal::XMLInputArchive ar(ss); cereal::XMLInputArchive ar(ss);
// Output out of order, try to load in order 1 2 3 4 // Output prodered 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

@ -9,14 +9,14 @@
* Redistributions in binary form must reproduce the above copyright * Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution. documentation and/or other materials provided with the distribution.
* Neither the name of the copyright holder nor the * Neither the name of cereal nor the
names of its contributors may be used to endorse or promote products names of its contributors may be used to endorse or promote products
derived from this software without specific prior written permission. derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 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 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DISCLAIMED. IN NO EVENT SHALL RANDOLPH VOORHIES AND SHANE GRANT BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
@ -311,6 +311,31 @@ struct OOJson
} }
}; };
enum Bla
{
x,
y
};
template <class Archive>
void save( Archive & ar, Bla const & b )
{
ar( (const int &)b );
}
template <class Archive>
void load( Archive & ar, Bla & b )
{
ar( (int&)b );
}
CEREAL_SPECIALIZE_FOR_ALL_ARCHIVES( Bla, cereal::specialization::non_member_load_save )
//namespace cereal
//{
// //template <class Archive> struct specialize<Archive, Bla, cereal::specialization::non_member_load_save> {};
//}
// ###################################################################### // ######################################################################
int main() int main()
{ {
@ -345,6 +370,8 @@ int main()
auto f2 = f; auto f2 = f;
archive( f ); archive( f );
archive( f2 ); archive( f2 );
archive( Bla::x );
} }
// test out of order // test out of order

View File

@ -9,14 +9,14 @@
* Redistributions in binary form must reproduce the above copyright * Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution. documentation and/or other materials provided with the distribution.
* Neither the name of the copyright holder nor the * Neither the name of cereal nor the
names of its contributors may be used to endorse or promote products names of its contributors may be used to endorse or promote products
derived from this software without specific prior written permission. derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 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 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DISCLAIMED. IN NO EVENT SHALL RANDOLPH VOORHIES AND SHANE GRANT BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
@ -37,7 +37,6 @@ struct Base
{ {
int y; int y;
virtual void foo() = 0; virtual void foo() = 0;
virtual ~Base() {}
template<class Archive> template<class Archive>
void save(Archive & ar) const void save(Archive & ar) const
@ -56,8 +55,6 @@ struct Base
struct MyType : public Base struct MyType : public Base
{ {
virtual ~MyType() {}
int x; int x;
void foo() {} void foo() {}
@ -80,8 +77,6 @@ CEREAL_REGISTER_TYPE(MyType)
struct YourType : public Base struct YourType : public Base
{ {
virtual ~YourType() {}
YourType(int xx) : x(xx) {} YourType(int xx) : x(xx) {}
YourType() : x(-1) {} YourType() : x(-1) {}
int x; int x;
@ -119,8 +114,6 @@ struct OurType : public OurBase
{ {
OurType() : OurBase(), x() {} OurType() : OurBase(), x() {}
OurType(int x_) : x(x_) {} OurType(int x_) : x(x_) {}
virtual ~OurType() {}
void foo() {} void foo() {}
int x; int x;
@ -143,8 +136,6 @@ struct BaseVirtual
struct DerivedVirtual : public virtual BaseVirtual struct DerivedVirtual : public virtual BaseVirtual
{ {
virtual ~DerivedVirtual() {}
int y; int y;
virtual void foo() {} virtual void foo() {}
@ -186,7 +177,6 @@ struct AAA
struct BBB : AAA struct BBB : AAA
{ {
virtual ~BBB() {}
void foo() {} void foo() {}
template <class Archive> template <class Archive>
void serialize( Archive & ) {} void serialize( Archive & ) {}

View File

@ -1,6 +1 @@
add_library(sandbox_vs_dll SHARED base.cpp derived.cpp) add_library(sandbox_vs_dll SHARED base.cpp derived.cpp)
target_link_libraries(sandbox_vs_dll ${CEREAL_THREAD_LIBS})
target_include_directories(sandbox_vs_dll PUBLIC
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>
$<INSTALL_INTERFACE:include>
)

View File

@ -2,9 +2,6 @@
#include "base.hpp" #include "base.hpp"
class Derived : public Base class Derived : public Base
{ {
public:
virtual ~Derived() {}
private: private:
friend class cereal::access; friend class cereal::access;
template <class Archive> template <class Archive>

View File

@ -1,30 +1,3 @@
/*
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 the copyright holder 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 THE COPYRIGHT HOLDER OR CONTRIBUTORS 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.
*/
#include <base.hpp> #include <base.hpp>
#include <derived.hpp> #include <derived.hpp>
@ -77,7 +50,7 @@ CEREAL_SETUP_ARCHIVE_TRAITS(Archive, Archive)
struct Test struct Test
{ {
template <class Archive> template <class Archive>
void serialize( Archive & ) void serialzize( Archive & )
{ {
std::cout << "hey there" << std::endl; std::cout << "hey there" << std::endl;
} }
@ -152,12 +125,10 @@ namespace cereal
struct A struct A
{ {
virtual void foo() = 0; virtual void foo() = 0;
virtual ~A() {}
}; };
struct B : A struct B : A
{ {
virtual ~B() {}
void foo() {} void foo() {}
template <class Archive> template <class Archive>

View File

@ -1,80 +0,0 @@
@echo off
setlocal enabledelayedexpansion
if not defined APPVEYOR (
@echo This script is meant to be used with AppVeyor CI. This can be used as reference.
@echo I sincerely recommend not using it for building/testing cereal locally.
exit /b 0
)
if not defined BOOST_ROOT (
set BOOST_ROOT=C:\Libraries\boost
)
if not defined VS_VERSION_MAJOR (
set VS_VERSION_MAJOR=14
)
if not defined VS_VERSION_YEAR (
if "%VS_VERSION_MAJOR%" == "12" (
set VS_VERSION_YEAR=2013
) else if "%VS_VERSION_MAJOR%" == "14" (
set VS_VERSION_YEAR=2015
) else if "%VS_VERSION_MAJOR%" == "15" (
set VS_VERSION_YEAR=2017
) else if "%VS_VERSION_MAJOR%" == "16" (
set VS_VERSION_YEAR=2019
) else if "%VS_VERSION_MAJOR%" == "17" (
set VS_VERSION_YEAR=2022
) else (
@echo Cannot use Visual Studio version %VS_VERSION_MAJOR%
exit /b 1
)
)
if not defined CMAKE_GENERATOR_PREFIX (
set CMAKE_GENERATOR_PREFIX=Visual Studio %VS_VERSION_MAJOR% %VS_VERSION_YEAR%
)
@rem CONFIGURATION is (one of the entries) defined in appveyor.yml
if not defined CONFIGURATION (
set CONFIGURATION=Release
)
@rem PLATFORM is (one of the entries) defined in appveyor.yml
if "%PLATFORM%"=="x64" (
set BIT_COUNT=64
) else (
set BIT_COUNT=32
)
set BOOST_LIBRARYDIR=%BOOST_ROOT%\lib%BIT_COUNT%-msvc-%VS_VERSION_MAJOR%.0
set START_DIR=%CD%
if not exist build\NUL mkdir build
cd build
if "%~1" == "test" (
@rem overloading the batch script; Run tests if the first argument is `test` (without quotes).
@rem Cereal uses Boost Unit test framework. Rather than modifying the code to load boost test
@rem dll from its location OR copying the boost dlls to the directory of every test being run,
@rem we use another option Windows leaves us - modify the PATH.
for %%i in (ctest.exe) do set CTEST_EXE=%%~$PATH:i
PATH %BOOST_LIBRARYDIR%
"!CTEST_EXE!" -C %CONFIGURATION%
if %errorlevel% neq 0 exit /b %errorlevel%
goto done
)
if "%PLATFORM%" == "x64" (
@rem please excuse the hack - CMake is unable to produce multiarch MSVC projects
cmake -G "%CMAKE_GENERATOR_PREFIX%" -DBOOST_ROOT=%BOOST_ROOT% -DBOOST_LIBRARYDIR=%BOOST_LIBRARYDIR% ..
cmake --build . --config %CONFIGURATION% --target portability_test32
del CMakeCache.txt
rmdir /s /q CMakeFiles
)
cmake -G "%CMAKE_GENERATOR_PREFIX%" -A %PLATFORM% -DBOOST_ROOT=%BOOST_ROOT% -DBOOST_LIBRARYDIR=%BOOST_LIBRARYDIR% ..
@rem left the actual build for later - AppVeyor enables parallel jobs in a much cleaner way than msbuild
:done
@REM go back home
cd %START_DIR%

View File

@ -1,7 +1,7 @@
#!/usr/bin/env bash #!/usr/bin/env bash
# Updates the coverage documentation, and copies it into the appropriate place # Updates the coverage documentation, and copies it into the appropriate place
# in the gh-pages branch. # in the gh-pages-develop branch.
# $1 from CMAKE will contain the root directory of cereal # $1 from CMAKE will contain the root directory of cereal
# this requires lcov 1.10 or newer # this requires lcov 1.10 or newer
@ -21,11 +21,11 @@ for f in $COVERAGE_TESTS
tempdir=`mktemp -d` tempdir=`mktemp -d`
lcov --capture --directory $1 --output-file coverage.info --no-external lcov --capture --directory $1 --output-file coverage.info --no-external
lcov --remove coverage.info '*/external/*' '*/cereal/details/util.hpp' 'sandbox/*' '*/unittests/*' -o coverage.info lcov --remove coverage.info '*/external/*' 'cereal/details/util.hpp' 'sandbox/*' 'unittests/*' -o coverage.info
genhtml --demangle-cpp coverage.info --output-directory ${tempdir} genhtml --demangle-cpp coverage.info --output-directory ${tempdir}
# copy over to gh pages # copy over to gh pages
git checkout gh-pages git checkout gh-pages-develop
rm -rf $1/assets/coverage rm -rf $1/assets/coverage
mkdir $1/assets/coverage mkdir $1/assets/coverage

Some files were not shown because too many files have changed in this diff Show More