mirror of
https://github.com/USCiLab/cereal.git
synced 2025-07-20 22:02:02 +02:00
Compare commits
252 Commits
Author | SHA1 | Date | |
---|---|---|---|
![]() |
a56bad8bbb | ||
![]() |
b4703c47ec | ||
![]() |
2c647d87d4 | ||
![]() |
f7deca361c | ||
![]() |
cb6c6ac1f0 | ||
![]() |
864c2fc370 | ||
![]() |
66d74f8cb9 | ||
![]() |
d1fcec807b | ||
![]() |
f3e31f32f7 | ||
![]() |
83b6fa06a0 | ||
![]() |
b2d68c522b | ||
![]() |
ddd4672447 | ||
![]() |
5b37553aa9 | ||
![]() |
343473b752 | ||
![]() |
45e40375b6 | ||
![]() |
ebef1e9298 | ||
![]() |
6e1c66a94c | ||
![]() |
39d202053d | ||
![]() |
1de8fe8947 | ||
![]() |
107f8c2aa9 | ||
![]() |
ca9aeaab27 | ||
![]() |
8291f44e05 | ||
![]() |
de953044b0 | ||
![]() |
408a351ce0 | ||
![]() |
90ea8a98c5 | ||
![]() |
2c5e1b792f | ||
![]() |
af0700efb2 | ||
![]() |
f8338dbb73 | ||
![]() |
0bbbb142f9 | ||
![]() |
46a4a91007 | ||
![]() |
e735cc8bc1 | ||
![]() |
6d1c2885f2 | ||
![]() |
64f50dbd5c | ||
![]() |
f27c12d491 | ||
![]() |
48fda3f0a6 | ||
![]() |
562321c354 | ||
![]() |
b5e17a9159 | ||
![]() |
3e4d1b84ca | ||
![]() |
10d9a29c22 | ||
![]() |
a5a3095312 | ||
![]() |
075c44feef | ||
![]() |
8bd726281f | ||
![]() |
02eace19a9 | ||
![]() |
37b4567934 | ||
![]() |
021e5da2fe | ||
![]() |
49fbbed8e2 | ||
![]() |
1bce4362db | ||
![]() |
797239531b | ||
![]() |
0db8d115bf | ||
![]() |
4b466f4f80 | ||
![]() |
aafd7702bd | ||
![]() |
fedddc5a1b | ||
![]() |
6c7c93edfa | ||
![]() |
7fcfa29353 | ||
![]() |
6ccd33fe37 | ||
![]() |
33224f4660 | ||
![]() |
62034cbe26 | ||
![]() |
8195d35fbc | ||
![]() |
f64864fa74 | ||
![]() |
946b568bf7 | ||
![]() |
0399962807 | ||
![]() |
e50424c9fa | ||
![]() |
bd766fe0bd | ||
![]() |
3452ab4244 | ||
![]() |
b37ff23566 | ||
![]() |
d5f531fd5c | ||
![]() |
df16f32fa7 | ||
![]() |
36ab0c1f89 | ||
![]() |
cfbb7b0f25 | ||
![]() |
182876d4a3 | ||
![]() |
afe6ab9883 | ||
![]() |
8475382ad5 | ||
![]() |
d16feb9de8 | ||
![]() |
96b34c2e71 | ||
![]() |
319ce5f5ee | ||
![]() |
9ccfaa0bea | ||
![]() |
3d5d20d1d8 | ||
![]() |
78b88cc314 | ||
![]() |
b883b47a65 | ||
![]() |
e6dc5d37cb | ||
![]() |
487c3375e1 | ||
![]() |
3d4fea5bdb | ||
![]() |
0a7a989763 | ||
![]() |
16378d5847 | ||
![]() |
0cf8150bc4 | ||
![]() |
9aa7f390c4 | ||
![]() |
009e383cf3 | ||
![]() |
ae57c6271b | ||
![]() |
f36e2d1c79 | ||
![]() |
1bf8c629b1 | ||
![]() |
02724b9a39 | ||
![]() |
3f205c28e2 | ||
![]() |
dc9e573dfb | ||
![]() |
13d1d36cae | ||
![]() |
ae7529c211 | ||
![]() |
a88e1c7dfd | ||
![]() |
7cf1cba5f1 | ||
![]() |
e9234e3fb6 | ||
![]() |
e9551c9942 | ||
![]() |
f094ba78ec | ||
![]() |
83df216451 | ||
![]() |
6a2826150f | ||
![]() |
53441ea669 | ||
![]() |
0d96673536 | ||
![]() |
322fb95a5d | ||
![]() |
0d3edb8c29 | ||
![]() |
65adc87c7c | ||
![]() |
e519567cd2 | ||
![]() |
0f61bc8a38 | ||
![]() |
59621d6023 | ||
![]() |
f158a44a32 | ||
![]() |
0cef0b7073 | ||
![]() |
ed49c96c80 | ||
![]() |
84a6c4b063 | ||
![]() |
05c0cb0521 | ||
![]() |
c37d44fd7e | ||
![]() |
54b2fe12b5 | ||
![]() |
9323fc0af7 | ||
![]() |
11882b6261 | ||
![]() |
f5a9404503 | ||
![]() |
c0f2e28719 | ||
![]() |
bcd69859c0 | ||
![]() |
ca75f4b53e | ||
![]() |
cb78660421 | ||
![]() |
f7baa90c23 | ||
![]() |
7292a605dd | ||
![]() |
01dd76f515 | ||
![]() |
f698f33ca0 | ||
![]() |
8859e1f9f0 | ||
![]() |
baeb6d8b0e | ||
![]() |
ebbf3a6768 | ||
![]() |
0adf9e6865 | ||
![]() |
85b5f73252 | ||
![]() |
a4edd60629 | ||
![]() |
72c83d9b04 | ||
![]() |
efcfb95e9f | ||
![]() |
9b1dd1673d | ||
![]() |
dbb16b1942 | ||
![]() |
96442fff9e | ||
![]() |
ba559a23ed | ||
![]() |
9b1fe1efa5 | ||
![]() |
7fd9136f8d | ||
![]() |
4e79985fb9 | ||
![]() |
c76d02cbfe | ||
![]() |
7c65494566 | ||
![]() |
123eeb55d6 | ||
![]() |
43077e7f03 | ||
![]() |
d5b212629f | ||
![]() |
c3eda13e9e | ||
![]() |
e84a6735bd | ||
![]() |
ca5cd7eece | ||
![]() |
0481881be2 | ||
![]() |
673add1212 | ||
![]() |
015ed43eed | ||
![]() |
70754e2cab | ||
![]() |
1947a96308 | ||
![]() |
8e25c2bb7e | ||
![]() |
ae9b1063f0 | ||
![]() |
508b02047f | ||
![]() |
63eee8104f | ||
![]() |
aa891a42d7 | ||
![]() |
fcef0da01a | ||
![]() |
950aca4523 | ||
![]() |
35a36afb97 | ||
![]() |
ad905576d2 | ||
![]() |
f031131130 | ||
![]() |
c4dcc8d5de | ||
![]() |
52b03d58c5 | ||
![]() |
2ab15f7540 | ||
![]() |
7723503fcc | ||
![]() |
68f56eed92 | ||
![]() |
676d329d81 | ||
![]() |
546fd9b896 | ||
![]() |
8b8f5814e2 | ||
![]() |
51cbda5f30 | ||
![]() |
e38d6fecc1 | ||
![]() |
70c4420632 | ||
![]() |
2590f219a2 | ||
![]() |
a91737466f | ||
![]() |
ee17db59c8 | ||
![]() |
b827b955f9 | ||
![]() |
f577fc4ce4 | ||
![]() |
fb6606dbb8 | ||
![]() |
a2d5a15b67 | ||
![]() |
e4d543d0b4 | ||
![]() |
2261feea2f | ||
![]() |
4ff4db8532 | ||
![]() |
655696ad81 | ||
![]() |
df44243bad | ||
![]() |
0a908bc8c8 | ||
![]() |
4a92e2930e | ||
![]() |
a8e99636f5 | ||
![]() |
75e50ee1e6 | ||
![]() |
507f97d3ad | ||
![]() |
f69ad7cd9e | ||
![]() |
d21b0c0ab6 | ||
![]() |
e63f08f4d7 | ||
![]() |
29829c167e | ||
![]() |
ad927466b5 | ||
![]() |
9978e0c03f | ||
![]() |
1edc5c6f6d | ||
![]() |
6086234740 | ||
![]() |
6e717666f3 | ||
![]() |
2e96b9915e | ||
![]() |
9376ca6055 | ||
![]() |
72d79364c9 | ||
![]() |
1d67d44024 | ||
![]() |
66528b68be | ||
![]() |
978b3b56b4 | ||
![]() |
13ae5609df | ||
![]() |
07818f4527 | ||
![]() |
b5e500d3b2 | ||
![]() |
a6e59d7e06 | ||
![]() |
cd46374df8 | ||
![]() |
38e15480c0 | ||
![]() |
15c73394a9 | ||
![]() |
928cd36335 | ||
![]() |
0a262ece48 | ||
![]() |
671999e4ea | ||
![]() |
195c0bf229 | ||
![]() |
34bb0d9494 | ||
![]() |
e597e03f8a | ||
![]() |
d27cc338d2 | ||
![]() |
74030ce9e2 | ||
![]() |
bf0f9aee1c | ||
![]() |
fc57d93847 | ||
![]() |
8c1517d1b0 | ||
![]() |
96deb7e9d3 | ||
![]() |
74e0b1b698 | ||
![]() |
500e7a0188 | ||
![]() |
e715149f4d | ||
![]() |
f4ae56a19b | ||
![]() |
383cea57eb | ||
![]() |
e080c31867 | ||
![]() |
3541f6588c | ||
![]() |
c51095f9d3 | ||
![]() |
4854ed5380 | ||
![]() |
80c518bcfc | ||
![]() |
f414a41a76 | ||
![]() |
c7b33a5a9c | ||
![]() |
c99294ea91 | ||
![]() |
e694a6311a | ||
![]() |
a06680868e | ||
![]() |
3fb59dbe6c | ||
![]() |
3d5a77d2c3 | ||
![]() |
adea360c7a | ||
![]() |
b8d9acc502 | ||
![]() |
b9c424e06a | ||
![]() |
c83a7f99e6 | ||
![]() |
cd37b64b78 | ||
![]() |
d16f88da40 | ||
![]() |
7409da1fb4 |
45
.github/workflows/ci-macos.yml
vendored
Normal file
45
.github/workflows/ci-macos.yml
vendored
Normal file
@ -0,0 +1,45 @@
|
||||
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
|
237
.github/workflows/ci.yml
vendored
Normal file
237
.github/workflows/ci.yml
vendored
Normal file
@ -0,0 +1,237 @@
|
||||
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
8
.gitignore
vendored
@ -18,14 +18,18 @@
|
||||
*.suo
|
||||
*.user
|
||||
*/x64
|
||||
*/Debug*
|
||||
*/Release*
|
||||
*\Debug*
|
||||
*\Release*
|
||||
*.log
|
||||
*.tlog*
|
||||
*.obj
|
||||
*.VC.db
|
||||
*.VC.VC.opendb
|
||||
*.pdb
|
||||
*.idb
|
||||
*\build_*
|
||||
.vs/
|
||||
CMakeSettings.json
|
||||
|
||||
# misc files mostly used for testing
|
||||
out.txt
|
||||
|
291
.travis.yml
291
.travis.yml
@ -1,50 +1,269 @@
|
||||
# Portions of this file based on https://github.com/Microsoft/GSL/blob/master/.travis.yml
|
||||
|
||||
language: cpp
|
||||
os: linux
|
||||
dist: trusty
|
||||
sudo: false
|
||||
group: beta
|
||||
|
||||
compiler:
|
||||
# TODO: Clang is currently giving issues
|
||||
#- clang
|
||||
- gcc
|
||||
addons:
|
||||
apt:
|
||||
sources: &default_sources
|
||||
- ubuntu-toolchain-r-test
|
||||
- libboost-latest
|
||||
packages: &default_packages
|
||||
- libboost-serialization-dev
|
||||
- libboost-dev
|
||||
|
||||
before_install:
|
||||
# Always install g++4.8.1
|
||||
- sudo add-apt-repository -y ppa:ubuntu-toolchain-r/test
|
||||
|
||||
# Install recent version of Boost
|
||||
- sudo add-apt-repository -y ppa:boost-latest/ppa
|
||||
matrix:
|
||||
include:
|
||||
|
||||
# clang 3.3
|
||||
- if [ "$CXX" == "clang++" ]; then sudo add-apt-repository -y ppa:h-rayflood/llvm; fi
|
||||
# |---------- LINUX GCC ----------|
|
||||
- compiler: g++-4.7
|
||||
env: ["CMAKE_OPTIONS='-DSKIP_PORTABILITY_TEST=ON'", "COMPILER=g++-4.7"]
|
||||
addons:
|
||||
apt:
|
||||
sources: *default_sources
|
||||
packages: ['g++-4.7', *default_packages]
|
||||
|
||||
- sudo apt-get update -qq
|
||||
- compiler: g++-4.8
|
||||
env: ["CMAKE_OPTIONS='-DSKIP_PORTABILITY_TEST=ON'", "COMPILER=g++-4.8"]
|
||||
addons:
|
||||
apt:
|
||||
sources: *default_sources
|
||||
packages: ['g++-4.8', *default_packages]
|
||||
|
||||
- compiler: g++-4.9
|
||||
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]
|
||||
|
||||
install:
|
||||
- sudo apt-get install cmake
|
||||
- sudo apt-get install libboost1.54-all-dev
|
||||
- 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]
|
||||
|
||||
# Always install valgrind
|
||||
- sudo apt-get install valgrind
|
||||
# |---------- 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]
|
||||
|
||||
# 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
|
||||
|
||||
# clang 3.3
|
||||
- if [ "$CXX" == "clang++" ]; then sudo apt-get install --allow-unauthenticated -qq clang-3.3; fi
|
||||
- if [ "$CXX" == "clang++" ]; then export CMAKE_CXX_COMPILER="clang++-3.3"; fi
|
||||
- if [ "$CXX" == "clang++" ]; then export CXX="clang++-3.3"; fi
|
||||
# |---------- 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:
|
||||
# Set the ${CXX} variable properly
|
||||
- export CXX=${COMPILER}
|
||||
- ${CXX} --version
|
||||
|
||||
# Dependencies required by the CI are installed in ${TRAVIS_BUILD_DIR}/deps/
|
||||
- DEPS_DIR="${TRAVIS_BUILD_DIR}/deps"
|
||||
- mkdir -p "${DEPS_DIR}"
|
||||
- cd "${DEPS_DIR}"
|
||||
|
||||
- JOBS=2
|
||||
|
||||
# [linux]: Install the right version of libc++
|
||||
- |
|
||||
LLVM_INSTALL=${DEPS_DIR}/llvm/install
|
||||
# if in linux and compiler clang and llvm not installed
|
||||
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:
|
||||
- mkdir build
|
||||
- cd build
|
||||
- cmake ..
|
||||
- make
|
||||
|
||||
after_script:
|
||||
- ctest .
|
||||
# - make valgrind
|
||||
- cd "${TRAVIS_BUILD_DIR}"
|
||||
- if [[ "${COMPILERCC}" != "" ]]; then export CC="${COMPILERCC}"; fi
|
||||
- if [[ "${COMPILER}" != "" ]]; then export CXX="${COMPILER}"; fi
|
||||
- $CXX --version
|
||||
- cmake --version
|
||||
- mkdir build && cd build
|
||||
- cmake ${CMAKE_OPTIONS} .. && make -j4
|
||||
- ctest . --output-on-failure
|
||||
|
||||
branches:
|
||||
only:
|
||||
- develop
|
||||
- master
|
||||
|
174
CMakeLists.txt
174
CMakeLists.txt
@ -1,75 +1,143 @@
|
||||
cmake_minimum_required (VERSION 2.6.2)
|
||||
project (cereal)
|
||||
cmake_minimum_required(VERSION 3.6...3.15)
|
||||
|
||||
option(SKIP_PORTABILITY_TEST "Skip portability tests" OFF)
|
||||
project(cereal LANGUAGES CXX VERSION 1.3.2)
|
||||
|
||||
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
|
||||
option(JUST_INSTALL_CEREAL "Don't do anything besides installing the library" OFF)
|
||||
endif()
|
||||
|
||||
option(THREAD_SAFE "Use mutexes to ensure thread safety" OFF)
|
||||
if(THREAD_SAFE)
|
||||
add_definitions(-DCEREAL_THREAD_SAFE=1)
|
||||
set(CEREAL_THREAD_LIBS "pthread")
|
||||
else()
|
||||
set(CEREAL_THREAD_LIBS "")
|
||||
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")
|
||||
set(CMAKE_CXX_STANDARD 11)
|
||||
endif()
|
||||
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||
set(CEREAL_THREAD_LIBS)
|
||||
if(UNIX)
|
||||
option(THREAD_SAFE "Use mutexes to ensure thread safety" OFF)
|
||||
if(THREAD_SAFE)
|
||||
message(STATUS "Use mutexes")
|
||||
add_definitions(-DCEREAL_THREAD_SAFE=1)
|
||||
set(CEREAL_THREAD_LIBS pthread)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(NOT CMAKE_VERSION VERSION_LESS 3.0)
|
||||
add_library(cereal INTERFACE)
|
||||
target_include_directories(cereal INTERFACE
|
||||
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
|
||||
$<INSTALL_INTERFACE:include>
|
||||
)
|
||||
install(TARGETS cereal EXPORT cereal
|
||||
DESTINATION lib) # ignored
|
||||
install(EXPORT cereal FILE cereal-config.cmake
|
||||
DESTINATION share/cmake/cereal)
|
||||
install(DIRECTORY include/cereal DESTINATION include)
|
||||
|
||||
if(MSVC)
|
||||
add_compile_options(/bigobj /W3 /WX)
|
||||
else()
|
||||
add_compile_options(-Wall -Wextra -pedantic -Wshadow -Wold-style-cast)
|
||||
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()
|
||||
|
||||
if(NOT DEFINED CMAKE_CXX_STANDARD OR CMAKE_CXX_STANDARD STREQUAL "98")
|
||||
set(CMAKE_CXX_STANDARD 11)
|
||||
endif()
|
||||
|
||||
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||
endif()
|
||||
|
||||
|
||||
add_library(cereal INTERFACE)
|
||||
add_library(cereal::cereal ALIAS cereal)
|
||||
target_include_directories(cereal INTERFACE
|
||||
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
|
||||
$<INSTALL_INTERFACE:include>
|
||||
)
|
||||
list(APPEND CEREAL_THREAD_LIBS cereal::cereal)
|
||||
|
||||
if(NOT CMAKE_VERSION VERSION_LESS 3.8)
|
||||
target_compile_features(cereal INTERFACE cxx_std_11)
|
||||
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)
|
||||
return()
|
||||
endif()
|
||||
|
||||
include_directories(./include)
|
||||
|
||||
find_package(Boost COMPONENTS serialization unit_test_framework)
|
||||
if(NOT SKIP_PERFORMANCE_COMPARISON)
|
||||
# Boost serialization for performance sandbox
|
||||
find_package(Boost REQUIRED COMPONENTS serialization)
|
||||
endif()
|
||||
|
||||
if(Boost_FOUND)
|
||||
include_directories(SYSTEM ${Boost_INCLUDE_DIRS})
|
||||
enable_testing()
|
||||
add_subdirectory(unittests)
|
||||
endif(Boost_FOUND)
|
||||
|
||||
add_subdirectory(sandbox)
|
||||
option(BUILD_TESTS "Build tests" ${CEREAL_MASTER_PROJECT})
|
||||
if(BUILD_TESTS)
|
||||
enable_testing()
|
||||
add_subdirectory(unittests)
|
||||
endif()
|
||||
|
||||
find_package(Doxygen)
|
||||
if(DOXYGEN_FOUND)
|
||||
|
||||
configure_file("${CMAKE_CURRENT_SOURCE_DIR}/doc/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
|
||||
)
|
||||
if(BUILD_SANDBOX)
|
||||
add_subdirectory(sandbox)
|
||||
endif()
|
||||
|
||||
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)
|
||||
if(BUILD_DOC)
|
||||
add_subdirectory(doc)
|
||||
endif()
|
||||
|
3
Config.cmake.in
Normal file
3
Config.cmake.in
Normal file
@ -0,0 +1,3 @@
|
||||
@PACKAGE_INIT@
|
||||
|
||||
include("${CMAKE_CURRENT_LIST_DIR}/@PROJECT_NAME@Targets.cmake")
|
6
LICENSE
6
LICENSE
@ -1,4 +1,4 @@
|
||||
Copyright (c) 2014, Randolph Voorhies, Shane Grant
|
||||
Copyright (c) 2013-2022, Randolph Voorhies, Shane Grant
|
||||
All rights reserved.
|
||||
|
||||
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
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of cereal nor the
|
||||
* 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 RANDOLPH VOORHIES OR SHANE GRANT BE LIABLE FOR ANY
|
||||
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
|
||||
|
10
README.md
10
README.md
@ -1,15 +1,15 @@
|
||||
cereal - A C++11 library for serialization
|
||||
==========================================
|
||||
|
||||
<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>
|
||||
<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>
|
||||
|
||||
### cereal has great documentation
|
||||
|
||||
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.
|
||||
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.
|
||||
|
||||
### cereal is easy to use
|
||||
|
||||
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:
|
||||
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:
|
||||
|
||||
* 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
|
||||
@ -77,7 +77,9 @@ cereal is licensed under the [BSD license](http://opensource.org/licenses/BSD-3-
|
||||
|
||||
## cereal build status
|
||||
|
||||
* develop : [](https://travis-ci.org/USCiLab/cereal)
|
||||
* [](https://github.com/USCiLab/cereal/actions/workflows/ci.yml)
|
||||
* [](https://github.com/USCiLab/cereal/actions/workflows/ci-macos.yml)
|
||||
* [](https://ci.appveyor.com/project/AzothAmmo/cereal/branch/master)
|
||||
|
||||
---
|
||||
|
||||
|
55
appveyor.yml
Normal file
55
appveyor.yml
Normal file
@ -0,0 +1,55 @@
|
||||
# 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
|
8
cereal.pc.in
Normal file
8
cereal.pc.in
Normal file
@ -0,0 +1,8 @@
|
||||
prefix=@CMAKE_INSTALL_PREFIX@
|
||||
includedir=${prefix}/@CMAKE_INSTALL_INCLUDEDIR@
|
||||
|
||||
Name: @PROJECT_NAME@
|
||||
Description: cereal is a header-only C++11 serialization library
|
||||
URL: https://uscilab.github.io/cereal/
|
||||
Version: @PROJECT_VERSION@
|
||||
Cflags: -I"${includedir}"
|
18
doc/CMakeLists.txt
Normal file
18
doc/CMakeLists.txt
Normal file
@ -0,0 +1,18 @@
|
||||
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()
|
@ -52,7 +52,7 @@ PROJECT_LOGO =
|
||||
# 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.
|
||||
|
||||
OUTPUT_DIRECTORY = doc
|
||||
OUTPUT_DIRECTORY = @CMAKE_CURRENT_BINARY_DIR@/
|
||||
|
||||
# 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
|
||||
@ -119,7 +119,7 @@ INLINE_INHERITED_MEMB = NO
|
||||
# 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.
|
||||
|
||||
FULL_PATH_NAMES = YES
|
||||
FULL_PATH_NAMES = NO
|
||||
|
||||
# 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
|
||||
@ -130,7 +130,7 @@ FULL_PATH_NAMES = YES
|
||||
# relative paths, which will be relative from the directory where doxygen is
|
||||
# started.
|
||||
|
||||
STRIP_FROM_PATH =
|
||||
STRIP_FROM_PATH = @PROJECT_SOURCE_DIR@
|
||||
|
||||
# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of
|
||||
# the 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
|
||||
# DoxygenLayout.xml will be used as the name of the layout file.
|
||||
|
||||
LAYOUT_FILE = "@CMAKE_CURRENT_SOURCE_DIR@/doc/DoxygenLayout.xml"
|
||||
LAYOUT_FILE = "@CMAKE_CURRENT_SOURCE_DIR@/DoxygenLayout.xml"
|
||||
|
||||
# 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
|
||||
@ -668,7 +668,7 @@ WARN_LOGFILE =
|
||||
# directories like "/usr/src/myproject". Separate the files or directories
|
||||
# with spaces.
|
||||
|
||||
INPUT = @CMAKE_CURRENT_SOURCE_DIR@/include @CMAKE_CURRENT_SOURCE_DIR@/doc #include doc
|
||||
INPUT = @CMAKE_CURRENT_SOURCE_DIR@/../include @CMAKE_CURRENT_SOURCE_DIR@/
|
||||
|
||||
# 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
|
||||
@ -701,7 +701,7 @@ RECURSIVE = YES
|
||||
# Note that relative paths are relative to the directory from which doxygen is
|
||||
# run.
|
||||
|
||||
EXCLUDE = external
|
||||
EXCLUDE = @CMAKE_CURRENT_SOURCE_DIR@/../external
|
||||
|
||||
# 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
|
||||
@ -911,7 +911,7 @@ HTML_HEADER =
|
||||
# each generated HTML page. If it is left blank doxygen will generate a
|
||||
# standard footer.
|
||||
|
||||
HTML_FOOTER ="@CMAKE_CURRENT_SOURCE_DIR@/doc/footer.html"
|
||||
HTML_FOOTER ="@CMAKE_CURRENT_SOURCE_DIR@/footer.html"
|
||||
|
||||
# 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
|
||||
@ -1476,13 +1476,13 @@ XML_OUTPUT = xml
|
||||
# which can be used by a validating XML parser to check the
|
||||
# syntax of the XML files.
|
||||
|
||||
XML_SCHEMA =
|
||||
# XML_SCHEMA =
|
||||
|
||||
# The XML_DTD tag can be used to specify an XML DTD,
|
||||
# which can be used by a validating XML parser to check the
|
||||
# syntax of the XML files.
|
||||
|
||||
XML_DTD =
|
||||
# XML_DTD =
|
||||
|
||||
# If the XML_PROGRAMLISTING tag is set to YES Doxygen will
|
||||
# dump the program listings (including syntax highlighting
|
||||
@ -1626,7 +1626,7 @@ TAGFILES =
|
||||
# When a file name is specified after GENERATE_TAGFILE, doxygen will create
|
||||
# a tag file that is based on the input files it reads.
|
||||
|
||||
GENERATE_TAGFILE =
|
||||
GENERATE_TAGFILE = cereal.doxytags
|
||||
|
||||
# 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
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*! \file access.hpp
|
||||
\brief Access control, default construction, and serialization disambiguation */
|
||||
\brief Access control and default construction */
|
||||
/*
|
||||
Copyright (c) 2014, Randolph Voorhies, Shane Grant
|
||||
All rights reserved.
|
||||
@ -11,14 +11,14 @@
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of cereal nor the
|
||||
* 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 RANDOLPH VOORHIES OR SHANE GRANT BE LIABLE FOR ANY
|
||||
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
|
||||
@ -34,8 +34,9 @@
|
||||
#include <cstdint>
|
||||
#include <functional>
|
||||
|
||||
#include <cereal/macros.hpp>
|
||||
#include <cereal/details/helpers.hpp>
|
||||
#include "cereal/macros.hpp"
|
||||
#include "cereal/specialize.hpp"
|
||||
#include "cereal/details/helpers.hpp"
|
||||
|
||||
namespace cereal
|
||||
{
|
||||
@ -110,6 +111,7 @@ namespace cereal
|
||||
// forward decl for construct
|
||||
//! @cond PRIVATE_NEVERDEFINED
|
||||
namespace memory_detail{ template <class Ar, class T> struct LoadAndConstructLoadWrapper; }
|
||||
namespace boost_variant_detail{ template <class Ar, class T> struct LoadAndConstructLoadWrapper; }
|
||||
//! @endcond
|
||||
|
||||
//! Used to construct types with no default constructor
|
||||
@ -202,7 +204,8 @@ namespace cereal
|
||||
}
|
||||
|
||||
private:
|
||||
template <class A, class B> friend struct ::cereal::memory_detail::LoadAndConstructLoadWrapper;
|
||||
template <class Ar, class TT> 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, std::function<void()> enableSharedFunc ) : // g++4.7 ice with default lambda to std func
|
||||
@ -331,106 +334,6 @@ namespace cereal
|
||||
}
|
||||
}; // end class access
|
||||
|
||||
// ######################################################################
|
||||
//! A specifier used in conjunction with cereal::specialize to disambiguate
|
||||
//! serialization in special cases
|
||||
/*! @relates specialize
|
||||
@ingroup Access */
|
||||
enum class specialization
|
||||
{
|
||||
member_serialize, //!< Force the use of a member serialize function
|
||||
member_load_save, //!< Force the use of a member load/save pair
|
||||
member_load_save_minimal, //!< Force the use of a member minimal load/save pair
|
||||
non_member_serialize, //!< Force the use of a non-member serialize function
|
||||
non_member_load_save, //!< Force the use of a non-member load/save pair
|
||||
non_member_load_save_minimal //!< Force the use of a non-member minimal load/save pair
|
||||
};
|
||||
|
||||
//! A class used to disambiguate cases where cereal cannot detect a unique way of serializing a class
|
||||
/*! cereal attempts to figure out which method of serialization (member vs. non-member serialize
|
||||
or load/save pair) at compile time. If for some reason cereal cannot find a non-ambiguous way
|
||||
of serializing a type, it will produce a static assertion complaining about this.
|
||||
|
||||
This can happen because you have both a serialize and load/save pair, or even because a base
|
||||
class has a serialize (public or private with friend access) and a derived class does not
|
||||
overwrite this due to choosing some other serialization type.
|
||||
|
||||
Specializing this class will tell cereal to explicitly use the serialization type you specify
|
||||
and it will not complain about ambiguity in its compile time selection. However, if cereal detects
|
||||
an ambiguity in specializations, it will continue to issue a static assertion.
|
||||
|
||||
@code{.cpp}
|
||||
class MyParent
|
||||
{
|
||||
friend class cereal::access;
|
||||
template <class Archive>
|
||||
void serialize( Archive & ar ) {}
|
||||
};
|
||||
|
||||
// Although serialize is private in MyParent, to cereal::access it will look public,
|
||||
// even through MyDerived
|
||||
class MyDerived : public MyParent
|
||||
{
|
||||
public:
|
||||
template <class Archive>
|
||||
void load( Archive & ar ) {}
|
||||
|
||||
template <class Archive>
|
||||
void save( Archive & ar ) {}
|
||||
};
|
||||
|
||||
// The load/save pair in MyDerived is ambiguous because serialize in MyParent can
|
||||
// be accessed from cereal::access. This looks the same as making serialize public
|
||||
// in MyParent, making it seem as though MyDerived has both a serialize and a load/save pair.
|
||||
// cereal will complain about this at compile time unless we disambiguate:
|
||||
|
||||
namespace cereal
|
||||
{
|
||||
// This struct specialization will tell cereal which is the right way to serialize the ambiguity
|
||||
template <class Archive> struct specialize<Archive, MyDerived, cereal::specialization::member_load_save> {};
|
||||
|
||||
// If we only had a disambiguation for a specific archive type, it would look something like this
|
||||
template <> struct specialize<cereal::BinaryOutputArchive, MyDerived, cereal::specialization::member_load_save> {};
|
||||
}
|
||||
@endcode
|
||||
|
||||
You can also choose to use the macros CEREAL_SPECIALIZE_FOR_ALL_ARCHIVES or
|
||||
CEREAL_SPECIALIZE_FOR_ARCHIVE if you want to type a little bit less.
|
||||
|
||||
@tparam T The type to specialize the serialization for
|
||||
@tparam S The specialization type to use for T
|
||||
@ingroup Access */
|
||||
template <class Archive, class T, specialization S>
|
||||
struct specialize : public std::false_type {};
|
||||
|
||||
//! Convenient macro for performing specialization for all archive types
|
||||
/*! This performs specialization for the specific type for all types of archives.
|
||||
This macro should be placed at the global namespace.
|
||||
|
||||
@code{cpp}
|
||||
struct MyType {};
|
||||
CEREAL_SPECIALIZE_FOR_ALL_ARCHIVES( MyType, cereal::specialization::member_load_save );
|
||||
@endcode
|
||||
|
||||
@relates specialize
|
||||
@ingroup Access */
|
||||
#define CEREAL_SPECIALIZE_FOR_ALL_ARCHIVES( Type, Specialization ) \
|
||||
namespace cereal { template <class Archive> struct specialize<Archive, Type, Specialization> {}; }
|
||||
|
||||
//! Convenient macro for performing specialization for a single archive type
|
||||
/*! This performs specialization for the specific type for a single type of archive.
|
||||
This macro should be placed at the global namespace.
|
||||
|
||||
@code{cpp}
|
||||
struct MyType {};
|
||||
CEREAL_SPECIALIZE_FOR_ARCHIVE( cereal::XMLInputArchive, MyType, cereal::specialization::member_load_save );
|
||||
@endcode
|
||||
|
||||
@relates specialize
|
||||
@ingroup Access */
|
||||
#define CEREAL_SPECIALIZE_FOR_ARCHIVE( Archive, Type, Specialization ) \
|
||||
namespace cereal { template <> struct specialize<Archive, Type, Specialization> {}; }
|
||||
|
||||
// ######################################################################
|
||||
// Deferred Implementation, see construct for more information
|
||||
template <class T> template <class ... Args> inline
|
||||
|
@ -12,14 +12,14 @@
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of cereal nor the
|
||||
* 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 RANDOLPH VOORHIES OR SHANE GRANT BE LIABLE FOR ANY
|
||||
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
|
||||
@ -30,7 +30,7 @@
|
||||
#ifndef CEREAL_ARCHIVES_ADAPTERS_HPP_
|
||||
#define CEREAL_ARCHIVES_ADAPTERS_HPP_
|
||||
|
||||
#include <cereal/details/helpers.hpp>
|
||||
#include "cereal/details/helpers.hpp"
|
||||
#include <utility>
|
||||
|
||||
namespace cereal
|
||||
|
@ -11,14 +11,14 @@
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of cereal nor the
|
||||
* 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 RANDOLPH VOORHIES OR SHANE GRANT BE LIABLE FOR ANY
|
||||
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
|
||||
@ -29,7 +29,7 @@
|
||||
#ifndef CEREAL_ARCHIVES_BINARY_HPP_
|
||||
#define CEREAL_ARCHIVES_BINARY_HPP_
|
||||
|
||||
#include <cereal/cereal.hpp>
|
||||
#include "cereal/cereal.hpp"
|
||||
#include <sstream>
|
||||
|
||||
namespace cereal
|
||||
@ -62,9 +62,9 @@ namespace cereal
|
||||
~BinaryOutputArchive() CEREAL_NOEXCEPT = default;
|
||||
|
||||
//! Writes size bytes of data to the output stream
|
||||
void saveBinary( const void * data, std::size_t size )
|
||||
void saveBinary( const void * data, std::streamsize size )
|
||||
{
|
||||
auto const writtenSize = static_cast<std::size_t>( itsStream.rdbuf()->sputn( reinterpret_cast<const char*>( data ), size ) );
|
||||
auto const writtenSize = itsStream.rdbuf()->sputn( reinterpret_cast<const char*>( data ), size );
|
||||
|
||||
if(writtenSize != size)
|
||||
throw Exception("Failed to write " + std::to_string(size) + " bytes to output stream! Wrote " + std::to_string(writtenSize));
|
||||
@ -97,9 +97,9 @@ namespace cereal
|
||||
~BinaryInputArchive() CEREAL_NOEXCEPT = default;
|
||||
|
||||
//! Reads size bytes of data from the input stream
|
||||
void loadBinary( void * const data, std::size_t size )
|
||||
void loadBinary( void * const data, std::streamsize size )
|
||||
{
|
||||
auto const readSize = static_cast<std::size_t>( itsStream.rdbuf()->sgetn( reinterpret_cast<char*>( data ), size ) );
|
||||
auto const readSize = itsStream.rdbuf()->sgetn( reinterpret_cast<char*>( data ), size );
|
||||
|
||||
if(readSize != size)
|
||||
throw Exception("Failed to read " + std::to_string(size) + " bytes from input stream! Read " + std::to_string(readSize));
|
||||
@ -148,14 +148,14 @@ namespace cereal
|
||||
template <class T> inline
|
||||
void CEREAL_SAVE_FUNCTION_NAME(BinaryOutputArchive & ar, BinaryData<T> const & bd)
|
||||
{
|
||||
ar.saveBinary( bd.data, static_cast<std::size_t>( bd.size ) );
|
||||
ar.saveBinary( bd.data, static_cast<std::streamsize>( bd.size ) );
|
||||
}
|
||||
|
||||
//! Loading binary data
|
||||
template <class T> inline
|
||||
void CEREAL_LOAD_FUNCTION_NAME(BinaryInputArchive & ar, BinaryData<T> & bd)
|
||||
{
|
||||
ar.loadBinary(bd.data, static_cast<std::size_t>(bd.size));
|
||||
ar.loadBinary(bd.data, static_cast<std::streamsize>( bd.size ) );
|
||||
}
|
||||
} // namespace cereal
|
||||
|
||||
|
@ -11,14 +11,14 @@
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of cereal nor the
|
||||
* 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 RANDOLPH VOORHIES OR SHANE GRANT BE LIABLE FOR ANY
|
||||
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
|
||||
@ -29,8 +29,8 @@
|
||||
#ifndef CEREAL_ARCHIVES_JSON_HPP_
|
||||
#define CEREAL_ARCHIVES_JSON_HPP_
|
||||
|
||||
#include <cereal/cereal.hpp>
|
||||
#include <cereal/details/util.hpp>
|
||||
#include "cereal/cereal.hpp"
|
||||
#include "cereal/details/util.hpp"
|
||||
|
||||
namespace cereal
|
||||
{
|
||||
@ -40,6 +40,11 @@ namespace cereal
|
||||
{ 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
|
||||
#ifndef CEREAL_RAPIDJSON_ASSERT
|
||||
#define CEREAL_RAPIDJSON_ASSERT(x) if(!(x)){ \
|
||||
@ -47,14 +52,20 @@ namespace cereal
|
||||
#endif // RAPIDJSON_ASSERT
|
||||
|
||||
// Enable support for parsing of nan, inf, -inf
|
||||
#ifndef CEREAL_RAPIDJSON_WRITE_DEFAULT_FLAGS
|
||||
#define CEREAL_RAPIDJSON_WRITE_DEFAULT_FLAGS kWriteNanAndInfFlag
|
||||
#define CEREAL_RAPIDJSON_PARSE_DEFAULT_FLAGS kParseFullPrecisionFlag | kParseNanAndInfFlag
|
||||
#endif
|
||||
|
||||
#include <cereal/external/rapidjson/prettywriter.h>
|
||||
#include <cereal/external/rapidjson/ostreamwrapper.h>
|
||||
#include <cereal/external/rapidjson/istreamwrapper.h>
|
||||
#include <cereal/external/rapidjson/document.h>
|
||||
#include <cereal/external/base64.hpp>
|
||||
// Enable support for parsing of nan, inf, -inf
|
||||
#ifndef CEREAL_RAPIDJSON_PARSE_DEFAULT_FLAGS
|
||||
#define CEREAL_RAPIDJSON_PARSE_DEFAULT_FLAGS kParseFullPrecisionFlag | kParseNanAndInfFlag
|
||||
#endif
|
||||
|
||||
#include "cereal/external/rapidjson/prettywriter.h"
|
||||
#include "cereal/external/rapidjson/ostreamwrapper.h"
|
||||
#include "cereal/external/rapidjson/istreamwrapper.h"
|
||||
#include "cereal/external/rapidjson/document.h"
|
||||
#include "cereal/external/base64.hpp"
|
||||
|
||||
#include <limits>
|
||||
#include <sstream>
|
||||
@ -96,8 +107,8 @@ namespace cereal
|
||||
{
|
||||
enum class NodeType { StartObject, InObject, StartArray, InArray };
|
||||
|
||||
using WriteStream = rapidjson::OStreamWrapper;
|
||||
using JSONWriter = rapidjson::PrettyWriter<WriteStream>;
|
||||
using WriteStream = CEREAL_RAPIDJSON_NAMESPACE::OStreamWrapper;
|
||||
using JSONWriter = CEREAL_RAPIDJSON_NAMESPACE::PrettyWriter<WriteStream>;
|
||||
|
||||
public:
|
||||
/*! @name Common Functionality
|
||||
@ -177,7 +188,7 @@ namespace cereal
|
||||
|
||||
auto base64string = base64::encode( reinterpret_cast<const unsigned char *>( data ), size );
|
||||
saveValue( base64string );
|
||||
};
|
||||
}
|
||||
|
||||
//! @}
|
||||
/*! @name Internal Functionality
|
||||
@ -209,11 +220,13 @@ namespace cereal
|
||||
{
|
||||
case NodeType::StartArray:
|
||||
itsWriter.StartArray();
|
||||
// fall through
|
||||
case NodeType::InArray:
|
||||
itsWriter.EndArray();
|
||||
break;
|
||||
case NodeType::StartObject:
|
||||
itsWriter.StartObject();
|
||||
// fall through
|
||||
case NodeType::InObject:
|
||||
itsWriter.EndObject();
|
||||
break;
|
||||
@ -242,12 +255,19 @@ namespace cereal
|
||||
//! Saves a double to the current node
|
||||
void saveValue(double d) { itsWriter.Double(d); }
|
||||
//! Saves a string to the current node
|
||||
void saveValue(std::string const & s) { itsWriter.String(s.c_str(), static_cast<rapidjson::SizeType>( s.size() )); }
|
||||
void saveValue(std::string const & s) { itsWriter.String(s.c_str(), static_cast<CEREAL_RAPIDJSON_NAMESPACE::SizeType>( s.size() )); }
|
||||
//! Saves a const char * to the current node
|
||||
void saveValue(char const * s) { itsWriter.String(s); }
|
||||
//! Saves a nullptr to the current node
|
||||
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:
|
||||
// Some compilers/OS have difficulty disambiguating the above for various flavors of longs, so we provide
|
||||
// special overloads to handle these cases.
|
||||
@ -273,19 +293,19 @@ namespace cereal
|
||||
void saveLong(T lu){ saveValue( static_cast<std::uint64_t>( lu ) ); }
|
||||
|
||||
public:
|
||||
#ifdef _MSC_VER
|
||||
#if defined(_MSC_VER) && _MSC_VER < 1916
|
||||
//! MSVC only long overload to current node
|
||||
void saveValue( unsigned long lu ){ saveLong( lu ); };
|
||||
#else // _MSC_VER
|
||||
//! Serialize a long if it would not be caught otherwise
|
||||
template <class T, traits::EnableIf<std::is_same<T, long>::value,
|
||||
!std::is_same<T, std::int32_t>::value,
|
||||
!std::is_same<T, int>::value,
|
||||
!std::is_same<T, std::int64_t>::value> = traits::sfinae> inline
|
||||
void saveValue( T t ){ saveLong( t ); }
|
||||
|
||||
//! Serialize an unsigned long if it would not be caught otherwise
|
||||
template <class T, traits::EnableIf<std::is_same<T, unsigned long>::value,
|
||||
!std::is_same<T, std::uint32_t>::value,
|
||||
!std::is_same<T, unsigned>::value,
|
||||
!std::is_same<T, std::uint64_t>::value> = traits::sfinae> inline
|
||||
void saveValue( T t ){ saveLong( t ); }
|
||||
#endif // _MSC_VER
|
||||
@ -297,6 +317,8 @@ namespace cereal
|
||||
!std::is_same<T, unsigned long>::value,
|
||||
!std::is_same<T, std::int64_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
|
||||
void saveValue(T const & t)
|
||||
{
|
||||
@ -406,11 +428,11 @@ namespace cereal
|
||||
class JSONInputArchive : public InputArchive<JSONInputArchive>, public traits::TextArchive
|
||||
{
|
||||
private:
|
||||
using ReadStream = rapidjson::IStreamWrapper;
|
||||
typedef rapidjson::GenericValue<rapidjson::UTF8<>> JSONValue;
|
||||
using ReadStream = CEREAL_RAPIDJSON_NAMESPACE::IStreamWrapper;
|
||||
typedef CEREAL_RAPIDJSON_NAMESPACE::GenericValue<CEREAL_RAPIDJSON_NAMESPACE::UTF8<>> JSONValue;
|
||||
typedef JSONValue::ConstMemberIterator MemberIterator;
|
||||
typedef JSONValue::ConstValueIterator ValueIterator;
|
||||
typedef rapidjson::Document::GenericValue GenericValue;
|
||||
typedef CEREAL_RAPIDJSON_NAMESPACE::Document::GenericValue GenericValue;
|
||||
|
||||
public:
|
||||
/*! @name Common Functionality
|
||||
@ -452,7 +474,7 @@ namespace cereal
|
||||
|
||||
std::memcpy( data, decoded.data(), decoded.size() );
|
||||
itsNextName = nullptr;
|
||||
};
|
||||
}
|
||||
|
||||
private:
|
||||
//! @}
|
||||
@ -470,12 +492,18 @@ namespace cereal
|
||||
Iterator() : itsIndex( 0 ), itsType(Null_) {}
|
||||
|
||||
Iterator(MemberIterator begin, MemberIterator end) :
|
||||
itsMemberItBegin(begin), itsMemberItEnd(end), itsIndex(0), itsType(Member)
|
||||
{ }
|
||||
itsMemberItBegin(begin), itsMemberItEnd(end), itsIndex(0), itsSize(std::distance(begin, end)), itsType(Member)
|
||||
{
|
||||
if( itsSize == 0 )
|
||||
itsType = Null_;
|
||||
}
|
||||
|
||||
Iterator(ValueIterator begin, ValueIterator end) :
|
||||
itsValueItBegin(begin), itsValueItEnd(end), itsIndex(0), itsType(Value)
|
||||
{ }
|
||||
itsValueItBegin(begin), itsIndex(0), itsSize(std::distance(begin, end)), itsType(Value)
|
||||
{
|
||||
if( itsSize == 0 )
|
||||
itsType = Null_;
|
||||
}
|
||||
|
||||
//! Advance to the next node
|
||||
Iterator & operator++()
|
||||
@ -487,11 +515,14 @@ namespace cereal
|
||||
//! Get the value of the current node
|
||||
GenericValue const & value()
|
||||
{
|
||||
if( itsIndex >= itsSize )
|
||||
throw cereal::Exception("No more objects in input");
|
||||
|
||||
switch(itsType)
|
||||
{
|
||||
case Value : return itsValueItBegin[itsIndex];
|
||||
case Member: return itsMemberItBegin[itsIndex].value;
|
||||
default: throw cereal::Exception("Invalid Iterator Type!");
|
||||
default: throw cereal::Exception("JSONInputArchive internal error: null or empty iterator to object or array!");
|
||||
}
|
||||
}
|
||||
|
||||
@ -526,9 +557,9 @@ namespace cereal
|
||||
|
||||
private:
|
||||
MemberIterator itsMemberItBegin, itsMemberItEnd; //!< The member iterator (object)
|
||||
ValueIterator itsValueItBegin, itsValueItEnd; //!< The value iterator (array)
|
||||
size_t itsIndex; //!< The current index of this iterator
|
||||
enum Type {Value, Member, Null_} itsType; //!< Whether this holds values (array) or members (objects) or nothing
|
||||
ValueIterator itsValueItBegin; //!< The value iterator (array)
|
||||
size_t itsIndex, itsSize; //!< The current index of this iterator
|
||||
enum Type {Value, Member, Null_} itsType; //!< Whether this holds values (array) or members (objects) or nothing
|
||||
};
|
||||
|
||||
//! Searches for the expectedName node if it doesn't match the actualName
|
||||
@ -542,18 +573,20 @@ namespace cereal
|
||||
@throws Exception if an expectedName is given and not found */
|
||||
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()
|
||||
if( itsNextName )
|
||||
if( localNextName )
|
||||
{
|
||||
// The actual name of the current node
|
||||
auto const actualName = itsIteratorStack.back().name();
|
||||
|
||||
// Do a search if we don't see a name coming up, or if the names don't match
|
||||
if( !actualName || std::strcmp( itsNextName, actualName ) != 0 )
|
||||
itsIteratorStack.back().search( itsNextName );
|
||||
if( !actualName || std::strcmp( localNextName, actualName ) != 0 )
|
||||
itsIteratorStack.back().search( localNextName );
|
||||
}
|
||||
|
||||
itsNextName = nullptr;
|
||||
}
|
||||
|
||||
public:
|
||||
@ -635,6 +668,12 @@ namespace cereal
|
||||
//! Loads a nullptr from the current node
|
||||
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
|
||||
// the int32_t or int64_t on various compiler/OS combinations. MSVC doesn't need any of this.
|
||||
#ifndef _MSC_VER
|
||||
@ -690,6 +729,8 @@ namespace cereal
|
||||
!std::is_same<T, unsigned long>::value,
|
||||
!std::is_same<T, std::int64_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 void loadValue(T & val)
|
||||
{
|
||||
@ -713,7 +754,7 @@ namespace cereal
|
||||
const char * itsNextName; //!< Next name set by NVP
|
||||
ReadStream itsReadStream; //!< Rapidjson write stream
|
||||
std::vector<Iterator> itsIteratorStack; //!< 'Stack' of rapidJSON iterators
|
||||
rapidjson::Document itsDocument; //!< Rapidjson document
|
||||
CEREAL_RAPIDJSON_NAMESPACE::Document itsDocument; //!< Rapidjson document
|
||||
};
|
||||
|
||||
// ######################################################################
|
||||
@ -745,6 +786,31 @@ namespace cereal
|
||||
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
|
||||
/*! SizeTags are strictly ignored for JSON, they just indicate
|
||||
|
@ -11,14 +11,14 @@
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of cereal nor the
|
||||
* 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 RANDOLPH VOORHIES OR SHANE GRANT BE LIABLE FOR ANY
|
||||
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
|
||||
@ -29,7 +29,7 @@
|
||||
#ifndef CEREAL_ARCHIVES_PORTABLE_BINARY_HPP_
|
||||
#define CEREAL_ARCHIVES_PORTABLE_BINARY_HPP_
|
||||
|
||||
#include <cereal/cereal.hpp>
|
||||
#include "cereal/cereal.hpp"
|
||||
#include <sstream>
|
||||
#include <limits>
|
||||
|
||||
@ -128,19 +128,19 @@ namespace cereal
|
||||
~PortableBinaryOutputArchive() CEREAL_NOEXCEPT = default;
|
||||
|
||||
//! Writes size bytes of data to the output stream
|
||||
template <std::size_t DataSize> inline
|
||||
void saveBinary( const void * data, std::size_t size )
|
||||
template <std::streamsize DataSize> inline
|
||||
void saveBinary( const void * data, std::streamsize size )
|
||||
{
|
||||
std::size_t writtenSize = 0;
|
||||
std::streamsize writtenSize = 0;
|
||||
|
||||
if( itsConvertEndianness )
|
||||
{
|
||||
for( std::size_t i = 0; i < size; i += DataSize )
|
||||
for( std::size_t j = 0; j < DataSize; ++j )
|
||||
writtenSize += static_cast<std::size_t>( itsStream.rdbuf()->sputn( reinterpret_cast<const char*>( data ) + DataSize - j - 1 + i, 1 ) );
|
||||
for( std::streamsize i = 0; i < size; i += DataSize )
|
||||
for( std::streamsize j = 0; j < DataSize; ++j )
|
||||
writtenSize += itsStream.rdbuf()->sputn( reinterpret_cast<const char*>( data ) + DataSize - j - 1 + i, 1 );
|
||||
}
|
||||
else
|
||||
writtenSize = static_cast<std::size_t>( itsStream.rdbuf()->sputn( reinterpret_cast<const char*>( data ), size ) );
|
||||
writtenSize = itsStream.rdbuf()->sputn( reinterpret_cast<const char*>( data ), size );
|
||||
|
||||
if(writtenSize != size)
|
||||
throw Exception("Failed to write " + std::to_string(size) + " bytes to output stream! Wrote " + std::to_string(writtenSize));
|
||||
@ -235,11 +235,11 @@ namespace cereal
|
||||
/*! @param data The data to save
|
||||
@param size The number of bytes in the data
|
||||
@tparam DataSize T The size of the actual type of the data elements being loaded */
|
||||
template <std::size_t DataSize> inline
|
||||
void loadBinary( void * const data, std::size_t size )
|
||||
template <std::streamsize DataSize> inline
|
||||
void loadBinary( void * const data, std::streamsize size )
|
||||
{
|
||||
// load data
|
||||
auto const readSize = static_cast<std::size_t>( itsStream.rdbuf()->sgetn( reinterpret_cast<char*>( data ), size ) );
|
||||
auto const readSize = itsStream.rdbuf()->sgetn( reinterpret_cast<char*>( data ), size );
|
||||
|
||||
if(readSize != size)
|
||||
throw Exception("Failed to read " + std::to_string(size) + " bytes from input stream! Read " + std::to_string(readSize));
|
||||
@ -248,7 +248,7 @@ namespace cereal
|
||||
if( itsConvertEndianness )
|
||||
{
|
||||
std::uint8_t * ptr = reinterpret_cast<std::uint8_t*>( data );
|
||||
for( std::size_t i = 0; i < size; i += DataSize )
|
||||
for( std::streamsize i = 0; i < size; i += DataSize )
|
||||
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),
|
||||
"Portable binary only supports IEEE 754 standardized floating point" );
|
||||
|
||||
ar.template saveBinary<sizeof(TT)>( bd.data, static_cast<std::size_t>( bd.size ) );
|
||||
ar.template saveBinary<sizeof(TT)>( bd.data, static_cast<std::streamsize>( bd.size ) );
|
||||
}
|
||||
|
||||
//! Loading binary data from portable binary
|
||||
@ -320,7 +320,7 @@ namespace cereal
|
||||
(std::is_floating_point<TT>::value && std::numeric_limits<TT>::is_iec559),
|
||||
"Portable binary only supports IEEE 754 standardized floating point" );
|
||||
|
||||
ar.template loadBinary<sizeof(TT)>( bd.data, static_cast<std::size_t>( bd.size ) );
|
||||
ar.template loadBinary<sizeof(TT)>( bd.data, static_cast<std::streamsize>( bd.size ) );
|
||||
}
|
||||
} // namespace cereal
|
||||
|
||||
|
@ -11,14 +11,14 @@
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of cereal nor the
|
||||
* 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 RANDOLPH VOORHIES OR SHANE GRANT BE LIABLE FOR ANY
|
||||
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
|
||||
@ -28,12 +28,12 @@
|
||||
*/
|
||||
#ifndef CEREAL_ARCHIVES_XML_HPP_
|
||||
#define CEREAL_ARCHIVES_XML_HPP_
|
||||
#include <cereal/cereal.hpp>
|
||||
#include <cereal/details/util.hpp>
|
||||
#include "cereal/cereal.hpp"
|
||||
#include "cereal/details/util.hpp"
|
||||
|
||||
#include <cereal/external/rapidxml/rapidxml.hpp>
|
||||
#include <cereal/external/rapidxml/rapidxml_print.hpp>
|
||||
#include <cereal/external/base64.hpp>
|
||||
#include "cereal/external/rapidxml/rapidxml.hpp"
|
||||
#include "cereal/external/rapidxml/rapidxml_print.hpp"
|
||||
#include "cereal/external/base64.hpp"
|
||||
|
||||
#include <sstream>
|
||||
#include <stack>
|
||||
@ -101,31 +101,58 @@ namespace cereal
|
||||
//! @{
|
||||
|
||||
//! 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
|
||||
{
|
||||
public:
|
||||
//! Default options
|
||||
static Options Default(){ return Options(); }
|
||||
|
||||
//! Default options with no indentation
|
||||
static Options NoIndent(){ return Options( std::numeric_limits<double>::max_digits10, false ); }
|
||||
|
||||
//! Specify specific options for the XMLOutputArchive
|
||||
/*! @param precision The precision used for floating point numbers
|
||||
@param indent Whether to indent each line of XML
|
||||
@param outputType Whether to output the type of each serialized object as an attribute */
|
||||
explicit Options( int precision = std::numeric_limits<double>::max_digits10,
|
||||
bool indent = true,
|
||||
bool outputType = false ) :
|
||||
itsPrecision( precision ),
|
||||
itsIndent( indent ),
|
||||
itsOutputType( outputType ) { }
|
||||
/*! @param precision_ The precision used for floating point numbers
|
||||
@param indent_ Whether to indent each line of XML
|
||||
@param outputType_ Whether to output the type of each serialized object as an attribute
|
||||
@param sizeAttributes_ Whether dynamically sized containers output the size=dynamic attribute */
|
||||
explicit Options( int precision_ = std::numeric_limits<double>::max_digits10,
|
||||
bool indent_ = true,
|
||||
bool outputType_ = false,
|
||||
bool sizeAttributes_ = true ) :
|
||||
itsPrecision( precision_ ),
|
||||
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:
|
||||
friend class XMLOutputArchive;
|
||||
int itsPrecision;
|
||||
bool itsIndent;
|
||||
bool itsOutputType;
|
||||
bool itsSizeAttributes;
|
||||
};
|
||||
|
||||
//! Construct, outputting to the provided stream upon destruction
|
||||
@ -137,7 +164,8 @@ namespace cereal
|
||||
OutputArchive<XMLOutputArchive>(this),
|
||||
itsStream(stream),
|
||||
itsOutputType( options.itsOutputType ),
|
||||
itsIndent( options.itsIndent )
|
||||
itsIndent( options.itsIndent ),
|
||||
itsSizeAttributes(options.itsSizeAttributes)
|
||||
{
|
||||
// rapidxml will delete all allocations when xml_document is cleared
|
||||
auto node = itsXML.allocate_node( rapidxml::node_declaration );
|
||||
@ -182,7 +210,7 @@ namespace cereal
|
||||
itsNodes.top().node->append_attribute( itsXML.allocate_attribute( "type", "cereal binary data" ) );
|
||||
|
||||
finishNode();
|
||||
};
|
||||
}
|
||||
|
||||
//! @}
|
||||
/*! @name Internal Functionality
|
||||
@ -289,6 +317,8 @@ namespace cereal
|
||||
itsNodes.top().node->append_attribute( itsXML.allocate_attribute( namePtr, valuePtr ) );
|
||||
}
|
||||
|
||||
bool hasSizeAttributes() const { return itsSizeAttributes; }
|
||||
|
||||
protected:
|
||||
//! A struct that contains metadata about a node
|
||||
struct NodeInfo
|
||||
@ -330,6 +360,7 @@ namespace cereal
|
||||
std::ostringstream itsOS; //!< Used to format strings internally
|
||||
bool itsOutputType; //!< Controls whether type information is printed
|
||||
bool itsIndent; //!< Controls whether indenting is used
|
||||
bool itsSizeAttributes; //!< Controls whether lists have a size attribute
|
||||
}; // XMLOutputArchive
|
||||
|
||||
// ######################################################################
|
||||
@ -436,7 +467,7 @@ namespace cereal
|
||||
std::memcpy( data, decoded.data(), decoded.size() );
|
||||
|
||||
finishNode();
|
||||
};
|
||||
}
|
||||
|
||||
//! @}
|
||||
/*! @name Internal Functionality
|
||||
@ -758,13 +789,41 @@ namespace cereal
|
||||
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
|
||||
/*! SizeTags do not start or finish nodes */
|
||||
template <class T> inline
|
||||
void prologue( XMLOutputArchive & ar, SizeTag<T> const & )
|
||||
{
|
||||
ar.appendAttribute( "size", "dynamic" );
|
||||
if (ar.hasSizeAttributes())
|
||||
{
|
||||
ar.appendAttribute("size", "dynamic");
|
||||
}
|
||||
}
|
||||
|
||||
template <class T> inline
|
||||
|
@ -11,14 +11,14 @@
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of cereal nor the
|
||||
* 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 RANDOLPH VOORHIES OR SHANE GRANT BE LIABLE FOR ANY
|
||||
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
|
||||
@ -32,6 +32,7 @@
|
||||
#include <type_traits>
|
||||
#include <string>
|
||||
#include <memory>
|
||||
#include <functional>
|
||||
#include <unordered_map>
|
||||
#include <unordered_set>
|
||||
#include <vector>
|
||||
@ -39,10 +40,10 @@
|
||||
#include <cstdint>
|
||||
#include <functional>
|
||||
|
||||
#include <cereal/macros.hpp>
|
||||
#include <cereal/details/traits.hpp>
|
||||
#include <cereal/details/helpers.hpp>
|
||||
#include <cereal/types/base_class.hpp>
|
||||
#include "cereal/macros.hpp"
|
||||
#include "cereal/details/traits.hpp"
|
||||
#include "cereal/details/helpers.hpp"
|
||||
#include "cereal/types/base_class.hpp"
|
||||
|
||||
namespace cereal
|
||||
{
|
||||
@ -97,6 +98,59 @@ namespace cereal
|
||||
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
|
||||
//! for processing some type
|
||||
@ -122,7 +176,7 @@ namespace cereal
|
||||
a serialization function. Classes with no data members are considered to be
|
||||
empty. Be warned that if this is enabled and you attempt to serialize an
|
||||
empty class with improperly formed serialize or load/save functions, no
|
||||
static error will occur - the error will propogate silently and your
|
||||
static error will occur - the error will propagate silently and your
|
||||
intended serialization functions may not be called. You can manually
|
||||
ensure that your classes that have custom serialization are correct
|
||||
by using the traits is_output_serializable and is_input_serializable
|
||||
@ -145,6 +199,14 @@ namespace cereal
|
||||
instantiate_polymorphic_binding( T*, Archive*, BindingTag, adl_tag ); \
|
||||
} } /* 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
|
||||
/*! Versioning information is optional and adds some small amount of
|
||||
@ -196,6 +258,26 @@ namespace cereal
|
||||
Interfaces for other forms of serialization functions is similar. This
|
||||
macro should be placed at global scope.
|
||||
@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) \
|
||||
namespace cereal { namespace detail { \
|
||||
template <> struct Version<TYPE> \
|
||||
@ -207,12 +289,14 @@ namespace cereal
|
||||
std::type_index(typeid(TYPE)).hash_code(), VERSION_NUMBER ); \
|
||||
return VERSION_NUMBER; \
|
||||
} \
|
||||
static void unused() { (void)version; } \
|
||||
CEREAL_UNUSED_FUNCTION \
|
||||
}; /* end Version */ \
|
||||
const std::uint32_t Version<TYPE>::version = \
|
||||
Version<TYPE>::registerVersion(); \
|
||||
} } // end namespaces
|
||||
|
||||
#endif
|
||||
|
||||
// ######################################################################
|
||||
//! The base output archive class
|
||||
/*! This is the base output archive for all output archives. If you create
|
||||
@ -250,11 +334,33 @@ namespace cereal
|
||||
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
|
||||
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(). */
|
||||
//! @{
|
||||
|
||||
//! 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
|
||||
/*! 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
|
||||
@ -285,12 +391,17 @@ namespace cereal
|
||||
point to the same data.
|
||||
|
||||
@internal
|
||||
@param addr The address (see shared_ptr get()) pointed to by the shared pointer
|
||||
@param sharedPointer The shared pointer itself (the address is taken via get()).
|
||||
The archive takes a copy to prevent the memory location to be freed
|
||||
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 */
|
||||
inline std::uint32_t registerSharedPointer( void const * addr )
|
||||
inline std::uint32_t registerSharedPointer(const std::shared_ptr<const void>& sharedPointer)
|
||||
{
|
||||
void const * addr = sharedPointer.get();
|
||||
|
||||
// Handle null pointers by just returning 0
|
||||
if(addr == 0) return 0;
|
||||
itsSharedPointerStorage.push_back(sharedPointer);
|
||||
|
||||
auto id = itsSharedPointerMap.find( addr );
|
||||
if( id == itsSharedPointerMap.end() )
|
||||
@ -365,6 +476,17 @@ namespace cereal
|
||||
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
|
||||
/*! Requirements:
|
||||
Has the requested serialization function
|
||||
@ -469,8 +591,7 @@ namespace cereal
|
||||
/*! If this is the first time this class has been serialized, we will record its
|
||||
version number and serialize that.
|
||||
|
||||
@tparam T The type of the class being serialized
|
||||
@param version The version number associated with it */
|
||||
@tparam T The type of the class being serialized */
|
||||
template <class T> inline
|
||||
std::uint32_t registerClassVersion()
|
||||
{
|
||||
@ -551,6 +672,10 @@ namespace cereal
|
||||
//! Maps from addresses to pointer ids
|
||||
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
|
||||
std::uint32_t itsCurrentPointerId;
|
||||
|
||||
@ -606,11 +731,33 @@ namespace cereal
|
||||
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
|
||||
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(). */
|
||||
//! @{
|
||||
|
||||
//! 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
|
||||
/*! 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
|
||||
@ -639,6 +786,7 @@ namespace cereal
|
||||
/*! This is used to retrieve a previously registered shared_ptr
|
||||
which has already been loaded.
|
||||
|
||||
@internal
|
||||
@param id The unique id that was serialized for the pointer
|
||||
@return A shared pointer to the data
|
||||
@throw Exception if the id does not exist */
|
||||
@ -657,6 +805,7 @@ namespace cereal
|
||||
/*! After a shared pointer has been allocated for the first time, it should
|
||||
be registered with its loaded id for future references to it.
|
||||
|
||||
@internal
|
||||
@param id The unique identifier for the shared pointer
|
||||
@param ptr The actual shared pointer */
|
||||
inline void registerSharedPointer(std::uint32_t const id, std::shared_ptr<void> ptr)
|
||||
@ -669,8 +818,9 @@ namespace cereal
|
||||
/*! This is used to retrieve a string previously registered during
|
||||
a polymorphic load.
|
||||
|
||||
@internal
|
||||
@param id The unique id that was serialized for the polymorphic type
|
||||
@return The string identifier for the tyep */
|
||||
@return The string identifier for the type */
|
||||
inline std::string getPolymorphicName(std::uint32_t const id)
|
||||
{
|
||||
auto name = itsPolymorphicTypeMap.find( id );
|
||||
@ -685,8 +835,9 @@ namespace cereal
|
||||
/*! After a polymorphic type has been loaded for the first time, it should
|
||||
be registered with its loaded id for future references to it.
|
||||
|
||||
@internal
|
||||
@param id The unique identifier for the polymorphic type
|
||||
@param name The name associated with the tyep */
|
||||
@param name The name associated with the type */
|
||||
inline void registerPolymorphicName(std::uint32_t const id, std::string const & name)
|
||||
{
|
||||
std::uint32_t const stripped_id = id & ~detail::msb_32bit;
|
||||
@ -734,6 +885,17 @@ namespace cereal
|
||||
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
|
||||
/*! Requirements:
|
||||
Has the requested serialization function
|
||||
@ -847,8 +1009,7 @@ namespace cereal
|
||||
/*! If this is the first time this class has been serialized, we will record its
|
||||
version number and serialize that.
|
||||
|
||||
@tparam T The type of the class being serialized
|
||||
@param version The version number associated with it */
|
||||
@tparam T The type of the class being serialized */
|
||||
template <class T> inline
|
||||
std::uint32_t loadClassVersion()
|
||||
{
|
||||
@ -954,6 +1115,6 @@ namespace cereal
|
||||
} // namespace cereal
|
||||
|
||||
// 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_
|
||||
|
@ -12,14 +12,14 @@
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of cereal nor the
|
||||
* 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 RANDOLPH VOORHIES OR SHANE GRANT BE LIABLE FOR ANY
|
||||
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
|
||||
@ -37,8 +37,8 @@
|
||||
#include <unordered_map>
|
||||
#include <stdexcept>
|
||||
|
||||
#include <cereal/macros.hpp>
|
||||
#include <cereal/details/static_object.hpp>
|
||||
#include "cereal/macros.hpp"
|
||||
#include "cereal/details/static_object.hpp"
|
||||
|
||||
namespace cereal
|
||||
{
|
||||
@ -55,8 +55,10 @@ namespace cereal
|
||||
//! The size type used by cereal
|
||||
/*! To ensure compatability between 32, 64, etc bit machines, we need to use
|
||||
a fixed size type instead of size_t, which may vary from machine to
|
||||
machine. */
|
||||
using size_type = uint64_t;
|
||||
machine.
|
||||
|
||||
The default value for CEREAL_SIZE_TYPE is specified in cereal/macros.hpp */
|
||||
using size_type = CEREAL_SIZE_TYPE;
|
||||
|
||||
// forward decls
|
||||
class BinaryOutputArchive;
|
||||
@ -66,8 +68,10 @@ namespace cereal
|
||||
namespace detail
|
||||
{
|
||||
struct NameValuePairCore {}; //!< Traits struct for NVPs
|
||||
struct DeferredDataCore {}; //!< Traits struct for DeferredData
|
||||
}
|
||||
|
||||
// ######################################################################
|
||||
//! For holding name value pairs
|
||||
/*! This pairs a name (some string) with some value such that an archive
|
||||
can potentially take advantage of the pairing.
|
||||
@ -208,7 +212,7 @@ namespace cereal
|
||||
{
|
||||
//! Internally store the pointer as a void *, keeping const if created with
|
||||
//! a const pointer
|
||||
using PT = typename std::conditional<std::is_const<typename std::remove_pointer<T>::type>::value,
|
||||
using PT = typename std::conditional<std::is_const<typename std::remove_pointer<typename std::remove_reference<T>::type>::type>::value,
|
||||
const void *,
|
||||
void *>::type;
|
||||
|
||||
@ -218,6 +222,43 @@ namespace cereal
|
||||
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
|
||||
{
|
||||
@ -254,7 +295,7 @@ namespace cereal
|
||||
struct adl_tag;
|
||||
|
||||
// used during saving pointers
|
||||
static const int32_t msb_32bit = 0x80000000;
|
||||
static const uint32_t msb_32bit = 0x80000000;
|
||||
static const int32_t msb2_32bit = 0x40000000;
|
||||
}
|
||||
|
||||
|
@ -12,14 +12,14 @@
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of cereal nor the
|
||||
* 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 RANDOLPH VOORHIES OR SHANE GRANT BE LIABLE FOR ANY
|
||||
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
|
||||
@ -45,32 +45,58 @@
|
||||
#ifndef CEREAL_DETAILS_POLYMORPHIC_IMPL_HPP_
|
||||
#define CEREAL_DETAILS_POLYMORPHIC_IMPL_HPP_
|
||||
|
||||
#include <cereal/details/polymorphic_impl_fwd.hpp>
|
||||
#include <cereal/details/static_object.hpp>
|
||||
#include <cereal/types/memory.hpp>
|
||||
#include <cereal/types/string.hpp>
|
||||
#include "cereal/details/polymorphic_impl_fwd.hpp"
|
||||
#include "cereal/details/static_object.hpp"
|
||||
#include "cereal/types/memory.hpp"
|
||||
#include "cereal/types/string.hpp"
|
||||
#include <functional>
|
||||
#include <typeindex>
|
||||
#include <map>
|
||||
#include <limits>
|
||||
#include <set>
|
||||
#include <stack>
|
||||
|
||||
//! Binds a polymorhic type to all registered archives
|
||||
//! Helper macro to omit unused warning
|
||||
#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
|
||||
have been registered with CEREAL_REGISTER_ARCHIVE. This must be called
|
||||
after all archives are registered (usually after the archives themselves
|
||||
have been included). */
|
||||
#ifdef CEREAL_HAS_CPP17
|
||||
#define CEREAL_BIND_TO_ARCHIVES(...) \
|
||||
namespace cereal { \
|
||||
namespace detail { \
|
||||
template<> \
|
||||
struct init_binding<__VA_ARGS__> { \
|
||||
static bind_to_archives<__VA_ARGS__> const & b; \
|
||||
static void unused() { (void)b; } \
|
||||
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(...) \
|
||||
namespace cereal { \
|
||||
namespace detail { \
|
||||
template<> \
|
||||
struct init_binding<__VA_ARGS__> { \
|
||||
static bind_to_archives<__VA_ARGS__> const& b; \
|
||||
CEREAL_BIND_TO_ARCHIVES_UNUSED_FUNCTION \
|
||||
}; \
|
||||
bind_to_archives<__VA_ARGS__> const & init_binding<__VA_ARGS__>::b = \
|
||||
::cereal::detail::StaticObject< \
|
||||
bind_to_archives<__VA_ARGS__> \
|
||||
>::getInstance().bind(); \
|
||||
}} /* end namespaces */
|
||||
#endif
|
||||
|
||||
namespace cereal
|
||||
{
|
||||
@ -112,8 +138,12 @@ namespace cereal
|
||||
all registered mappings between base and derived types. */
|
||||
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
|
||||
std::map<std::type_index, std::map<std::type_index, std::vector<PolymorphicCaster const*>>> map;
|
||||
std::unordered_map<std::type_index, DerivedCasterMap> map;
|
||||
|
||||
std::multimap<std::type_index, std::type_index> reverseMap;
|
||||
|
||||
//! Error message used for unregistered polymorphic casts
|
||||
#define UNREGISTERED_POLYMORPHIC_CAST_EXCEPTION(LoadSave) \
|
||||
@ -122,24 +152,26 @@ namespace cereal
|
||||
"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.");
|
||||
|
||||
//! Checks if the mapping object that can perform the upcast or downcast
|
||||
//! Checks if the mapping object that can perform the upcast or downcast exists, and returns it if so
|
||||
/*! Uses the type index from the base and derived class to find the matching
|
||||
registered caster. If no matching caster exists, returns false. */
|
||||
static bool exists( std::type_index const & baseIndex, std::type_index const & derivedIndex )
|
||||
registered caster. If no matching caster exists, the bool in the pair will be false and the vector
|
||||
reference should not be used. */
|
||||
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
|
||||
auto const & baseMap = StaticObject<PolymorphicCasters>::getInstance().map;
|
||||
auto baseIter = baseMap.find( baseIndex );
|
||||
if (baseIter == baseMap.end())
|
||||
return false;
|
||||
return {false, {}};
|
||||
|
||||
// Second phase - find a match from base to derived
|
||||
auto & derivedMap = baseIter->second;
|
||||
auto const & derivedMap = baseIter->second;
|
||||
auto derivedIter = derivedMap.find( derivedIndex );
|
||||
if (derivedIter == derivedMap.end())
|
||||
return false;
|
||||
return {false, {}};
|
||||
|
||||
return true;
|
||||
return {true, derivedIter->second};
|
||||
}
|
||||
|
||||
//! Gets the mapping object that can perform the upcast or downcast
|
||||
@ -157,7 +189,7 @@ namespace cereal
|
||||
exceptionFunc();
|
||||
|
||||
// Second phase - find a match from base to derived
|
||||
auto & derivedMap = baseIter->second;
|
||||
auto const & derivedMap = baseIter->second;
|
||||
auto derivedIter = derivedMap.find( derivedIndex );
|
||||
if( derivedIter == derivedMap.end() )
|
||||
exceptionFunc();
|
||||
@ -171,8 +203,8 @@ namespace cereal
|
||||
{
|
||||
auto const & mapping = lookup( baseInfo, typeid(Derived), [&](){ UNREGISTERED_POLYMORPHIC_CAST_EXCEPTION(save) } );
|
||||
|
||||
for( auto const * map : mapping )
|
||||
dptr = map->downcast( dptr );
|
||||
for( auto const * dmap : mapping )
|
||||
dptr = dmap->downcast( dptr );
|
||||
|
||||
return static_cast<Derived const *>( dptr );
|
||||
}
|
||||
@ -186,8 +218,8 @@ namespace cereal
|
||||
auto const & mapping = lookup( baseInfo, typeid(Derived), [&](){ UNREGISTERED_POLYMORPHIC_CAST_EXCEPTION(load) } );
|
||||
|
||||
void * uptr = dptr;
|
||||
for( auto const * map : mapping )
|
||||
uptr = map->upcast( uptr );
|
||||
for( auto mIter = mapping.rbegin(), mEnd = mapping.rend(); mIter != mEnd; ++mIter )
|
||||
uptr = (*mIter)->upcast( uptr );
|
||||
|
||||
return uptr;
|
||||
}
|
||||
@ -199,8 +231,8 @@ namespace cereal
|
||||
auto const & mapping = lookup( baseInfo, typeid(Derived), [&](){ UNREGISTERED_POLYMORPHIC_CAST_EXCEPTION(load) } );
|
||||
|
||||
std::shared_ptr<void> uptr = dptr;
|
||||
for( auto const * map : mapping )
|
||||
uptr = map->upcast( uptr );
|
||||
for( auto mIter = mapping.rbegin(), mEnd = mapping.rend(); mIter != mEnd; ++mIter )
|
||||
uptr = (*mIter)->upcast( uptr );
|
||||
|
||||
return uptr;
|
||||
}
|
||||
@ -208,6 +240,14 @@ namespace cereal
|
||||
#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
|
||||
template <class Base, class Derived>
|
||||
struct PolymorphicVirtualCaster : PolymorphicCaster
|
||||
@ -218,72 +258,155 @@ namespace cereal
|
||||
assuming dynamic type information is available */
|
||||
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();
|
||||
auto & baseMap = StaticObject<PolymorphicCasters>::getInstance().map;
|
||||
auto baseKey = std::type_index(typeid(Base));
|
||||
auto lb = baseMap.lower_bound(baseKey);
|
||||
|
||||
{
|
||||
auto & derivedMap = baseMap.insert( lb, {baseKey, {}} )->second;
|
||||
auto derivedKey = std::type_index(typeid(Derived));
|
||||
auto lbd = derivedMap.lower_bound(derivedKey);
|
||||
auto & derivedVec = derivedMap.insert( lbd, { std::move(derivedKey), {}} )->second;
|
||||
auto & derivedMap = baseMap.insert( {baseKey, PolymorphicCasters::DerivedCasterMap{}} ).first->second;
|
||||
auto & derivedVec = derivedMap.insert( {derivedKey, {}} ).first->second;
|
||||
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
|
||||
std::map<std::type_index, std::pair<std::type_index, std::vector<PolymorphicCaster const *>>> unregisteredRelations;
|
||||
/* The strategy here is to process only the nodes in the class hierarchy graph that have been
|
||||
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 */
|
||||
{
|
||||
auto checkRelation = [](std::type_index const & baseInfo, std::type_index const & derivedInfo)
|
||||
// Checks whether there is a path from parent->child and returns a <dist, path> pair
|
||||
// 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 &>
|
||||
{
|
||||
const bool exists = PolymorphicCasters::exists( baseInfo, derivedInfo );
|
||||
return std::make_pair( exists, exists ? PolymorphicCasters::lookup( baseInfo, derivedInfo, [](){} ) :
|
||||
std::vector<PolymorphicCaster const *>{} );
|
||||
auto result = PolymorphicCasters::lookup_if_exists( parentInfo, childInfo );
|
||||
if( result.first )
|
||||
{
|
||||
auto const & path = result.second;
|
||||
return {path.size(), path};
|
||||
}
|
||||
else
|
||||
return {(std::numeric_limits<size_t>::max)(), {}};
|
||||
};
|
||||
|
||||
for( auto baseIt : baseMap )
|
||||
for( auto derivedIt : baseIt.second )
|
||||
std::stack<std::type_index> parentStack; // Holds the parent nodes to be processed
|
||||
std::vector<std::type_index> dirtySet; // Marks child nodes that have been changed
|
||||
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( 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 *>>>;
|
||||
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] )
|
||||
{
|
||||
for( auto otherBaseIt : baseMap )
|
||||
const auto child = childPair.first;
|
||||
if( isDirty( child ) && baseMap.count( child ) )
|
||||
{
|
||||
if( baseIt.first == otherBaseIt.first ) // only interested in chained relations
|
||||
continue;
|
||||
auto parentChildPath = checkRelation( parent, child );
|
||||
|
||||
// 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 )
|
||||
// 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] )
|
||||
{
|
||||
std::vector<PolymorphicCaster const *> path = otherBaseToBase.second;
|
||||
path.insert( path.end(), baseToDerived.second.begin(), baseToDerived.second.end() );
|
||||
const auto finalChild = finalChildPair.first;
|
||||
|
||||
#ifdef CEREAL_OLDER_GCC
|
||||
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
|
||||
unregisteredRelations.emplace( otherBaseIt.first,
|
||||
std::pair<std::type_index, std::vector<PolymorphicCaster const *>>{derivedIt.first, std::move(path)} );
|
||||
#endif // NOT CEREAL_OLDER_GCC
|
||||
}
|
||||
} // end otherBaseIt
|
||||
} // end derivedIt
|
||||
} // end chain lookup
|
||||
auto parentFinalChildPath = checkRelation( parent, finalChild );
|
||||
auto childFinalChildPath = checkRelation( child, finalChild );
|
||||
|
||||
// Insert chained relations
|
||||
for( auto it : unregisteredRelations )
|
||||
{
|
||||
auto & derivedMap = baseMap.find( it.first )->second;
|
||||
derivedMap[it.second.first] = it.second.second;
|
||||
}
|
||||
}
|
||||
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;
|
||||
|
||||
auto newPath = std::pair<std::type_index, std::vector<PolymorphicCaster const *>>{finalChild, std::move(path)};
|
||||
|
||||
// Insert the new path if it doesn't exist, otherwise this will just lookup where to do the
|
||||
// replacement
|
||||
#ifdef CEREAL_OLDER_GCC
|
||||
auto old = unregisteredRelations.insert( hint, std::make_pair(parent, newPath) );
|
||||
#else // NOT CEREAL_OLDER_GCC
|
||||
auto old = unregisteredRelations.emplace_hint( hint, parent, newPath );
|
||||
#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 if dirty and child has children
|
||||
} // end loop over children
|
||||
|
||||
// Insert chained relations
|
||||
for( auto const & it : unregisteredRelations )
|
||||
{
|
||||
auto & derivedMap = baseMap.find( it.first )->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
|
||||
void const * downcast( void const * const ptr ) const override
|
||||
@ -546,7 +669,7 @@ namespace cereal
|
||||
|
||||
auto ptr = PolymorphicCasters::template downcast<T>( dptr, baseInfo );
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#if defined(_MSC_VER) && _MSC_VER < 1916 && !defined(__clang__)
|
||||
savePolymorphicSharedPtr( ar, ptr, ::cereal::traits::has_shared_from_this<T>::type() ); // MSVC doesn't like typename here
|
||||
#else // not _MSC_VER
|
||||
savePolymorphicSharedPtr( ar, ptr, typename ::cereal::traits::has_shared_from_this<T>::type() );
|
||||
@ -572,9 +695,23 @@ namespace cereal
|
||||
//! of instantiate_polymorphic_binding
|
||||
struct adl_tag {};
|
||||
|
||||
//! Tag for init_binding, bind_to_archives and instantiate_polymorphic_binding. Due to the use of anonymous
|
||||
//! namespace it becomes a different type in each translation unit.
|
||||
//! Tag for init_binding, bind_to_archives and instantiate_polymorphic_binding.
|
||||
//! For C++14 and below, we must instantiate a unique StaticObject per TU that is
|
||||
//! 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 {}; }
|
||||
#endif
|
||||
|
||||
|
||||
//! Causes the static object bindings between an archive type and a serializable type T
|
||||
template <class Archive, class T>
|
||||
@ -644,8 +781,8 @@ namespace cereal
|
||||
{
|
||||
//! Binding for non abstract types
|
||||
void bind(std::false_type) const
|
||||
{
|
||||
instantiate_polymorphic_binding((T*) 0, 0, Tag{}, adl_tag{});
|
||||
{
|
||||
instantiate_polymorphic_binding(static_cast<T*>(nullptr), 0, Tag{}, adl_tag{});
|
||||
}
|
||||
|
||||
//! Binding for abstract types
|
||||
@ -675,7 +812,7 @@ namespace cereal
|
||||
|
||||
Since the compiler needs to check all possible overloads, the
|
||||
other overloads created via CEREAL_REGISTER_ARCHIVE, which will have
|
||||
lower precedence due to requring a conversion from int to (Archive*),
|
||||
lower precedence due to requiring a conversion from int to (Archive*),
|
||||
will cause their return types to be instantiated through the static object
|
||||
mechanisms even though they are never called.
|
||||
|
||||
|
@ -12,14 +12,14 @@
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of cereal nor the
|
||||
* 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 RANDOLPH VOORHIES OR SHANE GRANT BE LIABLE FOR ANY
|
||||
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
|
||||
|
@ -11,13 +11,13 @@
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of cereal nor the
|
||||
* 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 RANDOLPH VOORHIES OR SHANE GRANT BE LIABLE FOR ANY
|
||||
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
|
||||
@ -28,7 +28,7 @@
|
||||
#ifndef CEREAL_DETAILS_STATIC_OBJECT_HPP_
|
||||
#define CEREAL_DETAILS_STATIC_OBJECT_HPP_
|
||||
|
||||
#include <cereal/macros.hpp>
|
||||
#include "cereal/macros.hpp"
|
||||
|
||||
#if CEREAL_THREAD_SAFE
|
||||
#include <mutex>
|
||||
@ -44,11 +44,11 @@
|
||||
License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
|
||||
http://www.boost.org/LICENSE_1_0.txt) */
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#if defined(_MSC_VER) && !defined(__clang__)
|
||||
# define CEREAL_DLL_EXPORT __declspec(dllexport)
|
||||
# define CEREAL_USED
|
||||
#else // clang or gcc
|
||||
# define CEREAL_DLL_EXPORT
|
||||
# define CEREAL_DLL_EXPORT __attribute__ ((visibility("default")))
|
||||
# define CEREAL_USED __attribute__ ((__used__))
|
||||
#endif
|
||||
|
||||
@ -67,13 +67,12 @@ namespace cereal
|
||||
class CEREAL_DLL_EXPORT StaticObject
|
||||
{
|
||||
private:
|
||||
//! Forces instantiation at pre-execution time
|
||||
static void instantiate( T const & ) {}
|
||||
|
||||
static T & create()
|
||||
{
|
||||
static T t;
|
||||
instantiate(instance);
|
||||
//! Forces instantiation at pre-execution time
|
||||
(void)instance;
|
||||
return t;
|
||||
}
|
||||
|
||||
@ -95,6 +94,8 @@ namespace cereal
|
||||
std::unique_lock<std::mutex> lock;
|
||||
#else
|
||||
public:
|
||||
LockGuard() = default;
|
||||
LockGuard(LockGuard const &) = default; // prevents implicit copy ctor warning
|
||||
~LockGuard() CEREAL_NOEXCEPT {} // prevents variable not used
|
||||
#endif
|
||||
};
|
||||
@ -109,6 +110,7 @@ namespace cereal
|
||||
static LockGuard lock()
|
||||
{
|
||||
#if CEREAL_THREAD_SAFE
|
||||
static std::mutex instanceMutex;
|
||||
return LockGuard{instanceMutex};
|
||||
#else
|
||||
return LockGuard{};
|
||||
@ -117,15 +119,9 @@ namespace cereal
|
||||
|
||||
private:
|
||||
static T & instance;
|
||||
#if CEREAL_THREAD_SAFE
|
||||
static std::mutex instanceMutex;
|
||||
#endif
|
||||
};
|
||||
|
||||
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 cereal
|
||||
|
||||
|
@ -12,14 +12,14 @@
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of cereal nor the
|
||||
* 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 RANDOLPH VOORHIES OR SHANE GRANT BE LIABLE FOR ANY
|
||||
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
|
||||
@ -39,8 +39,8 @@
|
||||
#include <type_traits>
|
||||
#include <typeindex>
|
||||
|
||||
#include <cereal/macros.hpp>
|
||||
#include <cereal/access.hpp>
|
||||
#include "cereal/macros.hpp"
|
||||
#include "cereal/access.hpp"
|
||||
|
||||
namespace cereal
|
||||
{
|
||||
@ -800,6 +800,18 @@ namespace cereal
|
||||
|
||||
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 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 */
|
||||
@ -847,9 +859,6 @@ namespace cereal
|
||||
static_assert( check::valid || !check::exists, "cereal detected different types in corresponding non-member " \
|
||||
#test_name " and " #save_name " functions. \n " \
|
||||
"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 */ \
|
||||
\
|
||||
@ -869,17 +878,29 @@ namespace cereal
|
||||
#undef CEREAL_MAKE_HAS_NON_MEMBER_LOAD_MINIMAL_TEST
|
||||
|
||||
// ######################################################################
|
||||
namespace detail
|
||||
{
|
||||
// const stripped away before reaching here, prevents errors on conversion from
|
||||
// construct<const T> to construct<T>
|
||||
template<typename T, typename A>
|
||||
struct has_member_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>&>() ) ), 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 : std::integral_constant<bool,
|
||||
std::is_same<decltype( access::load_and_construct<T>( std::declval<A&>(), std::declval< ::cereal::construct<T>&>() ) ), void>::value>
|
||||
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)
|
||||
template<typename T, typename 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>
|
||||
struct has_member_versioned_load_and_construct : detail::has_member_versioned_load_and_construct_impl<typename std::remove_const<T>::type, A>
|
||||
{ };
|
||||
|
||||
// ######################################################################
|
||||
@ -901,7 +922,8 @@ namespace cereal
|
||||
}; \
|
||||
} /* end namespace detail */ \
|
||||
template <class T, class A> \
|
||||
struct has_non_member_##test_name : std::integral_constant<bool, detail::has_non_member_##test_name##_impl<T, A>::value> {};
|
||||
struct has_non_member_##test_name : \
|
||||
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
|
||||
@ -1180,9 +1202,9 @@ namespace cereal
|
||||
struct shared_from_this_wrapper
|
||||
{
|
||||
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>
|
||||
static auto get( U const & t ) -> decltype( t.shared_from_this() );
|
||||
@ -1191,7 +1213,7 @@ namespace cereal
|
||||
|
||||
//! Determine if T or any base class of T has inherited from std::enable_shared_from_this
|
||||
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
|
||||
|
@ -12,14 +12,14 @@
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of cereal nor the
|
||||
* 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 RANDOLPH VOORHIES OR SHANE GRANT BE LIABLE FOR ANY
|
||||
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
|
||||
|
21
include/cereal/external/LICENSE
vendored
Normal file
21
include/cereal/external/LICENSE
vendored
Normal file
@ -0,0 +1,21 @@
|
||||
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
|
23
include/cereal/external/base64.hpp
vendored
23
include/cereal/external/base64.hpp
vendored
@ -25,6 +25,11 @@
|
||||
#ifndef CEREAL_EXTERNAL_BASE64_HPP_
|
||||
#define CEREAL_EXTERNAL_BASE64_HPP_
|
||||
|
||||
#ifdef __GNUC__
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wconversion"
|
||||
#endif
|
||||
|
||||
#include <string>
|
||||
|
||||
namespace cereal
|
||||
@ -50,10 +55,10 @@ namespace cereal
|
||||
while (in_len--) {
|
||||
char_array_3[i++] = *(bytes_to_encode++);
|
||||
if (i == 3) {
|
||||
char_array_4[0] = (unsigned char) ((char_array_3[0] & 0xfc) >> 2);
|
||||
char_array_4[1] = (unsigned char) ( ( ( char_array_3[0] & 0x03 ) << 4 ) + ( ( char_array_3[1] & 0xf0 ) >> 4 ) );
|
||||
char_array_4[2] = (unsigned char) ( ( ( char_array_3[1] & 0x0f ) << 2 ) + ( ( char_array_3[2] & 0xc0 ) >> 6 ) );
|
||||
char_array_4[3] = (unsigned char) ( char_array_3[2] & 0x3f );
|
||||
char_array_4[0] = static_cast<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[2] = static_cast<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 );
|
||||
|
||||
for(i = 0; (i <4) ; i++)
|
||||
ret += chars[char_array_4[i]];
|
||||
@ -76,11 +81,9 @@ namespace cereal
|
||||
|
||||
while((i++ < 3))
|
||||
ret += '=';
|
||||
|
||||
}
|
||||
|
||||
return ret;
|
||||
|
||||
}
|
||||
|
||||
inline std::string decode(std::string const& encoded_string) {
|
||||
@ -95,7 +98,7 @@ namespace cereal
|
||||
char_array_4[i++] = encoded_string[in_]; in_++;
|
||||
if (i ==4) {
|
||||
for (i = 0; i <4; i++)
|
||||
char_array_4[i] = (unsigned char) chars.find( char_array_4[i] );
|
||||
char_array_4[i] = static_cast<unsigned char>(chars.find( char_array_4[i] ));
|
||||
|
||||
char_array_3[0] = (char_array_4[0] << 2) + ((char_array_4[1] & 0x30) >> 4);
|
||||
char_array_3[1] = ((char_array_4[1] & 0xf) << 4) + ((char_array_4[2] & 0x3c) >> 2);
|
||||
@ -112,7 +115,7 @@ namespace cereal
|
||||
char_array_4[j] = 0;
|
||||
|
||||
for (j = 0; j <4; j++)
|
||||
char_array_4[j] = (unsigned char) chars.find( char_array_4[j] );
|
||||
char_array_4[j] = static_cast<unsigned char>(chars.find( char_array_4[j] ));
|
||||
|
||||
char_array_3[0] = (char_array_4[0] << 2) + ((char_array_4[1] & 0x30) >> 4);
|
||||
char_array_3[1] = ((char_array_4[1] & 0xf) << 4) + ((char_array_4[2] & 0x3c) >> 2);
|
||||
@ -125,5 +128,7 @@ namespace cereal
|
||||
}
|
||||
} // namespace base64
|
||||
} // namespace cereal
|
||||
|
||||
#ifdef __GNUC__
|
||||
#pragma GCC diagnostic pop
|
||||
#endif
|
||||
#endif // CEREAL_EXTERNAL_BASE64_HPP_
|
||||
|
13
include/cereal/external/rapidjson/LICENSE
vendored
Normal file
13
include/cereal/external/rapidjson/LICENSE
vendored
Normal file
@ -0,0 +1,13 @@
|
||||
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.
|
17
include/cereal/external/rapidjson/allocators.h
vendored
17
include/cereal/external/rapidjson/allocators.h
vendored
@ -52,6 +52,19 @@ concept Allocator {
|
||||
\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
|
||||
|
||||
@ -236,7 +249,7 @@ private:
|
||||
*/
|
||||
bool AddChunk(size_t capacity) {
|
||||
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))) {
|
||||
chunk->capacity = capacity;
|
||||
chunk->size = 0;
|
||||
@ -248,7 +261,7 @@ private:
|
||||
return false;
|
||||
}
|
||||
|
||||
static const int kDefaultChunkCapacity = 64 * 1024; //!< Default chunk capacity.
|
||||
static const int kDefaultChunkCapacity = CEREAL_RAPIDJSON_ALLOCATOR_DEFAULT_CHUNK_CAPACITY; //!< Default chunk capacity.
|
||||
|
||||
//! Chunk header for perpending to each chunk.
|
||||
/*! Chunks are stored as a singly linked list.
|
||||
|
78
include/cereal/external/rapidjson/cursorstreamwrapper.h
vendored
Normal file
78
include/cereal/external/rapidjson/cursorstreamwrapper.h
vendored
Normal file
@ -0,0 +1,78 @@
|
||||
// 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_
|
366
include/cereal/external/rapidjson/document.h
vendored
366
include/cereal/external/rapidjson/document.h
vendored
@ -1,5 +1,5 @@
|
||||
// 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
|
||||
@ -7,9 +7,9 @@
|
||||
//
|
||||
// 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
|
||||
// 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_DOCUMENT_H_
|
||||
@ -24,28 +24,26 @@
|
||||
#include "encodedstream.h"
|
||||
#include <new> // placement new
|
||||
#include <limits>
|
||||
|
||||
CEREAL_RAPIDJSON_DIAG_PUSH
|
||||
#ifdef _MSC_VER
|
||||
CEREAL_RAPIDJSON_DIAG_OFF(4127) // conditional expression is constant
|
||||
CEREAL_RAPIDJSON_DIAG_OFF(4244) // conversion from kXxxFlags to 'uint16_t', possible loss of data
|
||||
#ifdef __cpp_lib_three_way_comparison
|
||||
#include <compare>
|
||||
#endif
|
||||
|
||||
CEREAL_RAPIDJSON_DIAG_PUSH
|
||||
#ifdef __clang__
|
||||
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(4244) // conversion from kXxxFlags to 'uint16_t', possible loss of data
|
||||
#endif
|
||||
|
||||
#ifdef __GNUC__
|
||||
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__
|
||||
|
||||
#ifndef CEREAL_RAPIDJSON_NOMEMBERITERATORCLASS
|
||||
#include <iterator> // std::iterator, std::random_access_iterator_tag
|
||||
#include <iterator> // std::random_access_iterator_tag
|
||||
#endif
|
||||
|
||||
#if CEREAL_RAPIDJSON_HAS_CXX11_RVALUE_REFS
|
||||
@ -67,10 +65,16 @@ class GenericDocument;
|
||||
But a compiler (IBM XL C/C++ for AIX) have reported to have problem with that so it moved as a namespace scope struct.
|
||||
https://code.google.com/p/rapidjson/issues/detail?id=64
|
||||
*/
|
||||
template <typename Encoding, typename Allocator>
|
||||
struct GenericMember {
|
||||
template <typename Encoding, typename Allocator>
|
||||
struct GenericMember {
|
||||
GenericValue<Encoding, Allocator> name; //!< name of member (must be a string)
|
||||
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);
|
||||
}
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
@ -98,16 +102,13 @@ struct GenericMember {
|
||||
\see GenericMember, GenericValue::MemberIterator, GenericValue::ConstMemberIterator
|
||||
*/
|
||||
template <bool Const, typename Encoding, typename Allocator>
|
||||
class GenericMemberIterator
|
||||
: public std::iterator<std::random_access_iterator_tag
|
||||
, typename internal::MaybeAddConst<Const,GenericMember<Encoding,Allocator> >::Type> {
|
||||
class GenericMemberIterator {
|
||||
|
||||
friend class GenericValue<Encoding,Allocator>;
|
||||
template <bool, typename, typename> friend class GenericMemberIterator;
|
||||
|
||||
typedef GenericMember<Encoding,Allocator> PlainType;
|
||||
typedef typename internal::MaybeAddConst<Const,PlainType>::Type ValueType;
|
||||
typedef std::iterator<std::random_access_iterator_tag,ValueType> BaseType;
|
||||
|
||||
public:
|
||||
//! Iterator type itself
|
||||
@ -117,12 +118,21 @@ public:
|
||||
//! Non-constant iterator type
|
||||
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
|
||||
typedef typename BaseType::pointer Pointer;
|
||||
typedef pointer Pointer;
|
||||
//! Reference to (const) GenericMember
|
||||
typedef typename BaseType::reference Reference;
|
||||
typedef reference Reference;
|
||||
//! Signed integer type (e.g. \c ptrdiff_t)
|
||||
typedef typename BaseType::difference_type DifferenceType;
|
||||
typedef difference_type DifferenceType;
|
||||
|
||||
//! Default constructor (singular value)
|
||||
/*! Creates an iterator pointing to no element.
|
||||
@ -168,12 +178,16 @@ public:
|
||||
|
||||
//! @name relations
|
||||
//@{
|
||||
bool operator==(ConstIterator that) const { return ptr_ == that.ptr_; }
|
||||
bool operator!=(ConstIterator that) const { return ptr_ != that.ptr_; }
|
||||
bool operator<=(ConstIterator that) const { return ptr_ <= that.ptr_; }
|
||||
bool operator>=(ConstIterator that) const { return ptr_ >= that.ptr_; }
|
||||
bool operator< (ConstIterator 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_; }
|
||||
template <bool Const_> bool operator!=(const GenericMemberIterator<Const_, Encoding, Allocator>& that) const { return ptr_ != that.ptr_; }
|
||||
template <bool Const_> bool operator<=(const GenericMemberIterator<Const_, Encoding, Allocator>& that) const { return ptr_ <= that.ptr_; }
|
||||
template <bool Const_> bool operator>=(const GenericMemberIterator<Const_, Encoding, Allocator>& that) const { return ptr_ >= that.ptr_; }
|
||||
template <bool Const_> bool operator< (const GenericMemberIterator<Const_, Encoding, Allocator>& that) const { return ptr_ < that.ptr_; }
|
||||
template <bool Const_> bool operator> (const GenericMemberIterator<Const_, Encoding, Allocator>& 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
|
||||
@ -198,17 +212,17 @@ private:
|
||||
// class-based member iterator implementation disabled, use plain pointers
|
||||
|
||||
template <bool Const, typename Encoding, typename Allocator>
|
||||
struct GenericMemberIterator;
|
||||
class GenericMemberIterator;
|
||||
|
||||
//! non-const GenericMemberIterator
|
||||
template <typename Encoding, typename Allocator>
|
||||
struct GenericMemberIterator<false,Encoding,Allocator> {
|
||||
class GenericMemberIterator<false,Encoding,Allocator> {
|
||||
//! use plain pointer as iterator type
|
||||
typedef GenericMember<Encoding,Allocator>* Iterator;
|
||||
};
|
||||
//! const GenericMemberIterator
|
||||
template <typename Encoding, typename Allocator>
|
||||
struct GenericMemberIterator<true,Encoding,Allocator> {
|
||||
class GenericMemberIterator<true,Encoding,Allocator> {
|
||||
//! use plain const pointer as iterator type
|
||||
typedef const GenericMember<Encoding,Allocator>* Iterator;
|
||||
};
|
||||
@ -300,7 +314,7 @@ struct GenericStringRef {
|
||||
*/
|
||||
#endif
|
||||
explicit GenericStringRef(const CharType* str)
|
||||
: s(str), length(internal::StrLen(str)){ CEREAL_RAPIDJSON_ASSERT(s != 0); }
|
||||
: s(str), length(NotNullStrLen(str)) {}
|
||||
|
||||
//! Create constant string reference from pointer and length
|
||||
#ifndef __clang__ // -Wdocumentation
|
||||
@ -312,12 +326,10 @@ struct GenericStringRef {
|
||||
*/
|
||||
#endif
|
||||
GenericStringRef(const CharType* str, SizeType len)
|
||||
: s(str), length(len) { CEREAL_RAPIDJSON_ASSERT(s != 0); }
|
||||
: s(CEREAL_RAPIDJSON_LIKELY(str) ? str : emptyString), length(len) { CEREAL_RAPIDJSON_ASSERT(str != 0 || len == 0u); }
|
||||
|
||||
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
|
||||
operator const Ch *() const { return s; }
|
||||
|
||||
@ -325,11 +337,24 @@ struct GenericStringRef {
|
||||
const SizeType length; //!< length of the string (excluding the trailing NULL terminator)
|
||||
|
||||
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
|
||||
template<SizeType N>
|
||||
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 plain character pointer as a "string literal". This function
|
||||
can be used to avoid copying a character string to be referenced as a
|
||||
@ -344,7 +369,7 @@ private:
|
||||
*/
|
||||
template<typename CharType>
|
||||
inline GenericStringRef<CharType> StringRef(const CharType* str) {
|
||||
return GenericStringRef<CharType>(str, internal::StrLen(str));
|
||||
return GenericStringRef<CharType>(str);
|
||||
}
|
||||
|
||||
//! Mark a character pointer as constant string
|
||||
@ -410,7 +435,7 @@ namespace internal {
|
||||
template <typename ValueType, typename T>
|
||||
struct TypeHelper {};
|
||||
|
||||
template<typename ValueType>
|
||||
template<typename ValueType>
|
||||
struct TypeHelper<ValueType, bool> {
|
||||
static bool Is(const ValueType& v) { return v.IsBool(); }
|
||||
static bool Get(const ValueType& v) { return v.GetBool(); }
|
||||
@ -418,7 +443,7 @@ struct TypeHelper<ValueType, bool> {
|
||||
static ValueType& Set(ValueType& v, bool data, typename ValueType::AllocatorType&) { return v.SetBool(data); }
|
||||
};
|
||||
|
||||
template<typename ValueType>
|
||||
template<typename ValueType>
|
||||
struct TypeHelper<ValueType, int> {
|
||||
static bool Is(const ValueType& v) { return v.IsInt(); }
|
||||
static int Get(const ValueType& v) { return v.GetInt(); }
|
||||
@ -426,7 +451,7 @@ struct TypeHelper<ValueType, int> {
|
||||
static ValueType& Set(ValueType& v, int data, typename ValueType::AllocatorType&) { return v.SetInt(data); }
|
||||
};
|
||||
|
||||
template<typename ValueType>
|
||||
template<typename ValueType>
|
||||
struct TypeHelper<ValueType, unsigned> {
|
||||
static bool Is(const ValueType& v) { return v.IsUint(); }
|
||||
static unsigned Get(const ValueType& v) { return v.GetUint(); }
|
||||
@ -434,7 +459,27 @@ struct TypeHelper<ValueType, unsigned> {
|
||||
static ValueType& Set(ValueType& v, unsigned data, typename ValueType::AllocatorType&) { return v.SetUint(data); }
|
||||
};
|
||||
|
||||
template<typename ValueType>
|
||||
#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>
|
||||
struct TypeHelper<ValueType, int64_t> {
|
||||
static bool Is(const ValueType& v) { return v.IsInt64(); }
|
||||
static int64_t Get(const ValueType& v) { return v.GetInt64(); }
|
||||
@ -442,7 +487,7 @@ struct TypeHelper<ValueType, int64_t> {
|
||||
static ValueType& Set(ValueType& v, int64_t data, typename ValueType::AllocatorType&) { return v.SetInt64(data); }
|
||||
};
|
||||
|
||||
template<typename ValueType>
|
||||
template<typename ValueType>
|
||||
struct TypeHelper<ValueType, uint64_t> {
|
||||
static bool Is(const ValueType& v) { return v.IsUint64(); }
|
||||
static uint64_t Get(const ValueType& v) { return v.GetUint64(); }
|
||||
@ -450,7 +495,7 @@ struct TypeHelper<ValueType, uint64_t> {
|
||||
static ValueType& Set(ValueType& v, uint64_t data, typename ValueType::AllocatorType&) { return v.SetUint64(data); }
|
||||
};
|
||||
|
||||
template<typename ValueType>
|
||||
template<typename ValueType>
|
||||
struct TypeHelper<ValueType, double> {
|
||||
static bool Is(const ValueType& v) { return v.IsDouble(); }
|
||||
static double Get(const ValueType& v) { return v.GetDouble(); }
|
||||
@ -458,7 +503,7 @@ struct TypeHelper<ValueType, double> {
|
||||
static ValueType& Set(ValueType& v, double data, typename ValueType::AllocatorType&) { return v.SetDouble(data); }
|
||||
};
|
||||
|
||||
template<typename ValueType>
|
||||
template<typename ValueType>
|
||||
struct TypeHelper<ValueType, float> {
|
||||
static bool Is(const ValueType& v) { return v.IsFloat(); }
|
||||
static float Get(const ValueType& v) { return v.GetFloat(); }
|
||||
@ -466,7 +511,7 @@ struct TypeHelper<ValueType, float> {
|
||||
static ValueType& Set(ValueType& v, float data, typename ValueType::AllocatorType&) { return v.SetFloat(data); }
|
||||
};
|
||||
|
||||
template<typename ValueType>
|
||||
template<typename ValueType>
|
||||
struct TypeHelper<ValueType, const typename ValueType::Ch*> {
|
||||
typedef const typename ValueType::Ch* StringType;
|
||||
static bool Is(const ValueType& v) { return v.IsString(); }
|
||||
@ -476,7 +521,7 @@ struct TypeHelper<ValueType, const typename ValueType::Ch*> {
|
||||
};
|
||||
|
||||
#if CEREAL_RAPIDJSON_HAS_STDSTRING
|
||||
template<typename ValueType>
|
||||
template<typename ValueType>
|
||||
struct TypeHelper<ValueType, std::basic_string<typename ValueType::Ch> > {
|
||||
typedef std::basic_string<typename ValueType::Ch> StringType;
|
||||
static bool Is(const ValueType& v) { return v.IsString(); }
|
||||
@ -485,7 +530,7 @@ struct TypeHelper<ValueType, std::basic_string<typename ValueType::Ch> > {
|
||||
};
|
||||
#endif
|
||||
|
||||
template<typename ValueType>
|
||||
template<typename ValueType>
|
||||
struct TypeHelper<ValueType, typename ValueType::Array> {
|
||||
typedef typename ValueType::Array ArrayType;
|
||||
static bool Is(const ValueType& v) { return v.IsArray(); }
|
||||
@ -494,23 +539,23 @@ struct TypeHelper<ValueType, typename ValueType::Array> {
|
||||
static ValueType& Set(ValueType& v, ArrayType data, typename ValueType::AllocatorType&) { return v = data; }
|
||||
};
|
||||
|
||||
template<typename ValueType>
|
||||
template<typename ValueType>
|
||||
struct TypeHelper<ValueType, typename ValueType::ConstArray> {
|
||||
typedef typename ValueType::ConstArray ArrayType;
|
||||
static bool Is(const ValueType& v) { return v.IsArray(); }
|
||||
static ArrayType Get(const ValueType& v) { return v.GetArray(); }
|
||||
};
|
||||
|
||||
template<typename ValueType>
|
||||
template<typename ValueType>
|
||||
struct TypeHelper<ValueType, typename ValueType::Object> {
|
||||
typedef typename ValueType::Object ObjectType;
|
||||
static bool Is(const ValueType& v) { return v.IsObject(); }
|
||||
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, typename ValueType::AllocatorType&) { v = data; }
|
||||
static ValueType& Set(ValueType& v, ObjectType data, typename ValueType::AllocatorType&) { return v = data; }
|
||||
};
|
||||
|
||||
template<typename ValueType>
|
||||
template<typename ValueType>
|
||||
struct TypeHelper<ValueType, typename ValueType::ConstObject> {
|
||||
typedef typename ValueType::ConstObject ObjectType;
|
||||
static bool Is(const ValueType& v) { return v.IsObject(); }
|
||||
@ -536,7 +581,7 @@ template <bool, typename> class GenericObject;
|
||||
\tparam Encoding Encoding of the value. (Even non-string values need to have the same encoding in a document)
|
||||
\tparam Allocator Allocator type for allocating memory of object, array and string.
|
||||
*/
|
||||
template <typename Encoding, typename Allocator = MemoryPoolAllocator<> >
|
||||
template <typename Encoding, typename Allocator = MemoryPoolAllocator<> >
|
||||
class GenericValue {
|
||||
public:
|
||||
//! Name-value pair in an object.
|
||||
@ -590,11 +635,11 @@ public:
|
||||
\note Default content for number is zero.
|
||||
*/
|
||||
explicit GenericValue(Type type) CEREAL_RAPIDJSON_NOEXCEPT : data_() {
|
||||
static const uint16_t defaultFlags[7] = {
|
||||
static const uint16_t defaultFlags[] = {
|
||||
kNullFlag, kFalseFlag, kTrueFlag, kObjectFlag, kArrayFlag, kShortStringFlag,
|
||||
kNumberAnyFlag
|
||||
};
|
||||
CEREAL_RAPIDJSON_ASSERT(type <= kNumberType);
|
||||
CEREAL_RAPIDJSON_NOEXCEPT_ASSERT(type >= kNullType && type <= kNumberType);
|
||||
data_.f.flags = defaultFlags[type];
|
||||
|
||||
// Use ShortString to store empty string.
|
||||
@ -607,10 +652,50 @@ public:
|
||||
\tparam SourceAllocator allocator of \c rhs
|
||||
\param rhs Value to copy from (read-only)
|
||||
\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()
|
||||
*/
|
||||
template< typename SourceAllocator >
|
||||
GenericValue(const GenericValue<Encoding, SourceAllocator>& rhs, Allocator & allocator);
|
||||
template <typename SourceAllocator>
|
||||
GenericValue(const GenericValue<Encoding,SourceAllocator>& rhs, Allocator& allocator, bool copyConstStrings = false) {
|
||||
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.
|
||||
/*! \param b Boolean value
|
||||
@ -638,7 +723,7 @@ public:
|
||||
|
||||
//! Constructor for unsigned value.
|
||||
explicit GenericValue(unsigned u) CEREAL_RAPIDJSON_NOEXCEPT : data_() {
|
||||
data_.n.u64 = u;
|
||||
data_.n.u64 = u;
|
||||
data_.f.flags = (u & 0x80000000) ? kNumberUintFlag : (kNumberUintFlag | kIntFlag | kInt64Flag);
|
||||
}
|
||||
|
||||
@ -672,6 +757,9 @@ public:
|
||||
//! Constructor for double value.
|
||||
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)
|
||||
GenericValue(const Ch* s, SizeType length) CEREAL_RAPIDJSON_NOEXCEPT : data_() { SetStringRaw(StringRef(s, length)); }
|
||||
|
||||
@ -753,9 +841,10 @@ public:
|
||||
/*! \param rhs Source of the assignment. It will become a null value after assignment.
|
||||
*/
|
||||
GenericValue& operator=(GenericValue& rhs) CEREAL_RAPIDJSON_NOEXCEPT {
|
||||
CEREAL_RAPIDJSON_ASSERT(this != &rhs);
|
||||
this->~GenericValue();
|
||||
RawAssign(rhs);
|
||||
if (CEREAL_RAPIDJSON_LIKELY(this != &rhs)) {
|
||||
this->~GenericValue();
|
||||
RawAssign(rhs);
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
@ -800,12 +889,13 @@ public:
|
||||
\tparam SourceAllocator Allocator type of \c rhs
|
||||
\param rhs Value to copy from (read-only)
|
||||
\param allocator Allocator to use for copying
|
||||
\param copyConstStrings Force copying of constant strings (e.g. referencing an in-situ buffer)
|
||||
*/
|
||||
template <typename SourceAllocator>
|
||||
GenericValue& CopyFrom(const GenericValue<Encoding, SourceAllocator>& rhs, Allocator& allocator) {
|
||||
GenericValue& CopyFrom(const GenericValue<Encoding, SourceAllocator>& rhs, Allocator& allocator, bool copyConstStrings = false) {
|
||||
CEREAL_RAPIDJSON_ASSERT(static_cast<void*>(this) != static_cast<void const*>(&rhs));
|
||||
this->~GenericValue();
|
||||
new (this) GenericValue(rhs, allocator);
|
||||
new (this) GenericValue(rhs, allocator, copyConstStrings);
|
||||
return *this;
|
||||
}
|
||||
|
||||
@ -846,7 +936,7 @@ public:
|
||||
//! Equal-to operator
|
||||
/*!
|
||||
\note If an object contains duplicated named member, comparing equality with any object is always \c false.
|
||||
\note Linear time complexity (number of all values in the subtree and total lengths of all strings).
|
||||
\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).
|
||||
*/
|
||||
template <typename SourceAllocator>
|
||||
bool operator==(const GenericValue<Encoding, SourceAllocator>& rhs) const {
|
||||
@ -857,14 +947,14 @@ public:
|
||||
switch (GetType()) {
|
||||
case kObjectType: // Warning: O(n^2) inner-loop
|
||||
if (data_.o.size != rhs.data_.o.size)
|
||||
return false;
|
||||
return false;
|
||||
for (ConstMemberIterator lhsMemberItr = MemberBegin(); lhsMemberItr != MemberEnd(); ++lhsMemberItr) {
|
||||
typename RhsType::ConstMemberIterator rhsMemberItr = rhs.FindMember(lhsMemberItr->name);
|
||||
if (rhsMemberItr == rhs.MemberEnd() || lhsMemberItr->value != rhsMemberItr->value)
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
|
||||
|
||||
case kArrayType:
|
||||
if (data_.a.size != rhs.data_.a.size)
|
||||
return false;
|
||||
@ -955,14 +1045,14 @@ public:
|
||||
uint64_t u = GetUint64();
|
||||
volatile double d = static_cast<double>(u);
|
||||
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));
|
||||
}
|
||||
if (IsInt64()) {
|
||||
int64_t i = GetInt64();
|
||||
volatile double d = static_cast<double>(i);
|
||||
return (d >= static_cast<double>(std::numeric_limits<int64_t>::min()))
|
||||
&& (d < static_cast<double>(std::numeric_limits<int64_t>::max()))
|
||||
return (d >= static_cast<double>((std::numeric_limits<int64_t>::min)()))
|
||||
&& (d < static_cast<double>((std::numeric_limits<int64_t>::max)()))
|
||||
&& (i == static_cast<int64_t>(d));
|
||||
}
|
||||
return true; // double, int, uint are always lossless
|
||||
@ -979,8 +1069,8 @@ public:
|
||||
bool IsLosslessFloat() const {
|
||||
if (!IsNumber()) return false;
|
||||
double a = GetDouble();
|
||||
if (a < static_cast<double>(-std::numeric_limits<float>::max())
|
||||
|| 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)()))
|
||||
return false;
|
||||
double b = static_cast<double>(static_cast<float>(a));
|
||||
return a >= b && a <= b; // Prevent -Wfloat-equal
|
||||
@ -1015,6 +1105,9 @@ public:
|
||||
//! Get the number of members in the object.
|
||||
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.
|
||||
bool ObjectEmpty() const { CEREAL_RAPIDJSON_ASSERT(IsObject()); return data_.o.size == 0; }
|
||||
|
||||
@ -1083,6 +1176,21 @@ public:
|
||||
/*! \pre IsObject() == true */
|
||||
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.
|
||||
/*!
|
||||
\param name Member name to be searched.
|
||||
@ -1188,17 +1296,8 @@ public:
|
||||
CEREAL_RAPIDJSON_ASSERT(name.IsString());
|
||||
|
||||
ObjectData& o = data_.o;
|
||||
if (o.size >= o.capacity) {
|
||||
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))));
|
||||
}
|
||||
}
|
||||
if (o.size >= o.capacity)
|
||||
MemberReserve(o.capacity == 0 ? kDefaultObjectCapacity : (o.capacity + (o.capacity + 1) / 2), allocator);
|
||||
Member* members = GetMembersPointer();
|
||||
members[o.size].name.RawAssign(name);
|
||||
members[o.size].value.RawAssign(value);
|
||||
@ -1335,7 +1434,7 @@ public:
|
||||
\note Linear time complexity.
|
||||
*/
|
||||
void RemoveAllMembers() {
|
||||
CEREAL_RAPIDJSON_ASSERT(IsObject());
|
||||
CEREAL_RAPIDJSON_ASSERT(IsObject());
|
||||
for (MemberIterator m = MemberBegin(); m != MemberEnd(); ++m)
|
||||
m->~Member();
|
||||
data_.o.size = 0;
|
||||
@ -1425,7 +1524,7 @@ public:
|
||||
MemberIterator pos = MemberBegin() + (first - MemberBegin());
|
||||
for (MemberIterator itr = pos; itr != last; ++itr)
|
||||
itr->~Member();
|
||||
std::memmove(&*pos, &*last, static_cast<size_t>(MemberEnd() - last) * sizeof(Member));
|
||||
std::memmove(static_cast<void*>(&*pos), &*last, static_cast<size_t>(MemberEnd() - last) * sizeof(Member));
|
||||
data_.o.size -= static_cast<SizeType>(last - first);
|
||||
return pos;
|
||||
}
|
||||
@ -1481,7 +1580,7 @@ public:
|
||||
\note Linear time complexity.
|
||||
*/
|
||||
void Clear() {
|
||||
CEREAL_RAPIDJSON_ASSERT(IsArray());
|
||||
CEREAL_RAPIDJSON_ASSERT(IsArray());
|
||||
GenericValue* e = GetElementsPointer();
|
||||
for (GenericValue* v = e; v != e + data_.a.size; ++v)
|
||||
v->~GenericValue();
|
||||
@ -1628,8 +1727,8 @@ public:
|
||||
CEREAL_RAPIDJSON_ASSERT(last <= End());
|
||||
ValueIterator pos = Begin() + (first - Begin());
|
||||
for (ValueIterator itr = pos; itr != last; ++itr)
|
||||
itr->~GenericValue();
|
||||
std::memmove(pos, last, static_cast<size_t>(End() - last) * sizeof(GenericValue));
|
||||
itr->~GenericValue();
|
||||
std::memmove(static_cast<void*>(pos), last, static_cast<size_t>(End() - last) * sizeof(GenericValue));
|
||||
data_.a.size -= static_cast<SizeType>(last - first);
|
||||
return pos;
|
||||
}
|
||||
@ -1671,7 +1770,7 @@ public:
|
||||
GenericValue& SetInt64(int64_t i64) { this->~GenericValue(); new (this) GenericValue(i64); return *this; }
|
||||
GenericValue& SetUint64(uint64_t u64) { this->~GenericValue(); new (this) GenericValue(u64); return *this; }
|
||||
GenericValue& SetDouble(double d) { this->~GenericValue(); new (this) GenericValue(d); return *this; }
|
||||
GenericValue& SetFloat(float f) { this->~GenericValue(); new (this) GenericValue(f); return *this; }
|
||||
GenericValue& SetFloat(float f) { this->~GenericValue(); new (this) GenericValue(static_cast<double>(f)); return *this; }
|
||||
|
||||
//@}
|
||||
|
||||
@ -1687,7 +1786,7 @@ public:
|
||||
|
||||
//! Set this value as a string without copying source string.
|
||||
/*! This version has better performance with supplied length, and also support string containing null character.
|
||||
\param s source string pointer.
|
||||
\param s source string pointer.
|
||||
\param length The length of source string, excluding the trailing null terminator.
|
||||
\return The value itself for fluent API.
|
||||
\post IsString() == true && GetString() == s && GetStringLength() == length
|
||||
@ -1704,21 +1803,29 @@ public:
|
||||
|
||||
//! Set this value as a string by copying from source string.
|
||||
/*! This version has better performance with supplied length, and also support string containing null character.
|
||||
\param s source string.
|
||||
\param s source string.
|
||||
\param length The length of source string, excluding the trailing null terminator.
|
||||
\param allocator Allocator for allocating copied buffer. Commonly use GenericDocument::GetAllocator().
|
||||
\return The value itself for fluent API.
|
||||
\post IsString() == true && GetString() != s && strcmp(GetString(),s) == 0 && GetStringLength() == length
|
||||
*/
|
||||
GenericValue& SetString(const Ch* s, SizeType length, Allocator& allocator) { this->~GenericValue(); SetStringRaw(StringRef(s, length), allocator); return *this; }
|
||||
GenericValue& SetString(const Ch* s, SizeType length, Allocator& allocator) { return SetString(StringRef(s, length), allocator); }
|
||||
|
||||
//! Set this value as a string by copying from source string.
|
||||
/*! \param s source string.
|
||||
/*! \param s source string.
|
||||
\param allocator Allocator for allocating copied buffer. Commonly use GenericDocument::GetAllocator().
|
||||
\return The value itself for fluent API.
|
||||
\post IsString() == true && GetString() != s && strcmp(GetString(),s) == 0 && GetStringLength() == length
|
||||
*/
|
||||
GenericValue& SetString(const Ch* s, Allocator& allocator) { return SetString(s, internal::StrLen(s), allocator); }
|
||||
GenericValue& SetString(const Ch* s, Allocator& allocator) { return SetString(StringRef(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
|
||||
//! Set this value as a string by copying from source string.
|
||||
@ -1728,7 +1835,7 @@ public:
|
||||
\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.
|
||||
*/
|
||||
GenericValue& SetString(const std::basic_string<Ch>& s, Allocator& allocator) { return SetString(s.data(), SizeType(s.size()), allocator); }
|
||||
GenericValue& SetString(const std::basic_string<Ch>& s, Allocator& allocator) { return SetString(StringRef(s), allocator); }
|
||||
#endif
|
||||
|
||||
//@}
|
||||
@ -1790,10 +1897,10 @@ public:
|
||||
if (CEREAL_RAPIDJSON_UNLIKELY(!v->Accept(handler)))
|
||||
return false;
|
||||
return handler.EndArray(data_.a.size);
|
||||
|
||||
|
||||
case kStringType:
|
||||
return handler.String(GetString(), GetStringLength(), (data_.f.flags & kCopyFlag) != 0);
|
||||
|
||||
|
||||
default:
|
||||
CEREAL_RAPIDJSON_ASSERT(GetType() == kNumberType);
|
||||
if (IsDouble()) return handler.Double(data_.n.d);
|
||||
@ -1936,7 +2043,7 @@ private:
|
||||
if (count) {
|
||||
GenericValue* e = static_cast<GenericValue*>(allocator.Malloc(count * sizeof(GenericValue)));
|
||||
SetElementsPointer(e);
|
||||
std::memcpy(e, values, count * sizeof(GenericValue));
|
||||
std::memcpy(static_cast<void*>(e), values, count * sizeof(GenericValue));
|
||||
}
|
||||
else
|
||||
SetElementsPointer(0);
|
||||
@ -1949,7 +2056,7 @@ private:
|
||||
if (count) {
|
||||
Member* m = static_cast<Member*>(allocator.Malloc(count * sizeof(Member)));
|
||||
SetMembersPointer(m);
|
||||
std::memcpy(m, members, count * sizeof(Member));
|
||||
std::memcpy(static_cast<void*>(m), members, count * sizeof(Member));
|
||||
}
|
||||
else
|
||||
SetMembersPointer(0);
|
||||
@ -2010,7 +2117,7 @@ private:
|
||||
typedef GenericValue<UTF8<> > Value;
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// GenericDocument
|
||||
// GenericDocument
|
||||
|
||||
//! A document for parsing JSON text as DOM.
|
||||
/*!
|
||||
@ -2038,20 +2145,20 @@ public:
|
||||
GenericValue<Encoding, Allocator>(type), allocator_(allocator), ownAllocator_(0), stack_(stackAllocator, stackCapacity), parseResult_()
|
||||
{
|
||||
if (!allocator_)
|
||||
ownAllocator_ = allocator_ = CEREAL_RAPIDJSON_NEW(Allocator());
|
||||
ownAllocator_ = allocator_ = CEREAL_RAPIDJSON_NEW(Allocator)();
|
||||
}
|
||||
|
||||
//! Constructor
|
||||
/*! Creates an empty document which type is Null.
|
||||
/*! Creates an empty document which type is Null.
|
||||
\param allocator Optional allocator for allocating memory.
|
||||
\param stackCapacity Optional initial capacity of stack in bytes.
|
||||
\param stackAllocator Optional allocator for allocating memory for stack.
|
||||
*/
|
||||
GenericDocument(Allocator* allocator = 0, size_t stackCapacity = kDefaultStackCapacity, StackAllocator* stackAllocator = 0) :
|
||||
GenericDocument(Allocator* allocator = 0, size_t stackCapacity = kDefaultStackCapacity, StackAllocator* stackAllocator = 0) :
|
||||
allocator_(allocator), ownAllocator_(0), stack_(stackAllocator, stackCapacity), parseResult_()
|
||||
{
|
||||
if (!allocator_)
|
||||
ownAllocator_ = allocator_ = CEREAL_RAPIDJSON_NEW(Allocator());
|
||||
ownAllocator_ = allocator_ = CEREAL_RAPIDJSON_NEW(Allocator)();
|
||||
}
|
||||
|
||||
#if CEREAL_RAPIDJSON_HAS_CXX11_RVALUE_REFS
|
||||
@ -2112,6 +2219,10 @@ public:
|
||||
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
|
||||
/*!
|
||||
Helper function to enable support for common swap implementation pattern based on \c std::swap:
|
||||
@ -2243,7 +2354,7 @@ public:
|
||||
template <unsigned parseFlags, typename SourceEncoding>
|
||||
GenericDocument& Parse(const typename SourceEncoding::Ch* str, size_t length) {
|
||||
CEREAL_RAPIDJSON_ASSERT(!(parseFlags & kParseInsituFlag));
|
||||
MemoryStream ms(static_cast<const char*>(str), length * sizeof(typename SourceEncoding::Ch));
|
||||
MemoryStream ms(reinterpret_cast<const char*>(str), length * sizeof(typename SourceEncoding::Ch));
|
||||
EncodedInputStream<SourceEncoding, MemoryStream> is(ms);
|
||||
ParseStream<parseFlags, SourceEncoding>(is);
|
||||
return *this;
|
||||
@ -2253,7 +2364,7 @@ public:
|
||||
GenericDocument& Parse(const Ch* str, size_t length) {
|
||||
return Parse<parseFlags, Encoding>(str, length);
|
||||
}
|
||||
|
||||
|
||||
GenericDocument& Parse(const Ch* str, size_t length) {
|
||||
return Parse<kParseDefaultFlags>(str, length);
|
||||
}
|
||||
@ -2273,14 +2384,14 @@ public:
|
||||
GenericDocument& Parse(const std::basic_string<Ch>& str) {
|
||||
return Parse<kParseDefaultFlags>(str);
|
||||
}
|
||||
#endif // CEREAL_RAPIDJSON_HAS_STDSTRING
|
||||
#endif // CEREAL_RAPIDJSON_HAS_STDSTRING
|
||||
|
||||
//!@}
|
||||
|
||||
//!@name Handling parse errors
|
||||
//!@{
|
||||
|
||||
//! Whether a parse error has occured in the last parsing.
|
||||
//! Whether a parse error has occurred in the last parsing.
|
||||
bool HasParseError() const { return parseResult_.IsError(); }
|
||||
|
||||
//! Get the \ref ParseErrorCode of last parsing.
|
||||
@ -2338,16 +2449,16 @@ public:
|
||||
bool Uint64(uint64_t i) { new (stack_.template Push<ValueType>()) ValueType(i); return true; }
|
||||
bool Double(double d) { new (stack_.template Push<ValueType>()) ValueType(d); return true; }
|
||||
|
||||
bool RawNumber(const Ch* str, SizeType length, bool copy) {
|
||||
if (copy)
|
||||
bool RawNumber(const Ch* str, SizeType length, bool copy) {
|
||||
if (copy)
|
||||
new (stack_.template Push<ValueType>()) ValueType(str, length, GetAllocator());
|
||||
else
|
||||
new (stack_.template Push<ValueType>()) ValueType(str, length);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool String(const Ch* str, SizeType length, bool copy) {
|
||||
if (copy)
|
||||
bool String(const Ch* str, SizeType length, bool copy) {
|
||||
if (copy)
|
||||
new (stack_.template Push<ValueType>()) ValueType(str, length, GetAllocator());
|
||||
else
|
||||
new (stack_.template Push<ValueType>()) ValueType(str, length);
|
||||
@ -2355,7 +2466,7 @@ public:
|
||||
}
|
||||
|
||||
bool StartObject() { new (stack_.template Push<ValueType>()) ValueType(kObjectType); return true; }
|
||||
|
||||
|
||||
bool Key(const Ch* str, SizeType length, bool copy) { return String(str, length, copy); }
|
||||
|
||||
bool EndObject(SizeType memberCount) {
|
||||
@ -2365,7 +2476,7 @@ public:
|
||||
}
|
||||
|
||||
bool StartArray() { new (stack_.template Push<ValueType>()) ValueType(kArrayType); return true; }
|
||||
|
||||
|
||||
bool EndArray(SizeType elementCount) {
|
||||
ValueType* elements = stack_.template Pop<ValueType>(elementCount);
|
||||
stack_.template Top<ValueType>()->SetArrayRaw(elements, elementCount, GetAllocator());
|
||||
@ -2401,35 +2512,6 @@ private:
|
||||
//! GenericDocument with UTF8 encoding
|
||||
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.
|
||||
/*!
|
||||
Instance of this helper class is obtained by \c GenericValue::GetArray().
|
||||
@ -2510,6 +2592,7 @@ public:
|
||||
~GenericObject() {}
|
||||
|
||||
SizeType MemberCount() const { return value_.MemberCount(); }
|
||||
SizeType MemberCapacity() const { return value_.MemberCapacity(); }
|
||||
bool ObjectEmpty() const { return value_.ObjectEmpty(); }
|
||||
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]; }
|
||||
@ -2518,6 +2601,7 @@ public:
|
||||
#endif
|
||||
MemberIterator MemberBegin() const { return value_.MemberBegin(); }
|
||||
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); }
|
||||
#if CEREAL_RAPIDJSON_HAS_STDSTRING
|
||||
bool HasMember(const std::basic_string<Ch>& name) const { return value_.HasMember(name); }
|
||||
@ -2543,7 +2627,7 @@ public:
|
||||
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; }
|
||||
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() { return value_.RemoveAllMembers(); }
|
||||
void RemoveAllMembers() { value_.RemoveAllMembers(); }
|
||||
bool RemoveMember(const Ch* name) const { return value_.RemoveMember(name); }
|
||||
#if CEREAL_RAPIDJSON_HAS_STDSTRING
|
||||
bool RemoveMember(const std::basic_string<Ch>& name) const { return value_.RemoveMember(name); }
|
||||
|
@ -200,7 +200,7 @@ private:
|
||||
// xx xx xx xx UTF-8
|
||||
|
||||
if (!hasBOM_) {
|
||||
unsigned pattern = (c[0] ? 1 : 0) | (c[1] ? 2 : 0) | (c[2] ? 4 : 0) | (c[3] ? 8 : 0);
|
||||
int pattern = (c[0] ? 1 : 0) | (c[1] ? 2 : 0) | (c[2] ? 4 : 0) | (c[3] ? 8 : 0);
|
||||
switch (pattern) {
|
||||
case 0x08: type_ = kUTF32BE; break;
|
||||
case 0x0A: type_ = kUTF16BE; break;
|
||||
|
86
include/cereal/external/rapidjson/encodings.h
vendored
86
include/cereal/external/rapidjson/encodings.h
vendored
@ -17,7 +17,7 @@
|
||||
|
||||
#include "rapidjson.h"
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#if defined(_MSC_VER) && !defined(__clang__)
|
||||
CEREAL_RAPIDJSON_DIAG_PUSH
|
||||
CEREAL_RAPIDJSON_DIAG_OFF(4244) // conversion from 'type1' to 'type2', possible loss of data
|
||||
CEREAL_RAPIDJSON_DIAG_OFF(4702) // unreachable code
|
||||
@ -144,9 +144,9 @@ struct UTF8 {
|
||||
|
||||
template <typename InputStream>
|
||||
static bool Decode(InputStream& is, unsigned* codepoint) {
|
||||
#define COPY() c = is.Take(); *codepoint = (*codepoint << 6) | (static_cast<unsigned char>(c) & 0x3Fu)
|
||||
#define TRANS(mask) result &= ((GetRange(static_cast<unsigned char>(c)) & mask) != 0)
|
||||
#define TAIL() COPY(); TRANS(0x70)
|
||||
#define CEREAL_RAPIDJSON_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 CEREAL_RAPIDJSON_TAIL() CEREAL_RAPIDJSON_COPY(); CEREAL_RAPIDJSON_TRANS(0x70)
|
||||
typename InputStream::Ch c = is.Take();
|
||||
if (!(c & 0x80)) {
|
||||
*codepoint = static_cast<unsigned char>(c);
|
||||
@ -157,48 +157,48 @@ struct UTF8 {
|
||||
if (type >= 32) {
|
||||
*codepoint = 0;
|
||||
} else {
|
||||
*codepoint = (0xFF >> type) & static_cast<unsigned char>(c);
|
||||
*codepoint = (0xFFu >> type) & static_cast<unsigned char>(c);
|
||||
}
|
||||
bool result = true;
|
||||
switch (type) {
|
||||
case 2: TAIL(); return result;
|
||||
case 3: TAIL(); TAIL(); return result;
|
||||
case 4: COPY(); TRANS(0x50); TAIL(); return result;
|
||||
case 5: COPY(); TRANS(0x10); TAIL(); TAIL(); return result;
|
||||
case 6: TAIL(); TAIL(); TAIL(); return result;
|
||||
case 10: COPY(); TRANS(0x20); TAIL(); return result;
|
||||
case 11: COPY(); TRANS(0x60); TAIL(); TAIL(); return result;
|
||||
case 2: CEREAL_RAPIDJSON_TAIL(); return result;
|
||||
case 3: CEREAL_RAPIDJSON_TAIL(); CEREAL_RAPIDJSON_TAIL(); return result;
|
||||
case 4: CEREAL_RAPIDJSON_COPY(); CEREAL_RAPIDJSON_TRANS(0x50); CEREAL_RAPIDJSON_TAIL(); return result;
|
||||
case 5: CEREAL_RAPIDJSON_COPY(); CEREAL_RAPIDJSON_TRANS(0x10); CEREAL_RAPIDJSON_TAIL(); CEREAL_RAPIDJSON_TAIL(); return result;
|
||||
case 6: CEREAL_RAPIDJSON_TAIL(); CEREAL_RAPIDJSON_TAIL(); CEREAL_RAPIDJSON_TAIL(); return result;
|
||||
case 10: CEREAL_RAPIDJSON_COPY(); CEREAL_RAPIDJSON_TRANS(0x20); CEREAL_RAPIDJSON_TAIL(); return result;
|
||||
case 11: CEREAL_RAPIDJSON_COPY(); CEREAL_RAPIDJSON_TRANS(0x60); CEREAL_RAPIDJSON_TAIL(); CEREAL_RAPIDJSON_TAIL(); return result;
|
||||
default: return false;
|
||||
}
|
||||
#undef COPY
|
||||
#undef TRANS
|
||||
#undef TAIL
|
||||
#undef CEREAL_RAPIDJSON_COPY
|
||||
#undef CEREAL_RAPIDJSON_TRANS
|
||||
#undef CEREAL_RAPIDJSON_TAIL
|
||||
}
|
||||
|
||||
template <typename InputStream, typename OutputStream>
|
||||
static bool Validate(InputStream& is, OutputStream& os) {
|
||||
#define COPY() os.Put(c = is.Take())
|
||||
#define TRANS(mask) result &= ((GetRange(static_cast<unsigned char>(c)) & mask) != 0)
|
||||
#define TAIL() COPY(); TRANS(0x70)
|
||||
#define CEREAL_RAPIDJSON_COPY() os.Put(c = is.Take())
|
||||
#define CEREAL_RAPIDJSON_TRANS(mask) result &= ((GetRange(static_cast<unsigned char>(c)) & mask) != 0)
|
||||
#define CEREAL_RAPIDJSON_TAIL() CEREAL_RAPIDJSON_COPY(); CEREAL_RAPIDJSON_TRANS(0x70)
|
||||
Ch c;
|
||||
COPY();
|
||||
CEREAL_RAPIDJSON_COPY();
|
||||
if (!(c & 0x80))
|
||||
return true;
|
||||
|
||||
bool result = true;
|
||||
switch (GetRange(static_cast<unsigned char>(c))) {
|
||||
case 2: TAIL(); return result;
|
||||
case 3: TAIL(); TAIL(); return result;
|
||||
case 4: COPY(); TRANS(0x50); TAIL(); return result;
|
||||
case 5: COPY(); TRANS(0x10); TAIL(); TAIL(); return result;
|
||||
case 6: TAIL(); TAIL(); TAIL(); return result;
|
||||
case 10: COPY(); TRANS(0x20); TAIL(); return result;
|
||||
case 11: COPY(); TRANS(0x60); TAIL(); TAIL(); return result;
|
||||
case 2: CEREAL_RAPIDJSON_TAIL(); return result;
|
||||
case 3: CEREAL_RAPIDJSON_TAIL(); CEREAL_RAPIDJSON_TAIL(); return result;
|
||||
case 4: CEREAL_RAPIDJSON_COPY(); CEREAL_RAPIDJSON_TRANS(0x50); CEREAL_RAPIDJSON_TAIL(); return result;
|
||||
case 5: CEREAL_RAPIDJSON_COPY(); CEREAL_RAPIDJSON_TRANS(0x10); CEREAL_RAPIDJSON_TAIL(); CEREAL_RAPIDJSON_TAIL(); return result;
|
||||
case 6: CEREAL_RAPIDJSON_TAIL(); CEREAL_RAPIDJSON_TAIL(); CEREAL_RAPIDJSON_TAIL(); return result;
|
||||
case 10: CEREAL_RAPIDJSON_COPY(); CEREAL_RAPIDJSON_TRANS(0x20); CEREAL_RAPIDJSON_TAIL(); return result;
|
||||
case 11: CEREAL_RAPIDJSON_COPY(); CEREAL_RAPIDJSON_TRANS(0x60); CEREAL_RAPIDJSON_TAIL(); CEREAL_RAPIDJSON_TAIL(); return result;
|
||||
default: return false;
|
||||
}
|
||||
#undef COPY
|
||||
#undef TRANS
|
||||
#undef TAIL
|
||||
#undef CEREAL_RAPIDJSON_COPY
|
||||
#undef CEREAL_RAPIDJSON_TRANS
|
||||
#undef CEREAL_RAPIDJSON_TAIL
|
||||
}
|
||||
|
||||
static unsigned char GetRange(unsigned char c) {
|
||||
@ -283,7 +283,7 @@ struct UTF16 {
|
||||
CEREAL_RAPIDJSON_ASSERT(codepoint <= 0x10FFFF);
|
||||
unsigned v = codepoint - 0x10000;
|
||||
os.Put(static_cast<typename OutputStream::Ch>((v >> 10) | 0xD800));
|
||||
os.Put((v & 0x3FF) | 0xDC00);
|
||||
os.Put(static_cast<typename OutputStream::Ch>((v & 0x3FF) | 0xDC00));
|
||||
}
|
||||
}
|
||||
|
||||
@ -299,7 +299,7 @@ struct UTF16 {
|
||||
CEREAL_RAPIDJSON_ASSERT(codepoint <= 0x10FFFF);
|
||||
unsigned v = codepoint - 0x10000;
|
||||
PutUnsafe(os, static_cast<typename OutputStream::Ch>((v >> 10) | 0xD800));
|
||||
PutUnsafe(os, (v & 0x3FF) | 0xDC00);
|
||||
PutUnsafe(os, static_cast<typename OutputStream::Ch>((v & 0x3FF) | 0xDC00));
|
||||
}
|
||||
}
|
||||
|
||||
@ -384,7 +384,7 @@ struct UTF16BE : UTF16<CharType> {
|
||||
static CharType Take(InputByteStream& is) {
|
||||
CEREAL_RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1);
|
||||
unsigned c = static_cast<unsigned>(static_cast<uint8_t>(is.Take())) << 8;
|
||||
c |= static_cast<uint8_t>(is.Take());
|
||||
c |= static_cast<unsigned>(static_cast<uint8_t>(is.Take()));
|
||||
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
|
||||
|
||||
template<typename OutputStream>
|
||||
CEREAL_RAPIDJSON_FORCEINLINE static void Encode(OutputStream& os, unsigned codepoint) {
|
||||
static CEREAL_RAPIDJSON_FORCEINLINE void Encode(OutputStream& os, unsigned codepoint) {
|
||||
typedef void (*EncodeFunc)(OutputStream&, unsigned);
|
||||
static const EncodeFunc f[] = { CEREAL_RAPIDJSON_ENCODINGS_FUNC(Encode) };
|
||||
(*f[os.GetType()])(os, codepoint);
|
||||
}
|
||||
|
||||
template<typename OutputStream>
|
||||
CEREAL_RAPIDJSON_FORCEINLINE static void EncodeUnsafe(OutputStream& os, unsigned codepoint) {
|
||||
static CEREAL_RAPIDJSON_FORCEINLINE void EncodeUnsafe(OutputStream& os, unsigned codepoint) {
|
||||
typedef void (*EncodeFunc)(OutputStream&, unsigned);
|
||||
static const EncodeFunc f[] = { CEREAL_RAPIDJSON_ENCODINGS_FUNC(EncodeUnsafe) };
|
||||
(*f[os.GetType()])(os, codepoint);
|
||||
}
|
||||
|
||||
template <typename InputStream>
|
||||
CEREAL_RAPIDJSON_FORCEINLINE static bool Decode(InputStream& is, unsigned* codepoint) {
|
||||
static CEREAL_RAPIDJSON_FORCEINLINE bool Decode(InputStream& is, unsigned* codepoint) {
|
||||
typedef bool (*DecodeFunc)(InputStream&, unsigned*);
|
||||
static const DecodeFunc f[] = { CEREAL_RAPIDJSON_ENCODINGS_FUNC(Decode) };
|
||||
return (*f[is.GetType()])(is, codepoint);
|
||||
}
|
||||
|
||||
template <typename InputStream, typename OutputStream>
|
||||
CEREAL_RAPIDJSON_FORCEINLINE static bool Validate(InputStream& is, OutputStream& os) {
|
||||
static CEREAL_RAPIDJSON_FORCEINLINE bool Validate(InputStream& is, OutputStream& os) {
|
||||
typedef bool (*ValidateFunc)(InputStream&, OutputStream&);
|
||||
static const ValidateFunc f[] = { CEREAL_RAPIDJSON_ENCODINGS_FUNC(Validate) };
|
||||
return (*f[is.GetType()])(is, os);
|
||||
@ -658,7 +658,7 @@ template<typename SourceEncoding, typename TargetEncoding>
|
||||
struct Transcoder {
|
||||
//! Take one Unicode codepoint from source encoding, convert it to target encoding and put it to the output stream.
|
||||
template<typename InputStream, typename OutputStream>
|
||||
CEREAL_RAPIDJSON_FORCEINLINE static bool Transcode(InputStream& is, OutputStream& os) {
|
||||
static CEREAL_RAPIDJSON_FORCEINLINE bool Transcode(InputStream& is, OutputStream& os) {
|
||||
unsigned codepoint;
|
||||
if (!SourceEncoding::Decode(is, &codepoint))
|
||||
return false;
|
||||
@ -667,7 +667,7 @@ struct Transcoder {
|
||||
}
|
||||
|
||||
template<typename InputStream, typename OutputStream>
|
||||
CEREAL_RAPIDJSON_FORCEINLINE static bool TranscodeUnsafe(InputStream& is, OutputStream& os) {
|
||||
static CEREAL_RAPIDJSON_FORCEINLINE bool TranscodeUnsafe(InputStream& is, OutputStream& os) {
|
||||
unsigned codepoint;
|
||||
if (!SourceEncoding::Decode(is, &codepoint))
|
||||
return false;
|
||||
@ -677,7 +677,7 @@ struct Transcoder {
|
||||
|
||||
//! Validate one Unicode codepoint from an encoded stream.
|
||||
template<typename InputStream, typename OutputStream>
|
||||
CEREAL_RAPIDJSON_FORCEINLINE static bool Validate(InputStream& is, OutputStream& os) {
|
||||
static CEREAL_RAPIDJSON_FORCEINLINE bool Validate(InputStream& is, OutputStream& os) {
|
||||
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>
|
||||
struct Transcoder<Encoding, Encoding> {
|
||||
template<typename InputStream, typename OutputStream>
|
||||
CEREAL_RAPIDJSON_FORCEINLINE static bool Transcode(InputStream& is, OutputStream& os) {
|
||||
static CEREAL_RAPIDJSON_FORCEINLINE bool Transcode(InputStream& is, OutputStream& os) {
|
||||
os.Put(is.Take()); // Just copy one code unit. This semantic is different from primary template class.
|
||||
return true;
|
||||
}
|
||||
|
||||
template<typename InputStream, typename OutputStream>
|
||||
CEREAL_RAPIDJSON_FORCEINLINE static bool TranscodeUnsafe(InputStream& is, OutputStream& os) {
|
||||
static CEREAL_RAPIDJSON_FORCEINLINE bool TranscodeUnsafe(InputStream& is, OutputStream& os) {
|
||||
PutUnsafe(os, is.Take()); // Just copy one code unit. This semantic is different from primary template class.
|
||||
return true;
|
||||
}
|
||||
|
||||
template<typename InputStream, typename OutputStream>
|
||||
CEREAL_RAPIDJSON_FORCEINLINE static bool Validate(InputStream& is, OutputStream& os) {
|
||||
static CEREAL_RAPIDJSON_FORCEINLINE bool Validate(InputStream& is, OutputStream& os) {
|
||||
return Encoding::Validate(is, os); // source/target encoding are the same
|
||||
}
|
||||
};
|
||||
|
||||
CEREAL_RAPIDJSON_NAMESPACE_END
|
||||
|
||||
#if defined(__GNUC__) || defined(_MSC_VER)
|
||||
#if defined(__GNUC__) || (defined(_MSC_VER) && !defined(__clang__))
|
||||
CEREAL_RAPIDJSON_DIAG_POP
|
||||
#endif
|
||||
|
||||
|
10
include/cereal/external/rapidjson/error/error.h
vendored
10
include/cereal/external/rapidjson/error/error.h
vendored
@ -104,6 +104,8 @@ enum ParseErrorCode {
|
||||
\see GenericReader::Parse, GenericDocument::Parse
|
||||
*/
|
||||
struct ParseResult {
|
||||
//!! Unspecified boolean type
|
||||
typedef bool (ParseResult::*BooleanType)() const;
|
||||
public:
|
||||
//! Default constructor, no error.
|
||||
ParseResult() : code_(kParseErrorNone), offset_(0) {}
|
||||
@ -115,8 +117,8 @@ public:
|
||||
//! Get the error offset, if \ref IsError(), 0 otherwise.
|
||||
size_t Offset() const { return offset_; }
|
||||
|
||||
//! Conversion to \c bool, returns \c true, iff !\ref IsError().
|
||||
operator bool() const { return !IsError(); }
|
||||
//! Explicit conversion to \c bool, returns \c true, iff !\ref IsError().
|
||||
operator BooleanType() const { return !IsError() ? &ParseResult::IsError : NULL; }
|
||||
//! Whether the result is an error.
|
||||
bool IsError() const { return code_ != kParseErrorNone; }
|
||||
|
||||
@ -124,6 +126,10 @@ public:
|
||||
bool operator==(ParseErrorCode code) const { return code_ == 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.
|
||||
void Clear() { Set(kParseErrorNone); }
|
||||
//! Update error code and offset.
|
||||
|
@ -59,7 +59,7 @@ public:
|
||||
|
||||
// For encoding detection only.
|
||||
const Ch* Peek4() const {
|
||||
return (current_ + 4 <= bufferLast_) ? current_ : 0;
|
||||
return (current_ + 4 - !eof_ <= bufferLast_) ? current_ : 0;
|
||||
}
|
||||
|
||||
private:
|
||||
@ -68,7 +68,7 @@ private:
|
||||
++current_;
|
||||
else if (!eof_) {
|
||||
count_ += readCount_;
|
||||
readCount_ = fread(buffer_, 1, bufferSize_, fp_);
|
||||
readCount_ = std::fread(buffer_, 1, bufferSize_, fp_);
|
||||
bufferLast_ = buffer_ + readCount_ - 1;
|
||||
current_ = buffer_;
|
||||
|
||||
|
@ -25,7 +25,7 @@ CEREAL_RAPIDJSON_DIAG_OFF(unreachable-code)
|
||||
|
||||
CEREAL_RAPIDJSON_NAMESPACE_BEGIN
|
||||
|
||||
//! Wrapper of C file stream for input using fread().
|
||||
//! Wrapper of C file stream for output using fwrite().
|
||||
/*!
|
||||
\note implements Stream concept
|
||||
*/
|
||||
@ -62,7 +62,7 @@ public:
|
||||
|
||||
void Flush() {
|
||||
if (current_ != buffer_) {
|
||||
size_t result = fwrite(buffer_, 1, static_cast<size_t>(current_ - buffer_), fp_);
|
||||
size_t result = std::fwrite(buffer_, 1, static_cast<size_t>(current_ - buffer_), fp_);
|
||||
if (result < static_cast<size_t>(current_ - buffer_)) {
|
||||
// failure deliberately ignored at this time
|
||||
// added to avoid warn_unused_result build errors
|
||||
|
@ -17,7 +17,7 @@
|
||||
|
||||
#include "../rapidjson.h"
|
||||
|
||||
#if defined(_MSC_VER) && defined(_M_AMD64)
|
||||
#if defined(_MSC_VER) && !__INTEL_COMPILER && defined(_M_AMD64)
|
||||
#include <intrin.h> // for _umul128
|
||||
#pragma intrinsic(_umul128)
|
||||
#endif
|
||||
@ -133,7 +133,7 @@ public:
|
||||
CEREAL_RAPIDJSON_ASSERT(count_ + offset <= kCapacity);
|
||||
|
||||
if (interShift == 0) {
|
||||
std::memmove(&digits_[count_ - 1 + offset], &digits_[count_ - 1], count_ * sizeof(Type));
|
||||
std::memmove(digits_ + offset, digits_, count_ * sizeof(Type));
|
||||
count_ += offset;
|
||||
}
|
||||
else {
|
||||
|
@ -1,5 +1,5 @@
|
||||
// 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
|
||||
@ -7,9 +7,9 @@
|
||||
//
|
||||
// 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
|
||||
// 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.
|
||||
|
||||
// This is a C++ header-only implementation of Grisu2 algorithm from the publication:
|
||||
@ -20,8 +20,9 @@
|
||||
#define CEREAL_RAPIDJSON_DIYFP_H_
|
||||
|
||||
#include "../rapidjson.h"
|
||||
#include <limits>
|
||||
|
||||
#if defined(_MSC_VER) && defined(_M_AMD64)
|
||||
#if defined(_MSC_VER) && defined(_M_AMD64) && !defined(__INTEL_COMPILER)
|
||||
#include <intrin.h>
|
||||
#pragma intrinsic(_BitScanReverse64)
|
||||
#pragma intrinsic(_umul128)
|
||||
@ -56,7 +57,7 @@ struct DiyFp {
|
||||
if (biased_e != 0) {
|
||||
f = significand + kDpHiddenBit;
|
||||
e = biased_e - kDpExponentBias;
|
||||
}
|
||||
}
|
||||
else {
|
||||
f = significand;
|
||||
e = kDpMinExponent + 1;
|
||||
@ -99,6 +100,7 @@ struct DiyFp {
|
||||
}
|
||||
|
||||
DiyFp Normalize() const {
|
||||
CEREAL_RAPIDJSON_ASSERT(f != 0); // https://stackoverflow.com/a/26809183/291737
|
||||
#if defined(_MSC_VER) && defined(_M_AMD64)
|
||||
unsigned long index;
|
||||
_BitScanReverse64(&index, f);
|
||||
@ -141,7 +143,16 @@ struct DiyFp {
|
||||
double d;
|
||||
uint64_t u64;
|
||||
}u;
|
||||
const uint64_t be = (e == kDpDenormalExponent && (f & kDpHiddenBit) == 0) ? 0 :
|
||||
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 :
|
||||
static_cast<uint64_t>(e + kDpExponentBias);
|
||||
u.u64 = (f & kDpSignificandMask) | (be << kDpSignificandSize);
|
||||
return u.d;
|
||||
@ -220,9 +231,10 @@ inline DiyFp GetCachedPowerByIndex(size_t index) {
|
||||
641, 667, 694, 720, 747, 774, 800, 827, 853, 880,
|
||||
907, 933, 960, 986, 1013, 1039, 1066
|
||||
};
|
||||
CEREAL_RAPIDJSON_ASSERT(index < 87);
|
||||
return DiyFp(kCachedPowers_F[index], kCachedPowers_E[index]);
|
||||
}
|
||||
|
||||
|
||||
inline DiyFp GetCachedPower(int e, int* K) {
|
||||
|
||||
//int k = static_cast<int>(ceil((-61 - e) * 0.30102999566398114)) + 374;
|
||||
@ -238,10 +250,11 @@ inline DiyFp GetCachedPower(int e, int* K) {
|
||||
}
|
||||
|
||||
inline DiyFp GetCachedPower10(int exp, int *outExp) {
|
||||
unsigned index = (static_cast<unsigned>(exp) + 348u) / 8u;
|
||||
*outExp = -348 + static_cast<int>(index) * 8;
|
||||
return GetCachedPowerByIndex(index);
|
||||
}
|
||||
CEREAL_RAPIDJSON_ASSERT(exp >= -348);
|
||||
unsigned index = static_cast<unsigned>(exp + 348) / 8u;
|
||||
*outExp = -348 + static_cast<int>(index) * 8;
|
||||
return GetCachedPowerByIndex(index);
|
||||
}
|
||||
|
||||
#ifdef __GNUC__
|
||||
CEREAL_RAPIDJSON_DIAG_POP
|
||||
|
@ -41,7 +41,7 @@ inline void GrisuRound(char* buffer, int len, uint64_t delta, uint64_t rest, uin
|
||||
}
|
||||
}
|
||||
|
||||
inline unsigned CountDecimalDigit32(uint32_t n) {
|
||||
inline int CountDecimalDigit32(uint32_t n) {
|
||||
// Simple pure C++ implementation was faster than __builtin_clz version in this situation.
|
||||
if (n < 10) return 1;
|
||||
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;
|
||||
uint32_t p1 = static_cast<uint32_t>(Mp.f >> -one.e);
|
||||
uint64_t p2 = Mp.f & (one.f - 1);
|
||||
unsigned kappa = CountDecimalDigit32(p1); // kappa in [0, 9]
|
||||
int kappa = CountDecimalDigit32(p1); // kappa in [0, 9]
|
||||
*len = 0;
|
||||
|
||||
while (kappa > 0) {
|
||||
@ -102,8 +102,8 @@ inline void DigitGen(const DiyFp& W, const DiyFp& Mp, uint64_t delta, char* buff
|
||||
kappa--;
|
||||
if (p2 < delta) {
|
||||
*K += kappa;
|
||||
int index = -static_cast<int>(kappa);
|
||||
GrisuRound(buffer, *len, delta, p2, one.f, wp_w.f * (index < 9 ? kPow10[-static_cast<int>(kappa)] : 0));
|
||||
int index = -kappa;
|
||||
GrisuRound(buffer, *len, delta, p2, one.f, wp_w.f * (index < 9 ? kPow10[index] : 0));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
@ -48,13 +48,13 @@ public:
|
||||
int IntegerExponent() const { return (IsNormal() ? Exponent() : kDenormalExponent) - kSignificandSize; }
|
||||
uint64_t ToBias() const { return (u_ & kSignMask) ? ~u_ + 1 : u_ | kSignMask; }
|
||||
|
||||
static unsigned EffectiveSignificandSize(int order) {
|
||||
static int EffectiveSignificandSize(int order) {
|
||||
if (order >= -1021)
|
||||
return 53;
|
||||
else if (order <= -1074)
|
||||
return 0;
|
||||
else
|
||||
return static_cast<unsigned>(order) + 1074;
|
||||
return order + 1074;
|
||||
}
|
||||
|
||||
private:
|
||||
|
@ -1,5 +1,5 @@
|
||||
// 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
|
||||
@ -7,9 +7,9 @@
|
||||
//
|
||||
// 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
|
||||
// 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_ITOA_
|
||||
@ -37,12 +37,14 @@ inline const char* GetDigitsLut() {
|
||||
}
|
||||
|
||||
inline char* u32toa(uint32_t value, char* buffer) {
|
||||
CEREAL_RAPIDJSON_ASSERT(buffer != 0);
|
||||
|
||||
const char* cDigitsLut = GetDigitsLut();
|
||||
|
||||
if (value < 10000) {
|
||||
const uint32_t d1 = (value / 100) << 1;
|
||||
const uint32_t d2 = (value % 100) << 1;
|
||||
|
||||
|
||||
if (value >= 1000)
|
||||
*buffer++ = cDigitsLut[d1];
|
||||
if (value >= 100)
|
||||
@ -55,13 +57,13 @@ inline char* u32toa(uint32_t value, char* buffer) {
|
||||
// value = bbbbcccc
|
||||
const uint32_t b = value / 10000;
|
||||
const uint32_t c = value % 10000;
|
||||
|
||||
|
||||
const uint32_t d1 = (b / 100) << 1;
|
||||
const uint32_t d2 = (b % 100) << 1;
|
||||
|
||||
|
||||
const uint32_t d3 = (c / 100) << 1;
|
||||
const uint32_t d4 = (c % 100) << 1;
|
||||
|
||||
|
||||
if (value >= 10000000)
|
||||
*buffer++ = cDigitsLut[d1];
|
||||
if (value >= 1000000)
|
||||
@ -69,7 +71,7 @@ inline char* u32toa(uint32_t value, char* buffer) {
|
||||
if (value >= 100000)
|
||||
*buffer++ = cDigitsLut[d2];
|
||||
*buffer++ = cDigitsLut[d2 + 1];
|
||||
|
||||
|
||||
*buffer++ = cDigitsLut[d3];
|
||||
*buffer++ = cDigitsLut[d3 + 1];
|
||||
*buffer++ = cDigitsLut[d4];
|
||||
@ -77,10 +79,10 @@ inline char* u32toa(uint32_t value, char* buffer) {
|
||||
}
|
||||
else {
|
||||
// value = aabbbbcccc in decimal
|
||||
|
||||
|
||||
const uint32_t a = value / 100000000; // 1 to 42
|
||||
value %= 100000000;
|
||||
|
||||
|
||||
if (a >= 10) {
|
||||
const unsigned i = a << 1;
|
||||
*buffer++ = cDigitsLut[i];
|
||||
@ -91,13 +93,13 @@ inline char* u32toa(uint32_t value, char* buffer) {
|
||||
|
||||
const uint32_t b = value / 10000; // 0 to 9999
|
||||
const uint32_t c = value % 10000; // 0 to 9999
|
||||
|
||||
|
||||
const uint32_t d1 = (b / 100) << 1;
|
||||
const uint32_t d2 = (b % 100) << 1;
|
||||
|
||||
|
||||
const uint32_t d3 = (c / 100) << 1;
|
||||
const uint32_t d4 = (c % 100) << 1;
|
||||
|
||||
|
||||
*buffer++ = cDigitsLut[d1];
|
||||
*buffer++ = cDigitsLut[d1 + 1];
|
||||
*buffer++ = cDigitsLut[d2];
|
||||
@ -111,6 +113,7 @@ inline char* u32toa(uint32_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);
|
||||
if (value < 0) {
|
||||
*buffer++ = '-';
|
||||
@ -121,6 +124,7 @@ inline char* i32toa(int32_t value, char* buffer) {
|
||||
}
|
||||
|
||||
inline char* u64toa(uint64_t value, char* buffer) {
|
||||
CEREAL_RAPIDJSON_ASSERT(buffer != 0);
|
||||
const char* cDigitsLut = GetDigitsLut();
|
||||
const uint64_t kTen8 = 100000000;
|
||||
const uint64_t kTen9 = kTen8 * 10;
|
||||
@ -131,13 +135,13 @@ inline char* u64toa(uint64_t value, char* buffer) {
|
||||
const uint64_t kTen14 = kTen8 * 1000000;
|
||||
const uint64_t kTen15 = kTen8 * 10000000;
|
||||
const uint64_t kTen16 = kTen8 * kTen8;
|
||||
|
||||
|
||||
if (value < kTen8) {
|
||||
uint32_t v = static_cast<uint32_t>(value);
|
||||
if (v < 10000) {
|
||||
const uint32_t d1 = (v / 100) << 1;
|
||||
const uint32_t d2 = (v % 100) << 1;
|
||||
|
||||
|
||||
if (v >= 1000)
|
||||
*buffer++ = cDigitsLut[d1];
|
||||
if (v >= 100)
|
||||
@ -150,13 +154,13 @@ inline char* u64toa(uint64_t value, char* buffer) {
|
||||
// value = bbbbcccc
|
||||
const uint32_t b = v / 10000;
|
||||
const uint32_t c = v % 10000;
|
||||
|
||||
|
||||
const uint32_t d1 = (b / 100) << 1;
|
||||
const uint32_t d2 = (b % 100) << 1;
|
||||
|
||||
|
||||
const uint32_t d3 = (c / 100) << 1;
|
||||
const uint32_t d4 = (c % 100) << 1;
|
||||
|
||||
|
||||
if (value >= 10000000)
|
||||
*buffer++ = cDigitsLut[d1];
|
||||
if (value >= 1000000)
|
||||
@ -164,7 +168,7 @@ inline char* u64toa(uint64_t value, char* buffer) {
|
||||
if (value >= 100000)
|
||||
*buffer++ = cDigitsLut[d2];
|
||||
*buffer++ = cDigitsLut[d2 + 1];
|
||||
|
||||
|
||||
*buffer++ = cDigitsLut[d3];
|
||||
*buffer++ = cDigitsLut[d3 + 1];
|
||||
*buffer++ = cDigitsLut[d4];
|
||||
@ -174,22 +178,22 @@ inline char* u64toa(uint64_t value, char* buffer) {
|
||||
else if (value < kTen16) {
|
||||
const uint32_t v0 = static_cast<uint32_t>(value / kTen8);
|
||||
const uint32_t v1 = static_cast<uint32_t>(value % kTen8);
|
||||
|
||||
|
||||
const uint32_t b0 = v0 / 10000;
|
||||
const uint32_t c0 = v0 % 10000;
|
||||
|
||||
|
||||
const uint32_t d1 = (b0 / 100) << 1;
|
||||
const uint32_t d2 = (b0 % 100) << 1;
|
||||
|
||||
|
||||
const uint32_t d3 = (c0 / 100) << 1;
|
||||
const uint32_t d4 = (c0 % 100) << 1;
|
||||
|
||||
const uint32_t b1 = v1 / 10000;
|
||||
const uint32_t c1 = v1 % 10000;
|
||||
|
||||
|
||||
const uint32_t d5 = (b1 / 100) << 1;
|
||||
const uint32_t d6 = (b1 % 100) << 1;
|
||||
|
||||
|
||||
const uint32_t d7 = (c1 / 100) << 1;
|
||||
const uint32_t d8 = (c1 % 100) << 1;
|
||||
|
||||
@ -207,9 +211,8 @@ inline char* u64toa(uint64_t value, char* buffer) {
|
||||
*buffer++ = cDigitsLut[d3 + 1];
|
||||
if (value >= kTen9)
|
||||
*buffer++ = cDigitsLut[d4];
|
||||
if (value >= kTen8)
|
||||
*buffer++ = cDigitsLut[d4 + 1];
|
||||
|
||||
|
||||
*buffer++ = cDigitsLut[d4 + 1];
|
||||
*buffer++ = cDigitsLut[d5];
|
||||
*buffer++ = cDigitsLut[d5 + 1];
|
||||
*buffer++ = cDigitsLut[d6];
|
||||
@ -222,7 +225,7 @@ inline char* u64toa(uint64_t value, char* buffer) {
|
||||
else {
|
||||
const uint32_t a = static_cast<uint32_t>(value / kTen16); // 1 to 1844
|
||||
value %= kTen16;
|
||||
|
||||
|
||||
if (a < 10)
|
||||
*buffer++ = static_cast<char>('0' + static_cast<char>(a));
|
||||
else if (a < 100) {
|
||||
@ -232,7 +235,7 @@ inline char* u64toa(uint64_t value, char* buffer) {
|
||||
}
|
||||
else if (a < 1000) {
|
||||
*buffer++ = static_cast<char>('0' + static_cast<char>(a / 100));
|
||||
|
||||
|
||||
const uint32_t i = (a % 100) << 1;
|
||||
*buffer++ = cDigitsLut[i];
|
||||
*buffer++ = cDigitsLut[i + 1];
|
||||
@ -245,28 +248,28 @@ inline char* u64toa(uint64_t value, char* buffer) {
|
||||
*buffer++ = cDigitsLut[j];
|
||||
*buffer++ = cDigitsLut[j + 1];
|
||||
}
|
||||
|
||||
|
||||
const uint32_t v0 = static_cast<uint32_t>(value / kTen8);
|
||||
const uint32_t v1 = static_cast<uint32_t>(value % kTen8);
|
||||
|
||||
|
||||
const uint32_t b0 = v0 / 10000;
|
||||
const uint32_t c0 = v0 % 10000;
|
||||
|
||||
|
||||
const uint32_t d1 = (b0 / 100) << 1;
|
||||
const uint32_t d2 = (b0 % 100) << 1;
|
||||
|
||||
|
||||
const uint32_t d3 = (c0 / 100) << 1;
|
||||
const uint32_t d4 = (c0 % 100) << 1;
|
||||
|
||||
|
||||
const uint32_t b1 = v1 / 10000;
|
||||
const uint32_t c1 = v1 % 10000;
|
||||
|
||||
|
||||
const uint32_t d5 = (b1 / 100) << 1;
|
||||
const uint32_t d6 = (b1 % 100) << 1;
|
||||
|
||||
|
||||
const uint32_t d7 = (c1 / 100) << 1;
|
||||
const uint32_t d8 = (c1 % 100) << 1;
|
||||
|
||||
|
||||
*buffer++ = cDigitsLut[d1];
|
||||
*buffer++ = cDigitsLut[d1 + 1];
|
||||
*buffer++ = cDigitsLut[d2];
|
||||
@ -284,11 +287,12 @@ inline char* u64toa(uint64_t value, char* buffer) {
|
||||
*buffer++ = cDigitsLut[d8];
|
||||
*buffer++ = cDigitsLut[d8 + 1];
|
||||
}
|
||||
|
||||
|
||||
return buffer;
|
||||
}
|
||||
|
||||
inline char* i64toa(int64_t value, char* buffer) {
|
||||
CEREAL_RAPIDJSON_ASSERT(buffer != 0);
|
||||
uint64_t u = static_cast<uint64_t>(value);
|
||||
if (value < 0) {
|
||||
*buffer++ = '-';
|
||||
|
@ -21,7 +21,8 @@
|
||||
CEREAL_RAPIDJSON_DIAG_PUSH
|
||||
CEREAL_RAPIDJSON_DIAG_OFF(effc++)
|
||||
#endif
|
||||
#if defined(_MSC_VER)
|
||||
|
||||
#if defined(_MSC_VER) && !defined(__clang__)
|
||||
CEREAL_RAPIDJSON_DIAG_PUSH
|
||||
CEREAL_RAPIDJSON_DIAG_OFF(6334)
|
||||
#endif
|
||||
@ -174,7 +175,11 @@ template <typename T> struct RemoveSfinaeTag<SfinaeTag&(*)(T)> { typedef T Type;
|
||||
CEREAL_RAPIDJSON_NAMESPACE_END
|
||||
//@endcond
|
||||
|
||||
#if defined(__GNUC__) || defined(_MSC_VER)
|
||||
#if defined(_MSC_VER) && !defined(__clang__)
|
||||
CEREAL_RAPIDJSON_DIAG_POP
|
||||
#endif
|
||||
|
||||
#ifdef __GNUC__
|
||||
CEREAL_RAPIDJSON_DIAG_POP
|
||||
#endif
|
||||
|
||||
|
319
include/cereal/external/rapidjson/internal/regex.h
vendored
319
include/cereal/external/rapidjson/internal/regex.h
vendored
@ -24,16 +24,17 @@ CEREAL_RAPIDJSON_DIAG_PUSH
|
||||
CEREAL_RAPIDJSON_DIAG_OFF(padded)
|
||||
CEREAL_RAPIDJSON_DIAG_OFF(switch-enum)
|
||||
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
|
||||
|
||||
#ifdef __GNUC__
|
||||
CEREAL_RAPIDJSON_DIAG_PUSH
|
||||
CEREAL_RAPIDJSON_DIAG_OFF(effc++)
|
||||
#if __GNUC__ >= 7
|
||||
CEREAL_RAPIDJSON_DIAG_OFF(implicit-fallthrough)
|
||||
#endif
|
||||
|
||||
#ifdef _MSC_VER
|
||||
CEREAL_RAPIDJSON_DIAG_PUSH
|
||||
CEREAL_RAPIDJSON_DIAG_OFF(4512) // assignment operator could not be generated
|
||||
#endif
|
||||
|
||||
#ifndef CEREAL_RAPIDJSON_REGEX_VERBOSE
|
||||
@ -43,12 +44,40 @@ CEREAL_RAPIDJSON_DIAG_OFF(4512) // assignment operator could not be generated
|
||||
CEREAL_RAPIDJSON_NAMESPACE_BEGIN
|
||||
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
|
||||
|
||||
static const SizeType kRegexInvalidState = ~SizeType(0); //!< Represents an invalid index in GenericRegex::State::out, out1
|
||||
static const SizeType kRegexInvalidRange = ~SizeType(0);
|
||||
|
||||
template <typename Encoding, typename Allocator>
|
||||
class GenericRegexSearch;
|
||||
|
||||
//! Regular expression engine with subset of ECMAscript grammar.
|
||||
/*!
|
||||
Supported regular expression syntax:
|
||||
@ -84,45 +113,29 @@ static const SizeType kRegexInvalidRange = ~SizeType(0);
|
||||
template <typename Encoding, typename Allocator = CrtAllocator>
|
||||
class GenericRegex {
|
||||
public:
|
||||
typedef Encoding EncodingType;
|
||||
typedef typename Encoding::Ch Ch;
|
||||
template <typename, typename> friend class GenericRegexSearch;
|
||||
|
||||
GenericRegex(const Ch* source, Allocator* allocator = 0) :
|
||||
states_(allocator, 256), ranges_(allocator, 256), root_(kRegexInvalidState), stateCount_(), rangeCount_(),
|
||||
stateSet_(), state0_(allocator, 0), state1_(allocator, 0), anchorBegin_(), anchorEnd_()
|
||||
ownAllocator_(allocator ? 0 : CEREAL_RAPIDJSON_NEW(Allocator)()), allocator_(allocator ? allocator : ownAllocator_),
|
||||
states_(allocator_, 256), ranges_(allocator_, 256), root_(kRegexInvalidState), stateCount_(), rangeCount_(),
|
||||
anchorBegin_(), anchorEnd_()
|
||||
{
|
||||
GenericStringStream<Encoding> ss(source);
|
||||
DecodedStream<GenericStringStream<Encoding> > ds(ss);
|
||||
DecodedStream<GenericStringStream<Encoding>, Encoding> ds(ss);
|
||||
Parse(ds);
|
||||
}
|
||||
|
||||
~GenericRegex() {
|
||||
Allocator::Free(stateSet_);
|
||||
~GenericRegex()
|
||||
{
|
||||
CEREAL_RAPIDJSON_DELETE(ownAllocator_);
|
||||
}
|
||||
|
||||
bool IsValid() const {
|
||||
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:
|
||||
enum Operator {
|
||||
kZeroOrOne,
|
||||
@ -157,28 +170,6 @@ private:
|
||||
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) {
|
||||
CEREAL_RAPIDJSON_ASSERT(index < stateCount_);
|
||||
return states_.template Bottom<State>()[index];
|
||||
@ -200,11 +191,10 @@ private:
|
||||
}
|
||||
|
||||
template <typename InputStream>
|
||||
void Parse(DecodedStream<InputStream>& ds) {
|
||||
Allocator allocator;
|
||||
Stack<Allocator> operandStack(&allocator, 256); // Frag
|
||||
Stack<Allocator> operatorStack(&allocator, 256); // Operator
|
||||
Stack<Allocator> atomCountStack(&allocator, 256); // unsigned (Atom per parenthesis)
|
||||
void Parse(DecodedStream<InputStream, Encoding>& ds) {
|
||||
Stack<Allocator> operandStack(allocator_, 256); // Frag
|
||||
Stack<Allocator> operatorStack(allocator_, 256); // Operator
|
||||
Stack<Allocator> atomCountStack(allocator_, 256); // unsigned (Atom per parenthesis)
|
||||
|
||||
*atomCountStack.template Push<unsigned>() = 0;
|
||||
|
||||
@ -327,14 +317,6 @@ private:
|
||||
printf("\n");
|
||||
#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) {
|
||||
@ -413,8 +395,7 @@ private:
|
||||
}
|
||||
return false;
|
||||
|
||||
default:
|
||||
CEREAL_RAPIDJSON_ASSERT(op == kOneOrMore);
|
||||
case kOneOrMore:
|
||||
if (operandStack.GetSize() >= sizeof(Frag)) {
|
||||
Frag e = *operandStack.template Pop<Frag>(1);
|
||||
SizeType s = NewState(kRegexInvalidState, e.start, 0);
|
||||
@ -423,6 +404,10 @@ private:
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
||||
default:
|
||||
// syntax error (e.g. unclosed kLeftParenthesis)
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@ -483,7 +468,7 @@ private:
|
||||
}
|
||||
|
||||
template <typename InputStream>
|
||||
bool ParseUnsigned(DecodedStream<InputStream>& ds, unsigned* u) {
|
||||
bool ParseUnsigned(DecodedStream<InputStream, Encoding>& ds, unsigned* u) {
|
||||
unsigned r = 0;
|
||||
if (ds.Peek() < '0' || ds.Peek() > '9')
|
||||
return false;
|
||||
@ -497,7 +482,7 @@ private:
|
||||
}
|
||||
|
||||
template <typename InputStream>
|
||||
bool ParseRange(DecodedStream<InputStream>& ds, SizeType* range) {
|
||||
bool ParseRange(DecodedStream<InputStream, Encoding>& ds, SizeType* range) {
|
||||
bool isBegin = true;
|
||||
bool negate = false;
|
||||
int step = 0;
|
||||
@ -575,7 +560,7 @@ private:
|
||||
}
|
||||
|
||||
template <typename InputStream>
|
||||
bool CharacterEscape(DecodedStream<InputStream>& ds, unsigned* escapedCodepoint) {
|
||||
bool CharacterEscape(DecodedStream<InputStream, Encoding>& ds, unsigned* escapedCodepoint) {
|
||||
unsigned codepoint;
|
||||
switch (codepoint = ds.Take()) {
|
||||
case '^':
|
||||
@ -603,72 +588,8 @@ private:
|
||||
}
|
||||
}
|
||||
|
||||
template <typename InputStream>
|
||||
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;
|
||||
}
|
||||
|
||||
Allocator* ownAllocator_;
|
||||
Allocator* allocator_;
|
||||
Stack<Allocator> states_;
|
||||
Stack<Allocator> ranges_;
|
||||
SizeType root_;
|
||||
@ -678,23 +599,141 @@ private:
|
||||
static const unsigned kInfinityQuantifier = ~0u;
|
||||
|
||||
// For SearchWithAnchoring()
|
||||
uint32_t* stateSet_; // allocated by states_.GetAllocator()
|
||||
mutable Stack<Allocator> state0_;
|
||||
mutable Stack<Allocator> state1_;
|
||||
bool anchorBegin_;
|
||||
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 GenericRegexSearch<Regex> RegexSearch;
|
||||
|
||||
} // namespace internal
|
||||
CEREAL_RAPIDJSON_NAMESPACE_END
|
||||
|
||||
#ifdef __clang__
|
||||
#ifdef __GNUC__
|
||||
CEREAL_RAPIDJSON_DIAG_POP
|
||||
#endif
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#if defined(__clang__) || defined(_MSC_VER)
|
||||
CEREAL_RAPIDJSON_DIAG_POP
|
||||
#endif
|
||||
|
||||
|
@ -17,6 +17,7 @@
|
||||
|
||||
#include "../allocators.h"
|
||||
#include "swap.h"
|
||||
#include <cstddef>
|
||||
|
||||
#if defined(__clang__)
|
||||
CEREAL_RAPIDJSON_DIAG_PUSH
|
||||
@ -100,7 +101,7 @@ public:
|
||||
void ShrinkToFit() {
|
||||
if (Empty()) {
|
||||
// If the stack is empty, completely deallocate the memory.
|
||||
Allocator::Free(stack_);
|
||||
Allocator::Free(stack_); // NOLINT (+clang-analyzer-unix.Malloc)
|
||||
stack_ = 0;
|
||||
stackTop_ = 0;
|
||||
stackEnd_ = 0;
|
||||
@ -114,7 +115,7 @@ public:
|
||||
template<typename T>
|
||||
CEREAL_RAPIDJSON_FORCEINLINE void Reserve(size_t count = 1) {
|
||||
// Expand the stack if needed
|
||||
if (CEREAL_RAPIDJSON_UNLIKELY(stackTop_ + sizeof(T) * count > stackEnd_))
|
||||
if (CEREAL_RAPIDJSON_UNLIKELY(static_cast<std::ptrdiff_t>(sizeof(T) * count) > (stackEnd_ - stackTop_)))
|
||||
Expand<T>(count);
|
||||
}
|
||||
|
||||
@ -126,7 +127,8 @@ public:
|
||||
|
||||
template<typename T>
|
||||
CEREAL_RAPIDJSON_FORCEINLINE T* PushUnsafe(size_t count = 1) {
|
||||
CEREAL_RAPIDJSON_ASSERT(stackTop_ + sizeof(T) * count <= stackEnd_);
|
||||
CEREAL_RAPIDJSON_ASSERT(stackTop_);
|
||||
CEREAL_RAPIDJSON_ASSERT(static_cast<std::ptrdiff_t>(sizeof(T) * count) <= (stackEnd_ - stackTop_));
|
||||
T* ret = reinterpret_cast<T*>(stackTop_);
|
||||
stackTop_ += sizeof(T) * count;
|
||||
return ret;
|
||||
@ -183,7 +185,7 @@ private:
|
||||
size_t newCapacity;
|
||||
if (stack_ == 0) {
|
||||
if (!allocator_)
|
||||
ownAllocator_ = allocator_ = CEREAL_RAPIDJSON_NEW(Allocator());
|
||||
ownAllocator_ = allocator_ = CEREAL_RAPIDJSON_NEW(Allocator)();
|
||||
newCapacity = initialCapacity_;
|
||||
} else {
|
||||
newCapacity = GetCapacity();
|
||||
|
@ -16,6 +16,7 @@
|
||||
#define CEREAL_RAPIDJSON_INTERNAL_STRFUNC_H_
|
||||
|
||||
#include "../stream.h"
|
||||
#include <cwchar>
|
||||
|
||||
CEREAL_RAPIDJSON_NAMESPACE_BEGIN
|
||||
namespace internal {
|
||||
@ -28,14 +29,27 @@ namespace internal {
|
||||
*/
|
||||
template <typename Ch>
|
||||
inline SizeType StrLen(const Ch* s) {
|
||||
CEREAL_RAPIDJSON_ASSERT(s != 0);
|
||||
const Ch* p = s;
|
||||
while (*p) ++p;
|
||||
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.
|
||||
template<typename Encoding>
|
||||
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);
|
||||
const typename Encoding::Ch* end = s + length;
|
||||
SizeType count = 0;
|
||||
|
111
include/cereal/external/rapidjson/internal/strtod.h
vendored
111
include/cereal/external/rapidjson/internal/strtod.h
vendored
@ -19,6 +19,8 @@
|
||||
#include "biginteger.h"
|
||||
#include "diyfp.h"
|
||||
#include "pow10.h"
|
||||
#include <climits>
|
||||
#include <limits>
|
||||
|
||||
CEREAL_RAPIDJSON_NAMESPACE_BEGIN
|
||||
namespace internal {
|
||||
@ -126,46 +128,46 @@ inline bool StrtodFast(double d, int p, double* result) {
|
||||
}
|
||||
|
||||
// Compute an approximation and see if it is within 1/2 ULP
|
||||
inline bool StrtodDiyFp(const char* decimals, size_t length, size_t decimalPosition, int exp, double* result) {
|
||||
inline bool StrtodDiyFp(const char* decimals, int dLen, int dExp, double* result) {
|
||||
uint64_t significand = 0;
|
||||
size_t i = 0; // 2^64 - 1 = 18446744073709551615, 1844674407370955161 = 0x1999999999999999
|
||||
for (; i < length; i++) {
|
||||
int i = 0; // 2^64 - 1 = 18446744073709551615, 1844674407370955161 = 0x1999999999999999
|
||||
for (; i < dLen; i++) {
|
||||
if (significand > CEREAL_RAPIDJSON_UINT64_C2(0x19999999, 0x99999999) ||
|
||||
(significand == CEREAL_RAPIDJSON_UINT64_C2(0x19999999, 0x99999999) && decimals[i] > '5'))
|
||||
break;
|
||||
significand = significand * 10u + static_cast<unsigned>(decimals[i] - '0');
|
||||
}
|
||||
|
||||
if (i < length && decimals[i] >= '5') // Rounding
|
||||
if (i < dLen && decimals[i] >= '5') // Rounding
|
||||
significand++;
|
||||
|
||||
size_t remaining = length - i;
|
||||
const unsigned kUlpShift = 3;
|
||||
const unsigned kUlp = 1 << kUlpShift;
|
||||
int remaining = dLen - i;
|
||||
const int kUlpShift = 3;
|
||||
const int kUlp = 1 << kUlpShift;
|
||||
int64_t error = (remaining == 0) ? 0 : kUlp / 2;
|
||||
|
||||
DiyFp v(significand, 0);
|
||||
v = v.Normalize();
|
||||
error <<= -v.e;
|
||||
|
||||
const int dExp = static_cast<int>(decimalPosition) - static_cast<int>(i) + exp;
|
||||
dExp += remaining;
|
||||
|
||||
int actualExp;
|
||||
DiyFp cachedPower = GetCachedPower10(dExp, &actualExp);
|
||||
if (actualExp != dExp) {
|
||||
static const DiyFp kPow10[] = {
|
||||
DiyFp(CEREAL_RAPIDJSON_UINT64_C2(0xa0000000, 00000000), -60), // 10^1
|
||||
DiyFp(CEREAL_RAPIDJSON_UINT64_C2(0xc8000000, 00000000), -57), // 10^2
|
||||
DiyFp(CEREAL_RAPIDJSON_UINT64_C2(0xfa000000, 00000000), -54), // 10^3
|
||||
DiyFp(CEREAL_RAPIDJSON_UINT64_C2(0x9c400000, 00000000), -50), // 10^4
|
||||
DiyFp(CEREAL_RAPIDJSON_UINT64_C2(0xc3500000, 00000000), -47), // 10^5
|
||||
DiyFp(CEREAL_RAPIDJSON_UINT64_C2(0xf4240000, 00000000), -44), // 10^6
|
||||
DiyFp(CEREAL_RAPIDJSON_UINT64_C2(0x98968000, 00000000), -40) // 10^7
|
||||
DiyFp(CEREAL_RAPIDJSON_UINT64_C2(0xa0000000, 0x00000000), -60), // 10^1
|
||||
DiyFp(CEREAL_RAPIDJSON_UINT64_C2(0xc8000000, 0x00000000), -57), // 10^2
|
||||
DiyFp(CEREAL_RAPIDJSON_UINT64_C2(0xfa000000, 0x00000000), -54), // 10^3
|
||||
DiyFp(CEREAL_RAPIDJSON_UINT64_C2(0x9c400000, 0x00000000), -50), // 10^4
|
||||
DiyFp(CEREAL_RAPIDJSON_UINT64_C2(0xc3500000, 0x00000000), -47), // 10^5
|
||||
DiyFp(CEREAL_RAPIDJSON_UINT64_C2(0xf4240000, 0x00000000), -44), // 10^6
|
||||
DiyFp(CEREAL_RAPIDJSON_UINT64_C2(0x98968000, 0x00000000), -40) // 10^7
|
||||
};
|
||||
int adjustment = dExp - actualExp - 1;
|
||||
CEREAL_RAPIDJSON_ASSERT(adjustment >= 0 && adjustment < 7);
|
||||
v = v * kPow10[adjustment];
|
||||
if (length + static_cast<unsigned>(adjustment)> 19u) // has more digits than decimal digits in 64-bit
|
||||
int adjustment = dExp - actualExp;
|
||||
CEREAL_RAPIDJSON_ASSERT(adjustment >= 1 && adjustment < 8);
|
||||
v = v * kPow10[adjustment - 1];
|
||||
if (dLen + adjustment > 19) // has more digits than decimal digits in 64-bit
|
||||
error += kUlp / 2;
|
||||
}
|
||||
|
||||
@ -177,17 +179,17 @@ inline bool StrtodDiyFp(const char* decimals, size_t length, size_t decimalPosit
|
||||
v = v.Normalize();
|
||||
error <<= oldExp - v.e;
|
||||
|
||||
const unsigned effectiveSignificandSize = Double::EffectiveSignificandSize(64 + v.e);
|
||||
unsigned precisionSize = 64 - effectiveSignificandSize;
|
||||
const int effectiveSignificandSize = Double::EffectiveSignificandSize(64 + v.e);
|
||||
int precisionSize = 64 - effectiveSignificandSize;
|
||||
if (precisionSize + kUlpShift >= 64) {
|
||||
unsigned scaleExp = (precisionSize + kUlpShift) - 63;
|
||||
int scaleExp = (precisionSize + kUlpShift) - 63;
|
||||
v.f >>= scaleExp;
|
||||
v.e += scaleExp;
|
||||
error = (error >> scaleExp) + 1 + static_cast<int>(kUlp);
|
||||
error = (error >> scaleExp) + 1 + kUlp;
|
||||
precisionSize -= scaleExp;
|
||||
}
|
||||
|
||||
DiyFp rounded(v.f >> precisionSize, v.e + static_cast<int>(precisionSize));
|
||||
DiyFp rounded(v.f >> precisionSize, v.e + precisionSize);
|
||||
const uint64_t precisionBits = (v.f & ((uint64_t(1) << precisionSize) - 1)) * kUlp;
|
||||
const uint64_t halfWay = (uint64_t(1) << (precisionSize - 1)) * kUlp;
|
||||
if (precisionBits >= halfWay + static_cast<unsigned>(error)) {
|
||||
@ -203,9 +205,9 @@ inline bool StrtodDiyFp(const char* decimals, size_t length, size_t decimalPosit
|
||||
return halfWay - static_cast<unsigned>(error) >= precisionBits || precisionBits >= halfWay + static_cast<unsigned>(error);
|
||||
}
|
||||
|
||||
inline double StrtodBigInteger(double approx, const char* decimals, size_t length, size_t decimalPosition, int exp) {
|
||||
const BigInteger dInt(decimals, length);
|
||||
const int dExp = static_cast<int>(decimalPosition) - static_cast<int>(length) + exp;
|
||||
inline double StrtodBigInteger(double approx, const char* decimals, int dLen, int dExp) {
|
||||
CEREAL_RAPIDJSON_ASSERT(dLen >= 0);
|
||||
const BigInteger dInt(decimals, static_cast<unsigned>(dLen));
|
||||
Double a(approx);
|
||||
int cmp = CheckWithinHalfULP(a.Value(), dInt, dExp);
|
||||
if (cmp < 0)
|
||||
@ -225,42 +227,61 @@ inline double StrtodFullPrecision(double d, int p, const char* decimals, size_t
|
||||
CEREAL_RAPIDJSON_ASSERT(d >= 0.0);
|
||||
CEREAL_RAPIDJSON_ASSERT(length >= 1);
|
||||
|
||||
double result;
|
||||
double result = 0.0;
|
||||
if (StrtodFast(d, p, &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
|
||||
while (*decimals == '0' && length > 1) {
|
||||
length--;
|
||||
while (dLen > 0 && *decimals == '0') {
|
||||
dLen--;
|
||||
decimals++;
|
||||
decimalPosition--;
|
||||
}
|
||||
|
||||
// Trim trailing zeros
|
||||
while (decimals[length - 1] == '0' && length > 1) {
|
||||
length--;
|
||||
decimalPosition--;
|
||||
exp++;
|
||||
while (dLen > 0 && decimals[dLen - 1] == '0') {
|
||||
dLen--;
|
||||
dExp++;
|
||||
}
|
||||
|
||||
if (dLen == 0) { // Buffer only contains zeros.
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
// Trim right-most digits
|
||||
const int kMaxDecimalDigit = 780;
|
||||
if (static_cast<int>(length) > kMaxDecimalDigit) {
|
||||
int delta = (static_cast<int>(length) - kMaxDecimalDigit);
|
||||
exp += delta;
|
||||
decimalPosition -= static_cast<unsigned>(delta);
|
||||
length = kMaxDecimalDigit;
|
||||
const int kMaxDecimalDigit = 767 + 1;
|
||||
if (dLen > kMaxDecimalDigit) {
|
||||
dExp += dLen - kMaxDecimalDigit;
|
||||
dLen = kMaxDecimalDigit;
|
||||
}
|
||||
|
||||
// If too small, underflow to zero
|
||||
if (int(length) + exp < -324)
|
||||
// If too small, underflow to zero.
|
||||
// Any x <= 10^-324 is interpreted as zero.
|
||||
if (dLen + dExp <= -324)
|
||||
return 0.0;
|
||||
|
||||
if (StrtodDiyFp(decimals, length, decimalPosition, exp, &result))
|
||||
// If too large, overflow to infinity.
|
||||
// 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;
|
||||
|
||||
// Use approximation from StrtodDiyFp and make adjustment with BigInteger comparison
|
||||
return StrtodBigInteger(result, decimals, length, decimalPosition, exp);
|
||||
return StrtodBigInteger(result, decimals, dLen, dExp);
|
||||
}
|
||||
|
||||
} // namespace internal
|
||||
|
@ -1,5 +1,5 @@
|
||||
// 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
|
||||
@ -7,9 +7,9 @@
|
||||
//
|
||||
// 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
|
||||
// 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_ISTREAMWRAPPER_H_
|
||||
@ -17,16 +17,14 @@
|
||||
|
||||
#include "stream.h"
|
||||
#include <iosfwd>
|
||||
#include <ios>
|
||||
|
||||
#ifdef __clang__
|
||||
CEREAL_RAPIDJSON_DIAG_PUSH
|
||||
CEREAL_RAPIDJSON_DIAG_OFF(padded)
|
||||
#endif
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#elif defined(_MSC_VER)
|
||||
CEREAL_RAPIDJSON_DIAG_PUSH
|
||||
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
|
||||
|
||||
CEREAL_RAPIDJSON_NAMESPACE_BEGIN
|
||||
@ -46,62 +44,76 @@ CEREAL_RAPIDJSON_NAMESPACE_BEGIN
|
||||
|
||||
\tparam StreamType Class derived from \c std::basic_istream.
|
||||
*/
|
||||
|
||||
|
||||
template <typename StreamType>
|
||||
class BasicIStreamWrapper {
|
||||
public:
|
||||
typedef typename StreamType::char_type Ch;
|
||||
BasicIStreamWrapper(StreamType& stream) : stream_(stream), count_(), peekBuffer_() {}
|
||||
|
||||
Ch Peek() const {
|
||||
typename StreamType::int_type c = stream_.peek();
|
||||
return CEREAL_RAPIDJSON_LIKELY(c != StreamType::traits_type::eof()) ? static_cast<Ch>(c) : '\0';
|
||||
//! Constructor.
|
||||
/*!
|
||||
\param stream stream opened for read.
|
||||
*/
|
||||
BasicIStreamWrapper(StreamType &stream) : stream_(stream), buffer_(peekBuffer_), bufferSize_(4), bufferLast_(0), current_(buffer_), readCount_(0), count_(0), eof_(false) {
|
||||
Read();
|
||||
}
|
||||
|
||||
Ch Take() {
|
||||
typename StreamType::int_type c = stream_.get();
|
||||
if (CEREAL_RAPIDJSON_LIKELY(c != StreamType::traits_type::eof())) {
|
||||
count_++;
|
||||
return static_cast<Ch>(c);
|
||||
}
|
||||
else
|
||||
return '\0';
|
||||
//! Constructor.
|
||||
/*!
|
||||
\param stream stream opened for read.
|
||||
\param buffer user-supplied buffer.
|
||||
\param bufferSize size of buffer in bytes. Must >=4 bytes.
|
||||
*/
|
||||
BasicIStreamWrapper(StreamType &stream, char* buffer, size_t bufferSize) : stream_(stream), buffer_(buffer), bufferSize_(bufferSize), bufferLast_(0), current_(buffer_), readCount_(0), count_(0), eof_(false) {
|
||||
CEREAL_RAPIDJSON_ASSERT(bufferSize >= 4);
|
||||
Read();
|
||||
}
|
||||
|
||||
// tellg() may return -1 when failed. So we count by ourself.
|
||||
size_t Tell() const { return count_; }
|
||||
Ch Peek() const { return *current_; }
|
||||
Ch Take() { Ch c = *current_; Read(); return c; }
|
||||
size_t Tell() const { return count_ + static_cast<size_t>(current_ - buffer_); }
|
||||
|
||||
Ch* PutBegin() { CEREAL_RAPIDJSON_ASSERT(false); return 0; }
|
||||
// Not implemented
|
||||
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; }
|
||||
|
||||
// For encoding detection only.
|
||||
const Ch* Peek4() const {
|
||||
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;
|
||||
return (current_ + 4 - !eof_ <= bufferLast_) ? current_ : 0;
|
||||
}
|
||||
|
||||
private:
|
||||
BasicIStreamWrapper();
|
||||
BasicIStreamWrapper(const BasicIStreamWrapper&);
|
||||
BasicIStreamWrapper& operator=(const BasicIStreamWrapper&);
|
||||
|
||||
StreamType& stream_;
|
||||
size_t count_; //!< Number of characters read. Note:
|
||||
mutable Ch peekBuffer_[4];
|
||||
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_;
|
||||
Ch peekBuffer_[4], *buffer_;
|
||||
size_t bufferSize_;
|
||||
Ch *bufferLast_;
|
||||
Ch *current_;
|
||||
size_t readCount_;
|
||||
size_t count_; //!< Number of characters read
|
||||
bool eof_;
|
||||
};
|
||||
|
||||
typedef BasicIStreamWrapper<std::istream> IStreamWrapper;
|
||||
|
15
include/cereal/external/rapidjson/memorystream.h
vendored
15
include/cereal/external/rapidjson/memorystream.h
vendored
@ -1,5 +1,5 @@
|
||||
// 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
|
||||
@ -7,9 +7,9 @@
|
||||
//
|
||||
// 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
|
||||
// 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_MEMORYSTREAM_H_
|
||||
@ -23,11 +23,6 @@ CEREAL_RAPIDJSON_DIAG_OFF(unreachable-code)
|
||||
CEREAL_RAPIDJSON_DIAG_OFF(missing-noreturn)
|
||||
#endif
|
||||
|
||||
#ifdef _MSC_VER
|
||||
CEREAL_RAPIDJSON_DIAG_PUSH
|
||||
CEREAL_RAPIDJSON_DIAG_OFF( 4127 ) // ignore assert(false) for triggering exception
|
||||
#endif
|
||||
|
||||
CEREAL_RAPIDJSON_NAMESPACE_BEGIN
|
||||
|
||||
//! Represents an in-memory input byte stream.
|
||||
@ -69,7 +64,7 @@ struct MemoryStream {
|
||||
|
||||
CEREAL_RAPIDJSON_NAMESPACE_END
|
||||
|
||||
#if defined(__clang__) || defined(_MSC_VER)
|
||||
#ifdef __clang__
|
||||
CEREAL_RAPIDJSON_DIAG_POP
|
||||
#endif
|
||||
|
||||
|
29
include/cereal/external/rapidjson/msinttypes/LICENSE
vendored
Normal file
29
include/cereal/external/rapidjson/msinttypes/LICENSE
vendored
Normal file
@ -0,0 +1,29 @@
|
||||
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.
|
92
include/cereal/external/rapidjson/pointer.h
vendored
92
include/cereal/external/rapidjson/pointer.h
vendored
@ -21,9 +21,7 @@
|
||||
#ifdef __clang__
|
||||
CEREAL_RAPIDJSON_DIAG_PUSH
|
||||
CEREAL_RAPIDJSON_DIAG_OFF(switch-enum)
|
||||
#endif
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#elif defined(_MSC_VER)
|
||||
CEREAL_RAPIDJSON_DIAG_PUSH
|
||||
CEREAL_RAPIDJSON_DIAG_OFF(4512) // assignment operator could not be generated
|
||||
#endif
|
||||
@ -165,7 +163,12 @@ public:
|
||||
GenericPointer(const Token* tokens, size_t tokenCount) : allocator_(), ownAllocator_(), nameBuffer_(), tokens_(const_cast<Token*>(tokens)), tokenCount_(tokenCount), parseErrorOffset_(), parseErrorCode_(kPointerParseErrorNone) {}
|
||||
|
||||
//! Copy constructor.
|
||||
GenericPointer(const GenericPointer& rhs, Allocator* allocator = 0) : allocator_(allocator), ownAllocator_(), nameBuffer_(), tokens_(), tokenCount_(), parseErrorOffset_(), parseErrorCode_(kPointerParseErrorNone) {
|
||||
GenericPointer(const GenericPointer& rhs) : allocator_(rhs.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;
|
||||
}
|
||||
|
||||
@ -197,6 +200,36 @@ public:
|
||||
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
|
||||
@ -240,7 +273,7 @@ public:
|
||||
template <typename T>
|
||||
CEREAL_RAPIDJSON_DISABLEIF_RETURN((internal::NotExpr<internal::IsSame<typename internal::RemoveConst<T>::Type, Ch> >), (GenericPointer))
|
||||
Append(T* name, Allocator* allocator = 0) const {
|
||||
return Append(name, StrLen(name), allocator);
|
||||
return Append(name, internal::StrLen(name), allocator);
|
||||
}
|
||||
|
||||
#if CEREAL_RAPIDJSON_HAS_STDSTRING
|
||||
@ -274,7 +307,7 @@ public:
|
||||
else {
|
||||
Ch name[21];
|
||||
for (size_t i = 0; i <= length; i++)
|
||||
name[i] = buffer[i];
|
||||
name[i] = static_cast<Ch>(buffer[i]);
|
||||
Token token = { name, length, index };
|
||||
return Append(token, allocator);
|
||||
}
|
||||
@ -353,6 +386,33 @@ public:
|
||||
*/
|
||||
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
|
||||
@ -532,14 +592,14 @@ public:
|
||||
*/
|
||||
ValueType& GetWithDefault(ValueType& root, const ValueType& defaultValue, typename ValueType::AllocatorType& allocator) const {
|
||||
bool alreadyExist;
|
||||
Value& v = Create(root, allocator, &alreadyExist);
|
||||
ValueType& v = Create(root, allocator, &alreadyExist);
|
||||
return alreadyExist ? v : v.CopyFrom(defaultValue, allocator);
|
||||
}
|
||||
|
||||
//! Query a value in a subtree with default null-terminated string.
|
||||
ValueType& GetWithDefault(ValueType& root, const Ch* defaultValue, typename ValueType::AllocatorType& allocator) const {
|
||||
bool alreadyExist;
|
||||
Value& v = Create(root, allocator, &alreadyExist);
|
||||
ValueType& v = Create(root, allocator, &alreadyExist);
|
||||
return alreadyExist ? v : v.SetString(defaultValue, allocator);
|
||||
}
|
||||
|
||||
@ -547,7 +607,7 @@ public:
|
||||
//! 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 {
|
||||
bool alreadyExist;
|
||||
Value& v = Create(root, allocator, &alreadyExist);
|
||||
ValueType& v = Create(root, allocator, &alreadyExist);
|
||||
return alreadyExist ? v : v.SetString(defaultValue, allocator);
|
||||
}
|
||||
#endif
|
||||
@ -758,7 +818,7 @@ private:
|
||||
*/
|
||||
Ch* CopyFromRaw(const GenericPointer& rhs, size_t extraToken = 0, size_t extraNameBufferSize = 0) {
|
||||
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
|
||||
for (Token *t = rhs.tokens_; t != rhs.tokens_ + rhs.tokenCount_; ++t)
|
||||
@ -806,7 +866,7 @@ private:
|
||||
|
||||
// Create own allocator if user did not supply.
|
||||
if (!allocator_)
|
||||
ownAllocator_ = allocator_ = CEREAL_RAPIDJSON_NEW(Allocator());
|
||||
ownAllocator_ = allocator_ = CEREAL_RAPIDJSON_NEW(Allocator)();
|
||||
|
||||
// Count number of '/' as tokenCount
|
||||
tokenCount_ = 0;
|
||||
@ -1029,8 +1089,8 @@ private:
|
||||
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' };
|
||||
os_.Put('%');
|
||||
os_.Put(hexDigits[u >> 4]);
|
||||
os_.Put(hexDigits[u & 15]);
|
||||
os_.Put(static_cast<typename OutputStream::Ch>(hexDigits[u >> 4]));
|
||||
os_.Put(static_cast<typename OutputStream::Ch>(hexDigits[u & 15]));
|
||||
}
|
||||
private:
|
||||
OutputStream& os_;
|
||||
@ -1347,11 +1407,7 @@ bool EraseValueByPointer(T& root, const CharType(&source)[N]) {
|
||||
|
||||
CEREAL_RAPIDJSON_NAMESPACE_END
|
||||
|
||||
#ifdef __clang__
|
||||
CEREAL_RAPIDJSON_DIAG_POP
|
||||
#endif
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#if defined(__clang__) || defined(_MSC_VER)
|
||||
CEREAL_RAPIDJSON_DIAG_POP
|
||||
#endif
|
||||
|
||||
|
60
include/cereal/external/rapidjson/prettywriter.h
vendored
60
include/cereal/external/rapidjson/prettywriter.h
vendored
@ -22,6 +22,11 @@ CEREAL_RAPIDJSON_DIAG_PUSH
|
||||
CEREAL_RAPIDJSON_DIAG_OFF(effc++)
|
||||
#endif
|
||||
|
||||
#if defined(__clang__)
|
||||
CEREAL_RAPIDJSON_DIAG_PUSH
|
||||
CEREAL_RAPIDJSON_DIAG_OFF(c++98-compat)
|
||||
#endif
|
||||
|
||||
CEREAL_RAPIDJSON_NAMESPACE_BEGIN
|
||||
|
||||
//! Combination of PrettyWriter format flags.
|
||||
@ -34,7 +39,7 @@ enum PrettyFormatOptions {
|
||||
|
||||
//! Writer with indentation and spacing.
|
||||
/*!
|
||||
\tparam OutputStream Type of ouptut os.
|
||||
\tparam OutputStream Type of output os.
|
||||
\tparam SourceEncoding Encoding of source string.
|
||||
\tparam TargetEncoding Encoding of output stream.
|
||||
\tparam StackAllocator Type of allocator for allocating memory of stack.
|
||||
@ -42,7 +47,7 @@ enum PrettyFormatOptions {
|
||||
template<typename OutputStream, typename SourceEncoding = UTF8<>, typename TargetEncoding = UTF8<>, typename StackAllocator = CrtAllocator, unsigned writeFlags = kWriteDefaultFlags>
|
||||
class PrettyWriter : public Writer<OutputStream, SourceEncoding, TargetEncoding, StackAllocator, writeFlags> {
|
||||
public:
|
||||
typedef Writer<OutputStream, SourceEncoding, TargetEncoding, StackAllocator> Base;
|
||||
typedef Writer<OutputStream, SourceEncoding, TargetEncoding, StackAllocator, writeFlags> Base;
|
||||
typedef typename Base::Ch Ch;
|
||||
|
||||
//! Constructor
|
||||
@ -57,6 +62,11 @@ public:
|
||||
explicit PrettyWriter(StackAllocator* allocator = 0, size_t levelDepth = Base::kDefaultLevelDepth) :
|
||||
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.
|
||||
/*! \param indentChar Character for indentation. Must be whitespace character (' ', '\\t', '\\n', '\\r').
|
||||
\param indentCharCount Number of indent characters for each indentation level.
|
||||
@ -82,24 +92,26 @@ public:
|
||||
*/
|
||||
//@{
|
||||
|
||||
bool Null() { PrettyPrefix(kNullType); return Base::WriteNull(); }
|
||||
bool Bool(bool b) { PrettyPrefix(b ? kTrueType : kFalseType); return Base::WriteBool(b); }
|
||||
bool Int(int i) { PrettyPrefix(kNumberType); return Base::WriteInt(i); }
|
||||
bool Uint(unsigned u) { PrettyPrefix(kNumberType); return Base::WriteUint(u); }
|
||||
bool Int64(int64_t i64) { PrettyPrefix(kNumberType); return Base::WriteInt64(i64); }
|
||||
bool Uint64(uint64_t u64) { PrettyPrefix(kNumberType); return Base::WriteUint64(u64); }
|
||||
bool Double(double d) { PrettyPrefix(kNumberType); return Base::WriteDouble(d); }
|
||||
bool Null() { PrettyPrefix(kNullType); return Base::EndValue(Base::WriteNull()); }
|
||||
bool Bool(bool b) { PrettyPrefix(b ? kTrueType : kFalseType); return Base::EndValue(Base::WriteBool(b)); }
|
||||
bool Int(int i) { PrettyPrefix(kNumberType); return Base::EndValue(Base::WriteInt(i)); }
|
||||
bool Uint(unsigned u) { PrettyPrefix(kNumberType); return Base::EndValue(Base::WriteUint(u)); }
|
||||
bool Int64(int64_t i64) { PrettyPrefix(kNumberType); return Base::EndValue(Base::WriteInt64(i64)); }
|
||||
bool Uint64(uint64_t u64) { PrettyPrefix(kNumberType); return Base::EndValue(Base::WriteUint64(u64)); }
|
||||
bool Double(double d) { PrettyPrefix(kNumberType); return Base::EndValue(Base::WriteDouble(d)); }
|
||||
|
||||
bool RawNumber(const Ch* str, SizeType length, bool copy = false) {
|
||||
CEREAL_RAPIDJSON_ASSERT(str != 0);
|
||||
(void)copy;
|
||||
PrettyPrefix(kNumberType);
|
||||
return Base::WriteString(str, length);
|
||||
return Base::EndValue(Base::WriteString(str, length));
|
||||
}
|
||||
|
||||
bool String(const Ch* str, SizeType length, bool copy = false) {
|
||||
CEREAL_RAPIDJSON_ASSERT(str != 0);
|
||||
(void)copy;
|
||||
PrettyPrefix(kStringType);
|
||||
return Base::WriteString(str, length);
|
||||
return Base::EndValue(Base::WriteString(str, length));
|
||||
}
|
||||
|
||||
#if CEREAL_RAPIDJSON_HAS_STDSTRING
|
||||
@ -124,19 +136,21 @@ public:
|
||||
|
||||
bool EndObject(SizeType memberCount = 0) {
|
||||
(void)memberCount;
|
||||
CEREAL_RAPIDJSON_ASSERT(Base::level_stack_.GetSize() >= sizeof(typename Base::Level));
|
||||
CEREAL_RAPIDJSON_ASSERT(!Base::level_stack_.template Top<typename Base::Level>()->inArray);
|
||||
CEREAL_RAPIDJSON_ASSERT(Base::level_stack_.GetSize() >= sizeof(typename Base::Level)); // not inside an Object
|
||||
CEREAL_RAPIDJSON_ASSERT(!Base::level_stack_.template Top<typename Base::Level>()->inArray); // currently inside an Array, not Object
|
||||
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;
|
||||
|
||||
if (!empty) {
|
||||
Base::os_->Put('\n');
|
||||
WriteIndent();
|
||||
}
|
||||
bool ret = Base::WriteEndObject();
|
||||
bool ret = Base::EndValue(Base::WriteEndObject());
|
||||
(void)ret;
|
||||
CEREAL_RAPIDJSON_ASSERT(ret == true);
|
||||
if (Base::level_stack_.Empty()) // end of json text
|
||||
Base::os_->Flush();
|
||||
Base::Flush();
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -156,11 +170,11 @@ public:
|
||||
Base::os_->Put('\n');
|
||||
WriteIndent();
|
||||
}
|
||||
bool ret = Base::WriteEndArray();
|
||||
bool ret = Base::EndValue(Base::WriteEndArray());
|
||||
(void)ret;
|
||||
CEREAL_RAPIDJSON_ASSERT(ret == true);
|
||||
if (Base::level_stack_.Empty()) // end of json text
|
||||
Base::os_->Flush();
|
||||
Base::Flush();
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -184,7 +198,11 @@ public:
|
||||
\param type Type of the root of json.
|
||||
\note When using PrettyWriter::RawValue(), the result json may not be indented correctly.
|
||||
*/
|
||||
bool RawValue(const Ch* json, size_t length, Type type) { PrettyPrefix(type); return Base::WriteRawValue(json, length); }
|
||||
bool RawValue(const Ch* json, size_t length, Type type) {
|
||||
CEREAL_RAPIDJSON_ASSERT(json != 0);
|
||||
PrettyPrefix(type);
|
||||
return Base::EndValue(Base::WriteRawValue(json, length));
|
||||
}
|
||||
|
||||
protected:
|
||||
void PrettyPrefix(Type type) {
|
||||
@ -233,7 +251,7 @@ protected:
|
||||
|
||||
void WriteIndent() {
|
||||
size_t count = (Base::level_stack_.GetSize() / sizeof(typename Base::Level)) * indentCharCount_;
|
||||
PutN(*Base::os_, static_cast<typename TargetEncoding::Ch>(indentChar_), count);
|
||||
PutN(*Base::os_, static_cast<typename OutputStream::Ch>(indentChar_), count);
|
||||
}
|
||||
|
||||
Ch indentChar_;
|
||||
@ -248,6 +266,10 @@ private:
|
||||
|
||||
CEREAL_RAPIDJSON_NAMESPACE_END
|
||||
|
||||
#if defined(__clang__)
|
||||
CEREAL_RAPIDJSON_DIAG_POP
|
||||
#endif
|
||||
|
||||
#ifdef __GNUC__
|
||||
CEREAL_RAPIDJSON_DIAG_POP
|
||||
#endif
|
||||
|
113
include/cereal/external/rapidjson/rapidjson.h
vendored
113
include/cereal/external/rapidjson/rapidjson.h
vendored
@ -26,7 +26,7 @@
|
||||
|
||||
Some RapidJSON features are configurable to adapt the library to a wide
|
||||
variety of platforms, environments and usage scenarios. Most of the
|
||||
features can be configured in terms of overriden or predefined
|
||||
features can be configured in terms of overridden or predefined
|
||||
preprocessor macros at compile-time.
|
||||
|
||||
Some additional customization is available in the \ref CEREAL_RAPIDJSON_ERRORS APIs.
|
||||
@ -49,6 +49,11 @@
|
||||
// token stringification
|
||||
#define CEREAL_RAPIDJSON_STRINGIFY(x) CEREAL_RAPIDJSON_DO_STRINGIFY(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
|
||||
|
||||
/*! \def CEREAL_RAPIDJSON_MAJOR_VERSION
|
||||
@ -68,8 +73,8 @@
|
||||
\brief Version of RapidJSON in "<major>.<minor>.<patch>" string format.
|
||||
*/
|
||||
#define CEREAL_RAPIDJSON_MAJOR_VERSION 1
|
||||
#define CEREAL_RAPIDJSON_MINOR_VERSION 0
|
||||
#define CEREAL_RAPIDJSON_PATCH_VERSION 2
|
||||
#define CEREAL_RAPIDJSON_MINOR_VERSION 1
|
||||
#define CEREAL_RAPIDJSON_PATCH_VERSION 0
|
||||
#define CEREAL_RAPIDJSON_VERSION_STRING \
|
||||
CEREAL_RAPIDJSON_STRINGIFY(CEREAL_RAPIDJSON_MAJOR_VERSION.CEREAL_RAPIDJSON_MINOR_VERSION.CEREAL_RAPIDJSON_PATCH_VERSION)
|
||||
|
||||
@ -214,7 +219,7 @@
|
||||
# elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
|
||||
# define CEREAL_RAPIDJSON_ENDIAN CEREAL_RAPIDJSON_BIGENDIAN
|
||||
# else
|
||||
# error Unknown machine endianess detected. User needs to define CEREAL_RAPIDJSON_ENDIAN.
|
||||
# error Unknown machine endianness detected. User needs to define CEREAL_RAPIDJSON_ENDIAN.
|
||||
# endif // __BYTE_ORDER__
|
||||
// Detect with GLIBC's endian.h
|
||||
# elif defined(__GLIBC__)
|
||||
@ -224,7 +229,7 @@
|
||||
# elif (__BYTE_ORDER == __BIG_ENDIAN)
|
||||
# define CEREAL_RAPIDJSON_ENDIAN CEREAL_RAPIDJSON_BIGENDIAN
|
||||
# else
|
||||
# error Unknown machine endianess detected. User needs to define CEREAL_RAPIDJSON_ENDIAN.
|
||||
# error Unknown machine endianness detected. User needs to define CEREAL_RAPIDJSON_ENDIAN.
|
||||
# endif // __GLIBC__
|
||||
// Detect with _LITTLE_ENDIAN and _BIG_ENDIAN macro
|
||||
# elif defined(_LITTLE_ENDIAN) && !defined(_BIG_ENDIAN)
|
||||
@ -236,12 +241,12 @@
|
||||
# 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__)
|
||||
# define CEREAL_RAPIDJSON_ENDIAN CEREAL_RAPIDJSON_LITTLEENDIAN
|
||||
# elif defined(_MSC_VER) && defined(_M_ARM)
|
||||
# elif defined(_MSC_VER) && (defined(_M_ARM) || defined(_M_ARM64))
|
||||
# define CEREAL_RAPIDJSON_ENDIAN CEREAL_RAPIDJSON_LITTLEENDIAN
|
||||
# elif defined(CEREAL_RAPIDJSON_DOXYGEN_RUNNING)
|
||||
# define CEREAL_RAPIDJSON_ENDIAN
|
||||
# else
|
||||
# error Unknown machine endianess detected. User needs to define CEREAL_RAPIDJSON_ENDIAN.
|
||||
# error Unknown machine endianness detected. User needs to define CEREAL_RAPIDJSON_ENDIAN.
|
||||
# endif
|
||||
#endif // CEREAL_RAPIDJSON_ENDIAN
|
||||
|
||||
@ -264,16 +269,11 @@
|
||||
/*! \ingroup CEREAL_RAPIDJSON_CONFIG
|
||||
\param x pointer to align
|
||||
|
||||
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.
|
||||
Some machines require strict data alignment. The default is 8 bytes.
|
||||
User can customize by defining the CEREAL_RAPIDJSON_ALIGN function macro.
|
||||
*/
|
||||
#ifndef CEREAL_RAPIDJSON_ALIGN
|
||||
#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
|
||||
#define CEREAL_RAPIDJSON_ALIGN(x) (((x) + static_cast<size_t>(7u)) & ~static_cast<size_t>(7u))
|
||||
#endif
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
@ -320,17 +320,17 @@
|
||||
#endif
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// CEREAL_RAPIDJSON_SSE2/CEREAL_RAPIDJSON_SSE42/CEREAL_RAPIDJSON_SIMD
|
||||
// CEREAL_RAPIDJSON_SSE2/CEREAL_RAPIDJSON_SSE42/CEREAL_RAPIDJSON_NEON/CEREAL_RAPIDJSON_SIMD
|
||||
|
||||
/*! \def CEREAL_RAPIDJSON_SIMD
|
||||
\ingroup CEREAL_RAPIDJSON_CONFIG
|
||||
\brief Enable SSE2/SSE4.2 optimization.
|
||||
\brief Enable SSE2/SSE4.2/Neon optimization.
|
||||
|
||||
RapidJSON supports optimized implementations for some parsing operations
|
||||
based on the SSE2 or SSE4.2 SIMD extensions on modern Intel-compatible
|
||||
processors.
|
||||
based on the SSE2, SSE4.2 or NEon SIMD extensions on modern Intel
|
||||
or ARM compatible processors.
|
||||
|
||||
To enable these optimizations, two different symbols can be defined;
|
||||
To enable these optimizations, three different symbols can be defined;
|
||||
\code
|
||||
// Enable SSE2 optimization.
|
||||
#define CEREAL_RAPIDJSON_SSE2
|
||||
@ -339,13 +339,17 @@
|
||||
#define CEREAL_RAPIDJSON_SSE42
|
||||
\endcode
|
||||
|
||||
\c CEREAL_RAPIDJSON_SSE42 takes precedence, if both are defined.
|
||||
// Enable ARM Neon optimization.
|
||||
#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
|
||||
\c CEREAL_RAPIDJSON_SIMD to indicate the availability of the optimized code.
|
||||
*/
|
||||
#if defined(CEREAL_RAPIDJSON_SSE2) || defined(CEREAL_RAPIDJSON_SSE42) \
|
||||
|| defined(CEREAL_RAPIDJSON_DOXYGEN_RUNNING)
|
||||
|| defined(CEREAL_RAPIDJSON_NEON) || defined(CEREAL_RAPIDJSON_DOXYGEN_RUNNING)
|
||||
#define CEREAL_RAPIDJSON_SIMD
|
||||
#endif
|
||||
|
||||
@ -405,7 +409,15 @@ CEREAL_RAPIDJSON_NAMESPACE_END
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// CEREAL_RAPIDJSON_STATIC_ASSERT
|
||||
|
||||
// Adopt from boost
|
||||
// Prefer C++11 static_assert, if available
|
||||
#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 __clang__
|
||||
//!@cond CEREAL_RAPIDJSON_HIDDEN_FROM_DOXYGEN
|
||||
@ -413,14 +425,10 @@ CEREAL_RAPIDJSON_NAMESPACE_END
|
||||
CEREAL_RAPIDJSON_NAMESPACE_BEGIN
|
||||
template <bool x> struct STATIC_ASSERTION_FAILURE;
|
||||
template <> struct STATIC_ASSERTION_FAILURE<true> { enum { value = 1 }; };
|
||||
template<int x> struct StaticAssertTest {};
|
||||
template <size_t x> struct StaticAssertTest {};
|
||||
CEREAL_RAPIDJSON_NAMESPACE_END
|
||||
|
||||
#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__)
|
||||
#if defined(__GNUC__) || defined(__clang__)
|
||||
#define CEREAL_RAPIDJSON_STATIC_ASSERT_UNUSED_ATTRIBUTE __attribute__((unused))
|
||||
#else
|
||||
#define CEREAL_RAPIDJSON_STATIC_ASSERT_UNUSED_ATTRIBUTE
|
||||
@ -438,7 +446,7 @@ CEREAL_RAPIDJSON_NAMESPACE_END
|
||||
typedef ::CEREAL_RAPIDJSON_NAMESPACE::StaticAssertTest< \
|
||||
sizeof(::CEREAL_RAPIDJSON_NAMESPACE::STATIC_ASSERTION_FAILURE<bool(x) >)> \
|
||||
CEREAL_RAPIDJSON_JOIN(StaticAssertTypedef, __LINE__) CEREAL_RAPIDJSON_STATIC_ASSERT_UNUSED_ATTRIBUTE
|
||||
#endif
|
||||
#endif // CEREAL_RAPIDJSON_STATIC_ASSERT
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// CEREAL_RAPIDJSON_LIKELY, CEREAL_RAPIDJSON_UNLIKELY
|
||||
@ -530,13 +538,14 @@ CEREAL_RAPIDJSON_NAMESPACE_END
|
||||
#ifndef CEREAL_RAPIDJSON_HAS_CXX11_RVALUE_REFS
|
||||
#if defined(__clang__)
|
||||
#if __has_feature(cxx_rvalue_references) && \
|
||||
(defined(_LIBCPP_VERSION) || defined(__GLIBCXX__) && __GLIBCXX__ >= 20080306)
|
||||
(defined(_MSC_VER) || defined(_LIBCPP_VERSION) || defined(__GLIBCXX__) && __GLIBCXX__ >= 20080306)
|
||||
#define CEREAL_RAPIDJSON_HAS_CXX11_RVALUE_REFS 1
|
||||
#else
|
||||
#define CEREAL_RAPIDJSON_HAS_CXX11_RVALUE_REFS 0
|
||||
#endif
|
||||
#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
|
||||
#else
|
||||
@ -547,8 +556,9 @@ CEREAL_RAPIDJSON_NAMESPACE_END
|
||||
#ifndef CEREAL_RAPIDJSON_HAS_CXX11_NOEXCEPT
|
||||
#if defined(__clang__)
|
||||
#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__))
|
||||
// (defined(_MSC_VER) && _MSC_VER >= ????) // not yet supported
|
||||
#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(__SUNPRO_CC) && __SUNPRO_CC >= 0x5140 && defined(__GXX_EXPERIMENTAL_CXX0X__))
|
||||
#define CEREAL_RAPIDJSON_HAS_CXX11_NOEXCEPT 1
|
||||
#else
|
||||
#define CEREAL_RAPIDJSON_HAS_CXX11_NOEXCEPT 0
|
||||
@ -562,14 +572,19 @@ CEREAL_RAPIDJSON_NAMESPACE_END
|
||||
|
||||
// no automatic detection, yet
|
||||
#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
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef CEREAL_RAPIDJSON_HAS_CXX11_RANGE_FOR
|
||||
#if defined(__clang__)
|
||||
#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,3,0)) && defined(__GXX_EXPERIMENTAL_CXX0X__)) || \
|
||||
(defined(_MSC_VER) && _MSC_VER >= 1700)
|
||||
#elif (defined(CEREAL_RAPIDJSON_GNUC) && (CEREAL_RAPIDJSON_GNUC >= CEREAL_RAPIDJSON_VERSION_CODE(4,6,0)) && defined(__GXX_EXPERIMENTAL_CXX0X__)) || \
|
||||
(defined(_MSC_VER) && _MSC_VER >= 1700) || \
|
||||
(defined(__SUNPRO_CC) && __SUNPRO_CC >= 0x5140 && defined(__GXX_EXPERIMENTAL_CXX0X__))
|
||||
#define CEREAL_RAPIDJSON_HAS_CXX11_RANGE_FOR 1
|
||||
#else
|
||||
#define CEREAL_RAPIDJSON_HAS_CXX11_RANGE_FOR 0
|
||||
@ -578,12 +593,38 @@ CEREAL_RAPIDJSON_NAMESPACE_END
|
||||
|
||||
//!@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
|
||||
|
||||
#ifndef CEREAL_RAPIDJSON_NEW
|
||||
///! customization point for global \c new
|
||||
#define CEREAL_RAPIDJSON_NEW(x) new x
|
||||
#define CEREAL_RAPIDJSON_NEW(TypeName) new TypeName
|
||||
#endif
|
||||
#ifndef CEREAL_RAPIDJSON_DELETE
|
||||
///! customization point for global \c delete
|
||||
|
599
include/cereal/external/rapidjson/reader.h
vendored
599
include/cereal/external/rapidjson/reader.h
vendored
@ -33,12 +33,8 @@
|
||||
#include <nmmintrin.h>
|
||||
#elif defined(CEREAL_RAPIDJSON_SSE2)
|
||||
#include <emmintrin.h>
|
||||
#endif
|
||||
|
||||
#ifdef _MSC_VER
|
||||
CEREAL_RAPIDJSON_DIAG_PUSH
|
||||
CEREAL_RAPIDJSON_DIAG_OFF(4127) // conditional expression is constant
|
||||
CEREAL_RAPIDJSON_DIAG_OFF(4702) // unreachable code
|
||||
#elif defined(CEREAL_RAPIDJSON_NEON)
|
||||
#include <arm_neon.h>
|
||||
#endif
|
||||
|
||||
#ifdef __clang__
|
||||
@ -46,6 +42,10 @@ CEREAL_RAPIDJSON_DIAG_PUSH
|
||||
CEREAL_RAPIDJSON_DIAG_OFF(old-style-cast)
|
||||
CEREAL_RAPIDJSON_DIAG_OFF(padded)
|
||||
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
|
||||
|
||||
#ifdef __GNUC__
|
||||
@ -299,16 +299,9 @@ inline const char *SkipWhitespace_SIMD(const char* p) {
|
||||
|
||||
for (;; p += 16) {
|
||||
const __m128i s = _mm_load_si128(reinterpret_cast<const __m128i *>(p));
|
||||
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 != 0) { // some of characters is non-whitespace
|
||||
#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
|
||||
}
|
||||
const int r = _mm_cmpistri(w, s, _SIDD_UBYTE_OPS | _SIDD_CMP_EQUAL_ANY | _SIDD_LEAST_SIGNIFICANT | _SIDD_NEGATIVE_POLARITY);
|
||||
if (r != 16) // some of characters is non-whitespace
|
||||
return p + r;
|
||||
}
|
||||
}
|
||||
|
||||
@ -325,16 +318,9 @@ inline const char *SkipWhitespace_SIMD(const char* p, const char* end) {
|
||||
|
||||
for (; p <= end - 16; p += 16) {
|
||||
const __m128i s = _mm_loadu_si128(reinterpret_cast<const __m128i *>(p));
|
||||
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 != 0) { // some of characters is non-whitespace
|
||||
#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
|
||||
}
|
||||
const int r = _mm_cmpistri(w, s, _SIDD_UBYTE_OPS | _SIDD_CMP_EQUAL_ANY | _SIDD_LEAST_SIGNIFICANT | _SIDD_NEGATIVE_POLARITY);
|
||||
if (r != 16) // some of characters is non-whitespace
|
||||
return p + r;
|
||||
}
|
||||
|
||||
return SkipWhitespace(p, end);
|
||||
@ -425,7 +411,92 @@ inline const char *SkipWhitespace_SIMD(const char* p, const char* end) {
|
||||
return SkipWhitespace(p, end);
|
||||
}
|
||||
|
||||
#endif // CEREAL_RAPIDJSON_SSE2
|
||||
#elif defined(CEREAL_RAPIDJSON_NEON)
|
||||
|
||||
//! 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
|
||||
//! Template function specialization for InsituStringStream
|
||||
@ -471,7 +542,8 @@ public:
|
||||
/*! \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)
|
||||
*/
|
||||
GenericReader(StackAllocator* stackAllocator = 0, size_t stackCapacity = kDefaultStackCapacity) : stack_(stackAllocator, stackCapacity), parseResult_() {}
|
||||
GenericReader(StackAllocator* stackAllocator = 0, size_t stackCapacity = kDefaultStackCapacity) :
|
||||
stack_(stackAllocator, stackCapacity), parseResult_(), state_(IterativeParsingStartState) {}
|
||||
|
||||
//! Parse JSON text.
|
||||
/*! \tparam parseFlags Combination of \ref ParseFlag.
|
||||
@ -527,7 +599,84 @@ public:
|
||||
return Parse<kParseDefaultFlags>(is, handler);
|
||||
}
|
||||
|
||||
//! Whether a parse error has occured in the last parsing.
|
||||
//! Initialize JSON text token-by-token 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(); }
|
||||
|
||||
//! Get the \ref ParseErrorCode of last parsing.
|
||||
@ -575,7 +724,7 @@ private:
|
||||
}
|
||||
}
|
||||
else if (CEREAL_RAPIDJSON_LIKELY(Consume(is, '/')))
|
||||
while (is.Peek() != '\0' && is.Take() != '\n');
|
||||
while (is.Peek() != '\0' && is.Take() != '\n') {}
|
||||
else
|
||||
CEREAL_RAPIDJSON_PARSE_ERROR(kParseErrorUnspecificSyntaxError, is.Tell());
|
||||
|
||||
@ -750,7 +899,7 @@ private:
|
||||
return false;
|
||||
}
|
||||
|
||||
// Helper function to parse four hexidecimal digits in \uXXXX in ParseString().
|
||||
// Helper function to parse four hexadecimal digits in \uXXXX in ParseString().
|
||||
template<typename InputStream>
|
||||
unsigned ParseHex4(InputStream& is, size_t escapeOffset) {
|
||||
unsigned codepoint = 0;
|
||||
@ -857,7 +1006,7 @@ private:
|
||||
|
||||
Ch c = is.Peek();
|
||||
if (CEREAL_RAPIDJSON_UNLIKELY(c == '\\')) { // Escape
|
||||
size_t escapeOffset = is.Tell(); // For invalid escaping, report the inital '\\' as error offset
|
||||
size_t escapeOffset = is.Tell(); // For invalid escaping, report the initial '\\' as error offset
|
||||
is.Take();
|
||||
Ch e = is.Peek();
|
||||
if ((sizeof(Ch) == 1 || unsigned(e) < 256) && CEREAL_RAPIDJSON_LIKELY(escape[static_cast<unsigned char>(e)])) {
|
||||
@ -892,7 +1041,7 @@ private:
|
||||
if (c == '\0')
|
||||
CEREAL_RAPIDJSON_PARSE_ERROR(kParseErrorStringMissQuotationMark, is.Tell());
|
||||
else
|
||||
CEREAL_RAPIDJSON_PARSE_ERROR(kParseErrorStringEscapeInvalid, is.Tell());
|
||||
CEREAL_RAPIDJSON_PARSE_ERROR(kParseErrorStringInvalidEncoding, is.Tell());
|
||||
}
|
||||
else {
|
||||
size_t offset = is.Tell();
|
||||
@ -927,7 +1076,7 @@ private:
|
||||
// The rest of string using SIMD
|
||||
static const char dquote[16] = { '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"' };
|
||||
static const char bslash[16] = { '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\' };
|
||||
static const char space[16] = { 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19 };
|
||||
static const char space[16] = { 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F };
|
||||
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 sp = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&space[0]));
|
||||
@ -936,7 +1085,7 @@ private:
|
||||
const __m128i s = _mm_load_si128(reinterpret_cast<const __m128i *>(p));
|
||||
const __m128i t1 = _mm_cmpeq_epi8(s, dq);
|
||||
const __m128i t2 = _mm_cmpeq_epi8(s, bs);
|
||||
const __m128i t3 = _mm_cmpeq_epi8(_mm_max_epu8(s, sp), sp); // s < 0x20 <=> max(s, 0x19) == 0x19
|
||||
const __m128i t3 = _mm_cmpeq_epi8(_mm_max_epu8(s, sp), sp); // s < 0x20 <=> max(s, 0x1F) == 0x1F
|
||||
const __m128i x = _mm_or_si128(_mm_or_si128(t1, t2), t3);
|
||||
unsigned short r = static_cast<unsigned short>(_mm_movemask_epi8(x));
|
||||
if (CEREAL_RAPIDJSON_UNLIKELY(r != 0)) { // some of characters is escaped
|
||||
@ -948,11 +1097,13 @@ private:
|
||||
#else
|
||||
length = static_cast<SizeType>(__builtin_ffs(r) - 1);
|
||||
#endif
|
||||
char* q = reinterpret_cast<char*>(os.Push(length));
|
||||
for (size_t i = 0; i < length; i++)
|
||||
q[i] = p[i];
|
||||
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;
|
||||
p += length;
|
||||
}
|
||||
break;
|
||||
}
|
||||
_mm_storeu_si128(reinterpret_cast<__m128i *>(os.Push(16)), s);
|
||||
@ -988,7 +1139,7 @@ private:
|
||||
// The rest of string using SIMD
|
||||
static const char dquote[16] = { '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"' };
|
||||
static const char bslash[16] = { '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\' };
|
||||
static const char space[16] = { 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19 };
|
||||
static const char space[16] = { 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F };
|
||||
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 sp = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&space[0]));
|
||||
@ -997,7 +1148,7 @@ private:
|
||||
const __m128i s = _mm_load_si128(reinterpret_cast<const __m128i *>(p));
|
||||
const __m128i t1 = _mm_cmpeq_epi8(s, dq);
|
||||
const __m128i t2 = _mm_cmpeq_epi8(s, bs);
|
||||
const __m128i t3 = _mm_cmpeq_epi8(_mm_max_epu8(s, sp), sp); // s < 0x20 <=> max(s, 0x19) == 0x19
|
||||
const __m128i t3 = _mm_cmpeq_epi8(_mm_max_epu8(s, sp), sp); // s < 0x20 <=> max(s, 0x1F) == 0x1F
|
||||
const __m128i x = _mm_or_si128(_mm_or_si128(t1, t2), t3);
|
||||
unsigned short r = static_cast<unsigned short>(_mm_movemask_epi8(x));
|
||||
if (CEREAL_RAPIDJSON_UNLIKELY(r != 0)) { // some of characters is escaped
|
||||
@ -1036,7 +1187,7 @@ private:
|
||||
// The rest of string using SIMD
|
||||
static const char dquote[16] = { '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"' };
|
||||
static const char bslash[16] = { '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\' };
|
||||
static const char space[16] = { 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19 };
|
||||
static const char space[16] = { 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F };
|
||||
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 sp = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&space[0]));
|
||||
@ -1045,7 +1196,7 @@ private:
|
||||
const __m128i s = _mm_load_si128(reinterpret_cast<const __m128i *>(p));
|
||||
const __m128i t1 = _mm_cmpeq_epi8(s, dq);
|
||||
const __m128i t2 = _mm_cmpeq_epi8(s, bs);
|
||||
const __m128i t3 = _mm_cmpeq_epi8(_mm_max_epu8(s, sp), sp); // s < 0x20 <=> max(s, 0x19) == 0x19
|
||||
const __m128i t3 = _mm_cmpeq_epi8(_mm_max_epu8(s, sp), sp); // s < 0x20 <=> max(s, 0x1F) == 0x1F
|
||||
const __m128i x = _mm_or_si128(_mm_or_si128(t1, t2), t3);
|
||||
unsigned short r = static_cast<unsigned short>(_mm_movemask_epi8(x));
|
||||
if (CEREAL_RAPIDJSON_UNLIKELY(r != 0)) { // some of characters is escaped
|
||||
@ -1064,7 +1215,180 @@ private:
|
||||
|
||||
is.src_ = is.dst_ = p;
|
||||
}
|
||||
#endif
|
||||
#elif defined(CEREAL_RAPIDJSON_NEON)
|
||||
// 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>
|
||||
class NumberStream;
|
||||
@ -1075,7 +1399,6 @@ private:
|
||||
typedef typename InputStream::Ch Ch;
|
||||
|
||||
NumberStream(GenericReader& reader, InputStream& s) : is(s) { (void)reader; }
|
||||
~NumberStream() {}
|
||||
|
||||
CEREAL_RAPIDJSON_FORCEINLINE Ch Peek() const { return is.Peek(); }
|
||||
CEREAL_RAPIDJSON_FORCEINLINE Ch TakePush() { return is.Take(); }
|
||||
@ -1097,7 +1420,6 @@ private:
|
||||
typedef NumberStream<InputStream, false, false> Base;
|
||||
public:
|
||||
NumberStream(GenericReader& reader, InputStream& s) : Base(reader, s), stackStream(reader.stack_) {}
|
||||
~NumberStream() {}
|
||||
|
||||
CEREAL_RAPIDJSON_FORCEINLINE Ch TakePush() {
|
||||
stackStream.Put(static_cast<char>(Base::is.Peek()));
|
||||
@ -1124,7 +1446,6 @@ private:
|
||||
typedef NumberStream<InputStream, true, false> Base;
|
||||
public:
|
||||
NumberStream(GenericReader& reader, InputStream& is) : Base(reader, is) {}
|
||||
~NumberStream() {}
|
||||
|
||||
CEREAL_RAPIDJSON_FORCEINLINE Ch Take() { return Base::TakePush(); }
|
||||
};
|
||||
@ -1185,18 +1506,27 @@ private:
|
||||
}
|
||||
// Parse NaN or Infinity here
|
||||
else if ((parseFlags & kParseNanAndInfFlag) && CEREAL_RAPIDJSON_LIKELY((s.Peek() == 'I' || s.Peek() == 'N'))) {
|
||||
useNanOrInf = true;
|
||||
if (CEREAL_RAPIDJSON_LIKELY(Consume(s, 'N') && Consume(s, 'a') && Consume(s, 'N'))) {
|
||||
d = std::numeric_limits<double>::quiet_NaN();
|
||||
if (Consume(s, 'N')) {
|
||||
if (Consume(s, 'a') && Consume(s, 'N')) {
|
||||
d = std::numeric_limits<double>::quiet_NaN();
|
||||
useNanOrInf = true;
|
||||
}
|
||||
}
|
||||
else if (CEREAL_RAPIDJSON_LIKELY(Consume(s, 'I') && Consume(s, 'n') && Consume(s, 'f'))) {
|
||||
d = (minus ? -std::numeric_limits<double>::infinity() : std::numeric_limits<double>::infinity());
|
||||
if (CEREAL_RAPIDJSON_UNLIKELY(s.Peek() == 'i' && !(Consume(s, 'i') && Consume(s, 'n')
|
||||
&& Consume(s, 'i') && Consume(s, 't') && Consume(s, 'y'))))
|
||||
CEREAL_RAPIDJSON_PARSE_ERROR(kParseErrorValueInvalid, s.Tell());
|
||||
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());
|
||||
useNanOrInf = true;
|
||||
|
||||
if (CEREAL_RAPIDJSON_UNLIKELY(s.Peek() == 'i' && !(Consume(s, 'i') && Consume(s, 'n')
|
||||
&& Consume(s, 'i') && Consume(s, 't') && Consume(s, 'y')))) {
|
||||
CEREAL_RAPIDJSON_PARSE_ERROR(kParseErrorValueInvalid, s.Tell());
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
|
||||
if (CEREAL_RAPIDJSON_UNLIKELY(!useNanOrInf)) {
|
||||
CEREAL_RAPIDJSON_PARSE_ERROR(kParseErrorValueInvalid, s.Tell());
|
||||
}
|
||||
}
|
||||
else
|
||||
CEREAL_RAPIDJSON_PARSE_ERROR(kParseErrorValueInvalid, s.Tell());
|
||||
@ -1231,8 +1561,6 @@ private:
|
||||
// Force double for big integer
|
||||
if (useDouble) {
|
||||
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');
|
||||
}
|
||||
}
|
||||
@ -1302,9 +1630,18 @@ private:
|
||||
if (CEREAL_RAPIDJSON_LIKELY(s.Peek() >= '0' && s.Peek() <= '9')) {
|
||||
exp = static_cast<int>(s.Take() - '0');
|
||||
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')) {
|
||||
exp = exp * 10 + static_cast<int>(s.Take() - '0');
|
||||
if (exp >= 214748364) { // Issue #313: prevent overflow exponent
|
||||
if (CEREAL_RAPIDJSON_UNLIKELY(exp > maxExp)) {
|
||||
while (CEREAL_RAPIDJSON_UNLIKELY(s.Peek() >= '0' && s.Peek() <= '9')) // Consume the rest of exponent
|
||||
s.Take();
|
||||
}
|
||||
@ -1363,6 +1700,13 @@ private:
|
||||
else
|
||||
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);
|
||||
}
|
||||
else if (useNanOrInf) {
|
||||
@ -1408,29 +1752,31 @@ private:
|
||||
|
||||
// States
|
||||
enum IterativeParsingState {
|
||||
IterativeParsingStartState = 0,
|
||||
IterativeParsingFinishState,
|
||||
IterativeParsingErrorState,
|
||||
IterativeParsingFinishState = 0, // sink states at top
|
||||
IterativeParsingErrorState, // sink states at top
|
||||
IterativeParsingStartState,
|
||||
|
||||
// Object states
|
||||
IterativeParsingObjectInitialState,
|
||||
IterativeParsingMemberKeyState,
|
||||
IterativeParsingKeyValueDelimiterState,
|
||||
IterativeParsingMemberValueState,
|
||||
IterativeParsingMemberDelimiterState,
|
||||
IterativeParsingObjectFinishState,
|
||||
|
||||
// Array states
|
||||
IterativeParsingArrayInitialState,
|
||||
IterativeParsingElementState,
|
||||
IterativeParsingElementDelimiterState,
|
||||
IterativeParsingArrayFinishState,
|
||||
|
||||
// Single value state
|
||||
IterativeParsingValueState
|
||||
};
|
||||
IterativeParsingValueState,
|
||||
|
||||
enum { cIterativeParsingStateCount = IterativeParsingValueState + 1 };
|
||||
// Delimiter states (at bottom)
|
||||
IterativeParsingElementDelimiterState,
|
||||
IterativeParsingMemberDelimiterState,
|
||||
IterativeParsingKeyValueDelimiterState,
|
||||
|
||||
cIterativeParsingStateCount
|
||||
};
|
||||
|
||||
// Tokens
|
||||
enum Token {
|
||||
@ -1452,7 +1798,7 @@ private:
|
||||
kTokenCount
|
||||
};
|
||||
|
||||
CEREAL_RAPIDJSON_FORCEINLINE Token Tokenize(Ch c) {
|
||||
CEREAL_RAPIDJSON_FORCEINLINE Token Tokenize(Ch c) const {
|
||||
|
||||
//!@cond CEREAL_RAPIDJSON_HIDDEN_FROM_DOXYGEN
|
||||
#define N NumberToken
|
||||
@ -1479,9 +1825,21 @@ private:
|
||||
return NumberToken;
|
||||
}
|
||||
|
||||
CEREAL_RAPIDJSON_FORCEINLINE IterativeParsingState Predict(IterativeParsingState state, Token token) {
|
||||
CEREAL_RAPIDJSON_FORCEINLINE IterativeParsingState Predict(IterativeParsingState state, Token token) const {
|
||||
// current state x one lookahead token -> new state
|
||||
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
|
||||
{
|
||||
IterativeParsingArrayInitialState, // Left bracket
|
||||
@ -1496,18 +1854,6 @@ private:
|
||||
IterativeParsingValueState, // Null
|
||||
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
|
||||
{
|
||||
IterativeParsingErrorState, // Left bracket
|
||||
@ -1536,20 +1882,6 @@ private:
|
||||
IterativeParsingErrorState, // Null
|
||||
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
|
||||
{
|
||||
IterativeParsingErrorState, // Left bracket
|
||||
@ -1564,20 +1896,6 @@ private:
|
||||
IterativeParsingErrorState, // Null
|
||||
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)
|
||||
{
|
||||
IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState,
|
||||
@ -1612,6 +1930,18 @@ private:
|
||||
IterativeParsingErrorState, // Null
|
||||
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
|
||||
{
|
||||
IterativeParsingArrayInitialState, // Left bracket(push Element state)
|
||||
@ -1626,18 +1956,34 @@ private:
|
||||
IterativeParsingElementState, // Null
|
||||
IterativeParsingElementState // Number
|
||||
},
|
||||
// ArrayFinish(sink state)
|
||||
// MemberDelimiter
|
||||
{
|
||||
IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState,
|
||||
IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState,
|
||||
IterativeParsingErrorState
|
||||
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
|
||||
},
|
||||
// Single Value (sink state)
|
||||
// KeyValueDelimiter
|
||||
{
|
||||
IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState,
|
||||
IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState,
|
||||
IterativeParsingErrorState
|
||||
}
|
||||
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
|
||||
},
|
||||
}; // End of G
|
||||
|
||||
return static_cast<IterativeParsingState>(G[state][token]);
|
||||
@ -1818,6 +2164,14 @@ 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>
|
||||
ParseResult IterativeParse(InputStream& is, Handler& handler) {
|
||||
parseResult_.Clear();
|
||||
@ -1856,6 +2210,7 @@ private:
|
||||
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.
|
||||
ParseResult parseResult_;
|
||||
IterativeParsingState state_;
|
||||
}; // class GenericReader
|
||||
|
||||
//! Reader with UTF8 encoding and default allocator.
|
||||
@ -1863,7 +2218,7 @@ typedef GenericReader<UTF8<>, UTF8<> > Reader;
|
||||
|
||||
CEREAL_RAPIDJSON_NAMESPACE_END
|
||||
|
||||
#ifdef __clang__
|
||||
#if defined(__clang__) || defined(_MSC_VER)
|
||||
CEREAL_RAPIDJSON_DIAG_POP
|
||||
#endif
|
||||
|
||||
@ -1872,8 +2227,4 @@ CEREAL_RAPIDJSON_DIAG_POP
|
||||
CEREAL_RAPIDJSON_DIAG_POP
|
||||
#endif
|
||||
|
||||
#ifdef _MSC_VER
|
||||
CEREAL_RAPIDJSON_DIAG_POP
|
||||
#endif
|
||||
|
||||
#endif // CEREAL_RAPIDJSON_READER_H_
|
||||
|
717
include/cereal/external/rapidjson/schema.h
vendored
717
include/cereal/external/rapidjson/schema.h
vendored
File diff suppressed because it is too large
Load Diff
52
include/cereal/external/rapidjson/stream.h
vendored
52
include/cereal/external/rapidjson/stream.h
vendored
@ -1,5 +1,5 @@
|
||||
// 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
|
||||
@ -7,9 +7,9 @@
|
||||
//
|
||||
// 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
|
||||
// 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.
|
||||
|
||||
#include "rapidjson.h"
|
||||
@ -100,6 +100,50 @@ inline void PutN(Stream& stream, Ch c, size_t n) {
|
||||
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
|
||||
|
||||
|
@ -78,8 +78,12 @@ public:
|
||||
return stack_.template Bottom<Ch>();
|
||||
}
|
||||
|
||||
//! Get the size of string in bytes in the string buffer.
|
||||
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;
|
||||
mutable internal::Stack<Allocator> stack_;
|
||||
|
||||
|
161
include/cereal/external/rapidjson/writer.h
vendored
161
include/cereal/external/rapidjson/writer.h
vendored
@ -16,6 +16,7 @@
|
||||
#define CEREAL_RAPIDJSON_WRITER_H_
|
||||
|
||||
#include "stream.h"
|
||||
#include "internal/meta.h"
|
||||
#include "internal/stack.h"
|
||||
#include "internal/strfunc.h"
|
||||
#include "internal/dtoa.h"
|
||||
@ -31,17 +32,18 @@
|
||||
#include <nmmintrin.h>
|
||||
#elif defined(CEREAL_RAPIDJSON_SSE2)
|
||||
#include <emmintrin.h>
|
||||
#endif
|
||||
|
||||
#ifdef _MSC_VER
|
||||
CEREAL_RAPIDJSON_DIAG_PUSH
|
||||
CEREAL_RAPIDJSON_DIAG_OFF(4127) // conditional expression is constant
|
||||
#elif defined(CEREAL_RAPIDJSON_NEON)
|
||||
#include <arm_neon.h>
|
||||
#endif
|
||||
|
||||
#ifdef __clang__
|
||||
CEREAL_RAPIDJSON_DIAG_PUSH
|
||||
CEREAL_RAPIDJSON_DIAG_OFF(padded)
|
||||
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
|
||||
|
||||
CEREAL_RAPIDJSON_NAMESPACE_BEGIN
|
||||
@ -63,7 +65,7 @@ CEREAL_RAPIDJSON_NAMESPACE_BEGIN
|
||||
enum WriteFlag {
|
||||
kWriteNoFlags = 0, //!< No flags are set.
|
||||
kWriteValidateEncodingFlag = 1, //!< Validate encoding of JSON strings.
|
||||
kWriteNanAndInfFlag = 2, //!< Allow writing of Inf, -Inf and NaN.
|
||||
kWriteNanAndInfFlag = 2, //!< Allow writing of Infinity, -Infinity and NaN.
|
||||
kWriteDefaultFlags = CEREAL_RAPIDJSON_WRITE_DEFAULT_FLAGS //!< Default write flags. Can be customized by defining CEREAL_RAPIDJSON_WRITE_DEFAULT_FLAGS
|
||||
};
|
||||
|
||||
@ -103,6 +105,13 @@ public:
|
||||
Writer(StackAllocator* allocator = 0, size_t levelDepth = kDefaultLevelDepth) :
|
||||
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.
|
||||
/*!
|
||||
This function reset the writer with a new stream and default settings,
|
||||
@ -184,12 +193,14 @@ public:
|
||||
bool Double(double d) { Prefix(kNumberType); return EndValue(WriteDouble(d)); }
|
||||
|
||||
bool RawNumber(const Ch* str, SizeType length, bool copy = false) {
|
||||
CEREAL_RAPIDJSON_ASSERT(str != 0);
|
||||
(void)copy;
|
||||
Prefix(kNumberType);
|
||||
return EndValue(WriteString(str, length));
|
||||
}
|
||||
|
||||
bool String(const Ch* str, SizeType length, bool copy = false) {
|
||||
CEREAL_RAPIDJSON_ASSERT(str != 0);
|
||||
(void)copy;
|
||||
Prefix(kStringType);
|
||||
return EndValue(WriteString(str, length));
|
||||
@ -209,10 +220,18 @@ public:
|
||||
|
||||
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) {
|
||||
(void)memberCount;
|
||||
CEREAL_RAPIDJSON_ASSERT(level_stack_.GetSize() >= sizeof(Level));
|
||||
CEREAL_RAPIDJSON_ASSERT(!level_stack_.template Top<Level>()->inArray);
|
||||
CEREAL_RAPIDJSON_ASSERT(level_stack_.GetSize() >= sizeof(Level)); // not inside an Object
|
||||
CEREAL_RAPIDJSON_ASSERT(!level_stack_.template Top<Level>()->inArray); // currently inside an Array, not Object
|
||||
CEREAL_RAPIDJSON_ASSERT(0 == level_stack_.template Top<Level>()->valueCount % 2); // Object has a Key without a Value
|
||||
level_stack_.template Pop<Level>(1);
|
||||
return EndValue(WriteEndObject());
|
||||
}
|
||||
@ -236,9 +255,9 @@ public:
|
||||
//@{
|
||||
|
||||
//! Simpler but slower overload.
|
||||
bool String(const Ch* str) { return String(str, internal::StrLen(str)); }
|
||||
bool Key(const Ch* str) { return Key(str, internal::StrLen(str)); }
|
||||
|
||||
bool String(const Ch* const& str) { return String(str, internal::StrLen(str)); }
|
||||
bool Key(const Ch* const& str) { return Key(str, internal::StrLen(str)); }
|
||||
|
||||
//@}
|
||||
|
||||
//! Write a raw JSON value.
|
||||
@ -249,7 +268,19 @@ public:
|
||||
\param length Length of the json.
|
||||
\param type Type of the root of json.
|
||||
*/
|
||||
bool RawValue(const Ch* json, size_t length, Type type) { Prefix(type); return EndValue(WriteRawValue(json, length)); }
|
||||
bool RawValue(const Ch* json, size_t length, Type type) {
|
||||
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:
|
||||
//! Information for each nested level
|
||||
@ -283,7 +314,7 @@ protected:
|
||||
const char* end = internal::i32toa(i, buffer);
|
||||
PutReserve(*os_, static_cast<size_t>(end - buffer));
|
||||
for (const char* p = buffer; p != end; ++p)
|
||||
PutUnsafe(*os_, static_cast<typename TargetEncoding::Ch>(*p));
|
||||
PutUnsafe(*os_, static_cast<typename OutputStream::Ch>(*p));
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -292,7 +323,7 @@ protected:
|
||||
const char* end = internal::u32toa(u, buffer);
|
||||
PutReserve(*os_, static_cast<size_t>(end - buffer));
|
||||
for (const char* p = buffer; p != end; ++p)
|
||||
PutUnsafe(*os_, static_cast<typename TargetEncoding::Ch>(*p));
|
||||
PutUnsafe(*os_, static_cast<typename OutputStream::Ch>(*p));
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -301,7 +332,7 @@ protected:
|
||||
const char* end = internal::i64toa(i64, buffer);
|
||||
PutReserve(*os_, static_cast<size_t>(end - buffer));
|
||||
for (const char* p = buffer; p != end; ++p)
|
||||
PutUnsafe(*os_, static_cast<typename TargetEncoding::Ch>(*p));
|
||||
PutUnsafe(*os_, static_cast<typename OutputStream::Ch>(*p));
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -310,7 +341,7 @@ protected:
|
||||
char* end = internal::u64toa(u64, buffer);
|
||||
PutReserve(*os_, static_cast<size_t>(end - buffer));
|
||||
for (char* p = buffer; p != end; ++p)
|
||||
PutUnsafe(*os_, static_cast<typename TargetEncoding::Ch>(*p));
|
||||
PutUnsafe(*os_, static_cast<typename OutputStream::Ch>(*p));
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -338,12 +369,12 @@ protected:
|
||||
char* end = internal::dtoa(d, buffer, maxDecimalPlaces_);
|
||||
PutReserve(*os_, static_cast<size_t>(end - buffer));
|
||||
for (char* p = buffer; p != end; ++p)
|
||||
PutUnsafe(*os_, static_cast<typename TargetEncoding::Ch>(*p));
|
||||
PutUnsafe(*os_, static_cast<typename OutputStream::Ch>(*p));
|
||||
return true;
|
||||
}
|
||||
|
||||
bool WriteString(const Ch* str, SizeType length) {
|
||||
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 typename OutputStream::Ch hexDigits[16] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
|
||||
static const char escape[256] = {
|
||||
#define Z16 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
|
||||
//0 1 2 3 4 5 6 7 8 9 A B C D E F
|
||||
@ -399,7 +430,7 @@ protected:
|
||||
else if ((sizeof(Ch) == 1 || static_cast<unsigned>(c) < 256) && CEREAL_RAPIDJSON_UNLIKELY(escape[static_cast<unsigned char>(c)])) {
|
||||
is.Take();
|
||||
PutUnsafe(*os_, '\\');
|
||||
PutUnsafe(*os_, static_cast<typename TargetEncoding::Ch>(escape[static_cast<unsigned char>(c)]));
|
||||
PutUnsafe(*os_, static_cast<typename OutputStream::Ch>(escape[static_cast<unsigned char>(c)]));
|
||||
if (escape[static_cast<unsigned char>(c)] == 'u') {
|
||||
PutUnsafe(*os_, '0');
|
||||
PutUnsafe(*os_, '0');
|
||||
@ -427,9 +458,13 @@ protected:
|
||||
|
||||
bool WriteRawValue(const Ch* json, size_t length) {
|
||||
PutReserve(*os_, length);
|
||||
for (size_t i = 0; i < length; i++) {
|
||||
CEREAL_RAPIDJSON_ASSERT(json[i] != '\0');
|
||||
PutUnsafe(*os_, json[i]);
|
||||
GenericStringStream<SourceEncoding> is(json);
|
||||
while (CEREAL_RAPIDJSON_LIKELY(is.Tell() < length)) {
|
||||
CEREAL_RAPIDJSON_ASSERT(is.Peek() != '\0');
|
||||
if (CEREAL_RAPIDJSON_UNLIKELY(!(writeFlags & kWriteValidateEncodingFlag ?
|
||||
Transcoder<SourceEncoding, TargetEncoding>::Validate(is, *os_) :
|
||||
Transcoder<SourceEncoding, TargetEncoding>::TranscodeUnsafe(is, *os_))))
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@ -457,7 +492,7 @@ protected:
|
||||
// Flush the value if it is the top level one.
|
||||
bool EndValue(bool ret) {
|
||||
if (CEREAL_RAPIDJSON_UNLIKELY(level_stack_.Empty())) // end of json text
|
||||
os_->Flush();
|
||||
Flush();
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -561,7 +596,7 @@ inline bool Writer<StringBuffer>::ScanWriteUnescapedString(StringStream& is, siz
|
||||
// The rest of string using SIMD
|
||||
static const char dquote[16] = { '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"' };
|
||||
static const char bslash[16] = { '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\' };
|
||||
static const char space[16] = { 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19 };
|
||||
static const char space[16] = { 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F };
|
||||
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 sp = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&space[0]));
|
||||
@ -570,7 +605,7 @@ inline bool Writer<StringBuffer>::ScanWriteUnescapedString(StringStream& is, siz
|
||||
const __m128i s = _mm_load_si128(reinterpret_cast<const __m128i *>(p));
|
||||
const __m128i t1 = _mm_cmpeq_epi8(s, dq);
|
||||
const __m128i t2 = _mm_cmpeq_epi8(s, bs);
|
||||
const __m128i t3 = _mm_cmpeq_epi8(_mm_max_epu8(s, sp), sp); // s < 0x20 <=> max(s, 0x19) == 0x19
|
||||
const __m128i t3 = _mm_cmpeq_epi8(_mm_max_epu8(s, sp), sp); // s < 0x20 <=> max(s, 0x1F) == 0x1F
|
||||
const __m128i x = _mm_or_si128(_mm_or_si128(t1, t2), t3);
|
||||
unsigned short r = static_cast<unsigned short>(_mm_movemask_epi8(x));
|
||||
if (CEREAL_RAPIDJSON_UNLIKELY(r != 0)) { // some of characters is escaped
|
||||
@ -595,15 +630,79 @@ inline bool Writer<StringBuffer>::ScanWriteUnescapedString(StringStream& is, siz
|
||||
is.src_ = p;
|
||||
return CEREAL_RAPIDJSON_LIKELY(is.Tell() < length);
|
||||
}
|
||||
#endif // defined(CEREAL_RAPIDJSON_SSE2) || defined(CEREAL_RAPIDJSON_SSE42)
|
||||
#elif defined(CEREAL_RAPIDJSON_NEON)
|
||||
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
|
||||
|
||||
#ifdef _MSC_VER
|
||||
CEREAL_RAPIDJSON_DIAG_POP
|
||||
#endif
|
||||
|
||||
#ifdef __clang__
|
||||
#if defined(_MSC_VER) || defined(__clang__)
|
||||
CEREAL_RAPIDJSON_DIAG_POP
|
||||
#endif
|
||||
|
||||
|
88
include/cereal/external/rapidxml/rapidxml.hpp
vendored
88
include/cereal/external/rapidxml/rapidxml.hpp
vendored
@ -85,7 +85,7 @@ namespace rapidxml
|
||||
|
||||
//! Gets human readable description of error.
|
||||
//! \return Pointer to null terminated description of the error.
|
||||
virtual const char *what() const throw()
|
||||
virtual const char *what() const CEREAL_NOEXCEPT override
|
||||
{
|
||||
return m_what;
|
||||
}
|
||||
@ -317,7 +317,7 @@ namespace rapidxml
|
||||
const Ch *tmp = p;
|
||||
while (*tmp)
|
||||
++tmp;
|
||||
return tmp - p;
|
||||
return static_cast<std::size_t>(tmp - p);
|
||||
}
|
||||
|
||||
// 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>
|
||||
//! to obtain best wasted memory to performance compromise.
|
||||
//! To do it, define their values before rapidxml.hpp file is included.
|
||||
//! \param Ch Character type of created nodes.
|
||||
//! \tparam Ch Character type of created nodes.
|
||||
template<class Ch = char>
|
||||
class memory_pool
|
||||
{
|
||||
@ -656,7 +656,7 @@ namespace rapidxml
|
||||
|
||||
//! Base class for xml_node and xml_attribute implementing common functions:
|
||||
//! name(), name_size(), value(), value_size() and parent().
|
||||
//! \param Ch Character type to use
|
||||
//! \tparam Ch Character type to use
|
||||
template<class Ch = char>
|
||||
class xml_base
|
||||
{
|
||||
@ -729,7 +729,7 @@ namespace rapidxml
|
||||
//! <br><br>
|
||||
//! 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).
|
||||
//! \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.
|
||||
void name(const Ch *name_, std::size_t size)
|
||||
{
|
||||
@ -739,7 +739,7 @@ namespace rapidxml
|
||||
|
||||
//! Sets name of node to a zero-terminated string.
|
||||
//! 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_)
|
||||
{
|
||||
this->name(name_, internal::measure(name_));
|
||||
@ -759,7 +759,7 @@ namespace rapidxml
|
||||
//! <br><br>
|
||||
//! 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.
|
||||
//! \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.
|
||||
void value(const Ch *value_, std::size_t size)
|
||||
{
|
||||
@ -769,7 +769,7 @@ namespace rapidxml
|
||||
|
||||
//! Sets value of node to a zero-terminated string.
|
||||
//! 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_)
|
||||
{
|
||||
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).
|
||||
//! 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.
|
||||
//! \param Ch Character type to use.
|
||||
//! \tparam Ch Character type to use.
|
||||
template<class Ch = char>
|
||||
class xml_attribute: public xml_base<Ch>
|
||||
{
|
||||
@ -862,8 +862,8 @@ namespace rapidxml
|
||||
}
|
||||
|
||||
//! 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_size Size of name, in characters, or 0 to have size calculated automatically from string
|
||||
//! \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 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.
|
||||
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>
|
||||
//! 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.
|
||||
//! \param Ch Character type to use.
|
||||
//! \tparam Ch Character type to use.
|
||||
template<class Ch = char>
|
||||
class xml_node: public xml_base<Ch>
|
||||
{
|
||||
@ -910,7 +910,7 @@ namespace rapidxml
|
||||
|
||||
//! Constructs an empty node with the specified type.
|
||||
//! 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_)
|
||||
: m_type(type_)
|
||||
, m_first_node(0)
|
||||
@ -942,8 +942,8 @@ namespace rapidxml
|
||||
}
|
||||
|
||||
//! 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_size Size of name, in characters, or 0 to have size calculated automatically from string
|
||||
//! \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 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.
|
||||
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.
|
||||
//! Behaviour is undefined if node has no 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_size Size of name, in characters, or 0 to have size calculated automatically from string
|
||||
//! \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 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.
|
||||
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.
|
||||
//! \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_ 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 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.
|
||||
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
|
||||
|
||||
//! Sets type of node.
|
||||
//! \param type Type of node to set.
|
||||
//! \param type_ Type of node to set.
|
||||
void type(node_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,
|
||||
//! which are inherited from memory_pool.
|
||||
//! To access root node of the document, use the document itself, as if it was an xml_node.
|
||||
//! \param Ch Character type to use.
|
||||
//! \tparam Ch Character type to use.
|
||||
template<class Ch = char>
|
||||
class xml_document: public xml_node<Ch>, public memory_pool<Ch>
|
||||
{
|
||||
@ -1527,7 +1527,7 @@ namespace rapidxml
|
||||
{
|
||||
// Insert 8-bit ASCII character
|
||||
// Todo: possibly verify that code is less than 256 and use replacement char otherwise?
|
||||
text[0] = static_cast<unsigned char>(code);
|
||||
text[0] = static_cast<Ch>(code);
|
||||
text += 1;
|
||||
}
|
||||
else
|
||||
@ -1535,28 +1535,28 @@ namespace rapidxml
|
||||
// Insert UTF8 sequence
|
||||
if (code < 0x80) // 1 byte sequence
|
||||
{
|
||||
text[0] = static_cast<unsigned char>(code);
|
||||
text[0] = static_cast<Ch>(code);
|
||||
text += 1;
|
||||
}
|
||||
else if (code < 0x800) // 2 byte sequence
|
||||
{
|
||||
text[1] = static_cast<unsigned char>((code | 0x80) & 0xBF); code >>= 6;
|
||||
text[0] = static_cast<unsigned char>(code | 0xC0);
|
||||
text[1] = static_cast<Ch>((code | 0x80) & 0xBF); code >>= 6;
|
||||
text[0] = static_cast<Ch>(code | 0xC0);
|
||||
text += 2;
|
||||
}
|
||||
else if (code < 0x10000) // 3 byte sequence
|
||||
{
|
||||
text[2] = static_cast<unsigned char>((code | 0x80) & 0xBF); code >>= 6;
|
||||
text[1] = static_cast<unsigned char>((code | 0x80) & 0xBF); code >>= 6;
|
||||
text[0] = static_cast<unsigned char>(code | 0xE0);
|
||||
text[2] = static_cast<Ch>((code | 0x80) & 0xBF); code >>= 6;
|
||||
text[1] = static_cast<Ch>((code | 0x80) & 0xBF); code >>= 6;
|
||||
text[0] = static_cast<Ch>(code | 0xE0);
|
||||
text += 3;
|
||||
}
|
||||
else if (code < 0x110000) // 4 byte sequence
|
||||
{
|
||||
text[3] = static_cast<unsigned char>((code | 0x80) & 0xBF); code >>= 6;
|
||||
text[2] = static_cast<unsigned char>((code | 0x80) & 0xBF); code >>= 6;
|
||||
text[1] = static_cast<unsigned char>((code | 0x80) & 0xBF); code >>= 6;
|
||||
text[0] = static_cast<unsigned char>(code | 0xF0);
|
||||
text[3] = static_cast<Ch>((code | 0x80) & 0xBF); code >>= 6;
|
||||
text[2] = static_cast<Ch>((code | 0x80) & 0xBF); code >>= 6;
|
||||
text[1] = static_cast<Ch>((code | 0x80) & 0xBF); code >>= 6;
|
||||
text[0] = static_cast<Ch>(code | 0xF0);
|
||||
text += 4;
|
||||
}
|
||||
else // Invalid, only codes up to 0x10FFFF are allowed in Unicode
|
||||
@ -1812,7 +1812,7 @@ namespace rapidxml
|
||||
|
||||
// Create comment node
|
||||
xml_node<Ch> *comment = this->allocate_node(node_comment);
|
||||
comment->value(value_, text - value_);
|
||||
comment->value(value_, static_cast<std::size_t>(text - value_));
|
||||
|
||||
// Place zero terminator after comment value
|
||||
if (!(Flags & parse_no_string_terminators))
|
||||
@ -1871,7 +1871,7 @@ namespace rapidxml
|
||||
{
|
||||
// Create a new doctype node
|
||||
xml_node<Ch> *doctype = this->allocate_node(node_doctype);
|
||||
doctype->value(value_, text - value_);
|
||||
doctype->value(value_, static_cast<std::size_t>(text - value_));
|
||||
|
||||
// Place zero terminator after value
|
||||
if (!(Flags & parse_no_string_terminators))
|
||||
@ -1903,7 +1903,7 @@ namespace rapidxml
|
||||
skip<node_name_pred, Flags>(text);
|
||||
if (text == name_)
|
||||
CEREAL_RAPIDXML_PARSE_ERROR("expected PI target", text);
|
||||
pi->name(name_, text - name_);
|
||||
pi->name(name_, static_cast<std::size_t>(text - name_));
|
||||
|
||||
// Skip whitespace between pi target and pi
|
||||
skip<whitespace_pred, Flags>(text);
|
||||
@ -1920,7 +1920,7 @@ namespace rapidxml
|
||||
}
|
||||
|
||||
// Set pi value (verbatim, no entity expansion or whitespace normalization)
|
||||
pi->value(value_, text - value_);
|
||||
pi->value(value_, static_cast<std::size_t>(text - value_));
|
||||
|
||||
// Place zero terminator after name and value
|
||||
if (!(Flags & parse_no_string_terminators))
|
||||
@ -1987,14 +1987,14 @@ namespace rapidxml
|
||||
if (!(Flags & parse_no_data_nodes))
|
||||
{
|
||||
xml_node<Ch> *data = this->allocate_node(node_data);
|
||||
data->value(value_, end - value_);
|
||||
data->value(value_, static_cast<std::size_t>(end - value_));
|
||||
node->append_node(data);
|
||||
}
|
||||
|
||||
// Add data to parent node if no data exists yet
|
||||
if (!(Flags & parse_no_element_values))
|
||||
if (*node->value() == Ch('\0'))
|
||||
node->value(value_, end - value_);
|
||||
node->value(value_, static_cast<std::size_t>(end - value_));
|
||||
|
||||
// Place zero terminator after value
|
||||
if (!(Flags & parse_no_string_terminators))
|
||||
@ -2037,7 +2037,7 @@ namespace rapidxml
|
||||
|
||||
// Create new cdata node
|
||||
xml_node<Ch> *cdata = this->allocate_node(node_cdata);
|
||||
cdata->value(value_, text - value_);
|
||||
cdata->value(value_, static_cast<std::size_t>(text - value_));
|
||||
|
||||
// Place zero terminator after value
|
||||
if (!(Flags & parse_no_string_terminators))
|
||||
@ -2059,7 +2059,7 @@ namespace rapidxml
|
||||
skip<node_name_pred, Flags>(text);
|
||||
if (text == name_)
|
||||
CEREAL_RAPIDXML_PARSE_ERROR("expected element name", text);
|
||||
element->name(name_, text - name_);
|
||||
element->name(name_, static_cast<std::size_t>(text - name_));
|
||||
|
||||
// Skip whitespace between element name and attributes or >
|
||||
skip<whitespace_pred, Flags>(text);
|
||||
@ -2216,7 +2216,7 @@ namespace rapidxml
|
||||
// Skip and validate closing tag name
|
||||
Ch *closing_name = text;
|
||||
skip<node_name_pred, Flags>(text);
|
||||
if (!internal::compare(node->name(), node->name_size(), closing_name, text - closing_name, true))
|
||||
if (!internal::compare(node->name(), node->name_size(), closing_name, static_cast<std::size_t>(text - closing_name), true))
|
||||
CEREAL_RAPIDXML_PARSE_ERROR("invalid closing tag name", text);
|
||||
}
|
||||
else
|
||||
@ -2232,7 +2232,7 @@ namespace rapidxml
|
||||
|
||||
if (contents_end && contents_end != contents_start)
|
||||
{
|
||||
node->value(contents_start, contents_end - contents_start);
|
||||
node->value(contents_start, static_cast<std::size_t>(contents_end - contents_start));
|
||||
node->value()[node->value_size()] = Ch('\0');
|
||||
}
|
||||
return; // Node closed, finished parsing contents
|
||||
@ -2275,7 +2275,7 @@ namespace rapidxml
|
||||
|
||||
// Create new attribute
|
||||
xml_attribute<Ch> *attribute = this->allocate_attribute();
|
||||
attribute->name(name_, text - name_);
|
||||
attribute->name(name_, static_cast<std::size_t>(text - name_));
|
||||
node->append_attribute(attribute);
|
||||
|
||||
// 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);
|
||||
|
||||
// Set attribute value
|
||||
attribute->value(value_, end - value_);
|
||||
attribute->value(value_, static_cast<std::size_t>(end - value_));
|
||||
|
||||
// Make sure that end quote is present
|
||||
if (*text != quote)
|
||||
|
@ -363,10 +363,12 @@ namespace rapidxml
|
||||
out = print_pi_node(out, node, flags, indent);
|
||||
break;
|
||||
|
||||
#ifndef __GNUC__
|
||||
// Unknown
|
||||
default:
|
||||
assert(0);
|
||||
break;
|
||||
#endif
|
||||
}
|
||||
|
||||
// If indenting not disabled, add line break after node
|
||||
|
@ -25,14 +25,14 @@
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of cereal nor the
|
||||
* 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 RANDOLPH VOORHIES OR SHANE GRANT BE LIABLE FOR ANY
|
||||
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
|
||||
@ -51,11 +51,25 @@
|
||||
|
||||
Note that even with this enabled you must still ensure that
|
||||
archives are accessed by only one thread at a time; it is safe
|
||||
to use multiple archives in paralel, but not to access one archive
|
||||
to use multiple archives in parallel, but not to access one archive
|
||||
from many places simultaneously. */
|
||||
#define CEREAL_THREAD_SAFE 0
|
||||
#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
|
||||
//! The serialization/deserialization function name to search for.
|
||||
@ -118,4 +132,25 @@
|
||||
#endif // end !defined(CEREAL_HAS_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_
|
||||
|
139
include/cereal/specialize.hpp
Normal file
139
include/cereal/specialize.hpp
Normal file
@ -0,0 +1,139 @@
|
||||
/*! \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
|
@ -12,14 +12,14 @@
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of cereal nor the
|
||||
* 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 RANDOLPH VOORHIES OR SHANE GRANT BE LIABLE FOR ANY
|
||||
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
|
||||
@ -30,7 +30,7 @@
|
||||
#ifndef CEREAL_TYPES_ARRAY_HPP_
|
||||
#define CEREAL_TYPES_ARRAY_HPP_
|
||||
|
||||
#include <cereal/cereal.hpp>
|
||||
#include "cereal/cereal.hpp"
|
||||
#include <array>
|
||||
|
||||
namespace cereal
|
||||
@ -42,7 +42,7 @@ namespace cereal
|
||||
&& std::is_arithmetic<T>::value, void>::type
|
||||
CEREAL_SAVE_FUNCTION_NAME( Archive & ar, std::array<T, N> const & array )
|
||||
{
|
||||
ar( binary_data( array.data(), sizeof(array) ) );
|
||||
ar( binary_data( array.data(), N*sizeof(T) ) );
|
||||
}
|
||||
|
||||
//! Loading for std::array primitive types
|
||||
@ -52,7 +52,7 @@ namespace cereal
|
||||
&& std::is_arithmetic<T>::value, void>::type
|
||||
CEREAL_LOAD_FUNCTION_NAME( Archive & ar, std::array<T, N> & array )
|
||||
{
|
||||
ar( binary_data( array.data(), sizeof(array) ) );
|
||||
ar( binary_data( array.data(), N*sizeof(T) ) );
|
||||
}
|
||||
|
||||
//! Saving for std::array all other types
|
||||
|
55
include/cereal/types/atomic.hpp
Normal file
55
include/cereal/types/atomic.hpp
Normal file
@ -0,0 +1,55 @@
|
||||
/*! \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_
|
@ -12,14 +12,14 @@
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of cereal nor the
|
||||
* 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 RANDOLPH VOORHIES OR SHANE GRANT BE LIABLE FOR ANY
|
||||
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
|
||||
@ -30,8 +30,8 @@
|
||||
#ifndef CEREAL_TYPES_BASE_CLASS_HPP_
|
||||
#define CEREAL_TYPES_BASE_CLASS_HPP_
|
||||
|
||||
#include <cereal/details/traits.hpp>
|
||||
#include <cereal/details/polymorphic_impl_fwd.hpp>
|
||||
#include "cereal/details/traits.hpp"
|
||||
#include "cereal/details/polymorphic_impl_fwd.hpp"
|
||||
|
||||
namespace cereal
|
||||
{
|
||||
@ -63,7 +63,8 @@ namespace cereal
|
||||
|
||||
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
|
||||
see the documentation on polymorphism.
|
||||
see the documentation on polymorphism. If using a polymorphic class, be sure to include support for
|
||||
polymorphism (cereal/types/polymorphic.hpp).
|
||||
|
||||
\sa virtual_base_class
|
||||
|
||||
@ -120,7 +121,8 @@ namespace cereal
|
||||
|
||||
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
|
||||
see the documentation on polymorphism.
|
||||
see the documentation on polymorphism. If using a polymorphic class, be sure to include support for
|
||||
polymorphism (cereal/types/polymorphic.hpp).
|
||||
|
||||
\sa base_class
|
||||
|
||||
|
@ -12,14 +12,14 @@
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of cereal nor the
|
||||
* 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 RANDOLPH VOORHIES OR SHANE GRANT BE LIABLE FOR ANY
|
||||
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
|
||||
@ -30,8 +30,8 @@
|
||||
#ifndef CEREAL_TYPES_BITSET_HPP_
|
||||
#define CEREAL_TYPES_BITSET_HPP_
|
||||
|
||||
#include <cereal/cereal.hpp>
|
||||
#include <cereal/types/string.hpp>
|
||||
#include "cereal/cereal.hpp"
|
||||
#include "cereal/types/string.hpp"
|
||||
#include <bitset>
|
||||
|
||||
namespace cereal
|
||||
@ -67,7 +67,7 @@ namespace cereal
|
||||
if( bits[i] )
|
||||
chunk |= mask;
|
||||
|
||||
mask >>= 1;
|
||||
mask = static_cast<std::uint8_t>(mask >> 1);
|
||||
|
||||
// output current chunk when mask is empty (8 bits)
|
||||
if( mask == 0 )
|
||||
@ -148,6 +148,8 @@ namespace cereal
|
||||
std::uint8_t chunk = 0;
|
||||
std::uint8_t mask = 0;
|
||||
|
||||
bits.reset();
|
||||
|
||||
// Load one chunk at a time, rotating through the chunk
|
||||
// to set bits in the bitset
|
||||
for( std::size_t i = 0; i < N; ++i )
|
||||
@ -161,7 +163,7 @@ namespace cereal
|
||||
if( chunk & mask )
|
||||
bits[i] = 1;
|
||||
|
||||
mask >>= 1;
|
||||
mask = static_cast<std::uint8_t>(mask >> 1);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -12,14 +12,14 @@
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of cereal nor the
|
||||
* 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 RANDOLPH VOORHIES OR SHANE GRANT BE LIABLE FOR ANY
|
||||
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
|
||||
@ -30,13 +30,20 @@
|
||||
#ifndef CEREAL_TYPES_BOOST_VARIANT_HPP_
|
||||
#define CEREAL_TYPES_BOOST_VARIANT_HPP_
|
||||
|
||||
#include <cereal/cereal.hpp>
|
||||
#include <boost/variant.hpp>
|
||||
#include <boost/mpl/size.hpp>
|
||||
//! @internal
|
||||
#if defined(_MSC_VER) && _MSC_VER < 1911
|
||||
#define CEREAL_CONSTEXPR_LAMBDA
|
||||
#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 variant_detail
|
||||
namespace boost_variant_detail
|
||||
{
|
||||
//! @internal
|
||||
template <class Archive>
|
||||
@ -45,62 +52,113 @@ namespace cereal
|
||||
variant_save_visitor(Archive & ar_) : ar(ar_) {}
|
||||
|
||||
template<class T>
|
||||
void operator()(T const & value) const
|
||||
{
|
||||
ar( CEREAL_NVP_("data", value) );
|
||||
}
|
||||
void operator()(T const & value) const
|
||||
{
|
||||
ar( CEREAL_NVP_("data", value) );
|
||||
}
|
||||
|
||||
Archive & ar;
|
||||
};
|
||||
|
||||
//! @internal
|
||||
template<int N, class Variant, class ... Args, class Archive>
|
||||
typename std::enable_if<N == boost::mpl::size<typename Variant::types>::value, void>::type
|
||||
load_variant(Archive & /*ar*/, int /*target*/, Variant & /*variant*/)
|
||||
template <class Archive, class T>
|
||||
struct LoadAndConstructLoadWrapper
|
||||
{
|
||||
throw ::cereal::Exception("Error traversing variant during load");
|
||||
}
|
||||
using ST = typename std::aligned_storage<sizeof(T), CEREAL_ALIGNOF(T)>::type;
|
||||
|
||||
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
|
||||
template<int N, class Variant, class H, class ... T, class Archive>
|
||||
typename std::enable_if<N < boost::mpl::size<typename Variant::types>::value, void>::type
|
||||
load_variant(Archive & ar, int target, Variant & variant)
|
||||
{
|
||||
if(N == target)
|
||||
{
|
||||
H value;
|
||||
ar( CEREAL_NVP_("data", value) );
|
||||
variant = value;
|
||||
}
|
||||
else
|
||||
load_variant<N+1, Variant, T...>(ar, target, variant);
|
||||
}
|
||||
template <class T> struct load_variant_wrapper;
|
||||
|
||||
} // namespace variant_detail
|
||||
//! Avoid serializing variant void_ type
|
||||
/*! @internal */
|
||||
template <>
|
||||
struct load_variant_wrapper<boost::detail::variant::void_>
|
||||
{
|
||||
template <class Variant, class Archive>
|
||||
static void load_variant( Archive &, Variant & )
|
||||
{ }
|
||||
};
|
||||
|
||||
//! @internal
|
||||
template <class T>
|
||||
struct load_variant_wrapper
|
||||
{
|
||||
// default constructible
|
||||
template <class Archive, class Variant>
|
||||
static void load_variant_impl( Archive & ar, Variant & variant, std::true_type )
|
||||
{
|
||||
T value;
|
||||
ar( CEREAL_NVP_("data", value) );
|
||||
variant = std::move(value);
|
||||
}
|
||||
|
||||
// not default constructible
|
||||
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
|
||||
template <class Archive, typename VariantType1, typename... VariantTypes> inline
|
||||
void CEREAL_SAVE_FUNCTION_NAME( Archive & ar, boost::variant<VariantType1, VariantTypes...> const & variant )
|
||||
template <class Archive, typename ... VariantTypes> inline
|
||||
void CEREAL_SAVE_FUNCTION_NAME( Archive & ar, boost::variant<VariantTypes...> const & variant )
|
||||
{
|
||||
int32_t which = variant.which();
|
||||
ar( CEREAL_NVP_("which", which) );
|
||||
variant_detail::variant_save_visitor<Archive> visitor(ar);
|
||||
boost_variant_detail::variant_save_visitor<Archive> visitor(ar);
|
||||
variant.apply_visitor(visitor);
|
||||
}
|
||||
|
||||
//! Loading for boost::variant
|
||||
template <class Archive, typename VariantType1, typename... VariantTypes> inline
|
||||
void CEREAL_LOAD_FUNCTION_NAME( Archive & ar, boost::variant<VariantType1, VariantTypes...> & variant )
|
||||
template <class Archive, typename ... VariantTypes> inline
|
||||
void CEREAL_LOAD_FUNCTION_NAME( Archive & ar, boost::variant<VariantTypes...> & variant )
|
||||
{
|
||||
typedef typename boost::variant<VariantType1, VariantTypes...>::types types;
|
||||
|
||||
int32_t 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");
|
||||
|
||||
variant_detail::load_variant<0, boost::variant<VariantType1, VariantTypes...>, VariantType1, VariantTypes...>(ar, which, variant);
|
||||
loadFuncArray[which](ar, variant);
|
||||
}
|
||||
} // namespace cereal
|
||||
|
||||
#undef CEREAL_CONSTEXPR_LAMBDA
|
||||
|
||||
#endif // CEREAL_TYPES_BOOST_VARIANT_HPP_
|
||||
|
@ -12,14 +12,14 @@
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of cereal nor the
|
||||
* 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 RANDOLPH VOORHIES OR SHANE GRANT BE LIABLE FOR ANY
|
||||
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
|
||||
|
@ -12,14 +12,14 @@
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of cereal nor the
|
||||
* 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 RANDOLPH VOORHIES OR SHANE GRANT BE LIABLE FOR ANY
|
||||
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
|
||||
@ -30,7 +30,7 @@
|
||||
#ifndef CEREAL_TYPES_COMMON_HPP_
|
||||
#define CEREAL_TYPES_COMMON_HPP_
|
||||
|
||||
#include <cereal/cereal.hpp>
|
||||
#include "cereal/cereal.hpp"
|
||||
|
||||
namespace cereal
|
||||
{
|
||||
|
@ -12,14 +12,14 @@
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of cereal nor the
|
||||
* 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 RANDOLPH VOORHIES OR SHANE GRANT BE LIABLE FOR ANY
|
||||
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
|
||||
|
@ -13,14 +13,14 @@
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of cereal nor the
|
||||
* 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 RANDOLPH VOORHIES OR SHANE GRANT BE LIABLE FOR ANY
|
||||
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
|
||||
@ -31,7 +31,7 @@
|
||||
#ifndef CEREAL_CONCEPTS_PAIR_ASSOCIATIVE_CONTAINER_HPP_
|
||||
#define CEREAL_CONCEPTS_PAIR_ASSOCIATIVE_CONTAINER_HPP_
|
||||
|
||||
#include <cereal/cereal.hpp>
|
||||
#include "cereal/cereal.hpp"
|
||||
|
||||
namespace cereal
|
||||
{
|
||||
|
@ -12,14 +12,14 @@
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of cereal nor the
|
||||
* 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 RANDOLPH VOORHIES OR SHANE GRANT BE LIABLE FOR ANY
|
||||
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
|
||||
@ -30,7 +30,7 @@
|
||||
#ifndef CEREAL_TYPES_DEQUE_HPP_
|
||||
#define CEREAL_TYPES_DEQUE_HPP_
|
||||
|
||||
#include <cereal/cereal.hpp>
|
||||
#include "cereal/cereal.hpp"
|
||||
#include <deque>
|
||||
|
||||
namespace cereal
|
||||
|
@ -12,14 +12,14 @@
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of cereal nor the
|
||||
* 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 RANDOLPH VOORHIES OR SHANE GRANT BE LIABLE FOR ANY
|
||||
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
|
||||
@ -30,7 +30,7 @@
|
||||
#ifndef CEREAL_TYPES_FORWARD_LIST_HPP_
|
||||
#define CEREAL_TYPES_FORWARD_LIST_HPP_
|
||||
|
||||
#include <cereal/cereal.hpp>
|
||||
#include "cereal/cereal.hpp"
|
||||
#include <forward_list>
|
||||
|
||||
namespace cereal
|
||||
|
@ -12,14 +12,14 @@
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of cereal nor the
|
||||
* 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 RANDOLPH VOORHIES OR SHANE GRANT BE LIABLE FOR ANY
|
||||
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
|
||||
|
@ -12,14 +12,14 @@
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of cereal nor the
|
||||
* 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 RANDOLPH VOORHIES OR SHANE GRANT BE LIABLE FOR ANY
|
||||
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
|
||||
@ -30,7 +30,7 @@
|
||||
#ifndef CEREAL_TYPES_LIST_HPP_
|
||||
#define CEREAL_TYPES_LIST_HPP_
|
||||
|
||||
#include <cereal/cereal.hpp>
|
||||
#include "cereal/cereal.hpp"
|
||||
#include <list>
|
||||
|
||||
namespace cereal
|
||||
|
@ -12,14 +12,14 @@
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of cereal nor the
|
||||
* 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 RANDOLPH VOORHIES OR SHANE GRANT BE LIABLE FOR ANY
|
||||
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
|
||||
@ -30,7 +30,7 @@
|
||||
#ifndef 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>
|
||||
|
||||
#endif // CEREAL_TYPES_MAP_HPP_
|
||||
|
@ -12,14 +12,14 @@
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of cereal nor the
|
||||
* 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 RANDOLPH VOORHIES OR SHANE GRANT BE LIABLE FOR ANY
|
||||
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
|
||||
@ -30,17 +30,10 @@
|
||||
#ifndef CEREAL_TYPES_SHARED_PTR_HPP_
|
||||
#define CEREAL_TYPES_SHARED_PTR_HPP_
|
||||
|
||||
#include <cereal/cereal.hpp>
|
||||
#include "cereal/cereal.hpp"
|
||||
#include <memory>
|
||||
#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 memory_detail
|
||||
@ -54,6 +47,7 @@ namespace cereal
|
||||
PtrWrapper(T && p) : ptr(std::forward<T>(p)) {}
|
||||
T & ptr;
|
||||
|
||||
PtrWrapper( PtrWrapper const & ) = default;
|
||||
PtrWrapper & operator=( PtrWrapper const & ) = delete;
|
||||
};
|
||||
|
||||
@ -110,6 +104,11 @@ namespace cereal
|
||||
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).
|
||||
|
||||
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:
|
||||
|
||||
@code{.cpp}
|
||||
@ -136,7 +135,7 @@ namespace cereal
|
||||
using BaseType = typename ::cereal::traits::get_shared_from_this_base<T>::type;
|
||||
using ParentType = std::enable_shared_from_this<BaseType>;
|
||||
using StorageType = typename std::aligned_storage<sizeof(ParentType), CEREAL_ALIGNOF(ParentType)>::type;
|
||||
|
||||
|
||||
public:
|
||||
//! Saves the state of some type inheriting from enable_shared_from_this
|
||||
/*! @param ptr The raw pointer held by the shared_ptr */
|
||||
@ -153,7 +152,8 @@ namespace cereal
|
||||
{
|
||||
if( !itsRestored )
|
||||
{
|
||||
std::memcpy( itsPtr, &itsState, sizeof(ParentType) );
|
||||
// void * cast needed when type has no trivial copy-assignment
|
||||
std::memcpy( static_cast<void *>(itsPtr), &itsState, sizeof(ParentType) );
|
||||
itsRestored = true;
|
||||
}
|
||||
}
|
||||
@ -263,7 +263,7 @@ namespace cereal
|
||||
{
|
||||
auto & ptr = wrapper.ptr;
|
||||
|
||||
uint32_t id = ar.registerSharedPointer( ptr.get() );
|
||||
uint32_t id = ar.registerSharedPointer( ptr );
|
||||
ar( CEREAL_NVP_("id", id) );
|
||||
|
||||
if( id & detail::msb_32bit )
|
||||
@ -278,8 +278,6 @@ namespace cereal
|
||||
typename std::enable_if<traits::has_load_and_construct<T, Archive>::value, void>::type
|
||||
CEREAL_LOAD_FUNCTION_NAME( Archive & ar, memory_detail::PtrWrapper<std::shared_ptr<T> &> & wrapper )
|
||||
{
|
||||
auto & ptr = wrapper.ptr;
|
||||
|
||||
uint32_t id;
|
||||
|
||||
ar( CEREAL_NVP_("id", id) );
|
||||
@ -288,7 +286,7 @@ namespace cereal
|
||||
{
|
||||
// Storage type for the pointer - since we can't default construct this type,
|
||||
// we'll allocate it using std::aligned_storage and use a custom deleter
|
||||
using ST = typename std::aligned_storage<sizeof(T), CEREAL_ALIGNOF(T)>::type;
|
||||
using AlignedStorage = typename std::aligned_storage<sizeof(T), CEREAL_ALIGNOF(T)>::type;
|
||||
|
||||
// Valid flag - set to true once construction finishes
|
||||
// This prevents us from calling the destructor on
|
||||
@ -297,26 +295,28 @@ namespace cereal
|
||||
|
||||
// Allocate our storage, which we will treat as
|
||||
// uninitialized until initialized with placement new
|
||||
ptr.reset( reinterpret_cast<T *>( new ST() ),
|
||||
[=]( T * t )
|
||||
using NonConstT = typename std::remove_const<T>::type;
|
||||
std::shared_ptr<NonConstT> ptr(reinterpret_cast<NonConstT *>(new AlignedStorage()),
|
||||
[=]( NonConstT * t )
|
||||
{
|
||||
if( *valid )
|
||||
t->~T();
|
||||
|
||||
delete reinterpret_cast<ST *>( t );
|
||||
delete reinterpret_cast<AlignedStorage*>( t );
|
||||
} );
|
||||
|
||||
// Register the pointer
|
||||
ar.registerSharedPointer( id, ptr );
|
||||
|
||||
// Perform the actual loading and allocation
|
||||
memory_detail::loadAndConstructSharedPtr( ar, ptr.get(), typename ::cereal::traits::has_shared_from_this<T>::type() );
|
||||
memory_detail::loadAndConstructSharedPtr( ar, ptr.get(), typename ::cereal::traits::has_shared_from_this<NonConstT>::type() );
|
||||
|
||||
// Mark pointer as valid (initialized)
|
||||
*valid = true;
|
||||
wrapper.ptr = std::move(ptr);
|
||||
}
|
||||
else
|
||||
ptr = std::static_pointer_cast<T>(ar.getSharedPointer(id));
|
||||
wrapper.ptr = std::static_pointer_cast<T>(ar.getSharedPointer(id));
|
||||
}
|
||||
|
||||
//! 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
|
||||
CEREAL_LOAD_FUNCTION_NAME( Archive & ar, memory_detail::PtrWrapper<std::shared_ptr<T> &> & wrapper )
|
||||
{
|
||||
auto & ptr = wrapper.ptr;
|
||||
|
||||
uint32_t id;
|
||||
|
||||
ar( CEREAL_NVP_("id", id) );
|
||||
|
||||
if( id & detail::msb_32bit )
|
||||
{
|
||||
ptr.reset( detail::Construct<T, Archive>::load_andor_construct() );
|
||||
using NonConstT = typename std::remove_const<T>::type;
|
||||
std::shared_ptr<NonConstT> ptr( detail::Construct<NonConstT, Archive>::load_andor_construct() );
|
||||
ar.registerSharedPointer( id, ptr );
|
||||
ar( CEREAL_NVP_("data", *ptr) );
|
||||
wrapper.ptr = std::move(ptr);
|
||||
}
|
||||
else
|
||||
ptr = std::static_pointer_cast<T>(ar.getSharedPointer(id));
|
||||
wrapper.ptr = std::static_pointer_cast<T>(ar.getSharedPointer(id));
|
||||
}
|
||||
|
||||
//! Saving std::unique_ptr (wrapper implementation)
|
||||
@ -374,16 +374,17 @@ namespace cereal
|
||||
|
||||
if( isValid )
|
||||
{
|
||||
using NonConstT = typename std::remove_const<T>::type;
|
||||
// Storage type for the pointer - since we can't default construct this type,
|
||||
// we'll allocate it using std::aligned_storage
|
||||
using ST = typename std::aligned_storage<sizeof(T), CEREAL_ALIGNOF(T)>::type;
|
||||
using AlignedStorage = typename std::aligned_storage<sizeof(NonConstT), CEREAL_ALIGNOF(NonConstT)>::type;
|
||||
|
||||
// Allocate storage - note the ST type so that deleter is correct if
|
||||
// Allocate storage - note the AlignedStorage type so that deleter is correct if
|
||||
// an exception is thrown before we are initialized
|
||||
std::unique_ptr<ST> stPtr( new ST() );
|
||||
std::unique_ptr<AlignedStorage> stPtr( new AlignedStorage() );
|
||||
|
||||
// Use wrapper to enter into "data" nvp of ptr_wrapper
|
||||
memory_detail::LoadAndConstructLoadWrapper<Archive, T> loadWrapper( reinterpret_cast<T *>( stPtr.get() ) );
|
||||
memory_detail::LoadAndConstructLoadWrapper<Archive, NonConstT> loadWrapper( reinterpret_cast<NonConstT *>( stPtr.get() ) );
|
||||
|
||||
// Initialize storage
|
||||
ar( CEREAL_NVP_("data", loadWrapper) );
|
||||
@ -404,22 +405,21 @@ namespace cereal
|
||||
uint8_t isValid;
|
||||
ar( CEREAL_NVP_("valid", isValid) );
|
||||
|
||||
auto & ptr = wrapper.ptr;
|
||||
|
||||
if( isValid )
|
||||
{
|
||||
ptr.reset( detail::Construct<T, Archive>::load_andor_construct() );
|
||||
using NonConstT = typename std::remove_const<T>::type;
|
||||
std::unique_ptr<NonConstT, D> ptr( detail::Construct<NonConstT, Archive>::load_andor_construct() );
|
||||
ar( CEREAL_NVP_( "data", *ptr ) );
|
||||
wrapper.ptr = std::move(ptr);
|
||||
}
|
||||
else
|
||||
{
|
||||
ptr.reset( nullptr );
|
||||
wrapper.ptr.reset( nullptr );
|
||||
}
|
||||
}
|
||||
} // namespace cereal
|
||||
|
||||
// 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_
|
||||
|
65
include/cereal/types/optional.hpp
Normal file
65
include/cereal/types/optional.hpp
Normal file
@ -0,0 +1,65 @@
|
||||
/*! \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_
|
@ -12,14 +12,14 @@
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of cereal nor the
|
||||
* 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 RANDOLPH VOORHIES OR SHANE GRANT BE LIABLE FOR ANY
|
||||
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
|
||||
@ -30,15 +30,15 @@
|
||||
#ifndef CEREAL_TYPES_POLYMORPHIC_HPP_
|
||||
#define CEREAL_TYPES_POLYMORPHIC_HPP_
|
||||
|
||||
#include <cereal/cereal.hpp>
|
||||
#include <cereal/types/memory.hpp>
|
||||
#include "cereal/cereal.hpp"
|
||||
#include "cereal/types/memory.hpp"
|
||||
|
||||
#include <cereal/details/util.hpp>
|
||||
#include <cereal/details/helpers.hpp>
|
||||
#include <cereal/details/traits.hpp>
|
||||
#include <cereal/details/polymorphic_impl.hpp>
|
||||
#include "cereal/details/util.hpp"
|
||||
#include "cereal/details/helpers.hpp"
|
||||
#include "cereal/details/traits.hpp"
|
||||
#include "cereal/details/polymorphic_impl.hpp"
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#if defined(_MSC_VER) && _MSC_VER < 1916
|
||||
#define CEREAL_STATIC_CONSTEXPR static
|
||||
#else
|
||||
#define CEREAL_STATIC_CONSTEXPR static constexpr
|
||||
@ -165,17 +165,19 @@
|
||||
See CEREAL_REGISTER_DYNAMIC_INIT for detailed explanation
|
||||
of how this macro should be used. The name used should
|
||||
match that for CEREAL_REGISTER_DYNAMIC_INIT. */
|
||||
#define CEREAL_FORCE_DYNAMIC_INIT(LibName) \
|
||||
namespace cereal { \
|
||||
namespace detail { \
|
||||
void dynamic_init_dummy_##LibName(); \
|
||||
} /* end detail */ \
|
||||
namespace { \
|
||||
void dynamic_init_##LibName() \
|
||||
{ \
|
||||
::cereal::detail::dynamic_init_dummy_##LibName(); \
|
||||
} \
|
||||
} } /* end namespaces */
|
||||
#define CEREAL_FORCE_DYNAMIC_INIT(LibName) \
|
||||
namespace cereal { \
|
||||
namespace detail { \
|
||||
void CEREAL_DLL_EXPORT dynamic_init_dummy_##LibName(); \
|
||||
} /* end detail */ \
|
||||
} /* end cereal */ \
|
||||
namespace { \
|
||||
struct dynamic_init_##LibName { \
|
||||
dynamic_init_##LibName() { \
|
||||
::cereal::detail::dynamic_init_dummy_##LibName(); \
|
||||
} \
|
||||
} dynamic_init_instance_##LibName; \
|
||||
} /* end anonymous namespace */
|
||||
|
||||
namespace cereal
|
||||
{
|
||||
|
@ -12,14 +12,14 @@
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of cereal nor the
|
||||
* 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 RANDOLPH VOORHIES OR SHANE GRANT BE LIABLE FOR ANY
|
||||
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
|
||||
@ -30,13 +30,13 @@
|
||||
#ifndef CEREAL_TYPES_QUEUE_HPP_
|
||||
#define CEREAL_TYPES_QUEUE_HPP_
|
||||
|
||||
#include <cereal/details/helpers.hpp>
|
||||
#include "cereal/details/helpers.hpp"
|
||||
#include <queue>
|
||||
|
||||
// The default container for queue is deque, so let's include that too
|
||||
#include <cereal/types/deque.hpp>
|
||||
#include "cereal/types/deque.hpp"
|
||||
// The default comparator for queue is less
|
||||
#include <cereal/types/functional.hpp>
|
||||
#include "cereal/types/functional.hpp"
|
||||
|
||||
namespace cereal
|
||||
{
|
||||
|
@ -12,14 +12,14 @@
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of cereal nor the
|
||||
* 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 RANDOLPH VOORHIES OR SHANE GRANT BE LIABLE FOR ANY
|
||||
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
|
||||
@ -30,7 +30,7 @@
|
||||
#ifndef CEREAL_TYPES_SET_HPP_
|
||||
#define CEREAL_TYPES_SET_HPP_
|
||||
|
||||
#include <cereal/cereal.hpp>
|
||||
#include "cereal/cereal.hpp"
|
||||
#include <set>
|
||||
|
||||
namespace cereal
|
||||
|
@ -12,14 +12,14 @@
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of cereal nor the
|
||||
* 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 RANDOLPH VOORHIES OR SHANE GRANT BE LIABLE FOR ANY
|
||||
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
|
||||
@ -30,11 +30,11 @@
|
||||
#ifndef CEREAL_TYPES_STACK_HPP_
|
||||
#define CEREAL_TYPES_STACK_HPP_
|
||||
|
||||
#include <cereal/cereal.hpp>
|
||||
#include "cereal/cereal.hpp"
|
||||
#include <stack>
|
||||
|
||||
// The default container for stack is deque, so let's include that too
|
||||
#include <cereal/types/deque.hpp>
|
||||
#include "cereal/types/deque.hpp"
|
||||
|
||||
namespace cereal
|
||||
{
|
||||
|
@ -12,14 +12,14 @@
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of cereal nor the
|
||||
* 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 RANDOLPH VOORHIES OR SHANE GRANT BE LIABLE FOR ANY
|
||||
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
|
||||
@ -30,7 +30,7 @@
|
||||
#ifndef CEREAL_TYPES_STRING_HPP_
|
||||
#define CEREAL_TYPES_STRING_HPP_
|
||||
|
||||
#include <cereal/cereal.hpp>
|
||||
#include "cereal/cereal.hpp"
|
||||
#include <string>
|
||||
|
||||
namespace cereal
|
||||
|
@ -12,14 +12,14 @@
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of cereal nor the
|
||||
* 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 RANDOLPH VOORHIES OR SHANE GRANT BE LIABLE FOR ANY
|
||||
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
|
||||
@ -30,7 +30,7 @@
|
||||
#ifndef CEREAL_TYPES_TUPLE_HPP_
|
||||
#define CEREAL_TYPES_TUPLE_HPP_
|
||||
|
||||
#include <cereal/cereal.hpp>
|
||||
#include "cereal/cereal.hpp"
|
||||
#include <tuple>
|
||||
|
||||
namespace cereal
|
||||
@ -38,7 +38,7 @@ namespace cereal
|
||||
namespace tuple_detail
|
||||
{
|
||||
//! Creates a c string from a sequence of characters
|
||||
/*! The c string created will alwas be prefixed by "tuple_element"
|
||||
/*! The c string created will always be prefixed by "tuple_element"
|
||||
Based on code from: http://stackoverflow/a/20973438/710791
|
||||
@internal */
|
||||
template<char...Cs>
|
||||
@ -63,7 +63,7 @@ namespace cereal
|
||||
template <size_t Q, size_t R, char ... C>
|
||||
struct to_string_impl
|
||||
{
|
||||
using type = typename to_string_impl<Q/10, Q%10, R+'0', C...>::type;
|
||||
using type = typename to_string_impl<Q/10, Q%10, static_cast<char>(R+std::size_t{'0'}), C...>::type;
|
||||
};
|
||||
|
||||
//! Base case with no quotient
|
||||
@ -71,7 +71,7 @@ namespace cereal
|
||||
template <size_t R, char ... C>
|
||||
struct to_string_impl<0, R, C...>
|
||||
{
|
||||
using type = char_seq_to_c_str<R+'0', C...>;
|
||||
using type = char_seq_to_c_str<static_cast<char>(R+std::size_t{'0'}), C...>;
|
||||
};
|
||||
|
||||
//! Generates a c string for a given index of a tuple
|
||||
@ -84,7 +84,7 @@ namespace cereal
|
||||
struct tuple_element_name
|
||||
{
|
||||
using type = typename to_string_impl<T/10, T%10>::type;
|
||||
static const typename type::arr_type c_str(){ return type::str; };
|
||||
static const typename type::arr_type c_str(){ return type::str; }
|
||||
};
|
||||
|
||||
// unwinds a tuple to save it
|
||||
|
@ -12,14 +12,14 @@
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of cereal nor the
|
||||
* 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 RANDOLPH VOORHIES OR SHANE GRANT BE LIABLE FOR ANY
|
||||
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
|
||||
@ -30,7 +30,7 @@
|
||||
#ifndef 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>
|
||||
|
||||
#endif // CEREAL_TYPES_UNORDERED_MAP_HPP_
|
||||
|
@ -12,14 +12,14 @@
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of cereal nor the
|
||||
* 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 RANDOLPH VOORHIES OR SHANE GRANT BE LIABLE FOR ANY
|
||||
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
|
||||
@ -30,7 +30,7 @@
|
||||
#ifndef CEREAL_TYPES_UNORDERED_SET_HPP_
|
||||
#define CEREAL_TYPES_UNORDERED_SET_HPP_
|
||||
|
||||
#include <cereal/cereal.hpp>
|
||||
#include "cereal/cereal.hpp"
|
||||
#include <unordered_set>
|
||||
|
||||
namespace cereal
|
||||
|
@ -12,14 +12,14 @@
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of cereal nor the
|
||||
* 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 RANDOLPH VOORHIES OR SHANE GRANT BE LIABLE FOR ANY
|
||||
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
|
||||
@ -30,7 +30,7 @@
|
||||
#ifndef CEREAL_TYPES_UTILITY_HPP_
|
||||
#define CEREAL_TYPES_UTILITY_HPP_
|
||||
|
||||
#include <cereal/cereal.hpp>
|
||||
#include "cereal/cereal.hpp"
|
||||
#include <utility>
|
||||
|
||||
namespace cereal
|
||||
|
@ -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
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL RANDOLPH VOORHIES OR SHANE GRANT BE LIABLE FOR ANY
|
||||
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
|
||||
@ -32,7 +32,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#ifndef CEREAL_TYPES_VALARRAY_HPP_
|
||||
#define CEREAL_TYPES_VALARRAY_HPP_
|
||||
|
||||
#include <cereal/cereal.hpp>
|
||||
#include "cereal/cereal.hpp"
|
||||
#include <valarray>
|
||||
|
||||
namespace cereal
|
||||
|
108
include/cereal/types/variant.hpp
Normal file
108
include/cereal/types/variant.hpp
Normal file
@ -0,0 +1,108 @@
|
||||
/*! \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_
|
@ -12,14 +12,14 @@
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of cereal nor the
|
||||
* 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 RANDOLPH VOORHIES OR SHANE GRANT BE LIABLE FOR ANY
|
||||
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
|
||||
@ -30,7 +30,7 @@
|
||||
#ifndef CEREAL_TYPES_VECTOR_HPP_
|
||||
#define CEREAL_TYPES_VECTOR_HPP_
|
||||
|
||||
#include <cereal/cereal.hpp>
|
||||
#include "cereal/cereal.hpp"
|
||||
#include <vector>
|
||||
|
||||
namespace cereal
|
||||
@ -60,8 +60,8 @@ namespace cereal
|
||||
|
||||
//! Serialization for non-arithmetic vector types
|
||||
template <class Archive, class T, class A> inline
|
||||
typename std::enable_if<!traits::is_output_serializable<BinaryData<T>, Archive>::value
|
||||
|| !std::is_arithmetic<T>::value, void>::type
|
||||
typename std::enable_if<(!traits::is_output_serializable<BinaryData<T>, Archive>::value
|
||||
|| !std::is_arithmetic<T>::value) && !std::is_same<T, bool>::value, void>::type
|
||||
CEREAL_SAVE_FUNCTION_NAME( Archive & ar, std::vector<T, A> const & vector )
|
||||
{
|
||||
ar( make_size_tag( static_cast<size_type>(vector.size()) ) ); // number of elements
|
||||
@ -71,8 +71,8 @@ namespace cereal
|
||||
|
||||
//! Serialization for non-arithmetic vector types
|
||||
template <class Archive, class T, class A> inline
|
||||
typename std::enable_if<!traits::is_input_serializable<BinaryData<T>, Archive>::value
|
||||
|| !std::is_arithmetic<T>::value, void>::type
|
||||
typename std::enable_if<(!traits::is_input_serializable<BinaryData<T>, Archive>::value
|
||||
|| !std::is_arithmetic<T>::value) && !std::is_same<T, bool>::value, void>::type
|
||||
CEREAL_LOAD_FUNCTION_NAME( Archive & ar, std::vector<T, A> & vector )
|
||||
{
|
||||
size_type size;
|
||||
@ -88,7 +88,7 @@ namespace cereal
|
||||
void CEREAL_SAVE_FUNCTION_NAME( Archive & ar, std::vector<bool, A> const & vector )
|
||||
{
|
||||
ar( make_size_tag( static_cast<size_type>(vector.size()) ) ); // number of elements
|
||||
for(auto && v : vector)
|
||||
for(const auto v : vector)
|
||||
ar( static_cast<bool>(v) );
|
||||
}
|
||||
|
||||
|
52
include/cereal/version.hpp
Normal file
52
include/cereal/version.hpp
Normal file
@ -0,0 +1,52 @@
|
||||
/*! \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_
|
@ -1,14 +1,22 @@
|
||||
add_subdirectory(sandbox_shared_lib)
|
||||
|
||||
add_executable(sandbox sandbox.cpp)
|
||||
target_link_libraries(sandbox ${CEREAL_THREAD_LIBS})
|
||||
|
||||
add_executable(sandbox_json sandbox_json.cpp)
|
||||
target_link_libraries(sandbox_json ${CEREAL_THREAD_LIBS})
|
||||
|
||||
add_executable(sandbox_rtti sandbox_rtti.cpp)
|
||||
target_link_libraries(sandbox_rtti ${CEREAL_THREAD_LIBS})
|
||||
|
||||
add_executable(sandbox_vs sandbox_vs.cpp)
|
||||
target_link_libraries(sandbox_vs sandbox_vs_dll)
|
||||
include_directories(sandbox_shared_lib)
|
||||
|
||||
if(Boost_FOUND)
|
||||
if(Boost_FOUND AND NOT SKIP_PERFORMANCE_COMPARISON)
|
||||
add_executable(performance performance.cpp)
|
||||
target_link_libraries(performance ${Boost_LIBRARIES})
|
||||
endif(Boost_FOUND)
|
||||
if(MSVC)
|
||||
set_target_properties(performance PROPERTIES COMPILE_DEFINITIONS "BOOST_SERIALIZATION_DYN_LINK")
|
||||
endif()
|
||||
target_include_directories(performance PUBLIC ${Boost_INCLUDE_DIRS})
|
||||
target_link_libraries(performance ${CEREAL_THREAD_LIBS} ${Boost_LIBRARIES})
|
||||
endif()
|
||||
|
@ -9,14 +9,14 @@
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of cereal nor the
|
||||
* 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 RANDOLPH VOORHIES AND SHANE GRANT BE LIABLE FOR ANY
|
||||
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
|
||||
@ -29,6 +29,9 @@
|
||||
# pragma warning(disable : 4244 4267)
|
||||
#endif
|
||||
|
||||
// fix for old versions of boost + deprecated auto_ptr
|
||||
#define BOOST_NO_AUTO_PTR
|
||||
|
||||
#include <sstream>
|
||||
#include <iostream>
|
||||
#include <chrono>
|
||||
@ -255,7 +258,7 @@ random_value(std::mt19937 & gen)
|
||||
{
|
||||
std::string s(std::uniform_int_distribution<int>(3, 30)(gen), ' ');
|
||||
for(char & c : s)
|
||||
c = std::uniform_int_distribution<char>(' ', '~')(gen);
|
||||
c = static_cast<char>( std::uniform_int_distribution<int>(' ', '~')(gen) );
|
||||
return s;
|
||||
}
|
||||
|
||||
@ -274,7 +277,7 @@ std::string random_binary_string(std::mt19937 & gen)
|
||||
{
|
||||
std::string s(N, ' ');
|
||||
for(auto & c : s )
|
||||
c = std::uniform_int_distribution<char>('0', '1')(gen);
|
||||
c = static_cast<char>( std::uniform_int_distribution<int>( '0', '1' )(gen) );
|
||||
return s;
|
||||
}
|
||||
|
||||
|
@ -9,14 +9,14 @@
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of cereal nor the
|
||||
* 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 RANDOLPH VOORHIES AND SHANE GRANT BE LIABLE FOR ANY
|
||||
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
|
||||
@ -65,6 +65,8 @@ class Base
|
||||
|
||||
public:
|
||||
int x;
|
||||
|
||||
virtual ~Base() {}
|
||||
};
|
||||
|
||||
class Derived : public Base
|
||||
@ -77,6 +79,7 @@ class Derived : public Base
|
||||
y = d;
|
||||
x = b;
|
||||
}
|
||||
virtual ~Derived() {}
|
||||
|
||||
template <class Archive>
|
||||
void save( Archive & ar ) const
|
||||
@ -386,7 +389,8 @@ void test_unordered_loads()
|
||||
cereal::make_nvp( name3, i_vecbool3 ),
|
||||
cereal::make_nvp( name1, i_int1 ),
|
||||
cereal::make_nvp( name5, i_int5 ),
|
||||
i_int6 );
|
||||
i_int6,
|
||||
i_un7 );
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -651,9 +655,9 @@ int main()
|
||||
iar( d1 );
|
||||
assert( d1->x == 4 && d1->y == 3 );
|
||||
iar( d2 );
|
||||
assert( ((Derived*)d2.get())->x == 5 && ((Derived*)d2.get())->y == 4 );
|
||||
assert( dynamic_cast<Derived*>(d2.get())->x == 5 && dynamic_cast<Derived*>(d2.get())->y == 4 );
|
||||
iar( d3 );
|
||||
assert( ((Derived*)d3.get())->x == 6 && ((Derived*)d3.get())->y == 5 );
|
||||
assert( dynamic_cast<Derived*>(d3.get())->x == 6 && dynamic_cast<Derived*>(d3.get())->y == 5 );
|
||||
}
|
||||
|
||||
{
|
||||
@ -710,7 +714,7 @@ int main()
|
||||
std::ifstream ss("xml_ordering.out");
|
||||
cereal::XMLInputArchive ar(ss);
|
||||
|
||||
// Output prodered out of order, try to load in order 1 2 3 4
|
||||
// Output out of order, try to load in order 1 2 3 4
|
||||
double one;
|
||||
double two;
|
||||
double three;
|
||||
|
@ -9,14 +9,14 @@
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of cereal nor the
|
||||
* 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 RANDOLPH VOORHIES AND SHANE GRANT BE LIABLE FOR ANY
|
||||
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
|
||||
@ -311,31 +311,6 @@ 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()
|
||||
{
|
||||
@ -370,8 +345,6 @@ int main()
|
||||
auto f2 = f;
|
||||
archive( f );
|
||||
archive( f2 );
|
||||
|
||||
archive( Bla::x );
|
||||
}
|
||||
|
||||
// test out of order
|
||||
|
@ -9,14 +9,14 @@
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of cereal nor the
|
||||
* 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 RANDOLPH VOORHIES AND SHANE GRANT BE LIABLE FOR ANY
|
||||
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
|
||||
@ -37,6 +37,7 @@ struct Base
|
||||
{
|
||||
int y;
|
||||
virtual void foo() = 0;
|
||||
virtual ~Base() {}
|
||||
|
||||
template<class Archive>
|
||||
void save(Archive & ar) const
|
||||
@ -55,6 +56,8 @@ struct Base
|
||||
|
||||
struct MyType : public Base
|
||||
{
|
||||
virtual ~MyType() {}
|
||||
|
||||
int x;
|
||||
|
||||
void foo() {}
|
||||
@ -77,6 +80,8 @@ CEREAL_REGISTER_TYPE(MyType)
|
||||
|
||||
struct YourType : public Base
|
||||
{
|
||||
virtual ~YourType() {}
|
||||
|
||||
YourType(int xx) : x(xx) {}
|
||||
YourType() : x(-1) {}
|
||||
int x;
|
||||
@ -114,6 +119,8 @@ struct OurType : public OurBase
|
||||
{
|
||||
OurType() : OurBase(), x() {}
|
||||
OurType(int x_) : x(x_) {}
|
||||
virtual ~OurType() {}
|
||||
|
||||
void foo() {}
|
||||
|
||||
int x;
|
||||
@ -136,6 +143,8 @@ struct BaseVirtual
|
||||
|
||||
struct DerivedVirtual : public virtual BaseVirtual
|
||||
{
|
||||
virtual ~DerivedVirtual() {}
|
||||
|
||||
int y;
|
||||
virtual void foo() {}
|
||||
|
||||
@ -177,6 +186,7 @@ struct AAA
|
||||
|
||||
struct BBB : AAA
|
||||
{
|
||||
virtual ~BBB() {}
|
||||
void foo() {}
|
||||
template <class Archive>
|
||||
void serialize( Archive & ) {}
|
||||
|
@ -1 +1,6 @@
|
||||
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>
|
||||
)
|
||||
|
@ -2,6 +2,9 @@
|
||||
#include "base.hpp"
|
||||
class Derived : public Base
|
||||
{
|
||||
public:
|
||||
virtual ~Derived() {}
|
||||
|
||||
private:
|
||||
friend class cereal::access;
|
||||
template <class Archive>
|
||||
|
@ -1,3 +1,30 @@
|
||||
/*
|
||||
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 <derived.hpp>
|
||||
|
||||
@ -50,7 +77,7 @@ CEREAL_SETUP_ARCHIVE_TRAITS(Archive, Archive)
|
||||
struct Test
|
||||
{
|
||||
template <class Archive>
|
||||
void serialzize( Archive & )
|
||||
void serialize( Archive & )
|
||||
{
|
||||
std::cout << "hey there" << std::endl;
|
||||
}
|
||||
@ -125,10 +152,12 @@ namespace cereal
|
||||
struct A
|
||||
{
|
||||
virtual void foo() = 0;
|
||||
virtual ~A() {}
|
||||
};
|
||||
|
||||
struct B : A
|
||||
{
|
||||
virtual ~B() {}
|
||||
void foo() {}
|
||||
|
||||
template <class Archive>
|
||||
|
80
scripts/appveyor.bat
Normal file
80
scripts/appveyor.bat
Normal file
@ -0,0 +1,80 @@
|
||||
@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%
|
@ -1,7 +1,7 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
# Updates the coverage documentation, and copies it into the appropriate place
|
||||
# in the gh-pages-develop branch.
|
||||
# in the gh-pages branch.
|
||||
# $1 from CMAKE will contain the root directory of cereal
|
||||
|
||||
# this requires lcov 1.10 or newer
|
||||
@ -21,11 +21,11 @@ for f in $COVERAGE_TESTS
|
||||
tempdir=`mktemp -d`
|
||||
|
||||
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}
|
||||
|
||||
# copy over to gh pages
|
||||
git checkout gh-pages-develop
|
||||
git checkout gh-pages
|
||||
|
||||
rm -rf $1/assets/coverage
|
||||
mkdir $1/assets/coverage
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user