mirror of
https://github.com/boostorg/json.git
synced 2026-01-19 04:12:14 +00:00
Add files
This commit is contained in:
147
.appveyor.yml
Normal file
147
.appveyor.yml
Normal file
@@ -0,0 +1,147 @@
|
||||
# Copyright 2016, 2017 Peter Dimov
|
||||
# Copyright (C) 2017 - 2019 James E. King III
|
||||
# Distributed under the Boost Software License, Version 1.0.
|
||||
# (See accompanying file LICENSE_1_0.txt or copy at http://boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#
|
||||
# Generic Appveyor build script for boostorg repositories
|
||||
# See: https://github.com/boostorg/boost-ci/
|
||||
#
|
||||
# Instructions for customizing this script for your library:
|
||||
#
|
||||
# 1. Customize the compilers and language levels you want.
|
||||
# 2. If you have more than include/, src/, test/, example/, examples/,
|
||||
# benchmark/ or tools/ directories, set the environment variable DEPINST.
|
||||
# For example if your build uses code in "bench/" and "fog/" directories:
|
||||
# - DEPINST: --include bench --include fog
|
||||
# 3. Enable pull request builds in your boostorg/<library> account.
|
||||
#
|
||||
# That's it - the script will do everything else for you.
|
||||
#
|
||||
|
||||
version: 1.0.{build}-{branch}
|
||||
|
||||
shallow_clone: true
|
||||
|
||||
branches:
|
||||
only:
|
||||
- master
|
||||
- develop
|
||||
- /bugfix\/.*/
|
||||
- /feature\/.*/
|
||||
- /fix\/.*/
|
||||
- /pr\/.*/
|
||||
|
||||
matrix:
|
||||
# Adding MAYFAIL to any matrix job allows it to fail but the build stays green:
|
||||
allow_failures:
|
||||
- MAYFAIL: true
|
||||
|
||||
environment:
|
||||
global:
|
||||
# see: http://www.boost.org/build/doc/html/bbv2/overview/invocation.html#bbv2.overview.invocation.properties
|
||||
# to use the default for a given environment, comment it out; recommend you build debug and release however:
|
||||
# on Windows it is important to exercise all the possibilities, especially shared vs static, however most
|
||||
# libraries that care about this exercise it in their Jamfiles...
|
||||
# B2_ADDRESS_MODEL: address-model=64,32
|
||||
# B2_LINK: link=shared,static
|
||||
# B2_THREADING: threading=multi,single
|
||||
B2_VARIANT: variant=release
|
||||
|
||||
matrix:
|
||||
- FLAVOR: Visual Studio 2019
|
||||
APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2019
|
||||
B2_ADDRESS_MODEL: address-model=64
|
||||
B2_CXXFLAGS: cxxflags=-permissive-
|
||||
B2_CXXSTD: latest # 2a
|
||||
B2_TOOLSET: msvc-14.2
|
||||
|
||||
- FLAVOR: Visual Studio 2017 C++2a Strict
|
||||
APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017
|
||||
B2_ADDRESS_MODEL: address-model=64
|
||||
B2_CXXFLAGS: cxxflags=-permissive-
|
||||
B2_CXXSTD: latest # 2a
|
||||
B2_TOOLSET: msvc-14.1
|
||||
|
||||
- FLAVOR: Visual Studio 2017 C++17
|
||||
APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017
|
||||
B2_ADDRESS_MODEL: address-model=64
|
||||
B2_CXXSTD: 17
|
||||
B2_TOOLSET: msvc-14.1
|
||||
B2_VARIANT: variant=debug
|
||||
|
||||
- FLAVOR: Visual Studio 2017 C++14 (Default)
|
||||
APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017
|
||||
B2_ADDRESS_MODEL: address-model=64,32
|
||||
B2_TOOLSET: msvc-14.1
|
||||
|
||||
- FLAVOR: clang-cl
|
||||
APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017
|
||||
B2_ADDRESS_MODEL: address-model=64
|
||||
B2_CXXSTD: 11
|
||||
B2_TOOLSET: clang-win
|
||||
|
||||
- FLAVOR: Visual Studio 2015 C++14 (Default)
|
||||
APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015
|
||||
B2_ADDRESS_MODEL: address-model=64,32
|
||||
B2_TOOLSET: msvc-14.0
|
||||
B2_VARIANT: variant=debug
|
||||
|
||||
- FLAVOR: Visual Studio 2010, 2012, 2013
|
||||
APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015
|
||||
B2_TOOLSET: msvc-10.0,msvc-11.0,msvc-12.0
|
||||
|
||||
- FLAVOR: cygwin (32-bit)
|
||||
APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017
|
||||
ADDPATH: C:\cygwin\bin;
|
||||
B2_ADDRESS_MODEL: address-model=32
|
||||
B2_CXXSTD: 03,11
|
||||
# https://github.com/boostorg/test/issues/144
|
||||
B2_DEFINES: define=_POSIX_C_SOURCE=200112L
|
||||
B2_THREADING: threadapi=pthread
|
||||
B2_TOOLSET: gcc
|
||||
B2_VARIANT: variant=debug
|
||||
|
||||
- FLAVOR: cygwin (64-bit)
|
||||
APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017
|
||||
ADDPATH: C:\cygwin64\bin;
|
||||
B2_ADDRESS_MODEL: address-model=64
|
||||
B2_CXXSTD: 11,17
|
||||
# https://github.com/boostorg/test/issues/144
|
||||
B2_DEFINES: define=_POSIX_C_SOURCE=200112L define=__USE_ISOC99
|
||||
B2_THREADING: threadapi=pthread
|
||||
B2_TOOLSET: gcc
|
||||
|
||||
- FLAVOR: mingw32
|
||||
APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017
|
||||
ARCH: i686
|
||||
B2_ADDRESS_MODEL: address-model=32
|
||||
B2_CXXSTD: 03,11
|
||||
SCRIPT: ci\appveyor\mingw.bat
|
||||
B2_VARIANT: variant=debug
|
||||
|
||||
- FLAVOR: mingw64
|
||||
APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017
|
||||
ARCH: x86_64
|
||||
B2_ADDRESS_MODEL: address-model=64
|
||||
B2_CXXSTD: 11,17
|
||||
B2_DEFINES: define=__USE_ISOC99
|
||||
SCRIPT: ci\appveyor\mingw.bat
|
||||
|
||||
install:
|
||||
- set SELF=%APPVEYOR_PROJECT_NAME:-=_%
|
||||
- git clone https://github.com/boostorg/boost-ci.git C:\boost-ci
|
||||
- xcopy /s /e /q /i C:\boost-ci\ci .\ci
|
||||
- ci\appveyor\install.bat
|
||||
|
||||
build: off
|
||||
|
||||
test_script:
|
||||
- set SELF=%APPVEYOR_PROJECT_NAME:-=_%
|
||||
- PATH=%ADDPATH%%PATH%
|
||||
# The definition of B2_TOOLCXX omits B2_CXXSTD= if it was not defined above
|
||||
- IF NOT DEFINED B2_CXXSTD (SET B2_TOOLCXX=toolset=%B2_TOOLSET%) ELSE (SET B2_TOOLCXX=toolset=%B2_TOOLSET% cxxstd=%B2_CXXSTD%)
|
||||
# Echo the complete build command to the build log
|
||||
- IF NOT DEFINED SCRIPT (ECHO b2 libs/%SELF:\=/% %B2_TOOLCXX% %B2_CXXFLAGS% %B2_DEFINES% %B2_THREADING% %B2_ADDRESS_MODEL% %B2_LINK% %B2_THREADING% %B2_VARIANT% -j3)
|
||||
# Now go build...
|
||||
- IF DEFINED SCRIPT (call libs\%SELF%\%SCRIPT%) ELSE (b2 libs/%SELF:\=/% %B2_TOOLCXX% %B2_CXXFLAGS% %B2_DEFINES% %B2_THREADING% %B2_ADDRESS_MODEL% %B2_LINK% %B2_THREADING% %B2_VARIANT% -j3)
|
||||
311
.azure-pipelines.yml
Normal file
311
.azure-pipelines.yml
Normal file
@@ -0,0 +1,311 @@
|
||||
# Copyright 2015-2019 Rene Rivera.
|
||||
# Copyright 2019 Mateusz Loskot <mateusz at loskot dot net>
|
||||
# Distributed under the Boost Software License, Version 1.0.
|
||||
# (See accompanying file LICENSE_1_0.txt or copy at http://boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#
|
||||
# Generic Azure Pipelines build script for boostorg repositories
|
||||
# See: https://github.com/boostorg/boost-ci/
|
||||
#
|
||||
# Instructions for customizing this script for your library:
|
||||
#
|
||||
# 1. Customize the compilers and language levels you want.
|
||||
# 2. If you have more than include/, src/, test/, example/, examples/,
|
||||
# benchmark/ or tools/ directories, set the environment variable DEPINST.
|
||||
# For example if your build uses code in "bench/" and "fog/" directories:
|
||||
# - DEPINST: --include bench --include fog
|
||||
# 3. Enable pull request builds in your boostorg/<library> account.
|
||||
#
|
||||
# That's it - the script will do everything else for you.
|
||||
|
||||
trigger:
|
||||
branches:
|
||||
include:
|
||||
- develop
|
||||
- master
|
||||
- bugfix/*
|
||||
- feature/*
|
||||
- fix/*
|
||||
- pr/*
|
||||
|
||||
pr:
|
||||
branches:
|
||||
include:
|
||||
- develop
|
||||
|
||||
variables:
|
||||
- name: B2_VARIANT
|
||||
value: variant=release,debug
|
||||
|
||||
stages:
|
||||
|
||||
- stage: Test
|
||||
jobs:
|
||||
|
||||
- job: 'Linux'
|
||||
pool:
|
||||
vmImage: 'ubuntu-16.04'
|
||||
strategy:
|
||||
matrix:
|
||||
GCC 8:
|
||||
B2_TOOLSET: gcc
|
||||
B2_CXXSTD: 14,17,2a
|
||||
CXX: g++-8
|
||||
PACKAGES: g++-8
|
||||
GCC 7:
|
||||
B2_TOOLSET: gcc
|
||||
B2_CXXSTD: 11,14,17
|
||||
CXX: g++-7
|
||||
PACKAGES: g++-7
|
||||
GCC 6:
|
||||
B2_TOOLSET: gcc
|
||||
B2_CXXSTD: 11,14
|
||||
CXX: g++-6
|
||||
PACKAGES: g++-6
|
||||
GCC 5:
|
||||
B2_TOOLSET: gcc
|
||||
B2_CXXSTD: 11
|
||||
CXX: g++-5
|
||||
PACKAGES: g++-5
|
||||
GCC 4.9:
|
||||
B2_TOOLSET: gcc
|
||||
B2_CXXSTD: 03,11
|
||||
CXX: g++-4.9
|
||||
PACKAGES: g++-4.9
|
||||
GCC 4.8:
|
||||
B2_TOOLSET: gcc
|
||||
B2_CXXSTD: 03,11
|
||||
CXX: g++-4.8
|
||||
PACKAGES: g++-4.8
|
||||
Clang 8:
|
||||
B2_TOOLSET: clang
|
||||
B2_CXXSTD: 14,17,2a
|
||||
CXX: clang++-8
|
||||
PACKAGES: clang-8
|
||||
LLVM_REPO: llvm-toolchain-xenial-8
|
||||
Clang 7:
|
||||
B2_TOOLSET: clang
|
||||
B2_CXXSTD: 14,17,2a
|
||||
CXX: clang++-7
|
||||
PACKAGES: clang-7
|
||||
LLVM_REPO: llvm-toolchain-xenial-7
|
||||
Clang 6:
|
||||
B2_TOOLSET: clang
|
||||
B2_CXXSTD: 03,11,14,17,2a
|
||||
B2_CXXFLAGS: -stdlib=libc++
|
||||
CXX: clang++-6.0
|
||||
PACKAGES: clang-6.0
|
||||
LLVM_REPO: llvm-toolchain-xenial-6.0
|
||||
Clang 6:
|
||||
B2_TOOLSET: clang
|
||||
B2_CXXSTD: 14,17,2a
|
||||
CXX: clang++-6.0
|
||||
PACKAGES: clang-6.0
|
||||
LLVM_REPO: llvm-toolchain-xenial-6.0
|
||||
Clang 5:
|
||||
B2_TOOLSET: clang
|
||||
B2_CXXSTD: 11,14,17
|
||||
PACKAGES: clang-5.0
|
||||
CXX: clang++-5.0
|
||||
LLVM_REPO: llvm-toolchain-xenial-5.0
|
||||
Clang 4:
|
||||
B2_TOOLSET: clang
|
||||
B2_CXXSTD: 11,14,17
|
||||
CXX: clang++-4.0
|
||||
PACKAGES: clang-4.0
|
||||
LLVM_REPO: llvm-toolchain-xenial-4.0
|
||||
Clang 3.9:
|
||||
B2_TOOLSET: clang
|
||||
B2_CXXSTD: 03,11,14
|
||||
CXX: clang++-3.9
|
||||
PACKAGES: clang-3.9
|
||||
Clang 3.8:
|
||||
B2_TOOLSET: clang
|
||||
CXX: clang++-3.8
|
||||
B2_CXXSTD: 03,11,14
|
||||
PACKAGES: clang-3.8
|
||||
Clang 3.7:
|
||||
B2_TOOLSET: clang
|
||||
B2_CXXSTD: 03,11
|
||||
CXX: clang++-3.7
|
||||
PACKAGES: clang-3.7
|
||||
Clang 3.6:
|
||||
B2_TOOLSET: clang
|
||||
B2_CXXSTD: 03,11
|
||||
CXX: clang++-3.6
|
||||
PACKAGES: clang-3.6
|
||||
Clang 3.5:
|
||||
B2_TOOLSET: clang
|
||||
B2_CXXSTD: 03,11
|
||||
CXX: clang++-3.5
|
||||
PACKAGES: clang-3.5
|
||||
steps:
|
||||
- bash: |
|
||||
set -e
|
||||
uname -a
|
||||
sudo -E apt-add-repository -y "ppa:ubuntu-toolchain-r/test"
|
||||
if test -n "${LLVM_REPO}" ; then
|
||||
wget -O - https://apt.llvm.org/llvm-snapshot.gpg.key | sudo apt-key add -
|
||||
sudo -E apt-add-repository "deb http://apt.llvm.org/xenial/ ${LLVM_REPO} main"
|
||||
fi
|
||||
sudo -E apt-get update
|
||||
sudo -E apt-get -yq --no-install-suggests --no-install-recommends install ${PACKAGES}
|
||||
|
||||
git clone --branch master https://github.com/boostorg/boost-ci.git boost-ci
|
||||
cp -pr boost-ci/ci boost-ci/.codecov.yml .
|
||||
rm -rf boost-ci
|
||||
source ci/azure-pipelines/install.sh
|
||||
|
||||
# AzP requires to run special task in order to export
|
||||
# SELF and BOOST_ROOT as job-scoped variable from a script.
|
||||
# NOTE: Disable set -x is necessary, see the troubleshooting guide
|
||||
# on "Variables having ' (single quote) appended":
|
||||
# https://docs.microsoft.com/en-us/azure/devops/pipelines/troubleshooting
|
||||
set +x
|
||||
echo "##vso[task.setvariable variable=SELF]"$SELF
|
||||
echo "##vso[task.setvariable variable=BOOST_ROOT]"$BOOST_ROOT
|
||||
set -x
|
||||
displayName: 'Install'
|
||||
- bash: |
|
||||
set -e
|
||||
echo "SELF=$SELF"
|
||||
echo "BOOST_ROOT=$BOOST_ROOT"
|
||||
|
||||
cd $BOOST_ROOT/libs/$SELF
|
||||
ci/azure-pipelines/build.sh --debug-configuration
|
||||
displayName: 'Build'
|
||||
|
||||
- job: 'Windows'
|
||||
strategy:
|
||||
matrix:
|
||||
VS 2019 C++2a Strict:
|
||||
B2_TOOLSET: msvc-14.2
|
||||
B2_CXXSTD: latest # 2a
|
||||
B2_CXXFLAGS: cxxflags=-permissive-
|
||||
B2_ADDRESS_MODEL: address-model=64
|
||||
VM_IMAGE: 'windows-2019'
|
||||
VS 2017 C++2a Strict:
|
||||
B2_TOOLSET: msvc-14.1
|
||||
B2_CXXSTD: latest # 2a
|
||||
B2_CXXFLAGS: cxxflags=-permissive-
|
||||
B2_ADDRESS_MODEL: address-model=64
|
||||
VM_IMAGE: 'vs2017-win2016'
|
||||
VS 2017 C++17:
|
||||
B2_TOOLSET: msvc-14.1
|
||||
B2_CXXSTD: 17
|
||||
B2_ADDRESS_MODEL: address-model=64,32
|
||||
VM_IMAGE: 'vs2017-win2016'
|
||||
VS 2017 C++14:
|
||||
B2_TOOLSET: msvc-14.1
|
||||
#B2_CXXSTD: 14 # default
|
||||
B2_ADDRESS_MODEL: address-model=64,32
|
||||
VM_IMAGE: 'vs2017-win2016'
|
||||
VS 2015 C++14:
|
||||
B2_TOOLSET: msvc-14.0
|
||||
#B2_CXXSTD: 14 # default
|
||||
B2_ADDRESS_MODEL: address-model=64,32
|
||||
VM_IMAGE: 'vs2015-win2012r2'
|
||||
|
||||
pool:
|
||||
vmImage: $(VM_IMAGE)
|
||||
steps:
|
||||
- script: |
|
||||
set SELF=%BUILD_REPOSITORY_NAME:-=_%
|
||||
for /f "tokens=2 delims=/" %%a in ("%SELF%") do set SELF=%%a
|
||||
set BOOST_ROOT=%BUILD_SOURCESDIRECTORY%\boost-root
|
||||
|
||||
git clone --branch master https://github.com/boostorg/boost-ci.git boost-ci
|
||||
xcopy /s /e /q /i boost-ci\ci .\ci
|
||||
cmd /k ci\azure-pipelines\install.bat
|
||||
|
||||
echo ##vso[task.setvariable variable=SELF]%SELF%
|
||||
echo ##vso[task.setvariable variable=BOOST_ROOT]%BOOST_ROOT%
|
||||
displayName: 'Install'
|
||||
- script: |
|
||||
PATH=%ADDPATH%%PATH%
|
||||
REM The definition of B2_TOOLCXX omits B2_CXXSTD= if it was not defined above
|
||||
IF NOT DEFINED B2_CXXSTD (SET B2_TOOLCXX=toolset=%B2_TOOLSET%) ELSE (SET B2_TOOLCXX=toolset=%B2_TOOLSET% cxxstd=%B2_CXXSTD%)
|
||||
cd %BOOST_ROOT%
|
||||
ECHO b2 libs/%SELF:\=/% %B2_TOOLCXX% %B2_CXXFLAGS% %B2_DEFINES% %B2_THREADING% %B2_ADDRESS_MODEL% %B2_LINK% %B2_THREADING% %B2_VARIANT% -j3
|
||||
b2 libs/%SELF:\=/% %B2_TOOLCXX% %B2_CXXFLAGS% %B2_DEFINES% %B2_THREADING% %B2_ADDRESS_MODEL% %B2_LINK% %B2_THREADING% %B2_VARIANT% -j3
|
||||
displayName: 'Build'
|
||||
|
||||
- job: 'macOS'
|
||||
pool:
|
||||
vmImage: 'macOS-10.13'
|
||||
strategy:
|
||||
matrix:
|
||||
Xcode 10.1:
|
||||
B2_TOOLSET: clang
|
||||
B2_CXXSTD: 14,17,2a
|
||||
XCODE_APP: /Applications/Xcode_10.1.app
|
||||
Xcode 10.0:
|
||||
B2_TOOLSET: clang
|
||||
B2_CXXSTD: 14,17,2a
|
||||
XCODE_APP: /Applications/Xcode_10.app
|
||||
Xcode 9.4.1:
|
||||
B2_TOOLSET: clang
|
||||
B2_CXXSTD: 11,14,17
|
||||
XCODE_APP: /Applications/Xcode_9.4.1.app
|
||||
Xcode 9.4:
|
||||
B2_TOOLSET: clang
|
||||
B2_CXXSTD: 11,14,17
|
||||
XCODE_APP: /Applications/Xcode_9.4.app
|
||||
Xcode 9.3.1:
|
||||
B2_TOOLSET: clang
|
||||
B2_CXXSTD: 11,14,17
|
||||
XCODE_APP: /Applications/Xcode_9.3.1.app
|
||||
Xcode 9.3:
|
||||
B2_TOOLSET: clang
|
||||
B2_CXXSTD: 11,14
|
||||
XCODE_APP: /Applications/Xcode_9.3.app
|
||||
Xcode 9.2:
|
||||
B2_TOOLSET: clang
|
||||
B2_CXXSTD: 11,14
|
||||
XCODE_APP: /Applications/Xcode_9.2.app
|
||||
Xcode 9.1:
|
||||
B2_TOOLSET: clang
|
||||
B2_CXXSTD: 03,11
|
||||
XCODE_APP: /Applications/Xcode_9.1.app
|
||||
Xcode 9.0.1:
|
||||
B2_TOOLSET: clang
|
||||
B2_CXXSTD: 03,11
|
||||
XCODE_APP: /Applications/Xcode_9.0.1.app
|
||||
Xcode 9.0:
|
||||
B2_TOOLSET: clang
|
||||
B2_CXXSTD: 03,11
|
||||
XCODE_APP: /Applications/Xcode_9.app
|
||||
Xcode 8.3.3:
|
||||
B2_TOOLSET: clang
|
||||
B2_CXXSTD: 03,11
|
||||
XCODE_APP: /Applications/Xcode_8.3.3.app
|
||||
steps:
|
||||
- bash: |
|
||||
set -e
|
||||
uname -a
|
||||
sudo xcode-select -switch ${XCODE_APP}
|
||||
which clang++
|
||||
|
||||
git clone --branch master https://github.com/boostorg/boost-ci.git boost-ci
|
||||
cp -pr boost-ci/ci boost-ci/.codecov.yml .
|
||||
rm -rf boost-ci
|
||||
source ci/azure-pipelines/install.sh
|
||||
|
||||
# AzP requires to run special task in order to export
|
||||
# SELF and BOOST_ROOT as job-scoped variable from a script.
|
||||
# NOTE: Disable set -x is necessary, see the troubleshooting guide
|
||||
# on "Variables having ' (single quote) appended":
|
||||
# https://docs.microsoft.com/en-us/azure/devops/pipelines/troubleshooting
|
||||
set +x
|
||||
echo "##vso[task.setvariable variable=SELF]"$SELF
|
||||
echo "##vso[task.setvariable variable=BOOST_ROOT]"$BOOST_ROOT
|
||||
set -x
|
||||
displayName: Install
|
||||
- bash: |
|
||||
set -e
|
||||
echo "SELF=$SELF"
|
||||
echo "BOOST_ROOT=$BOOST_ROOT"
|
||||
|
||||
cd $BOOST_ROOT/libs/$SELF
|
||||
ci/azure-pipelines/build.sh --debug-configuration
|
||||
displayName: 'Build'
|
||||
5
.gitignore
vendored
Normal file
5
.gitignore
vendored
Normal file
@@ -0,0 +1,5 @@
|
||||
bin/
|
||||
build/
|
||||
*.*#
|
||||
static/log.txt
|
||||
tags
|
||||
236
.travis.yml
Normal file
236
.travis.yml
Normal file
@@ -0,0 +1,236 @@
|
||||
# Copyright 2016 Peter Dimov
|
||||
# Copyright 2017 - 2019 James E. King III
|
||||
# Distributed under the Boost Software License, Version 1.0.
|
||||
# (See accompanying file LICENSE_1_0.txt or copy at http://boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#
|
||||
# Generic Travis CI build script for boostorg repositories
|
||||
# See: https://github.com/boostorg/boost-ci
|
||||
#
|
||||
# Instructions for customizing this script for your library:
|
||||
#
|
||||
# 1. Customize the compilers and language levels you want in the 'jobs'.
|
||||
# 2. If you have more than include/, src/, test/, example/, examples/, or
|
||||
# tools/ directories, modify your Travis CI project and add the environment
|
||||
# variable DEPINST. For example if your build uses code in "bench/" and
|
||||
# "fog/" directories, then set DEPINST to the following:
|
||||
# --include bench --include fog
|
||||
# 3. If you want to enable Coverity Scan, you need to provide the environment
|
||||
# variables COVERITY_SCAN_TOKEN and COVERITY_SCAN_NOTIFICATION_EMAIL in
|
||||
# your github settings.
|
||||
# 4. If you want to enable a big-endian build, you need to uncomment the
|
||||
# big-endian build job.
|
||||
# 5. Enable pull request builds in your boostorg/<library> account.
|
||||
#
|
||||
# That's it - the scripts will do everything else for you.
|
||||
|
||||
dist: xenial
|
||||
language: cpp
|
||||
|
||||
env:
|
||||
global:
|
||||
# see: http://www.boost.org/build/doc/html/bbv2/overview/invocation.html#bbv2.overview.invocation.properties
|
||||
# - B2_ADDRESS_MODEL=address-model=64,32
|
||||
# - B2_LINK=link=shared,static
|
||||
# - B2_THREADING=threading=multi,single
|
||||
- B2_VARIANT=variant=release
|
||||
|
||||
install:
|
||||
- git clone https://github.com/boostorg/boost-ci.git boost-ci
|
||||
- cp -pr boost-ci/ci boost-ci/.codecov.yml .
|
||||
- source ci/travis/install.sh
|
||||
|
||||
addons:
|
||||
apt:
|
||||
packages:
|
||||
- binutils-gold
|
||||
- gdb
|
||||
- libc6-dbg
|
||||
- qemu-user-static
|
||||
|
||||
services:
|
||||
- docker
|
||||
|
||||
branches:
|
||||
only:
|
||||
- master
|
||||
- develop
|
||||
- /bugfix\/.*/
|
||||
- /feature\/.*/
|
||||
- /fix\/.*/
|
||||
- /pr\/.*/
|
||||
|
||||
script:
|
||||
- cd $BOOST_ROOT/libs/$SELF
|
||||
- ci/travis/build.sh
|
||||
|
||||
#
|
||||
# Default toolsets in Ubuntu
|
||||
#
|
||||
# trusty xenial bionic
|
||||
# 14.04 16.04 18.04
|
||||
# ------ ------ ------
|
||||
# clang 3.4 3.8 6.0
|
||||
# gcc 4.8.2 5.3.1 7.3.0
|
||||
#
|
||||
|
||||
anchors:
|
||||
clang-38: &clang-38 { apt: { packages: [ "clang-3.8",
|
||||
"libstdc++-6-dev" ], sources: [ "llvm-toolchain-xenial-3.8",
|
||||
"ubuntu-toolchain-r-test" ] } }
|
||||
clang-4: &clang-4 { apt: { packages: [ "clang-4.0",
|
||||
"libstdc++-6-dev" ], sources: [ "llvm-toolchain-xenial-4.0",
|
||||
"ubuntu-toolchain-r-test" ] } }
|
||||
clang-5: &clang-5 { apt: { packages: [ "clang-5.0",
|
||||
"libstdc++-7-dev" ], sources: [ "llvm-toolchain-xenial-5.0",
|
||||
"ubuntu-toolchain-r-test" ] } }
|
||||
clang-6: &clang-6 { apt: { packages: [ "clang-6.0",
|
||||
"libc6-dbg",
|
||||
"libc++-dev",
|
||||
"libstdc++-8-dev" ], sources: [ "llvm-toolchain-xenial-6.0",
|
||||
"ubuntu-toolchain-r-test" ] } }
|
||||
clang-7: &clang-7 { apt: { packages: [ "clang-7",
|
||||
"libc6-dbg",
|
||||
"libc++-dev",
|
||||
"libstdc++-8-dev" ], sources: [ "llvm-toolchain-xenial-7",
|
||||
"ubuntu-toolchain-r-test" ] } }
|
||||
clang-8: &clang-8 { apt: { packages: [ "clang-8",
|
||||
"libc6-dbg",
|
||||
"libc++-dev",
|
||||
"libstdc++-8-dev" ], sources: [ "llvm-toolchain-xenial-8",
|
||||
"ubuntu-toolchain-r-test" ] } }
|
||||
gcc-48: &gcc-48 { apt: { packages: [ "g++-4.8" ] } }
|
||||
gcc-49: &gcc-49 { apt: { packages: [ "g++-4.9" ], sources: [ "ubuntu-toolchain-r-test" ] } }
|
||||
gcc-5: &gcc-5 { apt: { packages: [ "g++-5" ] } }
|
||||
gcc-6: &gcc-6 { apt: { packages: [ "g++-6" ], sources: [ "ubuntu-toolchain-r-test" ] } }
|
||||
gcc-7: &gcc-7 { apt: { packages: [ "g++-7" ], sources: [ "ubuntu-toolchain-r-test" ] } }
|
||||
gcc-8: &gcc-8 { apt: { packages: [ "g++-8" ], sources: [ "ubuntu-toolchain-r-test" ] } }
|
||||
gcc-9: &gcc-9 { apt: { packages: [ "g++-9" ], sources: [ "ubuntu-toolchain-r-test" ] } }
|
||||
|
||||
jobs:
|
||||
allow_failures:
|
||||
- env:
|
||||
- COPY="all the environment settings from your job"
|
||||
|
||||
include:
|
||||
# coverage
|
||||
- os: linux
|
||||
env:
|
||||
- COMMENT=codecov.io
|
||||
- B2_CXXSTD=11
|
||||
- B2_TOOLSET=gcc-8
|
||||
- B2_DEFINES="define=BOOST_NO_STRESS_TEST=1"
|
||||
addons: *gcc-8
|
||||
script:
|
||||
- cd $BOOST_ROOT/libs/$SELF
|
||||
- ci/travis/codecov.sh
|
||||
|
||||
- os: linux
|
||||
env:
|
||||
- COMMENT=asan
|
||||
- B2_VARIANT=variant=debug
|
||||
- B2_TOOLSET=gcc-8
|
||||
- B2_CXXSTD=11,14
|
||||
- B2_CXXFLAGS="address-sanitizer=norecover"
|
||||
- B2_DEFINES="define=BOOST_NO_STRESS_TEST=1"
|
||||
addons: *gcc-8
|
||||
|
||||
- os: linux
|
||||
env:
|
||||
- COMMENT=tsan
|
||||
- B2_VARIANT=variant=debug
|
||||
- B2_TOOLSET=gcc-8
|
||||
- B2_CXXSTD=11,14
|
||||
- B2_CXXFLAGS="thread-sanitizer=norecover"
|
||||
- B2_DEFINES="define=BOOST_NO_STRESS_TEST=1"
|
||||
addons: *gcc-8
|
||||
|
||||
- os: linux
|
||||
env:
|
||||
- COMMENT=ubsan
|
||||
- B2_VARIANT=variant=debug
|
||||
- B2_TOOLSET=gcc-8
|
||||
- B2_CXXSTD=11,14
|
||||
- B2_CXXFLAGS="undefined-sanitizer=norecover"
|
||||
- B2_DEFINES="define=BOOST_NO_STRESS_TEST=1"
|
||||
- B2_LINKFLAGS="linkflags=-fuse-ld=gold"
|
||||
- UBSAN_OPTIONS=print_stacktrace=1
|
||||
addons: *gcc-8
|
||||
|
||||
- os: linux
|
||||
env:
|
||||
- COMMENT=valgrind
|
||||
- B2_TOOLSET=clang-6.0
|
||||
- B2_CXXSTD=11,14
|
||||
- B2_DEFINES="define=BOOST_NO_STRESS_TEST=1"
|
||||
- B2_VARIANT=variant=debug
|
||||
- B2_TESTFLAGS=testing.launcher=valgrind
|
||||
- VALGRIND_OPTS=--error-exitcode=1
|
||||
addons: *clang-6
|
||||
script:
|
||||
- cd $BOOST_ROOT/libs/$SELF
|
||||
- ci/travis/valgrind.sh
|
||||
|
||||
# libstdc++
|
||||
- { os: "linux", dist: "trusty", # xenial has libstdc++ from gcc 5.4.0 with newer ABI
|
||||
env: [ "B2_TOOLSET=gcc-4.8", "B2_CXXSTD=11" ], addons: *gcc-48 }
|
||||
- { os: "linux", dist: "trusty", # xenial has libstdc++ from gcc 5.4.0 with newer ABI
|
||||
env: [ "B2_TOOLSET=gcc-4.9", "B2_CXXSTD=11" ], addons: *gcc-49 }
|
||||
- { os: "linux", env: [ "B2_TOOLSET=gcc-5", "B2_CXXSTD=11" ], addons: *gcc-5 }
|
||||
- { os: "linux", env: [ "B2_TOOLSET=gcc-6", "B2_CXXSTD=11,14" ], addons: *gcc-6 }
|
||||
- { os: "linux", env: [ "B2_TOOLSET=gcc-7", "B2_CXXSTD=14,17" ], addons: *gcc-7 }
|
||||
- { os: "linux", env: [ "B2_TOOLSET=gcc-8", "B2_CXXSTD=17,2a" ], addons: *gcc-8 }
|
||||
- { os: "linux", env: [ "B2_TOOLSET=gcc-9", "B2_CXXSTD=17,2a" ], addons: *gcc-9 }
|
||||
- { os: "linux", dist: "trusty", # xenial has libstdc++ from gcc 5.4.0 with newer ABI
|
||||
env: [ "B2_TOOLSET=clang-3.8", "B2_CXXSTD=11" ], addons: *clang-38 }
|
||||
- { os: "linux", env: [ "B2_TOOLSET=clang-4.0", "B2_CXXSTD=11,14" ], addons: *clang-4 }
|
||||
- { os: "linux", env: [ "B2_TOOLSET=clang-5.0", "B2_CXXSTD=11,14" ], addons: *clang-5 }
|
||||
- { os: "linux", env: [ "B2_TOOLSET=clang-6.0", "B2_CXXSTD=14,17" ], addons: *clang-6 }
|
||||
- { os: "linux", env: [ "B2_TOOLSET=clang-7", "B2_CXXSTD=17,2a" ], addons: *clang-7 }
|
||||
- { os: "linux", env: [ "B2_TOOLSET=clang-8", "B2_CXXSTD=17,2a" ], addons: *clang-8 }
|
||||
|
||||
# libc++
|
||||
- { os: "linux", env: [ "B2_TOOLSET=clang-6.0", "B2_CXXSTD=11,14",
|
||||
"B2_CXXFLAGS=-stdlib=libc++" ], addons: *clang-6 }
|
||||
- { os: "osx" , env: [ "B2_TOOLSET=clang", "B2_CXXSTD=11,17" ] }
|
||||
|
||||
# to enable Intel ICC define INTEL_ICC_SERIAL_NUMBER and the following (under development):
|
||||
# - { os: "linux", env: [ "B2_TOOLSET=intel-linux", "B2_CXXSTD=11,14,17" ], addons: *gcc-7,
|
||||
# script: cd $BOOST_ROOT/libs/$SELF && ci/travis/intelicc.sh }
|
||||
|
||||
# uncomment to enable a big-endian build job, just note that it is 5-10 times slower
|
||||
# than a regular build and travis has a 50 minute time limit per job
|
||||
# - os: linux
|
||||
# env:
|
||||
# - COMMENT=big-endian
|
||||
# - B2_CXXSTD=03
|
||||
# - B2_TOOLSET=gcc
|
||||
# - B2_DEFINES="define=BOOST_NO_STRESS_TEST=1"
|
||||
# - BDDE_OS=red
|
||||
# - BDDE_ARCH=ppc64
|
||||
# script:
|
||||
# - cd $BOOST_ROOT/libs/$SELF
|
||||
# - ci/travis/bdde.sh
|
||||
|
||||
# - os: linux
|
||||
# env:
|
||||
# - COMMENT=cppcheck
|
||||
# script:
|
||||
# - cd $BOOST_ROOT/libs/$SELF
|
||||
# - ci/travis/cppcheck.sh
|
||||
|
||||
#################### Jobs to run on pushes to master, develop ###################
|
||||
|
||||
# Coverity Scan
|
||||
- os: linux
|
||||
if: (env(COVERITY_SCAN_NOTIFICATION_EMAIL) IS present) AND (branch IN (develop, master)) AND (type IN (cron, push))
|
||||
env:
|
||||
- COMMENT="Coverity Scan"
|
||||
- B2_TOOLSET=clang
|
||||
script:
|
||||
- cd $BOOST_ROOT/libs/$SELF
|
||||
- ci/travis/coverity.sh
|
||||
|
||||
notifications:
|
||||
email:
|
||||
false
|
||||
147
CMakeLists.txt
Normal file
147
CMakeLists.txt
Normal file
@@ -0,0 +1,147 @@
|
||||
#
|
||||
# Copyright (c) 2016-2017 Vinnie Falco (vinnie dot falco at gmail dot com)
|
||||
#
|
||||
# Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
# file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
#
|
||||
# Official repository: https://github.com/boostorg/fixed_string
|
||||
#
|
||||
|
||||
cmake_minimum_required (VERSION 3.5.1)
|
||||
|
||||
if (POLICY CMP0074)
|
||||
cmake_policy (SET CMP0074 NEW)
|
||||
endif()
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
|
||||
function (DoGroupSources curdir rootdir folder)
|
||||
file (GLOB children RELATIVE ${PROJECT_SOURCE_DIR}/${curdir} ${PROJECT_SOURCE_DIR}/${curdir}/*)
|
||||
foreach (child ${children})
|
||||
if (IS_DIRECTORY ${PROJECT_SOURCE_DIR}/${curdir}/${child})
|
||||
DoGroupSources (${curdir}/${child} ${rootdir} ${folder})
|
||||
elseif (${child} STREQUAL "CMakeLists.txt")
|
||||
source_group("" FILES ${PROJECT_SOURCE_DIR}/${curdir}/${child})
|
||||
else()
|
||||
string (REGEX REPLACE ^${rootdir} ${folder} groupname ${curdir})
|
||||
string (REPLACE "/" "\\" groupname ${groupname})
|
||||
source_group (${groupname} FILES ${PROJECT_SOURCE_DIR}/${curdir}/${child})
|
||||
endif()
|
||||
endforeach()
|
||||
endfunction()
|
||||
|
||||
function (GroupSources curdir folder)
|
||||
DoGroupSources (${curdir} ${curdir} ${folder})
|
||||
endfunction()
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
#
|
||||
# JSON
|
||||
#
|
||||
#-------------------------------------------------------------------------------
|
||||
|
||||
project (JSON VERSION 1)
|
||||
|
||||
set_property (GLOBAL PROPERTY USE_FOLDERS ON)
|
||||
|
||||
if (MSVC)
|
||||
set (CMAKE_VERBOSE_MAKEFILE FALSE)
|
||||
|
||||
add_definitions (
|
||||
-D_WIN32_WINNT=0x0601
|
||||
)
|
||||
|
||||
add_compile_options(
|
||||
/permissive- # strict C++
|
||||
/W4 # enable all warnings
|
||||
/MP # Multi-processor compilation
|
||||
)
|
||||
|
||||
set (Boost_USE_STATIC_LIBS ON)
|
||||
set (Boost_USE_STATIC_RUNTIME ON)
|
||||
|
||||
set (CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} /MTd")
|
||||
set (CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} /Ob2 /Oi /Ot /GL /MT")
|
||||
set (CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO} /Oi /Ot /MT")
|
||||
|
||||
set (CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} /SAFESEH:NO")
|
||||
set (CMAKE_EXE_LINKER_FLAGS_RELEASE "${CMAKE_EXE_LINKER_FLAGS_RELEASE} /LTCG")
|
||||
|
||||
# for RelWithDebInfo builds, disable incremental linking
|
||||
# since CMake sets it ON by default for that build type and it
|
||||
# causes warnings
|
||||
#
|
||||
string (REPLACE "/INCREMENTAL" "/INCREMENTAL:NO" replacement_flags
|
||||
${CMAKE_EXE_LINKER_FLAGS_RELWITHDEBINFO})
|
||||
set (CMAKE_EXE_LINKER_FLAGS_RELWITHDEBINFO ${replacement_flags})
|
||||
|
||||
else()
|
||||
set (THREADS_PREFER_PTHREAD_FLAG ON)
|
||||
find_package (Threads)
|
||||
|
||||
set( CMAKE_CXX_FLAGS
|
||||
"${CMAKE_CXX_FLAGS} -std=c++11 -Wall -Wextra -Wpedantic -Wno-unused-parameter")
|
||||
|
||||
if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang")
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wrange-loop-analysis")
|
||||
endif ()
|
||||
endif()
|
||||
|
||||
# Must come before Boost includes, otherwise the
|
||||
# IDE sees the wrong file due to boost/ symlinks.
|
||||
include_directories (include)
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
#
|
||||
# Boost
|
||||
#
|
||||
#-------------------------------------------------------------------------------
|
||||
|
||||
get_filename_component (BOOST_ROOT ../../ ABSOLUTE)
|
||||
|
||||
# VFALCO I want static but "b2 stage" builds a minimal set which excludes static
|
||||
add_definitions (-DBOOST_ALL_STATIC_LINK=1)
|
||||
|
||||
include_directories (${BOOST_ROOT})
|
||||
|
||||
link_directories(${BOOST_ROOT}/stage/lib)
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
|
||||
if ("${VARIANT}" STREQUAL "coverage")
|
||||
if (MSVC)
|
||||
else()
|
||||
set (CMAKE_BUILD_TYPE DEBUG)
|
||||
set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -msse4.2 --coverage")
|
||||
set (CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} --coverage")
|
||||
endif()
|
||||
|
||||
elseif ("${VARIANT}" STREQUAL "ubasan")
|
||||
if (MSVC)
|
||||
else()
|
||||
set (CMAKE_BUILD_TYPE RELWITHDEBINFO)
|
||||
set (CMAKE_CXX_FLAGS
|
||||
"${CMAKE_CXX_FLAGS} -msse4.2 -funsigned-char -fno-omit-frame-pointer -fsanitize=address,undefined -fno-sanitize-recover=address,undefined -fsanitize-blacklist=${PROJECT_SOURCE_DIR}/tools/blacklist.supp")
|
||||
set (CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -fsanitize=address,undefined -fno-sanitize-recover=address,undefined")
|
||||
endif()
|
||||
|
||||
elseif ("${VARIANT}" STREQUAL "debug")
|
||||
set (CMAKE_BUILD_TYPE DEBUG)
|
||||
|
||||
elseif ("${VARIANT}" STREQUAL "release")
|
||||
set (CMAKE_BUILD_TYPE RELEASE)
|
||||
|
||||
endif()
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
#
|
||||
# Tests and examples
|
||||
#
|
||||
|
||||
file (GLOB_RECURSE PROJECT_FILES
|
||||
${PROJECT_SOURCE_DIR}/include/boost/json.hpp
|
||||
${PROJECT_SOURCE_DIR}/include/boost/json/*.hpp
|
||||
${PROJECT_SOURCE_DIR}/include/boost/json/*.ipp
|
||||
)
|
||||
|
||||
add_subdirectory (test)
|
||||
45
Jamfile
Normal file
45
Jamfile
Normal file
@@ -0,0 +1,45 @@
|
||||
#
|
||||
# Copyright (c) 2019 Vinnie Falco (vinnie dot falco at gmail dot com)
|
||||
#
|
||||
# Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
# file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
#
|
||||
# Official repository: https://github.com/boostorg/json
|
||||
#
|
||||
|
||||
import ac ;
|
||||
import os ;
|
||||
import feature ;
|
||||
import boost ;
|
||||
import modules ;
|
||||
import testing ;
|
||||
import ../../config/checks/config : requires ;
|
||||
|
||||
boost.use-project ;
|
||||
|
||||
local defines =
|
||||
[ requires
|
||||
cxx11_constexpr
|
||||
cxx11_decltype
|
||||
cxx11_hdr_tuple
|
||||
cxx11_template_aliases
|
||||
cxx11_variadic_templates
|
||||
]
|
||||
<include>.
|
||||
<implicit-dependency>/boost//headers
|
||||
<define>BOOST_ALL_NO_LIB=1
|
||||
<toolset>msvc-14.1:<cxxflags>"/permissive-"
|
||||
<toolset>msvc-14.2:<cxxflags>"/permissive-"
|
||||
<toolset>msvc,<variant>release:<cxxflags>"/Ob2 /Oi /Ot"
|
||||
<target-os>windows:<define>_WIN32_WINNT=0x0601
|
||||
;
|
||||
|
||||
project /boost/json
|
||||
: requirements
|
||||
<link>static
|
||||
$(defines)
|
||||
: usage-requirements
|
||||
$(defines)
|
||||
;
|
||||
|
||||
build-project test ;
|
||||
23
LICENSE_1_0.txt
Normal file
23
LICENSE_1_0.txt
Normal file
@@ -0,0 +1,23 @@
|
||||
Boost Software License - Version 1.0 - August 17th, 2003
|
||||
|
||||
Permission is hereby granted, free of charge, to any person or organization
|
||||
obtaining a copy of the software and accompanying documentation covered by
|
||||
this license (the "Software") to use, reproduce, display, distribute,
|
||||
execute, and transmit the Software, and to prepare derivative works of the
|
||||
Software, and to permit third-parties to whom the Software is furnished to
|
||||
do so, all subject to the following:
|
||||
|
||||
The copyright notices in the Software and this entire statement, including
|
||||
the above license grant, this restriction and the following disclaimer,
|
||||
must be included in all copies of the Software, in whole or in part, and
|
||||
all derivative works of the Software, unless such copies or derivative
|
||||
works are solely in the form of machine-executable object code generated by
|
||||
a source language processor.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
|
||||
SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
|
||||
FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
|
||||
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
DEALINGS IN THE SOFTWARE.
|
||||
@@ -1,2 +1,3 @@
|
||||
# json
|
||||
Boost.JSON
|
||||
# Boost.JSON
|
||||
|
||||
This is currently **NOT** an official Boost library.
|
||||
|
||||
30
include/boost/json.hpp
Normal file
30
include/boost/json.hpp
Normal file
@@ -0,0 +1,30 @@
|
||||
//
|
||||
// Copyright (c) 2016-2019 Vinnie Falco (vinnie dot falco at gmail dot com)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
// Official repository: https://github.com/boostorg/json
|
||||
//
|
||||
|
||||
#ifndef BOOST_JSON_HPP
|
||||
#define BOOST_JSON_HPP
|
||||
|
||||
#include <boost/json/allocator.hpp>
|
||||
#include <boost/json/array.hpp>
|
||||
#include <boost/json/assign_string.hpp>
|
||||
#include <boost/json/assign_vector.hpp>
|
||||
#include <boost/json/basic_parser.hpp>
|
||||
#include <boost/json/iterator.hpp>
|
||||
#include <boost/json/error.hpp>
|
||||
#include <boost/json/kind.hpp>
|
||||
#include <boost/json/number.hpp>
|
||||
#include <boost/json/object.hpp>
|
||||
#include <boost/json/parse_file.hpp>
|
||||
#include <boost/json/parser.hpp>
|
||||
#include <boost/json/serializer.hpp>
|
||||
#include <boost/json/storage.hpp>
|
||||
#include <boost/json/string.hpp>
|
||||
#include <boost/json/value.hpp>
|
||||
|
||||
#endif
|
||||
90
include/boost/json/allocator.hpp
Normal file
90
include/boost/json/allocator.hpp
Normal file
@@ -0,0 +1,90 @@
|
||||
//
|
||||
// Copyright (c) 2018-2019 Vinnie Falco (vinnie dot falco at gmail dot com)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
// Official repository: https://github.com/boostorg/json
|
||||
//
|
||||
|
||||
#ifndef BOOST_JSON_ALLOCATOR_HPP
|
||||
#define BOOST_JSON_ALLOCATOR_HPP
|
||||
|
||||
#include <boost/beast/core/detail/config.hpp>
|
||||
#include <boost/json/storage.hpp>
|
||||
#include <type_traits>
|
||||
|
||||
namespace boost {
|
||||
namespace beast {
|
||||
namespace json {
|
||||
|
||||
template<typename T>
|
||||
class allocator
|
||||
{
|
||||
storage_ptr sp_;
|
||||
|
||||
template<typename U>
|
||||
friend class allocator;
|
||||
|
||||
public:
|
||||
using pointer = T*;
|
||||
using reference = T&;
|
||||
using const_pointer = T const*;
|
||||
using const_reference = T const&;
|
||||
using value_type = T;
|
||||
using size_type = std::size_t;
|
||||
using difference_type = std::ptrdiff_t;
|
||||
|
||||
template<typename U>
|
||||
struct rebind
|
||||
{
|
||||
using other = allocator<U>;
|
||||
};
|
||||
|
||||
allocator(allocator const&) = default;
|
||||
allocator& operator=(allocator const&) = default;
|
||||
|
||||
allocator();
|
||||
|
||||
allocator(allocator&&) noexcept;
|
||||
|
||||
allocator& operator=(allocator&&) noexcept;
|
||||
|
||||
template<typename U>
|
||||
allocator(allocator<U> const& other) noexcept;
|
||||
|
||||
explicit
|
||||
allocator(storage_ptr sp) noexcept;
|
||||
|
||||
T*
|
||||
allocate(size_t n);
|
||||
|
||||
void
|
||||
deallocate(T* t, size_t n) noexcept;
|
||||
|
||||
bool
|
||||
operator==(allocator const&) const noexcept;
|
||||
|
||||
bool
|
||||
operator!=(allocator const&) const noexcept;
|
||||
|
||||
storage_ptr
|
||||
get_storage() const & noexcept
|
||||
{
|
||||
return sp_;
|
||||
}
|
||||
|
||||
storage_ptr
|
||||
get_storage() && noexcept
|
||||
{
|
||||
return std::move(sp_);
|
||||
}
|
||||
};
|
||||
|
||||
} // json
|
||||
} // beast
|
||||
} // boost
|
||||
|
||||
#include <boost/json/impl/allocator.hpp>
|
||||
|
||||
#endif
|
||||
440
include/boost/json/array.hpp
Normal file
440
include/boost/json/array.hpp
Normal file
@@ -0,0 +1,440 @@
|
||||
//
|
||||
// Copyright (c) 2018-2019 Vinnie Falco (vinnie dot falco at gmail dot com)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
// Official repository: https://github.com/boostorg/json
|
||||
//
|
||||
|
||||
#ifndef BOOST_JSON_ARRAY_HPP
|
||||
#define BOOST_JSON_ARRAY_HPP
|
||||
|
||||
#include <boost/beast/core/detail/config.hpp>
|
||||
#include <boost/json/allocator.hpp>
|
||||
#include <boost/json/storage.hpp>
|
||||
#include <cstdlib>
|
||||
#include <initializer_list>
|
||||
#include <iterator>
|
||||
|
||||
namespace boost {
|
||||
namespace beast {
|
||||
namespace json {
|
||||
|
||||
class value;
|
||||
|
||||
/** The native type of array values
|
||||
*/
|
||||
class array
|
||||
{
|
||||
class table;
|
||||
|
||||
table* tab_ = nullptr;
|
||||
storage_ptr sp_;
|
||||
|
||||
struct cleanup_assign;
|
||||
struct cleanup_insert;
|
||||
|
||||
public:
|
||||
using value_type = value;
|
||||
using size_type = std::size_t;
|
||||
using difference_type = std::ptrdiff_t;
|
||||
using reference = value&;
|
||||
using const_reference = value const&;
|
||||
using pointer = value*;
|
||||
using const_pointer = value const*;
|
||||
using iterator = value*;
|
||||
using const_iterator = value const*;
|
||||
using reverse_iterator =
|
||||
std::reverse_iterator<iterator>;
|
||||
using const_reverse_iterator =
|
||||
std::reverse_iterator<const_iterator>;
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
//
|
||||
// Special Members
|
||||
//
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
BOOST_BEAST_DECL
|
||||
~array();
|
||||
|
||||
BOOST_BEAST_DECL
|
||||
array();
|
||||
|
||||
BOOST_BEAST_DECL
|
||||
explicit
|
||||
array(storage_ptr store);
|
||||
|
||||
BOOST_BEAST_DECL
|
||||
array(
|
||||
size_type count);
|
||||
|
||||
BOOST_BEAST_DECL
|
||||
array(
|
||||
size_type count,
|
||||
storage_ptr store);
|
||||
|
||||
BOOST_BEAST_DECL
|
||||
array(
|
||||
size_type count,
|
||||
value_type const& v);
|
||||
|
||||
BOOST_BEAST_DECL
|
||||
array(
|
||||
size_type count,
|
||||
value_type const& v,
|
||||
storage_ptr store);
|
||||
|
||||
template<class InputIt>
|
||||
array(
|
||||
InputIt first, InputIt last);
|
||||
|
||||
template<class InputIt>
|
||||
array(
|
||||
InputIt first, InputIt last,
|
||||
storage_ptr store);
|
||||
|
||||
BOOST_BEAST_DECL
|
||||
array(array const& other);
|
||||
|
||||
BOOST_BEAST_DECL
|
||||
array(
|
||||
array const& other,
|
||||
storage_ptr store);
|
||||
|
||||
BOOST_BEAST_DECL
|
||||
array(array&& other) noexcept;
|
||||
|
||||
BOOST_BEAST_DECL
|
||||
array(
|
||||
array&& other,
|
||||
storage_ptr store);
|
||||
|
||||
BOOST_BEAST_DECL
|
||||
array(
|
||||
std::initializer_list<value_type> list);
|
||||
|
||||
BOOST_BEAST_DECL
|
||||
array(
|
||||
std::initializer_list<value_type> list,
|
||||
storage_ptr store);
|
||||
|
||||
BOOST_BEAST_DECL
|
||||
array&
|
||||
operator=(array&& other);
|
||||
|
||||
BOOST_BEAST_DECL
|
||||
array&
|
||||
operator=(array const& other);
|
||||
|
||||
BOOST_BEAST_DECL
|
||||
array&
|
||||
operator=(
|
||||
std::initializer_list<value_type> list);
|
||||
|
||||
BOOST_BEAST_DECL
|
||||
storage_ptr const&
|
||||
get_storage() const noexcept
|
||||
{
|
||||
return sp_;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
//
|
||||
// Elements
|
||||
//
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
BOOST_BEAST_DECL
|
||||
reference
|
||||
at(size_type pos);
|
||||
|
||||
BOOST_BEAST_DECL
|
||||
const_reference
|
||||
at(size_type pos) const;
|
||||
|
||||
BOOST_BEAST_DECL
|
||||
reference
|
||||
operator[](size_type pos);
|
||||
|
||||
BOOST_BEAST_DECL
|
||||
const_reference
|
||||
operator[](size_type pos) const;
|
||||
|
||||
reference
|
||||
front()
|
||||
{
|
||||
return (*this)[0];
|
||||
}
|
||||
|
||||
const_reference
|
||||
front() const
|
||||
{
|
||||
return (*this)[0];
|
||||
}
|
||||
|
||||
reference
|
||||
back()
|
||||
{
|
||||
return (*this)[size() - 1];
|
||||
}
|
||||
|
||||
const_reference
|
||||
back() const
|
||||
{
|
||||
return (*this)[size() - 1];
|
||||
}
|
||||
|
||||
BOOST_BEAST_DECL
|
||||
value_type*
|
||||
data() noexcept;
|
||||
|
||||
BOOST_BEAST_DECL
|
||||
value_type const*
|
||||
data() const noexcept;
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
//
|
||||
// Iterators
|
||||
//
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
BOOST_BEAST_DECL
|
||||
iterator
|
||||
begin() noexcept;
|
||||
|
||||
BOOST_BEAST_DECL
|
||||
const_iterator
|
||||
begin() const noexcept;
|
||||
|
||||
BOOST_BEAST_DECL
|
||||
const_iterator
|
||||
cbegin() noexcept
|
||||
{
|
||||
return begin();
|
||||
}
|
||||
|
||||
BOOST_BEAST_DECL
|
||||
iterator
|
||||
end() noexcept;
|
||||
|
||||
BOOST_BEAST_DECL
|
||||
const_iterator
|
||||
end() const noexcept;
|
||||
|
||||
BOOST_BEAST_DECL
|
||||
const_iterator
|
||||
cend() noexcept
|
||||
{
|
||||
return end();
|
||||
}
|
||||
|
||||
BOOST_BEAST_DECL
|
||||
reverse_iterator
|
||||
rbegin() noexcept;
|
||||
|
||||
BOOST_BEAST_DECL
|
||||
const_reverse_iterator
|
||||
rbegin() const noexcept;
|
||||
|
||||
BOOST_BEAST_DECL
|
||||
const_reverse_iterator
|
||||
crbegin() noexcept
|
||||
{
|
||||
return rbegin();
|
||||
}
|
||||
|
||||
BOOST_BEAST_DECL
|
||||
reverse_iterator
|
||||
rend() noexcept;
|
||||
|
||||
BOOST_BEAST_DECL
|
||||
const_reverse_iterator
|
||||
rend() const noexcept;
|
||||
|
||||
BOOST_BEAST_DECL
|
||||
const_reverse_iterator
|
||||
crend() noexcept
|
||||
{
|
||||
return rend();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
//
|
||||
// Capacity
|
||||
//
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
BOOST_BEAST_DECL
|
||||
bool
|
||||
empty() const noexcept;
|
||||
|
||||
BOOST_BEAST_DECL
|
||||
size_type
|
||||
size() const noexcept;
|
||||
|
||||
BOOST_BEAST_DECL
|
||||
size_type
|
||||
max_size() const noexcept;
|
||||
|
||||
BOOST_BEAST_DECL
|
||||
void
|
||||
reserve(size_type new_capacity);
|
||||
|
||||
BOOST_BEAST_DECL
|
||||
size_type
|
||||
capacity() const noexcept;
|
||||
|
||||
BOOST_BEAST_DECL
|
||||
void
|
||||
shrink_to_fit() noexcept;
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
//
|
||||
// Modifiers
|
||||
//
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
BOOST_BEAST_DECL
|
||||
void
|
||||
clear() noexcept;
|
||||
|
||||
BOOST_BEAST_DECL
|
||||
iterator
|
||||
insert(
|
||||
const_iterator before,
|
||||
value_type const& v);
|
||||
|
||||
BOOST_BEAST_DECL
|
||||
iterator
|
||||
insert(
|
||||
const_iterator before,
|
||||
value_type&& v);
|
||||
|
||||
BOOST_BEAST_DECL
|
||||
iterator
|
||||
insert (
|
||||
const_iterator before,
|
||||
size_type count,
|
||||
value_type const& v);
|
||||
|
||||
template<class InputIt>
|
||||
iterator
|
||||
insert(
|
||||
const_iterator before,
|
||||
InputIt first, InputIt last);
|
||||
|
||||
BOOST_BEAST_DECL
|
||||
iterator
|
||||
insert(
|
||||
const_iterator before,
|
||||
std::initializer_list<value_type> list);
|
||||
|
||||
template<class Arg>
|
||||
iterator
|
||||
emplace(
|
||||
const_iterator before,
|
||||
Arg&& arg);
|
||||
|
||||
BOOST_BEAST_DECL
|
||||
iterator
|
||||
erase(const_iterator pos);
|
||||
|
||||
BOOST_BEAST_DECL
|
||||
iterator
|
||||
erase(
|
||||
const_iterator first,
|
||||
const_iterator last);
|
||||
|
||||
BOOST_BEAST_DECL
|
||||
void
|
||||
push_back(value_type const& v);
|
||||
|
||||
BOOST_BEAST_DECL
|
||||
void
|
||||
push_back(value_type&& v);
|
||||
|
||||
template<class Arg>
|
||||
reference
|
||||
emplace_back(Arg&& arg);
|
||||
|
||||
BOOST_BEAST_DECL
|
||||
void
|
||||
pop_back();
|
||||
|
||||
BOOST_BEAST_DECL
|
||||
void
|
||||
resize(size_type count);
|
||||
|
||||
BOOST_BEAST_DECL
|
||||
void
|
||||
resize(
|
||||
size_type count,
|
||||
value_type const& v);
|
||||
|
||||
BOOST_BEAST_DECL
|
||||
void
|
||||
swap(array& other) noexcept;
|
||||
|
||||
private:
|
||||
template<class It>
|
||||
using iter_cat = typename
|
||||
std::iterator_traits<It>::iterator_category;
|
||||
|
||||
template<class InputIt>
|
||||
array(
|
||||
InputIt first, InputIt last,
|
||||
storage_ptr store,
|
||||
std::input_iterator_tag);
|
||||
|
||||
template<class InputIt>
|
||||
array(
|
||||
InputIt first, InputIt last,
|
||||
storage_ptr store,
|
||||
std::forward_iterator_tag);
|
||||
|
||||
template<class InputIt>
|
||||
iterator
|
||||
insert(
|
||||
const_iterator before,
|
||||
InputIt first, InputIt last,
|
||||
std::input_iterator_tag);
|
||||
|
||||
template<class InputIt>
|
||||
iterator
|
||||
insert(
|
||||
const_iterator before,
|
||||
InputIt first, InputIt last,
|
||||
std::forward_iterator_tag);
|
||||
|
||||
template<class Arg>
|
||||
iterator
|
||||
emplace_impl(
|
||||
const_iterator before,
|
||||
Arg&& arg);
|
||||
|
||||
BOOST_BEAST_DECL
|
||||
void
|
||||
destroy(
|
||||
value* first,
|
||||
value* last);
|
||||
|
||||
BOOST_BEAST_DECL
|
||||
void
|
||||
move(
|
||||
value* to,
|
||||
value* from,
|
||||
size_type n) noexcept;
|
||||
};
|
||||
|
||||
} // json
|
||||
} // beast
|
||||
} // boost
|
||||
|
||||
// Must be included here for this file to stand alone
|
||||
#include <boost/json/value.hpp>
|
||||
|
||||
// headers for this file are at the bottom of value.hpp
|
||||
|
||||
#endif
|
||||
43
include/boost/json/assign_string.hpp
Normal file
43
include/boost/json/assign_string.hpp
Normal file
@@ -0,0 +1,43 @@
|
||||
//
|
||||
// Copyright (c) 2018-2019 Vinnie Falco (vinnie dot falco at gmail dot com)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
// Official repository: https://github.com/boostorg/json
|
||||
//
|
||||
|
||||
#ifndef BOOST_JSON_ASSIGN_STRING_HPP
|
||||
#define BOOST_JSON_ASSIGN_STRING_HPP
|
||||
|
||||
#include <boost/beast/core/detail/config.hpp>
|
||||
#include <boost/json/error.hpp>
|
||||
#include <boost/json/value.hpp>
|
||||
#include <string>
|
||||
#include <type_traits>
|
||||
|
||||
namespace boost {
|
||||
namespace beast {
|
||||
namespace json {
|
||||
|
||||
template<class Allocator>
|
||||
void
|
||||
from_json(
|
||||
std::basic_string<
|
||||
char,
|
||||
std::char_traits<char>,
|
||||
Allocator>& t,
|
||||
value const& v)
|
||||
{
|
||||
if(! v.is_string())
|
||||
throw system_error(
|
||||
error::expected_string);
|
||||
auto& s= v.as_string();
|
||||
t.assign(s.data(), s.size());
|
||||
}
|
||||
|
||||
} // json
|
||||
} // beast
|
||||
} // boost
|
||||
|
||||
#endif
|
||||
49
include/boost/json/assign_vector.hpp
Normal file
49
include/boost/json/assign_vector.hpp
Normal file
@@ -0,0 +1,49 @@
|
||||
//
|
||||
// Copyright (c) 2018-2019 Vinnie Falco (vinnie dot falco at gmail dot com)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
// Official repository: https://github.com/boostorg/json
|
||||
//
|
||||
|
||||
#ifndef BOOST_JSON_ASSIGN_VECTOR_HPP
|
||||
#define BOOST_JSON_ASSIGN_VECTOR_HPP
|
||||
|
||||
#include <boost/beast/core/detail/config.hpp>
|
||||
#include <boost/json/error.hpp>
|
||||
#include <boost/json/value.hpp>
|
||||
#include <type_traits>
|
||||
#include <vector>
|
||||
|
||||
namespace boost {
|
||||
namespace beast {
|
||||
namespace json {
|
||||
|
||||
template<class T, class A
|
||||
#if 0
|
||||
,class = typename std::enable_if<
|
||||
can_assign_from<T>::value>::type
|
||||
#endif
|
||||
>
|
||||
void
|
||||
from_json(
|
||||
std::vector<T, A>& t,
|
||||
value const& v)
|
||||
{
|
||||
if(! v.is_array())
|
||||
throw system_error(
|
||||
error::expected_array);
|
||||
auto& arr = v.as_array();
|
||||
t.resize(0);
|
||||
t.resize(arr.size());
|
||||
auto it = t.begin();
|
||||
for(auto const& e : arr)
|
||||
e.store(*it++);
|
||||
}
|
||||
|
||||
} // json
|
||||
} // beast
|
||||
} // boost
|
||||
|
||||
#endif
|
||||
190
include/boost/json/basic_parser.hpp
Normal file
190
include/boost/json/basic_parser.hpp
Normal file
@@ -0,0 +1,190 @@
|
||||
//
|
||||
// Copyright (c) 2018-2019 Vinnie Falco (vinnie dot falco at gmail dot com)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
// Official repository: https://github.com/boostorg/json
|
||||
//
|
||||
|
||||
#ifndef BOOST_JSON_BASIC_PARSER_HPP
|
||||
#define BOOST_JSON_BASIC_PARSER_HPP
|
||||
|
||||
#include <boost/beast/core/detail/config.hpp>
|
||||
#include <boost/json/number.hpp>
|
||||
#include <boost/json/detail/basic_parser.hpp>
|
||||
#include <boost/json/detail/stack.hpp>
|
||||
#include <boost/beast/core/error.hpp>
|
||||
#include <boost/beast/core/string.hpp>
|
||||
#include <boost/asio/buffer.hpp>
|
||||
#include <cstdint>
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
namespace boost {
|
||||
namespace beast {
|
||||
namespace json {
|
||||
|
||||
/** A parser for serialized JSON
|
||||
*/
|
||||
class basic_parser
|
||||
#ifndef BOOST_BEAST_DOXYGEN
|
||||
: private detail::parser_base
|
||||
#endif
|
||||
{
|
||||
enum class state : char;
|
||||
|
||||
/// Depth to which the stack does not require dynamic allocation
|
||||
static std::size_t const stack_capacity = 64;
|
||||
|
||||
detail::stack<
|
||||
state, stack_capacity> stack_;
|
||||
number::mantissa_type n_mant_;
|
||||
number::exponent_type n_exp_;
|
||||
bool n_neg_;
|
||||
bool n_exp_neg_;
|
||||
bool is_key_;
|
||||
|
||||
BOOST_BEAST_DECL
|
||||
static
|
||||
bool
|
||||
append_digit(
|
||||
number::mantissa_type* value,
|
||||
char digit);
|
||||
|
||||
BOOST_BEAST_DECL
|
||||
static
|
||||
bool
|
||||
append_digit(
|
||||
number::exponent_type* value,
|
||||
char digit, bool neg);
|
||||
|
||||
public:
|
||||
/// Returns `true` if the parser has completed without error
|
||||
BOOST_BEAST_DECL
|
||||
bool
|
||||
is_done() const noexcept;
|
||||
|
||||
/** Reset the state, to parse a new document.
|
||||
*/
|
||||
BOOST_BEAST_DECL
|
||||
void
|
||||
reset();
|
||||
|
||||
template<
|
||||
class ConstBufferSequence
|
||||
#ifndef BOOST_BEAST_DOXYGEN
|
||||
,class = typename std::enable_if<
|
||||
! std::is_convertible<
|
||||
ConstBufferSequence,
|
||||
net::const_buffer>::value>::type
|
||||
#endif
|
||||
>
|
||||
std::size_t
|
||||
write_some(
|
||||
ConstBufferSequence const& buffers,
|
||||
error_code& ec);
|
||||
|
||||
BOOST_BEAST_DECL
|
||||
std::size_t
|
||||
write_some(
|
||||
net::const_buffer buffer,
|
||||
error_code& ec);
|
||||
|
||||
template<
|
||||
class ConstBufferSequence
|
||||
#ifndef BOOST_BEAST_DOXYGEN
|
||||
,class = typename std::enable_if<
|
||||
! std::is_convertible<
|
||||
ConstBufferSequence,
|
||||
net::const_buffer>::value>::type
|
||||
#endif
|
||||
>
|
||||
std::size_t
|
||||
write(
|
||||
ConstBufferSequence const& buffers,
|
||||
error_code& ec);
|
||||
|
||||
BOOST_BEAST_DECL
|
||||
std::size_t
|
||||
write(
|
||||
net::const_buffer buffer,
|
||||
error_code& ec);
|
||||
|
||||
BOOST_BEAST_DECL
|
||||
void
|
||||
write_eof(error_code& ec);
|
||||
|
||||
protected:
|
||||
/// Constructor (default)
|
||||
BOOST_BEAST_DECL
|
||||
basic_parser();
|
||||
|
||||
virtual
|
||||
void
|
||||
on_document_begin(error_code& ec) = 0;
|
||||
|
||||
virtual
|
||||
void
|
||||
on_object_begin(error_code& ec) = 0;
|
||||
|
||||
virtual
|
||||
void
|
||||
on_object_end(error_code& ec) = 0;
|
||||
|
||||
virtual
|
||||
void
|
||||
on_array_begin(error_code& ec) = 0;
|
||||
|
||||
virtual
|
||||
void
|
||||
on_array_end(error_code& ec) = 0;
|
||||
|
||||
virtual
|
||||
void
|
||||
on_key_data(
|
||||
string_view s,
|
||||
error_code& ec) = 0;
|
||||
|
||||
virtual
|
||||
void
|
||||
on_key_end(
|
||||
string_view s,
|
||||
error_code& ec) = 0;
|
||||
|
||||
virtual
|
||||
void
|
||||
on_string_data(
|
||||
string_view s,
|
||||
error_code& ec) = 0;
|
||||
|
||||
virtual
|
||||
void
|
||||
on_string_end(
|
||||
string_view,
|
||||
error_code& ec) = 0;
|
||||
|
||||
virtual
|
||||
void
|
||||
on_number(number n, error_code& ec) = 0;
|
||||
|
||||
virtual
|
||||
void
|
||||
on_bool(bool b, error_code& ec) = 0;
|
||||
|
||||
virtual
|
||||
void
|
||||
on_null(error_code& ec) = 0;
|
||||
};
|
||||
|
||||
} // json
|
||||
} // beast
|
||||
} // boost
|
||||
|
||||
#include <boost/json/impl/basic_parser.hpp>
|
||||
#if BOOST_BEAST_HEADER_ONLY
|
||||
#include <boost/json/impl/basic_parser.ipp>
|
||||
#endif
|
||||
|
||||
#endif
|
||||
49
include/boost/json/detail/basic_parser.hpp
Normal file
49
include/boost/json/detail/basic_parser.hpp
Normal file
@@ -0,0 +1,49 @@
|
||||
//
|
||||
// Copyright (c) 2018-2019 Vinnie Falco (vinnie dot falco at gmail dot com)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
// Official repository: https://github.com/boostorg/json
|
||||
//
|
||||
|
||||
#ifndef BOOST_JSON_DETAIL_BASIC_PARSER_HPP
|
||||
#define BOOST_JSON_DETAIL_BASIC_PARSER_HPP
|
||||
|
||||
namespace boost {
|
||||
namespace beast {
|
||||
namespace json {
|
||||
namespace detail {
|
||||
|
||||
struct parser_base
|
||||
{
|
||||
static
|
||||
bool
|
||||
is_ws(char c) noexcept
|
||||
{
|
||||
return
|
||||
c == ' ' || c == '\t' ||
|
||||
c == '\r' || c == '\n';
|
||||
}
|
||||
|
||||
static
|
||||
bool
|
||||
is_digit(char c) noexcept
|
||||
{
|
||||
return static_cast<unsigned char>(c - '0') < 10;
|
||||
}
|
||||
|
||||
static
|
||||
bool
|
||||
is_control(char c)
|
||||
{
|
||||
return static_cast<unsigned char>(c) < 32;
|
||||
}
|
||||
};
|
||||
|
||||
} // detail
|
||||
} // json
|
||||
} // beast
|
||||
} // boost
|
||||
|
||||
#endif
|
||||
39
include/boost/json/detail/is_specialized.hpp
Normal file
39
include/boost/json/detail/is_specialized.hpp
Normal file
@@ -0,0 +1,39 @@
|
||||
//
|
||||
// Copyright (c) 2018-2019 Vinnie Falco (vinnie dot falco at gmail dot com)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
// Official repository: https://github.com/boostorg/json
|
||||
//
|
||||
|
||||
#ifndef BOOST_JSON_DETAIL_IS_SPECIALIZED_HPP
|
||||
#define BOOST_JSON_DETAIL_IS_SPECIALIZED_HPP
|
||||
|
||||
#include <type_traits>
|
||||
|
||||
namespace boost {
|
||||
namespace beast {
|
||||
namespace json {
|
||||
namespace detail {
|
||||
|
||||
struct primary_template
|
||||
{
|
||||
};
|
||||
|
||||
template<class T>
|
||||
using is_specialized =
|
||||
std::integral_constant<bool,
|
||||
! std::is_base_of<primary_template, T>::value>;
|
||||
|
||||
template<class T>
|
||||
using remove_cr =
|
||||
typename std::remove_const<
|
||||
typename std::remove_reference<T>::type>::type;
|
||||
|
||||
} // detail
|
||||
} // json
|
||||
} // beast
|
||||
} // boost
|
||||
|
||||
#endif
|
||||
190
include/boost/json/detail/stack.hpp
Normal file
190
include/boost/json/detail/stack.hpp
Normal file
@@ -0,0 +1,190 @@
|
||||
//
|
||||
// Copyright (c) 2018-2019 Vinnie Falco (vinnie dot falco at gmail dot com)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
// Official repository: https://github.com/boostorg/json
|
||||
//
|
||||
|
||||
#ifndef BOOST_JSON_DETAIL_STACK_HPP
|
||||
#define BOOST_JSON_DETAIL_STACK_HPP
|
||||
|
||||
#include <boost/assert.hpp>
|
||||
#include <new>
|
||||
#include <type_traits>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
namespace boost {
|
||||
namespace beast {
|
||||
namespace json {
|
||||
namespace detail {
|
||||
|
||||
template<class T, std::size_t N>
|
||||
class stack
|
||||
{
|
||||
std::vector<T> v_;
|
||||
std::size_t n_ = 0; // includes v_.size()
|
||||
typename std::aligned_storage<
|
||||
N * sizeof(T), alignof(T)>::type buf_;
|
||||
|
||||
T*
|
||||
base() noexcept
|
||||
{
|
||||
return reinterpret_cast<
|
||||
T*>(&buf_);
|
||||
}
|
||||
|
||||
T const*
|
||||
base() const noexcept
|
||||
{
|
||||
return reinterpret_cast<
|
||||
T const*>(&buf_);
|
||||
}
|
||||
|
||||
void
|
||||
destroy()
|
||||
{
|
||||
for(auto p = base(),
|
||||
last = base() +
|
||||
(n_ < N ? n_ : N);
|
||||
p != last; ++p)
|
||||
{
|
||||
(*p).~T();
|
||||
}
|
||||
}
|
||||
|
||||
public:
|
||||
using value_type = T;
|
||||
|
||||
stack() = default;
|
||||
|
||||
~stack()
|
||||
{
|
||||
destroy();
|
||||
}
|
||||
|
||||
// element access
|
||||
|
||||
T&
|
||||
operator[](std::size_t i) noexcept
|
||||
{
|
||||
BOOST_ASSERT(i < n_);
|
||||
if(v_.empty())
|
||||
return base()[n_ - (i + 1)];
|
||||
if(i < v_.size())
|
||||
return v_[v_.size() - (i + 1)];
|
||||
return base()[
|
||||
N - (v_.size() + i + 1)];
|
||||
}
|
||||
|
||||
T const&
|
||||
operator[](std::size_t i) const noexcept
|
||||
{
|
||||
BOOST_ASSERT(i < n_);
|
||||
if(v_.empty())
|
||||
return base()[n_ - (i + 1)];
|
||||
if(i < v_.size())
|
||||
return v_[v_.size() - (i + 1)];
|
||||
return base()[
|
||||
N - (v_.size() + i + 1)];
|
||||
}
|
||||
|
||||
T&
|
||||
front() noexcept
|
||||
{
|
||||
return (*this)[0];
|
||||
}
|
||||
|
||||
T const&
|
||||
front() const noexcept
|
||||
{
|
||||
return (*this)[0];
|
||||
}
|
||||
|
||||
// capacity
|
||||
|
||||
bool
|
||||
empty() const noexcept
|
||||
{
|
||||
return n_ == 0;
|
||||
}
|
||||
|
||||
std::size_t
|
||||
size() const noexcept
|
||||
{
|
||||
return n_;
|
||||
}
|
||||
|
||||
std::size_t
|
||||
max_size() const noexcept
|
||||
{
|
||||
return v_.max_size();
|
||||
}
|
||||
|
||||
void
|
||||
reserve(std::size_t n)
|
||||
{
|
||||
if(n <= N)
|
||||
return;
|
||||
v_.reserve(n - N);
|
||||
}
|
||||
|
||||
std::size_t
|
||||
capacity() const noexcept
|
||||
{
|
||||
return N + v_.capacity();
|
||||
}
|
||||
|
||||
// modifiers
|
||||
|
||||
void
|
||||
clear() noexcept
|
||||
{
|
||||
v_.clear();
|
||||
destroy();
|
||||
n_ = 0;
|
||||
}
|
||||
|
||||
void
|
||||
push_front(T const& t)
|
||||
{
|
||||
if(n_ < N)
|
||||
::new(&base()[n_]) T(t);
|
||||
else
|
||||
v_.push_back(t);
|
||||
++n_;
|
||||
}
|
||||
|
||||
template<class... Args>
|
||||
void
|
||||
emplace_front(Args&&... args)
|
||||
{
|
||||
if(n_ < N)
|
||||
::new(&base()[n_]) T(
|
||||
std::forward<Args>(args)...);
|
||||
else
|
||||
v_.emplace_back(
|
||||
std::forward<Args>(args)...);
|
||||
++n_;
|
||||
}
|
||||
|
||||
void
|
||||
pop_front()
|
||||
{
|
||||
BOOST_ASSERT(n_ > 0);
|
||||
if(! v_.empty())
|
||||
v_.pop_back();
|
||||
else
|
||||
base()[n_ - 1].~T();
|
||||
--n_;
|
||||
}
|
||||
};
|
||||
|
||||
} // detail
|
||||
} // json
|
||||
} // beast
|
||||
} // boost
|
||||
|
||||
#endif
|
||||
112
include/boost/json/detail/storage_adaptor.hpp
Normal file
112
include/boost/json/detail/storage_adaptor.hpp
Normal file
@@ -0,0 +1,112 @@
|
||||
//
|
||||
// Copyright (c) 2018-2019 Vinnie Falco (vinnie dot falco at gmail dot com)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
// Official repository: https://github.com/boostorg/json
|
||||
//
|
||||
|
||||
#ifndef BOOST_JSON_DETAIL_STORAGE_ADAPTOR_HPP
|
||||
#define BOOST_JSON_DETAIL_STORAGE_ADAPTOR_HPP
|
||||
|
||||
#include <boost/beast/core/detail/config.hpp>
|
||||
#include <boost/beast/core/detail/allocator.hpp>
|
||||
#include <boost/json/storage.hpp>
|
||||
#include <boost/align/align_up.hpp>
|
||||
#include <boost/assert.hpp>
|
||||
#include <boost/core/empty_value.hpp>
|
||||
#include <atomic>
|
||||
#include <cstddef>
|
||||
|
||||
namespace boost {
|
||||
namespace beast {
|
||||
namespace json {
|
||||
namespace detail {
|
||||
|
||||
template<class Allocator>
|
||||
using allocator_of_char =
|
||||
typename beast::detail::allocator_traits<
|
||||
Allocator>::template rebind_alloc<char>;
|
||||
|
||||
template<class Allocator>
|
||||
struct storage_adaptor
|
||||
: boost::empty_value<
|
||||
allocator_of_char<Allocator>>
|
||||
, storage
|
||||
{
|
||||
// VFALCO This is all public because msvc friend bugs
|
||||
|
||||
std::atomic<unsigned> count_;
|
||||
|
||||
explicit
|
||||
storage_adaptor(Allocator const& alloc)
|
||||
: boost::empty_value<
|
||||
allocator_of_char<Allocator>>(
|
||||
boost::empty_init_t{}, alloc)
|
||||
, count_(1)
|
||||
{
|
||||
}
|
||||
|
||||
~storage_adaptor()
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
addref() noexcept override
|
||||
{
|
||||
++count_;
|
||||
}
|
||||
|
||||
void
|
||||
release() noexcept override
|
||||
{
|
||||
if(--count_ > 0)
|
||||
return;
|
||||
delete this;
|
||||
}
|
||||
|
||||
void*
|
||||
allocate(
|
||||
std::size_t n,
|
||||
std::size_t align) override
|
||||
{
|
||||
auto const n1 =
|
||||
boost::alignment::align_up(n, align);
|
||||
BOOST_ASSERT(n1 >= n);
|
||||
return this->get().allocate(n1);
|
||||
}
|
||||
|
||||
void
|
||||
deallocate(
|
||||
void* p,
|
||||
std::size_t n,
|
||||
std::size_t) noexcept override
|
||||
{
|
||||
this->get().deallocate(
|
||||
reinterpret_cast<
|
||||
char*>(p), n);
|
||||
}
|
||||
|
||||
bool
|
||||
is_equal(
|
||||
storage const& other) const noexcept override
|
||||
{
|
||||
auto p = dynamic_cast<
|
||||
storage_adaptor const*>(&other);
|
||||
if(! p)
|
||||
return false;
|
||||
//return this->get() == p->get();
|
||||
// VFALCO We require pointer equality
|
||||
// to prevent objects from different
|
||||
// "documents" getting mixed together.
|
||||
return this == p;
|
||||
}
|
||||
};
|
||||
|
||||
} // detail
|
||||
} // json
|
||||
} // beast
|
||||
} // boost
|
||||
|
||||
#endif
|
||||
150
include/boost/json/detail/value.hpp
Normal file
150
include/boost/json/detail/value.hpp
Normal file
@@ -0,0 +1,150 @@
|
||||
//
|
||||
// Copyright (c) 2018-2019 Vinnie Falco (vinnie dot falco at gmail dot com)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
// Official repository: https://github.com/boostorg/json
|
||||
//
|
||||
|
||||
#ifndef BOOST_JSON_DETAIL_VALUE_HPP
|
||||
#define BOOST_JSON_DETAIL_VALUE_HPP
|
||||
|
||||
#include <boost/beast/core/error.hpp>
|
||||
#include <boost/type_traits/make_void.hpp>
|
||||
#include <type_traits>
|
||||
|
||||
namespace boost {
|
||||
namespace beast {
|
||||
namespace json {
|
||||
|
||||
class value;
|
||||
|
||||
namespace detail {
|
||||
|
||||
// Determine if `to_json(value&,T)` is found via ADL
|
||||
template<class T, class = void>
|
||||
struct has_adl_to_json : std::false_type
|
||||
{
|
||||
};
|
||||
|
||||
template<class T>
|
||||
struct has_adl_to_json<T,
|
||||
boost::void_t<decltype(to_json(
|
||||
std::declval<T const&>(),
|
||||
std::declval<json::value&>()))>>
|
||||
: std::true_type
|
||||
{
|
||||
};
|
||||
|
||||
// Determine if `from_json(T&,value)` is found via ADL
|
||||
template<class T, class = void>
|
||||
struct has_adl_from_json : std::false_type
|
||||
{
|
||||
};
|
||||
|
||||
template<class T>
|
||||
struct has_adl_from_json<T,
|
||||
boost::void_t<decltype(from_json(
|
||||
std::declval<T&>(),
|
||||
std::declval<json::value const&>()))>>
|
||||
: std::true_type
|
||||
{
|
||||
};
|
||||
|
||||
// Determine if `t.to_json(value&)` exists
|
||||
template<class T, class = void>
|
||||
struct has_mf_to_json : std::false_type
|
||||
{
|
||||
};
|
||||
|
||||
template<class T>
|
||||
struct has_mf_to_json<T,
|
||||
boost::void_t<decltype(
|
||||
std::declval<T const&>().to_json(
|
||||
std::declval<json::value&>()))>>
|
||||
: std::true_type
|
||||
{
|
||||
};
|
||||
|
||||
// Determine if `t.to_json(value const&)` exists
|
||||
template<class T, class = void>
|
||||
struct has_mf_from_json : std::false_type
|
||||
{
|
||||
};
|
||||
|
||||
template<class T>
|
||||
struct has_mf_from_json<T,
|
||||
boost::void_t<decltype(
|
||||
std::declval<T&>().from_json(
|
||||
std::declval<json::value const&>()))>>
|
||||
: std::true_type
|
||||
{
|
||||
};
|
||||
|
||||
template<class T>
|
||||
void
|
||||
call_to_json(
|
||||
T const& t,
|
||||
value& v,
|
||||
std::true_type)
|
||||
{
|
||||
t.to_json(v);
|
||||
}
|
||||
|
||||
template<class T>
|
||||
void
|
||||
call_to_json(
|
||||
T const& t,
|
||||
value& v,
|
||||
std::false_type)
|
||||
{
|
||||
to_json(t, v);
|
||||
}
|
||||
|
||||
template<class T>
|
||||
void
|
||||
call_to_json(
|
||||
T const& t,
|
||||
value& v)
|
||||
{
|
||||
call_to_json(t, v,
|
||||
has_mf_to_json<T>{});
|
||||
}
|
||||
|
||||
template<class T>
|
||||
void
|
||||
call_from_json(
|
||||
T& t,
|
||||
value const& v,
|
||||
std::true_type)
|
||||
{
|
||||
t.from_json(v);
|
||||
}
|
||||
|
||||
template<class T>
|
||||
void
|
||||
call_from_json(
|
||||
T& t,
|
||||
value const& v,
|
||||
std::false_type)
|
||||
{
|
||||
from_json(t, v);
|
||||
}
|
||||
|
||||
template<class T>
|
||||
void
|
||||
call_from_json(
|
||||
T& t,
|
||||
value const& v)
|
||||
{
|
||||
call_from_json(t, v,
|
||||
has_mf_from_json<T>{});
|
||||
}
|
||||
|
||||
} // detail
|
||||
} // json
|
||||
} // beast
|
||||
} // boost
|
||||
|
||||
#endif
|
||||
45
include/boost/json/detail/varint.hpp
Normal file
45
include/boost/json/detail/varint.hpp
Normal file
@@ -0,0 +1,45 @@
|
||||
//
|
||||
// Copyright (c) 2018-2019 Vinnie Falco (vinnie dot falco at gmail dot com)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
// Official repository: https://github.com/boostorg/json
|
||||
//
|
||||
|
||||
#ifndef BOOST_JSON_DETAIL_VARINT_HPP
|
||||
#define BOOST_JSON_DETAIL_VARINT_HPP
|
||||
|
||||
#include <cstdlib>
|
||||
#include <cstdint>
|
||||
#include <utility>
|
||||
|
||||
namespace boost {
|
||||
namespace beast {
|
||||
namespace json {
|
||||
namespace detail {
|
||||
|
||||
BOOST_BEAST_DECL
|
||||
int
|
||||
varint_size(std::uint64_t value);
|
||||
|
||||
BOOST_BEAST_DECL
|
||||
std::pair<std::uint64_t, int>
|
||||
varint_read(void const* src);
|
||||
|
||||
BOOST_BEAST_DECL
|
||||
int
|
||||
varint_write(
|
||||
void* dest,
|
||||
std::uint64_t value);
|
||||
|
||||
} // detail
|
||||
} // json
|
||||
} // beast
|
||||
} // boost
|
||||
|
||||
#ifdef BOOST_BEAST_HEADER_ONLY
|
||||
#include <boost/json/detail/varint.ipp>
|
||||
#endif
|
||||
|
||||
#endif
|
||||
75
include/boost/json/detail/varint.ipp
Normal file
75
include/boost/json/detail/varint.ipp
Normal file
@@ -0,0 +1,75 @@
|
||||
//
|
||||
// Copyright (c) 2018-2019 Vinnie Falco (vinnie dot falco at gmail dot com)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
// Official repository: https://github.com/boostorg/json
|
||||
//
|
||||
|
||||
#ifndef BOOST_JSON_DETAIL_VARINT_IPP
|
||||
#define BOOST_JSON_DETAIL_VARINT_IPP
|
||||
|
||||
#include <boost/json/detail/varint.hpp>
|
||||
#include <utility>
|
||||
|
||||
namespace boost {
|
||||
namespace beast {
|
||||
namespace json {
|
||||
namespace detail {
|
||||
|
||||
int
|
||||
varint_size(std::uint64_t value)
|
||||
{
|
||||
int n = 1;
|
||||
while(value > 127)
|
||||
{
|
||||
++n;
|
||||
value /= 128;
|
||||
}
|
||||
return n;
|
||||
}
|
||||
|
||||
std::pair<std::uint64_t, int>
|
||||
varint_read(void const* src)
|
||||
{
|
||||
auto cp0 = reinterpret_cast<
|
||||
unsigned char const*>(src);
|
||||
auto cp = cp0;
|
||||
std::size_t value = 0;
|
||||
std::size_t factor = 1;
|
||||
while(*cp > 127)
|
||||
{
|
||||
value += (*cp++ & 0x7f) * factor;
|
||||
factor *= 128;
|
||||
}
|
||||
value += *cp++ * factor;
|
||||
return {value,
|
||||
static_cast<int>(cp - cp0)};
|
||||
}
|
||||
|
||||
int
|
||||
varint_write(
|
||||
void* dest,
|
||||
std::uint64_t value)
|
||||
{
|
||||
auto cp0 = reinterpret_cast<
|
||||
unsigned char*>(dest);
|
||||
auto cp = cp0;
|
||||
while(value > 127)
|
||||
{
|
||||
*cp++ = static_cast<
|
||||
unsigned char>(value & 0x7f);
|
||||
value >>= 7;
|
||||
}
|
||||
*cp++ = static_cast<
|
||||
unsigned char>(value);
|
||||
return static_cast<int>(cp - cp0);
|
||||
}
|
||||
|
||||
} // detail
|
||||
} // json
|
||||
} // beast
|
||||
} // boost
|
||||
|
||||
#endif
|
||||
81
include/boost/json/error.hpp
Normal file
81
include/boost/json/error.hpp
Normal file
@@ -0,0 +1,81 @@
|
||||
//
|
||||
// Copyright (c) 2018-2019 Vinnie Falco (vinnie dot falco at gmail dot com)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
// Official repository: https://github.com/boostorg/json
|
||||
//
|
||||
|
||||
#ifndef BOOST_JSON_ERROR_HPP
|
||||
#define BOOST_JSON_ERROR_HPP
|
||||
|
||||
#include <boost/beast/core/detail/config.hpp>
|
||||
#include <boost/beast/core/error.hpp>
|
||||
|
||||
namespace boost {
|
||||
namespace beast {
|
||||
namespace json {
|
||||
|
||||
/// Error codes returned by JSON operations
|
||||
enum class error
|
||||
{
|
||||
syntax = 1,
|
||||
|
||||
/// Unexpected extra data encountered while parsing
|
||||
extra_data,
|
||||
|
||||
/// A mantissa overflowed while parsing
|
||||
mantissa_overflow,
|
||||
|
||||
/// The parser encountered an exponent that overflowed
|
||||
exponent_overflow,
|
||||
|
||||
/// The parser's maximum depth limit was reached
|
||||
too_deep,
|
||||
|
||||
/// Expected a value of kind object
|
||||
expected_object,
|
||||
|
||||
/// Expected a value of kind array
|
||||
expected_array,
|
||||
|
||||
/// Expected a value of kind string
|
||||
expected_string,
|
||||
|
||||
/// Expect a value of kind number
|
||||
expected_number,
|
||||
|
||||
/// Expected a value of kind boolean
|
||||
expected_bool,
|
||||
|
||||
/// Expected a value of kind boolean
|
||||
expected_null,
|
||||
|
||||
/// An integer assignment would overflow
|
||||
integer_overflow,
|
||||
|
||||
/// The key was not found in the object
|
||||
key_not_found
|
||||
};
|
||||
|
||||
/// Error conditions corresponding to JSON errors
|
||||
enum class condition
|
||||
{
|
||||
/// A parser-related error
|
||||
parse_error = 1,
|
||||
|
||||
/// An error on assignment to or from a JSON value
|
||||
assign_error
|
||||
};
|
||||
|
||||
} // websocket
|
||||
} // beast
|
||||
} // boost
|
||||
|
||||
#include <boost/json/impl/error.hpp>
|
||||
#ifdef BOOST_BEAST_HEADER_ONLY
|
||||
#include <boost/json/impl/error.ipp>
|
||||
#endif
|
||||
|
||||
#endif
|
||||
99
include/boost/json/impl/allocator.hpp
Normal file
99
include/boost/json/impl/allocator.hpp
Normal file
@@ -0,0 +1,99 @@
|
||||
//
|
||||
// Copyright (c) 2018-2019 Vinnie Falco (vinnie dot falco at gmail dot com)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
// Official repository: https://github.com/boostorg/json
|
||||
//
|
||||
|
||||
#ifndef BOOST_JSON_IMPL_ALLOCATOR_HPP
|
||||
#define BOOST_JSON_IMPL_ALLOCATOR_HPP
|
||||
|
||||
#include <memory>
|
||||
#include <utility>
|
||||
|
||||
namespace boost {
|
||||
namespace beast {
|
||||
namespace json {
|
||||
|
||||
template<typename T>
|
||||
allocator<T>::
|
||||
allocator()
|
||||
: sp_(default_storage())
|
||||
{
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
allocator<T>::
|
||||
allocator(allocator&& other) noexcept
|
||||
: allocator(other)
|
||||
{
|
||||
// Postcondition: *this == other
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
auto
|
||||
allocator<T>::
|
||||
operator=(allocator&& other) noexcept ->
|
||||
allocator&
|
||||
{
|
||||
// Postcondition: *this == other
|
||||
sp_ = other.sp_;
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
template<typename U>
|
||||
allocator<T>::
|
||||
allocator(allocator<U> const& other) noexcept
|
||||
: sp_(other.sp_)
|
||||
{
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
allocator<T>::
|
||||
allocator(storage_ptr sp) noexcept
|
||||
: sp_(std::move(sp))
|
||||
{
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
T*
|
||||
allocator<T>::
|
||||
allocate(size_t n)
|
||||
{
|
||||
return static_cast<T*>(sp_->allocate(
|
||||
n * sizeof(T), alignof(T)));
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void
|
||||
allocator<T>::
|
||||
deallocate(T* p, size_t n) noexcept
|
||||
{
|
||||
sp_->deallocate(
|
||||
p, n * sizeof(T), alignof(T));
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
bool
|
||||
allocator<T>::
|
||||
operator==(allocator const& other) const noexcept
|
||||
{
|
||||
return *sp_ == *other.sp_;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
bool
|
||||
allocator<T>::
|
||||
operator!=(allocator const& other) const noexcept
|
||||
{
|
||||
return *sp_ != *other.sp_;
|
||||
}
|
||||
|
||||
} // json
|
||||
} // beast
|
||||
} // boost
|
||||
|
||||
#endif
|
||||
262
include/boost/json/impl/array.hpp
Normal file
262
include/boost/json/impl/array.hpp
Normal file
@@ -0,0 +1,262 @@
|
||||
//
|
||||
// Copyright (c) 2018-2019 Vinnie Falco (vinnie dot falco at gmail dot com)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
// Official repository: https://github.com/boostorg/json
|
||||
//
|
||||
|
||||
#ifndef BOOST_JSON_IMPL_ARRAY_HPP
|
||||
#define BOOST_JSON_IMPL_ARRAY_HPP
|
||||
|
||||
#include <boost/json/value.hpp>
|
||||
#include <boost/core/exchange.hpp>
|
||||
#include <boost/static_assert.hpp>
|
||||
#include <algorithm>
|
||||
#include <type_traits>
|
||||
|
||||
namespace boost {
|
||||
namespace beast {
|
||||
namespace json {
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
class array::table
|
||||
{
|
||||
union
|
||||
{
|
||||
std::size_t capacity_;
|
||||
value unused_; // for alignment
|
||||
};
|
||||
|
||||
BOOST_STATIC_ASSERT(
|
||||
sizeof(value) >= sizeof(std::size_t));
|
||||
|
||||
BOOST_BEAST_DECL
|
||||
~table();
|
||||
|
||||
public:
|
||||
size_type size = 0;
|
||||
|
||||
explicit
|
||||
table(size_type capacity)
|
||||
: capacity_(capacity)
|
||||
{
|
||||
}
|
||||
|
||||
size_type
|
||||
capacity() const noexcept
|
||||
{
|
||||
return capacity_;
|
||||
}
|
||||
|
||||
value_type*
|
||||
begin() noexcept
|
||||
{
|
||||
return reinterpret_cast<
|
||||
value_type*>(this + 1);
|
||||
}
|
||||
|
||||
value_type*
|
||||
end() noexcept
|
||||
{
|
||||
return begin() + size;
|
||||
}
|
||||
|
||||
BOOST_BEAST_DECL
|
||||
static
|
||||
table*
|
||||
create(
|
||||
size_type capacity,
|
||||
storage_ptr const& sp);
|
||||
|
||||
BOOST_BEAST_DECL
|
||||
static
|
||||
void
|
||||
destroy(
|
||||
table* tab,
|
||||
storage_ptr const& sp);
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
struct array::cleanup_assign
|
||||
{
|
||||
array& self;
|
||||
table* tab;
|
||||
bool ok = false;
|
||||
|
||||
BOOST_BEAST_DECL
|
||||
explicit
|
||||
cleanup_assign(
|
||||
array& self);
|
||||
|
||||
BOOST_BEAST_DECL
|
||||
~cleanup_assign();
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
struct array::cleanup_insert
|
||||
{
|
||||
array& self;
|
||||
size_type pos;
|
||||
size_type n;
|
||||
size_type valid = 0;
|
||||
bool ok = false;
|
||||
|
||||
BOOST_BEAST_DECL
|
||||
cleanup_insert(
|
||||
size_type pos_,
|
||||
size_type n_,
|
||||
array& self_);
|
||||
|
||||
BOOST_BEAST_DECL
|
||||
~cleanup_insert();
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
template<class InputIt>
|
||||
array::
|
||||
array(
|
||||
InputIt first, InputIt last)
|
||||
: array(
|
||||
first, last,
|
||||
default_storage())
|
||||
{
|
||||
}
|
||||
|
||||
template<class InputIt>
|
||||
array::
|
||||
array(
|
||||
InputIt first, InputIt last,
|
||||
storage_ptr store)
|
||||
: array(
|
||||
first, last,
|
||||
std::move(store),
|
||||
iter_cat<InputIt>{})
|
||||
{
|
||||
}
|
||||
|
||||
template<class InputIt>
|
||||
auto
|
||||
array::
|
||||
insert(
|
||||
const_iterator before,
|
||||
InputIt first, InputIt last) ->
|
||||
iterator
|
||||
{
|
||||
return insert(before, first, last,
|
||||
iter_cat<InputIt>{});
|
||||
}
|
||||
|
||||
template<class Arg>
|
||||
auto
|
||||
array::
|
||||
emplace(
|
||||
const_iterator before,
|
||||
Arg&& arg) ->
|
||||
iterator
|
||||
{
|
||||
return emplace_impl(
|
||||
before, std::forward<Arg>(arg));
|
||||
}
|
||||
|
||||
template<class Arg>
|
||||
auto
|
||||
array::
|
||||
emplace_back(Arg&& arg) ->
|
||||
reference
|
||||
{
|
||||
return *emplace_impl(
|
||||
end(), std::forward<Arg>(arg));
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
template<class InputIt>
|
||||
array::
|
||||
array(
|
||||
InputIt first, InputIt last,
|
||||
storage_ptr store,
|
||||
std::input_iterator_tag)
|
||||
: sp_(std::move(store))
|
||||
{
|
||||
while(first != last)
|
||||
emplace_impl(end(), *first++);
|
||||
}
|
||||
|
||||
template<class InputIt>
|
||||
array::
|
||||
array(
|
||||
InputIt first, InputIt last,
|
||||
storage_ptr store,
|
||||
std::forward_iterator_tag)
|
||||
: sp_(std::move(store))
|
||||
{
|
||||
reserve(std::distance(first, last));
|
||||
while(first != last)
|
||||
emplace_impl(end(), *first++);
|
||||
}
|
||||
template<class InputIt>
|
||||
auto
|
||||
array::
|
||||
insert(
|
||||
const_iterator before,
|
||||
InputIt first, InputIt last,
|
||||
std::input_iterator_tag) ->
|
||||
iterator
|
||||
{
|
||||
auto pos = before - begin();
|
||||
while(first != last)
|
||||
before = insert(before, *first++) + 1;
|
||||
return begin() + pos;
|
||||
}
|
||||
|
||||
template<class InputIt>
|
||||
auto
|
||||
array::
|
||||
insert(
|
||||
const_iterator before,
|
||||
InputIt first, InputIt last,
|
||||
std::forward_iterator_tag) ->
|
||||
iterator
|
||||
{
|
||||
auto count = std::distance(first, last);
|
||||
auto pos = before - begin();
|
||||
reserve(size() + count);
|
||||
cleanup_insert c(pos, count, *this);
|
||||
while(count--)
|
||||
{
|
||||
::new(&begin()[pos++]) value_type(
|
||||
*first++, sp_);
|
||||
++c.valid;
|
||||
}
|
||||
c.ok = true;
|
||||
return begin() + c.pos;
|
||||
}
|
||||
|
||||
template<class Arg>
|
||||
auto
|
||||
array::
|
||||
emplace_impl(
|
||||
const_iterator before,
|
||||
Arg&& arg) ->
|
||||
iterator
|
||||
{
|
||||
auto const pos = before - begin();
|
||||
reserve(size() + 1);
|
||||
cleanup_insert c(pos, 1, *this);
|
||||
::new(&tab_->begin()[pos]) value_type(
|
||||
std::forward<Arg>(arg), sp_);
|
||||
c.ok = true;
|
||||
return begin() + pos;
|
||||
}
|
||||
|
||||
} // json
|
||||
} // beast
|
||||
} // boost
|
||||
|
||||
#endif
|
||||
746
include/boost/json/impl/array.ipp
Normal file
746
include/boost/json/impl/array.ipp
Normal file
@@ -0,0 +1,746 @@
|
||||
//
|
||||
// Copyright (c) 2018-2019 Vinnie Falco (vinnie dot falco at gmail dot com)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
// Official repository: https://github.com/boostorg/json
|
||||
//
|
||||
|
||||
#ifndef BOOST_JSON_IMPL_ARRAY_IPP
|
||||
#define BOOST_JSON_IMPL_ARRAY_IPP
|
||||
|
||||
#include <boost/json/array.hpp>
|
||||
#include <boost/core/exchange.hpp>
|
||||
#include <boost/assert.hpp>
|
||||
#include <algorithm>
|
||||
#include <cstdlib>
|
||||
#include <limits>
|
||||
#include <new>
|
||||
#include <stdexcept>
|
||||
#include <type_traits>
|
||||
#include <utility>
|
||||
|
||||
namespace boost {
|
||||
namespace beast {
|
||||
namespace json {
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
array::
|
||||
table::
|
||||
~table()
|
||||
{
|
||||
while(size > 0)
|
||||
begin()[--size].~value();
|
||||
}
|
||||
|
||||
auto
|
||||
array::
|
||||
table::
|
||||
create(
|
||||
size_type capacity,
|
||||
storage_ptr const& sp) ->
|
||||
table*
|
||||
{
|
||||
return ::new(sp->allocate(
|
||||
sizeof(table) +
|
||||
capacity * sizeof(value_type),
|
||||
sizeof(value))) table(capacity);
|
||||
}
|
||||
|
||||
void
|
||||
array::
|
||||
table::
|
||||
destroy(
|
||||
table* tab,
|
||||
storage_ptr const& sp)
|
||||
{
|
||||
auto const capacity = tab->capacity();
|
||||
tab->~table();
|
||||
sp->deallocate(tab,
|
||||
sizeof(table) +
|
||||
capacity * sizeof(value_type),
|
||||
sizeof(value));
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
array::
|
||||
cleanup_assign::
|
||||
cleanup_assign(
|
||||
array& self_)
|
||||
: self(self_)
|
||||
, tab(boost::exchange(
|
||||
self_.tab_, nullptr))
|
||||
{
|
||||
}
|
||||
|
||||
array::
|
||||
cleanup_assign::
|
||||
~cleanup_assign()
|
||||
{
|
||||
if(ok)
|
||||
{
|
||||
if(tab)
|
||||
table::destroy(tab, self.sp_);
|
||||
}
|
||||
else
|
||||
{
|
||||
if(self.tab_)
|
||||
table::destroy(
|
||||
self.tab_, self.sp_);
|
||||
self.tab_ = tab;
|
||||
}
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
array::
|
||||
cleanup_insert::
|
||||
cleanup_insert(
|
||||
size_type pos_,
|
||||
size_type n_,
|
||||
array& self_)
|
||||
: self(self_)
|
||||
, pos(pos_)
|
||||
, n(n_)
|
||||
{
|
||||
self.move(
|
||||
self.data() + pos + n,
|
||||
self.data() + pos,
|
||||
self.size() - pos);
|
||||
}
|
||||
|
||||
array::
|
||||
cleanup_insert::
|
||||
~cleanup_insert()
|
||||
{
|
||||
if(ok)
|
||||
{
|
||||
self.tab_->size += n;
|
||||
}
|
||||
else
|
||||
{
|
||||
for(size_type i = n;
|
||||
valid--; ++i)
|
||||
self[i].~value();
|
||||
|
||||
self.move(
|
||||
self.data() + pos,
|
||||
self.data() + pos + n,
|
||||
self.size() - pos);
|
||||
}
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
//
|
||||
// Special Members
|
||||
//
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
array::
|
||||
~array()
|
||||
{
|
||||
if(tab_)
|
||||
table::destroy(tab_, sp_);
|
||||
}
|
||||
|
||||
array::
|
||||
array()
|
||||
: sp_(default_storage())
|
||||
{
|
||||
}
|
||||
|
||||
array::
|
||||
array(storage_ptr store)
|
||||
: sp_(std::move(store))
|
||||
{
|
||||
}
|
||||
|
||||
array::
|
||||
array(
|
||||
size_type count)
|
||||
: array(
|
||||
count, kind::null,
|
||||
default_storage())
|
||||
{
|
||||
}
|
||||
|
||||
array::
|
||||
array(
|
||||
size_type count,
|
||||
storage_ptr store)
|
||||
: array(
|
||||
count, kind::null,
|
||||
std::move(store))
|
||||
{
|
||||
}
|
||||
|
||||
array::
|
||||
array(
|
||||
size_type count,
|
||||
value_type const& v)
|
||||
: array(
|
||||
count, v,
|
||||
default_storage())
|
||||
{
|
||||
}
|
||||
|
||||
array::
|
||||
array(
|
||||
size_type count,
|
||||
value_type const& v,
|
||||
storage_ptr store)
|
||||
: sp_(std::move(store))
|
||||
{
|
||||
resize(count, v);
|
||||
}
|
||||
|
||||
array::
|
||||
array(array const& other)
|
||||
: sp_(other.get_storage())
|
||||
{
|
||||
*this = other;
|
||||
}
|
||||
|
||||
array::
|
||||
array(
|
||||
array const& other,
|
||||
storage_ptr store)
|
||||
: sp_(std::move(store))
|
||||
{
|
||||
*this = other;
|
||||
}
|
||||
|
||||
array::
|
||||
array(array&& other) noexcept
|
||||
: tab_(boost::exchange(
|
||||
other.tab_, nullptr))
|
||||
, sp_(other.sp_)
|
||||
{
|
||||
}
|
||||
|
||||
array::
|
||||
array(
|
||||
array&& other,
|
||||
storage_ptr store)
|
||||
: sp_(std::move(store))
|
||||
{
|
||||
*this = std::move(other);
|
||||
}
|
||||
|
||||
array::
|
||||
array(
|
||||
std::initializer_list<value_type> list)
|
||||
: sp_(default_storage())
|
||||
{
|
||||
*this = list;
|
||||
}
|
||||
|
||||
array::
|
||||
array(
|
||||
std::initializer_list<value_type> list,
|
||||
storage_ptr store)
|
||||
: sp_(std::move(store))
|
||||
{
|
||||
*this = list;
|
||||
}
|
||||
|
||||
array&
|
||||
array::
|
||||
operator=(array&& other)
|
||||
{
|
||||
if(*sp_ == *other.sp_)
|
||||
{
|
||||
if(tab_)
|
||||
table::destroy(tab_, sp_);
|
||||
tab_ = boost::exchange(
|
||||
other.tab_, nullptr);
|
||||
}
|
||||
else
|
||||
{
|
||||
*this = other;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
array&
|
||||
array::
|
||||
operator=(array const& other)
|
||||
{
|
||||
cleanup_assign c(*this);
|
||||
reserve(other.size());
|
||||
for(auto const& v : other)
|
||||
emplace_impl(end(), v);
|
||||
c.ok = true;
|
||||
return *this;
|
||||
}
|
||||
|
||||
array&
|
||||
array::
|
||||
operator=(
|
||||
std::initializer_list<value_type> list)
|
||||
{
|
||||
cleanup_assign c(*this);
|
||||
reserve(list.size());
|
||||
for(auto it = list.begin();
|
||||
it != list.end(); ++it)
|
||||
emplace_impl(end(), std::move(*it));
|
||||
c.ok = true;
|
||||
return *this;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
//
|
||||
// Elements
|
||||
//
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
auto
|
||||
array::
|
||||
at(size_type pos) ->
|
||||
reference
|
||||
{
|
||||
if(pos >= size())
|
||||
throw std::out_of_range(
|
||||
"json::array index out of bounds");
|
||||
return tab_->begin()[pos];
|
||||
}
|
||||
|
||||
auto
|
||||
array::
|
||||
at(size_type pos) const ->
|
||||
const_reference
|
||||
{
|
||||
if(pos >= size())
|
||||
throw std::out_of_range(
|
||||
"json::array index out of bounds");
|
||||
return tab_->begin()[pos];
|
||||
}
|
||||
|
||||
auto
|
||||
array::
|
||||
operator[](size_type pos) ->
|
||||
reference
|
||||
{
|
||||
return tab_->begin()[pos];
|
||||
}
|
||||
|
||||
auto
|
||||
array::
|
||||
operator[](size_type pos) const ->
|
||||
const_reference
|
||||
{
|
||||
return tab_->begin()[pos];
|
||||
}
|
||||
|
||||
auto
|
||||
array::
|
||||
data() noexcept ->
|
||||
value_type*
|
||||
{
|
||||
if(! tab_)
|
||||
return nullptr;
|
||||
return tab_->begin();
|
||||
}
|
||||
|
||||
auto
|
||||
array::
|
||||
data() const noexcept ->
|
||||
value_type const*
|
||||
{
|
||||
if(! tab_)
|
||||
return nullptr;
|
||||
return tab_->begin();
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
//
|
||||
// Iterators
|
||||
//
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
auto
|
||||
array::
|
||||
begin() noexcept ->
|
||||
iterator
|
||||
{
|
||||
if(! tab_)
|
||||
return nullptr;
|
||||
return tab_->begin();
|
||||
}
|
||||
|
||||
auto
|
||||
array::
|
||||
begin() const noexcept ->
|
||||
const_iterator
|
||||
{
|
||||
if(! tab_)
|
||||
return nullptr;
|
||||
return tab_->begin();
|
||||
}
|
||||
|
||||
auto
|
||||
array::
|
||||
end() noexcept ->
|
||||
iterator
|
||||
{
|
||||
if(! tab_)
|
||||
return nullptr;
|
||||
return tab_->end();
|
||||
}
|
||||
|
||||
auto
|
||||
array::
|
||||
end() const noexcept ->
|
||||
const_iterator
|
||||
{
|
||||
if(! tab_)
|
||||
return nullptr;
|
||||
return tab_->end();
|
||||
}
|
||||
|
||||
auto
|
||||
array::
|
||||
rbegin() noexcept ->
|
||||
reverse_iterator
|
||||
{
|
||||
if(! tab_)
|
||||
return reverse_iterator(nullptr);
|
||||
return reverse_iterator(tab_->end());
|
||||
}
|
||||
|
||||
auto
|
||||
array::
|
||||
rbegin() const noexcept ->
|
||||
const_reverse_iterator
|
||||
{
|
||||
if(! tab_)
|
||||
return const_reverse_iterator(nullptr);
|
||||
return const_reverse_iterator(tab_->end());
|
||||
}
|
||||
|
||||
auto
|
||||
array::
|
||||
rend() noexcept ->
|
||||
reverse_iterator
|
||||
{
|
||||
if(! tab_)
|
||||
return reverse_iterator(nullptr);
|
||||
return reverse_iterator(tab_->begin());
|
||||
}
|
||||
|
||||
auto
|
||||
array::
|
||||
rend() const noexcept ->
|
||||
const_reverse_iterator
|
||||
{
|
||||
if(! tab_)
|
||||
return const_reverse_iterator(nullptr);
|
||||
return const_reverse_iterator(tab_->begin());
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
//
|
||||
// Capacity
|
||||
//
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
bool
|
||||
array::
|
||||
empty() const noexcept
|
||||
{
|
||||
return ! tab_ || tab_->size == 0;
|
||||
}
|
||||
|
||||
auto
|
||||
array::
|
||||
size() const noexcept ->
|
||||
size_type
|
||||
{
|
||||
if(! tab_)
|
||||
return 0;
|
||||
return tab_->size;
|
||||
}
|
||||
|
||||
auto
|
||||
array::
|
||||
max_size() const noexcept ->
|
||||
size_type
|
||||
{
|
||||
return (std::numeric_limits<
|
||||
size_type>::max)() / sizeof(value_type);
|
||||
}
|
||||
|
||||
void
|
||||
array::
|
||||
reserve(size_type new_capacity)
|
||||
{
|
||||
// minimum size is 3
|
||||
if( new_capacity > 0 &&
|
||||
new_capacity < 3)
|
||||
new_capacity = 3;
|
||||
|
||||
// don't shrink
|
||||
if( tab_ &&
|
||||
new_capacity <= tab_->capacity())
|
||||
return;
|
||||
new_capacity = (std::max<size_type>)(
|
||||
tab_ ? ((tab_->capacity() * 3 + 1) / 2) : 0,
|
||||
new_capacity);
|
||||
|
||||
auto tab = table::create(new_capacity, sp_);
|
||||
if(! tab_)
|
||||
{
|
||||
tab_ = tab;
|
||||
return;
|
||||
}
|
||||
|
||||
for(size_type i = 0; i < tab_->size; ++i)
|
||||
::new(&tab->begin()[i]) value_type(
|
||||
std::move(tab_->begin()[i]));
|
||||
tab->size = tab_->size;
|
||||
std::swap(tab, tab_);
|
||||
table::destroy(tab, sp_);
|
||||
}
|
||||
|
||||
auto
|
||||
array::
|
||||
capacity() const noexcept ->
|
||||
size_type
|
||||
{
|
||||
if(! tab_)
|
||||
return 0;
|
||||
return tab_->capacity();
|
||||
}
|
||||
|
||||
void
|
||||
array::
|
||||
shrink_to_fit() noexcept
|
||||
{
|
||||
if(! tab_ ||
|
||||
tab_->capacity() <= tab_->size)
|
||||
return;
|
||||
auto tab = table::create(tab_->size, sp_);
|
||||
for(size_type i = 0; i < tab_->size; ++i)
|
||||
::new(&tab->begin()[i]) value_type(
|
||||
std::move(tab_->begin()[i]));
|
||||
tab->size = tab_->size;
|
||||
std::swap(tab, tab_);
|
||||
table::destroy(tab, sp_);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
//
|
||||
// Modifiers
|
||||
//
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
void
|
||||
array::
|
||||
clear() noexcept
|
||||
{
|
||||
if(! tab_)
|
||||
return;
|
||||
destroy(begin(), end());
|
||||
tab_->size = 0;
|
||||
}
|
||||
|
||||
auto
|
||||
array::
|
||||
insert(
|
||||
const_iterator before,
|
||||
value_type const& v) ->
|
||||
iterator
|
||||
{
|
||||
return emplace_impl(before, v);
|
||||
}
|
||||
|
||||
auto
|
||||
array::
|
||||
insert(
|
||||
const_iterator before,
|
||||
value_type&& v) ->
|
||||
iterator
|
||||
{
|
||||
return emplace_impl(
|
||||
before, std::move(v));
|
||||
}
|
||||
|
||||
auto
|
||||
array::
|
||||
insert(
|
||||
const_iterator before,
|
||||
size_type count,
|
||||
value_type const& v) ->
|
||||
iterator
|
||||
{
|
||||
auto pos = before - begin();
|
||||
reserve(size() + count);
|
||||
cleanup_insert c(pos, count, *this);
|
||||
while(count--)
|
||||
{
|
||||
::new(&begin()[pos++])
|
||||
value_type(v, sp_);
|
||||
++c.valid;
|
||||
}
|
||||
c.ok = true;
|
||||
return begin() + c.pos;
|
||||
}
|
||||
|
||||
auto
|
||||
array::
|
||||
insert(
|
||||
const_iterator before,
|
||||
std::initializer_list<value_type> list) ->
|
||||
iterator
|
||||
{
|
||||
auto pos = before - begin();
|
||||
reserve(size() + list.size());
|
||||
cleanup_insert c(
|
||||
pos, list.size(), *this);
|
||||
for(auto it = list.begin();
|
||||
it != list.end(); ++it)
|
||||
{
|
||||
::new(&begin()[pos++]) value_type(
|
||||
std::move(*it), sp_);
|
||||
++c.valid;
|
||||
}
|
||||
c.ok = true;
|
||||
return begin() + c.pos;
|
||||
}
|
||||
|
||||
auto
|
||||
array::
|
||||
erase(const_iterator pos) ->
|
||||
iterator
|
||||
{
|
||||
auto it = data() + (pos - begin());
|
||||
destroy(it, it + 1);
|
||||
move(it, it + 1, 1);
|
||||
--tab_->size;
|
||||
return it;
|
||||
}
|
||||
|
||||
auto
|
||||
array::
|
||||
erase(
|
||||
const_iterator first,
|
||||
const_iterator last) ->
|
||||
iterator
|
||||
{
|
||||
auto const n = last - first;
|
||||
auto it = data() + (first - begin());
|
||||
destroy(it, it + n);
|
||||
move(it, it + n, n);
|
||||
tab_->size -= n;
|
||||
return it;
|
||||
}
|
||||
|
||||
void
|
||||
array::
|
||||
push_back(value_type const& v)
|
||||
{
|
||||
emplace_impl(end(), v);
|
||||
}
|
||||
|
||||
void
|
||||
array::
|
||||
push_back(value_type&& v)
|
||||
{
|
||||
emplace_impl(end(), std::move(v));
|
||||
}
|
||||
|
||||
void
|
||||
array::
|
||||
pop_back()
|
||||
{
|
||||
back().~value();
|
||||
--tab_->size;
|
||||
}
|
||||
|
||||
void
|
||||
array::
|
||||
resize(size_type count)
|
||||
{
|
||||
resize(count, kind::null);
|
||||
}
|
||||
|
||||
void
|
||||
array::
|
||||
resize(
|
||||
size_type count,
|
||||
value_type const& v)
|
||||
{
|
||||
if(count > size())
|
||||
{
|
||||
reserve(count);
|
||||
while(count--)
|
||||
emplace_impl(end(), v);
|
||||
}
|
||||
else if(count < size())
|
||||
{
|
||||
tab_->size = count;
|
||||
count = size() - count;
|
||||
for(size_type i = size() - 1;
|
||||
count-- > 0; --i)
|
||||
tab_->begin()[i].~value();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
array::
|
||||
swap(array& other) noexcept
|
||||
{
|
||||
BOOST_ASSERT(*sp_ == *other.sp_);
|
||||
std::swap(tab_, other.tab_);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
void
|
||||
array::
|
||||
destroy(
|
||||
value* first,
|
||||
value* last)
|
||||
{
|
||||
while(first != last)
|
||||
(*first++).~value();
|
||||
}
|
||||
|
||||
void
|
||||
array::
|
||||
move(
|
||||
value* to,
|
||||
value* from,
|
||||
size_type n) noexcept
|
||||
{
|
||||
if(to > from)
|
||||
{
|
||||
// backwards
|
||||
to += n;
|
||||
from += n;
|
||||
while(n--)
|
||||
{
|
||||
::new(&*--to) value_type(
|
||||
std::move(*--from));
|
||||
from->~value();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
while(n--)
|
||||
{
|
||||
::new(&*to++) value_type(
|
||||
std::move(*from));
|
||||
(*from++).~value();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} // json
|
||||
} // beast
|
||||
} // boost
|
||||
|
||||
#endif
|
||||
76
include/boost/json/impl/basic_parser.hpp
Normal file
76
include/boost/json/impl/basic_parser.hpp
Normal file
@@ -0,0 +1,76 @@
|
||||
//
|
||||
// Copyright (c) 2018-2019 Vinnie Falco (vinnie dot falco at gmail dot com)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
// Official repository: https://github.com/boostorg/json
|
||||
//
|
||||
|
||||
#ifndef BOOST_JSON_IMPL_BASIC_PARSER_HPP
|
||||
#define BOOST_JSON_IMPL_BASIC_PARSER_HPP
|
||||
|
||||
#include <boost/beast/core/buffers_range.hpp>
|
||||
|
||||
namespace boost {
|
||||
namespace beast {
|
||||
namespace json {
|
||||
|
||||
template<class ConstBufferSequence, class>
|
||||
std::size_t
|
||||
basic_parser::
|
||||
write_some(
|
||||
ConstBufferSequence const& buffers,
|
||||
error_code& ec)
|
||||
{
|
||||
static_assert(
|
||||
net::is_const_buffer_sequence<ConstBufferSequence>::value,
|
||||
"ConstBufferSequence type requirements not met");
|
||||
|
||||
std::size_t bytes_used = 0;
|
||||
for(auto const b : beast::buffers_range_ref(buffers))
|
||||
{
|
||||
bytes_used += write_some(b, ec);
|
||||
if(ec)
|
||||
break;
|
||||
}
|
||||
return bytes_used;
|
||||
}
|
||||
|
||||
template<class ConstBufferSequence, class>
|
||||
std::size_t
|
||||
basic_parser::
|
||||
write(
|
||||
ConstBufferSequence const& buffers,
|
||||
error_code& ec)
|
||||
{
|
||||
static_assert(
|
||||
net::is_const_buffer_sequence<ConstBufferSequence>::value,
|
||||
"ConstBufferSequence type requirements not met");
|
||||
|
||||
std::size_t bytes_used = 0;
|
||||
auto it =
|
||||
net::buffer_sequence_begin(buffers);
|
||||
auto end =
|
||||
net::buffer_sequence_end(buffers);
|
||||
if(it == end)
|
||||
{
|
||||
ec = {};
|
||||
return 0;
|
||||
}
|
||||
for(--end; it != end; ++it)
|
||||
{
|
||||
bytes_used +=
|
||||
write_some(*it, ec);
|
||||
if(ec)
|
||||
return bytes_used;
|
||||
}
|
||||
bytes_used += write(*it, ec);
|
||||
return bytes_used;
|
||||
}
|
||||
|
||||
} // json
|
||||
} // beast
|
||||
} // boost
|
||||
|
||||
#endif
|
||||
967
include/boost/json/impl/basic_parser.ipp
Normal file
967
include/boost/json/impl/basic_parser.ipp
Normal file
@@ -0,0 +1,967 @@
|
||||
//
|
||||
// Copyright (c) 2018-2019 Vinnie Falco (vinnie dot falco at gmail dot com)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
// Official repository: https://github.com/boostorg/json
|
||||
//
|
||||
|
||||
#ifndef BOOST_JSON_IMPL_BASIC_PARSER_IPP
|
||||
#define BOOST_JSON_IMPL_BASIC_PARSER_IPP
|
||||
|
||||
#include <boost/json/basic_parser.hpp>
|
||||
#include <boost/json/error.hpp>
|
||||
#include <boost/beast/core/static_string.hpp>
|
||||
#include <boost/assert.hpp>
|
||||
|
||||
namespace boost {
|
||||
namespace beast {
|
||||
namespace json {
|
||||
|
||||
/* References:
|
||||
|
||||
https://www.json.org/
|
||||
|
||||
RFC 7159: The JavaScript Object Notation (JSON) Data Interchange Format
|
||||
https://tools.ietf.org/html/rfc7159
|
||||
|
||||
character
|
||||
'0020' . '10ffff' - '"' - '\'
|
||||
'\' escape
|
||||
|
||||
escape
|
||||
'"'
|
||||
'\'
|
||||
'/'
|
||||
'b'
|
||||
'n'
|
||||
'r'
|
||||
't'
|
||||
'u' hex hex hex hex
|
||||
|
||||
hex
|
||||
digit
|
||||
'A' . 'F'
|
||||
'a' . 'f'
|
||||
|
||||
number
|
||||
int frac exp
|
||||
|
||||
ws
|
||||
""
|
||||
'0009' ws
|
||||
'000A' ws
|
||||
'000D' ws
|
||||
'0020' ws
|
||||
*/
|
||||
|
||||
enum class basic_parser::state : char
|
||||
{
|
||||
json,
|
||||
element,
|
||||
ws,
|
||||
value,
|
||||
|
||||
object1, object2, object3, object4, colon,
|
||||
array1, array2, array3, array4,
|
||||
string1, string2, string3,
|
||||
true1, true2, true3, true4,
|
||||
false1, false2, false3, false4, false5,
|
||||
null1, null2, null3, null4,
|
||||
|
||||
number, number_mant1, number_mant2,
|
||||
number_fract1, number_fract2, number_fract3,
|
||||
number_exp, number_exp_sign,
|
||||
number_exp_digits1, number_exp_digits2, number_end,
|
||||
|
||||
end
|
||||
};
|
||||
|
||||
basic_parser::
|
||||
basic_parser()
|
||||
{
|
||||
reset();
|
||||
}
|
||||
|
||||
bool
|
||||
basic_parser::is_done() const noexcept
|
||||
{
|
||||
return stack_.front() == state::end;
|
||||
}
|
||||
|
||||
void
|
||||
basic_parser::
|
||||
reset()
|
||||
{
|
||||
stack_.clear();
|
||||
stack_.push_front(state::end);
|
||||
stack_.push_front(state::json);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
// Append the digit to the
|
||||
// value, which must be unsigned.
|
||||
// Returns `false` on overflow.
|
||||
bool
|
||||
basic_parser::
|
||||
append_digit(
|
||||
number::mantissa_type* value,
|
||||
char digit)
|
||||
{
|
||||
number::mantissa_type temp =
|
||||
*value * 10;
|
||||
if(temp < *value)
|
||||
return false;
|
||||
number::mantissa_type result =
|
||||
temp + digit;
|
||||
if(result < temp)
|
||||
return false;
|
||||
*value = result;
|
||||
return true;
|
||||
}
|
||||
|
||||
// Append the digit to the signed exponent
|
||||
bool
|
||||
basic_parser::
|
||||
append_digit(
|
||||
number::exponent_type* value,
|
||||
char digit, bool neg)
|
||||
{
|
||||
if(neg)
|
||||
{
|
||||
if(! *value)
|
||||
{
|
||||
*value = -digit;
|
||||
}
|
||||
else
|
||||
{
|
||||
*value *= 10;
|
||||
*value -= digit;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
*value *= 10;
|
||||
*value += digit;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
void
|
||||
basic_parser::
|
||||
write_eof(error_code& ec)
|
||||
{
|
||||
// write a null, this is invalid no matter
|
||||
// what state we are in, to get a descriptive
|
||||
// error.
|
||||
//
|
||||
// VFALCO we might want to return error::partial_data
|
||||
|
||||
auto const fail =
|
||||
[this, &ec]
|
||||
{
|
||||
char c = 0;
|
||||
write_some(
|
||||
boost::asio::const_buffer(
|
||||
&c, 1), ec);
|
||||
BOOST_ASSERT(ec);
|
||||
};
|
||||
|
||||
while(stack_.front() != state::end)
|
||||
{
|
||||
// pop all states that
|
||||
// allow "" (empty string)
|
||||
switch(stack_.front())
|
||||
{
|
||||
case state::number_mant2:
|
||||
case state::number_fract1:
|
||||
case state::number_fract3:
|
||||
case state::number_exp:
|
||||
case state::number_exp_digits2:
|
||||
stack_.front() = state::number_end;
|
||||
write_some(
|
||||
net::const_buffer{}, ec);
|
||||
if(ec)
|
||||
return;
|
||||
break;
|
||||
|
||||
case state::ws:
|
||||
stack_.pop_front();
|
||||
break;
|
||||
|
||||
default:
|
||||
return fail();
|
||||
}
|
||||
}
|
||||
ec = {};
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
std::size_t
|
||||
basic_parser::
|
||||
write_some(
|
||||
net::const_buffer buffer,
|
||||
error_code& ec)
|
||||
{
|
||||
auto p = static_cast<
|
||||
char const*>(buffer.data());
|
||||
auto n = buffer.size();
|
||||
auto const p0 = p;
|
||||
auto const p1 = p0 + n;
|
||||
static_string<4096> temp;
|
||||
ec.assign(0, ec.category());
|
||||
BOOST_ASSERT(stack_.front() != state::end);
|
||||
auto const maybe_flush =
|
||||
[&]
|
||||
{
|
||||
if(temp.size() != temp.max_size())
|
||||
return;
|
||||
if(is_key_)
|
||||
this->on_key_data(
|
||||
{temp.data(), temp.size()}, ec);
|
||||
else
|
||||
this->on_string_data(
|
||||
{temp.data(), temp.size()}, ec);
|
||||
};
|
||||
loop:
|
||||
switch(stack_.front())
|
||||
{
|
||||
case state::json:
|
||||
this->on_document_begin(ec);
|
||||
if(ec)
|
||||
goto finish;
|
||||
stack_.front() = state::element;
|
||||
temp.clear();
|
||||
is_key_ = false;
|
||||
goto loop;
|
||||
|
||||
case state::element:
|
||||
stack_.front() = state::ws;
|
||||
stack_.push_front(state::value);
|
||||
stack_.push_front(state::ws);
|
||||
goto loop;
|
||||
|
||||
case state::ws:
|
||||
while(p < p1)
|
||||
{
|
||||
if(! is_ws(*p))
|
||||
{
|
||||
stack_.pop_front();
|
||||
goto loop;
|
||||
}
|
||||
++p;
|
||||
}
|
||||
break;
|
||||
|
||||
case state::value:
|
||||
{
|
||||
if(p >= p1)
|
||||
break;
|
||||
switch(*p)
|
||||
{
|
||||
// object
|
||||
case '{':
|
||||
stack_.front() = state::object1;
|
||||
goto loop;
|
||||
|
||||
// array
|
||||
case '[':
|
||||
++p;
|
||||
stack_.front() = state::array1;
|
||||
this->on_array_begin(ec);
|
||||
goto loop;
|
||||
|
||||
// string
|
||||
case '"':
|
||||
stack_.front() = state::string1;
|
||||
goto loop;
|
||||
|
||||
// number
|
||||
case '0':
|
||||
case '1': case '2': case '3':
|
||||
case '4': case '5': case '6':
|
||||
case '7': case '8': case '9':
|
||||
case '-':
|
||||
stack_.front() = state::number;
|
||||
goto loop;
|
||||
|
||||
// true
|
||||
case 't':
|
||||
if(p + 4 <= p1)
|
||||
{
|
||||
if(
|
||||
p[1] != 'r' ||
|
||||
p[2] != 'u' ||
|
||||
p[3] != 'e')
|
||||
{
|
||||
ec = error::syntax;
|
||||
goto finish;
|
||||
}
|
||||
p = p + 4;
|
||||
stack_.front() = state::true4;
|
||||
goto loop;
|
||||
}
|
||||
++p;
|
||||
stack_.front() = state::true1;
|
||||
goto loop;
|
||||
|
||||
// false
|
||||
case 'f':
|
||||
if(p + 5 <= p1)
|
||||
{
|
||||
if(
|
||||
p[1] != 'a' ||
|
||||
p[2] != 'l' ||
|
||||
p[3] != 's' ||
|
||||
p[4] != 'e')
|
||||
{
|
||||
ec = error::syntax;
|
||||
goto finish;
|
||||
}
|
||||
p = p + 5;
|
||||
stack_.front() = state::false5;
|
||||
goto loop;
|
||||
}
|
||||
++p;
|
||||
stack_.front() = state::false1;
|
||||
goto loop;
|
||||
|
||||
// null
|
||||
case 'n':
|
||||
if(p + 4 <= p1)
|
||||
{
|
||||
if(
|
||||
p[1] != 'u' ||
|
||||
p[2] != 'l' ||
|
||||
p[3] != 'l')
|
||||
{
|
||||
ec = error::syntax;
|
||||
goto finish;
|
||||
}
|
||||
p = p + 4;
|
||||
stack_.front() = state::null4;
|
||||
goto loop;
|
||||
}
|
||||
++p;
|
||||
stack_.front() = state::null1;
|
||||
goto loop;
|
||||
|
||||
default:
|
||||
ec = error::syntax;
|
||||
goto finish;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
//
|
||||
// object
|
||||
//
|
||||
|
||||
// beginning of object
|
||||
case state::object1:
|
||||
BOOST_ASSERT(*p == '{');
|
||||
++p;
|
||||
this->on_object_begin(ec);
|
||||
if(ec)
|
||||
goto finish;
|
||||
stack_.front() = state::object2;
|
||||
stack_.push_front(state::ws);
|
||||
goto loop;
|
||||
|
||||
// first key or end of object
|
||||
case state::object2:
|
||||
if(p >= p1)
|
||||
break;
|
||||
if(*p == '}')
|
||||
{
|
||||
++p;
|
||||
stack_.front() = state::object4;
|
||||
goto loop;
|
||||
}
|
||||
stack_.front() = state::object3;
|
||||
stack_.push_front(state::element);
|
||||
stack_.push_front(state::colon);
|
||||
stack_.push_front(state::ws);
|
||||
stack_.push_front(state::string1);
|
||||
is_key_ = true;
|
||||
goto loop;
|
||||
|
||||
case state::object3:
|
||||
if(p >= p1)
|
||||
break;
|
||||
if(*p == '}')
|
||||
{
|
||||
++p;
|
||||
stack_.front() = state::object4;
|
||||
goto loop;
|
||||
}
|
||||
if(*p != ',')
|
||||
{
|
||||
ec = error::syntax;
|
||||
goto finish;
|
||||
}
|
||||
++p;
|
||||
stack_.front() = state::object3;
|
||||
stack_.push_front(state::element);
|
||||
stack_.push_front(state::colon);
|
||||
stack_.push_front(state::ws);
|
||||
stack_.push_front(state::string1);
|
||||
stack_.push_front(state::ws);
|
||||
is_key_ = true;
|
||||
goto loop;
|
||||
|
||||
case state::object4:
|
||||
this->on_object_end(ec);
|
||||
if(ec)
|
||||
goto finish;
|
||||
stack_.pop_front();
|
||||
goto loop;
|
||||
|
||||
case state::colon:
|
||||
if(p >= p1)
|
||||
break;
|
||||
if(*p != ':')
|
||||
{
|
||||
ec = error::syntax;
|
||||
goto finish;
|
||||
}
|
||||
++p;
|
||||
stack_.pop_front();
|
||||
goto loop;
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
//
|
||||
// array
|
||||
//
|
||||
|
||||
case state::array1:
|
||||
stack_.front() = state::array2;
|
||||
stack_.push_front(state::ws);
|
||||
goto loop;
|
||||
|
||||
case state::array2:
|
||||
if(p >= p1)
|
||||
break;
|
||||
if(*p == ']')
|
||||
{
|
||||
++p;
|
||||
stack_.front() = state::array4;
|
||||
goto loop;
|
||||
}
|
||||
stack_.front() = state::array3;
|
||||
stack_.push_front(state::element);
|
||||
goto loop;
|
||||
|
||||
case state::array3:
|
||||
if(p >= p1)
|
||||
break;
|
||||
if(*p == ']')
|
||||
{
|
||||
++p;
|
||||
stack_.front() = state::array4;
|
||||
goto loop;
|
||||
}
|
||||
if(*p != ',')
|
||||
{
|
||||
ec = error::syntax;
|
||||
goto finish;
|
||||
}
|
||||
++p;
|
||||
stack_.front() = state::array3;
|
||||
stack_.push_front(state::element);
|
||||
stack_.push_front(state::ws);
|
||||
goto loop;
|
||||
|
||||
case state::array4:
|
||||
this->on_array_end(ec);
|
||||
if(ec)
|
||||
goto finish;
|
||||
stack_.pop_front();
|
||||
goto loop;
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
//
|
||||
// string
|
||||
//
|
||||
|
||||
// double quote opening string
|
||||
case state::string1:
|
||||
if(p >= p1)
|
||||
break;
|
||||
if(*p != '\"')
|
||||
{
|
||||
ec = error::syntax;
|
||||
goto finish;
|
||||
}
|
||||
++p;
|
||||
stack_.front() = state::string2;
|
||||
goto loop;
|
||||
|
||||
// characters
|
||||
case state::string2:
|
||||
while(p < p1)
|
||||
{
|
||||
if(*p == '\"')
|
||||
{
|
||||
++p;
|
||||
if(is_key_)
|
||||
this->on_key_end({temp.data(),
|
||||
temp.size()}, ec);
|
||||
else
|
||||
this->on_string_end({temp.data(),
|
||||
temp.size()}, ec);
|
||||
if(ec)
|
||||
goto finish;
|
||||
temp.clear();
|
||||
is_key_ = false;
|
||||
stack_.pop_front();
|
||||
goto loop;
|
||||
}
|
||||
if(*p == '\\')
|
||||
{
|
||||
++p;
|
||||
stack_.front() = state::string3;
|
||||
goto loop;
|
||||
}
|
||||
if(is_control(*p))
|
||||
{
|
||||
ec = error::syntax;
|
||||
goto finish;
|
||||
}
|
||||
// TODO UTF-8
|
||||
maybe_flush();
|
||||
temp.push_back(*p++);
|
||||
}
|
||||
break;
|
||||
|
||||
// escape
|
||||
case state::string3:
|
||||
if(p >= p1)
|
||||
break;
|
||||
switch(*p)
|
||||
{
|
||||
case '\"':
|
||||
maybe_flush();
|
||||
temp.push_back('\"');
|
||||
break;
|
||||
|
||||
case '\\':
|
||||
maybe_flush();
|
||||
temp.push_back('\\');
|
||||
break;
|
||||
|
||||
case '/':
|
||||
maybe_flush();
|
||||
temp.push_back('/');
|
||||
break;
|
||||
|
||||
case 'b':
|
||||
maybe_flush();
|
||||
temp.push_back('\x08');
|
||||
break;
|
||||
|
||||
case 'f':
|
||||
maybe_flush();
|
||||
temp.push_back('\x08');
|
||||
break;
|
||||
|
||||
case 'n':
|
||||
maybe_flush();
|
||||
temp.push_back('\x0a');
|
||||
break;
|
||||
|
||||
case 'r':
|
||||
maybe_flush();
|
||||
temp.push_back('\x0d');
|
||||
break;
|
||||
|
||||
case 't':
|
||||
maybe_flush();
|
||||
temp.push_back('\x09');
|
||||
break;
|
||||
|
||||
case 'u':
|
||||
BOOST_ASSERT(false);
|
||||
break;
|
||||
|
||||
default:
|
||||
ec = error::syntax;
|
||||
goto finish;
|
||||
}
|
||||
++p;
|
||||
stack_.front()=state::string2;
|
||||
goto loop;
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
//
|
||||
// true
|
||||
//
|
||||
|
||||
case state::true1:
|
||||
if(p >= p1)
|
||||
break;
|
||||
if(*p != 'r')
|
||||
{
|
||||
ec = error::syntax;
|
||||
goto finish;
|
||||
}
|
||||
++p;
|
||||
stack_.front() = state::true2;
|
||||
BOOST_FALLTHROUGH;
|
||||
|
||||
case state::true2:
|
||||
if(p >= p1)
|
||||
break;
|
||||
if(*p != 'u')
|
||||
{
|
||||
ec = error::syntax;
|
||||
goto finish;
|
||||
}
|
||||
++p;
|
||||
stack_.front() = state::true3;
|
||||
BOOST_FALLTHROUGH;
|
||||
|
||||
case state::true3:
|
||||
if(p >= p1)
|
||||
break;
|
||||
if(*p != 'e')
|
||||
{
|
||||
ec = error::syntax;
|
||||
goto finish;
|
||||
}
|
||||
++p;
|
||||
stack_.front() = state::true4;
|
||||
BOOST_FALLTHROUGH;
|
||||
|
||||
case state::true4:
|
||||
this->on_bool(true, ec);
|
||||
if(ec)
|
||||
goto finish;
|
||||
stack_.pop_front();
|
||||
goto loop;
|
||||
|
||||
//
|
||||
// false
|
||||
//
|
||||
|
||||
case state::false1:
|
||||
if(p >= p1)
|
||||
break;
|
||||
if(*p != 'a')
|
||||
{
|
||||
ec = error::syntax;
|
||||
goto finish;
|
||||
}
|
||||
++p;
|
||||
stack_.front() = state::false2;
|
||||
BOOST_FALLTHROUGH;
|
||||
|
||||
case state::false2:
|
||||
if(p >= p1)
|
||||
break;
|
||||
if(*p != 'l')
|
||||
{
|
||||
ec = error::syntax;
|
||||
goto finish;
|
||||
}
|
||||
++p;
|
||||
stack_.front() = state::false3;
|
||||
BOOST_FALLTHROUGH;
|
||||
|
||||
case state::false3:
|
||||
if(p >= p1)
|
||||
break;
|
||||
if(*p != 's')
|
||||
{
|
||||
ec = error::syntax;
|
||||
goto finish;
|
||||
}
|
||||
++p;
|
||||
stack_.front() = state::false4;
|
||||
BOOST_FALLTHROUGH;
|
||||
|
||||
case state::false4:
|
||||
if(p >= p1)
|
||||
break;
|
||||
if(*p != 'e')
|
||||
{
|
||||
ec = error::syntax;
|
||||
goto finish;
|
||||
}
|
||||
++p;
|
||||
stack_.front() = state::false5;
|
||||
BOOST_FALLTHROUGH;
|
||||
|
||||
case state::false5:
|
||||
this->on_bool(false, ec);
|
||||
if(ec)
|
||||
goto finish;
|
||||
stack_.pop_front();
|
||||
goto loop;
|
||||
|
||||
//
|
||||
// null
|
||||
//
|
||||
|
||||
case state::null1:
|
||||
if(p >= p1)
|
||||
break;
|
||||
if(*p != 'u')
|
||||
{
|
||||
ec = error::syntax;
|
||||
goto finish;
|
||||
}
|
||||
++p;
|
||||
stack_.front() = state::null2;
|
||||
BOOST_FALLTHROUGH;
|
||||
|
||||
case state::null2:
|
||||
if(p >= p1)
|
||||
break;
|
||||
if(*p != 'l')
|
||||
{
|
||||
ec = error::syntax;
|
||||
goto finish;
|
||||
}
|
||||
++p;
|
||||
stack_.front() = state::null3;
|
||||
BOOST_FALLTHROUGH;
|
||||
|
||||
case state::null3:
|
||||
if(p >= p1)
|
||||
break;
|
||||
if(*p != 'l')
|
||||
{
|
||||
ec = error::syntax;
|
||||
goto finish;
|
||||
}
|
||||
++p;
|
||||
stack_.front() = state::null4;
|
||||
BOOST_FALLTHROUGH;
|
||||
|
||||
case state::null4:
|
||||
this->on_null(ec);
|
||||
if(ec)
|
||||
goto finish;
|
||||
stack_.pop_front();
|
||||
goto loop;
|
||||
|
||||
//
|
||||
// number
|
||||
//
|
||||
|
||||
case state::number:
|
||||
BOOST_ASSERT(p < p1);
|
||||
n_mant_ = 0;
|
||||
n_exp_ = 0;
|
||||
if(*p == '-')
|
||||
{
|
||||
++p;
|
||||
n_neg_ = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
n_neg_ = false;
|
||||
}
|
||||
stack_.front() = state::number_mant1;
|
||||
goto loop;
|
||||
|
||||
case state::number_mant1:
|
||||
if(p >= p1)
|
||||
break;
|
||||
if(! is_digit(*p))
|
||||
{
|
||||
// expected mantissa digit
|
||||
ec = error::syntax;
|
||||
goto finish;
|
||||
}
|
||||
if(*p != '0')
|
||||
{
|
||||
stack_.front() = state::number_mant2;
|
||||
goto loop;
|
||||
}
|
||||
++p;
|
||||
stack_.front() = state::number_fract1;
|
||||
goto loop;
|
||||
|
||||
case state::number_mant2:
|
||||
while(p < p1)
|
||||
{
|
||||
if(! is_digit(*p))
|
||||
{
|
||||
stack_.front() = state::number_fract1;
|
||||
goto loop;
|
||||
}
|
||||
if(! append_digit(&n_mant_, *p++ - '0'))
|
||||
{
|
||||
ec = error::mantissa_overflow;
|
||||
goto finish;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case state::number_fract1:
|
||||
if(p >= p1)
|
||||
break;
|
||||
if(*p == '.')
|
||||
{
|
||||
++p;
|
||||
stack_.front() = state::number_fract2;
|
||||
goto loop;
|
||||
}
|
||||
if(is_digit(*p))
|
||||
{
|
||||
// unexpected digit after zero
|
||||
ec = error::syntax;
|
||||
goto finish;
|
||||
}
|
||||
stack_.front() = state::number_exp;
|
||||
goto loop;
|
||||
|
||||
case state::number_fract2:
|
||||
if(p >= p1)
|
||||
break;
|
||||
if(! is_digit(*p))
|
||||
{
|
||||
// expected mantissa fraction digit
|
||||
ec = error::syntax;
|
||||
goto finish;
|
||||
}
|
||||
stack_.front() = state::number_fract3;
|
||||
goto loop;
|
||||
|
||||
case state::number_fract3:
|
||||
while(p < p1)
|
||||
{
|
||||
if(! is_digit(*p))
|
||||
{
|
||||
stack_.front() = state::number_exp;
|
||||
goto loop;
|
||||
}
|
||||
if(! append_digit(&n_mant_, *p++ - '0'))
|
||||
{
|
||||
ec = error::mantissa_overflow;
|
||||
goto finish;
|
||||
}
|
||||
--n_exp_;
|
||||
}
|
||||
break;
|
||||
|
||||
case state::number_exp:
|
||||
if(p >= p1)
|
||||
break;
|
||||
if(*p == 'e' || *p == 'E')
|
||||
{
|
||||
++p;
|
||||
stack_.front() = state::number_exp_sign;
|
||||
goto loop;
|
||||
}
|
||||
stack_.front() = state::number_end;
|
||||
goto loop;
|
||||
|
||||
case state::number_exp_sign:
|
||||
if(p >= p1)
|
||||
break;
|
||||
if(*p == '+')
|
||||
{
|
||||
++p;
|
||||
n_exp_neg_ = false;
|
||||
}
|
||||
else if(*p == '-')
|
||||
{
|
||||
++p;
|
||||
n_exp_neg_ = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
n_exp_neg_ = false;
|
||||
}
|
||||
stack_.front() = state::number_exp_digits1;
|
||||
goto loop;
|
||||
|
||||
case state::number_exp_digits1:
|
||||
if(p >= p1)
|
||||
break;
|
||||
if(! is_digit(*p))
|
||||
{
|
||||
// expected exponent digit
|
||||
ec = error::syntax;
|
||||
goto finish;
|
||||
}
|
||||
stack_.front() = state::number_exp_digits2;
|
||||
goto loop;
|
||||
|
||||
case state::number_exp_digits2:
|
||||
while(p < p1)
|
||||
{
|
||||
if(! is_digit(*p))
|
||||
{
|
||||
stack_.front() = state::number_end;
|
||||
goto loop;
|
||||
}
|
||||
if(! append_digit(&n_exp_,
|
||||
*p++ - '0', n_exp_neg_))
|
||||
{
|
||||
ec = error::exponent_overflow;
|
||||
goto finish;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case state::number_end:
|
||||
this->on_number(number(
|
||||
n_mant_, n_exp_, n_neg_), ec);
|
||||
if(ec)
|
||||
goto finish;
|
||||
stack_.pop_front();
|
||||
goto loop;
|
||||
|
||||
//
|
||||
// (end)
|
||||
//
|
||||
|
||||
case state::end:
|
||||
/*
|
||||
if(p < p1)
|
||||
{
|
||||
// unexpected extra characters
|
||||
ec = error::syntax;
|
||||
goto finish;
|
||||
}
|
||||
*/
|
||||
break;
|
||||
}
|
||||
|
||||
finish:
|
||||
return p - p0;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
// Called to parse the rest of the document, this
|
||||
// can be optimized by assuming no more data is coming.
|
||||
std::size_t
|
||||
basic_parser::
|
||||
write(
|
||||
net::const_buffer buffer,
|
||||
error_code& ec)
|
||||
{
|
||||
auto bytes_used =
|
||||
write_some(buffer, ec);
|
||||
if(! ec)
|
||||
write_eof(ec);
|
||||
return bytes_used;
|
||||
}
|
||||
|
||||
} // json
|
||||
} // beast
|
||||
} // boost
|
||||
|
||||
#endif
|
||||
46
include/boost/json/impl/error.hpp
Normal file
46
include/boost/json/impl/error.hpp
Normal file
@@ -0,0 +1,46 @@
|
||||
//
|
||||
// Copyright (c) 2018-2019 Vinnie Falco (vinnie dot falco at gmail dot com)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
// Official repository: https://github.com/boostorg/json
|
||||
//
|
||||
|
||||
#ifndef BOOST_JSON_IMPL_ERROR_HPP
|
||||
#define BOOST_JSON_IMPL_ERROR_HPP
|
||||
|
||||
#include <type_traits>
|
||||
|
||||
namespace boost {
|
||||
namespace system {
|
||||
template<>
|
||||
struct is_error_code_enum<::boost::beast::json::error>
|
||||
{
|
||||
static bool const value = true;
|
||||
};
|
||||
template<>
|
||||
struct is_error_condition_enum<::boost::beast::json::condition>
|
||||
{
|
||||
static bool const value = true;
|
||||
};
|
||||
} // system
|
||||
} // boost
|
||||
|
||||
namespace boost {
|
||||
namespace beast {
|
||||
namespace json {
|
||||
|
||||
BOOST_BEAST_DECL
|
||||
error_code
|
||||
make_error_code(error e);
|
||||
|
||||
BOOST_BEAST_DECL
|
||||
error_condition
|
||||
make_error_condition(condition c);
|
||||
|
||||
} // json
|
||||
} // beast
|
||||
} // boost
|
||||
|
||||
#endif
|
||||
157
include/boost/json/impl/error.ipp
Normal file
157
include/boost/json/impl/error.ipp
Normal file
@@ -0,0 +1,157 @@
|
||||
//
|
||||
// Copyright (c) 2018-2019 Vinnie Falco (vinnie dot falco at gmail dot com)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
// Official repository: https://github.com/boostorg/json
|
||||
//
|
||||
|
||||
#ifndef BOOST_JSON_IMPL_ERROR_IPP
|
||||
#define BOOST_JSON_IMPL_ERROR_IPP
|
||||
|
||||
#include <boost/json/error.hpp>
|
||||
|
||||
namespace boost {
|
||||
namespace beast {
|
||||
namespace json {
|
||||
|
||||
namespace detail {
|
||||
|
||||
class error_codes : public error_category
|
||||
{
|
||||
public:
|
||||
const char*
|
||||
name() const noexcept override
|
||||
{
|
||||
return "boost.beast.json";
|
||||
}
|
||||
|
||||
BOOST_BEAST_DECL
|
||||
std::string
|
||||
message(int ev) const override
|
||||
{
|
||||
switch(static_cast<error>(ev))
|
||||
{
|
||||
default:
|
||||
case error::syntax: return
|
||||
"The serialized JSON object contains a syntax error";
|
||||
|
||||
case error::extra_data: return
|
||||
"Unexpected extra data encountered while parsing";
|
||||
|
||||
case error::mantissa_overflow: return
|
||||
"A mantissa overflowed while parsing";
|
||||
|
||||
case error::exponent_overflow: return
|
||||
"An exponent overflowed while parsing";
|
||||
|
||||
case error::too_deep: return
|
||||
"The parser reached the maximum allowed depth";
|
||||
|
||||
//
|
||||
|
||||
case error::integer_overflow: return
|
||||
"An integer assignment overflowed";
|
||||
|
||||
case error::expected_object: return
|
||||
"Expected a value of kind object";
|
||||
|
||||
case error::expected_array: return
|
||||
"Expected a value of kind array";
|
||||
|
||||
case error::expected_string: return
|
||||
"Expected a value of kind string";
|
||||
|
||||
case error::expected_number: return
|
||||
"Expected a value of kind number";
|
||||
|
||||
case error::expected_bool: return
|
||||
"Expected a value of kind bool";
|
||||
|
||||
case error::expected_null: return
|
||||
"Expected a value of kind null";
|
||||
|
||||
//
|
||||
|
||||
case error::key_not_found: return
|
||||
"The key was not found in the object";
|
||||
}
|
||||
}
|
||||
|
||||
BOOST_BEAST_DECL
|
||||
error_condition
|
||||
default_error_condition(int ev) const noexcept override
|
||||
{
|
||||
switch(static_cast<error>(ev))
|
||||
{
|
||||
default:
|
||||
return {ev, *this};
|
||||
|
||||
case error::syntax:
|
||||
case error::extra_data:
|
||||
case error::mantissa_overflow:
|
||||
case error::exponent_overflow:
|
||||
case error::too_deep:
|
||||
return condition::parse_error;
|
||||
|
||||
case error::integer_overflow:
|
||||
case error::expected_object:
|
||||
case error::expected_array:
|
||||
case error::expected_string:
|
||||
case error::expected_number:
|
||||
case error::expected_bool:
|
||||
case error::expected_null:
|
||||
return condition::assign_error;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
class error_conditions : public error_category
|
||||
{
|
||||
public:
|
||||
BOOST_BEAST_DECL
|
||||
const char*
|
||||
name() const noexcept override
|
||||
{
|
||||
return "boost.beast";
|
||||
}
|
||||
|
||||
BOOST_BEAST_DECL
|
||||
std::string
|
||||
message(int cv) const override
|
||||
{
|
||||
switch(static_cast<condition>(cv))
|
||||
{
|
||||
default:
|
||||
case condition::parse_error:
|
||||
return "A JSON parsing error occurred";
|
||||
case condition::assign_error:
|
||||
return "An error occurred during assignment";
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
} // detail
|
||||
|
||||
error_code
|
||||
make_error_code(error e)
|
||||
{
|
||||
static detail::error_codes const cat{};
|
||||
return error_code{static_cast<
|
||||
std::underlying_type<error>::type>(e), cat};
|
||||
}
|
||||
|
||||
error_condition
|
||||
make_error_condition(condition c)
|
||||
{
|
||||
static detail::error_conditions const cat{};
|
||||
return error_condition{static_cast<
|
||||
std::underlying_type<condition>::type>(c), cat};
|
||||
}
|
||||
|
||||
} // json
|
||||
} // beast
|
||||
} // boost
|
||||
|
||||
#endif
|
||||
214
include/boost/json/impl/iterator.ipp
Normal file
214
include/boost/json/impl/iterator.ipp
Normal file
@@ -0,0 +1,214 @@
|
||||
//
|
||||
// Copyright (c) 2018-2019 Vinnie Falco (vinnie dot falco at gmail dot com)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
// Official repository: https://github.com/boostorg/json
|
||||
//
|
||||
|
||||
#ifndef BOOST_JSON_ITERATOR_IMPL_IPP
|
||||
#define BOOST_JSON_ITERATOR_IMPL_IPP
|
||||
|
||||
#include <boost/json/iterator.hpp>
|
||||
|
||||
namespace boost {
|
||||
namespace beast {
|
||||
namespace json {
|
||||
|
||||
const_iterator::
|
||||
node::
|
||||
~node()
|
||||
{
|
||||
if(it)
|
||||
{
|
||||
if(v->is_object())
|
||||
{
|
||||
obj_it.~const_iterator();
|
||||
}
|
||||
else
|
||||
{
|
||||
// VFALCO Why not?
|
||||
//arr.it.~const_iterator();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const_iterator::
|
||||
node::
|
||||
node(
|
||||
value const& v_,
|
||||
bool it_) noexcept
|
||||
: v(&v_)
|
||||
, it(it_)
|
||||
{
|
||||
if(it)
|
||||
{
|
||||
BOOST_ASSERT(
|
||||
v->is_structured());
|
||||
if(v->is_object())
|
||||
::new(&obj_it)
|
||||
object::const_iterator(
|
||||
v->as_object().begin());
|
||||
else
|
||||
::new(&arr_it)
|
||||
array::const_iterator(
|
||||
v->as_array().begin());
|
||||
}
|
||||
}
|
||||
|
||||
const_iterator::
|
||||
node::
|
||||
node(node const& other) noexcept
|
||||
: v(other.v)
|
||||
, key(other.key)
|
||||
{
|
||||
it = other.it;
|
||||
if(it)
|
||||
::new(&obj_it)
|
||||
object::const_iterator(
|
||||
other.obj_it);
|
||||
else
|
||||
::new(&arr_it)
|
||||
array::const_iterator(
|
||||
other.arr_it);
|
||||
}
|
||||
|
||||
bool
|
||||
const_iterator::
|
||||
node::
|
||||
last() const noexcept
|
||||
{
|
||||
if(! it)
|
||||
return true;
|
||||
if(v->is_object())
|
||||
return obj_it ==
|
||||
v->as_object().end();
|
||||
return arr_it ==
|
||||
v->as_array().end();
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
const_iterator::
|
||||
const_iterator(
|
||||
value const& jv)
|
||||
{
|
||||
stack_.emplace_front(
|
||||
jv, false);
|
||||
}
|
||||
|
||||
auto
|
||||
const_iterator::
|
||||
operator*() const noexcept ->
|
||||
value_type
|
||||
{
|
||||
auto const& n = stack_.front();
|
||||
if(! n.it)
|
||||
{
|
||||
BOOST_ASSERT(
|
||||
stack_.size() == 1);
|
||||
return {
|
||||
stack_.size() - 1,
|
||||
n.key,
|
||||
*n.v,
|
||||
true,
|
||||
false };
|
||||
}
|
||||
BOOST_ASSERT(n.v->is_structured());
|
||||
if(n.v->is_object())
|
||||
{
|
||||
if(n.obj_it !=
|
||||
n.v->as_object().end())
|
||||
return {
|
||||
stack_.size(),
|
||||
n.obj_it->first,
|
||||
n.obj_it->second,
|
||||
std::next(n.obj_it) ==
|
||||
n.v->as_object().end(),
|
||||
false };
|
||||
return {
|
||||
stack_.size() - 1,
|
||||
"",
|
||||
*n.v,
|
||||
stack_.size() == 1
|
||||
|| stack_[1].last(),
|
||||
true};
|
||||
}
|
||||
if(n.arr_it !=
|
||||
n.v->as_array().end())
|
||||
return {
|
||||
stack_.size(),
|
||||
"",
|
||||
*n.arr_it,
|
||||
std::next(n.arr_it) ==
|
||||
n.v->as_array().end(),
|
||||
false };
|
||||
return {
|
||||
stack_.size() - 1,
|
||||
"",
|
||||
*n.v,
|
||||
stack_.size() == 1
|
||||
|| stack_[1].last(),
|
||||
true};
|
||||
}
|
||||
|
||||
const_iterator&
|
||||
const_iterator::
|
||||
operator++() noexcept
|
||||
{
|
||||
auto& n = stack_.front();
|
||||
if(! n.it)
|
||||
{
|
||||
if(n.v->is_structured())
|
||||
{
|
||||
stack_.pop_front();
|
||||
stack_.emplace_front(
|
||||
*n.v, true);
|
||||
}
|
||||
else
|
||||
{
|
||||
stack_.pop_front();
|
||||
}
|
||||
}
|
||||
else if(n.v->is_object())
|
||||
{
|
||||
if(n.obj_it ==
|
||||
n.v->as_object().end())
|
||||
{
|
||||
stack_.pop_front();
|
||||
}
|
||||
else
|
||||
{
|
||||
auto const& jv =
|
||||
n.obj_it->second;
|
||||
if(jv.is_structured())
|
||||
stack_.emplace_front(
|
||||
jv, true);
|
||||
++n.obj_it;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if(n.arr_it ==
|
||||
n.v->as_array().end())
|
||||
{
|
||||
stack_.pop_front();
|
||||
}
|
||||
else
|
||||
{
|
||||
auto const& jv = *n.arr_it;
|
||||
if(jv.is_structured())
|
||||
stack_.emplace_front(
|
||||
jv, true);
|
||||
++n.arr_it;
|
||||
}
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
} // json
|
||||
} // beast
|
||||
} // boost
|
||||
|
||||
#endif
|
||||
454
include/boost/json/impl/number.ipp
Normal file
454
include/boost/json/impl/number.ipp
Normal file
@@ -0,0 +1,454 @@
|
||||
//
|
||||
// Copyright (c) 2018-2019 Vinnie Falco (vinnie dot falco at gmail dot com)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
// Official repository: https://github.com/boostorg/json
|
||||
//
|
||||
|
||||
#ifndef BOOST_JSON_IMPL_NUMBER_IPP
|
||||
#define BOOST_JSON_IMPL_NUMBER_IPP
|
||||
|
||||
#include <boost/json/number.hpp>
|
||||
#include <boost/beast/core/static_string.hpp>
|
||||
#include <algorithm>
|
||||
#include <cmath>
|
||||
#include <cstdint>
|
||||
#include <ostream>
|
||||
#include <cstdio>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
namespace boost {
|
||||
namespace beast {
|
||||
namespace json {
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
struct number::pow10
|
||||
{
|
||||
std::size_t
|
||||
size() const noexcept
|
||||
{
|
||||
return size_;
|
||||
}
|
||||
|
||||
mantissa_type const*
|
||||
begin() const noexcept
|
||||
{
|
||||
return begin_;
|
||||
}
|
||||
|
||||
mantissa_type const*
|
||||
end() const noexcept
|
||||
{
|
||||
return end_;
|
||||
}
|
||||
|
||||
mantissa_type
|
||||
operator[](
|
||||
exponent_type n) const
|
||||
{
|
||||
return begin_[n];
|
||||
}
|
||||
|
||||
static
|
||||
pow10 const&
|
||||
get() noexcept
|
||||
{
|
||||
struct pow10_impl : pow10
|
||||
{
|
||||
pow10_impl()
|
||||
{
|
||||
static mantissa_type constexpr list[] = {
|
||||
1ULL,
|
||||
10ULL,
|
||||
100ULL,
|
||||
1000ULL,
|
||||
10000ULL,
|
||||
100000ULL,
|
||||
1000000ULL,
|
||||
10000000ULL,
|
||||
100000000ULL,
|
||||
1000000000ULL,
|
||||
10000000000ULL,
|
||||
100000000000ULL,
|
||||
1000000000000ULL,
|
||||
10000000000000ULL,
|
||||
100000000000000ULL,
|
||||
1000000000000000ULL,
|
||||
10000000000000000ULL,
|
||||
100000000000000000ULL,
|
||||
1000000000000000000ULL,
|
||||
10000000000000000000ULL
|
||||
};
|
||||
size_ = std::extent<
|
||||
decltype(list)>::value;
|
||||
begin_ = &list[0];
|
||||
end_ = &list[size_];
|
||||
}
|
||||
};
|
||||
|
||||
static pow10_impl const tab;
|
||||
return tab;
|
||||
}
|
||||
|
||||
protected:
|
||||
std::size_t size_;
|
||||
mantissa_type const* begin_;
|
||||
mantissa_type const* end_;
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
number::
|
||||
number(
|
||||
mantissa_type mant,
|
||||
exponent_type exp,
|
||||
bool sign) noexcept
|
||||
{
|
||||
auto const as_double =
|
||||
[&]
|
||||
{
|
||||
double d =
|
||||
static_cast<double>(mant) *
|
||||
std::pow(10, exp);
|
||||
if(sign)
|
||||
d *= -1;
|
||||
return d;
|
||||
};
|
||||
|
||||
if(exp == 0)
|
||||
{
|
||||
if(! sign)
|
||||
{
|
||||
assign_unsigned(mant);
|
||||
}
|
||||
else if(mant <= static_cast<unsigned long long>(
|
||||
(std::numeric_limits<long long>::max)()) + 1)
|
||||
{
|
||||
assign_signed(static_cast<long long>(mant));
|
||||
}
|
||||
else
|
||||
{
|
||||
assign_double(as_double());
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
auto const d = as_double();
|
||||
if(! sign)
|
||||
{
|
||||
auto v = static_cast<unsigned long long>(d);
|
||||
if(v == d)
|
||||
assign_unsigned(v);
|
||||
else
|
||||
assign_double(d);
|
||||
}
|
||||
else
|
||||
{
|
||||
auto v = static_cast<long long>(d);
|
||||
if(v == d)
|
||||
assign_signed(v);
|
||||
else
|
||||
assign_double(d);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
number::
|
||||
number(short i) noexcept
|
||||
{
|
||||
assign_signed(i);
|
||||
}
|
||||
|
||||
number::
|
||||
number(int i) noexcept
|
||||
{
|
||||
assign_signed(i);
|
||||
}
|
||||
|
||||
number::
|
||||
number(long i) noexcept
|
||||
{
|
||||
assign_signed(i);
|
||||
}
|
||||
|
||||
number::
|
||||
number(long long i) noexcept
|
||||
{
|
||||
assign_signed(i);
|
||||
}
|
||||
|
||||
number::
|
||||
number(unsigned short i) noexcept
|
||||
{
|
||||
assign_unsigned(i);
|
||||
}
|
||||
|
||||
number::
|
||||
number(unsigned int i) noexcept
|
||||
{
|
||||
assign_unsigned(i);
|
||||
}
|
||||
|
||||
number::
|
||||
number(unsigned long i) noexcept
|
||||
{
|
||||
assign_unsigned(i);
|
||||
}
|
||||
|
||||
number::
|
||||
number(unsigned long long i) noexcept
|
||||
{
|
||||
assign_unsigned(i);
|
||||
}
|
||||
|
||||
number::
|
||||
number(float f) noexcept
|
||||
{
|
||||
assign_double(f);
|
||||
}
|
||||
|
||||
number::
|
||||
number(double f) noexcept
|
||||
{
|
||||
assign_double(f);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
bool
|
||||
number::
|
||||
is_int64() const noexcept
|
||||
{
|
||||
switch(k_)
|
||||
{
|
||||
case type_int64:
|
||||
return true;
|
||||
|
||||
case type_uint64:
|
||||
return int64_ >= 0;
|
||||
|
||||
case type_double:
|
||||
return static_cast<long long>(
|
||||
double_) == double_;
|
||||
|
||||
default:
|
||||
case type_ieee:
|
||||
break;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
number::
|
||||
is_uint64() const noexcept
|
||||
{
|
||||
switch(k_)
|
||||
{
|
||||
case type_int64:
|
||||
return int64_ >= 0;
|
||||
|
||||
case type_uint64:
|
||||
return true;
|
||||
|
||||
case type_double:
|
||||
return static_cast<
|
||||
unsigned long long>(
|
||||
double_) == double_;
|
||||
|
||||
default:
|
||||
case type_ieee:
|
||||
break;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
std::int_least64_t
|
||||
number::
|
||||
get_int64() const noexcept
|
||||
{
|
||||
switch(k_)
|
||||
{
|
||||
case type_int64:
|
||||
return int64_;
|
||||
|
||||
case type_uint64:
|
||||
return static_cast<
|
||||
long long>(uint64_);
|
||||
|
||||
case type_double:
|
||||
return static_cast<
|
||||
long long>(double_);
|
||||
|
||||
default:
|
||||
case type_ieee:
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
std::uint_least64_t
|
||||
number::
|
||||
get_uint64() const noexcept
|
||||
{
|
||||
switch(k_)
|
||||
{
|
||||
case type_int64:
|
||||
return static_cast<
|
||||
unsigned long long>(int64_);
|
||||
|
||||
case type_uint64:
|
||||
return uint64_;
|
||||
|
||||
case type_double:
|
||||
return static_cast<
|
||||
unsigned long long>(double_);
|
||||
|
||||
default:
|
||||
case type_ieee:
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
double
|
||||
number::
|
||||
get_double() const noexcept
|
||||
{
|
||||
switch(k_)
|
||||
{
|
||||
case type_int64:
|
||||
return static_cast<double>(int64_);
|
||||
|
||||
case type_uint64:
|
||||
return static_cast<double>(uint64_);
|
||||
|
||||
case type_double:
|
||||
return double_;
|
||||
|
||||
default:
|
||||
case type_ieee:
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
string_view
|
||||
number::
|
||||
print(
|
||||
char* buf,
|
||||
std::size_t buf_size) const noexcept
|
||||
{
|
||||
int n;
|
||||
switch(k_)
|
||||
{
|
||||
case type_int64:
|
||||
n = snprintf(buf, buf_size,
|
||||
"%lld", int64_);
|
||||
break;
|
||||
|
||||
case type_uint64:
|
||||
n = snprintf(buf, buf_size,
|
||||
"%llu", uint64_);
|
||||
break;
|
||||
|
||||
case type_double:
|
||||
n = snprintf(buf, buf_size,
|
||||
"%e", double_);
|
||||
break;
|
||||
|
||||
default:
|
||||
case type_ieee:
|
||||
n = snprintf(buf, buf_size,
|
||||
"_unimpl");
|
||||
break;
|
||||
}
|
||||
return { buf, static_cast<
|
||||
std::size_t>(n) };
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
void
|
||||
number::
|
||||
assign_signed(long long i) noexcept
|
||||
{
|
||||
k_ = type_int64;
|
||||
int64_ = i;
|
||||
}
|
||||
|
||||
void
|
||||
number::
|
||||
assign_unsigned(unsigned long long i) noexcept
|
||||
{
|
||||
k_ = type_uint64;
|
||||
uint64_ = i;
|
||||
}
|
||||
|
||||
void
|
||||
number::
|
||||
assign_double(double f) noexcept
|
||||
{
|
||||
k_ = type_double;
|
||||
double_ = f;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
std::ostream&
|
||||
operator<<(std::ostream& os, number const& n)
|
||||
{
|
||||
char buf[number::max_string_chars];
|
||||
os << n.print(buf, sizeof(buf));
|
||||
return os;
|
||||
}
|
||||
|
||||
bool
|
||||
operator==(
|
||||
number const& lhs,
|
||||
number const& rhs) noexcept
|
||||
{
|
||||
switch(lhs.k_)
|
||||
{
|
||||
case number::type_int64:
|
||||
return
|
||||
rhs.is_int64() &&
|
||||
lhs.get_int64() ==
|
||||
rhs.get_int64();
|
||||
|
||||
case number::type_uint64:
|
||||
return
|
||||
rhs.is_uint64() &&
|
||||
lhs.get_uint64() ==
|
||||
rhs.get_uint64();
|
||||
|
||||
case number::type_double:
|
||||
return
|
||||
lhs.get_double() ==
|
||||
rhs.get_double();
|
||||
|
||||
default:
|
||||
case number::type_ieee:
|
||||
break;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
operator!=(
|
||||
number const& lhs,
|
||||
number const& rhs) noexcept
|
||||
{
|
||||
return !(lhs == rhs);
|
||||
}
|
||||
|
||||
} // json
|
||||
} // beast
|
||||
} // boost
|
||||
|
||||
#endif
|
||||
932
include/boost/json/impl/object.hpp
Normal file
932
include/boost/json/impl/object.hpp
Normal file
@@ -0,0 +1,932 @@
|
||||
//
|
||||
// Copyright (c) 2018-2019 Vinnie Falco (vinnie dot falco at gmail dot com)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
// Official repository: https://github.com/boostorg/json
|
||||
//
|
||||
|
||||
#ifndef BOOST_JSON_IMPL_OBJECT_HPP
|
||||
#define BOOST_JSON_IMPL_OBJECT_HPP
|
||||
|
||||
#include <boost/json/value.hpp>
|
||||
#include <boost/json/detail/varint.hpp>
|
||||
#include <boost/core/exchange.hpp>
|
||||
#include <boost/core/ignore_unused.hpp>
|
||||
#include <algorithm>
|
||||
#include <type_traits>
|
||||
|
||||
namespace boost {
|
||||
namespace beast {
|
||||
namespace json {
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
struct object::list_hook
|
||||
{
|
||||
public:
|
||||
element* prev_;
|
||||
element* next_;
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
struct object::element
|
||||
: public list_hook
|
||||
{
|
||||
value v_;
|
||||
element* local_next_;
|
||||
|
||||
BOOST_BEAST_DECL
|
||||
string_view
|
||||
key() const noexcept;
|
||||
|
||||
struct cleanup
|
||||
{
|
||||
std::size_t size;
|
||||
storage_ptr const& sp;
|
||||
std::size_t n;
|
||||
|
||||
void
|
||||
operator()(char* p)
|
||||
{
|
||||
sp->deallocate(p,
|
||||
size, alignof(element));
|
||||
}
|
||||
};
|
||||
|
||||
template<class Arg>
|
||||
static
|
||||
element*
|
||||
allocate(
|
||||
storage_ptr const& sp,
|
||||
key_type key,
|
||||
Arg&& arg)
|
||||
{
|
||||
auto up =
|
||||
prepare_allocate(sp, key);
|
||||
auto const p = up.get();
|
||||
auto const n = up.get_deleter().n;
|
||||
auto e = ::new(up.get()) element(
|
||||
std::forward<Arg>(arg), sp);
|
||||
up.release();
|
||||
detail::varint_write(
|
||||
p + sizeof(element), key.size());
|
||||
std::memcpy(
|
||||
p + sizeof(element) + n,
|
||||
key.data(),
|
||||
key.size());
|
||||
p[sizeof(element) +
|
||||
n + key.size()] = '\0';
|
||||
boost::ignore_unused(e);
|
||||
BOOST_ASSERT(
|
||||
*e->v_.get_storage() == *sp);
|
||||
return reinterpret_cast<element*>(p);
|
||||
}
|
||||
|
||||
BOOST_BEAST_DECL
|
||||
static
|
||||
void
|
||||
destroy(
|
||||
element const* e,
|
||||
storage_ptr const& sp);
|
||||
|
||||
private:
|
||||
template<class Arg>
|
||||
element(
|
||||
Arg&& arg,
|
||||
storage_ptr sp)
|
||||
: v_(std::forward<Arg>(arg),
|
||||
std::move(sp))
|
||||
{
|
||||
}
|
||||
|
||||
BOOST_BEAST_DECL
|
||||
static
|
||||
std::unique_ptr<char, cleanup>
|
||||
prepare_allocate(
|
||||
storage_ptr const& sp,
|
||||
key_type key);
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
class object::hasher
|
||||
{
|
||||
BOOST_BEAST_DECL
|
||||
static
|
||||
std::pair<
|
||||
std::uint64_t, std::uint64_t>
|
||||
init(std::true_type) noexcept;
|
||||
|
||||
BOOST_BEAST_DECL
|
||||
static
|
||||
std::pair<
|
||||
std::uint32_t, std::uint32_t>
|
||||
init(std::false_type) noexcept;
|
||||
|
||||
public:
|
||||
BOOST_BEAST_DECL
|
||||
std::size_t
|
||||
operator()(key_type key) const noexcept;
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
class object::key_equal
|
||||
{
|
||||
public:
|
||||
bool
|
||||
operator()(
|
||||
beast::string_view lhs,
|
||||
beast::string_view rhs) const noexcept
|
||||
{
|
||||
return lhs == rhs;
|
||||
}
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
class object::pointer
|
||||
{
|
||||
reference t_;
|
||||
|
||||
public:
|
||||
pointer(reference t)
|
||||
: t_(t)
|
||||
{
|
||||
}
|
||||
|
||||
reference*
|
||||
operator->() noexcept
|
||||
{
|
||||
return &t_;
|
||||
}
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
class object::const_pointer
|
||||
{
|
||||
const_reference t_;
|
||||
|
||||
public:
|
||||
const_pointer(
|
||||
const_reference t)
|
||||
: t_(t)
|
||||
{
|
||||
}
|
||||
|
||||
const_reference*
|
||||
operator->() noexcept
|
||||
{
|
||||
return &t_;
|
||||
}
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
class object::iterator
|
||||
{
|
||||
element* e_ = nullptr;
|
||||
|
||||
friend class object;
|
||||
|
||||
iterator(element* e)
|
||||
: e_(e)
|
||||
{
|
||||
}
|
||||
|
||||
public:
|
||||
using value_type = object::value_type;
|
||||
using pointer = object::pointer;
|
||||
using reference = object::reference;
|
||||
using difference_type = std::ptrdiff_t;
|
||||
using iterator_category =
|
||||
std::bidirectional_iterator_tag;
|
||||
|
||||
iterator() = default;
|
||||
|
||||
iterator(
|
||||
iterator const&) = default;
|
||||
|
||||
iterator& operator=(
|
||||
iterator const&) = default;
|
||||
|
||||
bool
|
||||
operator==(
|
||||
iterator const& other) const noexcept
|
||||
{
|
||||
return e_ == other.e_;
|
||||
}
|
||||
|
||||
bool
|
||||
operator!=(
|
||||
iterator const& other) const noexcept
|
||||
{
|
||||
return e_ != other.e_;
|
||||
}
|
||||
|
||||
bool
|
||||
operator==(
|
||||
const_iterator const& other) const noexcept;
|
||||
|
||||
bool
|
||||
operator!=(
|
||||
const_iterator const& other) const noexcept;
|
||||
|
||||
iterator&
|
||||
operator++() noexcept
|
||||
{
|
||||
e_ = e_->next_;
|
||||
return *this;
|
||||
}
|
||||
|
||||
iterator
|
||||
operator++(int) noexcept
|
||||
{
|
||||
auto tmp = *this;
|
||||
++*this;
|
||||
return tmp;
|
||||
}
|
||||
|
||||
iterator&
|
||||
operator--() noexcept
|
||||
{
|
||||
e_ = e_->prev_;
|
||||
return *this;
|
||||
}
|
||||
|
||||
iterator
|
||||
operator--(int) noexcept
|
||||
{
|
||||
auto tmp = *this;
|
||||
--*this;
|
||||
return tmp;
|
||||
}
|
||||
|
||||
pointer
|
||||
operator->() const noexcept
|
||||
{
|
||||
return reference{
|
||||
e_->key(), e_->v_ };
|
||||
}
|
||||
|
||||
reference
|
||||
operator*() const noexcept
|
||||
{
|
||||
return {
|
||||
e_->key(), e_->v_ };
|
||||
}
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
class object::const_iterator
|
||||
{
|
||||
element* e_ = nullptr;
|
||||
|
||||
friend class object;
|
||||
|
||||
const_iterator(element* e)
|
||||
: e_(e)
|
||||
{
|
||||
}
|
||||
|
||||
public:
|
||||
using value_type = object::value_type;
|
||||
using pointer = object::const_pointer;
|
||||
using reference = object::const_reference;
|
||||
using difference_type = std::ptrdiff_t;
|
||||
using iterator_category =
|
||||
std::bidirectional_iterator_tag;
|
||||
|
||||
const_iterator() = default;
|
||||
|
||||
const_iterator(
|
||||
const_iterator const&) = default;
|
||||
|
||||
const_iterator& operator=(
|
||||
const_iterator const&) = default;
|
||||
|
||||
const_iterator(iterator it)
|
||||
: e_(it.e_)
|
||||
{
|
||||
}
|
||||
|
||||
const_iterator&
|
||||
operator=(iterator it) noexcept
|
||||
{
|
||||
e_ = it.e_;
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool
|
||||
operator==(
|
||||
const_iterator const& other) const noexcept
|
||||
{
|
||||
return e_ == other.e_;
|
||||
}
|
||||
|
||||
bool
|
||||
operator!=(
|
||||
const_iterator const& other) const noexcept
|
||||
{
|
||||
return e_ != other.e_;
|
||||
}
|
||||
|
||||
bool
|
||||
operator==(
|
||||
iterator const& other) const noexcept
|
||||
{
|
||||
return e_ == other.e_;
|
||||
}
|
||||
|
||||
bool
|
||||
operator!=(
|
||||
iterator const& other) const noexcept
|
||||
{
|
||||
return e_ != other.e_;
|
||||
}
|
||||
|
||||
const_iterator&
|
||||
operator++() noexcept
|
||||
{
|
||||
e_ = e_->next_;
|
||||
return *this;
|
||||
}
|
||||
|
||||
const_iterator
|
||||
operator++(int) noexcept
|
||||
{
|
||||
auto tmp = *this;
|
||||
++*this;
|
||||
return tmp;
|
||||
}
|
||||
|
||||
const_iterator&
|
||||
operator--() noexcept
|
||||
{
|
||||
e_ = e_->prev_;
|
||||
return *this;
|
||||
}
|
||||
|
||||
const_iterator
|
||||
operator--(int) noexcept
|
||||
{
|
||||
auto tmp = *this;
|
||||
--*this;
|
||||
return tmp;
|
||||
}
|
||||
|
||||
pointer
|
||||
operator->() const noexcept
|
||||
{
|
||||
return const_reference{
|
||||
e_->key(), e_->v_ };
|
||||
}
|
||||
|
||||
reference
|
||||
operator*() const noexcept
|
||||
{
|
||||
return {
|
||||
e_->key(), e_->v_ };
|
||||
}
|
||||
};
|
||||
|
||||
inline
|
||||
bool
|
||||
object::
|
||||
iterator::
|
||||
operator==(
|
||||
const_iterator const& other) const noexcept
|
||||
{
|
||||
return e_ == other.e_;
|
||||
}
|
||||
|
||||
inline
|
||||
bool
|
||||
object::
|
||||
iterator::
|
||||
operator!=(
|
||||
const_iterator const& other) const noexcept
|
||||
{
|
||||
return e_ != other.e_;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
class object::local_iterator
|
||||
{
|
||||
element* e_ = nullptr;
|
||||
|
||||
friend class object;
|
||||
|
||||
local_iterator(element* e)
|
||||
: e_(e)
|
||||
{
|
||||
}
|
||||
|
||||
public:
|
||||
using value_type = object::value_type;
|
||||
|
||||
using reference = object::reference;
|
||||
|
||||
local_iterator() = default;
|
||||
|
||||
local_iterator(
|
||||
local_iterator const&) = default;
|
||||
|
||||
local_iterator& operator=(
|
||||
local_iterator const&) = default;
|
||||
|
||||
bool
|
||||
operator==(
|
||||
local_iterator const& other) const noexcept
|
||||
{
|
||||
return e_ == other.e_;
|
||||
}
|
||||
|
||||
bool
|
||||
operator!=(
|
||||
local_iterator const& other) const noexcept
|
||||
{
|
||||
return e_ != other.e_;
|
||||
}
|
||||
|
||||
bool
|
||||
operator==(
|
||||
iterator const& other) const noexcept
|
||||
{
|
||||
return e_ == other.e_;
|
||||
}
|
||||
|
||||
bool
|
||||
operator!=(
|
||||
iterator const& other) const noexcept
|
||||
{
|
||||
return e_ != other.e_;
|
||||
}
|
||||
|
||||
local_iterator&
|
||||
operator++() noexcept
|
||||
{
|
||||
e_ = e_->local_next_;
|
||||
return *this;
|
||||
}
|
||||
|
||||
local_iterator
|
||||
operator++(int) noexcept
|
||||
{
|
||||
auto tmp = *this;
|
||||
++*this;
|
||||
return tmp;
|
||||
}
|
||||
|
||||
const_pointer
|
||||
operator->() const noexcept
|
||||
{
|
||||
return const_reference{
|
||||
e_->key(), e_->v_ };
|
||||
}
|
||||
|
||||
const_reference
|
||||
operator*() const noexcept
|
||||
{
|
||||
return {
|
||||
e_->key(), e_->v_ };
|
||||
}
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
class object::const_local_iterator
|
||||
{
|
||||
element const* e_ = nullptr;
|
||||
|
||||
friend class object;
|
||||
|
||||
const_local_iterator(element const* e)
|
||||
: e_(e)
|
||||
{
|
||||
}
|
||||
|
||||
public:
|
||||
using value_type = object::value_type;
|
||||
|
||||
using reference = object::const_reference;
|
||||
|
||||
const_local_iterator() = default;
|
||||
|
||||
const_local_iterator(
|
||||
const_local_iterator const&) = default;
|
||||
|
||||
const_local_iterator& operator=(
|
||||
const_local_iterator const&) = default;
|
||||
|
||||
bool
|
||||
operator==(
|
||||
const_local_iterator const& other) const noexcept
|
||||
{
|
||||
return e_ == other.e_;
|
||||
}
|
||||
|
||||
bool
|
||||
operator!=(
|
||||
const_local_iterator const& other) const noexcept
|
||||
{
|
||||
return e_ != other.e_;
|
||||
}
|
||||
|
||||
bool
|
||||
operator==(
|
||||
iterator const& other) const noexcept
|
||||
{
|
||||
return e_ == other.e_;
|
||||
}
|
||||
|
||||
bool
|
||||
operator!=(
|
||||
iterator const& other) const noexcept
|
||||
{
|
||||
return e_ != other.e_;
|
||||
}
|
||||
|
||||
const_local_iterator&
|
||||
operator++() noexcept
|
||||
{
|
||||
e_ = e_->local_next_;
|
||||
return *this;
|
||||
}
|
||||
|
||||
const_local_iterator
|
||||
operator++(int) noexcept
|
||||
{
|
||||
auto tmp = *this;
|
||||
++*this;
|
||||
return tmp;
|
||||
}
|
||||
|
||||
const_pointer
|
||||
operator->() const noexcept
|
||||
{
|
||||
return const_reference{
|
||||
e_->key(), e_->v_ };
|
||||
}
|
||||
|
||||
const_reference
|
||||
operator*() const noexcept
|
||||
{
|
||||
return {
|
||||
e_->key(), e_->v_ };
|
||||
}
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
class object::node_type
|
||||
{
|
||||
element* e_ = nullptr;
|
||||
storage_ptr sp_;
|
||||
|
||||
friend class object;
|
||||
|
||||
node_type(
|
||||
element* e,
|
||||
storage_ptr sp)
|
||||
: e_(e)
|
||||
, sp_(std::move(sp))
|
||||
{
|
||||
}
|
||||
|
||||
public:
|
||||
using key_type = beast::string_view;
|
||||
using mapped_type = json::value;
|
||||
|
||||
node_type() = default;
|
||||
node_type(node_type const&) = delete;
|
||||
|
||||
~node_type()
|
||||
{
|
||||
if(e_)
|
||||
element::destroy(e_, sp_);
|
||||
}
|
||||
|
||||
node_type(node_type&& other)
|
||||
: e_(boost::exchange(
|
||||
other.e_, nullptr))
|
||||
, sp_(boost::exchange(
|
||||
other.sp_, nullptr))
|
||||
{
|
||||
}
|
||||
|
||||
node_type&
|
||||
operator=(node_type&& other)
|
||||
{
|
||||
if(e_)
|
||||
{
|
||||
element::destroy(e_, sp_);
|
||||
e_ = nullptr;
|
||||
sp_ = nullptr;
|
||||
}
|
||||
if(other.e_)
|
||||
{
|
||||
e_ = boost::exchange(
|
||||
other.e_, nullptr);
|
||||
sp_ = std::move(other.sp_);
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
storage_ptr const&
|
||||
get_storage() const noexcept
|
||||
{
|
||||
return sp_;
|
||||
}
|
||||
|
||||
bool
|
||||
empty() const noexcept
|
||||
{
|
||||
return e_ == nullptr;
|
||||
}
|
||||
|
||||
explicit
|
||||
operator bool() const noexcept
|
||||
{
|
||||
return e_ != nullptr;
|
||||
}
|
||||
|
||||
key_type
|
||||
key() const noexcept
|
||||
{
|
||||
return e_->key();
|
||||
}
|
||||
|
||||
mapped_type&
|
||||
value() noexcept
|
||||
{
|
||||
return e_->v_;
|
||||
}
|
||||
|
||||
mapped_type const&
|
||||
value() const noexcept
|
||||
{
|
||||
return e_->v_;
|
||||
}
|
||||
};
|
||||
|
||||
struct object::insert_return_type
|
||||
{
|
||||
iterator position;
|
||||
bool inserted;
|
||||
node_type node;
|
||||
};
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
template<class InputIt>
|
||||
object::
|
||||
object(
|
||||
InputIt first,
|
||||
InputIt last)
|
||||
: sp_(default_storage())
|
||||
{
|
||||
construct(first, last, 0,
|
||||
iter_cat<InputIt>{});
|
||||
}
|
||||
|
||||
template<class InputIt>
|
||||
object::
|
||||
object(
|
||||
InputIt first,
|
||||
InputIt last,
|
||||
size_type capacity)
|
||||
: sp_(default_storage())
|
||||
{
|
||||
construct(first, last, capacity,
|
||||
iter_cat<InputIt>{});
|
||||
}
|
||||
|
||||
template<class InputIt>
|
||||
object::
|
||||
object(
|
||||
InputIt first,
|
||||
InputIt last,
|
||||
storage_ptr store)
|
||||
: sp_(std::move(store))
|
||||
{
|
||||
construct(first, last, 0,
|
||||
iter_cat<InputIt>{});
|
||||
}
|
||||
|
||||
template<class InputIt>
|
||||
object::
|
||||
object(
|
||||
InputIt first,
|
||||
InputIt last,
|
||||
size_type capacity,
|
||||
storage_ptr store)
|
||||
: sp_(std::move(store))
|
||||
{
|
||||
construct(first, last, capacity,
|
||||
iter_cat<InputIt>{});
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
template<class P, class>
|
||||
auto
|
||||
object::
|
||||
insert(P&& p)->
|
||||
std::pair<iterator, bool>
|
||||
{
|
||||
return insert(end(), std::forward<P>(p));
|
||||
}
|
||||
|
||||
template<class P, class>
|
||||
auto
|
||||
object::
|
||||
insert(const_iterator before, P&& p) ->
|
||||
std::pair<iterator, bool>
|
||||
{
|
||||
value_type v(std::forward<P>(p));
|
||||
return emplace_impl(before, v.first,
|
||||
std::move(v.second));
|
||||
}
|
||||
|
||||
template<class InputIt>
|
||||
void
|
||||
object::
|
||||
insert(InputIt first, InputIt last)
|
||||
{
|
||||
insert(first, last, iter_cat<InputIt>{});
|
||||
}
|
||||
|
||||
template<class M>
|
||||
auto
|
||||
object::
|
||||
insert_or_assign(
|
||||
key_type key, M&& obj) ->
|
||||
std::pair<iterator, bool>
|
||||
{
|
||||
return insert_or_assign(end(), key,
|
||||
std::forward<M>(obj));
|
||||
}
|
||||
|
||||
template<class M>
|
||||
auto
|
||||
object::
|
||||
insert_or_assign(
|
||||
const_iterator before,
|
||||
key_type key,
|
||||
M&& obj) ->
|
||||
std::pair<iterator, bool>
|
||||
{
|
||||
auto const hash = hasher{}(key);
|
||||
auto e = prepare_insert(&before, key, hash);
|
||||
if(e)
|
||||
{
|
||||
e->v_ = std::forward<M>(obj);
|
||||
return { iterator(e), false };
|
||||
}
|
||||
e = element::allocate(sp_, key,
|
||||
std::forward<M>(obj));
|
||||
finish_insert(before, e, hash);
|
||||
return { iterator(e), true, };
|
||||
}
|
||||
|
||||
template<class Arg>
|
||||
auto
|
||||
object::
|
||||
emplace(key_type key, Arg&& arg) ->
|
||||
std::pair<iterator, bool>
|
||||
{
|
||||
return emplace_impl(end(), key,
|
||||
std::forward<Arg>(arg));
|
||||
}
|
||||
|
||||
template<class Arg>
|
||||
auto
|
||||
object::
|
||||
emplace(const_iterator before,
|
||||
key_type key, Arg&& arg) ->
|
||||
std::pair<iterator, bool>
|
||||
{
|
||||
return emplace_impl(before, key,
|
||||
std::forward<Arg>(arg));
|
||||
}
|
||||
|
||||
inline
|
||||
auto
|
||||
object::
|
||||
hash_function() const ->
|
||||
hasher
|
||||
{
|
||||
return hasher{};
|
||||
}
|
||||
|
||||
inline
|
||||
auto
|
||||
object::
|
||||
key_eq() const ->
|
||||
key_equal
|
||||
{
|
||||
return key_equal{};
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
template<class InputIt>
|
||||
void
|
||||
object::
|
||||
construct(
|
||||
InputIt first,
|
||||
InputIt last,
|
||||
size_type capacity,
|
||||
std::forward_iterator_tag)
|
||||
{
|
||||
reserve(std::max<size_type>(capacity,
|
||||
std::distance(first, last)));
|
||||
while(first != last)
|
||||
{
|
||||
value_type v(*first++);
|
||||
emplace_impl(end(), v.first,
|
||||
std::move(v.second));
|
||||
}
|
||||
}
|
||||
|
||||
template<class InputIt>
|
||||
void
|
||||
object::
|
||||
construct(
|
||||
InputIt first,
|
||||
InputIt last,
|
||||
size_type capacity,
|
||||
std::input_iterator_tag)
|
||||
{
|
||||
reserve(capacity);
|
||||
while(first != last)
|
||||
{
|
||||
value_type v(*first++);
|
||||
emplace_impl(end(), v.first,
|
||||
std::move(v.second));
|
||||
}
|
||||
}
|
||||
|
||||
template<class InputIt>
|
||||
void
|
||||
object::
|
||||
insert(InputIt first, InputIt last,
|
||||
std::forward_iterator_tag)
|
||||
{
|
||||
reserve(size() +
|
||||
std::distance(first, last));
|
||||
while(first != last)
|
||||
{
|
||||
value_type v(*first++);
|
||||
emplace_impl(end(), v.first,
|
||||
std::move(v.second));
|
||||
}
|
||||
}
|
||||
|
||||
template<class InputIt>
|
||||
void
|
||||
object::
|
||||
insert(InputIt first, InputIt last,
|
||||
std::input_iterator_tag)
|
||||
{
|
||||
while(first != last)
|
||||
{
|
||||
value_type v(*first++);
|
||||
emplace_impl(end(), v.first,
|
||||
std::move(v.second));
|
||||
}
|
||||
}
|
||||
|
||||
template<class Arg>
|
||||
auto
|
||||
object::
|
||||
emplace_impl(
|
||||
const_iterator before,
|
||||
key_type key,
|
||||
Arg&& arg) ->
|
||||
std::pair<iterator, bool>
|
||||
{
|
||||
auto const hash = hasher{}(key);
|
||||
auto e = prepare_insert(
|
||||
&before, key, hash);
|
||||
if(e)
|
||||
return { iterator(e), false };
|
||||
e = element::allocate(sp_, key,
|
||||
std::forward<Arg>(arg));
|
||||
finish_insert(before, e, hash);
|
||||
return { iterator(e), true };
|
||||
}
|
||||
|
||||
} // json
|
||||
} // beast
|
||||
} // boost
|
||||
|
||||
#endif
|
||||
1268
include/boost/json/impl/object.ipp
Normal file
1268
include/boost/json/impl/object.ipp
Normal file
File diff suppressed because it is too large
Load Diff
61
include/boost/json/impl/parse_file.ipp
Normal file
61
include/boost/json/impl/parse_file.ipp
Normal file
@@ -0,0 +1,61 @@
|
||||
//
|
||||
// Copyright (c) 2018-2019 Vinnie Falco (vinnie dot falco at gmail dot com)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
// Official repository: https://github.com/boostorg/json
|
||||
//
|
||||
|
||||
#ifndef BOOST_JSON_IMPL_PARSE_FILE_IPP
|
||||
#define BOOST_JSON_IMPL_PARSE_FILE_IPP
|
||||
|
||||
#include <boost/beast/core/file.hpp>
|
||||
#include <boost/beast/core/flat_buffer.hpp>
|
||||
#include <boost/beast/core/detail/clamp.hpp>
|
||||
|
||||
namespace boost {
|
||||
namespace beast {
|
||||
namespace json {
|
||||
|
||||
void
|
||||
parse_file(
|
||||
char const* path,
|
||||
basic_parser& parser,
|
||||
error_code& ec)
|
||||
{
|
||||
file f;
|
||||
f.open(path, beast::file_mode::scan, ec);
|
||||
if(ec)
|
||||
return;
|
||||
flat_buffer b;
|
||||
auto remain = f.size(ec);
|
||||
if(ec)
|
||||
return;
|
||||
while(remain > 0)
|
||||
{
|
||||
auto amount = beast::detail::clamp(remain);
|
||||
auto mb = b.prepare(amount);
|
||||
b.commit(f.read(mb.data(), mb.size(), ec));
|
||||
if(ec)
|
||||
return;
|
||||
if(remain == b.size())
|
||||
break;
|
||||
auto bytes_used =
|
||||
parser.write_some(b.data(), ec);
|
||||
if(ec)
|
||||
return;
|
||||
remain -= b.size();
|
||||
b.consume(bytes_used);
|
||||
}
|
||||
parser.write(b.data(), ec);
|
||||
if(ec)
|
||||
return;
|
||||
// finished
|
||||
}
|
||||
|
||||
} // json
|
||||
} // beast
|
||||
} // boost
|
||||
|
||||
#endif
|
||||
47
include/boost/json/impl/parser.hpp
Normal file
47
include/boost/json/impl/parser.hpp
Normal file
@@ -0,0 +1,47 @@
|
||||
//
|
||||
// Copyright (c) 2018-2019 Vinnie Falco (vinnie dot falco at gmail dot com)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
// Official repository: https://github.com/boostorg/json
|
||||
//
|
||||
|
||||
#ifndef BOOST_JSON_IMPL_PARSER_HPP
|
||||
#define BOOST_JSON_IMPL_PARSER_HPP
|
||||
|
||||
namespace boost {
|
||||
namespace beast {
|
||||
namespace json {
|
||||
|
||||
template<class T>
|
||||
void
|
||||
parser::
|
||||
assign(T&& t)
|
||||
{
|
||||
auto& jv = *stack_.front();
|
||||
BOOST_ASSERT(! jv.is_object());
|
||||
if(obj_)
|
||||
{
|
||||
BOOST_ASSERT(jv.is_null());
|
||||
jv = std::forward<T>(t);
|
||||
stack_.pop_front();
|
||||
}
|
||||
else if(stack_.front()->is_array())
|
||||
{
|
||||
BOOST_ASSERT(s_.empty());
|
||||
jv.as_array().emplace_back(
|
||||
std::forward<T>(t));
|
||||
}
|
||||
else
|
||||
{
|
||||
BOOST_ASSERT(jv.is_null());
|
||||
jv = std::forward<T>(t);
|
||||
}
|
||||
}
|
||||
|
||||
} // json
|
||||
} // beast
|
||||
} // boost
|
||||
|
||||
#endif
|
||||
273
include/boost/json/impl/parser.ipp
Normal file
273
include/boost/json/impl/parser.ipp
Normal file
@@ -0,0 +1,273 @@
|
||||
//
|
||||
// Copyright (c) 2018-2019 Vinnie Falco (vinnie dot falco at gmail dot com)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
// Official repository: https://github.com/boostorg/json
|
||||
//
|
||||
|
||||
#ifndef BOOST_JSON_IMPL_PARSER_IPP
|
||||
#define BOOST_JSON_IMPL_PARSER_IPP
|
||||
|
||||
#include <boost/json/parser.hpp>
|
||||
#include <boost/json/error.hpp>
|
||||
#include <boost/core/ignore_unused.hpp>
|
||||
#include <boost/assert.hpp>
|
||||
|
||||
namespace boost {
|
||||
namespace beast {
|
||||
namespace json {
|
||||
|
||||
parser::
|
||||
parser()
|
||||
{
|
||||
}
|
||||
|
||||
parser::
|
||||
parser(storage_ptr const& store)
|
||||
: jv_(store)
|
||||
{
|
||||
}
|
||||
|
||||
value const&
|
||||
parser::
|
||||
get() const noexcept
|
||||
{
|
||||
return jv_;
|
||||
}
|
||||
|
||||
value
|
||||
parser::
|
||||
release() noexcept
|
||||
{
|
||||
return std::move(jv_);
|
||||
}
|
||||
|
||||
void
|
||||
parser::
|
||||
on_document_begin(error_code&)
|
||||
{
|
||||
stack_.clear();
|
||||
stack_.push_front(&jv_);
|
||||
s_.clear();
|
||||
obj_ = false;
|
||||
}
|
||||
|
||||
void
|
||||
parser::
|
||||
on_object_begin(error_code& ec)
|
||||
{
|
||||
if(stack_.size() >= max_depth_)
|
||||
{
|
||||
ec = error::too_deep;
|
||||
return;
|
||||
}
|
||||
auto& jv = *stack_.front();
|
||||
BOOST_ASSERT(! jv.is_object());
|
||||
if(obj_)
|
||||
{
|
||||
BOOST_ASSERT(jv.is_null());
|
||||
jv.emplace_object();
|
||||
}
|
||||
else if(jv.is_array())
|
||||
{
|
||||
jv.as_array().emplace_back(
|
||||
kind::object);
|
||||
stack_.push_front(
|
||||
&jv.as_array().back());
|
||||
}
|
||||
else
|
||||
{
|
||||
BOOST_ASSERT(jv.is_null());
|
||||
jv = kind::object;
|
||||
}
|
||||
obj_ = true;
|
||||
}
|
||||
|
||||
void
|
||||
parser::
|
||||
on_object_end(error_code&)
|
||||
{
|
||||
BOOST_ASSERT(
|
||||
stack_.front()->is_object());
|
||||
stack_.pop_front();
|
||||
if(! stack_.empty())
|
||||
{
|
||||
auto const& jv = stack_.front();
|
||||
BOOST_ASSERT(
|
||||
jv->is_array() || jv->is_object());
|
||||
obj_ = jv->is_object();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
parser::
|
||||
on_array_begin(error_code& ec)
|
||||
{
|
||||
if(stack_.size() >= max_depth_)
|
||||
{
|
||||
ec = error::too_deep;
|
||||
return;
|
||||
}
|
||||
auto& jv = *stack_.front();
|
||||
BOOST_ASSERT(! jv.is_object());
|
||||
if(obj_)
|
||||
{
|
||||
BOOST_ASSERT(jv.is_null());
|
||||
jv.emplace_array();
|
||||
}
|
||||
else if(jv.is_array())
|
||||
{
|
||||
BOOST_ASSERT(s_.empty());
|
||||
jv.as_array().emplace_back(
|
||||
kind::array);
|
||||
stack_.push_front(
|
||||
&jv.as_array().back());
|
||||
}
|
||||
else
|
||||
{
|
||||
BOOST_ASSERT(jv.is_null());
|
||||
jv = kind::array;
|
||||
}
|
||||
obj_ = false;
|
||||
}
|
||||
|
||||
void
|
||||
parser::
|
||||
on_array_end(error_code&)
|
||||
{
|
||||
BOOST_ASSERT(
|
||||
stack_.front()->is_array());
|
||||
stack_.pop_front();
|
||||
if(! stack_.empty())
|
||||
{
|
||||
auto const& jv = stack_.front();
|
||||
BOOST_ASSERT(
|
||||
jv->is_array() || jv->is_object());
|
||||
obj_ = jv->is_object();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
parser::
|
||||
on_key_data(
|
||||
string_view s,
|
||||
error_code&)
|
||||
{
|
||||
s_.append(s.data(), s.size());
|
||||
}
|
||||
|
||||
void
|
||||
parser::
|
||||
on_key_end(
|
||||
string_view s,
|
||||
error_code&)
|
||||
{
|
||||
auto& jv = *stack_.front();
|
||||
if(! s_.empty())
|
||||
{
|
||||
s_.append(s.data(), s.size());
|
||||
s = {s_.data(), s_.size()};
|
||||
}
|
||||
if(jv.is_object())
|
||||
{
|
||||
stack_.push_front(
|
||||
&jv.as_object().emplace(s,
|
||||
kind::null).first->second);
|
||||
}
|
||||
else if(stack_.front()->is_array())
|
||||
{
|
||||
BOOST_ASSERT(s_.empty());
|
||||
jv.as_array().emplace_back(kind::null);
|
||||
}
|
||||
else
|
||||
{
|
||||
BOOST_ASSERT(jv.is_null());
|
||||
// nothing to do
|
||||
}
|
||||
s_.clear();
|
||||
}
|
||||
|
||||
void
|
||||
parser::
|
||||
on_string_data(
|
||||
string_view s, error_code&)
|
||||
{
|
||||
auto& jv = *stack_.front();
|
||||
BOOST_ASSERT(! jv.is_object());
|
||||
if(! jv.is_string())
|
||||
{
|
||||
if(obj_)
|
||||
{
|
||||
BOOST_ASSERT(jv.is_null());
|
||||
jv.emplace_string().append(
|
||||
s.data(), s.size());
|
||||
}
|
||||
else if(stack_.front()->is_array())
|
||||
{
|
||||
BOOST_ASSERT(s_.empty());
|
||||
jv.as_array().emplace_back(kind::string);
|
||||
stack_.push_front(
|
||||
&jv.as_array().back());
|
||||
stack_.front()->as_string().append(
|
||||
s.data(), s.size());
|
||||
}
|
||||
else
|
||||
{
|
||||
BOOST_ASSERT(jv.is_null());
|
||||
jv.emplace_string().append(
|
||||
s.data(), s.size());
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
stack_.front()->as_string().append(
|
||||
s.data(), s.size());
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
parser::
|
||||
on_string_end(
|
||||
string_view s,
|
||||
error_code& ec)
|
||||
{
|
||||
on_string_data(s, ec);
|
||||
BOOST_ASSERT(stack_.front()->is_string());
|
||||
stack_.pop_front();
|
||||
if(! stack_.empty())
|
||||
{
|
||||
auto const& jv = stack_.front();
|
||||
BOOST_ASSERT(
|
||||
jv->is_array() || jv->is_object());
|
||||
obj_ = jv->is_object();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
parser::
|
||||
on_number(number n, error_code&)
|
||||
{
|
||||
assign(n);
|
||||
}
|
||||
|
||||
void
|
||||
parser::
|
||||
on_bool(bool b, error_code&)
|
||||
{
|
||||
assign(b);
|
||||
}
|
||||
|
||||
void
|
||||
parser::
|
||||
on_null(error_code&)
|
||||
{
|
||||
assign(null);
|
||||
}
|
||||
|
||||
} // json
|
||||
} // beast
|
||||
} // boost
|
||||
|
||||
#endif
|
||||
260
include/boost/json/impl/serializer.ipp
Normal file
260
include/boost/json/impl/serializer.ipp
Normal file
@@ -0,0 +1,260 @@
|
||||
//
|
||||
// Copyright (c) 2018-2019 Vinnie Falco (vinnie dot falco at gmail dot com)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
// Official repository: https://github.com/boostorg/json
|
||||
//
|
||||
|
||||
#ifndef BOOST_JSON_IMPL_SERIALIZER_IPP
|
||||
#define BOOST_JSON_IMPL_SERIALIZER_IPP
|
||||
|
||||
#include <boost/json/serializer.hpp>
|
||||
|
||||
namespace boost {
|
||||
namespace beast {
|
||||
namespace json {
|
||||
|
||||
serializer::
|
||||
impl::
|
||||
impl(value const& jv)
|
||||
: jv_(jv)
|
||||
, it_(jv)
|
||||
{
|
||||
}
|
||||
|
||||
bool
|
||||
serializer::
|
||||
impl::
|
||||
is_done() const noexcept
|
||||
{
|
||||
return state_ == state::done;
|
||||
}
|
||||
|
||||
std::size_t
|
||||
serializer::
|
||||
impl::
|
||||
next(net::mutable_buffer b)
|
||||
{
|
||||
auto const p0 =
|
||||
reinterpret_cast<char*>(b.data());
|
||||
auto p = p0;
|
||||
auto n = b.size();
|
||||
while(n > 0)
|
||||
{
|
||||
switch(state_)
|
||||
{
|
||||
case state::next:
|
||||
++it_;
|
||||
if(it_ == end)
|
||||
{
|
||||
state_ = state::done;
|
||||
break;
|
||||
}
|
||||
BOOST_FALLTHROUGH;
|
||||
|
||||
case state::init:
|
||||
str_ = it_->key;
|
||||
if(! str_.empty())
|
||||
{
|
||||
*p++ = '\"';
|
||||
--n;
|
||||
state_ = state::key;
|
||||
}
|
||||
else
|
||||
{
|
||||
state_ = state::value;
|
||||
}
|
||||
break;
|
||||
|
||||
case state::key:
|
||||
case state::string:
|
||||
// Write escaped/UTF-8 string
|
||||
if(n >= str_.size())
|
||||
{
|
||||
std::memcpy(p,
|
||||
str_.data(), str_.size());
|
||||
p += str_.size();
|
||||
n -= str_.size();
|
||||
if(state_ == state::string)
|
||||
{
|
||||
if(last_)
|
||||
str_ = {"\"", 1};
|
||||
else
|
||||
str_ = {"\",", 2};
|
||||
state_ = state::literal;
|
||||
}
|
||||
else
|
||||
{
|
||||
str_ = {"\":", 2};
|
||||
state_ = state::key_literal;
|
||||
}
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
std::memcpy(p,
|
||||
str_.data(), n);
|
||||
p += n;
|
||||
str_ = {
|
||||
str_.data() + n,
|
||||
str_.size() - n};
|
||||
n = 0;
|
||||
}
|
||||
break;
|
||||
|
||||
case state::literal:
|
||||
case state::key_literal:
|
||||
// Copy content of str_ without escapes
|
||||
if(n >= str_.size())
|
||||
{
|
||||
std::memcpy(p,
|
||||
str_.data(), str_.size());
|
||||
p += str_.size();
|
||||
n -= str_.size();
|
||||
if(state_ == state::literal)
|
||||
state_ = state::next;
|
||||
else
|
||||
state_ = state::value;
|
||||
}
|
||||
else
|
||||
{
|
||||
std::memcpy(p,
|
||||
str_.data(), n);
|
||||
p += n;
|
||||
str_ = {
|
||||
str_.data() + n,
|
||||
str_.size() - n};
|
||||
n = 0;
|
||||
}
|
||||
break;
|
||||
|
||||
case state::value:
|
||||
{
|
||||
auto const& e = *it_;
|
||||
if(! e.end)
|
||||
{
|
||||
switch(e.value.kind())
|
||||
{
|
||||
case kind::object:
|
||||
*p++ = '{';
|
||||
--n;
|
||||
state_ = state::next;
|
||||
break;
|
||||
case kind::array:
|
||||
*p++ = '[';
|
||||
--n;
|
||||
state_ = state::next;
|
||||
break;
|
||||
case kind::string:
|
||||
*p++ = '\"';
|
||||
str_ = e.value.as_string();
|
||||
last_ = e.last;
|
||||
state_ = state::string;
|
||||
break;
|
||||
case kind::number:
|
||||
str_ = e.value.as_number().print(
|
||||
buf_, sizeof(buf_));
|
||||
if(! e.last)
|
||||
{
|
||||
buf_[str_.size()] = ',';
|
||||
str_ = {buf_, str_.size() + 1};
|
||||
}
|
||||
state_ = state::literal;
|
||||
break;
|
||||
case kind::boolean:
|
||||
if(e.value.as_bool())
|
||||
{
|
||||
if(! e.last)
|
||||
str_ = {"true,", 5};
|
||||
else
|
||||
str_ = {"true", 4};
|
||||
}
|
||||
else
|
||||
{
|
||||
if(! e.last)
|
||||
str_ = {"false,", 6};
|
||||
else
|
||||
str_ = {"false", 5};
|
||||
}
|
||||
state_ = state::literal;
|
||||
break;
|
||||
case kind::null:
|
||||
if(! e.last)
|
||||
str_ = {"null,", 5};
|
||||
else
|
||||
str_ = {"null", 4};
|
||||
state_ = state::literal;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if(e->value.is_object())
|
||||
{
|
||||
if(! e.last)
|
||||
str_ = {"},", 2};
|
||||
else
|
||||
str_ = {"}", 1};
|
||||
state_ = state::literal;
|
||||
}
|
||||
else if(e->value.is_array())
|
||||
{
|
||||
if(! e.last)
|
||||
str_ = {"],", 2};
|
||||
else
|
||||
str_ = {"]", 1};
|
||||
state_ = state::literal;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case state::done:
|
||||
goto finish;
|
||||
}
|
||||
}
|
||||
finish:
|
||||
return p - p0;
|
||||
}
|
||||
|
||||
void
|
||||
serializer::
|
||||
impl::
|
||||
append(char c,
|
||||
net::mutable_buffer& b)
|
||||
{
|
||||
BOOST_ASSERT(b.size() >= 1);
|
||||
*reinterpret_cast<char*>(b.data()) = c;
|
||||
b += 1;
|
||||
}
|
||||
|
||||
void
|
||||
serializer::
|
||||
impl::
|
||||
append(
|
||||
char const* s, std::size_t n,
|
||||
net::mutable_buffer& b)
|
||||
{
|
||||
BOOST_ASSERT(b.size() >= n);
|
||||
std::memcpy(b.data(), s, n);
|
||||
b += n;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
serializer::
|
||||
~serializer()
|
||||
{
|
||||
get_base().~base();
|
||||
}
|
||||
|
||||
serializer::
|
||||
serializer(value const& jv)
|
||||
{
|
||||
::new(&get_base()) impl(jv);
|
||||
}
|
||||
|
||||
} // json
|
||||
} // beast
|
||||
} // boost
|
||||
|
||||
#endif
|
||||
31
include/boost/json/impl/storage.hpp
Normal file
31
include/boost/json/impl/storage.hpp
Normal file
@@ -0,0 +1,31 @@
|
||||
//
|
||||
// Copyright (c) 2018-2019 Vinnie Falco (vinnie dot falco at gmail dot com)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
// Official repository: https://github.com/boostorg/json
|
||||
//
|
||||
|
||||
#ifndef BOOST_JSON_IMPL_STORAGE_HPP
|
||||
#define BOOST_JSON_IMPL_STORAGE_HPP
|
||||
|
||||
#include <boost/json/detail/storage_adaptor.hpp>
|
||||
|
||||
namespace boost {
|
||||
namespace beast {
|
||||
namespace json {
|
||||
|
||||
template<class Allocator>
|
||||
storage_ptr
|
||||
make_storage_ptr(Allocator const& a)
|
||||
{
|
||||
return storage_ptr(
|
||||
new detail::storage_adaptor<Allocator>(a));
|
||||
}
|
||||
|
||||
} // json
|
||||
} // beast
|
||||
} // boost
|
||||
|
||||
#endif
|
||||
113
include/boost/json/impl/storage.ipp
Normal file
113
include/boost/json/impl/storage.ipp
Normal file
@@ -0,0 +1,113 @@
|
||||
//
|
||||
// Copyright (c) 2018-2019 Vinnie Falco (vinnie dot falco at gmail dot com)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
// Official repository: https://github.com/boostorg/json
|
||||
//
|
||||
|
||||
#ifndef BOOST_JSON_IMPL_STORAGE_IPP
|
||||
#define BOOST_JSON_IMPL_STORAGE_IPP
|
||||
|
||||
#include <boost/json/storage.hpp>
|
||||
#include <boost/json/detail/storage_adaptor.hpp>
|
||||
#include <boost/core/exchange.hpp>
|
||||
#include <boost/assert.hpp>
|
||||
#include <memory>
|
||||
|
||||
namespace boost {
|
||||
namespace beast {
|
||||
namespace json {
|
||||
|
||||
storage_ptr::
|
||||
~storage_ptr()
|
||||
{
|
||||
if(p_)
|
||||
p_->release();
|
||||
}
|
||||
|
||||
storage_ptr::
|
||||
storage_ptr(storage_ptr&& other) noexcept
|
||||
: p_(boost::exchange(other.p_, nullptr))
|
||||
{
|
||||
}
|
||||
|
||||
storage_ptr::
|
||||
storage_ptr(storage_ptr const& other) noexcept
|
||||
: p_(other.p_)
|
||||
{
|
||||
if(p_)
|
||||
p_->addref();
|
||||
}
|
||||
|
||||
storage_ptr&
|
||||
storage_ptr::
|
||||
operator=(storage_ptr&& other) noexcept
|
||||
{
|
||||
BOOST_ASSERT(this != &other);
|
||||
if(p_)
|
||||
p_->release();
|
||||
p_ = boost::exchange(other.p_, nullptr);
|
||||
return *this;
|
||||
}
|
||||
|
||||
storage_ptr&
|
||||
storage_ptr::
|
||||
operator=(storage_ptr const& other) noexcept
|
||||
{
|
||||
if(other.p_)
|
||||
other.p_->addref();
|
||||
if(p_)
|
||||
p_->release();
|
||||
p_ = other.p_;
|
||||
return *this;
|
||||
}
|
||||
|
||||
storage_ptr::
|
||||
storage_ptr(storage* p) noexcept
|
||||
: p_(p)
|
||||
{
|
||||
}
|
||||
|
||||
storage*
|
||||
storage_ptr::
|
||||
release() noexcept
|
||||
{
|
||||
return boost::exchange(p_, nullptr);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
namespace detail {
|
||||
|
||||
inline
|
||||
storage_ptr&
|
||||
raw_default_storage() noexcept
|
||||
{
|
||||
static storage_ptr sp =
|
||||
make_storage_ptr(
|
||||
std::allocator<void>{});
|
||||
return sp;
|
||||
}
|
||||
|
||||
} // detail
|
||||
|
||||
storage_ptr
|
||||
default_storage()
|
||||
{
|
||||
return detail::raw_default_storage();
|
||||
}
|
||||
|
||||
void
|
||||
default_storage(storage_ptr sp)
|
||||
{
|
||||
detail::raw_default_storage() = std::move(sp);
|
||||
}
|
||||
|
||||
|
||||
} // json
|
||||
} // beast
|
||||
} // boost
|
||||
|
||||
#endif
|
||||
574
include/boost/json/impl/value.hpp
Normal file
574
include/boost/json/impl/value.hpp
Normal file
@@ -0,0 +1,574 @@
|
||||
//
|
||||
// Copyright (c) 2018-2019 Vinnie Falco (vinnie dot falco at gmail dot com)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
// Official repository: https://github.com/boostorg/json
|
||||
//
|
||||
|
||||
#ifndef BOOST_JSON_IMPL_VALUE_HPP
|
||||
#define BOOST_JSON_IMPL_VALUE_HPP
|
||||
|
||||
#include <boost/json/error.hpp>
|
||||
#include <boost/throw_exception.hpp>
|
||||
#include <limits>
|
||||
#include <type_traits>
|
||||
|
||||
namespace boost {
|
||||
namespace beast {
|
||||
namespace json {
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
class value::pointer
|
||||
{
|
||||
reference t_;
|
||||
|
||||
public:
|
||||
pointer(reference t)
|
||||
: t_(t)
|
||||
{
|
||||
}
|
||||
|
||||
reference*
|
||||
operator->() noexcept
|
||||
{
|
||||
return &t_;
|
||||
}
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
class value::const_pointer
|
||||
{
|
||||
const_reference t_;
|
||||
|
||||
public:
|
||||
const_pointer(
|
||||
const_reference t)
|
||||
: t_(t)
|
||||
{
|
||||
}
|
||||
|
||||
const_reference*
|
||||
operator->() noexcept
|
||||
{
|
||||
return &t_;
|
||||
}
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
class value::iterator
|
||||
{
|
||||
union
|
||||
{
|
||||
array::iterator arr_it_;
|
||||
object::iterator obj_it_;
|
||||
};
|
||||
bool arr_;
|
||||
|
||||
friend class value;
|
||||
|
||||
public:
|
||||
using value_type = value::value_type;
|
||||
using pointer = value::pointer;
|
||||
using reference = value::reference;
|
||||
using difference_type = std::ptrdiff_t;
|
||||
using iterator_category =
|
||||
std::bidirectional_iterator_tag;
|
||||
|
||||
~iterator()
|
||||
{
|
||||
if(! arr_)
|
||||
obj_it_.~iterator();
|
||||
}
|
||||
|
||||
iterator() noexcept
|
||||
: arr_it_{}
|
||||
, arr_(true)
|
||||
{
|
||||
}
|
||||
|
||||
iterator(iterator const& other) noexcept
|
||||
: arr_(other.arr_)
|
||||
{
|
||||
if(arr_)
|
||||
arr_it_ = other.arr_it_;
|
||||
else
|
||||
::new(&obj_it_)
|
||||
object::iterator(other.obj_it_);
|
||||
}
|
||||
|
||||
iterator(object::iterator it)
|
||||
: obj_it_(it)
|
||||
, arr_(false)
|
||||
{
|
||||
}
|
||||
|
||||
iterator(array::iterator it)
|
||||
: arr_it_(it)
|
||||
, arr_(true)
|
||||
{
|
||||
}
|
||||
|
||||
iterator&
|
||||
operator=(iterator const& other) noexcept
|
||||
{
|
||||
if(! arr_)
|
||||
obj_it_.~iterator();
|
||||
arr_ = other.arr_;
|
||||
if(arr_)
|
||||
arr_it_ = other.arr_it_;
|
||||
else
|
||||
::new(&obj_it_)
|
||||
object::iterator(other.obj_it_);
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool
|
||||
operator==(
|
||||
iterator const& other) const noexcept
|
||||
{
|
||||
if(arr_ != other.arr_)
|
||||
return false;
|
||||
if(arr_)
|
||||
return arr_it_ == other.arr_it_;
|
||||
return obj_it_ == other.obj_it_;
|
||||
}
|
||||
|
||||
bool
|
||||
operator!=(
|
||||
iterator const& other) const noexcept
|
||||
{
|
||||
return ! (*this == other);
|
||||
}
|
||||
|
||||
bool
|
||||
operator==(
|
||||
const_iterator const& other) const noexcept;
|
||||
|
||||
bool
|
||||
operator!=(
|
||||
const_iterator const& other) const noexcept;
|
||||
|
||||
iterator&
|
||||
operator++() noexcept
|
||||
{
|
||||
if(arr_)
|
||||
++arr_it_;
|
||||
else
|
||||
++obj_it_;
|
||||
return *this;
|
||||
}
|
||||
|
||||
iterator
|
||||
operator++(int) noexcept
|
||||
{
|
||||
auto tmp = *this;
|
||||
++*this;
|
||||
return tmp;
|
||||
}
|
||||
|
||||
iterator&
|
||||
operator--() noexcept
|
||||
{
|
||||
if(arr_)
|
||||
--arr_it_;
|
||||
else
|
||||
--obj_it_;
|
||||
return *this;
|
||||
}
|
||||
|
||||
iterator
|
||||
operator--(int) noexcept
|
||||
{
|
||||
auto tmp = *this;
|
||||
--*this;
|
||||
return tmp;
|
||||
}
|
||||
|
||||
reference
|
||||
operator*() const noexcept
|
||||
{
|
||||
if(arr_)
|
||||
return reference{
|
||||
"", *arr_it_ };
|
||||
return reference{
|
||||
obj_it_->first,
|
||||
obj_it_->second };
|
||||
}
|
||||
|
||||
pointer
|
||||
operator->() const noexcept
|
||||
{
|
||||
return *(*this);
|
||||
}
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
class value::const_iterator
|
||||
{
|
||||
union
|
||||
{
|
||||
array::const_iterator arr_it_;
|
||||
object::const_iterator obj_it_;
|
||||
};
|
||||
bool arr_;
|
||||
|
||||
friend class value;
|
||||
|
||||
public:
|
||||
using value_type = value::value_type;
|
||||
using pointer = value::const_pointer;
|
||||
using reference = value::const_reference;
|
||||
using difference_type = std::ptrdiff_t;
|
||||
using iterator_category =
|
||||
std::bidirectional_iterator_tag;
|
||||
|
||||
~const_iterator()
|
||||
{
|
||||
if(! arr_)
|
||||
obj_it_.~const_iterator();
|
||||
}
|
||||
|
||||
const_iterator() noexcept
|
||||
: arr_it_{}
|
||||
, arr_(true)
|
||||
{
|
||||
}
|
||||
|
||||
const_iterator(
|
||||
const_iterator const& other) noexcept
|
||||
: arr_(other.arr_)
|
||||
{
|
||||
if(arr_)
|
||||
arr_it_ = other.arr_it_;
|
||||
else
|
||||
::new(&obj_it_)
|
||||
object::const_iterator(
|
||||
other.obj_it_);
|
||||
}
|
||||
|
||||
const_iterator(
|
||||
object::const_iterator it)
|
||||
: obj_it_(it)
|
||||
, arr_(false)
|
||||
{
|
||||
}
|
||||
|
||||
const_iterator(
|
||||
array::const_iterator it)
|
||||
: arr_it_(it)
|
||||
, arr_(true)
|
||||
{
|
||||
}
|
||||
|
||||
const_iterator&
|
||||
operator=(const_iterator const& other) noexcept
|
||||
{
|
||||
if(! arr_)
|
||||
obj_it_.~const_iterator();
|
||||
arr_ = other.arr_;
|
||||
if(arr_)
|
||||
arr_it_ = other.arr_it_;
|
||||
else
|
||||
::new(&obj_it_)
|
||||
object::const_iterator(
|
||||
other.obj_it_);
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool
|
||||
operator==(
|
||||
const_iterator const& other) const noexcept
|
||||
{
|
||||
if(arr_ != other.arr_)
|
||||
return false;
|
||||
if(arr_)
|
||||
return arr_it_ == other.arr_it_;
|
||||
return obj_it_ == other.obj_it_;
|
||||
}
|
||||
|
||||
bool
|
||||
operator!=(
|
||||
const_iterator const& other) const noexcept
|
||||
{
|
||||
return ! (*this == other);
|
||||
}
|
||||
|
||||
bool
|
||||
operator==(
|
||||
iterator const& other) const noexcept;
|
||||
|
||||
bool
|
||||
operator!=(
|
||||
iterator const& other) const noexcept;
|
||||
|
||||
const_iterator&
|
||||
operator++() noexcept
|
||||
{
|
||||
if(arr_)
|
||||
++arr_it_;
|
||||
else
|
||||
++obj_it_;
|
||||
return *this;
|
||||
}
|
||||
|
||||
const_iterator
|
||||
operator++(int) noexcept
|
||||
{
|
||||
auto tmp = *this;
|
||||
++*this;
|
||||
return tmp;
|
||||
}
|
||||
|
||||
const_iterator&
|
||||
operator--() noexcept
|
||||
{
|
||||
if(arr_)
|
||||
--arr_it_;
|
||||
else
|
||||
--obj_it_;
|
||||
return *this;
|
||||
}
|
||||
|
||||
const_iterator
|
||||
operator--(int) noexcept
|
||||
{
|
||||
auto tmp = *this;
|
||||
--*this;
|
||||
return tmp;
|
||||
}
|
||||
|
||||
reference
|
||||
operator*() const noexcept
|
||||
{
|
||||
if(arr_)
|
||||
return reference{
|
||||
"", *arr_it_ };
|
||||
return reference{
|
||||
obj_it_->first,
|
||||
obj_it_->second };
|
||||
}
|
||||
|
||||
pointer
|
||||
operator->() const noexcept
|
||||
{
|
||||
return *(*this);
|
||||
}
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
template<class M>
|
||||
auto
|
||||
value::
|
||||
insert_or_assign(
|
||||
key_type key, M&& obj) ->
|
||||
std::pair<iterator, bool>
|
||||
{
|
||||
BOOST_ASSERT(is_object());
|
||||
return obj_.insert_or_assign(
|
||||
key, std::forward<M>(obj));
|
||||
}
|
||||
|
||||
template<class M>
|
||||
auto
|
||||
value::
|
||||
insert_or_assign(
|
||||
const_iterator before,
|
||||
key_type key,
|
||||
M&& obj) ->
|
||||
std::pair<iterator, bool>
|
||||
{
|
||||
BOOST_ASSERT(is_object());
|
||||
BOOST_ASSERT(! before.arr_);
|
||||
return obj_.insert_or_assign(
|
||||
before.obj_it_, key,
|
||||
std::forward<M>(obj));
|
||||
}
|
||||
|
||||
template<class Arg>
|
||||
auto
|
||||
value::
|
||||
emplace(key_type key, Arg&& arg) ->
|
||||
std::pair<iterator, bool>
|
||||
{
|
||||
BOOST_ASSERT(is_object());
|
||||
return obj_.emplace(key,
|
||||
std::forward<Arg>(arg));
|
||||
}
|
||||
|
||||
template<class Arg>
|
||||
auto
|
||||
value::
|
||||
emplace(
|
||||
const_iterator before,
|
||||
key_type key, Arg&& arg) ->
|
||||
std::pair<iterator, bool>
|
||||
{
|
||||
BOOST_ASSERT(is_object());
|
||||
BOOST_ASSERT(! before.arr_);
|
||||
return obj_.emplace(
|
||||
key, before.obj_it_,
|
||||
std::forward<Arg>(arg));
|
||||
}
|
||||
|
||||
template<class Arg>
|
||||
auto
|
||||
value::
|
||||
emplace(
|
||||
const_iterator before,
|
||||
Arg&& arg) ->
|
||||
iterator
|
||||
{
|
||||
BOOST_ASSERT(is_array());
|
||||
BOOST_ASSERT(before.arr_);
|
||||
return arr_.emplace(before.arr_it_,
|
||||
std::forward<Arg>(arg));
|
||||
}
|
||||
|
||||
template<class Arg>
|
||||
value&
|
||||
value::
|
||||
emplace_back(Arg&& arg)
|
||||
{
|
||||
BOOST_ASSERT(is_array());
|
||||
return *arr_.emplace(arr_.end(),
|
||||
std::forward<Arg>(arg));
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
namespace detail {
|
||||
|
||||
template<class T, class = void>
|
||||
struct is_range : std::false_type
|
||||
{
|
||||
};
|
||||
|
||||
template<class T>
|
||||
struct is_range<T, boost::void_t<
|
||||
typename T::value_type,
|
||||
decltype(
|
||||
std::declval<T const&>().begin(),
|
||||
std::declval<T const&>().end()
|
||||
)>> : std::true_type
|
||||
{
|
||||
};
|
||||
|
||||
} // detail
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
//
|
||||
// assign to value
|
||||
//
|
||||
|
||||
// range
|
||||
template<class T
|
||||
,class = typename std::enable_if<
|
||||
detail::is_range<T>::value
|
||||
&& ! std::is_same<typename T::value_type, char>::value
|
||||
&& has_to_json<typename T::value_type>::value
|
||||
>::type
|
||||
>
|
||||
void
|
||||
to_json(T const& t, value& v)
|
||||
{
|
||||
v.reset(json::kind::array);
|
||||
for(auto const& e : t)
|
||||
v.as_array().push_back(e);
|
||||
}
|
||||
|
||||
// string
|
||||
inline
|
||||
void
|
||||
to_json(string_view t, value& v)
|
||||
{
|
||||
v.emplace_string().assign(
|
||||
t.data(), t.size());
|
||||
}
|
||||
|
||||
// string
|
||||
inline
|
||||
void
|
||||
to_json(char const* t, value& v)
|
||||
{
|
||||
v.emplace_string() = t;
|
||||
}
|
||||
|
||||
// number
|
||||
template<class T
|
||||
,class = typename std::enable_if<
|
||||
std::is_constructible<number, T>::value &&
|
||||
! std::is_same<number, T>::value>::type
|
||||
>
|
||||
inline
|
||||
void
|
||||
to_json(T t, value& v)
|
||||
{
|
||||
v.emplace_number() = t;
|
||||
}
|
||||
|
||||
// bool
|
||||
inline
|
||||
void
|
||||
to_json(bool b, value& v)
|
||||
{
|
||||
v.emplace_bool() = b;
|
||||
}
|
||||
|
||||
// null
|
||||
inline
|
||||
void
|
||||
to_json(std::nullptr_t, value& v)
|
||||
{
|
||||
v.emplace_null();
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
//
|
||||
// assign value to
|
||||
//
|
||||
|
||||
// integer
|
||||
|
||||
template<typename T
|
||||
,class = typename std::enable_if<
|
||||
std::is_integral<T>::value>::type
|
||||
>
|
||||
void
|
||||
from_json(T& t, value const& v)
|
||||
{
|
||||
if(v.is_int64())
|
||||
{
|
||||
auto const rhs = v.get_int64();
|
||||
if( rhs > (std::numeric_limits<T>::max)() ||
|
||||
rhs < (std::numeric_limits<T>::min)())
|
||||
throw system_error(
|
||||
error::integer_overflow);
|
||||
t = static_cast<T>(rhs);
|
||||
}
|
||||
else if(v.is_uint64())
|
||||
{
|
||||
auto const rhs = v.get_uint64();
|
||||
if(rhs > (std::numeric_limits<T>::max)())
|
||||
throw system_error(
|
||||
error::integer_overflow);
|
||||
t = static_cast<T>(rhs);
|
||||
}
|
||||
else
|
||||
{
|
||||
throw system_error(
|
||||
error::expected_number);
|
||||
}
|
||||
}
|
||||
|
||||
} // json
|
||||
} // beast
|
||||
} // boost
|
||||
|
||||
#endif
|
||||
1149
include/boost/json/impl/value.ipp
Normal file
1149
include/boost/json/impl/value.ipp
Normal file
File diff suppressed because it is too large
Load Diff
149
include/boost/json/iterator.hpp
Normal file
149
include/boost/json/iterator.hpp
Normal file
@@ -0,0 +1,149 @@
|
||||
//
|
||||
// Copyright (c) 2018-2019 Vinnie Falco (vinnie dot falco at gmail dot com)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
// Official repository: https://github.com/boostorg/json
|
||||
//
|
||||
|
||||
#ifndef BOOST_JSON_ITERATOR_HPP
|
||||
#define BOOST_JSON_ITERATOR_HPP
|
||||
|
||||
#include <boost/beast/core/detail/config.hpp>
|
||||
#include <boost/beast/core/detail/static_const.hpp>
|
||||
#include <boost/json/value.hpp>
|
||||
#include <boost/json/detail/stack.hpp>
|
||||
#include <iterator>
|
||||
#include <new>
|
||||
|
||||
namespace boost {
|
||||
namespace beast {
|
||||
namespace json {
|
||||
|
||||
struct end_t
|
||||
{
|
||||
};
|
||||
|
||||
BOOST_BEAST_INLINE_VARIABLE(end, end_t)
|
||||
|
||||
/** A generator to perform a depth-first traversal of a JSON value.
|
||||
*/
|
||||
class const_iterator
|
||||
{
|
||||
struct node
|
||||
{
|
||||
union
|
||||
{
|
||||
array::const_iterator arr_it;
|
||||
object::const_iterator obj_it;
|
||||
};
|
||||
value const* v;
|
||||
string_view key;
|
||||
bool it;
|
||||
|
||||
BOOST_BEAST_DECL
|
||||
~node();
|
||||
|
||||
BOOST_BEAST_DECL
|
||||
node(
|
||||
value const& v_,
|
||||
bool it_) noexcept;
|
||||
|
||||
BOOST_BEAST_DECL
|
||||
node(node const& other) noexcept;
|
||||
|
||||
BOOST_BEAST_DECL
|
||||
bool
|
||||
last() const noexcept;
|
||||
};
|
||||
|
||||
detail::stack<node, 50> stack_;
|
||||
|
||||
public:
|
||||
struct value_type
|
||||
{
|
||||
std::size_t depth;
|
||||
string_view key;
|
||||
json::value const& value;
|
||||
bool last;
|
||||
bool end;
|
||||
|
||||
value_type const*
|
||||
operator->() const noexcept
|
||||
{
|
||||
return this;
|
||||
}
|
||||
};
|
||||
|
||||
BOOST_BEAST_DECL
|
||||
explicit
|
||||
const_iterator(
|
||||
value const& jv);
|
||||
|
||||
BOOST_BEAST_DECL
|
||||
value_type
|
||||
operator*() const noexcept;
|
||||
|
||||
BOOST_BEAST_DECL
|
||||
const_iterator&
|
||||
operator++() noexcept;
|
||||
|
||||
void
|
||||
operator++(int) noexcept
|
||||
{
|
||||
++*this;
|
||||
}
|
||||
|
||||
value_type
|
||||
operator->() const noexcept
|
||||
{
|
||||
return *(*this);
|
||||
}
|
||||
|
||||
friend
|
||||
bool
|
||||
operator==(
|
||||
const_iterator const& lhs,
|
||||
end_t) noexcept
|
||||
{
|
||||
return lhs.stack_.empty();
|
||||
}
|
||||
|
||||
friend
|
||||
bool
|
||||
operator==(
|
||||
end_t,
|
||||
const_iterator const& rhs) noexcept
|
||||
{
|
||||
return rhs.stack_.empty();
|
||||
}
|
||||
|
||||
friend
|
||||
bool
|
||||
operator!=(
|
||||
const_iterator const& lhs,
|
||||
end_t) noexcept
|
||||
{
|
||||
return ! lhs.stack_.empty();
|
||||
}
|
||||
|
||||
friend
|
||||
bool
|
||||
operator!=(
|
||||
end_t,
|
||||
const_iterator const& rhs) noexcept
|
||||
{
|
||||
return ! rhs.stack_.empty();
|
||||
}
|
||||
};
|
||||
|
||||
} // json
|
||||
} // beast
|
||||
} // boost
|
||||
|
||||
#if BOOST_BEAST_HEADER_ONLY
|
||||
#include <boost/json/impl/iterator.ipp>
|
||||
#endif
|
||||
|
||||
#endif
|
||||
38
include/boost/json/json.natvis
Normal file
38
include/boost/json/json.natvis
Normal file
@@ -0,0 +1,38 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<AutoVisualizer xmlns="http://schemas.microsoft.com/vstudio/debugger/natvis/2010">
|
||||
<Type Name="boost::beast::json::value">
|
||||
<DisplayString Condition="kind_==kind::object">object{obj_}</DisplayString>
|
||||
<DisplayString Condition="kind_==kind::array">array{arr_}</DisplayString>
|
||||
<DisplayString Condition="kind_==kind::string">string{str_}</DisplayString>
|
||||
<DisplayString Condition="kind_==kind::number">{nat_.num_}</DisplayString>
|
||||
<DisplayString Condition="kind_==kind::boolean">{nat_.bool_}</DisplayString>
|
||||
<DisplayString Condition="kind_==kind::null">null</DisplayString>
|
||||
<Expand>
|
||||
<ExpandedItem Condition="kind_==kind::object">obj_</ExpandedItem>
|
||||
<ExpandedItem Condition="kind_==kind::array">arr_</ExpandedItem>
|
||||
<ExpandedItem Condition="kind_==kind::string">str_</ExpandedItem>
|
||||
<Item Name="storage" Condition="kind_==kind::number||kind_==kind::boolean||kind_==kind::null">nat_.sp_</Item>
|
||||
<ExpandedItem Condition="kind_==kind::number">nat_.num_</ExpandedItem>
|
||||
<ExpandedItem Condition="kind_==kind::boolean">nat_.bool_</ExpandedItem>
|
||||
</Expand>
|
||||
</Type>
|
||||
<!--
|
||||
<Type Name="boost::beast::json::storage_ptr">
|
||||
<DisplayString>storage</DisplayString>
|
||||
<Expand>
|
||||
<ExpandedItem>p_</ExpandedItem>
|
||||
</Expand>
|
||||
</Type>
|
||||
<Type Name="boost::beast::json::allocator<*>">
|
||||
<DisplayString>allocator</DisplayString>
|
||||
<Expand>
|
||||
<ExpandedItem>sp_</ExpandedItem>
|
||||
</Expand>
|
||||
</Type>
|
||||
-->
|
||||
<Type Name="std::pair<const std::string, boost::beast::json::value>">
|
||||
<Expand>
|
||||
<ExpandedItem>second</ExpandedItem>
|
||||
</Expand>
|
||||
</Type>
|
||||
</AutoVisualizer>
|
||||
37
include/boost/json/kind.hpp
Normal file
37
include/boost/json/kind.hpp
Normal file
@@ -0,0 +1,37 @@
|
||||
//
|
||||
// Copyright (c) 2018-2019 Vinnie Falco (vinnie dot falco at gmail dot com)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
// Official repository: https://github.com/boostorg/json
|
||||
//
|
||||
|
||||
#ifndef BOOST_JSON_KIND_HPP
|
||||
#define BOOST_JSON_KIND_HPP
|
||||
|
||||
#include <boost/beast/core/detail/config.hpp>
|
||||
#include <boost/beast/core/detail/static_const.hpp>
|
||||
#include <cstddef>
|
||||
|
||||
namespace boost {
|
||||
namespace beast {
|
||||
namespace json {
|
||||
|
||||
enum class kind
|
||||
{
|
||||
object,
|
||||
array,
|
||||
string,
|
||||
number,
|
||||
boolean,
|
||||
null
|
||||
};
|
||||
|
||||
BOOST_BEAST_INLINE_VARIABLE(null, std::nullptr_t)
|
||||
|
||||
} // json
|
||||
} // beast
|
||||
} // boost
|
||||
|
||||
#endif
|
||||
237
include/boost/json/number.hpp
Normal file
237
include/boost/json/number.hpp
Normal file
@@ -0,0 +1,237 @@
|
||||
//
|
||||
// Copyright (c) 2018-2019 Vinnie Falco (vinnie dot falco at gmail dot com)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
// Official repository: https://github.com/boostorg/json
|
||||
//
|
||||
|
||||
#ifndef BOOST_JSON_NUMBER_HPP
|
||||
#define BOOST_JSON_NUMBER_HPP
|
||||
|
||||
#include <boost/beast/core/detail/config.hpp>
|
||||
#include <boost/beast/core/string.hpp>
|
||||
#include <cstdint>
|
||||
#include <iosfwd>
|
||||
#include <type_traits>
|
||||
|
||||
namespace boost {
|
||||
namespace beast {
|
||||
namespace json {
|
||||
|
||||
/** The representation of parsed numbers.
|
||||
*/
|
||||
class number
|
||||
{
|
||||
struct base10_ieee
|
||||
{
|
||||
unsigned
|
||||
long long mant;
|
||||
short exp;
|
||||
bool sign;
|
||||
};
|
||||
|
||||
enum kind
|
||||
{
|
||||
type_int64,
|
||||
type_uint64,
|
||||
type_double,
|
||||
type_ieee
|
||||
};
|
||||
|
||||
union
|
||||
{
|
||||
unsigned
|
||||
long long uint64_;
|
||||
long long int64_;
|
||||
double double_;
|
||||
base10_ieee ieee_;
|
||||
};
|
||||
|
||||
kind k_;
|
||||
|
||||
public:
|
||||
static std::size_t constexpr
|
||||
max_string_chars =
|
||||
1 + // '-'
|
||||
19 + // unsigned 64-bit mantissa
|
||||
1 + // 'e'
|
||||
1 + // '-'
|
||||
5; // unsigned 16-bit exponent
|
||||
|
||||
using mantissa_type =
|
||||
unsigned long long;
|
||||
|
||||
using exponent_type =
|
||||
short;
|
||||
|
||||
number() = default;
|
||||
number(number const&) = default;
|
||||
number& operator=(
|
||||
number const&) = default;
|
||||
|
||||
/** Construct a number from mantissa, exponent, and sign
|
||||
*/
|
||||
BOOST_BEAST_DECL
|
||||
number(
|
||||
mantissa_type mant,
|
||||
exponent_type exp,
|
||||
bool sign) noexcept;
|
||||
|
||||
/// Construct a number from a signed integer
|
||||
BOOST_BEAST_DECL
|
||||
number(short v) noexcept;
|
||||
|
||||
/// Construct a number from a signed integer
|
||||
BOOST_BEAST_DECL
|
||||
number(int v) noexcept;
|
||||
|
||||
/// Construct a number from a signed integer
|
||||
BOOST_BEAST_DECL
|
||||
number(long v) noexcept;
|
||||
|
||||
/// Construct a number from a signed integer
|
||||
BOOST_BEAST_DECL
|
||||
number(long long v) noexcept;
|
||||
|
||||
/// Construct a number from an unsigned integer
|
||||
BOOST_BEAST_DECL
|
||||
number(unsigned short v) noexcept;
|
||||
|
||||
/// Construct a number from an unsigned integer
|
||||
BOOST_BEAST_DECL
|
||||
number(unsigned int v) noexcept;
|
||||
|
||||
/// Construct a number from an unsigned integer
|
||||
BOOST_BEAST_DECL
|
||||
number(unsigned long v) noexcept;
|
||||
|
||||
/// Construct a number from an unsigned integer
|
||||
BOOST_BEAST_DECL
|
||||
number(unsigned long long v) noexcept;
|
||||
|
||||
/// Construct a number from a floating point value
|
||||
BOOST_BEAST_DECL
|
||||
number(float v) noexcept;
|
||||
|
||||
/// Construct a number from a floating point value
|
||||
BOOST_BEAST_DECL
|
||||
number(double v) noexcept;
|
||||
|
||||
/// Return true if the number is negative
|
||||
BOOST_BEAST_DECL
|
||||
bool
|
||||
is_negative() const noexcept;
|
||||
|
||||
/// Return true if the number is integral
|
||||
BOOST_BEAST_DECL
|
||||
bool
|
||||
is_integral() const noexcept;
|
||||
|
||||
/// Return true if the number can be represented with a signed 64-bit integer
|
||||
BOOST_BEAST_DECL
|
||||
bool
|
||||
is_int64() const noexcept;
|
||||
|
||||
/// Return true if the number can be represented with an unsigned 64-bit integer
|
||||
BOOST_BEAST_DECL
|
||||
bool
|
||||
is_uint64() const noexcept;
|
||||
|
||||
/** Return the number as a signed 64-bit integer
|
||||
|
||||
The return value is undefined unless @ref is_int64 returns `true`.
|
||||
*/
|
||||
BOOST_BEAST_DECL
|
||||
std::int_least64_t
|
||||
get_int64() const noexcept;
|
||||
|
||||
/** Return the number as an unsigned 64-bit integer
|
||||
|
||||
The return value is undefined unless @ref is_uint64 returns `true`.
|
||||
*/
|
||||
BOOST_BEAST_DECL
|
||||
std::uint_least64_t
|
||||
get_uint64() const noexcept;
|
||||
|
||||
/** Return the number as floating point
|
||||
*/
|
||||
BOOST_BEAST_DECL
|
||||
double
|
||||
get_double() const noexcept;
|
||||
|
||||
/** Convert the number to a string.
|
||||
|
||||
The destination must contain at least
|
||||
@ref max_string_chars bytes of valid storage.
|
||||
|
||||
@return A string view representing the number as
|
||||
as string. Storage for the view comes from `dest`.
|
||||
*/
|
||||
BOOST_BEAST_DECL
|
||||
string_view
|
||||
print(
|
||||
char* buf,
|
||||
std::size_t buf_size) const noexcept;
|
||||
|
||||
private:
|
||||
struct pow10;
|
||||
|
||||
BOOST_BEAST_DECL
|
||||
void
|
||||
assign_signed(
|
||||
long long i) noexcept;
|
||||
|
||||
BOOST_BEAST_DECL
|
||||
void
|
||||
assign_unsigned(
|
||||
unsigned long long i) noexcept;
|
||||
|
||||
BOOST_BEAST_DECL
|
||||
void
|
||||
assign_double(double f) noexcept;
|
||||
|
||||
friend
|
||||
std::ostream&
|
||||
operator<<(std::ostream& os, number const& n);
|
||||
|
||||
friend
|
||||
bool
|
||||
operator==(
|
||||
number const& lhs,
|
||||
number const& rhs) noexcept;
|
||||
|
||||
friend
|
||||
bool
|
||||
operator!=(
|
||||
number const& lhs,
|
||||
number const& rhs) noexcept;
|
||||
|
||||
};
|
||||
|
||||
BOOST_BEAST_DECL
|
||||
bool
|
||||
operator==(
|
||||
number const& lhs,
|
||||
number const& rhs) noexcept;
|
||||
|
||||
BOOST_BEAST_DECL
|
||||
bool
|
||||
operator!=(
|
||||
number const& lhs,
|
||||
number const& rhs) noexcept;
|
||||
|
||||
BOOST_BEAST_DECL
|
||||
std::ostream&
|
||||
operator<<(std::ostream& os, number const& n);
|
||||
|
||||
} // json
|
||||
} // beast
|
||||
} // boost
|
||||
|
||||
#ifdef BOOST_BEAST_HEADER_ONLY
|
||||
#include <boost/json/impl/number.ipp>
|
||||
#endif
|
||||
|
||||
#endif
|
||||
560
include/boost/json/object.hpp
Normal file
560
include/boost/json/object.hpp
Normal file
@@ -0,0 +1,560 @@
|
||||
//
|
||||
// Copyright (c) 2018-2019 Vinnie Falco (vinnie dot falco at gmail dot com)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
// Official repository: https://github.com/boostorg/json
|
||||
//
|
||||
|
||||
#ifndef BOOST_JSON_OBJECT_HPP
|
||||
#define BOOST_JSON_OBJECT_HPP
|
||||
|
||||
#include <boost/beast/core/detail/config.hpp>
|
||||
#include <boost/beast/core/string.hpp>
|
||||
#include <boost/json/storage.hpp>
|
||||
#include <cstdlib>
|
||||
#include <initializer_list>
|
||||
#include <iterator>
|
||||
#include <utility>
|
||||
|
||||
namespace boost {
|
||||
namespace beast {
|
||||
namespace json {
|
||||
|
||||
class value;
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
/** The native type of object values
|
||||
|
||||
This copies the interface of `std::unordered_map` with
|
||||
one important distinction: the order of insertions is
|
||||
preserved.
|
||||
*/
|
||||
class object
|
||||
{
|
||||
struct list_hook;
|
||||
struct element;
|
||||
class table;
|
||||
|
||||
storage_ptr sp_;
|
||||
table* tab_ = nullptr;
|
||||
float mf_ = 1.0;
|
||||
|
||||
public:
|
||||
using key_type = beast::string_view;
|
||||
using mapped_type = value;
|
||||
using value_type = std::pair<key_type, value>;
|
||||
using size_type = std::size_t;
|
||||
using difference_type = std::ptrdiff_t;
|
||||
using reference = std::pair<key_type, value&>;
|
||||
using const_reference = std::pair<key_type, value const&>;
|
||||
|
||||
class hasher;
|
||||
class key_equal;
|
||||
class pointer;
|
||||
class const_pointer;
|
||||
class iterator;
|
||||
class const_iterator;
|
||||
class local_iterator;
|
||||
class const_local_iterator;
|
||||
class node_type;
|
||||
struct insert_return_type;
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
//
|
||||
// Special Members
|
||||
//
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
BOOST_BEAST_DECL
|
||||
~object();
|
||||
|
||||
BOOST_BEAST_DECL
|
||||
object();
|
||||
|
||||
BOOST_BEAST_DECL
|
||||
object(
|
||||
size_type capacity);
|
||||
|
||||
BOOST_BEAST_DECL
|
||||
object(
|
||||
storage_ptr store);
|
||||
|
||||
BOOST_BEAST_DECL
|
||||
object(
|
||||
size_type capacity,
|
||||
storage_ptr store);
|
||||
|
||||
template<class InputIt>
|
||||
BOOST_BEAST_DECL
|
||||
object(
|
||||
InputIt first,
|
||||
InputIt last);
|
||||
|
||||
template<class InputIt>
|
||||
BOOST_BEAST_DECL
|
||||
object(
|
||||
InputIt first,
|
||||
InputIt last,
|
||||
size_type capacity);
|
||||
|
||||
template<class InputIt>
|
||||
BOOST_BEAST_DECL
|
||||
object(
|
||||
InputIt first,
|
||||
InputIt last,
|
||||
storage_ptr store);
|
||||
|
||||
template<class InputIt>
|
||||
BOOST_BEAST_DECL
|
||||
object(
|
||||
InputIt first,
|
||||
InputIt last,
|
||||
size_type capacity,
|
||||
storage_ptr store);
|
||||
|
||||
BOOST_BEAST_DECL
|
||||
object(object&& other) noexcept;
|
||||
|
||||
BOOST_BEAST_DECL
|
||||
object(
|
||||
object&& other,
|
||||
storage_ptr store) noexcept;
|
||||
|
||||
BOOST_BEAST_DECL
|
||||
object(
|
||||
object const& other);
|
||||
|
||||
BOOST_BEAST_DECL
|
||||
object(
|
||||
object const& other,
|
||||
storage_ptr store);
|
||||
|
||||
BOOST_BEAST_DECL
|
||||
object(
|
||||
std::initializer_list<value_type> list);
|
||||
|
||||
BOOST_BEAST_DECL
|
||||
object(
|
||||
std::initializer_list<value_type> list,
|
||||
size_type capacity);
|
||||
|
||||
BOOST_BEAST_DECL
|
||||
object(
|
||||
std::initializer_list<value_type> list,
|
||||
storage_ptr store);
|
||||
|
||||
BOOST_BEAST_DECL
|
||||
object(
|
||||
std::initializer_list<value_type> list,
|
||||
size_type capacity,
|
||||
storage_ptr store);
|
||||
|
||||
BOOST_BEAST_DECL
|
||||
object&
|
||||
operator=(object&& other);
|
||||
|
||||
BOOST_BEAST_DECL
|
||||
object&
|
||||
operator=(object const& other);
|
||||
|
||||
BOOST_BEAST_DECL
|
||||
object&
|
||||
operator=(
|
||||
std::initializer_list<value_type> list);
|
||||
|
||||
BOOST_BEAST_DECL
|
||||
storage_ptr const&
|
||||
get_storage() const noexcept;
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
//
|
||||
// Iterators
|
||||
//
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
BOOST_BEAST_DECL
|
||||
iterator
|
||||
begin() noexcept;
|
||||
|
||||
BOOST_BEAST_DECL
|
||||
const_iterator
|
||||
begin() const noexcept;
|
||||
|
||||
BOOST_BEAST_DECL
|
||||
const_iterator
|
||||
cbegin() const noexcept;
|
||||
|
||||
BOOST_BEAST_DECL
|
||||
iterator
|
||||
end() noexcept;
|
||||
|
||||
BOOST_BEAST_DECL
|
||||
const_iterator
|
||||
end() const noexcept;
|
||||
|
||||
BOOST_BEAST_DECL
|
||||
const_iterator
|
||||
cend() const noexcept;
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
//
|
||||
// Capacity
|
||||
//
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
BOOST_BEAST_DECL
|
||||
bool
|
||||
empty() const noexcept;
|
||||
|
||||
BOOST_BEAST_DECL
|
||||
size_type
|
||||
size() const noexcept;
|
||||
|
||||
BOOST_BEAST_DECL
|
||||
size_type
|
||||
max_size() const noexcept;
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
//
|
||||
// Modifiers
|
||||
//
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
BOOST_BEAST_DECL
|
||||
void
|
||||
clear() noexcept;
|
||||
|
||||
template<class P = value_type
|
||||
#ifndef BOOST_BEAST_DOXYGEN
|
||||
,class = typename std::enable_if<
|
||||
std::is_constructible<value_type,
|
||||
P&&>::value>::type
|
||||
#endif
|
||||
>
|
||||
std::pair<iterator, bool>
|
||||
insert(P&& p);
|
||||
|
||||
template<class P = value_type
|
||||
#ifndef BOOST_BEAST_DOXYGEN
|
||||
,class = typename std::enable_if<
|
||||
std::is_constructible<value_type,
|
||||
P&&>::value>::type
|
||||
#endif
|
||||
>
|
||||
std::pair<iterator, bool>
|
||||
insert(
|
||||
const_iterator before,
|
||||
P&& p);
|
||||
|
||||
template<class InputIt>
|
||||
void
|
||||
insert(InputIt first, InputIt last);
|
||||
|
||||
BOOST_BEAST_DECL
|
||||
void
|
||||
insert(std::initializer_list<
|
||||
value_type> list);
|
||||
|
||||
BOOST_BEAST_DECL
|
||||
insert_return_type
|
||||
insert(node_type&& nh);
|
||||
|
||||
BOOST_BEAST_DECL
|
||||
insert_return_type
|
||||
insert(
|
||||
const_iterator before,
|
||||
node_type&& nh);
|
||||
|
||||
template<class M>
|
||||
std::pair<iterator, bool>
|
||||
insert_or_assign(
|
||||
key_type key, M&& obj);
|
||||
|
||||
template<class M>
|
||||
std::pair<iterator, bool>
|
||||
insert_or_assign(
|
||||
const_iterator before,
|
||||
key_type key,
|
||||
M&& obj);
|
||||
|
||||
template<class Arg>
|
||||
std::pair<iterator, bool>
|
||||
emplace(key_type key, Arg&& arg);
|
||||
|
||||
template<class Arg>
|
||||
std::pair<iterator, bool>
|
||||
emplace(
|
||||
const_iterator before,
|
||||
key_type key, Arg&& arg);
|
||||
|
||||
BOOST_BEAST_DECL
|
||||
iterator
|
||||
erase(const_iterator pos);
|
||||
|
||||
BOOST_BEAST_DECL
|
||||
iterator
|
||||
erase(
|
||||
const_iterator first,
|
||||
const_iterator last);
|
||||
|
||||
BOOST_BEAST_DECL
|
||||
size_type
|
||||
erase(key_type key);
|
||||
|
||||
BOOST_BEAST_DECL
|
||||
void
|
||||
swap(object& other) noexcept;
|
||||
|
||||
BOOST_BEAST_DECL
|
||||
node_type
|
||||
extract(const_iterator pos);
|
||||
|
||||
BOOST_BEAST_DECL
|
||||
node_type
|
||||
extract(key_type key);
|
||||
|
||||
BOOST_BEAST_DECL
|
||||
void
|
||||
merge(object& source);
|
||||
|
||||
BOOST_BEAST_DECL
|
||||
void
|
||||
merge(object&& source);
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
//
|
||||
// Lookup
|
||||
//
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
BOOST_BEAST_DECL
|
||||
value&
|
||||
at(key_type key);
|
||||
|
||||
BOOST_BEAST_DECL
|
||||
value const&
|
||||
at(key_type key) const;
|
||||
|
||||
BOOST_BEAST_DECL
|
||||
value&
|
||||
operator[](key_type key);
|
||||
|
||||
BOOST_BEAST_DECL
|
||||
value const&
|
||||
operator[](key_type key) const;
|
||||
|
||||
BOOST_BEAST_DECL
|
||||
size_type
|
||||
count(key_type key) const;
|
||||
|
||||
BOOST_BEAST_DECL
|
||||
size_type
|
||||
count(
|
||||
key_type key,
|
||||
std::size_t hash) const;
|
||||
|
||||
BOOST_BEAST_DECL
|
||||
iterator
|
||||
find(key_type key);
|
||||
|
||||
BOOST_BEAST_DECL
|
||||
iterator
|
||||
find(
|
||||
key_type key,
|
||||
std::size_t hash);
|
||||
|
||||
BOOST_BEAST_DECL
|
||||
const_iterator
|
||||
find(key_type key) const;
|
||||
|
||||
BOOST_BEAST_DECL
|
||||
const_iterator
|
||||
find(
|
||||
key_type key,
|
||||
std::size_t hash) const;
|
||||
|
||||
BOOST_BEAST_DECL
|
||||
bool
|
||||
contains(key_type key) const;
|
||||
|
||||
BOOST_BEAST_DECL
|
||||
bool
|
||||
contains(
|
||||
key_type key,
|
||||
std::size_t hash ) const;
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
//
|
||||
// Bucket Interface
|
||||
//
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
BOOST_BEAST_DECL
|
||||
local_iterator
|
||||
begin(size_type n) noexcept;
|
||||
|
||||
BOOST_BEAST_DECL
|
||||
const_local_iterator
|
||||
begin(size_type n) const noexcept;
|
||||
|
||||
BOOST_BEAST_DECL
|
||||
const_local_iterator
|
||||
cbegin(size_type n) noexcept;
|
||||
|
||||
BOOST_BEAST_DECL
|
||||
local_iterator
|
||||
end(size_type n) noexcept;
|
||||
|
||||
BOOST_BEAST_DECL
|
||||
const_local_iterator
|
||||
end(size_type n) const noexcept;
|
||||
|
||||
BOOST_BEAST_DECL
|
||||
const_local_iterator
|
||||
cend(size_type n) noexcept;
|
||||
|
||||
BOOST_BEAST_DECL
|
||||
size_type
|
||||
bucket_count() const noexcept;
|
||||
|
||||
BOOST_BEAST_DECL
|
||||
size_type
|
||||
max_bucket_count() const noexcept;
|
||||
|
||||
BOOST_BEAST_DECL
|
||||
size_type
|
||||
bucket_size(size_type n) const noexcept;
|
||||
|
||||
BOOST_BEAST_DECL
|
||||
size_type
|
||||
bucket(key_type key) const noexcept;
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
//
|
||||
// Hash Policy
|
||||
//
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
BOOST_BEAST_DECL
|
||||
float
|
||||
load_factor() const noexcept;
|
||||
|
||||
BOOST_BEAST_DECL
|
||||
float
|
||||
max_load_factor() const;
|
||||
|
||||
BOOST_BEAST_DECL
|
||||
void
|
||||
max_load_factor(float ml);
|
||||
|
||||
BOOST_BEAST_DECL
|
||||
void
|
||||
rehash(size_type count);
|
||||
|
||||
BOOST_BEAST_DECL
|
||||
void
|
||||
reserve(size_type count);
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
//
|
||||
// Observers
|
||||
//
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
BOOST_BEAST_DECL
|
||||
hasher
|
||||
hash_function() const;
|
||||
|
||||
BOOST_BEAST_DECL
|
||||
key_equal
|
||||
key_eq() const;
|
||||
|
||||
private:
|
||||
struct cleanup_replace;
|
||||
|
||||
template<class It>
|
||||
using iter_cat = typename
|
||||
std::iterator_traits<It>::iterator_category;
|
||||
|
||||
template<class InputIt>
|
||||
void
|
||||
construct(
|
||||
InputIt first,
|
||||
InputIt last,
|
||||
size_type capacity,
|
||||
std::forward_iterator_tag);
|
||||
|
||||
template<class InputIt>
|
||||
void
|
||||
construct(
|
||||
InputIt first,
|
||||
InputIt last,
|
||||
size_type capacity,
|
||||
std::input_iterator_tag);
|
||||
|
||||
template<class InputIt>
|
||||
void
|
||||
insert(
|
||||
InputIt first,
|
||||
InputIt last,
|
||||
std::forward_iterator_tag);
|
||||
|
||||
template<class InputIt>
|
||||
void
|
||||
insert(
|
||||
InputIt first,
|
||||
InputIt last,
|
||||
std::input_iterator_tag);
|
||||
|
||||
template<class Arg>
|
||||
std::pair<iterator, bool>
|
||||
emplace_impl(
|
||||
const_iterator before,
|
||||
key_type key,
|
||||
Arg&& arg);
|
||||
|
||||
BOOST_BEAST_DECL
|
||||
static
|
||||
size_type
|
||||
constrain_hash(
|
||||
std::size_t hash,
|
||||
size_type bucket_count) noexcept;
|
||||
|
||||
BOOST_BEAST_DECL
|
||||
element*
|
||||
find_element(
|
||||
key_type key,
|
||||
std::size_t hash) const noexcept;
|
||||
|
||||
BOOST_BEAST_DECL
|
||||
element*
|
||||
prepare_insert(
|
||||
const_iterator* before,
|
||||
key_type key,
|
||||
std::size_t hash);
|
||||
|
||||
BOOST_BEAST_DECL
|
||||
void
|
||||
finish_insert(
|
||||
const_iterator before,
|
||||
element* e,
|
||||
std::size_t hash);
|
||||
|
||||
BOOST_BEAST_DECL
|
||||
void
|
||||
remove(element* e);
|
||||
};
|
||||
|
||||
} // json
|
||||
} // beast
|
||||
} // boost
|
||||
|
||||
// Must be included here for this file to stand alone
|
||||
#include <boost/json/value.hpp>
|
||||
|
||||
// headers for this file are at the bottom of value.hpp
|
||||
|
||||
#endif
|
||||
38
include/boost/json/parse_file.hpp
Normal file
38
include/boost/json/parse_file.hpp
Normal file
@@ -0,0 +1,38 @@
|
||||
//
|
||||
// Copyright (c) 2018-2019 Vinnie Falco (vinnie dot falco at gmail dot com)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
// Official repository: https://github.com/boostorg/json
|
||||
//
|
||||
|
||||
#ifndef BOOST_JSON_PARSE_FILE_HPP
|
||||
#define BOOST_JSON_PARSE_FILE_HPP
|
||||
|
||||
#include <boost/beast/core/detail/config.hpp>
|
||||
#include <boost/json/basic_parser.hpp>
|
||||
#include <boost/beast/core/error.hpp>
|
||||
|
||||
namespace boost {
|
||||
namespace beast {
|
||||
namespace json {
|
||||
|
||||
/** Parse the contents of a file as JSON.
|
||||
*/
|
||||
BOOST_BEAST_DECL
|
||||
void
|
||||
parse_file(
|
||||
char const* path,
|
||||
basic_parser& parser,
|
||||
error_code& ec);
|
||||
|
||||
} // json
|
||||
} // beast
|
||||
} // boost
|
||||
|
||||
#ifdef BOOST_BEAST_HEADER_ONLY
|
||||
#include <boost/json/impl/parse_file.ipp>
|
||||
#endif
|
||||
|
||||
#endif
|
||||
153
include/boost/json/parser.hpp
Normal file
153
include/boost/json/parser.hpp
Normal file
@@ -0,0 +1,153 @@
|
||||
//
|
||||
// Copyright (c) 2018-2019 Vinnie Falco (vinnie dot falco at gmail dot com)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
// Official repository: https://github.com/boostorg/json
|
||||
//
|
||||
|
||||
#ifndef BOOST_JSON_PARSER_HPP
|
||||
#define BOOST_JSON_PARSER_HPP
|
||||
|
||||
#include <boost/beast/core/detail/config.hpp>
|
||||
#include <boost/json/value.hpp>
|
||||
#include <boost/json/basic_parser.hpp>
|
||||
#include <boost/json/storage.hpp>
|
||||
#include <new>
|
||||
#include <string>
|
||||
#include <type_traits>
|
||||
|
||||
namespace boost {
|
||||
namespace beast {
|
||||
namespace json {
|
||||
|
||||
class parser : public basic_parser
|
||||
{
|
||||
static std::size_t const
|
||||
default_max_depth = 32;
|
||||
|
||||
value jv_;
|
||||
detail::stack<value*,
|
||||
default_max_depth> stack_;
|
||||
std::string s_;
|
||||
unsigned long max_depth_ =
|
||||
default_max_depth;
|
||||
bool obj_;
|
||||
|
||||
public:
|
||||
BOOST_BEAST_DECL
|
||||
parser();
|
||||
|
||||
BOOST_BEAST_DECL
|
||||
parser(storage_ptr const& store);
|
||||
|
||||
/** Returns the maximum allowed depth of input JSON.
|
||||
*/
|
||||
std::size_t
|
||||
max_depth() const noexcept
|
||||
{
|
||||
return max_depth_;
|
||||
}
|
||||
|
||||
/** Set the maximum allowed depth of input JSON.
|
||||
*/
|
||||
void
|
||||
max_depth(unsigned long levels) noexcept
|
||||
{
|
||||
max_depth_ = levels;
|
||||
}
|
||||
|
||||
BOOST_BEAST_DECL
|
||||
value const&
|
||||
get() const noexcept;
|
||||
|
||||
BOOST_BEAST_DECL
|
||||
value
|
||||
release() noexcept;
|
||||
|
||||
private:
|
||||
template<class T>
|
||||
void
|
||||
assign(T&& t);
|
||||
|
||||
BOOST_BEAST_DECL
|
||||
void
|
||||
reset();
|
||||
|
||||
BOOST_BEAST_DECL
|
||||
void
|
||||
on_document_begin(
|
||||
error_code& ec) override;
|
||||
|
||||
BOOST_BEAST_DECL
|
||||
void
|
||||
on_object_begin(
|
||||
error_code& ec) override;
|
||||
|
||||
BOOST_BEAST_DECL
|
||||
void
|
||||
on_object_end(
|
||||
error_code& ec) override;
|
||||
|
||||
BOOST_BEAST_DECL
|
||||
void
|
||||
on_array_begin(
|
||||
error_code& ec) override;
|
||||
|
||||
BOOST_BEAST_DECL
|
||||
void
|
||||
on_array_end(
|
||||
error_code& ec) override;
|
||||
|
||||
BOOST_BEAST_DECL
|
||||
void
|
||||
on_key_data(
|
||||
string_view s,
|
||||
error_code& ec) override;
|
||||
|
||||
BOOST_BEAST_DECL
|
||||
void
|
||||
on_key_end(
|
||||
string_view s,
|
||||
error_code& ec) override;
|
||||
|
||||
BOOST_BEAST_DECL
|
||||
void
|
||||
on_string_data(
|
||||
string_view s,
|
||||
error_code& ec) override;
|
||||
|
||||
BOOST_BEAST_DECL
|
||||
void
|
||||
on_string_end(
|
||||
string_view s,
|
||||
error_code& ec) override;
|
||||
|
||||
BOOST_BEAST_DECL
|
||||
void
|
||||
on_number(
|
||||
number n,
|
||||
error_code& ec) override;
|
||||
|
||||
BOOST_BEAST_DECL
|
||||
void
|
||||
on_bool(
|
||||
bool b,
|
||||
error_code& ec) override;
|
||||
|
||||
BOOST_BEAST_DECL
|
||||
void
|
||||
on_null(error_code&) override;
|
||||
};
|
||||
|
||||
} // json
|
||||
} // beast
|
||||
} // boost
|
||||
|
||||
#include <boost/json/impl/parser.hpp>
|
||||
#ifdef BOOST_BEAST_HEADER_ONLY
|
||||
#include <boost/json/impl/parser.ipp>
|
||||
#endif
|
||||
|
||||
#endif
|
||||
143
include/boost/json/serializer.hpp
Normal file
143
include/boost/json/serializer.hpp
Normal file
@@ -0,0 +1,143 @@
|
||||
//
|
||||
// Copyright (c) 2018-2019 Vinnie Falco (vinnie dot falco at gmail dot com)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
// Official repository: https://github.com/boostorg/json
|
||||
//
|
||||
|
||||
#ifndef BOOST_JSON_SERIALIZER_HPP
|
||||
#define BOOST_JSON_SERIALIZER_HPP
|
||||
|
||||
#include <boost/beast/core/detail/config.hpp>
|
||||
#include <boost/json/iterator.hpp>
|
||||
#include <boost/json/number.hpp>
|
||||
#include <boost/json/value.hpp>
|
||||
#include <boost/asio/buffer.hpp>
|
||||
|
||||
namespace boost {
|
||||
namespace beast {
|
||||
namespace json {
|
||||
|
||||
class serializer
|
||||
{
|
||||
struct base
|
||||
{
|
||||
virtual ~base() = default;
|
||||
|
||||
virtual
|
||||
bool
|
||||
is_done() const noexcept = 0;
|
||||
|
||||
virtual
|
||||
std::size_t
|
||||
next(net::mutable_buffer) = 0;
|
||||
};
|
||||
|
||||
class impl : public base
|
||||
{
|
||||
enum class state
|
||||
{
|
||||
next,
|
||||
init,
|
||||
key,
|
||||
value,
|
||||
literal,
|
||||
key_literal,
|
||||
string,
|
||||
done
|
||||
};
|
||||
|
||||
value const& jv_;
|
||||
const_iterator it_;
|
||||
string_view str_;
|
||||
char buf_[number::max_string_chars + 1];
|
||||
state state_ = state::init;
|
||||
bool last_;
|
||||
|
||||
public:
|
||||
BOOST_BEAST_DECL
|
||||
impl(value const& jv);
|
||||
|
||||
BOOST_BEAST_DECL
|
||||
bool
|
||||
is_done() const noexcept override;
|
||||
|
||||
BOOST_BEAST_DECL
|
||||
std::size_t
|
||||
next(net::mutable_buffer) override;
|
||||
|
||||
private:
|
||||
BOOST_BEAST_DECL
|
||||
void
|
||||
append(char c,
|
||||
net::mutable_buffer& b);
|
||||
|
||||
BOOST_BEAST_DECL
|
||||
void
|
||||
append(
|
||||
char const* s, std::size_t n,
|
||||
net::mutable_buffer& b);
|
||||
};
|
||||
|
||||
typename std::aligned_storage<
|
||||
sizeof(impl)>::type buf_;
|
||||
|
||||
base&
|
||||
get_base() noexcept
|
||||
{
|
||||
return *reinterpret_cast<
|
||||
base*>(&buf_);
|
||||
}
|
||||
|
||||
base const&
|
||||
get_base() const noexcept
|
||||
{
|
||||
return *reinterpret_cast<
|
||||
base const*>(&buf_);
|
||||
}
|
||||
|
||||
public:
|
||||
BOOST_BEAST_DECL
|
||||
~serializer();
|
||||
|
||||
BOOST_BEAST_DECL
|
||||
explicit
|
||||
serializer(value const& jv);
|
||||
|
||||
template<class MutableBufferSequence>
|
||||
std::size_t
|
||||
next(MutableBufferSequence const& buffers)
|
||||
{
|
||||
std::size_t bytes_transferred = 0;
|
||||
for(auto it = net::buffer_sequence_begin(buffers),
|
||||
end = net::buffer_sequence_end(buffers);
|
||||
it != end; ++it)
|
||||
bytes_transferred += next(
|
||||
net::mutable_buffer(*it));
|
||||
return bytes_transferred;
|
||||
}
|
||||
|
||||
bool
|
||||
is_done() const noexcept
|
||||
{
|
||||
return get_base().is_done();
|
||||
}
|
||||
|
||||
std::size_t
|
||||
next(net::mutable_buffer buffer)
|
||||
{
|
||||
return get_base().next(buffer);
|
||||
}
|
||||
};
|
||||
|
||||
} // json
|
||||
} // beast
|
||||
} // boost
|
||||
|
||||
#ifdef BOOST_BEAST_HEADER_ONLY
|
||||
#include <boost/json/impl/serializer.ipp>
|
||||
#endif
|
||||
|
||||
#endif
|
||||
41
include/boost/json/src.hpp
Normal file
41
include/boost/json/src.hpp
Normal file
@@ -0,0 +1,41 @@
|
||||
//
|
||||
// Copyright (c) 2016-2019 Vinnie Falco (vinnie dot falco at gmail dot com)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
// Official repository: https://github.com/boostorg/json
|
||||
//
|
||||
|
||||
#ifndef BOOST_BEAST_SRC_EXTRA_HPP
|
||||
#define BOOST_BEAST_SRC_EXTRA_HPP
|
||||
|
||||
/*
|
||||
|
||||
This file is meant to be included once, in a translation unit of
|
||||
the program, with the macro BOOST_BEAST_SPLIT_COMPILATION defined.
|
||||
|
||||
*/
|
||||
|
||||
#define BOOST_BEAST_SOURCE
|
||||
|
||||
#include <boost/beast/core/detail/config.hpp>
|
||||
|
||||
#if defined(BOOST_BEAST_HEADER_ONLY)
|
||||
# error Do not compile Beast library source with BOOST_BEAST_HEADER_ONLY defined
|
||||
#endif
|
||||
|
||||
#include <boost/json/detail/varint.ipp>
|
||||
#include <boost/json/impl/array.ipp>
|
||||
#include <boost/json/impl/basic_parser.ipp>
|
||||
#include <boost/json/impl/error.ipp>
|
||||
#include <boost/json/impl/iterator.ipp>
|
||||
#include <boost/json/impl/number.ipp>
|
||||
#include <boost/json/impl/object.ipp>
|
||||
#include <boost/json/impl/parse_file.ipp>
|
||||
#include <boost/json/impl/parser.ipp>
|
||||
#include <boost/json/impl/serializer.ipp>
|
||||
#include <boost/json/impl/storage.ipp>
|
||||
#include <boost/json/impl/value.ipp>
|
||||
|
||||
#endif
|
||||
220
include/boost/json/storage.hpp
Normal file
220
include/boost/json/storage.hpp
Normal file
@@ -0,0 +1,220 @@
|
||||
//
|
||||
// Copyright (c) 2018-2019 Vinnie Falco (vinnie dot falco at gmail dot com)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
// Official repository: https://github.com/boostorg/json
|
||||
//
|
||||
|
||||
#ifndef BOOST_JSON_STORAGE_HPP
|
||||
#define BOOST_JSON_STORAGE_HPP
|
||||
|
||||
#include <boost/beast/core/detail/config.hpp>
|
||||
#include <cstddef>
|
||||
#include <cstdlib>
|
||||
#include <type_traits>
|
||||
|
||||
namespace boost {
|
||||
namespace beast {
|
||||
namespace json {
|
||||
|
||||
/** Abstract interface to a memory resource used with JSON.
|
||||
*/
|
||||
struct storage
|
||||
{
|
||||
static std::size_t constexpr max_align =
|
||||
sizeof(max_align_t);
|
||||
|
||||
virtual
|
||||
~storage() = default;
|
||||
|
||||
virtual
|
||||
void
|
||||
addref() noexcept = 0;
|
||||
|
||||
virtual
|
||||
void
|
||||
release() noexcept = 0;
|
||||
|
||||
virtual
|
||||
void*
|
||||
allocate(
|
||||
std::size_t n,
|
||||
std::size_t align =
|
||||
max_align) = 0;
|
||||
|
||||
virtual
|
||||
void
|
||||
deallocate(
|
||||
void* p,
|
||||
std::size_t n,
|
||||
std::size_t align =
|
||||
max_align) noexcept = 0;
|
||||
|
||||
virtual
|
||||
bool
|
||||
is_equal(
|
||||
storage const& other) const noexcept = 0;
|
||||
|
||||
friend
|
||||
bool
|
||||
operator==(
|
||||
storage const& lhs,
|
||||
storage const& rhs) noexcept
|
||||
{
|
||||
return &lhs == &rhs || lhs.is_equal(rhs);
|
||||
}
|
||||
|
||||
friend
|
||||
bool
|
||||
operator!=(
|
||||
storage const& lhs,
|
||||
storage const& rhs) noexcept
|
||||
{
|
||||
return !(lhs == rhs);
|
||||
}
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
/** Manages a type-erased storage object and options for a set of JSON values.
|
||||
*/
|
||||
class storage_ptr
|
||||
{
|
||||
storage* p_ = nullptr;
|
||||
|
||||
public:
|
||||
storage_ptr() = default;
|
||||
|
||||
BOOST_BEAST_DECL
|
||||
~storage_ptr();
|
||||
|
||||
BOOST_BEAST_DECL
|
||||
storage_ptr(storage_ptr&&) noexcept;
|
||||
|
||||
BOOST_BEAST_DECL
|
||||
storage_ptr(storage_ptr const&) noexcept;
|
||||
|
||||
BOOST_BEAST_DECL
|
||||
storage_ptr&
|
||||
operator=(storage_ptr&&) noexcept;
|
||||
|
||||
BOOST_BEAST_DECL
|
||||
storage_ptr&
|
||||
operator=(storage_ptr const&) noexcept;
|
||||
|
||||
/** Constructor
|
||||
|
||||
@param p A pointer to a storage object. Ownership of the
|
||||
object is transferred; the reference count is not adjusted.
|
||||
*/
|
||||
BOOST_BEAST_DECL
|
||||
storage_ptr(storage* p) noexcept;
|
||||
|
||||
/** Return ownership of the managed storage object.
|
||||
*/
|
||||
BOOST_BEAST_DECL
|
||||
storage*
|
||||
release() noexcept;
|
||||
|
||||
explicit
|
||||
operator bool() const noexcept
|
||||
{
|
||||
return p_ != nullptr;
|
||||
}
|
||||
|
||||
storage*
|
||||
get() const noexcept
|
||||
{
|
||||
return p_;
|
||||
}
|
||||
|
||||
storage*
|
||||
operator->() const noexcept
|
||||
{
|
||||
return p_;
|
||||
}
|
||||
|
||||
storage&
|
||||
operator*() const noexcept
|
||||
{
|
||||
return *p_;
|
||||
}
|
||||
};
|
||||
|
||||
inline
|
||||
bool
|
||||
operator==(storage_ptr const& lhs, storage_ptr const& rhs) noexcept
|
||||
{
|
||||
return lhs.get() == rhs.get();
|
||||
}
|
||||
|
||||
inline
|
||||
bool
|
||||
operator==(storage* lhs, storage_ptr const& rhs) noexcept
|
||||
{
|
||||
return lhs == rhs.get();
|
||||
}
|
||||
|
||||
inline
|
||||
bool
|
||||
operator==(storage_ptr const& lhs, storage* rhs) noexcept
|
||||
{
|
||||
return lhs.get() == rhs;
|
||||
}
|
||||
|
||||
inline
|
||||
bool
|
||||
operator!=(storage_ptr const& lhs, storage_ptr const& rhs) noexcept
|
||||
{
|
||||
return lhs.get() != rhs.get();
|
||||
}
|
||||
|
||||
inline
|
||||
bool
|
||||
operator!=(storage* lhs, storage_ptr const& rhs) noexcept
|
||||
{
|
||||
return lhs != rhs.get();
|
||||
}
|
||||
|
||||
inline
|
||||
bool
|
||||
operator!=(storage_ptr const& lhs, storage* rhs) noexcept
|
||||
{
|
||||
return lhs.get() != rhs;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
/** Construct a storage pointer to the specified allocator
|
||||
*/
|
||||
template<class Allocator>
|
||||
storage_ptr
|
||||
make_storage_ptr(Allocator const& a);
|
||||
|
||||
/** Return a pointer to the current default storage
|
||||
*/
|
||||
BOOST_BEAST_DECL
|
||||
storage_ptr
|
||||
default_storage();
|
||||
|
||||
/** Set the current default storage
|
||||
|
||||
This function may not be called concurrently,
|
||||
or concurrent with @ref default_storage.
|
||||
*/
|
||||
BOOST_BEAST_DECL
|
||||
void
|
||||
default_storage(storage_ptr sp);
|
||||
|
||||
} // json
|
||||
} // beast
|
||||
} // boost
|
||||
|
||||
#include <boost/json/impl/storage.hpp>
|
||||
#ifdef BOOST_BEAST_HEADER_ONLY
|
||||
#include <boost/json/impl/storage.ipp>
|
||||
#endif
|
||||
|
||||
#endif
|
||||
35
include/boost/json/string.hpp
Normal file
35
include/boost/json/string.hpp
Normal file
@@ -0,0 +1,35 @@
|
||||
//
|
||||
// Copyright (c) 2018-2019 Vinnie Falco (vinnie dot falco at gmail dot com)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
// Official repository: https://github.com/boostorg/json
|
||||
//
|
||||
|
||||
#ifndef BOOST_JSON_STRING_HPP
|
||||
#define BOOST_JSON_STRING_HPP
|
||||
|
||||
#include <boost/beast/core/detail/config.hpp>
|
||||
#include <boost/json/allocator.hpp>
|
||||
#include <string>
|
||||
|
||||
namespace boost {
|
||||
namespace beast {
|
||||
namespace json {
|
||||
|
||||
class value;
|
||||
|
||||
/** The native type of string values
|
||||
*/
|
||||
using string =
|
||||
std::basic_string<
|
||||
char,
|
||||
std::char_traits<char>,
|
||||
allocator<char>>;
|
||||
|
||||
} // json
|
||||
} // beast
|
||||
} // boost
|
||||
|
||||
#endif
|
||||
942
include/boost/json/value.hpp
Normal file
942
include/boost/json/value.hpp
Normal file
@@ -0,0 +1,942 @@
|
||||
//
|
||||
// Copyright (c) 2018-2019 Vinnie Falco (vinnie dot falco at gmail dot com)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
// Official repository: https://github.com/boostorg/json
|
||||
//
|
||||
|
||||
#ifndef BOOST_JSON_VALUE_HPP
|
||||
#define BOOST_JSON_VALUE_HPP
|
||||
|
||||
#include <boost/beast/core/detail/config.hpp>
|
||||
#include <boost/json/array.hpp>
|
||||
#include <boost/json/kind.hpp>
|
||||
#include <boost/json/number.hpp>
|
||||
#include <boost/json/object.hpp>
|
||||
#include <boost/json/storage.hpp>
|
||||
#include <boost/json/string.hpp>
|
||||
#include <boost/json/detail/is_specialized.hpp>
|
||||
#include <boost/json/detail/value.hpp>
|
||||
#include <boost/type_traits/make_void.hpp>
|
||||
#include <cstdlib>
|
||||
#include <initializer_list>
|
||||
#include <iosfwd>
|
||||
#include <type_traits>
|
||||
#include <utility>
|
||||
|
||||
namespace boost {
|
||||
namespace beast {
|
||||
namespace json {
|
||||
|
||||
class value;
|
||||
|
||||
/** Customization point for assigning to and from class types.
|
||||
*/
|
||||
template<class T>
|
||||
struct value_exchange final
|
||||
#ifndef BOOST_BEAST_DOXYGEN
|
||||
: detail::primary_template
|
||||
#endif
|
||||
{
|
||||
static
|
||||
void
|
||||
to_json(T const& t, value& v)
|
||||
{
|
||||
detail::call_to_json(t, v);
|
||||
}
|
||||
|
||||
static
|
||||
void
|
||||
from_json(T& t, value const& v)
|
||||
{
|
||||
detail::call_from_json(t, v);
|
||||
}
|
||||
};
|
||||
|
||||
/** Trait to determine if a type can be assigned to a json value.
|
||||
*/
|
||||
template<class T>
|
||||
using has_from_json =
|
||||
#ifdef BOOST_BEAST_DOXYGEN
|
||||
__see_below__;
|
||||
#else
|
||||
std::integral_constant<bool,
|
||||
detail::is_specialized<value_exchange<
|
||||
detail::remove_cr<T>>>::value ||
|
||||
detail::has_adl_from_json<
|
||||
detail::remove_cr<T>>::value ||
|
||||
detail::has_mf_from_json<
|
||||
detail::remove_cr<T>>::value>;
|
||||
#endif
|
||||
|
||||
/** Returns `true` if a JSON value can be constructed from `T`
|
||||
*/
|
||||
template<class T>
|
||||
using has_to_json =
|
||||
#ifdef BOOST_BEAST_DOXYGEN
|
||||
__see_below__;
|
||||
#else
|
||||
std::integral_constant<bool,
|
||||
detail::is_specialized<value_exchange<
|
||||
detail::remove_cr<T>>>::value ||
|
||||
detail::has_adl_to_json<
|
||||
detail::remove_cr<T>>::value ||
|
||||
detail::has_mf_to_json<
|
||||
detail::remove_cr<T>>::value>;
|
||||
#endif
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
/** A JSON value.
|
||||
*/
|
||||
class value
|
||||
{
|
||||
friend class value_test;
|
||||
|
||||
struct native
|
||||
{
|
||||
union
|
||||
{
|
||||
number num_;
|
||||
bool bool_;
|
||||
};
|
||||
storage_ptr sp_;
|
||||
};
|
||||
|
||||
union
|
||||
{
|
||||
object obj_;
|
||||
array arr_;
|
||||
string str_;
|
||||
native nat_;
|
||||
};
|
||||
|
||||
json::kind kind_;
|
||||
|
||||
public:
|
||||
//--------------------------------------------------------------------------
|
||||
//
|
||||
// Special members
|
||||
//
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
/// Destroy a value and all of its contents
|
||||
BOOST_BEAST_DECL
|
||||
~value();
|
||||
|
||||
/// Move constructor
|
||||
BOOST_BEAST_DECL
|
||||
value(value&& other) noexcept;
|
||||
|
||||
/// Move construct a value, using the specified storage
|
||||
BOOST_BEAST_DECL
|
||||
value(
|
||||
value&& other,
|
||||
storage_ptr store);
|
||||
|
||||
/// Construct a copy of a value
|
||||
BOOST_BEAST_DECL
|
||||
value(value const& other);
|
||||
|
||||
/// Construct a copy of a value using the specified storage
|
||||
BOOST_BEAST_DECL
|
||||
value(
|
||||
value const& other,
|
||||
storage_ptr store);
|
||||
|
||||
/// Move-assign a value
|
||||
BOOST_BEAST_DECL
|
||||
value& operator=(value&& other);
|
||||
|
||||
/// Assign a copy of a value
|
||||
BOOST_BEAST_DECL
|
||||
value& operator=(value const& other);
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
//
|
||||
// Construction and Assignment
|
||||
//
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
/** Construct a null value using the default storage.
|
||||
*/
|
||||
BOOST_BEAST_DECL
|
||||
value() noexcept;
|
||||
|
||||
/** Construct a null value using the specified storage.
|
||||
|
||||
The value and all of its contents will use the
|
||||
specified storage object.
|
||||
*/
|
||||
BOOST_BEAST_DECL
|
||||
explicit
|
||||
value(storage_ptr store) noexcept;
|
||||
|
||||
/** Construct a value using the default storage
|
||||
|
||||
The value and all of its contents will use the
|
||||
specified storage object.
|
||||
*/
|
||||
BOOST_BEAST_DECL
|
||||
value(json::kind k) noexcept;
|
||||
|
||||
/** Construct a value using the specified storage.
|
||||
|
||||
The value and all of its contents will use the specified
|
||||
storage object.
|
||||
|
||||
@param k The kind of JSON value.
|
||||
|
||||
@param store The storage to use.
|
||||
*/
|
||||
BOOST_BEAST_DECL
|
||||
value(
|
||||
json::kind k,
|
||||
storage_ptr store) noexcept;
|
||||
|
||||
/** Construct a value from an object.
|
||||
*/
|
||||
BOOST_BEAST_DECL
|
||||
value(object obj) noexcept;
|
||||
|
||||
/** Construct a value from an object using the specified storage
|
||||
*/
|
||||
BOOST_BEAST_DECL
|
||||
value(object obj, storage_ptr store);
|
||||
|
||||
/** Construct a value from an array.
|
||||
*/
|
||||
BOOST_BEAST_DECL
|
||||
value(array arr) noexcept;
|
||||
|
||||
/** Construct a value from an array using the specified storage
|
||||
*/
|
||||
BOOST_BEAST_DECL
|
||||
value(array arr, storage_ptr store);
|
||||
|
||||
/** Construct a value from a string.
|
||||
*/
|
||||
BOOST_BEAST_DECL
|
||||
value(string str) noexcept;
|
||||
|
||||
/** Construct a value from a string using the specified storage
|
||||
*/
|
||||
BOOST_BEAST_DECL
|
||||
value(string str, storage_ptr store);
|
||||
|
||||
/** Construct a value from a nujmber
|
||||
*/
|
||||
BOOST_BEAST_DECL
|
||||
value(number num);
|
||||
|
||||
/** Construct a value from a nujmber using the specified storage
|
||||
*/
|
||||
BOOST_BEAST_DECL
|
||||
value(number num, storage_ptr store);
|
||||
|
||||
/** Construct an object from an initializer list.
|
||||
*/
|
||||
BOOST_BEAST_DECL
|
||||
value(std::initializer_list<
|
||||
std::pair<string_view, value>> init);
|
||||
|
||||
/** Construct an object from an initializer list using the specified storage
|
||||
*/
|
||||
BOOST_BEAST_DECL
|
||||
value(std::initializer_list<
|
||||
std::pair<string_view, value>> init,
|
||||
storage_ptr store);
|
||||
#if 0
|
||||
/** Construct an array from an initializer list.
|
||||
*/
|
||||
BOOST_BEAST_DECL
|
||||
value(std::initializer_list<value> init);
|
||||
|
||||
/** Construct an array from an initializer list using the specified storage.
|
||||
*/
|
||||
BOOST_BEAST_DECL
|
||||
value(std::initializer_list<value> init,
|
||||
storage_ptr store);
|
||||
#endif
|
||||
|
||||
/** Assign a value from an object
|
||||
*/
|
||||
BOOST_BEAST_DECL
|
||||
value&
|
||||
operator=(object obj);
|
||||
|
||||
/** Assign a value from an array
|
||||
*/
|
||||
BOOST_BEAST_DECL
|
||||
value&
|
||||
operator=(array arr);
|
||||
|
||||
/** Assign a value from a string
|
||||
*/
|
||||
BOOST_BEAST_DECL
|
||||
value&
|
||||
operator=(string str);
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
//
|
||||
// Modifiers
|
||||
//
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
/** Reset the json to the specified type.
|
||||
|
||||
This changes the value to hold a value of the
|
||||
specified type. Any previous contents are cleared.
|
||||
|
||||
@param k The kind to set. If the new kind is an
|
||||
object, array, or string the resulting value will be
|
||||
empty. Otherwise, the value will be in an undefined,
|
||||
valid state.
|
||||
*/
|
||||
BOOST_BEAST_DECL
|
||||
void
|
||||
reset(json::kind k = json::kind::null) noexcept;
|
||||
|
||||
/** Reset the json to the specified type.
|
||||
|
||||
This changes the value to hold a value of the
|
||||
specified type. Any previous contents are cleared.
|
||||
|
||||
@param k The kind to set. If the new kind is an
|
||||
object, array, or string the resulting value will be
|
||||
empty. Otherwise, the value will be in an undefined,
|
||||
valid state.
|
||||
*/
|
||||
BOOST_BEAST_DECL
|
||||
value&
|
||||
operator=(json::kind k) noexcept
|
||||
{
|
||||
reset(k);
|
||||
return *this;
|
||||
}
|
||||
|
||||
/** Set the value to an empty object, and return it.
|
||||
|
||||
This calls `reset(json::kind::object)` and returns
|
||||
`as_object()`. The previous contents of the value
|
||||
are destroyed.
|
||||
*/
|
||||
object&
|
||||
emplace_object() noexcept
|
||||
{
|
||||
reset(json::kind::object);
|
||||
return as_object();
|
||||
}
|
||||
|
||||
/** Set the value to an empty array, and return it.
|
||||
|
||||
This calls `reset(json::kind::array)` and returns
|
||||
`as_array()`. The previous contents of the value
|
||||
are destroyed.
|
||||
*/
|
||||
array&
|
||||
emplace_array() noexcept
|
||||
{
|
||||
reset(json::kind::array);
|
||||
return as_array();
|
||||
}
|
||||
|
||||
/** Set the value to an empty string, and return it.
|
||||
|
||||
This calls `reset(json::kind::string)` and returns
|
||||
`as_string()`. The previous contents of the value
|
||||
are destroyed.
|
||||
*/
|
||||
string&
|
||||
emplace_string() noexcept
|
||||
{
|
||||
reset(json::kind::string);
|
||||
return as_string();
|
||||
}
|
||||
|
||||
/** Set the value to an uninitialized number, and return it.
|
||||
|
||||
This calls `reset(json::kind::number)` and returns
|
||||
`as_number()`. The previous contents of the value
|
||||
are destroyed.
|
||||
*/
|
||||
number&
|
||||
emplace_number() noexcept
|
||||
{
|
||||
reset(json::kind::number);
|
||||
return as_number();
|
||||
}
|
||||
|
||||
/** Set the value to an uninitialized boolean, and return it.
|
||||
|
||||
This calls `reset(json::kind::boolean)` and returns
|
||||
`as_bool()`. The previous contents of the value
|
||||
are destroyed.
|
||||
*/
|
||||
bool&
|
||||
emplace_bool() noexcept
|
||||
{
|
||||
reset(json::kind::boolean);
|
||||
return as_bool();
|
||||
}
|
||||
|
||||
/// Set the value to a null
|
||||
void
|
||||
emplace_null() noexcept
|
||||
{
|
||||
reset(json::kind::null);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
//
|
||||
// Exchange
|
||||
//
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
/// Construct a value from another type
|
||||
template<
|
||||
class T
|
||||
#ifndef BOOST_BEAST_DOXYGEN
|
||||
,class = typename std::enable_if<
|
||||
has_to_json<T>::value>::type
|
||||
#endif
|
||||
>
|
||||
value(T const& t)
|
||||
: value(t, default_storage())
|
||||
{
|
||||
}
|
||||
|
||||
/// Construct a value from another type using the specified storage
|
||||
template<
|
||||
class T
|
||||
#ifndef BOOST_BEAST_DOXYGEN
|
||||
,class = typename std::enable_if<
|
||||
has_to_json<T>::value>::type
|
||||
#endif
|
||||
>
|
||||
value(T const& t, storage_ptr store)
|
||||
: value(std::move(store))
|
||||
{
|
||||
value_exchange<
|
||||
detail::remove_cr<T>
|
||||
>::to_json(t, *this);
|
||||
}
|
||||
|
||||
/// Assign a value from another type
|
||||
template<
|
||||
class T
|
||||
#ifndef BOOST_BEAST_DOXYGEN
|
||||
,class = typename std::enable_if<
|
||||
has_to_json<T>::value>::type
|
||||
#endif
|
||||
>
|
||||
value&
|
||||
operator=(T const& t)
|
||||
{
|
||||
value_exchange<
|
||||
detail::remove_cr<T>
|
||||
>::to_json(t, *this);
|
||||
return *this;
|
||||
}
|
||||
|
||||
/** Try to assign a value to another type
|
||||
|
||||
@throws system error Thrown upon failure
|
||||
*/
|
||||
template<class T>
|
||||
void
|
||||
store(T& t) const
|
||||
{
|
||||
// If this assert goes off, it means that there are no known
|
||||
// ways to convert a JSON value into a user defined type `T`.
|
||||
// There are three ways to fix this:
|
||||
//
|
||||
// 1. Add the member function `T::from_json(value const&)`,
|
||||
//
|
||||
// 2. Add the free function `from_json(T&, value const&)`
|
||||
// in the same namespace as T, or
|
||||
//
|
||||
// 3. Specialize `json::value_exchange` for `T`, and provide
|
||||
// the static member `from_json(T&, value const&)`.
|
||||
|
||||
static_assert(
|
||||
has_from_json<T>::value,
|
||||
"Destination type is unknown");
|
||||
value_exchange<
|
||||
detail::remove_cr<T>
|
||||
>::from_json(t, *this);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
//
|
||||
// Observers
|
||||
//
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
/// Returns the kind of this JSON value
|
||||
json::kind
|
||||
kind() const noexcept
|
||||
{
|
||||
return kind_;
|
||||
}
|
||||
|
||||
/// Returns `true` if this is an object
|
||||
bool
|
||||
is_object() const noexcept
|
||||
{
|
||||
return kind_ == json::kind::object;
|
||||
}
|
||||
|
||||
/// Returns `true` if this is an array
|
||||
bool
|
||||
is_array() const noexcept
|
||||
{
|
||||
return kind_ == json::kind::array;
|
||||
}
|
||||
|
||||
/// Returns `true` if this is a string
|
||||
bool
|
||||
is_string() const noexcept
|
||||
{
|
||||
return kind_ == json::kind::string;
|
||||
}
|
||||
|
||||
/// Returns `true` if this is a number
|
||||
bool
|
||||
is_number() const noexcept
|
||||
{
|
||||
return kind_ == json::kind::number;
|
||||
}
|
||||
|
||||
bool
|
||||
is_bool() const noexcept
|
||||
{
|
||||
return kind_ == json::kind::boolean;
|
||||
}
|
||||
|
||||
bool
|
||||
is_null() const noexcept
|
||||
{
|
||||
return kind_ == json::kind::null;
|
||||
}
|
||||
|
||||
//---
|
||||
|
||||
/// Returns `true` if this is not an array or object
|
||||
bool
|
||||
is_primitive() const noexcept
|
||||
{
|
||||
switch(kind_)
|
||||
{
|
||||
case json::kind::object:
|
||||
case json::kind::array:
|
||||
return false;
|
||||
default:
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/// Returns `true` if this is an array or object
|
||||
bool
|
||||
is_structured() const noexcept
|
||||
{
|
||||
return ! is_primitive();
|
||||
}
|
||||
|
||||
/// Returns `true` if this is a number representable as a `std::int64_t`
|
||||
bool
|
||||
is_int64() const noexcept
|
||||
{
|
||||
return
|
||||
kind_ == json::kind::number &&
|
||||
nat_.num_.is_int64();
|
||||
}
|
||||
|
||||
/// Returns `true` if this is a number representable as a `std::uint64_t`
|
||||
bool
|
||||
is_uint64() const noexcept
|
||||
{
|
||||
return
|
||||
kind_ == json::kind::number &&
|
||||
nat_.num_.is_uint64();
|
||||
}
|
||||
|
||||
/** Returns `true` if this is a number representable as a `double`
|
||||
|
||||
The return value will always be the same as the
|
||||
value returned from @ref is_number.
|
||||
*/
|
||||
bool
|
||||
is_double() const noexcept
|
||||
{
|
||||
return kind_ == json::kind::number;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
//
|
||||
// Accessors
|
||||
//
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
BOOST_BEAST_DECL
|
||||
storage_ptr
|
||||
get_storage() const noexcept;
|
||||
|
||||
object&
|
||||
as_object() noexcept
|
||||
{
|
||||
BOOST_ASSERT(is_object());
|
||||
return obj_;
|
||||
}
|
||||
|
||||
object const&
|
||||
as_object() const noexcept
|
||||
{
|
||||
BOOST_ASSERT(is_object());
|
||||
return obj_;
|
||||
}
|
||||
|
||||
array&
|
||||
as_array() noexcept
|
||||
{
|
||||
BOOST_ASSERT(is_array());
|
||||
return arr_;
|
||||
}
|
||||
|
||||
array const&
|
||||
as_array() const noexcept
|
||||
{
|
||||
BOOST_ASSERT(is_array());
|
||||
return arr_;
|
||||
}
|
||||
|
||||
string&
|
||||
as_string() noexcept
|
||||
{
|
||||
BOOST_ASSERT(is_string());
|
||||
return str_;
|
||||
}
|
||||
|
||||
string const&
|
||||
as_string() const noexcept
|
||||
{
|
||||
BOOST_ASSERT(is_string());
|
||||
return str_;
|
||||
}
|
||||
|
||||
number&
|
||||
as_number() noexcept
|
||||
{
|
||||
BOOST_ASSERT(is_number());
|
||||
return nat_.num_;
|
||||
}
|
||||
|
||||
number const&
|
||||
as_number() const noexcept
|
||||
{
|
||||
BOOST_ASSERT(is_number());
|
||||
return nat_.num_;
|
||||
}
|
||||
|
||||
std::int64_t
|
||||
get_int64() const noexcept
|
||||
{
|
||||
BOOST_ASSERT(is_int64());
|
||||
return nat_.num_.get_int64();
|
||||
}
|
||||
|
||||
std::uint64_t
|
||||
get_uint64() const noexcept
|
||||
{
|
||||
BOOST_ASSERT(is_uint64());
|
||||
return nat_.num_.get_uint64();
|
||||
}
|
||||
|
||||
double
|
||||
get_double() const noexcept
|
||||
{
|
||||
BOOST_ASSERT(is_double());
|
||||
return nat_.num_.get_double();
|
||||
}
|
||||
|
||||
bool&
|
||||
as_bool() noexcept
|
||||
{
|
||||
BOOST_ASSERT(is_bool());
|
||||
return nat_.bool_;
|
||||
}
|
||||
|
||||
bool const&
|
||||
as_bool() const noexcept
|
||||
{
|
||||
BOOST_ASSERT(is_bool());
|
||||
return nat_.bool_;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
//
|
||||
// Structured
|
||||
//
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
using key_type = beast::string_view;
|
||||
using mapped_type = value;
|
||||
using value_type = std::pair<key_type, value>;
|
||||
using size_type = std::size_t;
|
||||
using difference_type = std::ptrdiff_t;
|
||||
using reference = std::pair<key_type, value&>;
|
||||
using const_reference = std::pair<key_type, value const&>;
|
||||
class pointer;
|
||||
class const_pointer;
|
||||
class iterator;
|
||||
class const_iterator;
|
||||
using reverse_iterator =
|
||||
std::reverse_iterator<iterator>;
|
||||
using const_reverse_iterator =
|
||||
std::reverse_iterator<const_iterator>;
|
||||
|
||||
//
|
||||
// Capacity
|
||||
//
|
||||
|
||||
BOOST_BEAST_DECL
|
||||
bool
|
||||
empty() const;
|
||||
|
||||
BOOST_BEAST_DECL
|
||||
size_type
|
||||
size() const;
|
||||
|
||||
//
|
||||
// Iterators
|
||||
//
|
||||
|
||||
BOOST_BEAST_DECL
|
||||
iterator
|
||||
begin();
|
||||
|
||||
BOOST_BEAST_DECL
|
||||
const_iterator
|
||||
begin() const;
|
||||
|
||||
BOOST_BEAST_DECL
|
||||
const_iterator
|
||||
cbegin();
|
||||
|
||||
BOOST_BEAST_DECL
|
||||
iterator
|
||||
end();
|
||||
|
||||
BOOST_BEAST_DECL
|
||||
const_iterator
|
||||
end() const;
|
||||
|
||||
BOOST_BEAST_DECL
|
||||
const_iterator
|
||||
cend();
|
||||
|
||||
BOOST_BEAST_DECL
|
||||
reverse_iterator
|
||||
rbegin();
|
||||
|
||||
BOOST_BEAST_DECL
|
||||
const_reverse_iterator
|
||||
rbegin() const;
|
||||
|
||||
BOOST_BEAST_DECL
|
||||
const_reverse_iterator
|
||||
crbegin();
|
||||
|
||||
BOOST_BEAST_DECL
|
||||
reverse_iterator
|
||||
rend();
|
||||
|
||||
BOOST_BEAST_DECL
|
||||
const_reverse_iterator
|
||||
rend() const;
|
||||
|
||||
BOOST_BEAST_DECL
|
||||
const_reverse_iterator
|
||||
crend();
|
||||
|
||||
//
|
||||
// Lookup
|
||||
//
|
||||
|
||||
BOOST_BEAST_DECL
|
||||
value&
|
||||
at(key_type key);
|
||||
|
||||
BOOST_BEAST_DECL
|
||||
value const&
|
||||
at(key_type key) const;
|
||||
|
||||
BOOST_BEAST_DECL
|
||||
value&
|
||||
operator[](key_type key);
|
||||
|
||||
BOOST_BEAST_DECL
|
||||
value const&
|
||||
operator[](key_type key) const;
|
||||
|
||||
BOOST_BEAST_DECL
|
||||
size_type
|
||||
count(key_type key) const;
|
||||
|
||||
BOOST_BEAST_DECL
|
||||
iterator
|
||||
find(key_type key);
|
||||
|
||||
BOOST_BEAST_DECL
|
||||
const_iterator
|
||||
find(key_type key) const;
|
||||
|
||||
BOOST_BEAST_DECL
|
||||
bool
|
||||
contains(key_type key) const;
|
||||
|
||||
//
|
||||
// Elements
|
||||
//
|
||||
|
||||
BOOST_BEAST_DECL
|
||||
reference
|
||||
at(size_type pos);
|
||||
|
||||
BOOST_BEAST_DECL
|
||||
const_reference
|
||||
at(size_type pos) const;
|
||||
|
||||
BOOST_BEAST_DECL
|
||||
value&
|
||||
operator[](size_type i);
|
||||
|
||||
BOOST_BEAST_DECL
|
||||
value const&
|
||||
operator[](size_type i) const;
|
||||
|
||||
BOOST_BEAST_DECL
|
||||
reference
|
||||
front();
|
||||
|
||||
BOOST_BEAST_DECL
|
||||
const_reference
|
||||
front() const;
|
||||
|
||||
BOOST_BEAST_DECL
|
||||
reference
|
||||
back();
|
||||
|
||||
BOOST_BEAST_DECL
|
||||
const_reference
|
||||
back() const;
|
||||
|
||||
// Modifiers
|
||||
|
||||
BOOST_BEAST_DECL
|
||||
void
|
||||
clear() noexcept;
|
||||
|
||||
template<class M>
|
||||
std::pair<iterator, bool>
|
||||
insert_or_assign(
|
||||
key_type key, M&& obj);
|
||||
|
||||
template<class M>
|
||||
std::pair<iterator, bool>
|
||||
insert_or_assign(
|
||||
const_iterator before,
|
||||
key_type key,
|
||||
M&& obj);
|
||||
|
||||
template<class Arg>
|
||||
std::pair<iterator, bool>
|
||||
emplace(key_type key, Arg&& arg);
|
||||
|
||||
template<class Arg>
|
||||
std::pair<iterator, bool>
|
||||
emplace(
|
||||
const_iterator before,
|
||||
key_type key, Arg&& arg);
|
||||
|
||||
template<class Arg>
|
||||
iterator
|
||||
emplace(
|
||||
const_iterator before,
|
||||
Arg&& arg);
|
||||
|
||||
BOOST_BEAST_DECL
|
||||
size_type
|
||||
erase(key_type key);
|
||||
|
||||
BOOST_BEAST_DECL
|
||||
iterator
|
||||
erase(const_iterator pos);
|
||||
|
||||
BOOST_BEAST_DECL
|
||||
iterator
|
||||
erase(
|
||||
const_iterator first,
|
||||
const_iterator last);
|
||||
|
||||
template<class Arg>
|
||||
value&
|
||||
emplace_back(Arg&& arg);
|
||||
|
||||
BOOST_BEAST_DECL
|
||||
void
|
||||
pop_back();
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
private:
|
||||
BOOST_BEAST_DECL
|
||||
storage_ptr
|
||||
release_storage() noexcept;
|
||||
|
||||
BOOST_BEAST_DECL
|
||||
void
|
||||
construct(
|
||||
json::kind, storage_ptr) noexcept;
|
||||
|
||||
BOOST_BEAST_DECL
|
||||
void
|
||||
clear_impl() noexcept;
|
||||
|
||||
BOOST_BEAST_DECL
|
||||
void
|
||||
move(storage_ptr, value&&);
|
||||
|
||||
BOOST_BEAST_DECL
|
||||
void
|
||||
copy(storage_ptr, value const&);
|
||||
|
||||
BOOST_BEAST_DECL
|
||||
friend
|
||||
std::ostream&
|
||||
operator<<(
|
||||
std::ostream& os,
|
||||
value const& jv);
|
||||
};
|
||||
|
||||
} // json
|
||||
} // beast
|
||||
} // boost
|
||||
|
||||
#include <boost/json/impl/array.hpp>
|
||||
#include <boost/json/impl/object.hpp>
|
||||
#ifdef BOOST_BEAST_HEADER_ONLY
|
||||
#include <boost/json/impl/array.ipp>
|
||||
#include <boost/json/impl/object.ipp>
|
||||
#endif
|
||||
|
||||
// These must come after array and object
|
||||
#include <boost/json/impl/value.hpp>
|
||||
#ifdef BOOST_BEAST_HEADER_ONLY
|
||||
#include <boost/json/impl/value.ipp>
|
||||
#endif
|
||||
|
||||
#endif
|
||||
40
test/CMakeLists.txt
Normal file
40
test/CMakeLists.txt
Normal file
@@ -0,0 +1,40 @@
|
||||
#
|
||||
# Copyright (c) 2018-2019 Vinnie Falco (vinnie dot falco at gmail dot com)
|
||||
#
|
||||
# Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
# file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
#
|
||||
# Official repository: https://github.com/boostorg/json
|
||||
#
|
||||
|
||||
source_group (json FILES ${PROJECT_SOURCE_DIR}/include/boost/json.hpp)
|
||||
source_group (TREE ${PROJECT_SOURCE_DIR}/include/boost/json PREFIX json FILES ${PROJECT_FILES})
|
||||
|
||||
GroupSources(test "/")
|
||||
|
||||
add_executable (json-tests
|
||||
${BEAST_FILES}
|
||||
${PROJECT_FILES}
|
||||
Jamfile
|
||||
lib.cpp
|
||||
_detail_stack.cpp
|
||||
allocator.cpp
|
||||
array.cpp
|
||||
assign_string.cpp
|
||||
assign_vector.cpp
|
||||
basic_parser.cpp
|
||||
error.cpp
|
||||
iterator.cpp
|
||||
json.cpp
|
||||
kind.cpp
|
||||
number.cpp
|
||||
object.cpp
|
||||
parse_file.cpp
|
||||
parser.cpp
|
||||
serializer.cpp
|
||||
storage.cpp
|
||||
string.cpp
|
||||
value.cpp
|
||||
)
|
||||
|
||||
add_test(json-tests json-tests)
|
||||
51
test/Jamfile
Normal file
51
test/Jamfile
Normal file
@@ -0,0 +1,51 @@
|
||||
#
|
||||
# Copyright (c) 2013-2019 Vinnie Falco (vinnie dot falco at gmail dot com)
|
||||
#
|
||||
# Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
# file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
#
|
||||
# Official repository: https://github.com/boostorg/json
|
||||
#
|
||||
|
||||
local SOURCES =
|
||||
_detail_stack.cpp
|
||||
allocator.cpp
|
||||
array.cpp
|
||||
assign_string.cpp
|
||||
assign_vector.cpp
|
||||
basic_parser.cpp
|
||||
error.cpp
|
||||
iterator.cpp
|
||||
json.cpp
|
||||
kind.cpp
|
||||
number.cpp
|
||||
object.cpp
|
||||
parse_file.cpp
|
||||
parser.cpp
|
||||
serializer.cpp
|
||||
storage.cpp
|
||||
string.cpp
|
||||
value.cpp
|
||||
;
|
||||
|
||||
local RUN_TESTS ;
|
||||
|
||||
for local f in $(SOURCES)
|
||||
{
|
||||
RUN_TESTS += [ run $(f) lib.cpp ] ;
|
||||
}
|
||||
|
||||
alias run-tests : $(RUN_TESTS) ;
|
||||
|
||||
exe fat-tests :
|
||||
$(SOURCES)
|
||||
lib.cpp
|
||||
;
|
||||
|
||||
explicit fat-tests ;
|
||||
|
||||
run $(SOURCES)
|
||||
lib.cpp
|
||||
: : : : run-fat-tests ;
|
||||
|
||||
explicit run-fat-tests ;
|
||||
55
test/_detail_stack.cpp
Normal file
55
test/_detail_stack.cpp
Normal file
@@ -0,0 +1,55 @@
|
||||
//
|
||||
// Copyright (c) 2018-2019 Vinnie Falco (vinnie dot falco at gmail dot com)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
// Official repository: https://github.com/boostorg/json
|
||||
//
|
||||
|
||||
// Test that header file is self-contained.
|
||||
#include <boost/json/detail/stack.hpp>
|
||||
|
||||
#include <boost/beast/_experimental/unit_test/suite.hpp>
|
||||
#include <string>
|
||||
|
||||
namespace boost {
|
||||
namespace beast {
|
||||
namespace json {
|
||||
namespace detail {
|
||||
|
||||
class stack_test : public unit_test::suite
|
||||
{
|
||||
public:
|
||||
void
|
||||
testStack()
|
||||
{
|
||||
stack<std::string, 1> s;
|
||||
BEAST_EXPECT(s.empty());
|
||||
BEAST_EXPECT(s.capacity() > 0);
|
||||
BEAST_EXPECT(s.size() == 0);
|
||||
s.emplace_front("1");
|
||||
BEAST_EXPECT(s.size() == 1);
|
||||
BEAST_EXPECT(s[0] == "1");
|
||||
s.emplace_front("2");
|
||||
BEAST_EXPECT(s.size() == 2);
|
||||
BEAST_EXPECT(s[0] == "2");
|
||||
s.pop_front();
|
||||
BEAST_EXPECT(s.size() == 1);
|
||||
BEAST_EXPECT(s[0] == "1");
|
||||
s.pop_front();
|
||||
BEAST_EXPECT(s.empty());
|
||||
}
|
||||
|
||||
void run() override
|
||||
{
|
||||
testStack();
|
||||
}
|
||||
};
|
||||
|
||||
BEAST_DEFINE_TESTSUITE(beast,json,stack);
|
||||
|
||||
} // detail
|
||||
} // json
|
||||
} // beast
|
||||
} // boost
|
||||
51
test/allocator.cpp
Normal file
51
test/allocator.cpp
Normal file
@@ -0,0 +1,51 @@
|
||||
//
|
||||
// Copyright (c) 2018-2019 Vinnie Falco (vinnie dot falco at gmail dot com)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
// Official repository: https://github.com/vinniefalco/BeastLounge
|
||||
//
|
||||
|
||||
// Test that header file is self-contained.
|
||||
#include <boost/json/allocator.hpp>
|
||||
|
||||
#include <boost/beast/_experimental/unit_test/suite.hpp>
|
||||
#include <vector>
|
||||
|
||||
namespace boost {
|
||||
namespace beast {
|
||||
namespace json {
|
||||
|
||||
class allocator_test : public unit_test::suite
|
||||
{
|
||||
public:
|
||||
void
|
||||
testAllocator()
|
||||
{
|
||||
auto a1 = make_storage_ptr(
|
||||
std::allocator<void>{});
|
||||
auto a2 = a1;
|
||||
auto a3 = std::move(a2);
|
||||
a2 = a1;
|
||||
a3 = std::move(a2);
|
||||
|
||||
std::vector<char, allocator<char>> v(
|
||||
allocator<char>(make_storage_ptr(
|
||||
std::allocator<void>{})));
|
||||
v.resize(100);
|
||||
BEAST_EXPECT(v.capacity() >= 100);
|
||||
}
|
||||
|
||||
void
|
||||
run()
|
||||
{
|
||||
testAllocator();
|
||||
}
|
||||
};
|
||||
|
||||
BEAST_DEFINE_TESTSUITE(beast,json,allocator);
|
||||
|
||||
} // json
|
||||
} // beast
|
||||
} // boost
|
||||
832
test/array.cpp
Normal file
832
test/array.cpp
Normal file
@@ -0,0 +1,832 @@
|
||||
//
|
||||
// Copyright (c) 2018-2019 Vinnie Falco (vinnie dot falco at gmail dot com)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
// Official repository: https://github.com/vinniefalco/BeastLounge
|
||||
//
|
||||
|
||||
// Test that header file is self-contained.
|
||||
#include <boost/json/array.hpp>
|
||||
|
||||
#include <boost/beast/_experimental/unit_test/suite.hpp>
|
||||
|
||||
namespace boost {
|
||||
namespace beast {
|
||||
namespace json {
|
||||
|
||||
class array_test : public unit_test::suite
|
||||
{
|
||||
public:
|
||||
struct unique_storage : storage
|
||||
{
|
||||
void
|
||||
addref() noexcept override
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
release() noexcept override
|
||||
{
|
||||
}
|
||||
|
||||
void*
|
||||
allocate(
|
||||
std::size_t n,
|
||||
std::size_t) override
|
||||
{
|
||||
return std::allocator<
|
||||
char>{}.allocate(n);
|
||||
}
|
||||
|
||||
void
|
||||
deallocate(
|
||||
void* p,
|
||||
std::size_t n,
|
||||
std::size_t) noexcept override
|
||||
{
|
||||
auto cp =
|
||||
reinterpret_cast<char*>(p);
|
||||
return std::allocator<
|
||||
char>{}.deallocate(cp, n);
|
||||
}
|
||||
bool
|
||||
is_equal(
|
||||
storage const& other
|
||||
) const noexcept override
|
||||
{
|
||||
auto p = dynamic_cast<
|
||||
unique_storage const*>(&other);
|
||||
if(! p)
|
||||
return false;
|
||||
return this == p;
|
||||
}
|
||||
};
|
||||
|
||||
struct fail_storage : storage
|
||||
{
|
||||
std::size_t fail_max = 1;
|
||||
std::size_t fail = 0;
|
||||
|
||||
void
|
||||
addref() noexcept override
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
release() noexcept override
|
||||
{
|
||||
}
|
||||
|
||||
void*
|
||||
allocate(
|
||||
std::size_t n,
|
||||
std::size_t) override
|
||||
{
|
||||
if(++fail == fail_max)
|
||||
{
|
||||
++fail_max;
|
||||
fail = 0;
|
||||
throw std::bad_alloc{};
|
||||
}
|
||||
return std::allocator<
|
||||
char>{}.allocate(n);
|
||||
}
|
||||
|
||||
void
|
||||
deallocate(
|
||||
void* p,
|
||||
std::size_t n,
|
||||
std::size_t) noexcept override
|
||||
{
|
||||
auto cp =
|
||||
reinterpret_cast<char*>(p);
|
||||
return std::allocator<
|
||||
char>{}.deallocate(cp, n);
|
||||
}
|
||||
bool
|
||||
is_equal(
|
||||
storage const& other
|
||||
) const noexcept override
|
||||
{
|
||||
auto p = dynamic_cast<
|
||||
fail_storage const*>(&other);
|
||||
if(! p)
|
||||
return false;
|
||||
return this == p;
|
||||
}
|
||||
};
|
||||
|
||||
void
|
||||
check(array const& arr)
|
||||
{
|
||||
BEAST_EXPECT(arr.size() == 3);
|
||||
BEAST_EXPECT(arr[0].is_number());
|
||||
BEAST_EXPECT(arr[1].is_bool());
|
||||
BEAST_EXPECT(arr[2].is_string());
|
||||
}
|
||||
|
||||
void
|
||||
check(
|
||||
array const& arr,
|
||||
storage_ptr const& sp)
|
||||
{
|
||||
check(arr);
|
||||
BEAST_EXPECT(arr.get_storage() == sp);
|
||||
BEAST_EXPECT(arr[0].get_storage() == sp);
|
||||
BEAST_EXPECT(arr[1].get_storage() == sp);
|
||||
BEAST_EXPECT(arr[2].get_storage() == sp);
|
||||
}
|
||||
|
||||
void
|
||||
testSpecial()
|
||||
{
|
||||
unique_storage us;
|
||||
storage_ptr sp(&us);
|
||||
storage_ptr sp0 =
|
||||
default_storage();
|
||||
BEAST_EXPECT(*sp != *sp0);
|
||||
|
||||
// array()
|
||||
{
|
||||
array arr;
|
||||
BEAST_EXPECT(arr.empty());
|
||||
BEAST_EXPECT(arr.size() == 0);
|
||||
}
|
||||
|
||||
// array(storage)
|
||||
{
|
||||
array arr(sp);
|
||||
BEAST_EXPECT(arr.get_storage() == sp);
|
||||
BEAST_EXPECT(arr.get_storage() != sp0);
|
||||
}
|
||||
|
||||
// array(size_type)
|
||||
{
|
||||
array arr(3);
|
||||
BEAST_EXPECT(arr.size() == 3);
|
||||
for(auto const& v : arr)
|
||||
BEAST_EXPECT(v.is_null());
|
||||
}
|
||||
|
||||
// array(size_type, storage)
|
||||
{
|
||||
array arr(3, sp);
|
||||
BEAST_EXPECT(arr.size() == 3);
|
||||
for(auto const& v : arr)
|
||||
BEAST_EXPECT(v.get_storage() == sp);
|
||||
}
|
||||
|
||||
// array(size_type, value)
|
||||
{
|
||||
array arr(3, kind::boolean);
|
||||
BEAST_EXPECT(arr.size() == 3);
|
||||
for(auto const& v : arr)
|
||||
BEAST_EXPECT(v.is_bool());
|
||||
}
|
||||
|
||||
// array(size_type, value, storage)
|
||||
{
|
||||
array arr(3, kind::boolean, sp);
|
||||
BEAST_EXPECT(arr.size() == 3);
|
||||
for(auto const& v : arr)
|
||||
BEAST_EXPECT(v.get_storage() == sp);
|
||||
}
|
||||
|
||||
// array(InputIt, InputIt)
|
||||
{
|
||||
std::initializer_list<value> list =
|
||||
{ 1, true, "hello" };
|
||||
array arr(list.begin(), list.end());
|
||||
check(arr, sp0);
|
||||
}
|
||||
|
||||
// array(InputIt, InputIt, storage)
|
||||
{
|
||||
std::initializer_list<value> list =
|
||||
{ 1, true, "hello" };
|
||||
array arr(list.begin(), list.end(), sp);
|
||||
check(arr, sp);
|
||||
}
|
||||
|
||||
// array(array const&)
|
||||
{
|
||||
std::initializer_list<value> list =
|
||||
{ 1, true, "hello" };
|
||||
array arr1(list.begin(), list.end(), sp);
|
||||
array arr2 = arr1;
|
||||
check(arr2, sp);
|
||||
}
|
||||
|
||||
// array(array const&, storage)
|
||||
{
|
||||
std::initializer_list<value> list =
|
||||
{ 1, true, "hello" };
|
||||
array arr1(list.begin(), list.end());
|
||||
array arr2(arr1, sp);
|
||||
BEAST_EXPECT(arr2.size() == 3);
|
||||
BEAST_EXPECT(
|
||||
arr1[0].get_storage() !=
|
||||
arr2[0].get_storage());
|
||||
BEAST_EXPECT(
|
||||
arr1[1].get_storage() !=
|
||||
arr2[1].get_storage());
|
||||
BEAST_EXPECT(
|
||||
arr1[2].get_storage() !=
|
||||
arr2[2].get_storage());
|
||||
}
|
||||
|
||||
// array(array&&)
|
||||
{
|
||||
std::initializer_list<value> list =
|
||||
{ 1, true, "hello" };
|
||||
array arr1(list.begin(), list.end(), sp);
|
||||
array arr2 = std::move(arr1);
|
||||
BEAST_EXPECT(arr1.empty());
|
||||
BEAST_EXPECT(
|
||||
arr1.get_storage() ==
|
||||
arr2.get_storage());
|
||||
check(arr2, sp);
|
||||
}
|
||||
|
||||
// array(array&&, storage)
|
||||
{
|
||||
std::initializer_list<value> list =
|
||||
{ 1, true, "hello" };
|
||||
array arr1(list.begin(), list.end());
|
||||
array arr2(std::move(arr1), sp);
|
||||
BEAST_EXPECT(! arr1.empty());
|
||||
BEAST_EXPECT(
|
||||
arr1.get_storage() !=
|
||||
arr2.get_storage());
|
||||
check(arr2, sp);
|
||||
}
|
||||
|
||||
// array(init_list)
|
||||
{
|
||||
array arr({1, true, "hello"});
|
||||
check(arr, sp0);
|
||||
}
|
||||
|
||||
// array(init_list, storage)
|
||||
{
|
||||
array arr({1, true, "hello"}, sp);
|
||||
check(arr, sp);
|
||||
}
|
||||
|
||||
// operator=(array&&)
|
||||
{
|
||||
{
|
||||
array arr1({1, true, "hello"});
|
||||
array arr2({nullptr, kind::object, 1.f});
|
||||
arr2 = std::move(arr1);
|
||||
BEAST_EXPECT(arr1.empty());
|
||||
BEAST_EXPECT(
|
||||
arr1.get_storage() ==
|
||||
arr2.get_storage());
|
||||
check(arr2, sp0);
|
||||
}
|
||||
{
|
||||
array arr1({1, true, "hello"});
|
||||
array arr2({nullptr, kind::object, 1.f}, sp);
|
||||
arr2 = std::move(arr1);
|
||||
BEAST_EXPECT(! arr1.empty());
|
||||
BEAST_EXPECT(
|
||||
arr1.get_storage() !=
|
||||
arr2.get_storage());
|
||||
check(arr2, sp);
|
||||
}
|
||||
}
|
||||
|
||||
// operator=(array const&)
|
||||
{
|
||||
{
|
||||
array arr1({1, true, "hello"});
|
||||
array arr2({nullptr, kind::object, 1.f});
|
||||
arr2 = arr1;
|
||||
BEAST_EXPECT(! arr1.empty());
|
||||
check(arr2, sp0);
|
||||
}
|
||||
{
|
||||
array arr1({1, true, "hello"});
|
||||
array arr2({nullptr, kind::object, 1.f}, sp);
|
||||
arr2 = arr1;
|
||||
BEAST_EXPECT(! arr1.empty());
|
||||
BEAST_EXPECT(
|
||||
arr1.get_storage() !=
|
||||
arr2.get_storage());
|
||||
check(arr2, sp);
|
||||
}
|
||||
}
|
||||
|
||||
// operator=(init_list)
|
||||
{
|
||||
{
|
||||
std::initializer_list<value> list =
|
||||
{ 1, true, "hello" };
|
||||
array arr({nullptr, kind::object, 1.f});
|
||||
arr = list;
|
||||
check(arr, sp0);
|
||||
}
|
||||
{
|
||||
std::initializer_list<value> list =
|
||||
{ 1, true, "hello" };
|
||||
array arr({nullptr, kind::object, 1.f}, sp);
|
||||
arr = list;
|
||||
check(arr, sp);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
testElements()
|
||||
{
|
||||
// at(pos)
|
||||
{
|
||||
array arr({1, true, "hello"});
|
||||
BEAST_EXPECT(arr.at(0).is_number());
|
||||
BEAST_EXPECT(arr.at(1).is_bool());
|
||||
BEAST_EXPECT(arr.at(2).is_string());
|
||||
try
|
||||
{
|
||||
arr.at(3);
|
||||
BEAST_FAIL();
|
||||
}
|
||||
catch(std::out_of_range const&)
|
||||
{
|
||||
BEAST_PASS();
|
||||
}
|
||||
}
|
||||
|
||||
// at(pos) const
|
||||
{
|
||||
array const arr({1, true, "hello"});
|
||||
BEAST_EXPECT(arr.at(0).is_number());
|
||||
BEAST_EXPECT(arr.at(1).is_bool());
|
||||
BEAST_EXPECT(arr.at(2).is_string());
|
||||
try
|
||||
{
|
||||
arr.at(3);
|
||||
BEAST_FAIL();
|
||||
}
|
||||
catch(std::out_of_range const&)
|
||||
{
|
||||
BEAST_PASS();
|
||||
}
|
||||
}
|
||||
|
||||
// operator[](size_type)
|
||||
{
|
||||
array arr({1, true, "hello"});
|
||||
BEAST_EXPECT(arr[0].is_number());
|
||||
BEAST_EXPECT(arr[1].is_bool());
|
||||
BEAST_EXPECT(arr[2].is_string());
|
||||
}
|
||||
|
||||
// operator[](size_type) const
|
||||
{
|
||||
array const arr({1, true, "hello"});
|
||||
BEAST_EXPECT(arr[0].is_number());
|
||||
BEAST_EXPECT(arr[1].is_bool());
|
||||
BEAST_EXPECT(arr[2].is_string());
|
||||
}
|
||||
|
||||
// front()
|
||||
{
|
||||
array arr({1, true, "hello"});
|
||||
BEAST_EXPECT(arr.front().is_number());
|
||||
}
|
||||
|
||||
// front() const
|
||||
{
|
||||
array const arr({1, true, "hello"});
|
||||
BEAST_EXPECT(arr.front().is_number());
|
||||
}
|
||||
|
||||
// back()
|
||||
{
|
||||
array arr({1, true, "hello"});
|
||||
BEAST_EXPECT(arr.back().is_string());
|
||||
}
|
||||
|
||||
// back() const
|
||||
{
|
||||
array const arr({1, true, "hello"});
|
||||
BEAST_EXPECT(arr.back().is_string());
|
||||
}
|
||||
|
||||
// data()
|
||||
{
|
||||
array arr({1, true, "hello"});
|
||||
BEAST_EXPECT(arr.data() == &arr[0]);
|
||||
}
|
||||
|
||||
// data() const
|
||||
{
|
||||
array const arr({1, true, "hello"});
|
||||
BEAST_EXPECT(arr.data() == &arr[0]);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
testIterators()
|
||||
{
|
||||
array arr({1, true, "hello"});
|
||||
auto const& ac(arr);
|
||||
{
|
||||
auto it = arr.begin();
|
||||
BEAST_EXPECT(it->is_number()); ++it;
|
||||
BEAST_EXPECT(it->is_bool()); it++;
|
||||
BEAST_EXPECT(it->is_string()); ++it;
|
||||
BEAST_EXPECT(it == arr.end());
|
||||
}
|
||||
{
|
||||
auto it = arr.cbegin();
|
||||
BEAST_EXPECT(it->is_number()); ++it;
|
||||
BEAST_EXPECT(it->is_bool()); it++;
|
||||
BEAST_EXPECT(it->is_string()); ++it;
|
||||
BEAST_EXPECT(it == arr.cend());
|
||||
}
|
||||
{
|
||||
auto it = ac.begin();
|
||||
BEAST_EXPECT(it->is_number()); ++it;
|
||||
BEAST_EXPECT(it->is_bool()); it++;
|
||||
BEAST_EXPECT(it->is_string()); ++it;
|
||||
BEAST_EXPECT(it == ac.end());
|
||||
}
|
||||
{
|
||||
auto it = arr.end();
|
||||
--it; BEAST_EXPECT(it->is_string());
|
||||
it--; BEAST_EXPECT(it->is_bool());
|
||||
--it; BEAST_EXPECT(it->is_number());
|
||||
BEAST_EXPECT(it == arr.begin());
|
||||
}
|
||||
{
|
||||
auto it = arr.cend();
|
||||
--it; BEAST_EXPECT(it->is_string());
|
||||
it--; BEAST_EXPECT(it->is_bool());
|
||||
--it; BEAST_EXPECT(it->is_number());
|
||||
BEAST_EXPECT(it == arr.cbegin());
|
||||
}
|
||||
{
|
||||
auto it = ac.end();
|
||||
--it; BEAST_EXPECT(it->is_string());
|
||||
it--; BEAST_EXPECT(it->is_bool());
|
||||
--it; BEAST_EXPECT(it->is_number());
|
||||
BEAST_EXPECT(it == ac.begin());
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
testCapacity()
|
||||
{
|
||||
// empty()
|
||||
{
|
||||
array arr;
|
||||
BEAST_EXPECT(arr.empty());
|
||||
arr.emplace_back(1);
|
||||
BEAST_EXPECT(! arr.empty());
|
||||
}
|
||||
|
||||
// size()
|
||||
{
|
||||
array arr;
|
||||
BEAST_EXPECT(arr.size() == 0);
|
||||
arr.emplace_back(1);
|
||||
BEAST_EXPECT(arr.size() == 1);
|
||||
}
|
||||
|
||||
// max_size()
|
||||
{
|
||||
array arr;
|
||||
BEAST_EXPECT(arr.max_size() > 0);
|
||||
}
|
||||
|
||||
// reserve()
|
||||
{
|
||||
array arr;
|
||||
arr.reserve(50);
|
||||
BEAST_EXPECT(arr.capacity() >= 50);
|
||||
}
|
||||
|
||||
// capacity()
|
||||
{
|
||||
array arr;
|
||||
BEAST_EXPECT(arr.capacity() == 0);
|
||||
}
|
||||
|
||||
// shrink_to_fit()
|
||||
{
|
||||
array arr;
|
||||
arr.reserve(50);
|
||||
BEAST_EXPECT(arr.capacity() >= 50);
|
||||
arr.shrink_to_fit();
|
||||
BEAST_EXPECT(arr.capacity() == 0);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
testModifiers()
|
||||
{
|
||||
// clear
|
||||
{
|
||||
array arr({1, true, "hello"});
|
||||
arr.clear();
|
||||
BEAST_EXPECT(arr.capacity() > 0);
|
||||
}
|
||||
|
||||
// insert(before, value_type const&)
|
||||
{
|
||||
array arr({1, "hello"});
|
||||
value v(true);
|
||||
arr.insert(arr.begin() + 1, v);
|
||||
check(arr);
|
||||
}
|
||||
|
||||
// insert(before, value_type const&)
|
||||
{
|
||||
array arr({1, "hello"});
|
||||
arr.insert(arr.begin() + 1, true);
|
||||
check(arr);
|
||||
}
|
||||
// insert(before, size_type, value_type const&)
|
||||
{
|
||||
array arr({1, "hello"});
|
||||
arr.insert(arr.begin() + 1, 3, true);
|
||||
BEAST_EXPECT(arr[0].is_number());
|
||||
BEAST_EXPECT(arr[1].is_bool());
|
||||
BEAST_EXPECT(arr[2].is_bool());
|
||||
BEAST_EXPECT(arr[3].is_bool());
|
||||
BEAST_EXPECT(arr[4].is_string());
|
||||
}
|
||||
|
||||
// insert(before, InputIt, InputIt)
|
||||
{
|
||||
std::initializer_list<
|
||||
value> list = {1, true};
|
||||
array arr({"hello"});
|
||||
arr.insert(arr.begin(),
|
||||
list.begin(), list.end());
|
||||
check(arr);
|
||||
}
|
||||
|
||||
// insert(before, init_list)
|
||||
{
|
||||
array arr({"hello"});
|
||||
arr.insert(arr.begin(), {1, true});
|
||||
check(arr);
|
||||
}
|
||||
|
||||
// emplace(before, arg)
|
||||
{
|
||||
array arr({1, "hello"});
|
||||
auto it = arr.emplace(
|
||||
arr.begin() + 1, true);
|
||||
BEAST_EXPECT(it == arr.begin() + 1);
|
||||
check(arr);
|
||||
}
|
||||
|
||||
// erase(pos)
|
||||
{
|
||||
array arr({1, true, nullptr, "hello"});
|
||||
arr.erase(arr.begin() + 2);
|
||||
check(arr);
|
||||
}
|
||||
|
||||
// push_back(value const&)
|
||||
{
|
||||
array arr({1, true});
|
||||
value v("hello");
|
||||
arr.push_back(v);
|
||||
BEAST_EXPECT(
|
||||
v.as_string() == "hello");
|
||||
check(arr);
|
||||
}
|
||||
|
||||
// push_back(value&&)
|
||||
{
|
||||
array arr({1, true});
|
||||
value v("hello");
|
||||
arr.push_back(std::move(v));
|
||||
BEAST_EXPECT(v.is_null());
|
||||
check(arr);
|
||||
}
|
||||
|
||||
// emplace_back(arg)
|
||||
{
|
||||
array arr({1, true});
|
||||
arr.emplace_back("hello");
|
||||
check(arr);
|
||||
}
|
||||
|
||||
// pop_back()
|
||||
{
|
||||
array arr({1, true, "hello", nullptr});
|
||||
arr.pop_back();
|
||||
check(arr);
|
||||
}
|
||||
|
||||
// resize(size_type)
|
||||
{
|
||||
array arr;
|
||||
arr.resize(3);
|
||||
BEAST_EXPECT(arr.size() == 3);
|
||||
BEAST_EXPECT(arr[0].is_null());
|
||||
BEAST_EXPECT(arr[1].is_null());
|
||||
BEAST_EXPECT(arr[2].is_null());
|
||||
}
|
||||
|
||||
// resize(size_type, value_type const&)
|
||||
{
|
||||
array arr;
|
||||
value v(kind::boolean);
|
||||
arr.resize(3, v);
|
||||
BEAST_EXPECT(arr.size() == 3);
|
||||
BEAST_EXPECT(arr[0].is_bool());
|
||||
BEAST_EXPECT(arr[1].is_bool());
|
||||
BEAST_EXPECT(arr[2].is_bool());
|
||||
}
|
||||
|
||||
// swap
|
||||
{
|
||||
array arr1({1, true, "hello"});
|
||||
array arr2;
|
||||
arr1.swap(arr2);
|
||||
check(arr2);
|
||||
BEAST_EXPECT(arr1.empty());
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
testExceptions()
|
||||
{
|
||||
// operator=(array const&)
|
||||
{
|
||||
array arr0({1, true, "hello"});
|
||||
fail_storage fs;
|
||||
storage_ptr sp(&fs);
|
||||
array arr1;
|
||||
while(fs.fail < 200)
|
||||
{
|
||||
try
|
||||
{
|
||||
array arr(sp);
|
||||
arr.emplace_back(nullptr);
|
||||
arr = arr0;
|
||||
arr1 = arr;
|
||||
break;
|
||||
}
|
||||
catch(std::bad_alloc const&)
|
||||
{
|
||||
}
|
||||
}
|
||||
check(arr1);
|
||||
}
|
||||
|
||||
// operator=(init_list)
|
||||
{
|
||||
std::initializer_list<value> list(
|
||||
{1, true, "hello"});
|
||||
fail_storage fs;
|
||||
storage_ptr sp(&fs);
|
||||
array arr1;
|
||||
while(fs.fail < 200)
|
||||
{
|
||||
try
|
||||
{
|
||||
array arr(sp);
|
||||
arr.emplace_back(nullptr);
|
||||
arr = list;
|
||||
arr1 = arr;
|
||||
break;
|
||||
}
|
||||
catch(std::bad_alloc const&)
|
||||
{
|
||||
}
|
||||
}
|
||||
check(arr1);
|
||||
}
|
||||
|
||||
// insert(before, count, value_type const&)
|
||||
{
|
||||
fail_storage fs;
|
||||
storage_ptr sp(&fs);
|
||||
array arr1;
|
||||
while(fs.fail < 200)
|
||||
{
|
||||
try
|
||||
{
|
||||
array arr({1, true}, sp);
|
||||
arr.insert(arr.begin() + 1,
|
||||
3, kind::null);
|
||||
arr1 = arr;
|
||||
break;
|
||||
}
|
||||
catch(std::bad_alloc const&)
|
||||
{
|
||||
}
|
||||
}
|
||||
BEAST_EXPECT(arr1.size() == 5);
|
||||
BEAST_EXPECT(arr1[0].is_number());
|
||||
BEAST_EXPECT(arr1[1].is_null());
|
||||
BEAST_EXPECT(arr1[2].is_null());
|
||||
BEAST_EXPECT(arr1[3].is_null());
|
||||
BEAST_EXPECT(arr1[4].is_bool());
|
||||
}
|
||||
|
||||
#if _ITERATOR_DEBUG_LEVEL == 0
|
||||
// insert(before, InputIt, InputIt)
|
||||
{
|
||||
std::initializer_list<value> list(
|
||||
{1, true, "hello"});
|
||||
fail_storage fs;
|
||||
storage_ptr sp(&fs);
|
||||
array arr1;
|
||||
while(fs.fail < 200)
|
||||
{
|
||||
try
|
||||
{
|
||||
array arr(sp);
|
||||
arr.insert(arr.end(),
|
||||
list.begin(), list.end());
|
||||
arr1 = arr;
|
||||
break;
|
||||
}
|
||||
catch(std::bad_alloc const&)
|
||||
{
|
||||
}
|
||||
}
|
||||
check(arr1);
|
||||
}
|
||||
#endif
|
||||
|
||||
// emplace(before, arg)
|
||||
{
|
||||
fail_storage fs;
|
||||
storage_ptr sp(&fs);
|
||||
array arr1;
|
||||
while(fs.fail < 200)
|
||||
{
|
||||
try
|
||||
{
|
||||
array arr({1, nullptr}, sp);
|
||||
arr.emplace(arr.begin() + 1, true);
|
||||
arr1 = arr;
|
||||
break;
|
||||
}
|
||||
catch(std::bad_alloc const&)
|
||||
{
|
||||
}
|
||||
}
|
||||
BEAST_EXPECT(arr1.size() == 3);
|
||||
BEAST_EXPECT(arr1[0].is_number());
|
||||
BEAST_EXPECT(arr1[1].is_bool());
|
||||
BEAST_EXPECT(arr1[2].is_null());
|
||||
}
|
||||
|
||||
#if _ITERATOR_DEBUG_LEVEL == 0
|
||||
// emplace(before, arg)
|
||||
{
|
||||
fail_storage fs;
|
||||
storage_ptr sp(&fs);
|
||||
array arr1;
|
||||
while(fs.fail < 200)
|
||||
{
|
||||
try
|
||||
{
|
||||
array arr({1, "hello"}, sp);
|
||||
arr.emplace(arr.begin() + 1, true);
|
||||
arr1 = arr;
|
||||
break;
|
||||
}
|
||||
catch(std::bad_alloc const&)
|
||||
{
|
||||
}
|
||||
}
|
||||
check(arr1);
|
||||
BEAST_EXPECT(arr1.size() == 3);
|
||||
BEAST_EXPECT(arr1[0].is_number());
|
||||
BEAST_EXPECT(arr1[1].is_bool());
|
||||
BEAST_EXPECT(arr1[2].is_string());
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
run() override
|
||||
{
|
||||
testSpecial();
|
||||
testElements();
|
||||
testIterators();
|
||||
testCapacity();
|
||||
testModifiers();
|
||||
testExceptions();
|
||||
}
|
||||
};
|
||||
|
||||
BEAST_DEFINE_TESTSUITE(beast,json,array);
|
||||
|
||||
} // json
|
||||
} // beast
|
||||
} // boost
|
||||
49
test/assign_string.cpp
Normal file
49
test/assign_string.cpp
Normal file
@@ -0,0 +1,49 @@
|
||||
//
|
||||
// Copyright (c) 2018-2019 Vinnie Falco (vinnie dot falco at gmail dot com)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
// Official repository: https://github.com/boostorg/json
|
||||
//
|
||||
|
||||
// Test that header file is self-contained.
|
||||
#include <boost/json/assign_string.hpp>
|
||||
|
||||
#include <boost/beast/_experimental/unit_test/suite.hpp>
|
||||
#include <type_traits>
|
||||
|
||||
namespace boost {
|
||||
namespace beast {
|
||||
namespace json {
|
||||
|
||||
class assign_string_test : public unit_test::suite
|
||||
{
|
||||
public:
|
||||
void
|
||||
testAssign()
|
||||
{
|
||||
value jv = "test";
|
||||
std::string s;
|
||||
try
|
||||
{
|
||||
jv.store(s);
|
||||
BEAST_EXPECT(s == "test");
|
||||
}
|
||||
catch(std::exception const&)
|
||||
{
|
||||
BEAST_FAIL();
|
||||
}
|
||||
}
|
||||
|
||||
void run() override
|
||||
{
|
||||
testAssign();
|
||||
}
|
||||
};
|
||||
|
||||
BEAST_DEFINE_TESTSUITE(beast,json,assign_string);
|
||||
|
||||
} // json
|
||||
} // beast
|
||||
} // boost
|
||||
58
test/assign_vector.cpp
Normal file
58
test/assign_vector.cpp
Normal file
@@ -0,0 +1,58 @@
|
||||
//
|
||||
// Copyright (c) 2018-2019 Vinnie Falco (vinnie dot falco at gmail dot com)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
// Official repository: https://github.com/boostorg/json
|
||||
//
|
||||
|
||||
// Test that header file is self-contained.
|
||||
#include <boost/json/assign_vector.hpp>
|
||||
|
||||
#include <boost/beast/_experimental/unit_test/suite.hpp>
|
||||
#include <type_traits>
|
||||
|
||||
namespace boost {
|
||||
namespace beast {
|
||||
namespace json {
|
||||
|
||||
class assign_vector_test : public unit_test::suite
|
||||
{
|
||||
public:
|
||||
void
|
||||
testAssign()
|
||||
{
|
||||
value jv(kind::array);
|
||||
{
|
||||
auto& a = jv.as_array();
|
||||
a.push_back(1);
|
||||
a.push_back(2);
|
||||
a.push_back(3);
|
||||
}
|
||||
std::vector<int> v;
|
||||
try
|
||||
{
|
||||
jv.store(v);
|
||||
BEAST_EXPECT(v.size() == 3);
|
||||
BEAST_EXPECT(v[0] == 1);
|
||||
BEAST_EXPECT(v[1] == 2);
|
||||
BEAST_EXPECT(v[2] == 3);
|
||||
}
|
||||
catch(std::exception const&)
|
||||
{
|
||||
BEAST_FAIL();
|
||||
}
|
||||
}
|
||||
|
||||
void run() override
|
||||
{
|
||||
testAssign();
|
||||
}
|
||||
};
|
||||
|
||||
BEAST_DEFINE_TESTSUITE(beast,json,assign_vector);
|
||||
|
||||
} // json
|
||||
} // beast
|
||||
} // boost
|
||||
322
test/basic_parser.cpp
Normal file
322
test/basic_parser.cpp
Normal file
@@ -0,0 +1,322 @@
|
||||
//
|
||||
// Copyright (c) 2018-2019 Vinnie Falco (vinnie dot falco at gmail dot com)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
// Official repository: https://github.com/boostorg/json
|
||||
//
|
||||
|
||||
// Test that header file is self-contained.
|
||||
#include <boost/json/basic_parser.hpp>
|
||||
|
||||
#include <boost/beast/_experimental/unit_test/suite.hpp>
|
||||
|
||||
#include <boost/beast/core/buffers_range.hpp>
|
||||
#include <boost/beast/core/error.hpp>
|
||||
#include <boost/beast/core/string.hpp>
|
||||
#include <boost/asio/buffer.hpp>
|
||||
|
||||
namespace boost {
|
||||
namespace beast {
|
||||
namespace json {
|
||||
|
||||
class basic_parser_test : public beast::unit_test::suite
|
||||
{
|
||||
public:
|
||||
struct test_parser
|
||||
: basic_parser
|
||||
{
|
||||
test_parser() = default;
|
||||
|
||||
void
|
||||
on_document_begin(
|
||||
error_code&) override
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
on_object_begin(
|
||||
error_code&) override
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
on_object_end(
|
||||
error_code&) override
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
on_array_begin(
|
||||
error_code&) override
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
on_array_end(
|
||||
error_code&) override
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
on_key_data(
|
||||
string_view,
|
||||
error_code&) override
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
on_key_end(
|
||||
string_view,
|
||||
error_code&) override
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
on_string_data(
|
||||
string_view,
|
||||
error_code&) override
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
on_string_end(
|
||||
string_view,
|
||||
error_code&) override
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
on_number(
|
||||
number,
|
||||
error_code&) override
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
on_bool(
|
||||
bool,
|
||||
error_code&) override
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
on_null(error_code&) override
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
void
|
||||
good(string_view s)
|
||||
{
|
||||
error_code ec;
|
||||
for(std::size_t i = 0;
|
||||
i < s.size() - 1; ++i)
|
||||
{
|
||||
// write_some with 1 buffer
|
||||
{
|
||||
test_parser p;
|
||||
auto used = p.write_some(
|
||||
net::const_buffer(s.data(), i), ec);
|
||||
BEAST_EXPECT(used == i);
|
||||
BEAST_EXPECT(! p.is_done());
|
||||
if(! BEAST_EXPECTS(! ec, ec.message()))
|
||||
continue;
|
||||
used = p.write_some(net::const_buffer(
|
||||
s.data() + i, s.size() - i), ec);
|
||||
BEAST_EXPECT(used == s.size() - i);
|
||||
if(! BEAST_EXPECTS(! ec, ec.message()))
|
||||
continue;
|
||||
p.write({}, ec);
|
||||
BEAST_EXPECTS(! ec, ec.message());
|
||||
BEAST_EXPECT(p.is_done());
|
||||
}
|
||||
// write_some with 1 buffer sequence
|
||||
{
|
||||
test_parser p;
|
||||
std::array<
|
||||
net::const_buffer, 2> b;
|
||||
b[0] = {s.data(), i};
|
||||
b[1] = {s.data()+i, s.size()-i};
|
||||
auto used = p.write_some(b, ec);
|
||||
BEAST_EXPECT(used = s.size());
|
||||
BEAST_EXPECTS(! ec, ec.message());
|
||||
p.write({}, ec);
|
||||
BEAST_EXPECTS(! ec, ec.message());
|
||||
}
|
||||
// write with 1 buffer sequence
|
||||
{
|
||||
test_parser p;
|
||||
std::array<
|
||||
net::const_buffer, 2> b;
|
||||
b[0] = {s.data(), i};
|
||||
b[1] = {s.data()+i, s.size()-i};
|
||||
auto used = p.write(b, ec);
|
||||
BEAST_EXPECT(used = s.size());
|
||||
BEAST_EXPECTS(! ec, ec.message());
|
||||
}
|
||||
// write with 1 buffer
|
||||
{
|
||||
test_parser p;
|
||||
auto used = p.write(
|
||||
{s.data(), s.size()}, ec);
|
||||
BEAST_EXPECT(used = s.size());
|
||||
BEAST_EXPECTS(! ec, ec.message());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
bad(string_view s)
|
||||
{
|
||||
error_code ec;
|
||||
test_parser p;
|
||||
auto const used = p.write_some(
|
||||
boost::asio::const_buffer(
|
||||
s.data(), s.size()), ec);
|
||||
if(! ec)
|
||||
{
|
||||
if(p.is_done())
|
||||
{
|
||||
if(BEAST_EXPECT(used != s.size()))
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
p.write_eof(ec);
|
||||
if(BEAST_EXPECT(ec))
|
||||
return;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
pass();
|
||||
return;
|
||||
}
|
||||
log << "fail: \"" << s << "\"\n";
|
||||
}
|
||||
|
||||
void
|
||||
testObject()
|
||||
{
|
||||
good("{}");
|
||||
good("{ }");
|
||||
good("{ \t }");
|
||||
good("{ \"x\" : null }");
|
||||
good("{ \"x\" : {} }");
|
||||
good("{ \"x\" : { \"y\" : null } }");
|
||||
|
||||
bad ("{");
|
||||
bad ("{{}}");
|
||||
}
|
||||
|
||||
void
|
||||
testArray()
|
||||
{
|
||||
good("[]");
|
||||
good("[ ]");
|
||||
good("[ \t ]");
|
||||
good("[ \"\" ]");
|
||||
good("[ \" \" ]");
|
||||
good("[ \"x\" ]");
|
||||
good("[ \"x\", \"y\" ]");
|
||||
bad ("[");
|
||||
bad ("[ \"x\", ]");
|
||||
}
|
||||
|
||||
void
|
||||
testString()
|
||||
{
|
||||
good("\"" "x" "\"");
|
||||
good("\"" "xy" "\"");
|
||||
good("\"" "x y" "\"");
|
||||
|
||||
bad ("\"" "\t" "\"");
|
||||
}
|
||||
|
||||
void
|
||||
testNumber()
|
||||
{
|
||||
good("0");
|
||||
good("0.0");
|
||||
good("0.10");
|
||||
good("0.01");
|
||||
good("1");
|
||||
good("10");
|
||||
good("1.5");
|
||||
good("10.5");
|
||||
good("10.25");
|
||||
good("10.25e0");
|
||||
good("1e1");
|
||||
good("1e10");
|
||||
good("1e+0");
|
||||
good("1e+1");
|
||||
good("0e+10");
|
||||
good("0e-0");
|
||||
good("0e-1");
|
||||
good("0e-10");
|
||||
good("1E+1");
|
||||
good("-0");
|
||||
good("-1");
|
||||
good("-1e1");
|
||||
|
||||
bad ("");
|
||||
bad ("-");
|
||||
bad ("00");
|
||||
bad ("00.");
|
||||
bad ("00.0");
|
||||
bad ("1a");
|
||||
bad (".");
|
||||
bad ("1.");
|
||||
bad ("1+");
|
||||
bad ("0.0+");
|
||||
bad ("0.0e+");
|
||||
bad ("0.0e-");
|
||||
bad ("0.0e0-");
|
||||
bad ("0.0e");
|
||||
|
||||
}
|
||||
|
||||
void
|
||||
testMonostates()
|
||||
{
|
||||
good("true");
|
||||
good(" true");
|
||||
good("true ");
|
||||
good("\ttrue");
|
||||
good("true\t");
|
||||
good("\r\n\t true\r\n\t ");
|
||||
bad ("truu");
|
||||
bad ("tu");
|
||||
bad ("t");
|
||||
|
||||
good("false");
|
||||
bad ("fals");
|
||||
bad ("fel");
|
||||
bad ("f");
|
||||
|
||||
good("null");
|
||||
bad ("nul");
|
||||
bad ("no");
|
||||
bad ("n");
|
||||
}
|
||||
|
||||
void run() override
|
||||
{
|
||||
log <<
|
||||
"sizeof(basic_parser) == " <<
|
||||
sizeof(basic_parser) << "\n";
|
||||
testObject();
|
||||
testArray();
|
||||
testString();
|
||||
testNumber();
|
||||
testMonostates();
|
||||
}
|
||||
};
|
||||
|
||||
BEAST_DEFINE_TESTSUITE(beast,json,basic_parser);
|
||||
|
||||
} // json
|
||||
} // beast
|
||||
} // boost
|
||||
70
test/error.cpp
Normal file
70
test/error.cpp
Normal file
@@ -0,0 +1,70 @@
|
||||
//
|
||||
// Copyright (c) 2018-2019 Vinnie Falco (vinnie dot falco at gmail dot com)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
// Official repository: https://github.com/boostorg/json
|
||||
//
|
||||
|
||||
// Test that header file is self-contained.
|
||||
#include <boost/json/error.hpp>
|
||||
|
||||
#include <boost/beast/_experimental/unit_test/suite.hpp>
|
||||
#include <memory>
|
||||
|
||||
namespace boost {
|
||||
namespace beast {
|
||||
namespace json {
|
||||
|
||||
class error_test : public unit_test::suite
|
||||
{
|
||||
public:
|
||||
void check(error e)
|
||||
{
|
||||
auto const ec = make_error_code(e);
|
||||
ec.category().name();
|
||||
BEAST_EXPECT(! ec.message().empty());
|
||||
}
|
||||
|
||||
void check(condition c, error e)
|
||||
{
|
||||
{
|
||||
auto const ec = make_error_code(e);
|
||||
BEAST_EXPECT(ec.category().name() != nullptr);
|
||||
BEAST_EXPECT(! ec.message().empty());
|
||||
BEAST_EXPECT(ec == c);
|
||||
}
|
||||
{
|
||||
auto ec = make_error_condition(c);
|
||||
BEAST_EXPECT(ec.category().name() != nullptr);
|
||||
BEAST_EXPECT(! ec.message().empty());
|
||||
BEAST_EXPECT(ec == c);
|
||||
}
|
||||
}
|
||||
|
||||
void run() override
|
||||
{
|
||||
check(condition::parse_error, error::syntax);
|
||||
check(condition::parse_error, error::extra_data);
|
||||
check(condition::parse_error, error::mantissa_overflow);
|
||||
check(condition::parse_error, error::exponent_overflow);
|
||||
check(condition::parse_error, error::too_deep);
|
||||
|
||||
check(condition::assign_error, error::integer_overflow);
|
||||
check(condition::assign_error, error::expected_object);
|
||||
check(condition::assign_error, error::expected_array);
|
||||
check(condition::assign_error, error::expected_string);
|
||||
check(condition::assign_error, error::expected_number);
|
||||
check(condition::assign_error, error::expected_bool);
|
||||
check(condition::assign_error, error::expected_null);
|
||||
|
||||
check(error::key_not_found);
|
||||
}
|
||||
};
|
||||
|
||||
BEAST_DEFINE_TESTSUITE(beast,json,error);
|
||||
|
||||
} // json
|
||||
} // beast
|
||||
} // boost
|
||||
119
test/iterator.cpp
Normal file
119
test/iterator.cpp
Normal file
@@ -0,0 +1,119 @@
|
||||
//
|
||||
// Copyright (c) 2018-2019 Vinnie Falco (vinnie dot falco at gmail dot com)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
// Official repository: https://github.com/boostorg/json
|
||||
//
|
||||
|
||||
// Test that header file is self-contained.
|
||||
#include <boost/json/iterator.hpp>
|
||||
|
||||
#include <boost/beast/_experimental/unit_test/suite.hpp>
|
||||
|
||||
namespace boost {
|
||||
namespace beast {
|
||||
namespace json {
|
||||
|
||||
class iterator_test : public beast::unit_test::suite
|
||||
{
|
||||
public:
|
||||
void
|
||||
testIterator()
|
||||
{
|
||||
value jv = {
|
||||
{"pi", 3.141},
|
||||
{"happy", true},
|
||||
{"name", "Niels"},
|
||||
{"nothing", nullptr},
|
||||
{"answer", {
|
||||
{"everything", 42}
|
||||
}},
|
||||
#if 0
|
||||
{"list", {1, 0, 2}},
|
||||
{"object", {
|
||||
{"currency", "USD"},
|
||||
{"value", 42.99}
|
||||
}}
|
||||
#endif
|
||||
};
|
||||
|
||||
auto& arr = jv.as_object().
|
||||
emplace("arr", kind::array).first->second.as_array();
|
||||
arr.emplace_back(1);
|
||||
arr.emplace_back(2);
|
||||
arr.emplace_back(3);
|
||||
|
||||
const_iterator it(jv);
|
||||
while(it != end)
|
||||
{
|
||||
auto const& e = *it;
|
||||
log << std::string(e.depth*4, ' ');
|
||||
if(! e.end)
|
||||
{
|
||||
if(! e.key.empty())
|
||||
log << "\"" << e.key << "\" : ";
|
||||
switch(e.value.kind())
|
||||
{
|
||||
case kind::object:
|
||||
log << "{";
|
||||
break;
|
||||
case kind::array:
|
||||
log << "[";
|
||||
break;
|
||||
case kind::string:
|
||||
log << '\"' << e.value.as_string() << "\"";
|
||||
if(! e.last)
|
||||
log << ",";
|
||||
break;
|
||||
case kind::number:
|
||||
log << e.value.as_number();
|
||||
if(! e.last)
|
||||
log << ",";
|
||||
break;
|
||||
case kind::boolean:
|
||||
log << (e.value.as_bool() ?
|
||||
"true" : "false");
|
||||
if(! e.last)
|
||||
log << ",";
|
||||
break;
|
||||
case kind::null:
|
||||
log << "null";
|
||||
if(! e.last)
|
||||
log << ",";
|
||||
break;
|
||||
}
|
||||
log.flush();
|
||||
}
|
||||
else if(e->value.is_object())
|
||||
{
|
||||
log << "}";
|
||||
if(! e.last)
|
||||
log << ",";
|
||||
}
|
||||
else if(e->value.is_array())
|
||||
{
|
||||
log << "]";
|
||||
if(! e.last)
|
||||
log << ",";
|
||||
}
|
||||
log << "\n";
|
||||
log.flush();
|
||||
++it;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
run() override
|
||||
{
|
||||
testIterator();
|
||||
pass();
|
||||
}
|
||||
};
|
||||
|
||||
BEAST_DEFINE_TESTSUITE(beast,json,iterator);
|
||||
|
||||
} // json
|
||||
} // beast
|
||||
} // boost
|
||||
11
test/json.cpp
Normal file
11
test/json.cpp
Normal file
@@ -0,0 +1,11 @@
|
||||
//
|
||||
// Copyright (c) 2018-2019 Vinnie Falco (vinnie dot falco at gmail dot com)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
// Official repository: https://github.com/vinniefalco/BeastLounge
|
||||
//
|
||||
|
||||
// Test that header file is self-contained.
|
||||
#include <boost/json.hpp>
|
||||
42
test/kind.cpp
Normal file
42
test/kind.cpp
Normal file
@@ -0,0 +1,42 @@
|
||||
//
|
||||
// Copyright (c) 2018-2019 Vinnie Falco (vinnie dot falco at gmail dot com)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
// Official repository: https://github.com/boostorg/json
|
||||
//
|
||||
|
||||
// Test that header file is self-contained.
|
||||
#include <boost/json/kind.hpp>
|
||||
|
||||
#include <boost/beast/_experimental/unit_test/suite.hpp>
|
||||
#include <type_traits>
|
||||
|
||||
namespace boost {
|
||||
namespace beast {
|
||||
namespace json {
|
||||
|
||||
class kind_test : public unit_test::suite
|
||||
{
|
||||
public:
|
||||
BOOST_STATIC_ASSERT(
|
||||
std::is_enum<kind>::value);
|
||||
|
||||
void
|
||||
testEnum()
|
||||
{
|
||||
pass();
|
||||
}
|
||||
|
||||
void run() override
|
||||
{
|
||||
testEnum();
|
||||
}
|
||||
};
|
||||
|
||||
BEAST_DEFINE_TESTSUITE(beast,json,kind);
|
||||
|
||||
} // json
|
||||
} // beast
|
||||
} // boost
|
||||
11
test/lib.cpp
Normal file
11
test/lib.cpp
Normal file
@@ -0,0 +1,11 @@
|
||||
//
|
||||
// Copyright (c) 2016-2019 Vinnie Falco (vinnie dot falco at gmail dot com)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
// Official repository: https://github.com/boostorg/json
|
||||
//
|
||||
|
||||
#include <boost/beast/_experimental/unit_test/main.ipp>
|
||||
|
||||
324
test/number.cpp
Normal file
324
test/number.cpp
Normal file
@@ -0,0 +1,324 @@
|
||||
//
|
||||
// Copyright (c) 2018-2019 Vinnie Falco (vinnie dot falco at gmail dot com)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
// Official repository: https://github.com/boostorg/json
|
||||
//
|
||||
|
||||
// Test that header file is self-contained.
|
||||
#include <boost/json/number.hpp>
|
||||
|
||||
#include <boost/beast/_experimental/unit_test/suite.hpp>
|
||||
|
||||
#include <boost/beast/core/static_string.hpp>
|
||||
#include <cmath>
|
||||
|
||||
namespace boost {
|
||||
namespace beast {
|
||||
namespace json {
|
||||
|
||||
class number_test : public unit_test::suite
|
||||
{
|
||||
public:
|
||||
template<class I>
|
||||
void
|
||||
check(I v
|
||||
,typename std::enable_if<
|
||||
std::is_signed<I>::value &&
|
||||
std::is_integral<I>::value
|
||||
>::type* = 0) noexcept
|
||||
{
|
||||
number n(v);
|
||||
number n2(0);
|
||||
n2 = n;
|
||||
BEAST_EXPECT(n == n2);
|
||||
BEAST_EXPECT(n.is_int64());
|
||||
BEAST_EXPECT(n.get_int64() == v);
|
||||
BEAST_EXPECT(n.get_double() == v);
|
||||
}
|
||||
|
||||
template<class U>
|
||||
void
|
||||
check(U v
|
||||
,typename std::enable_if<
|
||||
std::is_unsigned<U>::value
|
||||
>::type* = 0) noexcept
|
||||
{
|
||||
number n(v);
|
||||
number n2(0);
|
||||
n2 = n;
|
||||
BEAST_EXPECT(n == n2);
|
||||
BEAST_EXPECT(n.is_uint64());
|
||||
BEAST_EXPECT(number(static_cast<
|
||||
number::mantissa_type>(v),
|
||||
0, false) == n);
|
||||
BEAST_EXPECT(n.get_uint64() == v);
|
||||
BEAST_EXPECT(n.get_double() == v);
|
||||
}
|
||||
|
||||
template<class F>
|
||||
void
|
||||
check(F v
|
||||
,typename std::enable_if<
|
||||
std::is_floating_point<
|
||||
F>::value>::type* = 0) noexcept
|
||||
{
|
||||
number n(v);
|
||||
number n2(0);
|
||||
n2 = n;
|
||||
BEAST_EXPECT(n == n2);
|
||||
BEAST_EXPECT(static_cast<F>(
|
||||
n.get_double()) == v);
|
||||
}
|
||||
|
||||
template<class F>
|
||||
void
|
||||
approx(F v) noexcept
|
||||
{
|
||||
number n(v);
|
||||
number n2(0);
|
||||
n2 = n;
|
||||
BEAST_EXPECT(n == n2);
|
||||
// VFALCO Unfortunately the results are not
|
||||
// quite exact due to power of 10 conversion.
|
||||
#if 0
|
||||
auto v1 = n.get_double();
|
||||
auto const d = std::fabs(v1 - v);
|
||||
BEAST_EXPECT(static_cast<F>(
|
||||
n.get_double()) == v);
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
testConstruction()
|
||||
{
|
||||
// Only perform light checking on
|
||||
// the result of the construction.
|
||||
|
||||
{
|
||||
number n((short)1);
|
||||
BEAST_EXPECT(n.get_int64() == 1);
|
||||
}
|
||||
{
|
||||
number n((int)2);
|
||||
BEAST_EXPECT(n.get_int64() == 2);
|
||||
}
|
||||
{
|
||||
number n((long)3);
|
||||
BEAST_EXPECT(n.get_int64() == 3);
|
||||
}
|
||||
{
|
||||
number n((long long)4);
|
||||
BEAST_EXPECT(n.get_int64() == 4);
|
||||
}
|
||||
{
|
||||
number n((unsigned short)1);
|
||||
BEAST_EXPECT(n.get_uint64() == 1);
|
||||
}
|
||||
{
|
||||
number n((unsigned int)2);
|
||||
BEAST_EXPECT(n.get_uint64() == 2);
|
||||
}
|
||||
{
|
||||
number n((unsigned long)3);
|
||||
BEAST_EXPECT(n.get_uint64() == 3);
|
||||
}
|
||||
{
|
||||
number n((unsigned long long)4);
|
||||
BEAST_EXPECT(n.get_uint64() == 4);
|
||||
}
|
||||
{
|
||||
number n((float)1.5f);
|
||||
BEAST_EXPECT(n.get_double() == 1.5);
|
||||
}
|
||||
{
|
||||
number n((double)2.5);
|
||||
BEAST_EXPECT(n.get_double() == 2.5);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
testAssignment()
|
||||
{
|
||||
// Only perform light checking on
|
||||
// the result of the construction.
|
||||
|
||||
{
|
||||
number n;
|
||||
n = (short)1;
|
||||
BEAST_EXPECT(n.get_int64() == 1);
|
||||
n = (int)2;
|
||||
BEAST_EXPECT(n.get_int64() == 2);
|
||||
n = (long)3;
|
||||
BEAST_EXPECT(n.get_int64() == 3);
|
||||
n = (long long)4;
|
||||
BEAST_EXPECT(n.get_int64() == 4);
|
||||
n = (unsigned short)5;
|
||||
BEAST_EXPECT(n.get_uint64() == 5);
|
||||
n = (unsigned int)6;
|
||||
BEAST_EXPECT(n.get_uint64() == 6);
|
||||
n = (unsigned long)7;
|
||||
BEAST_EXPECT(n.get_uint64() == 7);
|
||||
n = (unsigned long long)8;
|
||||
BEAST_EXPECT(n.get_uint64() == 8);
|
||||
n = (float)1.5;
|
||||
BEAST_EXPECT(n.get_double() == 1.5);
|
||||
n = (double)2.5;
|
||||
BEAST_EXPECT(n.get_double() == 2.5);
|
||||
n = (double)3.5l;
|
||||
BEAST_EXPECT(n.get_double() == 3.5);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
testComparison()
|
||||
{
|
||||
// Only perform light checking on
|
||||
// the result of the comparison.
|
||||
|
||||
number n = 1;
|
||||
BEAST_EXPECT(n == ((short)1));
|
||||
BEAST_EXPECT(n == ((int)1));
|
||||
BEAST_EXPECT(n == ((long)1));
|
||||
BEAST_EXPECT(n == ((long long)1));
|
||||
BEAST_EXPECT(n == ((unsigned short)1));
|
||||
BEAST_EXPECT(n == ((unsigned int)1));
|
||||
BEAST_EXPECT(n == ((unsigned long)1));
|
||||
BEAST_EXPECT(n == ((unsigned long long)1));
|
||||
|
||||
n = 1.f;
|
||||
BEAST_EXPECT(n == 1.f);
|
||||
|
||||
n = 1.;
|
||||
BEAST_EXPECT(n == 1.);
|
||||
}
|
||||
|
||||
void
|
||||
testValues()
|
||||
{
|
||||
// Test the range of each convertible numeric
|
||||
// type, make sure they round-trip correctly.
|
||||
|
||||
check(1.0/7);
|
||||
check((std::numeric_limits<short>::min)());
|
||||
check((std::numeric_limits<short>::max)());
|
||||
check((std::numeric_limits<short>::min)());
|
||||
check((std::numeric_limits<short>::max)());
|
||||
check((std::numeric_limits<int>::min)());
|
||||
check((std::numeric_limits<int>::max)());
|
||||
check((std::numeric_limits<int>::min)()/2);
|
||||
check((std::numeric_limits<int>::max)()/2);
|
||||
check((std::numeric_limits<long>::min)());
|
||||
check((std::numeric_limits<long>::max)());
|
||||
check((std::numeric_limits<long>::min)()/2);
|
||||
check((std::numeric_limits<long>::max)()/2);
|
||||
check((std::numeric_limits<long long>::min)());
|
||||
check((std::numeric_limits<long long>::max)());
|
||||
check((std::numeric_limits<long long>::min)()/2);
|
||||
check((std::numeric_limits<long long>::max)()/2);
|
||||
check((std::numeric_limits<unsigned short>::min)());
|
||||
check((std::numeric_limits<unsigned short>::max)());
|
||||
check((std::numeric_limits<unsigned short>::min)()/2);
|
||||
check((std::numeric_limits<unsigned short>::max)()/2);
|
||||
check((std::numeric_limits<unsigned int>::min)());
|
||||
check((std::numeric_limits<unsigned int>::max)());
|
||||
check((std::numeric_limits<unsigned int>::min)()/2);
|
||||
check((std::numeric_limits<unsigned int>::max)()/2);
|
||||
check((std::numeric_limits<unsigned long>::min)());
|
||||
check((std::numeric_limits<unsigned long>::max)());
|
||||
check((std::numeric_limits<unsigned long>::min)()/2);
|
||||
check((std::numeric_limits<unsigned long>::max)()/2);
|
||||
check((std::numeric_limits<unsigned long long>::min)());
|
||||
check((std::numeric_limits<unsigned long long>::max)());
|
||||
check((std::numeric_limits<unsigned long long>::min)()/2);
|
||||
check((std::numeric_limits<unsigned long long>::max)()/2);
|
||||
|
||||
check((std::numeric_limits<float>::min)());
|
||||
check((std::numeric_limits<float>::max)());
|
||||
check((std::numeric_limits<float>::min)()/2);
|
||||
check((std::numeric_limits<float>::max)()/2);
|
||||
check((std::numeric_limits<double>::min)());
|
||||
check((std::numeric_limits<double>::max)());
|
||||
check((std::numeric_limits<double>::min)()/2);
|
||||
|
||||
// not exact
|
||||
approx((std::numeric_limits<double>::max)()/2);
|
||||
}
|
||||
|
||||
template<class V>
|
||||
void
|
||||
check_output(V v)
|
||||
{
|
||||
char buf[number::max_string_chars];
|
||||
auto const s = number(v).print(buf, sizeof(buf));
|
||||
BEAST_EXPECTS(
|
||||
s == std::to_string(v).c_str(),
|
||||
std::string(s.data(), s.size()));
|
||||
}
|
||||
|
||||
void
|
||||
testOstream()
|
||||
{
|
||||
check_output(1);
|
||||
check_output(2);
|
||||
check_output(3);
|
||||
|
||||
// These don't match std::to_string
|
||||
/*
|
||||
check_output(1.5f);
|
||||
check_output(2.5);
|
||||
check_output(3.5l);
|
||||
*/
|
||||
|
||||
check_output((std::numeric_limits<short>::min)());
|
||||
check_output((std::numeric_limits<short>::max)());
|
||||
check_output((std::numeric_limits<short>::min)());
|
||||
check_output((std::numeric_limits<short>::max)());
|
||||
check_output((std::numeric_limits<int>::min)());
|
||||
check_output((std::numeric_limits<int>::max)());
|
||||
check_output((std::numeric_limits<int>::min)()/2);
|
||||
check_output((std::numeric_limits<int>::max)()/2);
|
||||
check_output((std::numeric_limits<long>::min)());
|
||||
check_output((std::numeric_limits<long>::max)());
|
||||
check_output((std::numeric_limits<long>::min)()/2);
|
||||
check_output((std::numeric_limits<long>::max)()/2);
|
||||
check_output((std::numeric_limits<long long>::min)());
|
||||
check_output((std::numeric_limits<long long>::max)());
|
||||
check_output((std::numeric_limits<long long>::min)()/2);
|
||||
check_output((std::numeric_limits<long long>::max)()/2);
|
||||
check_output((std::numeric_limits<unsigned short>::min)());
|
||||
check_output((std::numeric_limits<unsigned short>::max)());
|
||||
check_output((std::numeric_limits<unsigned short>::min)()/2);
|
||||
check_output((std::numeric_limits<unsigned short>::max)()/2);
|
||||
check_output((std::numeric_limits<unsigned int>::min)());
|
||||
check_output((std::numeric_limits<unsigned int>::max)());
|
||||
check_output((std::numeric_limits<unsigned int>::min)()/2);
|
||||
check_output((std::numeric_limits<unsigned int>::max)()/2);
|
||||
check_output((std::numeric_limits<unsigned long>::min)());
|
||||
check_output((std::numeric_limits<unsigned long>::max)());
|
||||
check_output((std::numeric_limits<unsigned long>::min)()/2);
|
||||
check_output((std::numeric_limits<unsigned long>::max)()/2);
|
||||
check_output((std::numeric_limits<unsigned long long>::min)());
|
||||
check_output((std::numeric_limits<unsigned long long>::max)());
|
||||
check_output((std::numeric_limits<unsigned long long>::min)()/2);
|
||||
check_output((std::numeric_limits<unsigned long long>::max)()/2);
|
||||
}
|
||||
|
||||
void
|
||||
run() override
|
||||
{
|
||||
testConstruction();
|
||||
testAssignment();
|
||||
testComparison();
|
||||
testValues();
|
||||
testOstream();
|
||||
}
|
||||
};
|
||||
|
||||
BEAST_DEFINE_TESTSUITE(beast,json,number);
|
||||
|
||||
} // json
|
||||
} // beast
|
||||
} // boost
|
||||
1060
test/object.cpp
Normal file
1060
test/object.cpp
Normal file
File diff suppressed because it is too large
Load Diff
11
test/parse_file.cpp
Normal file
11
test/parse_file.cpp
Normal file
@@ -0,0 +1,11 @@
|
||||
//
|
||||
// Copyright (c) 2018-2019 Vinnie Falco (vinnie dot falco at gmail dot com)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
// Official repository: https://github.com/vinniefalco/BeastLounge
|
||||
//
|
||||
|
||||
// Test that header file is self-contained.
|
||||
#include <boost/json/parse_file.hpp>
|
||||
84
test/parser.cpp
Normal file
84
test/parser.cpp
Normal file
@@ -0,0 +1,84 @@
|
||||
//
|
||||
// Copyright (c) 2018-2019 Vinnie Falco (vinnie dot falco at gmail dot com)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
// Official repository: https://github.com/vinniefalco/BeastLounge
|
||||
//
|
||||
|
||||
// Test that header file is self-contained.
|
||||
#include <boost/json/parser.hpp>
|
||||
|
||||
#include <boost/beast/_experimental/unit_test/suite.hpp>
|
||||
#include <boost/json/parser.hpp>
|
||||
#include <sstream>
|
||||
|
||||
namespace boost {
|
||||
namespace beast {
|
||||
namespace json {
|
||||
|
||||
class parser_test : public unit_test::suite
|
||||
{
|
||||
public:
|
||||
void
|
||||
testParser()
|
||||
{
|
||||
string_view in =
|
||||
R"xx({
|
||||
"glossary": {
|
||||
"title": "example glossary",
|
||||
"GlossDiv": {
|
||||
"title": "S",
|
||||
"GlossList": {
|
||||
"GlossEntry": {
|
||||
"ID": "SGML",
|
||||
"SortAs": "SGML",
|
||||
"GlossTerm": "Standard Generalized Markup Language",
|
||||
"Acronym": "SGML",
|
||||
"Abbrev": "ISO 8879:1986",
|
||||
"GlossDef": {
|
||||
"para": "A meta-markup language, used to create markup languages such as DocBook.",
|
||||
"GlossSeeAlso": ["GML", "XML"]
|
||||
},
|
||||
"GlossSee": "markup"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
})xx"
|
||||
;
|
||||
parser p;
|
||||
error_code ec;
|
||||
p.write({in.data(), in.size()}, ec);
|
||||
if(BEAST_EXPECTS(! ec, ec.message()))
|
||||
{
|
||||
std::stringstream ss;
|
||||
ss << p.get();
|
||||
BEAST_EXPECT(ss.str() ==
|
||||
"{\"glossary\":{\"title\":\"example glossary\",\"GlossDiv\":"
|
||||
"{\"title\":\"S\",\"GlossList\":{\"GlossEntry\":{\"ID\":\"SGML\","
|
||||
"\"SortAs\":\"SGML\",\"GlossTerm\":\"Standard Generalized Markup "
|
||||
"Language\",\"Acronym\":\"SGML\",\"Abbrev\":\"ISO 8879:1986\","
|
||||
"\"GlossDef\":{\"para\":\"A meta-markup language, used to create "
|
||||
"markup languages such as DocBook.\",\"GlossSeeAlso\":[\"GML\",\"XML\"]},"
|
||||
"\"GlossSee\":\"markup\"}}}}}"
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
run()
|
||||
{
|
||||
log <<
|
||||
"sizeof(parser) == " <<
|
||||
sizeof(parser) << "\n";
|
||||
testParser();
|
||||
}
|
||||
};
|
||||
|
||||
BEAST_DEFINE_TESTSUITE(beast,json,parser);
|
||||
|
||||
} // json
|
||||
} // beast
|
||||
} // boost
|
||||
68
test/serializer.cpp
Normal file
68
test/serializer.cpp
Normal file
@@ -0,0 +1,68 @@
|
||||
//
|
||||
// Copyright (c) 2018-2019 Vinnie Falco (vinnie dot falco at gmail dot com)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
// Official repository: https://github.com/vinniefalco/BeastLounge
|
||||
//
|
||||
|
||||
// Test that header file is self-contained.
|
||||
#include <boost/json/serializer.hpp>
|
||||
|
||||
#include <boost/beast/_experimental/unit_test/suite.hpp>
|
||||
|
||||
namespace boost {
|
||||
namespace beast {
|
||||
namespace json {
|
||||
|
||||
class serializer_test : public unit_test::suite
|
||||
{
|
||||
public:
|
||||
void
|
||||
testSerializer()
|
||||
{
|
||||
value jv = {
|
||||
{"pi", 3.141},
|
||||
{"happy", true},
|
||||
{"name", "Niels"},
|
||||
{"nothing", nullptr},
|
||||
{"answer", {
|
||||
{"everything", 42}
|
||||
}},
|
||||
#if 0
|
||||
{"list", {1, 0, 2}},
|
||||
{"object", {
|
||||
{"currency", "USD"},
|
||||
{"value", 42.99}
|
||||
}}
|
||||
#endif
|
||||
};
|
||||
|
||||
auto& arr = jv.as_object().
|
||||
emplace("arr", kind::array).first->second.as_array();
|
||||
arr.emplace_back(1);
|
||||
arr.emplace_back(2);
|
||||
arr.emplace_back(3);
|
||||
|
||||
serializer sr(jv);
|
||||
char buf[2048];
|
||||
auto const n =
|
||||
sr.next({buf, sizeof(buf)});
|
||||
string_view s(buf, n);
|
||||
log << s << "\n";
|
||||
}
|
||||
|
||||
void
|
||||
run()
|
||||
{
|
||||
testSerializer();
|
||||
pass();
|
||||
}
|
||||
};
|
||||
|
||||
BEAST_DEFINE_TESTSUITE(beast,json,serializer);
|
||||
|
||||
} // json
|
||||
} // beast
|
||||
} // boost
|
||||
191
test/storage.cpp
Normal file
191
test/storage.cpp
Normal file
@@ -0,0 +1,191 @@
|
||||
//
|
||||
// Copyright (c) 2018-2019 Vinnie Falco (vinnie dot falco at gmail dot com)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
// Official repository: https://github.com/boostorg/json
|
||||
//
|
||||
|
||||
// Test that header file is self-contained.
|
||||
#include <boost/json/storage.hpp>
|
||||
|
||||
#include <boost/beast/_experimental/unit_test/suite.hpp>
|
||||
#include <boost/json/detail/storage_adaptor.hpp>
|
||||
|
||||
namespace boost {
|
||||
namespace beast {
|
||||
namespace json {
|
||||
|
||||
class storage_test : public unit_test::suite
|
||||
{
|
||||
public:
|
||||
struct unique_storage : storage
|
||||
{
|
||||
void
|
||||
addref() noexcept override
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
release() noexcept override
|
||||
{
|
||||
}
|
||||
|
||||
void*
|
||||
allocate(
|
||||
std::size_t n,
|
||||
std::size_t) override
|
||||
{
|
||||
return std::allocator<
|
||||
char>{}.allocate(n);
|
||||
}
|
||||
|
||||
void
|
||||
deallocate(
|
||||
void* p,
|
||||
std::size_t n,
|
||||
std::size_t) noexcept override
|
||||
{
|
||||
auto cp =
|
||||
reinterpret_cast<char*>(p);
|
||||
return std::allocator<
|
||||
char>{}.deallocate(cp, n);
|
||||
}
|
||||
bool
|
||||
is_equal(
|
||||
storage const& other
|
||||
) const noexcept override
|
||||
{
|
||||
auto p = dynamic_cast<
|
||||
unique_storage const*>(&other);
|
||||
if(! p)
|
||||
return false;
|
||||
return this == p;
|
||||
}
|
||||
};
|
||||
|
||||
void
|
||||
testStoragePtr()
|
||||
{
|
||||
auto p = new detail::storage_adaptor<
|
||||
std::allocator<char>>({});
|
||||
|
||||
// default ctor
|
||||
{
|
||||
storage_ptr s;
|
||||
BEAST_EXPECT(s == nullptr);
|
||||
}
|
||||
|
||||
// move ctor
|
||||
{
|
||||
p->addref();
|
||||
storage_ptr s1(p);
|
||||
storage_ptr s2(std::move(s1));
|
||||
BEAST_EXPECT(s1 == nullptr);
|
||||
BEAST_EXPECT(s2 == p);
|
||||
}
|
||||
|
||||
// copy ctor
|
||||
{
|
||||
p->addref();
|
||||
storage_ptr s1(p);
|
||||
storage_ptr s2(s1);
|
||||
BEAST_EXPECT(s1 == p);
|
||||
BEAST_EXPECT(s2 == p);
|
||||
BEAST_EXPECT(s1 == s2);
|
||||
}
|
||||
|
||||
// move assign
|
||||
{
|
||||
p->addref();
|
||||
storage_ptr s1(p);
|
||||
storage_ptr s2;
|
||||
s2 = std::move(s1);
|
||||
BEAST_EXPECT(s1 == nullptr);
|
||||
BEAST_EXPECT(s2 == p);
|
||||
}
|
||||
|
||||
// copy assign
|
||||
{
|
||||
p->addref();
|
||||
storage_ptr s1(p);
|
||||
storage_ptr s2;
|
||||
s2 = s1;
|
||||
BEAST_EXPECT(s1 == p);
|
||||
BEAST_EXPECT(s2 == p);
|
||||
BEAST_EXPECT(s1 == s2);
|
||||
}
|
||||
|
||||
// construction
|
||||
{
|
||||
p->addref();
|
||||
storage_ptr sp(p);
|
||||
BEAST_EXPECT(sp == p);
|
||||
}
|
||||
|
||||
// release
|
||||
{
|
||||
p->addref();
|
||||
storage_ptr sp(
|
||||
storage_ptr{p}.release());
|
||||
BEAST_EXPECT(sp == p);
|
||||
}
|
||||
|
||||
// bool, get, ->, *
|
||||
{
|
||||
p->addref();
|
||||
storage_ptr sp(p);
|
||||
BEAST_EXPECT(sp);
|
||||
BEAST_EXPECT(sp.get() == p);
|
||||
BEAST_EXPECT(sp.operator->() == p);
|
||||
BEAST_EXPECT(&sp.operator*() == p);
|
||||
sp = nullptr;
|
||||
BEAST_EXPECT(! sp);
|
||||
}
|
||||
|
||||
// converting assignment
|
||||
{
|
||||
p->addref();
|
||||
storage_ptr sp;
|
||||
sp = p;
|
||||
BEAST_EXPECT(sp == p);
|
||||
sp = nullptr;
|
||||
BEAST_EXPECT(! sp);
|
||||
}
|
||||
|
||||
// equality
|
||||
{
|
||||
unique_storage us1;
|
||||
unique_storage us2;
|
||||
storage_ptr spu1(&us1);
|
||||
storage_ptr spu2(&us2);
|
||||
storage_ptr sp = make_storage_ptr(
|
||||
std::allocator<void>{});
|
||||
storage_ptr spd =
|
||||
default_storage();
|
||||
BEAST_EXPECT(us1 != us2);
|
||||
BEAST_EXPECT(us1 != *spd);
|
||||
BEAST_EXPECT(us2 != *spd);
|
||||
BEAST_EXPECT(us1 != *sp);
|
||||
BEAST_EXPECT(us2 != *sp);
|
||||
BEAST_EXPECT(
|
||||
*spd == *default_storage());
|
||||
BEAST_EXPECT(
|
||||
*sp != *default_storage());
|
||||
}
|
||||
|
||||
p->release();
|
||||
}
|
||||
|
||||
void run() override
|
||||
{
|
||||
testStoragePtr();
|
||||
}
|
||||
};
|
||||
|
||||
BEAST_DEFINE_TESTSUITE(beast,json,storage);
|
||||
|
||||
} // json
|
||||
} // beast
|
||||
} // boost
|
||||
33
test/string.cpp
Normal file
33
test/string.cpp
Normal file
@@ -0,0 +1,33 @@
|
||||
//
|
||||
// Copyright (c) 2018-2019 Vinnie Falco (vinnie dot falco at gmail dot com)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
// Official repository: https://github.com/vinniefalco/BeastLounge
|
||||
//
|
||||
|
||||
// Test that header file is self-contained.
|
||||
#include <boost/json/string.hpp>
|
||||
|
||||
#include <boost/beast/_experimental/unit_test/suite.hpp>
|
||||
|
||||
namespace boost {
|
||||
namespace beast {
|
||||
namespace json {
|
||||
|
||||
class string_test : public unit_test::suite
|
||||
{
|
||||
public:
|
||||
void
|
||||
run() override
|
||||
{
|
||||
pass();
|
||||
}
|
||||
};
|
||||
|
||||
BEAST_DEFINE_TESTSUITE(beast,json,string);
|
||||
|
||||
} // json
|
||||
} // beast
|
||||
} // boost
|
||||
725
test/value.cpp
Normal file
725
test/value.cpp
Normal file
@@ -0,0 +1,725 @@
|
||||
//
|
||||
// Copyright (c) 2018-2019 Vinnie Falco (vinnie dot falco at gmail dot com)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
// Official repository: https://github.com/boostorg/json
|
||||
//
|
||||
|
||||
// Test that header file is self-contained.
|
||||
#include <boost/json/value.hpp>
|
||||
|
||||
#include <boost/beast/_experimental/unit_test/suite.hpp>
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
|
||||
namespace boost {
|
||||
namespace beast {
|
||||
namespace json {
|
||||
|
||||
namespace value_test_ns {
|
||||
|
||||
struct T1
|
||||
{
|
||||
void
|
||||
to_json(value&) const
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
struct T2
|
||||
{
|
||||
};
|
||||
|
||||
void
|
||||
to_json(T2 const&, value&)
|
||||
{
|
||||
}
|
||||
|
||||
struct T3
|
||||
{
|
||||
};
|
||||
|
||||
} // value_test_ns
|
||||
|
||||
template<>
|
||||
struct value_exchange<value_test_ns::T3>
|
||||
{
|
||||
static
|
||||
void
|
||||
to_json(value_test_ns::T3, value&)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
class value_test : public unit_test::suite
|
||||
{
|
||||
public:
|
||||
struct unique_storage : storage
|
||||
{
|
||||
void
|
||||
addref() noexcept override
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
release() noexcept override
|
||||
{
|
||||
}
|
||||
|
||||
void*
|
||||
allocate(
|
||||
std::size_t n,
|
||||
std::size_t) override
|
||||
{
|
||||
return std::allocator<
|
||||
char>{}.allocate(n);
|
||||
}
|
||||
|
||||
void
|
||||
deallocate(
|
||||
void* p,
|
||||
std::size_t n,
|
||||
std::size_t) noexcept override
|
||||
{
|
||||
auto cp =
|
||||
reinterpret_cast<char*>(p);
|
||||
return std::allocator<
|
||||
char>{}.deallocate(cp, n);
|
||||
}
|
||||
bool
|
||||
is_equal(
|
||||
storage const& other
|
||||
) const noexcept override
|
||||
{
|
||||
auto p = dynamic_cast<
|
||||
unique_storage const*>(&other);
|
||||
if(! p)
|
||||
return false;
|
||||
return this == p;
|
||||
}
|
||||
};
|
||||
|
||||
void
|
||||
testSpecial()
|
||||
{
|
||||
// move ctor
|
||||
{
|
||||
value jv1;
|
||||
value jv2(std::move(jv1));
|
||||
}
|
||||
|
||||
// copy ctor
|
||||
{
|
||||
value jv1;
|
||||
value jv2(jv1);
|
||||
}
|
||||
|
||||
// move assign
|
||||
{
|
||||
value jv1;
|
||||
value jv2;
|
||||
jv2 = std::move(jv1);
|
||||
}
|
||||
|
||||
// copy assign
|
||||
{
|
||||
value jv1;
|
||||
value jv2;
|
||||
jv2 = jv1;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
testConstruct()
|
||||
{
|
||||
unique_storage us;
|
||||
storage_ptr sp(&us);
|
||||
storage_ptr sp0 =
|
||||
default_storage();
|
||||
|
||||
// default ctor
|
||||
{
|
||||
value jv;
|
||||
BEAST_EXPECT(jv.is_null());
|
||||
BEAST_EXPECT(jv.get_storage() != sp);
|
||||
BEAST_EXPECT(jv.get_storage() == sp0);
|
||||
}
|
||||
|
||||
// storage ctor
|
||||
{
|
||||
value jv1(sp);
|
||||
BEAST_EXPECT(jv1.is_null());
|
||||
BEAST_EXPECT(jv1.get_storage() == sp);
|
||||
BEAST_EXPECT(jv1.get_storage() != sp0);
|
||||
|
||||
auto sp2 = sp;
|
||||
value jv2(std::move(sp2));
|
||||
BEAST_EXPECT(jv2.is_null());
|
||||
BEAST_EXPECT(jv1.get_storage() == sp);
|
||||
BEAST_EXPECT(jv1.get_storage() != sp0);
|
||||
BEAST_EXPECT(jv2.get_storage() == sp);
|
||||
BEAST_EXPECT(jv2.get_storage() != sp0);
|
||||
}
|
||||
|
||||
// kind construct
|
||||
{
|
||||
value jv(kind::object);
|
||||
BEAST_EXPECT(jv.is_object());
|
||||
BEAST_EXPECT(jv.get_storage() != sp);
|
||||
BEAST_EXPECT(jv.get_storage() == sp0);
|
||||
}
|
||||
{
|
||||
value jv(kind::array);
|
||||
BEAST_EXPECT(jv.is_array());
|
||||
BEAST_EXPECT(jv.get_storage() != sp);
|
||||
BEAST_EXPECT(jv.get_storage() == sp0);
|
||||
}
|
||||
{
|
||||
value jv(kind::string);
|
||||
BEAST_EXPECT(jv.is_string());
|
||||
BEAST_EXPECT(jv.get_storage() != sp);
|
||||
BEAST_EXPECT(jv.get_storage() == sp0);
|
||||
}
|
||||
{
|
||||
value jv(kind::number);
|
||||
BEAST_EXPECT(jv.is_number());
|
||||
BEAST_EXPECT(jv.get_storage() != sp);
|
||||
BEAST_EXPECT(jv.get_storage() == sp0);
|
||||
}
|
||||
{
|
||||
value jv(kind::boolean);
|
||||
BEAST_EXPECT(jv.is_bool());
|
||||
BEAST_EXPECT(jv.get_storage() != sp);
|
||||
BEAST_EXPECT(jv.get_storage() == sp0);
|
||||
}
|
||||
{
|
||||
value jv(kind::null);
|
||||
BEAST_EXPECT(jv.is_null());
|
||||
BEAST_EXPECT(jv.get_storage() != sp);
|
||||
BEAST_EXPECT(jv.get_storage() == sp0);
|
||||
}
|
||||
|
||||
// kind, storage construct
|
||||
{
|
||||
value jv(kind::object, sp);
|
||||
BEAST_EXPECT(jv.is_object());
|
||||
BEAST_EXPECT(jv.get_storage() == sp);
|
||||
BEAST_EXPECT(jv.get_storage() != sp0);
|
||||
}
|
||||
{
|
||||
value jv(kind::array, sp);
|
||||
BEAST_EXPECT(jv.is_array());
|
||||
BEAST_EXPECT(jv.get_storage() == sp);
|
||||
BEAST_EXPECT(jv.get_storage() != sp0);
|
||||
}
|
||||
{
|
||||
value jv(kind::string, sp);
|
||||
BEAST_EXPECT(jv.is_string());
|
||||
BEAST_EXPECT(jv.get_storage() == sp);
|
||||
BEAST_EXPECT(jv.get_storage() != sp0);
|
||||
}
|
||||
{
|
||||
value jv(kind::number, sp);
|
||||
BEAST_EXPECT(jv.is_number());
|
||||
BEAST_EXPECT(jv.get_storage() == sp);
|
||||
BEAST_EXPECT(jv.get_storage() != sp0);
|
||||
}
|
||||
{
|
||||
value jv(kind::boolean, sp);
|
||||
BEAST_EXPECT(jv.is_bool());
|
||||
BEAST_EXPECT(jv.get_storage() == sp);
|
||||
BEAST_EXPECT(jv.get_storage() != sp0);
|
||||
}
|
||||
{
|
||||
value jv(kind::null, sp);
|
||||
BEAST_EXPECT(jv.is_null());
|
||||
BEAST_EXPECT(jv.get_storage() == sp);
|
||||
BEAST_EXPECT(jv.get_storage() != sp0);
|
||||
}
|
||||
|
||||
// construct from containers
|
||||
{
|
||||
{
|
||||
object obj;
|
||||
value jv(obj);
|
||||
BEAST_EXPECT(jv.is_object());
|
||||
BEAST_EXPECT(jv.get_storage() != sp);
|
||||
BEAST_EXPECT(jv.get_storage() == sp0);
|
||||
}
|
||||
{
|
||||
array arr;
|
||||
value jv(arr);
|
||||
BEAST_EXPECT(jv.is_array());
|
||||
BEAST_EXPECT(jv.get_storage() != sp);
|
||||
BEAST_EXPECT(jv.get_storage() == sp0);
|
||||
}
|
||||
{
|
||||
string str;
|
||||
value jv(str);
|
||||
BEAST_EXPECT(jv.is_string());
|
||||
BEAST_EXPECT(jv.get_storage() != sp);
|
||||
BEAST_EXPECT(jv.get_storage() == sp0);
|
||||
}
|
||||
{
|
||||
value jv(number(1));
|
||||
BEAST_EXPECT(jv.is_number());
|
||||
BEAST_EXPECT(jv.is_int64());
|
||||
BEAST_EXPECT(jv.is_uint64());
|
||||
BEAST_EXPECT(jv.is_double());
|
||||
BEAST_EXPECT(jv.get_int64() == 1);
|
||||
BEAST_EXPECT(jv.get_uint64() == 1);
|
||||
BEAST_EXPECT(jv.get_double() == 1);
|
||||
BEAST_EXPECT(jv.as_number() == 1);
|
||||
BEAST_EXPECT(jv.get_storage() != sp);
|
||||
BEAST_EXPECT(jv.get_storage() == sp0);
|
||||
}
|
||||
//
|
||||
{
|
||||
object obj;
|
||||
value jv(obj, sp);
|
||||
BEAST_EXPECT(jv.is_object());
|
||||
BEAST_EXPECT(jv.get_storage() == sp);
|
||||
BEAST_EXPECT(jv.get_storage() != sp0);
|
||||
}
|
||||
{
|
||||
array arr;
|
||||
value jv(arr, sp);
|
||||
BEAST_EXPECT(jv.is_array());
|
||||
BEAST_EXPECT(jv.get_storage() == sp);
|
||||
BEAST_EXPECT(jv.get_storage() != sp0);
|
||||
}
|
||||
{
|
||||
string str;
|
||||
value jv(str, sp);
|
||||
BEAST_EXPECT(jv.is_string());
|
||||
BEAST_EXPECT(jv.get_storage() == sp);
|
||||
BEAST_EXPECT(jv.get_storage() != sp0);
|
||||
}
|
||||
{
|
||||
value jv(number(1), sp);
|
||||
BEAST_EXPECT(jv.is_number());
|
||||
BEAST_EXPECT(jv.is_int64());
|
||||
BEAST_EXPECT(jv.is_uint64());
|
||||
BEAST_EXPECT(jv.is_double());
|
||||
BEAST_EXPECT(jv.get_int64() == 1);
|
||||
BEAST_EXPECT(jv.get_uint64() == 1);
|
||||
BEAST_EXPECT(jv.get_double() == 1);
|
||||
BEAST_EXPECT(jv.as_number() == 1);
|
||||
BEAST_EXPECT(jv.get_storage() == sp);
|
||||
BEAST_EXPECT(jv.get_storage() != sp0);
|
||||
}
|
||||
}
|
||||
|
||||
// assign from containers
|
||||
{
|
||||
{
|
||||
object obj;
|
||||
value jv;
|
||||
|
||||
jv = obj;
|
||||
BEAST_EXPECT(jv.is_object());
|
||||
BEAST_EXPECT(jv.get_storage() != sp);
|
||||
BEAST_EXPECT(jv.get_storage() == sp0);
|
||||
|
||||
jv.reset();
|
||||
BEAST_EXPECT(jv.is_null());
|
||||
BEAST_EXPECT(jv.get_storage() != sp);
|
||||
BEAST_EXPECT(jv.get_storage() == sp0);
|
||||
|
||||
jv = std::move(obj);
|
||||
BEAST_EXPECT(jv.is_object());
|
||||
BEAST_EXPECT(jv.get_storage() != sp);
|
||||
BEAST_EXPECT(jv.get_storage() == sp0);
|
||||
}
|
||||
{
|
||||
object obj;
|
||||
value jv(sp);
|
||||
|
||||
jv = obj;
|
||||
BEAST_EXPECT(jv.is_object());
|
||||
BEAST_EXPECT(jv.get_storage() == sp);
|
||||
BEAST_EXPECT(jv.get_storage() != sp0);
|
||||
|
||||
jv.reset();
|
||||
BEAST_EXPECT(jv.is_null());
|
||||
BEAST_EXPECT(jv.get_storage() == sp);
|
||||
BEAST_EXPECT(jv.get_storage() != sp0);
|
||||
|
||||
jv = std::move(obj);
|
||||
BEAST_EXPECT(jv.is_object());
|
||||
BEAST_EXPECT(jv.get_storage() == sp);
|
||||
BEAST_EXPECT(jv.get_storage() != sp0);
|
||||
}
|
||||
{
|
||||
array arr;
|
||||
value jv;
|
||||
|
||||
jv = arr;
|
||||
BEAST_EXPECT(jv.is_array());
|
||||
BEAST_EXPECT(jv.get_storage() != sp);
|
||||
BEAST_EXPECT(jv.get_storage() == sp0);
|
||||
|
||||
jv.reset();
|
||||
BEAST_EXPECT(jv.is_null());
|
||||
BEAST_EXPECT(jv.get_storage() != sp);
|
||||
BEAST_EXPECT(jv.get_storage() == sp0);
|
||||
|
||||
jv = std::move(arr);
|
||||
BEAST_EXPECT(jv.is_array());
|
||||
BEAST_EXPECT(jv.get_storage() != sp);
|
||||
BEAST_EXPECT(jv.get_storage() == sp0);
|
||||
}
|
||||
{
|
||||
array arr;
|
||||
value jv(sp);
|
||||
|
||||
jv = arr;
|
||||
BEAST_EXPECT(jv.is_array());
|
||||
BEAST_EXPECT(jv.get_storage() == sp);
|
||||
BEAST_EXPECT(jv.get_storage() != sp0);
|
||||
|
||||
jv.reset();
|
||||
BEAST_EXPECT(jv.is_null());
|
||||
BEAST_EXPECT(jv.get_storage() == sp);
|
||||
BEAST_EXPECT(jv.get_storage() != sp0);
|
||||
|
||||
jv = std::move(arr);
|
||||
BEAST_EXPECT(jv.is_array());
|
||||
BEAST_EXPECT(jv.get_storage() == sp);
|
||||
BEAST_EXPECT(jv.get_storage() != sp0);
|
||||
}
|
||||
{
|
||||
string str;
|
||||
value jv;
|
||||
|
||||
jv = str;
|
||||
BEAST_EXPECT(jv.is_string());
|
||||
BEAST_EXPECT(jv.get_storage() != sp);
|
||||
BEAST_EXPECT(jv.get_storage() == sp0);
|
||||
|
||||
jv.reset();
|
||||
BEAST_EXPECT(jv.is_null());
|
||||
BEAST_EXPECT(jv.get_storage() != sp);
|
||||
BEAST_EXPECT(jv.get_storage() == sp0);
|
||||
|
||||
jv = std::move(str);
|
||||
BEAST_EXPECT(jv.is_string());
|
||||
BEAST_EXPECT(jv.get_storage() != sp);
|
||||
BEAST_EXPECT(jv.get_storage() == sp0);
|
||||
}
|
||||
{
|
||||
string str;
|
||||
value jv(sp);
|
||||
|
||||
jv = str;
|
||||
BEAST_EXPECT(jv.is_string());
|
||||
BEAST_EXPECT(jv.get_storage() == sp);
|
||||
BEAST_EXPECT(jv.get_storage() != sp0);
|
||||
|
||||
jv.reset();
|
||||
BEAST_EXPECT(jv.is_null());
|
||||
BEAST_EXPECT(jv.get_storage() == sp);
|
||||
BEAST_EXPECT(jv.get_storage() != sp0);
|
||||
|
||||
jv = std::move(str);
|
||||
BEAST_EXPECT(jv.is_string());
|
||||
BEAST_EXPECT(jv.get_storage() == sp);
|
||||
BEAST_EXPECT(jv.get_storage() != sp0);
|
||||
}
|
||||
{
|
||||
number n(1);
|
||||
value jv;
|
||||
jv = n;
|
||||
BEAST_EXPECT(jv.is_number());
|
||||
BEAST_EXPECT(jv.is_int64());
|
||||
BEAST_EXPECT(jv.is_uint64());
|
||||
BEAST_EXPECT(jv.is_double());
|
||||
BEAST_EXPECT(jv.get_int64() == 1);
|
||||
BEAST_EXPECT(jv.get_uint64() == 1);
|
||||
BEAST_EXPECT(jv.get_double() == 1);
|
||||
BEAST_EXPECT(jv.as_number() == 1);
|
||||
BEAST_EXPECT(jv.get_storage() != sp);
|
||||
BEAST_EXPECT(jv.get_storage() == sp0);
|
||||
}
|
||||
{
|
||||
number n(1);
|
||||
value jv(sp);
|
||||
jv = n;
|
||||
BEAST_EXPECT(jv.is_number());
|
||||
BEAST_EXPECT(jv.is_int64());
|
||||
BEAST_EXPECT(jv.is_uint64());
|
||||
BEAST_EXPECT(jv.is_double());
|
||||
BEAST_EXPECT(jv.get_int64() == 1);
|
||||
BEAST_EXPECT(jv.get_uint64() == 1);
|
||||
BEAST_EXPECT(jv.get_double() == 1);
|
||||
BEAST_EXPECT(jv.as_number() == 1);
|
||||
BEAST_EXPECT(jv.get_storage() == sp);
|
||||
BEAST_EXPECT(jv.get_storage() != sp0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
testModifiers()
|
||||
{
|
||||
// reset
|
||||
{
|
||||
value jv;
|
||||
|
||||
jv.reset(kind::object);
|
||||
BEAST_EXPECT(jv.is_object());
|
||||
|
||||
jv.reset();
|
||||
BEAST_EXPECT(jv.is_null());
|
||||
|
||||
jv.reset(kind::array);
|
||||
BEAST_EXPECT(jv.is_array());
|
||||
|
||||
jv.reset(kind::string);
|
||||
BEAST_EXPECT(jv.is_string());
|
||||
|
||||
jv.reset(kind::number);
|
||||
BEAST_EXPECT(jv.is_number());
|
||||
|
||||
jv.reset(kind::boolean);
|
||||
BEAST_EXPECT(jv.is_bool());
|
||||
|
||||
jv.reset(kind::null);
|
||||
BEAST_EXPECT(jv.is_null());
|
||||
}
|
||||
|
||||
// assign
|
||||
{
|
||||
value jv;
|
||||
|
||||
jv = kind::object;
|
||||
BEAST_EXPECT(jv.is_object());
|
||||
|
||||
jv = kind::null;
|
||||
BEAST_EXPECT(jv.is_null());
|
||||
|
||||
jv = kind::array;
|
||||
BEAST_EXPECT(jv.is_array());
|
||||
|
||||
jv = kind::string;
|
||||
BEAST_EXPECT(jv.is_string());
|
||||
|
||||
jv = kind::number;
|
||||
BEAST_EXPECT(jv.is_number());
|
||||
|
||||
jv = kind::boolean;
|
||||
BEAST_EXPECT(jv.is_bool());
|
||||
|
||||
jv = kind::null;
|
||||
BEAST_EXPECT(jv.is_null());
|
||||
}
|
||||
|
||||
// emplace
|
||||
{
|
||||
{
|
||||
value jv;
|
||||
object& obj = jv.emplace_object();
|
||||
BEAST_EXPECT(jv.is_object());
|
||||
obj.clear();
|
||||
}
|
||||
{
|
||||
value jv;
|
||||
array& arr = jv.emplace_array();
|
||||
BEAST_EXPECT(jv.is_array());
|
||||
arr.clear();
|
||||
}
|
||||
{
|
||||
value jv;
|
||||
string& str = jv.emplace_string();
|
||||
BEAST_EXPECT(jv.is_string());
|
||||
str.clear();
|
||||
}
|
||||
{
|
||||
value jv;
|
||||
number& n= jv.emplace_number();
|
||||
BEAST_EXPECT(jv.is_number());
|
||||
n = 0;
|
||||
}
|
||||
{
|
||||
value jv;
|
||||
bool& b= jv.emplace_bool();
|
||||
BEAST_EXPECT(jv.is_bool());
|
||||
b = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
testExchange()
|
||||
{
|
||||
// construct from T
|
||||
{
|
||||
value v3("Hello!");
|
||||
value(std::string("Hello!"));
|
||||
value(short{0});
|
||||
value(int{0});
|
||||
value(long{0});
|
||||
value((long long)0);
|
||||
value((unsigned short)0);
|
||||
value((unsigned int)0);
|
||||
value((unsigned long)0);
|
||||
value((unsigned long long)0);
|
||||
value(float{0});
|
||||
value(double{0});
|
||||
value(true);
|
||||
value(false);
|
||||
value v4(null);
|
||||
value(nullptr);
|
||||
}
|
||||
|
||||
// assign from T
|
||||
{
|
||||
value jv;
|
||||
jv = "Hello!";
|
||||
jv = std::string("Hello!");
|
||||
jv = short{};
|
||||
jv = int{};
|
||||
jv = long{};
|
||||
jv = (long long)0;
|
||||
jv = (unsigned short)0;
|
||||
jv = (unsigned int)0;
|
||||
jv = (unsigned long)0;
|
||||
jv = (unsigned long long)0;
|
||||
jv = float{};
|
||||
jv = double{};
|
||||
jv = true;
|
||||
jv = false;
|
||||
jv = null;
|
||||
jv = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
testAccessors()
|
||||
{
|
||||
// raw
|
||||
value jv;
|
||||
value const& jc(jv);
|
||||
{
|
||||
jv = kind::object;
|
||||
BEAST_EXPECT(
|
||||
jv.as_object().size() == 0);
|
||||
jc.as_object();
|
||||
}
|
||||
{
|
||||
jv = kind::array;
|
||||
BEAST_EXPECT(
|
||||
jv.as_array().size() == 0);
|
||||
jc.as_array();
|
||||
}
|
||||
{
|
||||
jv = "x";
|
||||
jv.as_string() = "y";
|
||||
BEAST_EXPECT(jc.as_string() == "y");
|
||||
}
|
||||
{
|
||||
jv = signed{};
|
||||
BEAST_EXPECT(jc.get_int64() == 0);
|
||||
jv.as_number() = -1;
|
||||
BEAST_EXPECT(jc.get_int64() == -1);
|
||||
}
|
||||
{
|
||||
jv = unsigned{};
|
||||
jv.as_number() = 2;
|
||||
BEAST_EXPECT(jc.get_uint64() == 2);
|
||||
}
|
||||
{
|
||||
jv = bool{};
|
||||
jv.as_bool() = true;
|
||||
BEAST_EXPECT(jc.as_bool());
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
testStructured()
|
||||
{
|
||||
// empty()
|
||||
{
|
||||
value v;
|
||||
v = kind::object;
|
||||
BEAST_EXPECT(v.empty());
|
||||
v = kind::array;
|
||||
BEAST_EXPECT(v.empty());
|
||||
}
|
||||
|
||||
// size()
|
||||
{
|
||||
value v;
|
||||
v = kind::object;
|
||||
v.as_object().emplace("x", 1);
|
||||
BEAST_EXPECT(v.size() == 1);
|
||||
v = kind::array;
|
||||
v.as_array().emplace_back(1);
|
||||
BEAST_EXPECT(v.size() == 1);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
testCustomization()
|
||||
{
|
||||
using namespace value_test_ns;
|
||||
|
||||
// to_json
|
||||
{
|
||||
T1 t;
|
||||
value jv(t);
|
||||
}
|
||||
{
|
||||
T2 t;
|
||||
value jv(t);
|
||||
}
|
||||
{
|
||||
T3 t;
|
||||
value jv(t);
|
||||
}
|
||||
}
|
||||
|
||||
BOOST_STATIC_ASSERT(
|
||||
detail::is_range<std::vector<int>>::value);
|
||||
|
||||
BOOST_STATIC_ASSERT(
|
||||
detail::is_range<std::initializer_list<int>>::value);
|
||||
|
||||
void run() override
|
||||
{
|
||||
log <<
|
||||
"sizeof(value) == " <<
|
||||
sizeof(value) << "\n";
|
||||
log <<
|
||||
"sizeof(object) == " <<
|
||||
sizeof(object) << "\n";
|
||||
log <<
|
||||
"sizeof(array) == " <<
|
||||
sizeof(array) << "\n";
|
||||
log <<
|
||||
"sizeof(string) == " <<
|
||||
sizeof(string) << "\n";
|
||||
log <<
|
||||
"sizeof(number) == " <<
|
||||
sizeof(number) << "\n";
|
||||
|
||||
testSpecial();
|
||||
testConstruct();
|
||||
testModifiers();
|
||||
testExchange();
|
||||
testAccessors();
|
||||
testStructured();
|
||||
testCustomization();
|
||||
}
|
||||
};
|
||||
|
||||
BEAST_DEFINE_TESTSUITE(beast,json,value);
|
||||
|
||||
} // json
|
||||
} // beast
|
||||
} // boost
|
||||
|
||||
Reference in New Issue
Block a user