mirror of
https://github.com/openappsec/attachment.git
synced 2025-06-28 16:41:03 +03:00
Add docket support
This commit is contained in:
parent
09847ac179
commit
3703b14ba6
@ -1,12 +1,13 @@
|
||||
cmake_minimum_required (VERSION 2.8.4)
|
||||
project (ngen)
|
||||
cmake_minimum_required(VERSION 2.8.4)
|
||||
project(ngen)
|
||||
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fPIC")
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fPIC -Wno-terminate")
|
||||
|
||||
set (CMAKE_CXX_STANDARD 11)
|
||||
set(CMAKE_CXX_STANDARD 11)
|
||||
|
||||
include_directories(external)
|
||||
include_directories(core/include/attachments)
|
||||
|
||||
add_subdirectory(core)
|
||||
add_subdirectory(attachments)
|
||||
add_subdirectory(docker)
|
||||
|
@ -1,7 +1,8 @@
|
||||
# Welcome to open-appsec's Open Sources Contributing Guide
|
||||
We welcome everyone that wishes to share their expetise in improving open-appsec.
|
||||
Thank you for investing your time to consider a contribution to our project!
|
||||
Various open source repositories were released as part of Check Point's platform for distributing and deploying security applications for a variety of environments. We welcome everyone that wishes to share their knowledge and expertise to enhance and expand both our platform, and our ability to secure more environments.
|
||||
|
||||
Please ead our [Code of Conduct](./CODE_OF_CONDUCT.md) to keep our community approachable and respectable.
|
||||
Read our [Code of Conduct](./CODE_OF_CONDUCT.md) to keep our community approachable and respectable.
|
||||
|
||||
In this guide we will provide an overview of the various contribution options' guidelines - from reporting or fixing a bug, to suggesting an enhancement.
|
||||
|
||||
@ -15,7 +16,7 @@ An internal process will be activated upon determining the validity of a reporte
|
||||
|
||||
**Important - If the bug you wish to report regards a suspicion of a security vulnerability, please refer to the "Reporting security vulnerability" section**
|
||||
|
||||
To report a bug, you can either open a new issue using a relevant [issue form](https://github.com/github/docs/issues/new/choose), or, alternatively, contact us using [this email](mailto:opensource@openappsec.io).
|
||||
To report a bug, you can either open a new issue using a relevant [issue form](https://github.com/github/docs/issues/new/choose), or, alternatively, [contact us via our open-appsec open source distribution list](mailto:opensource@openappsec.io).
|
||||
|
||||
Be sure to include a **title and clear description**, as much relevant information as possible, and a **code sample** or an **executable test case** demonstrating the expected behavior that is not occurring.
|
||||
|
||||
@ -30,3 +31,10 @@ Please [suggest your change via our open-appsec open source distribution list](m
|
||||
## Open Source documentation issues
|
||||
|
||||
For reporting or suggesting a change, of any issue detected in the documentation files of our open source repositories, please use the same guidelines as bug reports/fixes.
|
||||
|
||||
# Final Thanks
|
||||
We value all users that use our open source files.
|
||||
We value all efforts to read, suggest changes and/or contribute to our open source files.
|
||||
Thank you for it.
|
||||
|
||||
The open-appsec Team
|
||||
|
88
README.md
88
README.md
@ -1,11 +1,11 @@
|
||||
<div align=center>
|
||||
<img src="https://i2-s3-ui-static-content-prod-10.s3.eu-west-1.amazonaws.com/elpis/tree-no-bg-256.png" width="100" height="100">
|
||||
<h1>openappsec/attachment</h1>
|
||||
<h1>openappsec/attachement</h1>
|
||||
</div>
|
||||
|
||||
## About
|
||||
|
||||
open-appsec (https://www.openappsec.io) is a machine learning security engine that preemptively and automatically prevent threats against Web Application & APIs.
|
||||
open-appsec is a machine learning security engine that preemptively and automatically prevent threats against Web Application & APIs.
|
||||
|
||||
<strong>open-appsec Attachments</strong> connect between processes that provide HTTP data and the <strong>open-appsec Agent</strong> security logic.
|
||||
|
||||
@ -18,44 +18,78 @@ This repository will host Attachment for different platforms. The first one is t
|
||||
|
||||
## open-appsec NGINX attachment compilation instructions
|
||||
|
||||
### Compiling the attachment code
|
||||
The attchment can be compiled to support an existing alpine based nginx server or an nginx/ingress-nginx alpine based docker.
|
||||
|
||||
Your compilation environment must be alpine based and contain git, docker, cmake and g++.
|
||||
|
||||
Before compiling, ensure the latest development versions of the following libraries:
|
||||
|
||||
* PCRE
|
||||
* libxml2
|
||||
* zlib
|
||||
* OpenSSL
|
||||
* Geoip
|
||||
|
||||
```bash
|
||||
$ apk update
|
||||
$ apk add pcre-dev libxml2-dev zlib-dev openssl-dev geoip-dev
|
||||
```
|
||||
|
||||
### Compiling the attachment code for an existing nginx server
|
||||
|
||||
On your existing nginx server:
|
||||
1. Run command to extract nginx compilation flags to a file
|
||||
|
||||
```bash
|
||||
$ nginx -V &> /tmp/nginx.ver
|
||||
```
|
||||
|
||||
On your compilation environment:
|
||||
1. Clone this repository
|
||||
2. Run CMake command
|
||||
3. Run make install command
|
||||
2. Copy the file created on your nginx server (the previous section) to your compilation environment to the path /tmp/nginx.ver
|
||||
3. Run Configuration script
|
||||
4. Run CMake command
|
||||
5. Run make command
|
||||
|
||||
```bash
|
||||
$ git clone https://github.com/openappsec/attachment.git
|
||||
$ cd attachment/
|
||||
$ ./attachments/nginx/ngx_module/nginx_version_configuration.sh --conf /tmp/nginx.ver build_out
|
||||
$ cmake -DCMAKE_INSTALL_PREFIX=build_out .
|
||||
$ make install
|
||||
```
|
||||
|
||||
### NGINX plugin
|
||||
|
||||
NGINX Plugins are built per specific version.
|
||||
1. Get nginx source code from [nginx.org](http://nginx.org/), e.g. version 1.23.0 (see [nginx compatibility](http://nginx.org/en/docs/njs/compatibility.html))
|
||||
2. Run make modules
|
||||
|
||||
```bash
|
||||
$ module_path=/<absolute-path>/attachment
|
||||
|
||||
$ wget 'https://nginx.org/download/nginx-1.23.0.tar.gz'
|
||||
$ sha256sum nginx-1.23.0.tar.gz
|
||||
820acaa35b9272be9e9e72f6defa4a5f2921824709f8aa4772c78ab31ed94cd1 nginx-1.23.0.tar.gz
|
||||
|
||||
$ tar -xzvf nginx-1.23.0.tar.gz
|
||||
$ cd nginx-1.23.0/
|
||||
|
||||
$ ./configure --add-dynamic-module=$module_path --with-cc-opt="-I $module_path/core/include/attachments"
|
||||
|
||||
$ make modules
|
||||
```
|
||||
|
||||
#### NGINX plugin associated libraries
|
||||
The NGINX plugin uses these libraries: shmem_ipc, compression_utils, and nginx_attachment_util.
|
||||
|
||||
They can be found under the `lib` directory in the `<output path>` given to the CMake.
|
||||
|
||||
#### Deploying the attachment on an existing alpine nginx server
|
||||
|
||||
1. Copy the associated libraries to /usr/lib on your existing nginx server
|
||||
2. Copy the nginx attachment file lib/libngx_module.so to the following path on your existing nginx server: /usr/lib/nginx/modules/
|
||||
3. Load the attachment on your nginx by adding the following command to the main nginx.conf file:
|
||||
load_module /usr/lib/nginx/modules/libngx_module.so;
|
||||
4. Restart your nginx server.
|
||||
|
||||
### Compiling the attachment code and create a docker image for an existing nginx/ingres-nginx alpine docker
|
||||
|
||||
This step requires Docker to be installed on your comilation environment
|
||||
|
||||
1. Clone this repository
|
||||
3. Run Configuration script with the required docker image name and tag
|
||||
4. Run CMake command
|
||||
5. Run make command
|
||||
|
||||
```bash
|
||||
$ git clone https://github.com/openappsec/attachment.git
|
||||
$ ./attachments/nginx/ngx_module/nginx_version_configuration.sh --docker <input docker image> build_out
|
||||
$ cmake -DCMAKE_INSTALL_PREFIX=build_out -DOUTPUT_DOCKER_IMAGE=<output docker image> .
|
||||
$ make install
|
||||
$ make docker
|
||||
```
|
||||
|
||||
Later on, you can push the image to your own registry in use it as needed.
|
||||
|
||||
## License
|
||||
|
||||
open-appsec/attachment is open source and available under the Apache 2.0 license.
|
||||
|
@ -1 +1,2 @@
|
||||
add_subdirectory(nginx_attachment_util)
|
||||
add_subdirectory(ngx_module)
|
||||
|
@ -1,5 +1,6 @@
|
||||
add_definitions(-DUSERSPACE)
|
||||
|
||||
add_library(osrc_nginx_attachment_util SHARED nginx_attachment_util.cc)
|
||||
target_link_libraries(osrc_nginx_attachment_util http_configuration)
|
||||
|
||||
install(TARGETS osrc_nginx_attachment_util DESTINATION lib)
|
||||
|
@ -83,6 +83,18 @@ getFailOpenTimeout()
|
||||
return conf_data.getNumericalValue("fail_open_timeout");
|
||||
}
|
||||
|
||||
int
|
||||
isFailOpenHoldMode()
|
||||
{
|
||||
return conf_data.getNumericalValue("is_fail_open_mode_hold_enabled");
|
||||
}
|
||||
|
||||
unsigned int
|
||||
getFailOpenHoldTimeout()
|
||||
{
|
||||
return conf_data.getNumericalValue("fail_open_hold_timeout");
|
||||
}
|
||||
|
||||
unsigned int
|
||||
getMaxSessionsPerMinute()
|
||||
{
|
||||
@ -137,6 +149,12 @@ getResBodyThreadTimeout()
|
||||
return conf_data.getNumericalValue("res_body_thread_timeout_msec");
|
||||
}
|
||||
|
||||
unsigned int
|
||||
getWaitingForVerdictThreadTimeout()
|
||||
{
|
||||
return conf_data.getNumericalValue("waiting_for_verdict_thread_timeout_msec");
|
||||
}
|
||||
|
||||
int
|
||||
isIPAddress(c_str ip_str)
|
||||
{
|
||||
|
48
attachments/nginx/ngx_module/CMakeLists.txt
Normal file
48
attachments/nginx/ngx_module/CMakeLists.txt
Normal file
@ -0,0 +1,48 @@
|
||||
MACRO(CREATE_INCLUDE_LIST result)
|
||||
file(READ ${CMAKE_INSTALL_PREFIX}/nginx-src/include_paths.mk relative_includes)
|
||||
STRING(REGEX REPLACE "\n" ";" relative_includes "${relative_includes}")
|
||||
set(inclist "")
|
||||
FOREACH(include ${relative_includes})
|
||||
if(NOT include MATCHES "^/")
|
||||
set(inclist ${inclist} "${CMAKE_INSTALL_PREFIX}/nginx-src/${include}")
|
||||
else()
|
||||
set(inclist ${inclist} "${include}")
|
||||
endif()
|
||||
ENDFOREACH()
|
||||
set(${result} ${inclist})
|
||||
ENDMACRO()
|
||||
|
||||
MACRO(READ_COMPILE_FLAGS result)
|
||||
file(READ ${CMAKE_INSTALL_PREFIX}/nginx-src/cc_flags.mk CC_FLAGS)
|
||||
string(REGEX REPLACE "\n" "" CC_FLAGS "${CC_FLAGS}")
|
||||
set(flag_list "")
|
||||
FOREACH(flag ${CC_FLAGS})
|
||||
if (flag MATCHES "-fstack-clash-protection" OR flag MATCHES "-fcf-protection" OR flag MATCHES "-Wno-cast-function-type")
|
||||
continue()
|
||||
endif()
|
||||
|
||||
set(flag_list ${flag_list} "${flag}")
|
||||
ENDFOREACH()
|
||||
separate_arguments(flag_list)
|
||||
set(${result} ${flag_list})
|
||||
ENDMACRO()
|
||||
|
||||
add_library(
|
||||
ngx_module
|
||||
SHARED
|
||||
ngx_http_cp_attachment_module.c ngx_cp_thread.c ngx_cp_hook_threads.c ngx_cp_hooks.c ngx_cp_utils.c
|
||||
ngx_cp_initializer.c ngx_cp_io.c ngx_cp_static_content.c ngx_cp_custom_response.c ngx_modules.c
|
||||
ngx_cp_compression.c ngx_cp_http_parser.c ngx_cp_failing_state.c ngx_cp_metric.c
|
||||
)
|
||||
|
||||
add_dependencies(ngx_module osrc_shmem_ipc osrc_nginx_attachment_util osrc_compression_utils)
|
||||
|
||||
target_link_libraries(ngx_module osrc_shmem_ipc osrc_nginx_attachment_util osrc_compression_utils)
|
||||
|
||||
CREATE_INCLUDE_LIST(NGX_INCLUDES)
|
||||
READ_COMPILE_FLAGS(CC_FLAG_LIST)
|
||||
|
||||
target_include_directories(ngx_module PRIVATE ${NGX_INCLUDES})
|
||||
target_compile_options(ngx_module PRIVATE ${CC_FLAG_LIST})
|
||||
|
||||
install(TARGETS ngx_module DESTINATION lib)
|
66
attachments/nginx/ngx_module/nginx_version_configuration.sh
Executable file
66
attachments/nginx/ngx_module/nginx_version_configuration.sh
Executable file
@ -0,0 +1,66 @@
|
||||
#!/bin/bash
|
||||
|
||||
NGINX_VERSION_CONF_INPUT_PATH=/tmp/nginx.sourcefile.ver
|
||||
if [ "${1}" == "--docker" ]; then
|
||||
docker run -it ${2} nginx -V > ${NGINX_VERSION_CONF_INPUT_PATH}
|
||||
elif [ "${1}" == "--conf" ]; then
|
||||
cp ${2} ${NGINX_VERSION_CONF_INPUT_PATH}
|
||||
else
|
||||
echo "Usage: ${0} [--conf <input nginx compilation flags file> | --docker <input docker name>] <compilation artifacts directory>"
|
||||
exit 1
|
||||
fi
|
||||
NGINX_VERSION_CONF_OUTPUT_PATH=/tmp/nginx.sourcefile.conf
|
||||
$(dirname $0)/nginx_version_extractor.sh -i ${NGINX_VERSION_CONF_INPUT_PATH} -o ${NGINX_VERSION_CONF_OUTPUT_PATH}
|
||||
BUILD_OUTPUT_DIR=${3}
|
||||
|
||||
if [[ ${BUILD_OUTPUT_DIR} != /* ]]; then
|
||||
BUILD_OUTPUT_DIR=$(pwd)/${BUILD_OUTPUT_DIR}
|
||||
fi
|
||||
|
||||
source ${NGINX_VERSION_CONF_OUTPUT_PATH}
|
||||
|
||||
CURRENT_PWD=$(pwd)
|
||||
|
||||
mkdir -p ${BUILD_OUTPUT_DIR}
|
||||
cd ${BUILD_OUTPUT_DIR}
|
||||
|
||||
wget --no-check-certificate https://nginx.org/download/nginx-${NGINX_VERSION}.tar.gz
|
||||
|
||||
tar -xzvf nginx-${NGINX_VERSION}.tar.gz
|
||||
|
||||
rm nginx-${NGINX_VERSION}.tar.gz
|
||||
|
||||
mv nginx-${NGINX_VERSION} nginx-src
|
||||
cd nginx-src
|
||||
|
||||
if test ! -f configured.ok; then
|
||||
echo "Configuring nginx compiler: ./configure ${CONFIGURE_OPT} --with-cc-opt=\"${EXTRA_CC_OPT} ${LOCAL_CC_OPT}\" && touch configured.ok"
|
||||
./configure ${CONFIGURE_OPT} --with-cc-opt="${EXTRA_CC_OPT} ${LOCAL_CC_OPT}" && touch configured.ok
|
||||
else
|
||||
echo "Nginx compiler already Configured...\n"
|
||||
fi
|
||||
|
||||
make && echo "${EXTRA_CC_OPT}" > cc_flags.mk
|
||||
|
||||
|
||||
OUTPUT_FILE_NAME=include_paths.mk
|
||||
|
||||
ALL_INCS=$(cat objs/Makefile|grep -v \$\(ALL_INCS\) | awk '/ALL_INCS/' RS="\n\n" ORS="\n\n" | tr '\\' ' ')
|
||||
ALL_INCS=${ALL_INCS/ALL_INCS =/}
|
||||
ALL_INCS=$(sed "s/-I//g" <<< "${ALL_INCS}")
|
||||
|
||||
echo > include_paths.mk
|
||||
for include in ${ALL_INCS}; do
|
||||
echo $include >> include_paths.mk
|
||||
done
|
||||
|
||||
cd ${CURRENT_PWD}
|
||||
|
||||
if [ "${1}" == "--docker" ]; then
|
||||
cp -f $(dirname $0)/../../../docker/Dockerfile ${BUILD_OUTPUT_DIR}/Dockerfile
|
||||
sed -i "s|<DOCKER BASE IMAGE>|${2}|g" ${BUILD_OUTPUT_DIR}/Dockerfile
|
||||
docker run -it ${2} whoami > /tmp/usertouse
|
||||
USER_NAME="$(cat /tmp/usertouse)"
|
||||
rm /tmp/usertouse
|
||||
sed -i "s|<DOCKER USER>|${USER_NAME}|g" ${BUILD_OUTPUT_DIR}/Dockerfile
|
||||
fi
|
347
attachments/nginx/ngx_module/nginx_version_extractor.sh
Executable file
347
attachments/nginx/ngx_module/nginx_version_extractor.sh
Executable file
@ -0,0 +1,347 @@
|
||||
#!/bin/bash
|
||||
|
||||
initializeEnviroment()
|
||||
{
|
||||
CURRENT_TIME=""
|
||||
PACKAGE_VERSION=""
|
||||
CUR_NGINX_ALREADY_SUPPORTED=false
|
||||
NUMBER_OF_CONFIGURATION_FLAGS=0
|
||||
TMP_NGINX_UNPARSED_CONFIGURATION="/tmp/nginx_unparsed_tmp_conf.txt"
|
||||
TMP_NGINX_PARSED_CONFIGURATION_FLAGS="/tmp/nginx_parsed_conf_flags.txt"
|
||||
TMP_DECODED_FILE_PATH="/tmp/decoded_file.txt"
|
||||
IS_ALPINE=false
|
||||
if [ ! -z "$(cat /etc/*release | grep alpine)" ]; then
|
||||
IS_ALPINE=true
|
||||
fi
|
||||
}
|
||||
|
||||
usage()
|
||||
{
|
||||
local IS_ERROR=$1
|
||||
local option=$2
|
||||
if [[ ${IS_ERROR} == true ]]; then
|
||||
echo "Error: unsupported option '${option}'"
|
||||
fi
|
||||
|
||||
echo "Usage:"
|
||||
line_padding=" "
|
||||
local debug_print_option="-h, --help"
|
||||
printf "%s %s Print (this) help message\n" "$debug_print_option" "${line_padding:${#debug_print_option}}"
|
||||
debug_print_option="-d, --debug"
|
||||
printf "%s %s Enable debug mode\n" "$debug_print_option" "${line_padding:${#debug_print_option}}"
|
||||
debug_print_option="-v, --verbose"
|
||||
printf "%s %s show version and configure options\n" "$debug_print_option" "${line_padding:${#debug_print_option}}"
|
||||
debug_print_option="-o, --output"
|
||||
printf "%s %s change output file name into '${option}'\n" "$debug_print_option" "${line_padding:${#debug_print_option}}"
|
||||
debug_print_option="-f, --force"
|
||||
printf "%s %s force creation of makefile'\n" "$debug_print_option" "${line_padding:${#debug_print_option}}"
|
||||
|
||||
if [[ ${IS_ERROR} == true ]]; then
|
||||
exit -1
|
||||
else
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
debug()
|
||||
{
|
||||
local debug_message=$1
|
||||
if [[ $IS_DEBUG_MODE_ACTIVE == true ]]; then
|
||||
echo -e $debug_message
|
||||
fi
|
||||
}
|
||||
|
||||
check_flags_options()
|
||||
{
|
||||
local argc=$#
|
||||
|
||||
for (( i = 1; i <= $argc; i++ )); do
|
||||
local option=${!i}
|
||||
local IS_ERROR=false
|
||||
if [[ "$option" == "--debug" || "$option" == "-d" ]]; then
|
||||
IS_DEBUG_MODE_ACTIVE=true
|
||||
elif [[ "$option" == "--verbose" || "$option" == "-v" ]]; then
|
||||
IS_VERBOSE_MODE_ACTIVE=true
|
||||
elif [[ "$option" == "--force" || "$option" == "-f" ]]; then
|
||||
IS_FORCE_OUTPUT=true
|
||||
elif [[ "$option" == "--output" || "$option" == "-o" ]]; then
|
||||
IS_OUTPUT_NAME_MODE_ACTIVE=true
|
||||
i=$((i+1))
|
||||
FILE_NAME=${!i}
|
||||
if [[ -z ${FILE_NAME} ]]; then
|
||||
echo "Error: No file name was given for ${option} option."
|
||||
exit -1
|
||||
fi
|
||||
elif [[ "$option" == "--input" || "$option" == "-i" ]]; then
|
||||
i=$((i+1))
|
||||
if [[ -z ${!i} ]]; then
|
||||
echo "Error: No file name was given for ${option} option."
|
||||
exit -1
|
||||
fi
|
||||
cp -f ${!i} ${TMP_NGINX_UNPARSED_CONFIGURATION}
|
||||
IS_INPUT_NAME_MODE_ACTIVE=true
|
||||
elif [[ "$option" == "--help" || "$option" == "-h" ]]; then
|
||||
usage ${IS_ERROR} ${option}
|
||||
elif [[ ! -z $option ]]; then
|
||||
IS_ERROR=true
|
||||
usage ${IS_ERROR} ${option}
|
||||
fi
|
||||
done
|
||||
}
|
||||
|
||||
_main()
|
||||
{
|
||||
echo "Starting verification of Check Point support with local nginx server"
|
||||
initializeEnviroment
|
||||
|
||||
if [[ ${IS_INPUT_NAME_MODE_ACTIVE} != true ]]; then
|
||||
nginx -V &> "$TMP_NGINX_UNPARSED_CONFIGURATION"
|
||||
fi
|
||||
getNginxVersion
|
||||
|
||||
if [[ $IS_VERBOSE_MODE_ACTIVE == true ]]; then
|
||||
echo ""
|
||||
cat ${TMP_NGINX_UNPARSED_CONFIGURATION}
|
||||
echo ""
|
||||
fi
|
||||
|
||||
while IFS= read -ra UNPARSED_CONFIGURATION_LINE <&3; do
|
||||
if [[ ${UNPARSED_CONFIGURATION_LINE} =~ ^"nginx version:" ]]; then
|
||||
openFile
|
||||
elif [[ ${UNPARSED_CONFIGURATION_LINE} =~ ^"built by gcc" ]]; then
|
||||
addBuiltConfiguration "${UNPARSED_CONFIGURATION_LINE}"
|
||||
elif [[ ${UNPARSED_CONFIGURATION_LINE} =~ ^"configure arguments:" ]]; then
|
||||
IFS="'"
|
||||
addAndCutOptionalFlags ${UNPARSED_CONFIGURATION_LINE}
|
||||
IFS=" "
|
||||
addRequiredFlags ${CONFIGURATION_FLAGES_NEED_TO_BE_PARSED}
|
||||
fi
|
||||
done 3<"$TMP_NGINX_UNPARSED_CONFIGURATION"
|
||||
|
||||
PARSED_CONFIGURATION="CONFIGURE_OPT=\"${COMBINED_CONFIGURATION_FLAGS}\"\n\n"
|
||||
NUMBER_OF_CONFIGURATION_FLAGS=$((NUMBER_OF_CONFIGURATION_FLAGS-1))
|
||||
local local_pwd=$(pwd)
|
||||
if [[ ${local_pwd:0:2} == "//" ]]; then
|
||||
local_pwd=${local_pwd:1}
|
||||
fi
|
||||
debug "Moving parsed configuration to target ${local_pwd}/${FILE_NAME} configuration file"
|
||||
echo -e ${PARSED_CONFIGURATION} > ${FILE_NAME}
|
||||
echo -e ${CC_OPTIONAL_FLAGS} >> ${FILE_NAME}
|
||||
add_nginx_and_release_versions
|
||||
if [[ $CUR_NGINX_ALREADY_SUPPORTED == true ]]; then
|
||||
tearDown
|
||||
echo -e "Check Point Nano Agent already supported on this environment"
|
||||
else
|
||||
tearDown
|
||||
echo -e "Extracted environment data to $(pwd)/${FILE_NAME} \nPlease send file to nano-agent-attachments-support@checkpoint.com"
|
||||
fi
|
||||
}
|
||||
|
||||
tearDown()
|
||||
{
|
||||
rm -f ${TMP_NGINX_UNPARSED_CONFIGURATION}
|
||||
rm -f ${TMP_NGINX_PARSED_CONFIGURATION_FLAGS}
|
||||
rm -f ${TMP_DECODED_FILE_PATH}
|
||||
rm -f ${TMP_NGINX_VERSION_FILE}
|
||||
}
|
||||
|
||||
getNginxVersion()
|
||||
{
|
||||
TMP_NGINX_VERSION_FILE="/tmp/nginx_version_file.txt"
|
||||
cat ${TMP_NGINX_UNPARSED_CONFIGURATION} | grep "nginx version:" &> "$TMP_NGINX_VERSION_FILE"
|
||||
if [[ $IS_ALPINE == true ]]; then
|
||||
NGINX_VERSION=`cat ${TMP_NGINX_VERSION_FILE} | grep -oE [0-9]+.[0-9]+.[0-9]+`
|
||||
else
|
||||
NGINX_VERSION=`cat ${TMP_NGINX_VERSION_FILE} | grep -oP [0-9]+.[0-9]+.[0-9]+`
|
||||
fi
|
||||
}
|
||||
|
||||
openFile()
|
||||
{
|
||||
if [[ ${IS_OUTPUT_NAME_MODE_ACTIVE} != true ]]; then
|
||||
FILE_NAME="${NGINX_VERSION}.mk"
|
||||
debug "Trying to create an empty ${NGINX_VERSION} file"
|
||||
FILE_NAME_PATH="$(pwd)/${FILE_NAME}"
|
||||
|
||||
if [[ -z ${FILE_NAME_PATH} || ! ( ${FILE_NAME} =~ [0-9]+.[0-9]+.[0-9]+.mk ) ]]; then
|
||||
echo "ERROR: can't find nginx version."
|
||||
exit -1
|
||||
fi
|
||||
|
||||
if [[ -f "${FILE_NAME_PATH}" ]]; then
|
||||
echo "The output file: ${FILE_NAME} already exists. Do you want to overwrite this file? [y/N]"
|
||||
read answer
|
||||
if [[ ${answer} != "y" ]]; then
|
||||
echo -e "Stopping after the operation was cancelled.\nIf you wish to use other output file name you can use option -o or --output"
|
||||
exit -1
|
||||
fi
|
||||
fi
|
||||
else
|
||||
debug "Trying to create an empty ${FILE_NAME} file"
|
||||
FILE_NAME_PATH="${FILE_NAME}"
|
||||
fi
|
||||
|
||||
touch ${FILE_NAME_PATH} &> /dev/null
|
||||
if [ ! -e ${FILE_NAME_PATH} ];then
|
||||
echo "Failed to create ${FILE_NAME_PATH}"
|
||||
exit -1
|
||||
fi
|
||||
debug "Created an empty ${FILE_NAME} file"
|
||||
}
|
||||
|
||||
checkAllDBLineFlags()
|
||||
{
|
||||
local argc=$#
|
||||
local argv=("$@")
|
||||
local number_of_db_line_flags=$((argc-3))
|
||||
local gcc_version_prefix="--with-cc="
|
||||
|
||||
if [[ ${number_of_db_line_flags} == ${NUMBER_OF_CONFIGURATION_FLAGS} ]]; then
|
||||
for ((i = 3; i < ${argc}; i++)); do
|
||||
if [[ ${argv[i]} =~ ^"${gcc_version_prefix}"* ]]; then
|
||||
continue
|
||||
fi
|
||||
checkFlag ${argv[i]}
|
||||
if [[ ${found_equal_flag} == false ]]; then
|
||||
EQUAL_FLAGS=false
|
||||
return
|
||||
fi
|
||||
done
|
||||
else return
|
||||
fi
|
||||
|
||||
EQUAL_FLAGS=true
|
||||
}
|
||||
|
||||
checkFlag()
|
||||
{
|
||||
found_equal_flag=false
|
||||
db_flag=$1
|
||||
while IFS='\' read -ra flag; do
|
||||
if [[ "${flag}" == "${db_flag}" ]] || [[ "${flag} " == "${db_flag}" ]]; then
|
||||
found_equal_flag=true
|
||||
break
|
||||
fi
|
||||
done < ${TMP_NGINX_PARSED_CONFIGURATION_FLAGS}
|
||||
}
|
||||
|
||||
addBuiltConfiguration()
|
||||
{
|
||||
BUILT_BY_GCC_FLAG_PREFIX="--with-cc=/usr/bin/"
|
||||
if [[ $IS_ALPINE == true ]]; then
|
||||
GCC_VERSION=`echo "$1" | grep -oE "gcc "[0-9]+ | tr ' ' '-'`
|
||||
else
|
||||
GCC_VERSION=`echo "$1" | grep -oP "gcc "[0-9]+ | tr ' ' '-'`
|
||||
fi
|
||||
if [[ "$GCC_VERSION" == "gcc-4" ]]; then
|
||||
GCC_VERSION=gcc-5
|
||||
elif [[ "$GCC_VERSION" == "gcc-10" ]] || [[ "$GCC_VERSION" == "gcc-11" ]]; then
|
||||
GCC_VERSION=gcc-8
|
||||
fi
|
||||
BUILT_BY_GCC_FLAG=" \\\\\n${BUILT_BY_GCC_FLAG_PREFIX}${GCC_VERSION}"
|
||||
NUMBER_OF_CONFIGURATION_FLAGS=$((NUMBER_OF_CONFIGURATION_FLAGS+1))
|
||||
}
|
||||
|
||||
addAndCutOptionalFlags()
|
||||
{
|
||||
debug "Parsing all nginx configuration flags"
|
||||
CC_EXTRA_PREFIX="EXTRA_CC_OPT="
|
||||
CC_OPTIONAL_FLAG_PREFIX="--with-cc-opt="
|
||||
LD_OPTIONAL_FLAG_PREFIX="--with-ld-opt="
|
||||
local argc=$#
|
||||
local argv=("$@")
|
||||
for (( i = 0; i < $argc; i++ )); do
|
||||
if [[ ${argv[i]} == *"${CC_OPTIONAL_FLAG_PREFIX}"* ]]; then
|
||||
debug "Successfully added compilation flags"
|
||||
CONFIGURATION_FLAGES_NEED_TO_BE_PARSED="${CONFIGURATION_FLAGES_NEED_TO_BE_PARSED}${argv[i]}"
|
||||
i=$((i+1))
|
||||
IFS=" "
|
||||
addCCFlagsWithoutSpecsLocalFlag ${argv[i]}
|
||||
CC_OPTIONAL_FLAGS="${CC_EXTRA_PREFIX}\"${CC_OPTIONAL_FLAGS}\""
|
||||
elif [[ ${argv[i]} == *"${LD_OPTIONAL_FLAG_PREFIX}"* ]]; then
|
||||
CONFIGURATION_FLAGES_NEED_TO_BE_PARSED="${CONFIGURATION_FLAGES_NEED_TO_BE_PARSED}${argv[i]}"
|
||||
i=$((i+1))
|
||||
else
|
||||
CONFIGURATION_FLAGES_NEED_TO_BE_PARSED="${CONFIGURATION_FLAGES_NEED_TO_BE_PARSED}${argv[i]}"
|
||||
fi
|
||||
done
|
||||
debug "Successfully finished adding optional flags"
|
||||
}
|
||||
|
||||
addCCFlagsWithoutSpecsLocalFlag()
|
||||
{
|
||||
local argc=$#
|
||||
local argv=("$@")
|
||||
SPECS_FLAG_PREFIX="-specs="
|
||||
NO_ERROR_PREFIX="-Wno-error="
|
||||
FCF_PROTECTION_PREFIX="-fcf-protection"
|
||||
FSTACK_PREFIX="-fstack-clash-protection"
|
||||
|
||||
for (( j = 0; j < $argc; j++ )); do
|
||||
if [[ ! ${argv[j]} =~ ^${SPECS_FLAG_PREFIX} ]] && \
|
||||
[[ ! ${argv[j]} =~ ^${NO_ERROR_PREFIX} ]] && \
|
||||
[[ ! ${argv[j]} =~ ^${FSTACK_PREFIX} ]] && \
|
||||
[[ ! ${argv[j]} =~ ^${FCF_PROTECTION_PREFIX} ]]; \
|
||||
then
|
||||
CC_OPTIONAL_FLAGS="${CC_OPTIONAL_FLAGS} ${argv[j]}"
|
||||
fi
|
||||
done
|
||||
CC_OPTIONAL_FLAGS=`echo $CC_OPTIONAL_FLAGS | grep ^"-"`
|
||||
}
|
||||
|
||||
addRequiredFlags()
|
||||
{
|
||||
local argc=$#
|
||||
local argv=("$@")
|
||||
CC_OPTIONAL_FLAG_PREFIX="--with-cc-opt="
|
||||
LD_OPTIONAL_FLAG_PREFIX="--with-ld-opt="
|
||||
ADDITIONAL_MODULE_FLAG_PREFIX="--add-module="
|
||||
DYNAMIC_MODULE_FLAG_PREFIX="--add-dynamic-module="
|
||||
BUILD_FLAG_PREFIX="--build="
|
||||
OPENSSL_VERSION_PREFIX="--with-openssl="
|
||||
OPENSSL_OPT_PREFIX="--with-openssl-opt="
|
||||
HPACK_ENC_PREFIX="--with-http_v2_hpack_enc"
|
||||
AUTH_JWT_PREFIX="--with-http_auth_jwt_module"
|
||||
F4F_PREFIX="--with-http_f4f_module"
|
||||
HLS_PREFIX="--with-http_hls_module"
|
||||
SESSION_LOG_PREFIX="--with-http_session_log_module"
|
||||
COMMON_PREFIX="--"
|
||||
WITH_CC_PREFIX="--with-cc"
|
||||
|
||||
for (( i = 1; i < $argc; i++ )); do
|
||||
if [[ "${argv[i]}" =~ ^${COMMON_PREFIX} ]] && \
|
||||
[[ ! ("${argv[i]}" =~ ^${CC_OPTIONAL_FLAG_PREFIX}) ]] && \
|
||||
[[ ! ("${argv[i]}" =~ ^${LD_OPTIONAL_FLAG_PREFIX}) ]] && \
|
||||
[[ ! ("${argv[i]}" =~ ${ADDITIONAL_MODULE_FLAG_PREFIX}) ]] && \
|
||||
[[ ! ("${argv[i]}" =~ ${OPENSSL_VERSION_PREFIX}) ]] && \
|
||||
[[ ! ("${argv[i]}" =~ ${OPENSSL_OPT_PREFIX}) ]] && \
|
||||
[[ ! ("${argv[i]}" =~ ${DYNAMIC_MODULE_FLAG_PREFIX}) ]] && \
|
||||
[[ ! ("${argv[i]}" =~ ${BUILD_FLAG_PREFIX}) ]] && \
|
||||
[[ ! ("${argv[i]}" =~ ${AUTH_JWT_PREFIX}) ]] && \
|
||||
[[ ! ("${argv[i]}" =~ ${F4F_PREFIX}) ]] && \
|
||||
[[ ! ("${argv[i]}" =~ ${HLS_PREFIX}) ]] && \
|
||||
[[ ! ("${argv[i]}" =~ ${SESSION_LOG_PREFIX}) ]] && \
|
||||
[[ ! ("${argv[i]}" =~ ${WITH_CC_PREFIX}) ]] && \
|
||||
[[ ! ("${argv[i]}" =~ ${HPACK_ENC_PREFIX}) ]] ; \
|
||||
then
|
||||
debug "Adding configuration flag: ${argv[i]}\n"
|
||||
NUMBER_OF_CONFIGURATION_FLAGS=$((NUMBER_OF_CONFIGURATION_FLAGS+1))
|
||||
CONFIGURATION_FLAGS="${CONFIGURATION_FLAGS} \\\\\n${argv[i]}"
|
||||
fi
|
||||
done
|
||||
COMBINED_CONFIGURATION_FLAGS="${CONFIGURATION_FLAGS}"
|
||||
debug "Successfully added nginx configuration flags"
|
||||
}
|
||||
|
||||
add_nginx_and_release_versions()
|
||||
{
|
||||
echo -e "NGINX_VERSION=\"${NGINX_VERSION}\"" >> ${FILE_NAME}
|
||||
RELEASE_VERSION=`cat /etc/*-release | grep -i "PRETTY_NAME\|Gaia" | cut -d"\"" -f2`
|
||||
echo -e "RELEASE_VERSION=\"${RELEASE_VERSION}\"" >> ${FILE_NAME}
|
||||
}
|
||||
|
||||
initializeEnviroment
|
||||
echo -e "Open-appsec Nginx version extractor\n"
|
||||
check_flags_options "$@"
|
||||
_main
|
||||
|
@ -380,7 +380,11 @@ compression_chain_filter(
|
||||
}
|
||||
|
||||
ngx_memcpy(curr_input_link->buf, output_buffer, sizeof(ngx_buf_t));
|
||||
curr_input_link->buf->memory = 1;
|
||||
|
||||
// Empty buffer should not be marked as "in-memory"
|
||||
if (curr_input_link->buf->last - curr_input_link->buf->pos != 0) {
|
||||
curr_input_link->buf->memory = 1;
|
||||
}
|
||||
}
|
||||
|
||||
write_dbg(DBG_LEVEL_TRACE, "Successfully %s chain", should_compress ? "compressed" : "decompressed");
|
||||
|
@ -333,7 +333,7 @@ ngx_http_cp_finalize_rejected_request(ngx_http_request_t *request)
|
||||
}
|
||||
out_chain[0].buf->last_buf = 1;
|
||||
out_chain[0].next = NULL;
|
||||
return ngx_http_output_filter(request, &out_chain[0]);
|
||||
ngx_http_output_filter(request, &out_chain[0]);
|
||||
}
|
||||
|
||||
CUSTOM_RES_OUT:
|
||||
|
@ -86,8 +86,8 @@ init_thread_ctx(
|
||||
void *
|
||||
ngx_http_cp_registration_thread(void *_ctx)
|
||||
{
|
||||
struct ngx_http_cp_event_thread_ctx_t *ctx = (struct ngx_http_cp_event_thread_ctx_t*)_ctx;
|
||||
ngx_int_t res = ngx_cp_attachment_init_process();
|
||||
struct ngx_http_cp_event_thread_ctx_t *ctx = (struct ngx_http_cp_event_thread_ctx_t *)_ctx;
|
||||
ngx_int_t res = ngx_cp_attachment_init_process(ctx->request);
|
||||
if (res == NGX_ABORT && already_registered) {
|
||||
already_registered = 0;
|
||||
disconnect_communication();
|
||||
@ -141,7 +141,8 @@ end_req_header_handler(
|
||||
&session_data_p->verdict,
|
||||
session_data_p->session_id,
|
||||
request,
|
||||
modifications
|
||||
modifications,
|
||||
REQUEST_END
|
||||
);
|
||||
}
|
||||
|
||||
@ -154,7 +155,7 @@ does_contain_body(ngx_http_headers_in_t *headers)
|
||||
void *
|
||||
ngx_http_cp_req_header_handler_thread(void *_ctx)
|
||||
{
|
||||
struct ngx_http_cp_event_thread_ctx_t *ctx = (struct ngx_http_cp_event_thread_ctx_t*)_ctx;
|
||||
struct ngx_http_cp_event_thread_ctx_t *ctx = (struct ngx_http_cp_event_thread_ctx_t *)_ctx;
|
||||
ngx_http_request_t *request = ctx->request;
|
||||
ngx_http_cp_session_data *session_data_p = ctx->session_data_p;
|
||||
ngx_int_t send_meta_data_result;
|
||||
@ -218,7 +219,7 @@ ngx_http_cp_req_header_handler_thread(void *_ctx)
|
||||
void *
|
||||
ngx_http_cp_req_body_filter_thread(void *_ctx)
|
||||
{
|
||||
struct ngx_http_cp_event_thread_ctx_t *ctx = (struct ngx_http_cp_event_thread_ctx_t*)_ctx;
|
||||
struct ngx_http_cp_event_thread_ctx_t *ctx = (struct ngx_http_cp_event_thread_ctx_t *)_ctx;
|
||||
ngx_http_request_t *request = ctx->request;
|
||||
ngx_http_cp_session_data *session_data_p = ctx->session_data_p;
|
||||
ngx_int_t is_last_part;
|
||||
@ -248,31 +249,14 @@ ngx_http_cp_req_body_filter_thread(void *_ctx)
|
||||
}
|
||||
session_data_p->remaining_messages_to_reply += num_messages_sent;
|
||||
|
||||
num_messages_sent = 0;
|
||||
if (is_last_part) {
|
||||
// Signals the nano service that the transaction reached the end.
|
||||
if (ngx_http_cp_end_transaction_sender(REQUEST_END, session_data_p->session_id, &num_messages_sent) != NGX_OK) {
|
||||
write_dbg(
|
||||
DBG_LEVEL_WARNING,
|
||||
"Failed to send request end data to the nano service. Session ID: %d",
|
||||
session_data_p->session_id
|
||||
);
|
||||
handle_inspection_failure(inspection_failure_weight, fail_mode_verdict, session_data_p);
|
||||
if (fail_mode_verdict == NGX_OK) {
|
||||
THREAD_CTX_RETURN_NEXT_FILTER();
|
||||
}
|
||||
THREAD_CTX_RETURN(NGX_ERROR);
|
||||
}
|
||||
session_data_p->remaining_messages_to_reply++;
|
||||
}
|
||||
|
||||
// Fetch nano services' results.
|
||||
ctx->res = ngx_http_cp_reply_receiver(
|
||||
&session_data_p->remaining_messages_to_reply,
|
||||
&session_data_p->verdict,
|
||||
session_data_p->session_id,
|
||||
request,
|
||||
&ctx->modifications
|
||||
&ctx->modifications,
|
||||
REQUEST_BODY
|
||||
);
|
||||
|
||||
if (is_last_part) session_data_p->was_request_fully_inspected = 1;
|
||||
@ -280,10 +264,49 @@ ngx_http_cp_req_body_filter_thread(void *_ctx)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void *
|
||||
ngx_http_cp_req_end_transaction_thread(void *_ctx)
|
||||
{
|
||||
struct ngx_http_cp_event_thread_ctx_t *ctx = (struct ngx_http_cp_event_thread_ctx_t *)_ctx;
|
||||
ngx_http_request_t *request = ctx->request;
|
||||
ngx_http_cp_session_data *session_data_p = ctx->session_data_p;
|
||||
ngx_uint_t num_messages_sent = 0;
|
||||
|
||||
if (ngx_http_cp_end_transaction_sender(REQUEST_END, session_data_p->session_id, &num_messages_sent) != NGX_OK) {
|
||||
write_dbg(
|
||||
DBG_LEVEL_WARNING,
|
||||
"Failed to send request end data to the nano service. Session ID: %d",
|
||||
session_data_p->session_id
|
||||
);
|
||||
handle_inspection_failure(inspection_failure_weight, fail_mode_verdict, session_data_p);
|
||||
if (fail_mode_verdict == NGX_OK) {
|
||||
THREAD_CTX_RETURN_NEXT_FILTER();
|
||||
}
|
||||
THREAD_CTX_RETURN(NGX_ERROR);
|
||||
}
|
||||
|
||||
session_data_p->remaining_messages_to_reply += num_messages_sent;
|
||||
|
||||
if (session_data_p->verdict != TRAFFIC_VERDICT_ACCEPT &&
|
||||
session_data_p->verdict != TRAFFIC_VERDICT_DROP) {
|
||||
// Fetch nano services' results.
|
||||
ctx->res = ngx_http_cp_reply_receiver(
|
||||
&session_data_p->remaining_messages_to_reply,
|
||||
&session_data_p->verdict,
|
||||
session_data_p->session_id,
|
||||
request,
|
||||
&ctx->modifications,
|
||||
REQUEST_END
|
||||
);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void *
|
||||
ngx_http_cp_res_header_filter_thread(void *_ctx)
|
||||
{
|
||||
struct ngx_http_cp_event_thread_ctx_t *ctx = (struct ngx_http_cp_event_thread_ctx_t*)_ctx;
|
||||
struct ngx_http_cp_event_thread_ctx_t *ctx = (struct ngx_http_cp_event_thread_ctx_t *)_ctx;
|
||||
ngx_http_request_t *request = ctx->request;
|
||||
ngx_http_cp_session_data *session_data_p = ctx->session_data_p;
|
||||
ngx_int_t set_response_content_encoding_res;
|
||||
@ -383,7 +406,8 @@ ngx_http_cp_res_header_filter_thread(void *_ctx)
|
||||
&session_data_p->verdict,
|
||||
session_data_p->session_id,
|
||||
request,
|
||||
&ctx->modifications
|
||||
&ctx->modifications,
|
||||
RESPONSE_HEADER
|
||||
);
|
||||
|
||||
return NULL;
|
||||
@ -392,7 +416,7 @@ ngx_http_cp_res_header_filter_thread(void *_ctx)
|
||||
void *
|
||||
ngx_http_cp_res_body_filter_thread(void *_ctx)
|
||||
{
|
||||
struct ngx_http_cp_event_thread_ctx_t *ctx = (struct ngx_http_cp_event_thread_ctx_t*)_ctx;
|
||||
struct ngx_http_cp_event_thread_ctx_t *ctx = (struct ngx_http_cp_event_thread_ctx_t *)_ctx;
|
||||
ngx_http_request_t *request = ctx->request;
|
||||
ngx_http_cp_session_data *session_data_p = ctx->session_data_p;
|
||||
ngx_int_t send_body_result;
|
||||
@ -446,7 +470,50 @@ ngx_http_cp_res_body_filter_thread(void *_ctx)
|
||||
&session_data_p->verdict,
|
||||
session_data_p->session_id,
|
||||
request,
|
||||
&ctx->modifications
|
||||
&ctx->modifications,
|
||||
RESPONSE_BODY
|
||||
);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void *
|
||||
ngx_http_cp_hold_verdict_thread(void *_ctx)
|
||||
{
|
||||
struct ngx_http_cp_event_thread_ctx_t *ctx = (struct ngx_http_cp_event_thread_ctx_t *)_ctx;
|
||||
|
||||
ngx_http_request_t *request = ctx->request;
|
||||
ngx_http_cp_session_data *session_data_p = ctx->session_data_p;
|
||||
|
||||
ngx_uint_t num_messages_sent = 0;
|
||||
|
||||
if (ngx_http_cp_wait_sender(session_data_p->session_id, &num_messages_sent) != NGX_OK) {
|
||||
write_dbg(
|
||||
DBG_LEVEL_WARNING,
|
||||
"Failed to send inspect wait request to the nano service. Session ID: %d",
|
||||
session_data_p->session_id
|
||||
);
|
||||
handle_inspection_failure(inspection_failure_weight, fail_mode_hold_verdict, session_data_p);
|
||||
if (fail_mode_hold_verdict == NGX_OK) {
|
||||
THREAD_CTX_RETURN_NEXT_FILTER();
|
||||
}
|
||||
THREAD_CTX_RETURN(NGX_ERROR);
|
||||
}
|
||||
session_data_p->remaining_messages_to_reply += num_messages_sent;
|
||||
|
||||
ctx->res = ngx_http_cp_reply_receiver(
|
||||
&session_data_p->remaining_messages_to_reply,
|
||||
&session_data_p->verdict,
|
||||
session_data_p->session_id,
|
||||
request,
|
||||
&ctx->modifications,
|
||||
HOLD_DATA
|
||||
);
|
||||
|
||||
write_dbg(
|
||||
DBG_LEVEL_TRACE,
|
||||
"Successfully receivied response to wait from the nano service. Session ID: %d",
|
||||
session_data_p->session_id
|
||||
);
|
||||
|
||||
return NULL;
|
||||
|
@ -121,6 +121,19 @@ void * ngx_http_cp_req_header_handler_thread(void *_ctx);
|
||||
///
|
||||
void * ngx_http_cp_req_body_filter_thread(void *_ctx);
|
||||
|
||||
///
|
||||
/// @brief Sends end request transmission to the attachment's service.
|
||||
/// @details Communicates with the attachment service by sending request body to the attachment's service
|
||||
/// and modifies _ctx by the received response.
|
||||
/// @note _ctx needs to be properly initialized by init_thread_ctx() and ngx_chain_t needs of not NULL.
|
||||
/// @param[in, out] _ctx is of type ngx_http_cp_event_thread_ctx_t.
|
||||
/// Modifies _ctx res to the following values:
|
||||
/// - #NGX_OK
|
||||
/// - #NGX_ERROR
|
||||
/// @return NULL.
|
||||
///
|
||||
void * ngx_http_cp_req_end_transaction_thread(void *_ctx);
|
||||
|
||||
///
|
||||
/// @brief Sends response headers to the attachment's service.
|
||||
/// @details Communicates with the attachment service by sending response headers to the attachment's service
|
||||
@ -147,6 +160,21 @@ void * ngx_http_cp_res_header_filter_thread(void *_ctx);
|
||||
///
|
||||
void * ngx_http_cp_res_body_filter_thread(void *_ctx);
|
||||
|
||||
///
|
||||
/// @brief Sends a request to the attachment's service to update the earlier provided "WAIT" verdict.
|
||||
/// @details Communicates with the attachment service by sending a HOLD_DATA request to the attachment's service
|
||||
/// and modifies _ctx by the received response.
|
||||
/// @note _ctx needs to be properly initialized by init_thread_ctx() and
|
||||
/// be called after another call returned wait verdict.
|
||||
/// @param[in, out] _ctx is of type ngx_http_cp_event_thread_ctx_t.
|
||||
/// Modifies _ctx res to the following values:
|
||||
/// - #NGX_OK
|
||||
/// - #NGX_ERROR
|
||||
/// Modifies _ctx session data with an updated verdict.
|
||||
/// @return NULL.
|
||||
///
|
||||
void * ngx_http_cp_hold_verdict_thread(void *_ctx);
|
||||
|
||||
///
|
||||
/// @brief Check if transaction contains headers.
|
||||
/// @param[in] headers ngx_http_headers_in_t struct.
|
||||
|
@ -144,6 +144,44 @@ was_transaction_timedout(ngx_http_cp_session_data *ctx)
|
||||
return 1;
|
||||
}
|
||||
|
||||
ngx_int_t
|
||||
ngx_http_cp_hold_verdict(struct ngx_http_cp_event_thread_ctx_t *ctx)
|
||||
{
|
||||
ngx_http_cp_session_data *session_data_p = ctx->session_data_p;
|
||||
for (uint i = 0; i < 3; i++) {
|
||||
sleep(1);
|
||||
int res = ngx_cp_run_in_thread_timeout(
|
||||
ngx_http_cp_hold_verdict_thread,
|
||||
(void *)ctx,
|
||||
waiting_for_verdict_thread_timeout_msec,
|
||||
"ngx_http_cp_hold_verdict_thread"
|
||||
);
|
||||
|
||||
if (!res) {
|
||||
write_dbg(
|
||||
DBG_LEVEL_DEBUG,
|
||||
"ngx_http_cp_hold_verdict_thread failed at attempt number=%d",
|
||||
i
|
||||
);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (session_data_p->verdict != TRAFFIC_VERDICT_WAIT) {
|
||||
// Verdict was updated.
|
||||
write_dbg(
|
||||
DBG_LEVEL_DEBUG,
|
||||
"finished ngx_http_cp_hold_verdict successfully. new verdict=%d",
|
||||
session_data_p->verdict
|
||||
);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
write_dbg(DBG_LEVEL_TRACE, "Handling Failure with fail %s mode", fail_mode_hold_verdict == NGX_OK ? "open" : "close");
|
||||
handle_inspection_failure(inspection_failure_weight, fail_mode_hold_verdict, session_data_p);
|
||||
session_data_p->verdict = fail_mode_hold_verdict == NGX_OK ? TRAFFIC_VERDICT_ACCEPT : TRAFFIC_VERDICT_DROP;
|
||||
return 0;
|
||||
}
|
||||
|
||||
ngx_http_cp_verdict_e
|
||||
enforce_sessions_rate()
|
||||
{
|
||||
@ -498,6 +536,12 @@ ngx_http_cp_req_body_filter(ngx_http_request_t *request, ngx_chain_t *request_bo
|
||||
write_dbg(DBG_LEVEL_DEBUG, "spawn ngx_http_cp_req_body_filter_thread");
|
||||
// Open threads while unprocessed chain elements still exist, up to num of elements in the chain iterations
|
||||
for (chain_elem = ctx.chain; chain_elem != NULL && ctx.chain; chain_elem = chain_elem->next) {
|
||||
// Notify if zero-size buf is marked as "memory". This should never happen but if it does we want to know.
|
||||
if (chain_elem->buf && chain_elem->buf->pos &&
|
||||
(chain_elem->buf->last - chain_elem->buf->pos == 0) && chain_elem->buf->memory == 1) {
|
||||
write_dbg(DBG_LEVEL_WARNING,
|
||||
"Warning: encountered request body chain element of size 0 with memory flag enabled");
|
||||
}
|
||||
clock_gettime(CLOCK_REALTIME, &hook_time_begin);
|
||||
res = ngx_cp_run_in_thread_timeout(
|
||||
ngx_http_cp_req_body_filter_thread,
|
||||
@ -529,8 +573,45 @@ ngx_http_cp_req_body_filter(ngx_http_request_t *request, ngx_chain_t *request_bo
|
||||
ctx.res
|
||||
);
|
||||
|
||||
calcProcessingTime(session_data_p, &hook_time_begin, 1);
|
||||
if (session_data_p->verdict == TRAFFIC_VERDICT_WAIT) {
|
||||
res = ngx_http_cp_hold_verdict(&ctx);
|
||||
if (!res) {
|
||||
session_data_p->verdict = fail_mode_hold_verdict == NGX_OK ? TRAFFIC_VERDICT_ACCEPT : TRAFFIC_VERDICT_DROP;
|
||||
updateMetricField(HOLD_THREAD_TIMEOUT, 1);
|
||||
return fail_mode_verdict == NGX_OK ? ngx_http_next_request_body_filter(request, request_body_chain) : NGX_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
if (session_data_p->was_request_fully_inspected) {
|
||||
res = ngx_cp_run_in_thread_timeout(
|
||||
ngx_http_cp_req_end_transaction_thread,
|
||||
(void *)&ctx,
|
||||
req_body_thread_timeout_msec,
|
||||
"ngx_http_cp_req_end_transaction_thread"
|
||||
);
|
||||
if (!res) {
|
||||
// failed to execute thread task, or it timed out
|
||||
session_data_p->verdict = fail_mode_verdict == NGX_OK ? TRAFFIC_VERDICT_ACCEPT : TRAFFIC_VERDICT_DROP;
|
||||
write_dbg(
|
||||
DBG_LEVEL_DEBUG,
|
||||
"req_end_transaction thread failed, returning default fail mode verdict. Session id: %d, verdict: %s",
|
||||
session_data_p->session_id,
|
||||
session_data_p->verdict == TRAFFIC_VERDICT_ACCEPT ? "accept" : "drop"
|
||||
);
|
||||
updateMetricField(REQ_BODY_THREAD_TIMEOUT, 1);
|
||||
return fail_mode_verdict == NGX_OK ? ngx_http_next_request_body_filter(request, request_body_chain) : NGX_ERROR;
|
||||
}
|
||||
|
||||
write_dbg(
|
||||
DBG_LEVEL_DEBUG,
|
||||
"finished ngx_http_cp_req_end_transaction_thread successfully. return=%d next_filter=%d res=%d",
|
||||
ctx.should_return,
|
||||
ctx.should_return_next_filter,
|
||||
ctx.res
|
||||
);
|
||||
}
|
||||
|
||||
calcProcessingTime(session_data_p, &hook_time_begin, 1);
|
||||
if (ctx.should_return_next_filter) {
|
||||
return ngx_http_next_request_body_filter(request, request_body_chain);
|
||||
}
|
||||
@ -787,7 +868,7 @@ ngx_http_cp_res_body_filter(ngx_http_request_t *request, ngx_chain_t *body_chain
|
||||
if (session_data_p->verdict == TRAFFIC_VERDICT_DROP) request->keepalive = 0;
|
||||
return ngx_http_next_response_body_filter(request, body_chain);
|
||||
}
|
||||
|
||||
|
||||
session_data_p->response_data.num_body_chunk++;
|
||||
|
||||
if (body_chain == NULL) {
|
||||
@ -890,6 +971,12 @@ ngx_http_cp_res_body_filter(ngx_http_request_t *request, ngx_chain_t *body_chain
|
||||
write_dbg(DBG_LEVEL_DEBUG, "spawn ngx_http_cp_res_body_filter_thread");
|
||||
// Open threads while unprocessed chain elements still exist, up to num of elements in the chain iterations
|
||||
for (chain_elem = ctx.chain; chain_elem != NULL && ctx.chain; chain_elem = chain_elem->next) {
|
||||
// Notify if zero-size buf is marked as "memory". This should never happen but if it does we want to know.
|
||||
if (chain_elem->buf && chain_elem->buf->pos &&
|
||||
(chain_elem->buf->last - chain_elem->buf->pos == 0) && chain_elem->buf->memory == 1) {
|
||||
write_dbg(DBG_LEVEL_WARNING,
|
||||
"Warning: encountered response body chain element of size 0 with memory flag enabled");
|
||||
}
|
||||
clock_gettime(CLOCK_REALTIME, &hook_time_begin);
|
||||
if (!ngx_cp_run_in_thread_timeout(
|
||||
ngx_http_cp_res_body_filter_thread,
|
||||
|
@ -25,6 +25,7 @@
|
||||
|
||||
#include "ngx_cp_http_parser.h"
|
||||
#include "nginx_attachment_common.h"
|
||||
#include "ngx_cp_hook_threads.h"
|
||||
|
||||
static const int registration_failure_weight = 2; ///< Registration failure weight.
|
||||
static const int inspection_failure_weight = 1; ///< Inspection failure weight.
|
||||
@ -96,6 +97,16 @@ ngx_int_t ngx_http_cp_res_header_filter(ngx_http_request_t *request);
|
||||
///
|
||||
ngx_int_t ngx_http_cp_req_header_handler(ngx_http_request_t *request);
|
||||
|
||||
///
|
||||
/// @brief Sends a request to the nano service to update the verdict.
|
||||
/// @note Should be called after the nano service provided the verdict TRAFFIC_VERDICT_WAIT to get the updated verdict.
|
||||
/// @param[in, out] request Event thread context to be updated.
|
||||
/// @returns ngx_int_t
|
||||
/// - #1 if request was properly communicated with the nano service and provided an updated response.
|
||||
/// - #0 otherwise.
|
||||
///
|
||||
ngx_int_t ngx_http_cp_hold_verdict(struct ngx_http_cp_event_thread_ctx_t *ctx);
|
||||
|
||||
///
|
||||
/// @brief Checks if transaction was timed out.
|
||||
/// @param[in, out] ctx
|
||||
|
@ -32,7 +32,7 @@ typedef enum ngx_cp_comm_direction {
|
||||
/// - #NGX_ERROR
|
||||
/// - #NGX_ABORT
|
||||
///
|
||||
ngx_int_t ngx_cp_attachment_init_process();
|
||||
ngx_int_t ngx_cp_attachment_init_process(ngx_http_request_t *);
|
||||
|
||||
///
|
||||
/// @brief Preforms send\receive information to\from the service via a socket.
|
||||
|
@ -81,6 +81,7 @@ ngx_http_cp_signal_to_service(uint32_t cur_session_id)
|
||||
///
|
||||
/// @brief Signals and recieve signal to/from nano service about new session to inspect.
|
||||
/// @param[in] cur_session_id Session's Id.
|
||||
/// @param[in] chunk_type Chunk type that the attachment is waiting for a response from nano service.
|
||||
/// @returns ngx_int_t
|
||||
/// - #NGX_OK
|
||||
/// - #NGX_ERROR
|
||||
@ -88,7 +89,7 @@ ngx_http_cp_signal_to_service(uint32_t cur_session_id)
|
||||
/// - #NGX_AGAIN
|
||||
///
|
||||
static ngx_int_t
|
||||
ngx_http_cp_wait_for_service(uint32_t cur_session_id)
|
||||
ngx_http_cp_wait_for_service(uint32_t cur_session_id, ngx_http_chunk_type_e chunk_type)
|
||||
{
|
||||
static int dbg_count = 0;
|
||||
static clock_t clock_start = (clock_t) 0;
|
||||
@ -97,6 +98,7 @@ ngx_http_cp_wait_for_service(uint32_t cur_session_id)
|
||||
uint32_t reply_from_service;
|
||||
ngx_int_t retry;
|
||||
int is_fail_open_disabled = (inspection_mode != NON_BLOCKING_THREAD);
|
||||
ngx_uint_t timeout = chunk_type == HOLD_DATA ? fail_open_hold_timeout : fail_open_timeout;
|
||||
|
||||
res = ngx_http_cp_signal_to_service(cur_session_id);
|
||||
if (res != NGX_OK) return res;
|
||||
@ -111,7 +113,7 @@ ngx_http_cp_wait_for_service(uint32_t cur_session_id)
|
||||
s_poll.fd = comm_socket;
|
||||
s_poll.events = POLLIN;
|
||||
s_poll.revents = 0;
|
||||
res = poll(&s_poll, 1, is_fail_open_disabled ? 150 : fail_open_timeout);
|
||||
res = poll(&s_poll, 1, is_fail_open_disabled ? 150 : timeout);
|
||||
|
||||
if (res < 0) {
|
||||
// Polling from the nano service has failed.
|
||||
@ -192,7 +194,9 @@ ngx_http_cp_send_data_to_service(
|
||||
const uint16_t *fragments_sizes,
|
||||
uint8_t num_of_data_elem,
|
||||
uint32_t cur_session_id,
|
||||
int *was_waiting)
|
||||
int *was_waiting,
|
||||
ngx_http_chunk_type_e chunk_type
|
||||
)
|
||||
{
|
||||
ngx_int_t max_retries;
|
||||
ngx_int_t res = NGX_OK;
|
||||
@ -209,7 +213,7 @@ ngx_http_cp_send_data_to_service(
|
||||
*was_waiting = 1;
|
||||
}
|
||||
|
||||
res = ngx_http_cp_wait_for_service(cur_session_id);
|
||||
res = ngx_http_cp_wait_for_service(cur_session_id, chunk_type);
|
||||
if (res != NGX_OK && res != NGX_AGAIN) return res;
|
||||
}
|
||||
|
||||
@ -428,7 +432,9 @@ ngx_http_cp_reply_receiver(
|
||||
ngx_http_cp_verdict_e *verdict,
|
||||
uint32_t cur_session_id,
|
||||
ngx_http_request_t *request,
|
||||
ngx_http_cp_modification_list **modification_list)
|
||||
ngx_http_cp_modification_list **modification_list,
|
||||
ngx_http_chunk_type_e chunk_type
|
||||
)
|
||||
{
|
||||
ngx_http_cp_reply_from_service_t *reply_p;
|
||||
ngx_http_cp_modification_list *new_modification = NULL;
|
||||
@ -446,7 +452,7 @@ ngx_http_cp_reply_receiver(
|
||||
}
|
||||
|
||||
do {
|
||||
res = ngx_http_cp_wait_for_service(cur_session_id);
|
||||
res = ngx_http_cp_wait_for_service(cur_session_id, chunk_type);
|
||||
} while (res == NGX_AGAIN);
|
||||
|
||||
if (res != NGX_OK) return NGX_ERROR;
|
||||
@ -554,10 +560,19 @@ ngx_http_cp_reply_receiver(
|
||||
break;
|
||||
}
|
||||
|
||||
case TRAFFIC_VERDICT_INSPECT:
|
||||
case TRAFFIC_VERDICT_INSPECT: {
|
||||
// After an irrelevant verdict, ignore the verdict and continue to the next response.
|
||||
write_dbg(DBG_LEVEL_TRACE, "Verdict inspect received from the nano service");
|
||||
updateMetricField(INSPECT_VERDICTS_COUNT, 1);
|
||||
break;
|
||||
}
|
||||
|
||||
case TRAFFIC_VERDICT_WAIT: {
|
||||
// After a wait verdict, query the nano agent again to get an updated verdict.
|
||||
write_dbg(DBG_LEVEL_DEBUG, "Verdict wait received from the nano service");
|
||||
updateMetricField(HOLD_VERDICTS_COUNT, 1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
free_data_from_service();
|
||||
@ -718,7 +733,7 @@ ngx_http_cp_meta_data_sender(ngx_http_request_t *request, uint32_t cur_request_i
|
||||
set_fragment_elem(fragments, fragments_sizes, &client_port, sizeof(client_port), CLIENT_PORT + 2);
|
||||
|
||||
// Sends all the data to the nano service.
|
||||
res = ngx_http_cp_send_data_to_service(fragments, fragments_sizes, META_DATA_COUNT + 2, cur_request_id, NULL);
|
||||
res = ngx_http_cp_send_data_to_service(fragments, fragments_sizes, META_DATA_COUNT + 2, cur_request_id, NULL, fail_open_timeout);
|
||||
if (res != NGX_OK) {
|
||||
// Failed to send the metadata to nano service.
|
||||
if (res == NGX_ERROR && failure_count++ == 5) {
|
||||
@ -764,7 +779,7 @@ ngx_http_cp_end_transaction_sender(
|
||||
|
||||
set_fragments_identifiers(fragments, fragments_sizes, (uint16_t *)&end_transaction_type, &cur_request_id);
|
||||
|
||||
res = ngx_http_cp_send_data_to_service(fragments, fragments_sizes, end_transaction_num_fragments, cur_request_id, NULL);
|
||||
res = ngx_http_cp_send_data_to_service(fragments, fragments_sizes, end_transaction_num_fragments, cur_request_id, NULL, fail_open_timeout);
|
||||
if (res != NGX_OK) {
|
||||
return NGX_ERROR;
|
||||
}
|
||||
@ -773,6 +788,30 @@ ngx_http_cp_end_transaction_sender(
|
||||
return NGX_OK;
|
||||
}
|
||||
|
||||
ngx_int_t
|
||||
ngx_http_cp_wait_sender(uint32_t cur_request_id, ngx_uint_t *num_messages_sent)
|
||||
{
|
||||
static const ngx_uint_t end_transaction_num_fragments = 2;
|
||||
|
||||
char *fragments[end_transaction_num_fragments];
|
||||
uint16_t fragments_sizes[end_transaction_num_fragments];
|
||||
ngx_http_chunk_type_e transaction_type = HOLD_DATA;
|
||||
ngx_int_t res;
|
||||
|
||||
set_fragments_identifiers(fragments, fragments_sizes, (uint16_t *)&transaction_type, &cur_request_id);
|
||||
|
||||
write_dbg(DBG_LEVEL_TRACE, "Sending wait event flag for inspection");
|
||||
|
||||
res = ngx_http_cp_send_data_to_service(fragments, fragments_sizes, end_transaction_num_fragments, cur_request_id, NULL, fail_open_timeout);
|
||||
if (res != NGX_OK) {
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
write_dbg(DBG_LEVEL_TRACE, "Successfully sent wait event");
|
||||
*num_messages_sent = 1;
|
||||
return NGX_OK;
|
||||
}
|
||||
|
||||
ngx_int_t
|
||||
ngx_http_cp_res_code_sender(uint16_t response_code, uint32_t cur_req_id, ngx_uint_t *num_messages_sent)
|
||||
{
|
||||
@ -788,7 +827,7 @@ ngx_http_cp_res_code_sender(uint16_t response_code, uint32_t cur_req_id, ngx_uin
|
||||
set_fragments_identifiers(fragments, fragments_sizes, &chunck_type, &cur_req_id);
|
||||
set_fragment_elem(fragments, fragments_sizes, &response_code, sizeof(uint16_t), 2);
|
||||
|
||||
if (ngx_http_cp_send_data_to_service(fragments, fragments_sizes, res_code_num_fragments, cur_req_id, NULL) != NGX_OK) {
|
||||
if (ngx_http_cp_send_data_to_service(fragments, fragments_sizes, res_code_num_fragments, cur_req_id, NULL, fail_open_hold_timeout) != NGX_OK) {
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
@ -812,7 +851,7 @@ ngx_http_cp_content_length_sender(uint64_t content_length_n, uint32_t cur_req_id
|
||||
set_fragments_identifiers(fragments, fragments_sizes, &chunck_type, &cur_req_id);
|
||||
set_fragment_elem(fragments, fragments_sizes, &content_length_val, sizeof(content_length_val), 2);
|
||||
|
||||
if (ngx_http_cp_send_data_to_service(fragments, fragments_sizes, content_length_num_fragments, cur_req_id, NULL) != NGX_OK) {
|
||||
if (ngx_http_cp_send_data_to_service(fragments, fragments_sizes, content_length_num_fragments, cur_req_id, NULL, fail_open_timeout) != NGX_OK) {
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
@ -865,7 +904,7 @@ send_header_bulk(
|
||||
set_fragment_elem(data, data_sizes, &is_last_part, sizeof(is_last_part), 2);
|
||||
set_fragment_elem(data, data_sizes, &bulk_part_index, sizeof(bulk_part_index), 3);
|
||||
|
||||
res = ngx_http_cp_send_data_to_service(data, data_sizes, HEADER_DATA_COUNT * num_headers + 4, cur_request_id, NULL);
|
||||
res = ngx_http_cp_send_data_to_service(data, data_sizes, HEADER_DATA_COUNT * num_headers + 4, cur_request_id, NULL, fail_open_timeout);
|
||||
if (res != NGX_OK) {
|
||||
write_dbg(DBG_LEVEL_TRACE, "Failed to send bulk of %iu headers", num_headers);
|
||||
return NGX_ERROR;
|
||||
@ -1048,7 +1087,7 @@ ngx_http_cp_body_sender(
|
||||
}
|
||||
// Sending the data to the nano service.
|
||||
res = ngx_http_cp_send_data_to_service(fragments, fragments_sizes, num_body_chunk_fragments, session_data->session_id,
|
||||
&was_waiting);
|
||||
&was_waiting, fail_open_timeout);
|
||||
|
||||
if (res != NGX_OK) {
|
||||
// Failed to send the fragments to the nano service.
|
||||
@ -1091,7 +1130,7 @@ ngx_http_cp_metric_data_sender()
|
||||
fragments = (char *)&data_to_send;
|
||||
fragments_sizes = sizeof(ngx_http_cp_metric_data_t);
|
||||
|
||||
res = ngx_http_cp_send_data_to_service(&fragments, &fragments_sizes, 1, 0, NULL);
|
||||
res = ngx_http_cp_send_data_to_service(&fragments, &fragments_sizes, 1, 0, NULL, fail_open_timeout);
|
||||
reset_metric_data();
|
||||
return res;
|
||||
}
|
||||
|
@ -47,6 +47,7 @@ extern int comm_socket; ///< Communication socket.
|
||||
/// @param[in] cur_session_id Session's Id.
|
||||
/// @param[in, out] request NGINX request.
|
||||
/// @param[in] modification_list
|
||||
/// @param[in] chunk_type Chunk type that the attachment is waiting for a response from nano service.
|
||||
/// @returns ngx_int_t
|
||||
/// - #NGX_OK
|
||||
/// - #NGX_HTTP_FORBIDDEN
|
||||
@ -58,7 +59,8 @@ ngx_http_cp_reply_receiver(
|
||||
ngx_http_cp_verdict_e *verdict,
|
||||
uint32_t cur_session_id,
|
||||
ngx_http_request_t *request,
|
||||
ngx_http_cp_modification_list **modification_list
|
||||
ngx_http_cp_modification_list **modification_list,
|
||||
ngx_http_chunk_type_e chunk_type
|
||||
);
|
||||
|
||||
///
|
||||
@ -170,6 +172,17 @@ ngx_http_cp_body_sender(
|
||||
ngx_chain_t **next_elem_to_inspect
|
||||
);
|
||||
|
||||
///
|
||||
/// @brief Sends HOLD_DATA request to the nano service.
|
||||
/// @details HOLD_DATA request is a request that asks the nano service to provide with an updated verdict.
|
||||
/// @param[in] cur_request_id Request session's Id.
|
||||
/// @param[in, out] num_messages_sent Number of messages sent will be saved onto this parameter.
|
||||
/// - #NGX_OK
|
||||
/// - #NGX_ERROR
|
||||
///
|
||||
ngx_int_t
|
||||
ngx_http_cp_wait_sender(uint32_t cur_request_id, ngx_uint_t *num_messages_sent);
|
||||
|
||||
///
|
||||
/// @brief Checks if reconf is needed and reconfigs if necessary.
|
||||
/// @returns ngx_int_t
|
||||
|
@ -51,7 +51,7 @@ ngx_cp_run_in_thread_timeout(CpThreadRoutine thread_func, void *arg, int timeout
|
||||
void *res = NULL;
|
||||
pthread_t thread;
|
||||
struct timespec ts;
|
||||
struct ngx_http_cp_event_thread_ctx_t *ctx = (struct ngx_http_cp_event_thread_ctx_t*)arg;
|
||||
struct ngx_http_cp_event_thread_ctx_t *ctx = (struct ngx_http_cp_event_thread_ctx_t *)arg;
|
||||
|
||||
if (inspection_mode == NO_THREAD) return ngx_cp_run_without_thread_timeout(thread_func, arg, func_name);
|
||||
|
||||
|
@ -81,9 +81,11 @@ ngx_http_cp_sessions_per_minute_limit sessions_per_minute_limit_info = {
|
||||
ngx_uint_t current_config_version = 0;
|
||||
|
||||
ngx_int_t fail_mode_verdict = NGX_OK; ///< Fail open verdict incase of a timeout.
|
||||
ngx_int_t fail_mode_hold_verdict = NGX_OK; ///< Fail open verdict incase of a timeout when waiting for wait verdict.
|
||||
ngx_int_t dbg_is_needed = 0; ///< Debug flag.
|
||||
ngx_int_t num_of_connection_attempts = 0; ///< Maximum number of attempted connections.
|
||||
ngx_uint_t fail_open_timeout = 50; ///< Fail open timeout in milliseconds.
|
||||
ngx_uint_t fail_open_hold_timeout = 150; ///< Fail open wait timeout in milliseconds.
|
||||
ngx_http_cp_verdict_e sessions_per_minute_limit_verdict = TRAFFIC_VERDICT_ACCEPT;
|
||||
ngx_uint_t max_sessions_per_minute = 0; ///< Masimum session per minute.
|
||||
ngx_uint_t req_max_proccessing_ms_time = 3000; ///< Total Request processing timeout in milliseconds.
|
||||
@ -93,6 +95,7 @@ ngx_uint_t req_header_thread_timeout_msec = 100; ///< Request header processing
|
||||
ngx_uint_t req_body_thread_timeout_msec = 150; ///< Request body processing timeout in milliseconds.
|
||||
ngx_uint_t res_header_thread_timeout_msec = 100; ///< Response header processing timeout in milliseconds.
|
||||
ngx_uint_t res_body_thread_timeout_msec = 150; ///< Response body processing timeout in milliseconds.
|
||||
ngx_uint_t waiting_for_verdict_thread_timeout_msec = 150; ///< Wait thread processing timeout in milliseconds.
|
||||
ngx_http_inspection_mode_e inspection_mode = NON_BLOCKING_THREAD; ///< Default inspection mode.
|
||||
ngx_uint_t num_of_nginx_ipc_elements = 200; ///< Number of NGINX IPC elements.
|
||||
ngx_msec_t keep_alive_interval_msec = DEFAULT_KEEP_ALIVE_INTERVAL_MSEC;
|
||||
@ -892,6 +895,10 @@ init_general_config(const char *conf_path)
|
||||
fail_mode_verdict = isFailOpenMode() == 1 ? NGX_OK : NGX_ERROR;
|
||||
fail_open_timeout = getFailOpenTimeout();
|
||||
|
||||
// Setting fail wait open/close
|
||||
fail_mode_hold_verdict = isFailOpenHoldMode() == 1 ? NGX_OK : NGX_ERROR;
|
||||
fail_open_hold_timeout = getFailOpenHoldTimeout();
|
||||
|
||||
// Setting attachment's variables.
|
||||
sessions_per_minute_limit_verdict = isFailOpenOnSessionLimit() ? TRAFFIC_VERDICT_ACCEPT : TRAFFIC_VERDICT_DROP;
|
||||
max_sessions_per_minute = getMaxSessionsPerMinute();
|
||||
@ -903,6 +910,7 @@ init_general_config(const char *conf_path)
|
||||
req_body_thread_timeout_msec = getReqBodyThreadTimeout();
|
||||
res_header_thread_timeout_msec = getResHeaderThreadTimeout();
|
||||
res_body_thread_timeout_msec = getResBodyThreadTimeout();
|
||||
waiting_for_verdict_thread_timeout_msec = getWaitingForVerdictThreadTimeout();
|
||||
|
||||
num_of_nginx_ipc_elements = getNumOfNginxIpcElements();
|
||||
keep_alive_interval_msec = (ngx_msec_t) getKeepAliveIntervalMsec();
|
||||
@ -917,6 +925,8 @@ init_general_config(const char *conf_path)
|
||||
"debug level: %d, "
|
||||
"failure mode: %s, "
|
||||
"fail mode timeout: %u msec, "
|
||||
"failure wait mode: %s, "
|
||||
"fail mode wait timeout: %u msec, "
|
||||
"sessions per minute limit verdict: %s, "
|
||||
"max sessions per minute: %u, "
|
||||
"req max processing time: %u msec, "
|
||||
@ -926,6 +936,7 @@ init_general_config(const char *conf_path)
|
||||
"req body thread timeout: %u msec, "
|
||||
"res header thread timeout: %u msec, "
|
||||
"res body thread timeout: %u msec, "
|
||||
"wait thread timeout: %u msec, "
|
||||
"static resources path: %s, "
|
||||
"num of nginx ipc elements: %u, "
|
||||
"keep alive interval msec: %u msec",
|
||||
@ -933,6 +944,8 @@ init_general_config(const char *conf_path)
|
||||
new_dbg_level,
|
||||
(fail_mode_verdict == NGX_OK ? "fail-open" : "fail-close"),
|
||||
fail_open_timeout,
|
||||
(fail_mode_hold_verdict == NGX_OK ? "fail-open" : "fail-close"),
|
||||
fail_open_hold_timeout,
|
||||
sessions_per_minute_limit_verdict == TRAFFIC_VERDICT_ACCEPT ? "Accpet" : "Drop",
|
||||
max_sessions_per_minute,
|
||||
req_max_proccessing_ms_time,
|
||||
@ -942,6 +955,7 @@ init_general_config(const char *conf_path)
|
||||
req_body_thread_timeout_msec,
|
||||
res_header_thread_timeout_msec,
|
||||
res_body_thread_timeout_msec,
|
||||
waiting_for_verdict_thread_timeout_msec,
|
||||
getStaticResourcesPath(),
|
||||
num_of_nginx_ipc_elements,
|
||||
keep_alive_interval_msec
|
||||
|
@ -46,10 +46,12 @@
|
||||
}
|
||||
|
||||
extern ngx_int_t fail_mode_verdict;
|
||||
extern ngx_int_t fail_mode_hold_verdict;
|
||||
extern ngx_int_t dbg_is_needed;
|
||||
extern ngx_int_t num_of_connection_attempts;
|
||||
extern ngx_uint_t content_length_would_change;
|
||||
extern ngx_uint_t fail_open_timeout;
|
||||
extern ngx_uint_t fail_open_hold_timeout;
|
||||
extern ngx_uint_t req_max_proccessing_ms_time;
|
||||
extern ngx_uint_t res_max_proccessing_ms_time;
|
||||
extern ngx_uint_t registration_thread_timeout_msec;
|
||||
@ -57,6 +59,7 @@ extern ngx_uint_t req_header_thread_timeout_msec;
|
||||
extern ngx_uint_t req_body_thread_timeout_msec;
|
||||
extern ngx_uint_t res_header_thread_timeout_msec;
|
||||
extern ngx_uint_t res_body_thread_timeout_msec;
|
||||
extern ngx_uint_t waiting_for_verdict_thread_timeout_msec;
|
||||
extern ngx_http_inspection_mode_e inspection_mode;
|
||||
extern ngx_uint_t num_of_nginx_ipc_elements;
|
||||
|
||||
|
37
attachments/nginx/ngx_module/ngx_modules.c
Executable file
37
attachments/nginx/ngx_module/ngx_modules.c
Executable file
@ -0,0 +1,37 @@
|
||||
// Copyright (C) 2022 Check Point Software Technologies Ltd. All rights reserved.
|
||||
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
/// @file ngx_modules.c
|
||||
/// \brief This file is generated from configuration and hold the data structures connecting the plugin to the server
|
||||
|
||||
#include <ngx_config.h>
|
||||
#include <ngx_core.h>
|
||||
|
||||
extern ngx_module_t ngx_http_cp_attachment_module;
|
||||
|
||||
ngx_module_t *ngx_modules[] = {
|
||||
&ngx_http_cp_attachment_module,
|
||||
NULL
|
||||
};
|
||||
|
||||
char *ngx_module_names[] = {
|
||||
"ngx_http_cp_attachment_module",
|
||||
NULL
|
||||
};
|
||||
|
||||
char *ngx_module_order[] = {
|
||||
"ngx_http_cp_attachment_module",
|
||||
"ngx_http_copy_filter_module",
|
||||
NULL
|
||||
};
|
@ -1,2 +1,3 @@
|
||||
add_subdirectory(shmem_ipc)
|
||||
add_subdirectory(compression)
|
||||
add_subdirectory(attachments)
|
||||
|
1
core/attachments/CMakeLists.txt
Normal file
1
core/attachments/CMakeLists.txt
Normal file
@ -0,0 +1 @@
|
||||
add_subdirectory(http_configuration)
|
1
core/attachments/http_configuration/CMakeLists.txt
Normal file
1
core/attachments/http_configuration/CMakeLists.txt
Normal file
@ -0,0 +1 @@
|
||||
add_library(http_configuration http_configuration.cc)
|
220
core/attachments/http_configuration/http_configuration.cc
Normal file
220
core/attachments/http_configuration/http_configuration.cc
Normal file
@ -0,0 +1,220 @@
|
||||
// Copyright (C) 2022 Check Point Software Technologies Ltd. All rights reserved.
|
||||
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include "http_configuration.h"
|
||||
|
||||
#include <fstream>
|
||||
|
||||
#include "cereal/types/vector.hpp"
|
||||
|
||||
#define DEFAULT_KEEP_ALIVE_INTERVAL_MSEC 30000
|
||||
|
||||
using namespace std;
|
||||
|
||||
void
|
||||
DebugConfig::save(cereal::JSONOutputArchive &archive) const
|
||||
{
|
||||
archive(
|
||||
cereal::make_nvp("clientIp", client),
|
||||
cereal::make_nvp("listeningIp", server),
|
||||
cereal::make_nvp("uriPrefix", uri),
|
||||
cereal::make_nvp("hostName", host),
|
||||
cereal::make_nvp("httpMethod", method),
|
||||
cereal::make_nvp("listeningPort", port)
|
||||
);
|
||||
}
|
||||
|
||||
void
|
||||
DebugConfig::load(cereal::JSONInputArchive &archive)
|
||||
{
|
||||
try {
|
||||
archive(
|
||||
cereal::make_nvp("clientIp", client),
|
||||
cereal::make_nvp("listeningIp", server),
|
||||
cereal::make_nvp("uriPrefix", uri),
|
||||
cereal::make_nvp("hostName", host),
|
||||
cereal::make_nvp("httpMethod", method),
|
||||
cereal::make_nvp("listeningPort", port)
|
||||
);
|
||||
} catch (const cereal::Exception &) {
|
||||
client = "";
|
||||
server = "";
|
||||
uri = "";
|
||||
host = "";
|
||||
method = "";
|
||||
port = 0;
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
DebugConfig::operator==(const DebugConfig &another) const
|
||||
{
|
||||
return
|
||||
client == another.client &&
|
||||
server == another.server &&
|
||||
port == another.port &&
|
||||
method == another.method &&
|
||||
host == another.host &&
|
||||
uri == another.uri;
|
||||
}
|
||||
|
||||
int
|
||||
HttpAttachmentConfiguration::init(const string &conf_file)
|
||||
{
|
||||
try {
|
||||
ifstream file(conf_file);
|
||||
cereal::JSONInputArchive ar(file);
|
||||
load(ar);
|
||||
return 1;
|
||||
} catch (exception &e) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
HttpAttachmentConfiguration::save(cereal::JSONOutputArchive &archive) const
|
||||
{
|
||||
archive(
|
||||
cereal::make_nvp("context_values", dbg),
|
||||
cereal::make_nvp("ip_ranges", exclude_sources),
|
||||
cereal::make_nvp("dbg_level", getNumericalValue("dbg_level")),
|
||||
cereal::make_nvp("static_resources_path", getStringValue("static_resources_path")),
|
||||
cereal::make_nvp("is_fail_open_mode_enabled", getNumericalValue("is_fail_open_mode_enabled")),
|
||||
cereal::make_nvp("fail_open_timeout", getNumericalValue("fail_open_timeout")),
|
||||
cereal::make_nvp("is_fail_open_mode_hold_enabled", getNumericalValue("is_fail_open_mode_hold_enabled")),
|
||||
cereal::make_nvp("fail_open_hold_timeout", getNumericalValue("fail_open_hold_timeout")),
|
||||
cereal::make_nvp("sessions_per_minute_limit_verdict", getStringValue("sessions_per_minute_limit_verdict")),
|
||||
cereal::make_nvp("max_sessions_per_minute", getNumericalValue("max_sessions_per_minute")),
|
||||
cereal::make_nvp("res_proccessing_timeout_msec", getNumericalValue("res_proccessing_timeout_msec")),
|
||||
cereal::make_nvp("req_proccessing_timeout_msec", getNumericalValue("req_proccessing_timeout_msec")),
|
||||
cereal::make_nvp("registration_thread_timeout_msec", getNumericalValue("registration_thread_timeout_msec")),
|
||||
cereal::make_nvp("req_header_thread_timeout_msec", getNumericalValue("req_header_thread_timeout_msec")),
|
||||
cereal::make_nvp("req_body_thread_timeout_msec", getNumericalValue("req_body_thread_timeout_msec")),
|
||||
cereal::make_nvp("res_header_thread_timeout_msec", getNumericalValue("res_header_thread_timeout_msec")),
|
||||
cereal::make_nvp("res_body_thread_timeout_msec", getNumericalValue("res_body_thread_timeout_msec")),
|
||||
cereal::make_nvp(
|
||||
"waiting_for_verdict_thread_timeout_msec",
|
||||
getNumericalValue("waiting_for_verdict_thread_timeout_msec")
|
||||
),
|
||||
cereal::make_nvp("nginx_inspection_mode", getNumericalValue("inspection_mode")),
|
||||
cereal::make_nvp("num_of_nginx_ipc_elements", getNumericalValue("num_of_nginx_ipc_elements")),
|
||||
cereal::make_nvp("keep_alive_interval_msec", getNumericalValue("keep_alive_interval_msec"))
|
||||
);
|
||||
}
|
||||
|
||||
void
|
||||
HttpAttachmentConfiguration::load(cereal::JSONInputArchive &archive)
|
||||
{
|
||||
try {
|
||||
archive(cereal::make_nvp("context_values", dbg));
|
||||
} catch (const cereal::Exception &) {
|
||||
dbg = DebugConfig();
|
||||
}
|
||||
|
||||
try {
|
||||
archive(cereal::make_nvp("ip_ranges", exclude_sources));
|
||||
} catch (const cereal::Exception &) {
|
||||
exclude_sources = {};
|
||||
}
|
||||
|
||||
try {
|
||||
string str;
|
||||
archive(cereal::make_nvp("static_resources_path", str));
|
||||
string_values["static_resources_path"] = str;
|
||||
} catch (const cereal::Exception &) {
|
||||
string_values.erase("static_resources_path");
|
||||
}
|
||||
|
||||
try {
|
||||
string str;
|
||||
archive(cereal::make_nvp("sessions_per_minute_limit_verdict", str));
|
||||
string_values["sessions_per_minute_limit_verdict"] = str;
|
||||
} catch (const cereal::Exception &) {
|
||||
string_values.erase("sessions_per_minute_limit_verdict");
|
||||
}
|
||||
|
||||
loadNumericalValue(archive, "dbg_level", 0);
|
||||
loadNumericalValue(archive, "is_fail_open_mode_enabled", 0);
|
||||
loadNumericalValue(archive, "fail_open_timeout", 50);
|
||||
loadNumericalValue(archive, "is_fail_open_mode_hold_enabled", 0);
|
||||
loadNumericalValue(archive, "fail_open_hold_timeout", 200);
|
||||
loadNumericalValue(archive, "sessions_per_minute_limit_verdict", 0);
|
||||
loadNumericalValue(archive, "max_sessions_per_minute", 0);
|
||||
loadNumericalValue(archive, "res_proccessing_timeout_msec", 3000);
|
||||
loadNumericalValue(archive, "req_proccessing_timeout_msec", 3000);
|
||||
loadNumericalValue(archive, "registration_thread_timeout_msec", 100);
|
||||
loadNumericalValue(archive, "req_header_thread_timeout_msec", 100);
|
||||
loadNumericalValue(archive, "req_body_thread_timeout_msec", 150);
|
||||
loadNumericalValue(archive, "res_header_thread_timeout_msec", 100);
|
||||
loadNumericalValue(archive, "res_body_thread_timeout_msec", 150);
|
||||
loadNumericalValue(archive, "waiting_for_verdict_thread_timeout_msec", 150);
|
||||
loadNumericalValue(archive, "nginx_inspection_mode", 0);
|
||||
loadNumericalValue(archive, "num_of_nginx_ipc_elements", 200);
|
||||
loadNumericalValue(archive, "keep_alive_interval_msec", DEFAULT_KEEP_ALIVE_INTERVAL_MSEC);
|
||||
|
||||
try {
|
||||
string user_check_logo_path;
|
||||
archive(cereal::make_nvp("user_check_logo_path", user_check_logo_path));
|
||||
ifstream logo_file(user_check_logo_path);
|
||||
if (!logo_file.is_open()) {
|
||||
string_values.erase("user_check_logo");
|
||||
} else {
|
||||
string_values["user_check_logo"] = string(
|
||||
istreambuf_iterator<char>(logo_file),
|
||||
istreambuf_iterator<char>()
|
||||
);
|
||||
}
|
||||
} catch (const cereal::Exception &) {
|
||||
string_values.erase("user_check_logo");
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
HttpAttachmentConfiguration::operator==(const HttpAttachmentConfiguration &other) const
|
||||
{
|
||||
return
|
||||
dbg == other.dbg &&
|
||||
numerical_values == other.numerical_values &&
|
||||
string_values == other.string_values &&
|
||||
exclude_sources == other.exclude_sources;
|
||||
}
|
||||
|
||||
unsigned int
|
||||
HttpAttachmentConfiguration::getNumericalValue(const string &key) const
|
||||
{
|
||||
auto elem = numerical_values.find(key);
|
||||
return elem != numerical_values.end() ? elem->second : 0;
|
||||
}
|
||||
|
||||
const string &
|
||||
HttpAttachmentConfiguration::getStringValue(const string &key) const
|
||||
{
|
||||
auto elem = string_values.find(key);
|
||||
return elem != string_values.end() ? elem->second : empty;
|
||||
}
|
||||
|
||||
void
|
||||
HttpAttachmentConfiguration::loadNumericalValue(
|
||||
cereal::JSONInputArchive &ar,
|
||||
const string &name,
|
||||
unsigned int default_value
|
||||
)
|
||||
{
|
||||
try {
|
||||
unsigned int value;
|
||||
ar(cereal::make_nvp(name, value));
|
||||
numerical_values[name] = value;
|
||||
} catch (const cereal::Exception &) {
|
||||
numerical_values[name] = default_value;
|
||||
}
|
||||
}
|
@ -105,6 +105,7 @@ static const int zlib_no_flush = Z_NO_FLUSH;
|
||||
struct CompressionStream
|
||||
{
|
||||
CompressionStream() { bzero(&stream, sizeof(z_stream)); }
|
||||
~CompressionStream() { fini(); }
|
||||
|
||||
tuple<basic_string<unsigned char>, bool>
|
||||
decompress(const unsigned char *data, uint32_t size)
|
||||
|
@ -29,7 +29,7 @@ struct DebugConfig
|
||||
|
||||
std::string client;
|
||||
std::string server;
|
||||
uint port = 0;
|
||||
unsigned int port = 0;
|
||||
std::string method;
|
||||
std::string host;
|
||||
std::string uri;
|
||||
@ -45,21 +45,21 @@ public:
|
||||
|
||||
bool operator==(const HttpAttachmentConfiguration &other) const;
|
||||
|
||||
uint getNumericalValue(const std::string &key) const;
|
||||
unsigned int getNumericalValue(const std::string &key) const;
|
||||
const std::string & getStringValue(const std::string &key) const;
|
||||
const std::vector<std::string> & getExcludeSources() const { return exclude_sources; }
|
||||
const DebugConfig & getDebugContext() const { return dbg; }
|
||||
|
||||
void setNumericalValue(const std::string &key, uint value) { numerical_values[key] = value; }
|
||||
void setNumericalValue(const std::string &key, unsigned int value) { numerical_values[key] = value; }
|
||||
void setStringValue(const std::string &key, const std::string &value) { string_values[key] = value; }
|
||||
void setExcludeSources(const std::vector<std::string> &new_sources) { exclude_sources = new_sources; }
|
||||
void setDebugContext(const DebugConfig &_dbg) { dbg = _dbg; }
|
||||
|
||||
private:
|
||||
void loadNumericalValue(cereal::JSONInputArchive &archive, const std::string &name, uint default_value);
|
||||
void loadNumericalValue(cereal::JSONInputArchive &archive, const std::string &name, unsigned int default_value);
|
||||
|
||||
DebugConfig dbg;
|
||||
std::map<std::string, uint> numerical_values;
|
||||
std::map<std::string, unsigned int> numerical_values;
|
||||
std::map<std::string, std::string> string_values;
|
||||
std::vector<std::string> exclude_sources;
|
||||
std::string empty;
|
||||
|
@ -64,6 +64,7 @@ typedef enum ngx_http_chunk_type
|
||||
RESPONSE_END,
|
||||
CONTENT_LENGTH,
|
||||
METRIC_DATA_FROM_PLUGIN,
|
||||
HOLD_DATA,
|
||||
|
||||
COUNT
|
||||
} ngx_http_chunk_type_e;
|
||||
@ -85,6 +86,7 @@ typedef enum ngx_http_plugin_metric_type
|
||||
IRRELEVANT_VERDICTS_COUNT,
|
||||
RECONF_VERDICTS_COUNT,
|
||||
INSPECT_VERDICTS_COUNT,
|
||||
HOLD_VERDICTS_COUNT,
|
||||
AVERAGE_OVERALL_PPROCESSING_TIME_UNTIL_VERDICT,
|
||||
MAX_OVERALL_PPROCESSING_TIME_UNTIL_VERDICT,
|
||||
MIN_OVERALL_PPROCESSING_TIME_UNTIL_VERDICT,
|
||||
@ -103,6 +105,7 @@ typedef enum ngx_http_plugin_metric_type
|
||||
MIN_REQ_BODY_SIZE_UPON_TIMEOUT,
|
||||
RES_HEADER_THREAD_TIMEOUT,
|
||||
RES_BODY_THREAD_TIMEOUT,
|
||||
HOLD_THREAD_TIMEOUT,
|
||||
AVERAGE_RES_BODY_SIZE_UPON_TIMEOUT,
|
||||
MAX_RES_BODY_SIZE_UPON_TIMEOUT,
|
||||
MIN_RES_BODY_SIZE_UPON_TIMEOUT,
|
||||
@ -139,7 +142,8 @@ typedef enum ngx_http_cp_verdict
|
||||
TRAFFIC_VERDICT_DROP,
|
||||
TRAFFIC_VERDICT_INJECT,
|
||||
TRAFFIC_VERDICT_IRRELEVANT,
|
||||
TRAFFIC_VERDICT_RECONF
|
||||
TRAFFIC_VERDICT_RECONF,
|
||||
TRAFFIC_VERDICT_WAIT
|
||||
} ngx_http_cp_verdict_e;
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
@ -33,12 +33,15 @@ ngx_http_inspection_mode_e getInspectionMode();
|
||||
unsigned int getNumOfNginxIpcElements();
|
||||
unsigned int getKeepAliveIntervalMsec();
|
||||
unsigned int getDbgLevel();
|
||||
int isDebugContext(c_str client, c_str server, unsigned int port, c_str method, c_str host , c_str uri);
|
||||
int isDebugContext(c_str client, c_str server, unsigned int port, c_str method, c_str host, c_str uri);
|
||||
c_str getStaticResourcesPath();
|
||||
|
||||
int isFailOpenMode();
|
||||
unsigned int getFailOpenTimeout();
|
||||
|
||||
int isFailOpenHoldMode();
|
||||
unsigned int getFailOpenHoldTimeout();
|
||||
|
||||
unsigned int getMaxSessionsPerMinute();
|
||||
int isFailOpenOnSessionLimit();
|
||||
|
||||
@ -52,6 +55,8 @@ unsigned int getResProccessingTimeout();
|
||||
unsigned int getResHeaderThreadTimeout();
|
||||
unsigned int getResBodyThreadTimeout();
|
||||
|
||||
unsigned int getWaitingForVerdictThreadTimeout();
|
||||
|
||||
int isIPAddress(c_str ip_str);
|
||||
int isSkipSource(c_str ip_str);
|
||||
|
||||
|
@ -26,8 +26,9 @@
|
||||
|
||||
#include "shared_ipc_debug.h"
|
||||
|
||||
static const uint16_t empty_buff_mgmt_magic = 0xcafe;
|
||||
static const uint16_t skip_buff_mgmt_magic = 0xbeef;
|
||||
static const uint16_t empty_buff_mgmt_magic = 0xfffe;
|
||||
static const uint16_t skip_buff_mgmt_magic = 0xfffd;
|
||||
static const uint32_t max_write_size = 0xfffc;
|
||||
const uint16_t max_num_of_data_segments = sizeof(DataSegment)/sizeof(uint16_t);
|
||||
|
||||
char g_rx_location_name[MAX_ONE_WAY_QUEUE_NAME_LENGTH] = "";
|
||||
@ -52,11 +53,8 @@ getNumOfDataSegmentsNeeded(uint16_t data_size)
|
||||
}
|
||||
|
||||
static int
|
||||
isThereEnoughMemoryInQueue(SharedRingQueue *queue, uint8_t num_of_elem_to_push)
|
||||
isThereEnoughMemoryInQueue(uint16_t write_pos, uint16_t read_pos, uint8_t num_of_elem_to_push)
|
||||
{
|
||||
uint16_t write_pos = queue->write_pos;
|
||||
uint16_t read_pos = queue->read_pos;
|
||||
uint16_t num_of_data_segments = queue->num_of_data_segments;
|
||||
int res;
|
||||
|
||||
writeDebug(
|
||||
@ -65,21 +63,21 @@ isThereEnoughMemoryInQueue(SharedRingQueue *queue, uint8_t num_of_elem_to_push)
|
||||
num_of_elem_to_push,
|
||||
write_pos,
|
||||
read_pos,
|
||||
num_of_data_segments
|
||||
g_num_of_data_segments
|
||||
);
|
||||
if (num_of_elem_to_push >= num_of_data_segments) {
|
||||
if (num_of_elem_to_push >= g_num_of_data_segments) {
|
||||
writeDebug(TraceLevel, "Amount of elements to push is larger then amount of available elements in the queue");
|
||||
return 0;
|
||||
}
|
||||
|
||||
// add skipped elements during write that does not fit from cur write position till end of queue
|
||||
if (write_pos + num_of_elem_to_push > num_of_data_segments) {
|
||||
num_of_elem_to_push += num_of_data_segments - write_pos;
|
||||
if (write_pos + num_of_elem_to_push > g_num_of_data_segments) {
|
||||
num_of_elem_to_push += g_num_of_data_segments - write_pos;
|
||||
}
|
||||
|
||||
// removing the aspect of circularity in queue and simulating as if the queue continued at its end
|
||||
if (write_pos + num_of_elem_to_push >= num_of_data_segments) {
|
||||
read_pos += num_of_data_segments;
|
||||
if (write_pos + num_of_elem_to_push >= g_num_of_data_segments) {
|
||||
read_pos += g_num_of_data_segments;
|
||||
}
|
||||
|
||||
res = write_pos + num_of_elem_to_push < read_pos || write_pos >= read_pos;
|
||||
@ -87,6 +85,22 @@ isThereEnoughMemoryInQueue(SharedRingQueue *queue, uint8_t num_of_elem_to_push)
|
||||
return res;
|
||||
}
|
||||
|
||||
static int
|
||||
isGetPossitionSucceccful(SharedRingQueue *queue, uint16_t *read_pos, uint16_t *write_pos)
|
||||
{
|
||||
if (g_num_of_data_segments == 0) return 0;
|
||||
|
||||
*read_pos = queue->read_pos;
|
||||
*write_pos = queue->write_pos;
|
||||
|
||||
if (queue->num_of_data_segments != g_num_of_data_segments) return 0;
|
||||
if (queue->size_of_memory != g_memory_size) return 0;
|
||||
if (*read_pos > g_num_of_data_segments) return 0;
|
||||
if (*write_pos > g_num_of_data_segments) return 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
void
|
||||
resetRingQueue(SharedRingQueue *queue, uint16_t num_of_data_segments)
|
||||
{
|
||||
@ -126,13 +140,14 @@ createSharedRingQueue(const char *shared_location_name, uint16_t num_of_data_seg
|
||||
|
||||
g_num_of_data_segments = num_of_data_segments;
|
||||
|
||||
fd = shm_open(shared_location_name, shmem_fd_flags, S_IRWXU | S_IRWXG | S_IRWXO);
|
||||
fd = shm_open(shared_location_name, shmem_fd_flags, S_IRUSR | S_IWUSR);
|
||||
if (fd == -1) {
|
||||
writeDebug(
|
||||
WarningLevel,
|
||||
"createSharedRingQueue: Failed to open shared memory for '%s'. Errno: %d\n",
|
||||
"createSharedRingQueue: Failed to open shared memory for '%s'. Errno: %d (%s)\n",
|
||||
shared_location_name,
|
||||
errno
|
||||
errno,
|
||||
strerror(errno)
|
||||
);
|
||||
return NULL;
|
||||
}
|
||||
@ -257,7 +272,7 @@ dumpRingQueueShmem(SharedRingQueue *queue)
|
||||
|
||||
writeDebug(WarningLevel, "mgmt_segment:");
|
||||
buffer_mgmt = (uint16_t *)queue->mgmt_segment.data;
|
||||
for (segment_idx = 0; segment_idx < max_num_of_data_segments; segment_idx++) {
|
||||
for (segment_idx = 0; segment_idx < queue->num_of_data_segments; segment_idx++) {
|
||||
writeDebug(WarningLevel, "%s%u", (segment_idx == 0 ? " " : ", "), buffer_mgmt[segment_idx]);
|
||||
}
|
||||
|
||||
@ -275,39 +290,44 @@ dumpRingQueueShmem(SharedRingQueue *queue)
|
||||
int
|
||||
peekToQueue(SharedRingQueue *queue, const char **output_buffer, uint16_t *output_buffer_size)
|
||||
{
|
||||
uint16_t read_pos = queue->read_pos;
|
||||
const uint16_t num_of_data_segments = queue->num_of_data_segments;
|
||||
uint16_t read_pos;
|
||||
uint16_t write_pos;
|
||||
uint16_t *buffer_mgmt = (uint16_t *)queue->mgmt_segment.data;
|
||||
|
||||
if (!isGetPossitionSucceccful(queue, &read_pos, &write_pos)) {
|
||||
writeDebug(WarningLevel, "Corrupted shared memory - cannot peek");
|
||||
return -1;
|
||||
}
|
||||
|
||||
writeDebug(
|
||||
TraceLevel,
|
||||
"Reading data from queue. Read index: %u, number of queue elements: %u",
|
||||
read_pos,
|
||||
num_of_data_segments
|
||||
g_num_of_data_segments
|
||||
);
|
||||
|
||||
if (isQueueEmpty(queue)) {
|
||||
if (read_pos == write_pos) {
|
||||
writeDebug(WarningLevel, "peekToQueue: Failed to read from an empty queue\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (read_pos >= num_of_data_segments) {
|
||||
if (read_pos >= g_num_of_data_segments) {
|
||||
writeDebug(
|
||||
WarningLevel,
|
||||
"peekToQueue: Failed to read from a corrupted queue! (read_pos= %d > num_of_data_segments=%d)\n",
|
||||
read_pos,
|
||||
num_of_data_segments
|
||||
g_num_of_data_segments
|
||||
);
|
||||
return CORRUPTED_SHMEM_ERROR;
|
||||
}
|
||||
|
||||
if (buffer_mgmt[read_pos] == skip_buff_mgmt_magic) {
|
||||
for ( ; read_pos < num_of_data_segments && buffer_mgmt[read_pos] == skip_buff_mgmt_magic; ++read_pos) {
|
||||
for ( ; read_pos < g_num_of_data_segments && buffer_mgmt[read_pos] == skip_buff_mgmt_magic; ++read_pos) {
|
||||
buffer_mgmt[read_pos] = empty_buff_mgmt_magic;
|
||||
}
|
||||
}
|
||||
|
||||
if (read_pos == num_of_data_segments) read_pos = 0;
|
||||
if (read_pos == g_num_of_data_segments) read_pos = 0;
|
||||
|
||||
*output_buffer_size = buffer_mgmt[read_pos];
|
||||
*output_buffer = queue->data_segment[read_pos].data;
|
||||
@ -332,25 +352,42 @@ pushBuffersToQueue(
|
||||
)
|
||||
{
|
||||
int idx;
|
||||
const uint16_t num_of_queue_elem = queue->num_of_data_segments;
|
||||
uint16_t write_pos = queue->write_pos;
|
||||
uint16_t total_elem_size = 0;
|
||||
uint32_t large_total_elem_size = 0;
|
||||
uint16_t read_pos;
|
||||
uint16_t write_pos;
|
||||
uint16_t total_elem_size;
|
||||
uint16_t *buffer_mgmt = (uint16_t *)queue->mgmt_segment.data;
|
||||
uint16_t end_pos;
|
||||
uint16_t num_of_segments_to_write;
|
||||
char *current_copy_pos;
|
||||
|
||||
if (!isGetPossitionSucceccful(queue, &read_pos, &write_pos)) {
|
||||
writeDebug(WarningLevel, "Corrupted shared memory - cannot push new buffers");
|
||||
return -1;
|
||||
}
|
||||
|
||||
writeDebug(
|
||||
TraceLevel,
|
||||
"Writing new data to queue. write index: %u, number of queue elements: %u, number of elements to push: %u",
|
||||
write_pos,
|
||||
num_of_queue_elem,
|
||||
g_num_of_data_segments,
|
||||
num_of_input_buffers
|
||||
);
|
||||
|
||||
for (idx = 0; idx < num_of_input_buffers; idx++) {
|
||||
total_elem_size += input_buffers_sizes[idx];
|
||||
large_total_elem_size += input_buffers_sizes[idx];
|
||||
|
||||
if (large_total_elem_size > max_write_size) {
|
||||
writeDebug(
|
||||
WarningLevel,
|
||||
"Requested write size %u exceeds the %u write limit",
|
||||
large_total_elem_size,
|
||||
max_write_size
|
||||
);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
total_elem_size = (uint16_t)large_total_elem_size;
|
||||
|
||||
num_of_segments_to_write = getNumOfDataSegmentsNeeded(total_elem_size);
|
||||
|
||||
@ -362,23 +399,23 @@ pushBuffersToQueue(
|
||||
);
|
||||
|
||||
|
||||
if (!isThereEnoughMemoryInQueue(queue, num_of_segments_to_write)) {
|
||||
if (!isThereEnoughMemoryInQueue(write_pos, read_pos, num_of_segments_to_write)) {
|
||||
writeDebug(WarningLevel, "Cannot write to a full queue\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (write_pos >= num_of_queue_elem) {
|
||||
if (write_pos >= g_num_of_data_segments) {
|
||||
writeDebug(
|
||||
WarningLevel,
|
||||
"Cannot write to a location outside the queue. Write index: %u, number of queue elements: %u",
|
||||
write_pos,
|
||||
num_of_queue_elem
|
||||
g_num_of_data_segments
|
||||
);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (write_pos + num_of_segments_to_write > num_of_queue_elem) {
|
||||
for ( ; write_pos < num_of_queue_elem; ++write_pos) {
|
||||
if (write_pos + num_of_segments_to_write > g_num_of_data_segments) {
|
||||
for ( ; write_pos < g_num_of_data_segments; ++write_pos) {
|
||||
buffer_mgmt[write_pos] = skip_buff_mgmt_magic;
|
||||
}
|
||||
write_pos = 0;
|
||||
@ -411,8 +448,9 @@ pushBuffersToQueue(
|
||||
buffer_mgmt[write_pos] = skip_buff_mgmt_magic;
|
||||
}
|
||||
|
||||
queue->write_pos = write_pos < num_of_queue_elem ? write_pos : 0;
|
||||
writeDebug(TraceLevel, "Successfully pushed data to queue. New write index: %u", queue->write_pos);
|
||||
if (write_pos >= g_num_of_data_segments) write_pos = 0;
|
||||
queue->write_pos = write_pos;
|
||||
writeDebug(TraceLevel, "Successfully pushed data to queue. New write index: %u", write_pos);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -427,19 +465,24 @@ int
|
||||
popFromQueue(SharedRingQueue *queue)
|
||||
{
|
||||
uint16_t num_of_read_segments;
|
||||
uint16_t read_pos = queue->read_pos;
|
||||
uint16_t read_pos;
|
||||
uint16_t write_pos;
|
||||
uint16_t end_pos;
|
||||
uint16_t num_of_data_segments = queue->num_of_data_segments;
|
||||
uint16_t *buffer_mgmt = (uint16_t *)queue->mgmt_segment.data;
|
||||
|
||||
if (!isGetPossitionSucceccful(queue, &read_pos, &write_pos)) {
|
||||
writeDebug(WarningLevel, "Corrupted shared memory - cannot pop data");
|
||||
return -1;
|
||||
}
|
||||
|
||||
writeDebug(
|
||||
TraceLevel,
|
||||
"Removing data from queue. new data to queue. Read index: %u, number of queue elements: %u",
|
||||
read_pos,
|
||||
num_of_data_segments
|
||||
g_num_of_data_segments
|
||||
);
|
||||
|
||||
if (isQueueEmpty(queue)) {
|
||||
if (read_pos == write_pos) {
|
||||
writeDebug(TraceLevel, "Cannot pop data from empty queue");
|
||||
return -1;
|
||||
}
|
||||
@ -460,16 +503,16 @@ popFromQueue(SharedRingQueue *queue)
|
||||
buffer_mgmt[read_pos] = empty_buff_mgmt_magic;
|
||||
}
|
||||
|
||||
if (read_pos < num_of_data_segments && buffer_mgmt[read_pos] == skip_buff_mgmt_magic) {
|
||||
for ( ; read_pos < num_of_data_segments; ++read_pos ) {
|
||||
if (read_pos < g_num_of_data_segments && buffer_mgmt[read_pos] == skip_buff_mgmt_magic) {
|
||||
for ( ; read_pos < g_num_of_data_segments; ++read_pos ) {
|
||||
buffer_mgmt[read_pos] = empty_buff_mgmt_magic;
|
||||
}
|
||||
}
|
||||
|
||||
if (read_pos == num_of_data_segments) read_pos = 0;
|
||||
if (read_pos == g_num_of_data_segments) read_pos = 0;
|
||||
|
||||
queue->read_pos = read_pos;
|
||||
writeDebug(TraceLevel, "Successfully popped data from queue. New read index: %u", queue->read_pos);
|
||||
writeDebug(TraceLevel, "Successfully popped data from queue. New read index: %u", read_pos);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -50,6 +50,7 @@ debugInitial(int is_error, const char *func, const char *file, int line_num, con
|
||||
va_start(args, fmt);
|
||||
vprintf(fmt, args);
|
||||
va_end(args);
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
void (*debug_int)(int is_error, const char *func, const char *file, int line_num, const char *fmt, ...) = debugInitial;
|
||||
@ -100,7 +101,7 @@ createOneWayIPCQueue(
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (is_owner && chmod(shmem_path, 0666) == -1) {
|
||||
if (is_owner && chown(shmem_path, user_id, group_id) == -1) {
|
||||
writeDebug(WarningLevel, "Failed to set the permissions");
|
||||
destroySharedRingQueue(ring_queue, is_owner, isTowardsOwner(is_owner, is_tx_queue));
|
||||
return NULL;
|
||||
|
11
docker/CMakeLists.txt
Normal file
11
docker/CMakeLists.txt
Normal file
@ -0,0 +1,11 @@
|
||||
install(TARGETS ngx_module DESTINATION lib)
|
||||
|
||||
add_custom_command(
|
||||
OUTPUT ${CMAKE_INSTALL_PREFIX}/nginx-docker.img
|
||||
COMMAND docker build -t nginx-docker ${CMAKE_INSTALL_PREFIX}
|
||||
COMMAND docker tag nginx-docker ${OUTPUT_DOCKER_IMAGE}
|
||||
COMMAND docker push ${OUTPUT_DOCKER_IMAGE}
|
||||
COMMAND docker image save nginx-docker -o ${CMAKE_INSTALL_PREFIX}/nginx-docker.img
|
||||
)
|
||||
|
||||
add_custom_target(docker DEPENDS ${CMAKE_INSTALL_PREFIX}/nginx-docker.img)
|
18
docker/Dockerfile
Normal file
18
docker/Dockerfile
Normal file
@ -0,0 +1,18 @@
|
||||
FROM <DOCKER BASE IMAGE>
|
||||
|
||||
USER root
|
||||
|
||||
RUN apk update
|
||||
RUN apk add --no-cache -u busybox
|
||||
RUN apk add --no-cache -u zlib
|
||||
RUN apk add --no-cache libstdc++
|
||||
|
||||
USER <DOCKER USER>
|
||||
|
||||
COPY lib/libosrc_compression_utils.so /usr/lib/libosrc_compression_utils.so
|
||||
COPY lib/libosrc_nginx_attachment_util.so /usr/lib/libosrc_nginx_attachment_util.so
|
||||
COPY lib/libosrc_shmem_ipc.so /usr/lib/libosrc_shmem_ipc.so
|
||||
COPY lib/libngx_module.so /usr/lib/nginx/modules/ngx_cp_attachment_module.so
|
||||
|
||||
RUN echo "load_module /usr/lib/nginx/modules/ngx_cp_attachment_module.so;"|cat - /etc/nginx/nginx.conf> /tmp/out && mv /tmp/out /etc/nginx/nginx.conf
|
||||
RUN [ -f /etc/nginx/template/nginx.tmpl ] && echo "load_module /usr/lib/nginx/modules/ngx_cp_attachment_module.so;"|cat - /etc/nginx/template/nginx.tmpl> /tmp/out.tmpl && mv /tmp/out.tmpl /etc/nginx/template/nginx.tmpl
|
1
external/cereal/archives/json.hpp
vendored
1
external/cereal/archives/json.hpp
vendored
@ -44,6 +44,7 @@ namespace cereal
|
||||
#ifndef CEREAL_RAPIDJSON_ASSERT
|
||||
#define CEREAL_RAPIDJSON_ASSERT(x) if(!(x)){ \
|
||||
throw ::cereal::RapidJSONException("rapidjson internal assertion failure: " #x); }
|
||||
#define RAPIDJSON_ASSERT(x) CEREAL_RAPIDJSON_ASSERT(x)
|
||||
#endif // RAPIDJSON_ASSERT
|
||||
|
||||
// Enable support for parsing of nan, inf, -inf
|
||||
|
550
external/cereal/external/rapidjson/allocators.h
vendored
550
external/cereal/external/rapidjson/allocators.h
vendored
@ -1,6 +1,6 @@
|
||||
// Tencent is pleased to support the open source community by making RapidJSON available.
|
||||
//
|
||||
// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
|
||||
// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip.
|
||||
//
|
||||
// Licensed under the MIT License (the "License"); you may not use this file except
|
||||
// in compliance with the License. You may obtain a copy of the License at
|
||||
@ -12,12 +12,20 @@
|
||||
// CONDITIONS OF ANY KIND, either express or implied. See the License for the
|
||||
// specific language governing permissions and limitations under the License.
|
||||
|
||||
#ifndef CEREAL_RAPIDJSON_ALLOCATORS_H_
|
||||
#define CEREAL_RAPIDJSON_ALLOCATORS_H_
|
||||
#ifndef RAPIDJSON_ALLOCATORS_H_
|
||||
#define RAPIDJSON_ALLOCATORS_H_
|
||||
|
||||
#include "rapidjson.h"
|
||||
#include "internal/meta.h"
|
||||
|
||||
CEREAL_RAPIDJSON_NAMESPACE_BEGIN
|
||||
#include <memory>
|
||||
#include <limits>
|
||||
|
||||
#if RAPIDJSON_HAS_CXX11
|
||||
#include <type_traits>
|
||||
#endif
|
||||
|
||||
RAPIDJSON_NAMESPACE_BEGIN
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Allocator
|
||||
@ -52,6 +60,19 @@ concept Allocator {
|
||||
\endcode
|
||||
*/
|
||||
|
||||
|
||||
/*! \def RAPIDJSON_ALLOCATOR_DEFAULT_CHUNK_CAPACITY
|
||||
\ingroup RAPIDJSON_CONFIG
|
||||
\brief User-defined kDefaultChunkCapacity definition.
|
||||
|
||||
User can define this as any \c size that is a power of 2.
|
||||
*/
|
||||
|
||||
#ifndef RAPIDJSON_ALLOCATOR_DEFAULT_CHUNK_CAPACITY
|
||||
#define RAPIDJSON_ALLOCATOR_DEFAULT_CHUNK_CAPACITY (64 * 1024)
|
||||
#endif
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// CrtAllocator
|
||||
|
||||
@ -64,19 +85,26 @@ public:
|
||||
static const bool kNeedFree = true;
|
||||
void* Malloc(size_t size) {
|
||||
if (size) // behavior of malloc(0) is implementation defined.
|
||||
return std::malloc(size);
|
||||
return RAPIDJSON_MALLOC(size);
|
||||
else
|
||||
return NULL; // standardize to returning NULL.
|
||||
}
|
||||
void* Realloc(void* originalPtr, size_t originalSize, size_t newSize) {
|
||||
(void)originalSize;
|
||||
if (newSize == 0) {
|
||||
std::free(originalPtr);
|
||||
RAPIDJSON_FREE(originalPtr);
|
||||
return NULL;
|
||||
}
|
||||
return std::realloc(originalPtr, newSize);
|
||||
return RAPIDJSON_REALLOC(originalPtr, newSize);
|
||||
}
|
||||
static void Free(void *ptr) RAPIDJSON_NOEXCEPT { RAPIDJSON_FREE(ptr); }
|
||||
|
||||
bool operator==(const CrtAllocator&) const RAPIDJSON_NOEXCEPT {
|
||||
return true;
|
||||
}
|
||||
bool operator!=(const CrtAllocator&) const RAPIDJSON_NOEXCEPT {
|
||||
return false;
|
||||
}
|
||||
static void Free(void *ptr) { std::free(ptr); }
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
@ -100,16 +128,64 @@ public:
|
||||
*/
|
||||
template <typename BaseAllocator = CrtAllocator>
|
||||
class MemoryPoolAllocator {
|
||||
//! Chunk header for perpending to each chunk.
|
||||
/*! Chunks are stored as a singly linked list.
|
||||
*/
|
||||
struct ChunkHeader {
|
||||
size_t capacity; //!< Capacity of the chunk in bytes (excluding the header itself).
|
||||
size_t size; //!< Current size of allocated memory in bytes.
|
||||
ChunkHeader *next; //!< Next chunk in the linked list.
|
||||
};
|
||||
|
||||
struct SharedData {
|
||||
ChunkHeader *chunkHead; //!< Head of the chunk linked-list. Only the head chunk serves allocation.
|
||||
BaseAllocator* ownBaseAllocator; //!< base allocator created by this object.
|
||||
size_t refcount;
|
||||
bool ownBuffer;
|
||||
};
|
||||
|
||||
static const size_t SIZEOF_SHARED_DATA = RAPIDJSON_ALIGN(sizeof(SharedData));
|
||||
static const size_t SIZEOF_CHUNK_HEADER = RAPIDJSON_ALIGN(sizeof(ChunkHeader));
|
||||
|
||||
static inline ChunkHeader *GetChunkHead(SharedData *shared)
|
||||
{
|
||||
return reinterpret_cast<ChunkHeader*>(reinterpret_cast<uint8_t*>(shared) + SIZEOF_SHARED_DATA);
|
||||
}
|
||||
static inline uint8_t *GetChunkBuffer(SharedData *shared)
|
||||
{
|
||||
return reinterpret_cast<uint8_t*>(shared->chunkHead) + SIZEOF_CHUNK_HEADER;
|
||||
}
|
||||
|
||||
static const size_t kDefaultChunkCapacity = RAPIDJSON_ALLOCATOR_DEFAULT_CHUNK_CAPACITY; //!< Default chunk capacity.
|
||||
|
||||
public:
|
||||
static const bool kNeedFree = false; //!< Tell users that no need to call Free() with this allocator. (concept Allocator)
|
||||
static const bool kRefCounted = true; //!< Tell users that this allocator is reference counted on copy
|
||||
|
||||
//! Constructor with chunkSize.
|
||||
/*! \param chunkSize The size of memory chunk. The default is kDefaultChunkSize.
|
||||
\param baseAllocator The allocator for allocating memory chunks.
|
||||
*/
|
||||
explicit
|
||||
MemoryPoolAllocator(size_t chunkSize = kDefaultChunkCapacity, BaseAllocator* baseAllocator = 0) :
|
||||
chunkHead_(0), chunk_capacity_(chunkSize), userBuffer_(0), baseAllocator_(baseAllocator), ownBaseAllocator_(0)
|
||||
chunk_capacity_(chunkSize),
|
||||
baseAllocator_(baseAllocator ? baseAllocator : RAPIDJSON_NEW(BaseAllocator)()),
|
||||
shared_(static_cast<SharedData*>(baseAllocator_ ? baseAllocator_->Malloc(SIZEOF_SHARED_DATA + SIZEOF_CHUNK_HEADER) : 0))
|
||||
{
|
||||
RAPIDJSON_ASSERT(baseAllocator_ != 0);
|
||||
RAPIDJSON_ASSERT(shared_ != 0);
|
||||
if (baseAllocator) {
|
||||
shared_->ownBaseAllocator = 0;
|
||||
}
|
||||
else {
|
||||
shared_->ownBaseAllocator = baseAllocator_;
|
||||
}
|
||||
shared_->chunkHead = GetChunkHead(shared_);
|
||||
shared_->chunkHead->capacity = 0;
|
||||
shared_->chunkHead->size = 0;
|
||||
shared_->chunkHead->next = 0;
|
||||
shared_->ownBuffer = true;
|
||||
shared_->refcount = 1;
|
||||
}
|
||||
|
||||
//! Constructor with user-supplied buffer.
|
||||
@ -123,41 +199,101 @@ public:
|
||||
\param baseAllocator The allocator for allocating memory chunks.
|
||||
*/
|
||||
MemoryPoolAllocator(void *buffer, size_t size, size_t chunkSize = kDefaultChunkCapacity, BaseAllocator* baseAllocator = 0) :
|
||||
chunkHead_(0), chunk_capacity_(chunkSize), userBuffer_(buffer), baseAllocator_(baseAllocator), ownBaseAllocator_(0)
|
||||
chunk_capacity_(chunkSize),
|
||||
baseAllocator_(baseAllocator),
|
||||
shared_(static_cast<SharedData*>(AlignBuffer(buffer, size)))
|
||||
{
|
||||
CEREAL_RAPIDJSON_ASSERT(buffer != 0);
|
||||
CEREAL_RAPIDJSON_ASSERT(size > sizeof(ChunkHeader));
|
||||
chunkHead_ = reinterpret_cast<ChunkHeader*>(buffer);
|
||||
chunkHead_->capacity = size - sizeof(ChunkHeader);
|
||||
chunkHead_->size = 0;
|
||||
chunkHead_->next = 0;
|
||||
RAPIDJSON_ASSERT(size >= SIZEOF_SHARED_DATA + SIZEOF_CHUNK_HEADER);
|
||||
shared_->chunkHead = GetChunkHead(shared_);
|
||||
shared_->chunkHead->capacity = size - SIZEOF_SHARED_DATA - SIZEOF_CHUNK_HEADER;
|
||||
shared_->chunkHead->size = 0;
|
||||
shared_->chunkHead->next = 0;
|
||||
shared_->ownBaseAllocator = 0;
|
||||
shared_->ownBuffer = false;
|
||||
shared_->refcount = 1;
|
||||
}
|
||||
|
||||
MemoryPoolAllocator(const MemoryPoolAllocator& rhs) RAPIDJSON_NOEXCEPT :
|
||||
chunk_capacity_(rhs.chunk_capacity_),
|
||||
baseAllocator_(rhs.baseAllocator_),
|
||||
shared_(rhs.shared_)
|
||||
{
|
||||
RAPIDJSON_NOEXCEPT_ASSERT(shared_->refcount > 0);
|
||||
++shared_->refcount;
|
||||
}
|
||||
MemoryPoolAllocator& operator=(const MemoryPoolAllocator& rhs) RAPIDJSON_NOEXCEPT
|
||||
{
|
||||
RAPIDJSON_NOEXCEPT_ASSERT(rhs.shared_->refcount > 0);
|
||||
++rhs.shared_->refcount;
|
||||
this->~MemoryPoolAllocator();
|
||||
baseAllocator_ = rhs.baseAllocator_;
|
||||
chunk_capacity_ = rhs.chunk_capacity_;
|
||||
shared_ = rhs.shared_;
|
||||
return *this;
|
||||
}
|
||||
|
||||
#if RAPIDJSON_HAS_CXX11_RVALUE_REFS
|
||||
MemoryPoolAllocator(MemoryPoolAllocator&& rhs) RAPIDJSON_NOEXCEPT :
|
||||
chunk_capacity_(rhs.chunk_capacity_),
|
||||
baseAllocator_(rhs.baseAllocator_),
|
||||
shared_(rhs.shared_)
|
||||
{
|
||||
RAPIDJSON_NOEXCEPT_ASSERT(rhs.shared_->refcount > 0);
|
||||
rhs.shared_ = 0;
|
||||
}
|
||||
MemoryPoolAllocator& operator=(MemoryPoolAllocator&& rhs) RAPIDJSON_NOEXCEPT
|
||||
{
|
||||
RAPIDJSON_NOEXCEPT_ASSERT(rhs.shared_->refcount > 0);
|
||||
this->~MemoryPoolAllocator();
|
||||
baseAllocator_ = rhs.baseAllocator_;
|
||||
chunk_capacity_ = rhs.chunk_capacity_;
|
||||
shared_ = rhs.shared_;
|
||||
rhs.shared_ = 0;
|
||||
return *this;
|
||||
}
|
||||
#endif
|
||||
|
||||
//! Destructor.
|
||||
/*! This deallocates all memory chunks, excluding the user-supplied buffer.
|
||||
*/
|
||||
~MemoryPoolAllocator() {
|
||||
~MemoryPoolAllocator() RAPIDJSON_NOEXCEPT {
|
||||
if (!shared_) {
|
||||
// do nothing if moved
|
||||
return;
|
||||
}
|
||||
if (shared_->refcount > 1) {
|
||||
--shared_->refcount;
|
||||
return;
|
||||
}
|
||||
Clear();
|
||||
CEREAL_RAPIDJSON_DELETE(ownBaseAllocator_);
|
||||
BaseAllocator *a = shared_->ownBaseAllocator;
|
||||
if (shared_->ownBuffer) {
|
||||
baseAllocator_->Free(shared_);
|
||||
}
|
||||
RAPIDJSON_DELETE(a);
|
||||
}
|
||||
|
||||
//! Deallocates all memory chunks, excluding the user-supplied buffer.
|
||||
void Clear() {
|
||||
while (chunkHead_ && chunkHead_ != userBuffer_) {
|
||||
ChunkHeader* next = chunkHead_->next;
|
||||
baseAllocator_->Free(chunkHead_);
|
||||
chunkHead_ = next;
|
||||
//! Deallocates all memory chunks, excluding the first/user one.
|
||||
void Clear() RAPIDJSON_NOEXCEPT {
|
||||
RAPIDJSON_NOEXCEPT_ASSERT(shared_->refcount > 0);
|
||||
for (;;) {
|
||||
ChunkHeader* c = shared_->chunkHead;
|
||||
if (!c->next) {
|
||||
break;
|
||||
}
|
||||
shared_->chunkHead = c->next;
|
||||
baseAllocator_->Free(c);
|
||||
}
|
||||
if (chunkHead_ && chunkHead_ == userBuffer_)
|
||||
chunkHead_->size = 0; // Clear user buffer
|
||||
shared_->chunkHead->size = 0;
|
||||
}
|
||||
|
||||
//! Computes the total capacity of allocated memory chunks.
|
||||
/*! \return total capacity in bytes.
|
||||
*/
|
||||
size_t Capacity() const {
|
||||
size_t Capacity() const RAPIDJSON_NOEXCEPT {
|
||||
RAPIDJSON_NOEXCEPT_ASSERT(shared_->refcount > 0);
|
||||
size_t capacity = 0;
|
||||
for (ChunkHeader* c = chunkHead_; c != 0; c = c->next)
|
||||
for (ChunkHeader* c = shared_->chunkHead; c != 0; c = c->next)
|
||||
capacity += c->capacity;
|
||||
return capacity;
|
||||
}
|
||||
@ -165,25 +301,35 @@ public:
|
||||
//! Computes the memory blocks allocated.
|
||||
/*! \return total used bytes.
|
||||
*/
|
||||
size_t Size() const {
|
||||
size_t Size() const RAPIDJSON_NOEXCEPT {
|
||||
RAPIDJSON_NOEXCEPT_ASSERT(shared_->refcount > 0);
|
||||
size_t size = 0;
|
||||
for (ChunkHeader* c = chunkHead_; c != 0; c = c->next)
|
||||
for (ChunkHeader* c = shared_->chunkHead; c != 0; c = c->next)
|
||||
size += c->size;
|
||||
return size;
|
||||
}
|
||||
|
||||
//! Whether the allocator is shared.
|
||||
/*! \return true or false.
|
||||
*/
|
||||
bool Shared() const RAPIDJSON_NOEXCEPT {
|
||||
RAPIDJSON_NOEXCEPT_ASSERT(shared_->refcount > 0);
|
||||
return shared_->refcount > 1;
|
||||
}
|
||||
|
||||
//! Allocates a memory block. (concept Allocator)
|
||||
void* Malloc(size_t size) {
|
||||
RAPIDJSON_NOEXCEPT_ASSERT(shared_->refcount > 0);
|
||||
if (!size)
|
||||
return NULL;
|
||||
|
||||
size = CEREAL_RAPIDJSON_ALIGN(size);
|
||||
if (chunkHead_ == 0 || chunkHead_->size + size > chunkHead_->capacity)
|
||||
size = RAPIDJSON_ALIGN(size);
|
||||
if (RAPIDJSON_UNLIKELY(shared_->chunkHead->size + size > shared_->chunkHead->capacity))
|
||||
if (!AddChunk(chunk_capacity_ > size ? chunk_capacity_ : size))
|
||||
return NULL;
|
||||
|
||||
void *buffer = reinterpret_cast<char *>(chunkHead_) + CEREAL_RAPIDJSON_ALIGN(sizeof(ChunkHeader)) + chunkHead_->size;
|
||||
chunkHead_->size += size;
|
||||
void *buffer = GetChunkBuffer(shared_) + shared_->chunkHead->size;
|
||||
shared_->chunkHead->size += size;
|
||||
return buffer;
|
||||
}
|
||||
|
||||
@ -192,21 +338,22 @@ public:
|
||||
if (originalPtr == 0)
|
||||
return Malloc(newSize);
|
||||
|
||||
RAPIDJSON_NOEXCEPT_ASSERT(shared_->refcount > 0);
|
||||
if (newSize == 0)
|
||||
return NULL;
|
||||
|
||||
originalSize = CEREAL_RAPIDJSON_ALIGN(originalSize);
|
||||
newSize = CEREAL_RAPIDJSON_ALIGN(newSize);
|
||||
originalSize = RAPIDJSON_ALIGN(originalSize);
|
||||
newSize = RAPIDJSON_ALIGN(newSize);
|
||||
|
||||
// Do not shrink if new size is smaller than original
|
||||
if (originalSize >= newSize)
|
||||
return originalPtr;
|
||||
|
||||
// Simply expand it if it is the last allocation and there is sufficient space
|
||||
if (originalPtr == reinterpret_cast<char *>(chunkHead_) + CEREAL_RAPIDJSON_ALIGN(sizeof(ChunkHeader)) + chunkHead_->size - originalSize) {
|
||||
if (originalPtr == GetChunkBuffer(shared_) + shared_->chunkHead->size - originalSize) {
|
||||
size_t increment = static_cast<size_t>(newSize - originalSize);
|
||||
if (chunkHead_->size + increment <= chunkHead_->capacity) {
|
||||
chunkHead_->size += increment;
|
||||
if (shared_->chunkHead->size + increment <= shared_->chunkHead->capacity) {
|
||||
shared_->chunkHead->size += increment;
|
||||
return originalPtr;
|
||||
}
|
||||
}
|
||||
@ -222,50 +369,325 @@ public:
|
||||
}
|
||||
|
||||
//! Frees a memory block (concept Allocator)
|
||||
static void Free(void *ptr) { (void)ptr; } // Do nothing
|
||||
static void Free(void *ptr) RAPIDJSON_NOEXCEPT { (void)ptr; } // Do nothing
|
||||
|
||||
//! Compare (equality) with another MemoryPoolAllocator
|
||||
bool operator==(const MemoryPoolAllocator& rhs) const RAPIDJSON_NOEXCEPT {
|
||||
RAPIDJSON_NOEXCEPT_ASSERT(shared_->refcount > 0);
|
||||
RAPIDJSON_NOEXCEPT_ASSERT(rhs.shared_->refcount > 0);
|
||||
return shared_ == rhs.shared_;
|
||||
}
|
||||
//! Compare (inequality) with another MemoryPoolAllocator
|
||||
bool operator!=(const MemoryPoolAllocator& rhs) const RAPIDJSON_NOEXCEPT {
|
||||
return !operator==(rhs);
|
||||
}
|
||||
|
||||
private:
|
||||
//! Copy constructor is not permitted.
|
||||
MemoryPoolAllocator(const MemoryPoolAllocator& rhs) /* = delete */;
|
||||
//! Copy assignment operator is not permitted.
|
||||
MemoryPoolAllocator& operator=(const MemoryPoolAllocator& rhs) /* = delete */;
|
||||
|
||||
//! Creates a new chunk.
|
||||
/*! \param capacity Capacity of the chunk in bytes.
|
||||
\return true if success.
|
||||
*/
|
||||
bool AddChunk(size_t capacity) {
|
||||
if (!baseAllocator_)
|
||||
ownBaseAllocator_ = baseAllocator_ = CEREAL_RAPIDJSON_NEW(BaseAllocator());
|
||||
if (ChunkHeader* chunk = reinterpret_cast<ChunkHeader*>(baseAllocator_->Malloc(CEREAL_RAPIDJSON_ALIGN(sizeof(ChunkHeader)) + capacity))) {
|
||||
shared_->ownBaseAllocator = baseAllocator_ = RAPIDJSON_NEW(BaseAllocator)();
|
||||
if (ChunkHeader* chunk = static_cast<ChunkHeader*>(baseAllocator_->Malloc(SIZEOF_CHUNK_HEADER + capacity))) {
|
||||
chunk->capacity = capacity;
|
||||
chunk->size = 0;
|
||||
chunk->next = chunkHead_;
|
||||
chunkHead_ = chunk;
|
||||
chunk->next = shared_->chunkHead;
|
||||
shared_->chunkHead = chunk;
|
||||
return true;
|
||||
}
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
static const int kDefaultChunkCapacity = 64 * 1024; //!< Default chunk capacity.
|
||||
static inline void* AlignBuffer(void* buf, size_t &size)
|
||||
{
|
||||
RAPIDJSON_NOEXCEPT_ASSERT(buf != 0);
|
||||
const uintptr_t mask = sizeof(void*) - 1;
|
||||
const uintptr_t ubuf = reinterpret_cast<uintptr_t>(buf);
|
||||
if (RAPIDJSON_UNLIKELY(ubuf & mask)) {
|
||||
const uintptr_t abuf = (ubuf + mask) & ~mask;
|
||||
RAPIDJSON_ASSERT(size >= abuf - ubuf);
|
||||
buf = reinterpret_cast<void*>(abuf);
|
||||
size -= abuf - ubuf;
|
||||
}
|
||||
return buf;
|
||||
}
|
||||
|
||||
//! Chunk header for perpending to each chunk.
|
||||
/*! Chunks are stored as a singly linked list.
|
||||
*/
|
||||
struct ChunkHeader {
|
||||
size_t capacity; //!< Capacity of the chunk in bytes (excluding the header itself).
|
||||
size_t size; //!< Current size of allocated memory in bytes.
|
||||
ChunkHeader *next; //!< Next chunk in the linked list.
|
||||
};
|
||||
|
||||
ChunkHeader *chunkHead_; //!< Head of the chunk linked-list. Only the head chunk serves allocation.
|
||||
size_t chunk_capacity_; //!< The minimum capacity of chunk when they are allocated.
|
||||
void *userBuffer_; //!< User supplied buffer.
|
||||
BaseAllocator* baseAllocator_; //!< base allocator for allocating memory chunks.
|
||||
BaseAllocator* ownBaseAllocator_; //!< base allocator created by this object.
|
||||
SharedData *shared_; //!< The shared data of the allocator
|
||||
};
|
||||
|
||||
CEREAL_RAPIDJSON_NAMESPACE_END
|
||||
namespace internal {
|
||||
template<typename, typename = void>
|
||||
struct IsRefCounted :
|
||||
public FalseType
|
||||
{ };
|
||||
template<typename T>
|
||||
struct IsRefCounted<T, typename internal::EnableIfCond<T::kRefCounted>::Type> :
|
||||
public TrueType
|
||||
{ };
|
||||
}
|
||||
|
||||
#endif // CEREAL_RAPIDJSON_ENCODINGS_H_
|
||||
template<typename T, typename A>
|
||||
inline T* Realloc(A& a, T* old_p, size_t old_n, size_t new_n)
|
||||
{
|
||||
RAPIDJSON_NOEXCEPT_ASSERT(old_n <= std::numeric_limits<size_t>::max() / sizeof(T) && new_n <= std::numeric_limits<size_t>::max() / sizeof(T));
|
||||
return static_cast<T*>(a.Realloc(old_p, old_n * sizeof(T), new_n * sizeof(T)));
|
||||
}
|
||||
|
||||
template<typename T, typename A>
|
||||
inline T *Malloc(A& a, size_t n = 1)
|
||||
{
|
||||
return Realloc<T, A>(a, NULL, 0, n);
|
||||
}
|
||||
|
||||
template<typename T, typename A>
|
||||
inline void Free(A& a, T *p, size_t n = 1)
|
||||
{
|
||||
static_cast<void>(Realloc<T, A>(a, p, n, 0));
|
||||
}
|
||||
|
||||
#ifdef __GNUC__
|
||||
RAPIDJSON_DIAG_PUSH
|
||||
RAPIDJSON_DIAG_OFF(effc++) // std::allocator can safely be inherited
|
||||
#endif
|
||||
|
||||
template <typename T, typename BaseAllocator = CrtAllocator>
|
||||
class StdAllocator :
|
||||
public std::allocator<T>
|
||||
{
|
||||
typedef std::allocator<T> allocator_type;
|
||||
#if RAPIDJSON_HAS_CXX11
|
||||
typedef std::allocator_traits<allocator_type> traits_type;
|
||||
#else
|
||||
typedef allocator_type traits_type;
|
||||
#endif
|
||||
|
||||
public:
|
||||
typedef BaseAllocator BaseAllocatorType;
|
||||
|
||||
StdAllocator() RAPIDJSON_NOEXCEPT :
|
||||
allocator_type(),
|
||||
baseAllocator_()
|
||||
{ }
|
||||
|
||||
StdAllocator(const StdAllocator& rhs) RAPIDJSON_NOEXCEPT :
|
||||
allocator_type(rhs),
|
||||
baseAllocator_(rhs.baseAllocator_)
|
||||
{ }
|
||||
|
||||
template<typename U>
|
||||
StdAllocator(const StdAllocator<U, BaseAllocator>& rhs) RAPIDJSON_NOEXCEPT :
|
||||
allocator_type(rhs),
|
||||
baseAllocator_(rhs.baseAllocator_)
|
||||
{ }
|
||||
|
||||
#if RAPIDJSON_HAS_CXX11_RVALUE_REFS
|
||||
StdAllocator(StdAllocator&& rhs) RAPIDJSON_NOEXCEPT :
|
||||
allocator_type(std::move(rhs)),
|
||||
baseAllocator_(std::move(rhs.baseAllocator_))
|
||||
{ }
|
||||
#endif
|
||||
#if RAPIDJSON_HAS_CXX11
|
||||
using propagate_on_container_move_assignment = std::true_type;
|
||||
using propagate_on_container_swap = std::true_type;
|
||||
#endif
|
||||
|
||||
/* implicit */
|
||||
StdAllocator(const BaseAllocator& allocator) RAPIDJSON_NOEXCEPT :
|
||||
allocator_type(),
|
||||
baseAllocator_(allocator)
|
||||
{ }
|
||||
|
||||
~StdAllocator() RAPIDJSON_NOEXCEPT
|
||||
{ }
|
||||
|
||||
template<typename U>
|
||||
struct rebind {
|
||||
typedef StdAllocator<U, BaseAllocator> other;
|
||||
};
|
||||
|
||||
typedef typename traits_type::size_type size_type;
|
||||
typedef typename traits_type::difference_type difference_type;
|
||||
|
||||
typedef typename traits_type::value_type value_type;
|
||||
typedef typename traits_type::pointer pointer;
|
||||
typedef typename traits_type::const_pointer const_pointer;
|
||||
|
||||
#if RAPIDJSON_HAS_CXX11
|
||||
|
||||
typedef typename std::add_lvalue_reference<value_type>::type &reference;
|
||||
typedef typename std::add_lvalue_reference<typename std::add_const<value_type>::type>::type &const_reference;
|
||||
|
||||
pointer address(reference r) const RAPIDJSON_NOEXCEPT
|
||||
{
|
||||
return std::addressof(r);
|
||||
}
|
||||
const_pointer address(const_reference r) const RAPIDJSON_NOEXCEPT
|
||||
{
|
||||
return std::addressof(r);
|
||||
}
|
||||
|
||||
size_type max_size() const RAPIDJSON_NOEXCEPT
|
||||
{
|
||||
return traits_type::max_size(*this);
|
||||
}
|
||||
|
||||
template <typename ...Args>
|
||||
void construct(pointer p, Args&&... args)
|
||||
{
|
||||
traits_type::construct(*this, p, std::forward<Args>(args)...);
|
||||
}
|
||||
void destroy(pointer p)
|
||||
{
|
||||
traits_type::destroy(*this, p);
|
||||
}
|
||||
|
||||
#else // !RAPIDJSON_HAS_CXX11
|
||||
|
||||
typedef typename allocator_type::reference reference;
|
||||
typedef typename allocator_type::const_reference const_reference;
|
||||
|
||||
pointer address(reference r) const RAPIDJSON_NOEXCEPT
|
||||
{
|
||||
return allocator_type::address(r);
|
||||
}
|
||||
const_pointer address(const_reference r) const RAPIDJSON_NOEXCEPT
|
||||
{
|
||||
return allocator_type::address(r);
|
||||
}
|
||||
|
||||
size_type max_size() const RAPIDJSON_NOEXCEPT
|
||||
{
|
||||
return allocator_type::max_size();
|
||||
}
|
||||
|
||||
void construct(pointer p, const_reference r)
|
||||
{
|
||||
allocator_type::construct(p, r);
|
||||
}
|
||||
void destroy(pointer p)
|
||||
{
|
||||
allocator_type::destroy(p);
|
||||
}
|
||||
|
||||
#endif // !RAPIDJSON_HAS_CXX11
|
||||
|
||||
template <typename U>
|
||||
U* allocate(size_type n = 1, const void* = 0)
|
||||
{
|
||||
return RAPIDJSON_NAMESPACE::Malloc<U>(baseAllocator_, n);
|
||||
}
|
||||
template <typename U>
|
||||
void deallocate(U* p, size_type n = 1)
|
||||
{
|
||||
RAPIDJSON_NAMESPACE::Free<U>(baseAllocator_, p, n);
|
||||
}
|
||||
|
||||
pointer allocate(size_type n = 1, const void* = 0)
|
||||
{
|
||||
return allocate<value_type>(n);
|
||||
}
|
||||
void deallocate(pointer p, size_type n = 1)
|
||||
{
|
||||
deallocate<value_type>(p, n);
|
||||
}
|
||||
|
||||
#if RAPIDJSON_HAS_CXX11
|
||||
using is_always_equal = std::is_empty<BaseAllocator>;
|
||||
#endif
|
||||
|
||||
template<typename U>
|
||||
bool operator==(const StdAllocator<U, BaseAllocator>& rhs) const RAPIDJSON_NOEXCEPT
|
||||
{
|
||||
return baseAllocator_ == rhs.baseAllocator_;
|
||||
}
|
||||
template<typename U>
|
||||
bool operator!=(const StdAllocator<U, BaseAllocator>& rhs) const RAPIDJSON_NOEXCEPT
|
||||
{
|
||||
return !operator==(rhs);
|
||||
}
|
||||
|
||||
//! rapidjson Allocator concept
|
||||
static const bool kNeedFree = BaseAllocator::kNeedFree;
|
||||
static const bool kRefCounted = internal::IsRefCounted<BaseAllocator>::Value;
|
||||
void* Malloc(size_t size)
|
||||
{
|
||||
return baseAllocator_.Malloc(size);
|
||||
}
|
||||
void* Realloc(void* originalPtr, size_t originalSize, size_t newSize)
|
||||
{
|
||||
return baseAllocator_.Realloc(originalPtr, originalSize, newSize);
|
||||
}
|
||||
static void Free(void *ptr) RAPIDJSON_NOEXCEPT
|
||||
{
|
||||
BaseAllocator::Free(ptr);
|
||||
}
|
||||
|
||||
private:
|
||||
template <typename, typename>
|
||||
friend class StdAllocator; // access to StdAllocator<!T>.*
|
||||
|
||||
BaseAllocator baseAllocator_;
|
||||
};
|
||||
|
||||
#if !RAPIDJSON_HAS_CXX17 // std::allocator<void> deprecated in C++17
|
||||
template <typename BaseAllocator>
|
||||
class StdAllocator<void, BaseAllocator> :
|
||||
public std::allocator<void>
|
||||
{
|
||||
typedef std::allocator<void> allocator_type;
|
||||
|
||||
public:
|
||||
typedef BaseAllocator BaseAllocatorType;
|
||||
|
||||
StdAllocator() RAPIDJSON_NOEXCEPT :
|
||||
allocator_type(),
|
||||
baseAllocator_()
|
||||
{ }
|
||||
|
||||
StdAllocator(const StdAllocator& rhs) RAPIDJSON_NOEXCEPT :
|
||||
allocator_type(rhs),
|
||||
baseAllocator_(rhs.baseAllocator_)
|
||||
{ }
|
||||
|
||||
template<typename U>
|
||||
StdAllocator(const StdAllocator<U, BaseAllocator>& rhs) RAPIDJSON_NOEXCEPT :
|
||||
allocator_type(rhs),
|
||||
baseAllocator_(rhs.baseAllocator_)
|
||||
{ }
|
||||
|
||||
/* implicit */
|
||||
StdAllocator(const BaseAllocator& baseAllocator) RAPIDJSON_NOEXCEPT :
|
||||
allocator_type(),
|
||||
baseAllocator_(baseAllocator)
|
||||
{ }
|
||||
|
||||
~StdAllocator() RAPIDJSON_NOEXCEPT
|
||||
{ }
|
||||
|
||||
template<typename U>
|
||||
struct rebind {
|
||||
typedef StdAllocator<U, BaseAllocator> other;
|
||||
};
|
||||
|
||||
typedef typename allocator_type::value_type value_type;
|
||||
|
||||
private:
|
||||
template <typename, typename>
|
||||
friend class StdAllocator; // access to StdAllocator<!T>.*
|
||||
|
||||
BaseAllocator baseAllocator_;
|
||||
};
|
||||
#endif
|
||||
|
||||
#ifdef __GNUC__
|
||||
RAPIDJSON_DIAG_POP
|
||||
#endif
|
||||
|
||||
RAPIDJSON_NAMESPACE_END
|
||||
|
||||
#endif // RAPIDJSON_ENCODINGS_H_
|
||||
|
78
external/cereal/external/rapidjson/cursorstreamwrapper.h
vendored
Normal file
78
external/cereal/external/rapidjson/cursorstreamwrapper.h
vendored
Normal file
@ -0,0 +1,78 @@
|
||||
// Tencent is pleased to support the open source community by making RapidJSON available.
|
||||
//
|
||||
// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip.
|
||||
//
|
||||
// Licensed under the MIT License (the "License"); you may not use this file except
|
||||
// in compliance with the License. You may obtain a copy of the License at
|
||||
//
|
||||
// http://opensource.org/licenses/MIT
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software distributed
|
||||
// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
|
||||
// CONDITIONS OF ANY KIND, either express or implied. See the License for the
|
||||
// specific language governing permissions and limitations under the License.
|
||||
|
||||
#ifndef RAPIDJSON_CURSORSTREAMWRAPPER_H_
|
||||
#define RAPIDJSON_CURSORSTREAMWRAPPER_H_
|
||||
|
||||
#include "stream.h"
|
||||
|
||||
#if defined(__GNUC__)
|
||||
RAPIDJSON_DIAG_PUSH
|
||||
RAPIDJSON_DIAG_OFF(effc++)
|
||||
#endif
|
||||
|
||||
#if defined(_MSC_VER) && _MSC_VER <= 1800
|
||||
RAPIDJSON_DIAG_PUSH
|
||||
RAPIDJSON_DIAG_OFF(4702) // unreachable code
|
||||
RAPIDJSON_DIAG_OFF(4512) // assignment operator could not be generated
|
||||
#endif
|
||||
|
||||
RAPIDJSON_NAMESPACE_BEGIN
|
||||
|
||||
|
||||
//! Cursor stream wrapper for counting line and column number if error exists.
|
||||
/*!
|
||||
\tparam InputStream Any stream that implements Stream Concept
|
||||
*/
|
||||
template <typename InputStream, typename Encoding = UTF8<> >
|
||||
class CursorStreamWrapper : public GenericStreamWrapper<InputStream, Encoding> {
|
||||
public:
|
||||
typedef typename Encoding::Ch Ch;
|
||||
|
||||
CursorStreamWrapper(InputStream& is):
|
||||
GenericStreamWrapper<InputStream, Encoding>(is), line_(1), col_(0) {}
|
||||
|
||||
// counting line and column number
|
||||
Ch Take() {
|
||||
Ch ch = this->is_.Take();
|
||||
if(ch == '\n') {
|
||||
line_ ++;
|
||||
col_ = 0;
|
||||
} else {
|
||||
col_ ++;
|
||||
}
|
||||
return ch;
|
||||
}
|
||||
|
||||
//! Get the error line number, if error exists.
|
||||
size_t GetLine() const { return line_; }
|
||||
//! Get the error column number, if error exists.
|
||||
size_t GetColumn() const { return col_; }
|
||||
|
||||
private:
|
||||
size_t line_; //!< Current Line
|
||||
size_t col_; //!< Current Column
|
||||
};
|
||||
|
||||
#if defined(_MSC_VER) && _MSC_VER <= 1800
|
||||
RAPIDJSON_DIAG_POP
|
||||
#endif
|
||||
|
||||
#if defined(__GNUC__)
|
||||
RAPIDJSON_DIAG_POP
|
||||
#endif
|
||||
|
||||
RAPIDJSON_NAMESPACE_END
|
||||
|
||||
#endif // RAPIDJSON_CURSORSTREAMWRAPPER_H_
|
1154
external/cereal/external/rapidjson/document.h
vendored
1154
external/cereal/external/rapidjson/document.h
vendored
File diff suppressed because it is too large
Load Diff
@ -1,6 +1,6 @@
|
||||
// Tencent is pleased to support the open source community by making RapidJSON available.
|
||||
//
|
||||
// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
|
||||
// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip.
|
||||
//
|
||||
// Licensed under the MIT License (the "License"); you may not use this file except
|
||||
// in compliance with the License. You may obtain a copy of the License at
|
||||
@ -12,23 +12,23 @@
|
||||
// CONDITIONS OF ANY KIND, either express or implied. See the License for the
|
||||
// specific language governing permissions and limitations under the License.
|
||||
|
||||
#ifndef CEREAL_RAPIDJSON_ENCODEDSTREAM_H_
|
||||
#define CEREAL_RAPIDJSON_ENCODEDSTREAM_H_
|
||||
#ifndef RAPIDJSON_ENCODEDSTREAM_H_
|
||||
#define RAPIDJSON_ENCODEDSTREAM_H_
|
||||
|
||||
#include "stream.h"
|
||||
#include "memorystream.h"
|
||||
|
||||
#ifdef __GNUC__
|
||||
CEREAL_RAPIDJSON_DIAG_PUSH
|
||||
CEREAL_RAPIDJSON_DIAG_OFF(effc++)
|
||||
RAPIDJSON_DIAG_PUSH
|
||||
RAPIDJSON_DIAG_OFF(effc++)
|
||||
#endif
|
||||
|
||||
#ifdef __clang__
|
||||
CEREAL_RAPIDJSON_DIAG_PUSH
|
||||
CEREAL_RAPIDJSON_DIAG_OFF(padded)
|
||||
RAPIDJSON_DIAG_PUSH
|
||||
RAPIDJSON_DIAG_OFF(padded)
|
||||
#endif
|
||||
|
||||
CEREAL_RAPIDJSON_NAMESPACE_BEGIN
|
||||
RAPIDJSON_NAMESPACE_BEGIN
|
||||
|
||||
//! Input byte stream wrapper with a statically bound encoding.
|
||||
/*!
|
||||
@ -37,7 +37,7 @@ CEREAL_RAPIDJSON_NAMESPACE_BEGIN
|
||||
*/
|
||||
template <typename Encoding, typename InputByteStream>
|
||||
class EncodedInputStream {
|
||||
CEREAL_RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1);
|
||||
RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1);
|
||||
public:
|
||||
typedef typename Encoding::Ch Ch;
|
||||
|
||||
@ -50,10 +50,10 @@ public:
|
||||
size_t Tell() const { return is_.Tell(); }
|
||||
|
||||
// Not implemented
|
||||
void Put(Ch) { CEREAL_RAPIDJSON_ASSERT(false); }
|
||||
void Flush() { CEREAL_RAPIDJSON_ASSERT(false); }
|
||||
Ch* PutBegin() { CEREAL_RAPIDJSON_ASSERT(false); return 0; }
|
||||
size_t PutEnd(Ch*) { CEREAL_RAPIDJSON_ASSERT(false); return 0; }
|
||||
void Put(Ch) { RAPIDJSON_ASSERT(false); }
|
||||
void Flush() { RAPIDJSON_ASSERT(false); }
|
||||
Ch* PutBegin() { RAPIDJSON_ASSERT(false); return 0; }
|
||||
size_t PutEnd(Ch*) { RAPIDJSON_ASSERT(false); return 0; }
|
||||
|
||||
private:
|
||||
EncodedInputStream(const EncodedInputStream&);
|
||||
@ -98,7 +98,7 @@ private:
|
||||
*/
|
||||
template <typename Encoding, typename OutputByteStream>
|
||||
class EncodedOutputStream {
|
||||
CEREAL_RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1);
|
||||
RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1);
|
||||
public:
|
||||
typedef typename Encoding::Ch Ch;
|
||||
|
||||
@ -111,11 +111,11 @@ public:
|
||||
void Flush() { os_.Flush(); }
|
||||
|
||||
// Not implemented
|
||||
Ch Peek() const { CEREAL_RAPIDJSON_ASSERT(false); return 0;}
|
||||
Ch Take() { CEREAL_RAPIDJSON_ASSERT(false); return 0;}
|
||||
size_t Tell() const { CEREAL_RAPIDJSON_ASSERT(false); return 0; }
|
||||
Ch* PutBegin() { CEREAL_RAPIDJSON_ASSERT(false); return 0; }
|
||||
size_t PutEnd(Ch*) { CEREAL_RAPIDJSON_ASSERT(false); return 0; }
|
||||
Ch Peek() const { RAPIDJSON_ASSERT(false); return 0;}
|
||||
Ch Take() { RAPIDJSON_ASSERT(false); return 0;}
|
||||
size_t Tell() const { RAPIDJSON_ASSERT(false); return 0; }
|
||||
Ch* PutBegin() { RAPIDJSON_ASSERT(false); return 0; }
|
||||
size_t PutEnd(Ch*) { RAPIDJSON_ASSERT(false); return 0; }
|
||||
|
||||
private:
|
||||
EncodedOutputStream(const EncodedOutputStream&);
|
||||
@ -124,7 +124,7 @@ private:
|
||||
OutputByteStream& os_;
|
||||
};
|
||||
|
||||
#define CEREAL_RAPIDJSON_ENCODINGS_FUNC(x) UTF8<Ch>::x, UTF16LE<Ch>::x, UTF16BE<Ch>::x, UTF32LE<Ch>::x, UTF32BE<Ch>::x
|
||||
#define RAPIDJSON_ENCODINGS_FUNC(x) UTF8<Ch>::x, UTF16LE<Ch>::x, UTF16BE<Ch>::x, UTF32LE<Ch>::x, UTF32BE<Ch>::x
|
||||
|
||||
//! Input stream wrapper with dynamically bound encoding and automatic encoding detection.
|
||||
/*!
|
||||
@ -133,7 +133,7 @@ private:
|
||||
*/
|
||||
template <typename CharType, typename InputByteStream>
|
||||
class AutoUTFInputStream {
|
||||
CEREAL_RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1);
|
||||
RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1);
|
||||
public:
|
||||
typedef CharType Ch;
|
||||
|
||||
@ -143,9 +143,9 @@ public:
|
||||
\param type UTF encoding type if it is not detected from the stream.
|
||||
*/
|
||||
AutoUTFInputStream(InputByteStream& is, UTFType type = kUTF8) : is_(&is), type_(type), hasBOM_(false) {
|
||||
CEREAL_RAPIDJSON_ASSERT(type >= kUTF8 && type <= kUTF32BE);
|
||||
RAPIDJSON_ASSERT(type >= kUTF8 && type <= kUTF32BE);
|
||||
DetectType();
|
||||
static const TakeFunc f[] = { CEREAL_RAPIDJSON_ENCODINGS_FUNC(Take) };
|
||||
static const TakeFunc f[] = { RAPIDJSON_ENCODINGS_FUNC(Take) };
|
||||
takeFunc_ = f[type_];
|
||||
current_ = takeFunc_(*is_);
|
||||
}
|
||||
@ -158,10 +158,10 @@ public:
|
||||
size_t Tell() const { return is_->Tell(); }
|
||||
|
||||
// Not implemented
|
||||
void Put(Ch) { CEREAL_RAPIDJSON_ASSERT(false); }
|
||||
void Flush() { CEREAL_RAPIDJSON_ASSERT(false); }
|
||||
Ch* PutBegin() { CEREAL_RAPIDJSON_ASSERT(false); return 0; }
|
||||
size_t PutEnd(Ch*) { CEREAL_RAPIDJSON_ASSERT(false); return 0; }
|
||||
void Put(Ch) { RAPIDJSON_ASSERT(false); }
|
||||
void Flush() { RAPIDJSON_ASSERT(false); }
|
||||
Ch* PutBegin() { RAPIDJSON_ASSERT(false); return 0; }
|
||||
size_t PutEnd(Ch*) { RAPIDJSON_ASSERT(false); return 0; }
|
||||
|
||||
private:
|
||||
AutoUTFInputStream(const AutoUTFInputStream&);
|
||||
@ -200,7 +200,7 @@ private:
|
||||
// xx xx xx xx UTF-8
|
||||
|
||||
if (!hasBOM_) {
|
||||
unsigned pattern = (c[0] ? 1 : 0) | (c[1] ? 2 : 0) | (c[2] ? 4 : 0) | (c[3] ? 8 : 0);
|
||||
int pattern = (c[0] ? 1 : 0) | (c[1] ? 2 : 0) | (c[2] ? 4 : 0) | (c[3] ? 8 : 0);
|
||||
switch (pattern) {
|
||||
case 0x08: type_ = kUTF32BE; break;
|
||||
case 0x0A: type_ = kUTF16BE; break;
|
||||
@ -212,8 +212,8 @@ private:
|
||||
}
|
||||
|
||||
// Runtime check whether the size of character type is sufficient. It only perform checks with assertion.
|
||||
if (type_ == kUTF16LE || type_ == kUTF16BE) CEREAL_RAPIDJSON_ASSERT(sizeof(Ch) >= 2);
|
||||
if (type_ == kUTF32LE || type_ == kUTF32BE) CEREAL_RAPIDJSON_ASSERT(sizeof(Ch) >= 4);
|
||||
if (type_ == kUTF16LE || type_ == kUTF16BE) RAPIDJSON_ASSERT(sizeof(Ch) >= 2);
|
||||
if (type_ == kUTF32LE || type_ == kUTF32BE) RAPIDJSON_ASSERT(sizeof(Ch) >= 4);
|
||||
}
|
||||
|
||||
typedef Ch (*TakeFunc)(InputByteStream& is);
|
||||
@ -231,7 +231,7 @@ private:
|
||||
*/
|
||||
template <typename CharType, typename OutputByteStream>
|
||||
class AutoUTFOutputStream {
|
||||
CEREAL_RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1);
|
||||
RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1);
|
||||
public:
|
||||
typedef CharType Ch;
|
||||
|
||||
@ -242,13 +242,13 @@ public:
|
||||
\param putBOM Whether to write BOM at the beginning of the stream.
|
||||
*/
|
||||
AutoUTFOutputStream(OutputByteStream& os, UTFType type, bool putBOM) : os_(&os), type_(type) {
|
||||
CEREAL_RAPIDJSON_ASSERT(type >= kUTF8 && type <= kUTF32BE);
|
||||
RAPIDJSON_ASSERT(type >= kUTF8 && type <= kUTF32BE);
|
||||
|
||||
// Runtime check whether the size of character type is sufficient. It only perform checks with assertion.
|
||||
if (type_ == kUTF16LE || type_ == kUTF16BE) CEREAL_RAPIDJSON_ASSERT(sizeof(Ch) >= 2);
|
||||
if (type_ == kUTF32LE || type_ == kUTF32BE) CEREAL_RAPIDJSON_ASSERT(sizeof(Ch) >= 4);
|
||||
if (type_ == kUTF16LE || type_ == kUTF16BE) RAPIDJSON_ASSERT(sizeof(Ch) >= 2);
|
||||
if (type_ == kUTF32LE || type_ == kUTF32BE) RAPIDJSON_ASSERT(sizeof(Ch) >= 4);
|
||||
|
||||
static const PutFunc f[] = { CEREAL_RAPIDJSON_ENCODINGS_FUNC(Put) };
|
||||
static const PutFunc f[] = { RAPIDJSON_ENCODINGS_FUNC(Put) };
|
||||
putFunc_ = f[type_];
|
||||
|
||||
if (putBOM)
|
||||
@ -261,11 +261,11 @@ public:
|
||||
void Flush() { os_->Flush(); }
|
||||
|
||||
// Not implemented
|
||||
Ch Peek() const { CEREAL_RAPIDJSON_ASSERT(false); return 0;}
|
||||
Ch Take() { CEREAL_RAPIDJSON_ASSERT(false); return 0;}
|
||||
size_t Tell() const { CEREAL_RAPIDJSON_ASSERT(false); return 0; }
|
||||
Ch* PutBegin() { CEREAL_RAPIDJSON_ASSERT(false); return 0; }
|
||||
size_t PutEnd(Ch*) { CEREAL_RAPIDJSON_ASSERT(false); return 0; }
|
||||
Ch Peek() const { RAPIDJSON_ASSERT(false); return 0;}
|
||||
Ch Take() { RAPIDJSON_ASSERT(false); return 0;}
|
||||
size_t Tell() const { RAPIDJSON_ASSERT(false); return 0; }
|
||||
Ch* PutBegin() { RAPIDJSON_ASSERT(false); return 0; }
|
||||
size_t PutEnd(Ch*) { RAPIDJSON_ASSERT(false); return 0; }
|
||||
|
||||
private:
|
||||
AutoUTFOutputStream(const AutoUTFOutputStream&);
|
||||
@ -273,7 +273,7 @@ private:
|
||||
|
||||
void PutBOM() {
|
||||
typedef void (*PutBOMFunc)(OutputByteStream&);
|
||||
static const PutBOMFunc f[] = { CEREAL_RAPIDJSON_ENCODINGS_FUNC(PutBOM) };
|
||||
static const PutBOMFunc f[] = { RAPIDJSON_ENCODINGS_FUNC(PutBOM) };
|
||||
f[type_](*os_);
|
||||
}
|
||||
|
||||
@ -284,16 +284,16 @@ private:
|
||||
PutFunc putFunc_;
|
||||
};
|
||||
|
||||
#undef CEREAL_RAPIDJSON_ENCODINGS_FUNC
|
||||
#undef RAPIDJSON_ENCODINGS_FUNC
|
||||
|
||||
CEREAL_RAPIDJSON_NAMESPACE_END
|
||||
RAPIDJSON_NAMESPACE_END
|
||||
|
||||
#ifdef __clang__
|
||||
CEREAL_RAPIDJSON_DIAG_POP
|
||||
RAPIDJSON_DIAG_POP
|
||||
#endif
|
||||
|
||||
#ifdef __GNUC__
|
||||
CEREAL_RAPIDJSON_DIAG_POP
|
||||
RAPIDJSON_DIAG_POP
|
||||
#endif
|
||||
|
||||
#endif // CEREAL_RAPIDJSON_FILESTREAM_H_
|
||||
#endif // RAPIDJSON_FILESTREAM_H_
|
||||
|
214
external/cereal/external/rapidjson/encodings.h
vendored
214
external/cereal/external/rapidjson/encodings.h
vendored
@ -1,6 +1,6 @@
|
||||
// Tencent is pleased to support the open source community by making RapidJSON available.
|
||||
//
|
||||
// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
|
||||
// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip.
|
||||
//
|
||||
// Licensed under the MIT License (the "License"); you may not use this file except
|
||||
// in compliance with the License. You may obtain a copy of the License at
|
||||
@ -12,22 +12,22 @@
|
||||
// CONDITIONS OF ANY KIND, either express or implied. See the License for the
|
||||
// specific language governing permissions and limitations under the License.
|
||||
|
||||
#ifndef CEREAL_RAPIDJSON_ENCODINGS_H_
|
||||
#define CEREAL_RAPIDJSON_ENCODINGS_H_
|
||||
#ifndef RAPIDJSON_ENCODINGS_H_
|
||||
#define RAPIDJSON_ENCODINGS_H_
|
||||
|
||||
#include "rapidjson.h"
|
||||
|
||||
#ifdef _MSC_VER
|
||||
CEREAL_RAPIDJSON_DIAG_PUSH
|
||||
CEREAL_RAPIDJSON_DIAG_OFF(4244) // conversion from 'type1' to 'type2', possible loss of data
|
||||
CEREAL_RAPIDJSON_DIAG_OFF(4702) // unreachable code
|
||||
#if defined(_MSC_VER) && !defined(__clang__)
|
||||
RAPIDJSON_DIAG_PUSH
|
||||
RAPIDJSON_DIAG_OFF(4244) // conversion from 'type1' to 'type2', possible loss of data
|
||||
RAPIDJSON_DIAG_OFF(4702) // unreachable code
|
||||
#elif defined(__GNUC__)
|
||||
CEREAL_RAPIDJSON_DIAG_PUSH
|
||||
CEREAL_RAPIDJSON_DIAG_OFF(effc++)
|
||||
CEREAL_RAPIDJSON_DIAG_OFF(overflow)
|
||||
RAPIDJSON_DIAG_PUSH
|
||||
RAPIDJSON_DIAG_OFF(effc++)
|
||||
RAPIDJSON_DIAG_OFF(overflow)
|
||||
#endif
|
||||
|
||||
CEREAL_RAPIDJSON_NAMESPACE_BEGIN
|
||||
RAPIDJSON_NAMESPACE_BEGIN
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Encoding
|
||||
@ -112,7 +112,7 @@ struct UTF8 {
|
||||
os.Put(static_cast<Ch>(0x80 | (codepoint & 0x3F)));
|
||||
}
|
||||
else {
|
||||
CEREAL_RAPIDJSON_ASSERT(codepoint <= 0x10FFFF);
|
||||
RAPIDJSON_ASSERT(codepoint <= 0x10FFFF);
|
||||
os.Put(static_cast<Ch>(0xF0 | ((codepoint >> 18) & 0xFF)));
|
||||
os.Put(static_cast<Ch>(0x80 | ((codepoint >> 12) & 0x3F)));
|
||||
os.Put(static_cast<Ch>(0x80 | ((codepoint >> 6) & 0x3F)));
|
||||
@ -134,7 +134,7 @@ struct UTF8 {
|
||||
PutUnsafe(os, static_cast<Ch>(0x80 | (codepoint & 0x3F)));
|
||||
}
|
||||
else {
|
||||
CEREAL_RAPIDJSON_ASSERT(codepoint <= 0x10FFFF);
|
||||
RAPIDJSON_ASSERT(codepoint <= 0x10FFFF);
|
||||
PutUnsafe(os, static_cast<Ch>(0xF0 | ((codepoint >> 18) & 0xFF)));
|
||||
PutUnsafe(os, static_cast<Ch>(0x80 | ((codepoint >> 12) & 0x3F)));
|
||||
PutUnsafe(os, static_cast<Ch>(0x80 | ((codepoint >> 6) & 0x3F)));
|
||||
@ -144,9 +144,9 @@ struct UTF8 {
|
||||
|
||||
template <typename InputStream>
|
||||
static bool Decode(InputStream& is, unsigned* codepoint) {
|
||||
#define COPY() c = is.Take(); *codepoint = (*codepoint << 6) | (static_cast<unsigned char>(c) & 0x3Fu)
|
||||
#define TRANS(mask) result &= ((GetRange(static_cast<unsigned char>(c)) & mask) != 0)
|
||||
#define TAIL() COPY(); TRANS(0x70)
|
||||
#define RAPIDJSON_COPY() c = is.Take(); *codepoint = (*codepoint << 6) | (static_cast<unsigned char>(c) & 0x3Fu)
|
||||
#define RAPIDJSON_TRANS(mask) result &= ((GetRange(static_cast<unsigned char>(c)) & mask) != 0)
|
||||
#define RAPIDJSON_TAIL() RAPIDJSON_COPY(); RAPIDJSON_TRANS(0x70)
|
||||
typename InputStream::Ch c = is.Take();
|
||||
if (!(c & 0x80)) {
|
||||
*codepoint = static_cast<unsigned char>(c);
|
||||
@ -157,48 +157,48 @@ struct UTF8 {
|
||||
if (type >= 32) {
|
||||
*codepoint = 0;
|
||||
} else {
|
||||
*codepoint = (0xFF >> type) & static_cast<unsigned char>(c);
|
||||
*codepoint = (0xFFu >> type) & static_cast<unsigned char>(c);
|
||||
}
|
||||
bool result = true;
|
||||
switch (type) {
|
||||
case 2: TAIL(); return result;
|
||||
case 3: TAIL(); TAIL(); return result;
|
||||
case 4: COPY(); TRANS(0x50); TAIL(); return result;
|
||||
case 5: COPY(); TRANS(0x10); TAIL(); TAIL(); return result;
|
||||
case 6: TAIL(); TAIL(); TAIL(); return result;
|
||||
case 10: COPY(); TRANS(0x20); TAIL(); return result;
|
||||
case 11: COPY(); TRANS(0x60); TAIL(); TAIL(); return result;
|
||||
case 2: RAPIDJSON_TAIL(); return result;
|
||||
case 3: RAPIDJSON_TAIL(); RAPIDJSON_TAIL(); return result;
|
||||
case 4: RAPIDJSON_COPY(); RAPIDJSON_TRANS(0x50); RAPIDJSON_TAIL(); return result;
|
||||
case 5: RAPIDJSON_COPY(); RAPIDJSON_TRANS(0x10); RAPIDJSON_TAIL(); RAPIDJSON_TAIL(); return result;
|
||||
case 6: RAPIDJSON_TAIL(); RAPIDJSON_TAIL(); RAPIDJSON_TAIL(); return result;
|
||||
case 10: RAPIDJSON_COPY(); RAPIDJSON_TRANS(0x20); RAPIDJSON_TAIL(); return result;
|
||||
case 11: RAPIDJSON_COPY(); RAPIDJSON_TRANS(0x60); RAPIDJSON_TAIL(); RAPIDJSON_TAIL(); return result;
|
||||
default: return false;
|
||||
}
|
||||
#undef COPY
|
||||
#undef TRANS
|
||||
#undef TAIL
|
||||
#undef RAPIDJSON_COPY
|
||||
#undef RAPIDJSON_TRANS
|
||||
#undef RAPIDJSON_TAIL
|
||||
}
|
||||
|
||||
template <typename InputStream, typename OutputStream>
|
||||
static bool Validate(InputStream& is, OutputStream& os) {
|
||||
#define COPY() os.Put(c = is.Take())
|
||||
#define TRANS(mask) result &= ((GetRange(static_cast<unsigned char>(c)) & mask) != 0)
|
||||
#define TAIL() COPY(); TRANS(0x70)
|
||||
#define RAPIDJSON_COPY() os.Put(c = is.Take())
|
||||
#define RAPIDJSON_TRANS(mask) result &= ((GetRange(static_cast<unsigned char>(c)) & mask) != 0)
|
||||
#define RAPIDJSON_TAIL() RAPIDJSON_COPY(); RAPIDJSON_TRANS(0x70)
|
||||
Ch c;
|
||||
COPY();
|
||||
RAPIDJSON_COPY();
|
||||
if (!(c & 0x80))
|
||||
return true;
|
||||
|
||||
bool result = true;
|
||||
switch (GetRange(static_cast<unsigned char>(c))) {
|
||||
case 2: TAIL(); return result;
|
||||
case 3: TAIL(); TAIL(); return result;
|
||||
case 4: COPY(); TRANS(0x50); TAIL(); return result;
|
||||
case 5: COPY(); TRANS(0x10); TAIL(); TAIL(); return result;
|
||||
case 6: TAIL(); TAIL(); TAIL(); return result;
|
||||
case 10: COPY(); TRANS(0x20); TAIL(); return result;
|
||||
case 11: COPY(); TRANS(0x60); TAIL(); TAIL(); return result;
|
||||
case 2: RAPIDJSON_TAIL(); return result;
|
||||
case 3: RAPIDJSON_TAIL(); RAPIDJSON_TAIL(); return result;
|
||||
case 4: RAPIDJSON_COPY(); RAPIDJSON_TRANS(0x50); RAPIDJSON_TAIL(); return result;
|
||||
case 5: RAPIDJSON_COPY(); RAPIDJSON_TRANS(0x10); RAPIDJSON_TAIL(); RAPIDJSON_TAIL(); return result;
|
||||
case 6: RAPIDJSON_TAIL(); RAPIDJSON_TAIL(); RAPIDJSON_TAIL(); return result;
|
||||
case 10: RAPIDJSON_COPY(); RAPIDJSON_TRANS(0x20); RAPIDJSON_TAIL(); return result;
|
||||
case 11: RAPIDJSON_COPY(); RAPIDJSON_TRANS(0x60); RAPIDJSON_TAIL(); RAPIDJSON_TAIL(); return result;
|
||||
default: return false;
|
||||
}
|
||||
#undef COPY
|
||||
#undef TRANS
|
||||
#undef TAIL
|
||||
#undef RAPIDJSON_COPY
|
||||
#undef RAPIDJSON_TRANS
|
||||
#undef RAPIDJSON_TAIL
|
||||
}
|
||||
|
||||
static unsigned char GetRange(unsigned char c) {
|
||||
@ -221,7 +221,7 @@ struct UTF8 {
|
||||
|
||||
template <typename InputByteStream>
|
||||
static CharType TakeBOM(InputByteStream& is) {
|
||||
CEREAL_RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1);
|
||||
RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1);
|
||||
typename InputByteStream::Ch c = Take(is);
|
||||
if (static_cast<unsigned char>(c) != 0xEFu) return c;
|
||||
c = is.Take();
|
||||
@ -234,13 +234,13 @@ struct UTF8 {
|
||||
|
||||
template <typename InputByteStream>
|
||||
static Ch Take(InputByteStream& is) {
|
||||
CEREAL_RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1);
|
||||
RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1);
|
||||
return static_cast<Ch>(is.Take());
|
||||
}
|
||||
|
||||
template <typename OutputByteStream>
|
||||
static void PutBOM(OutputByteStream& os) {
|
||||
CEREAL_RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1);
|
||||
RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1);
|
||||
os.Put(static_cast<typename OutputByteStream::Ch>(0xEFu));
|
||||
os.Put(static_cast<typename OutputByteStream::Ch>(0xBBu));
|
||||
os.Put(static_cast<typename OutputByteStream::Ch>(0xBFu));
|
||||
@ -248,7 +248,7 @@ struct UTF8 {
|
||||
|
||||
template <typename OutputByteStream>
|
||||
static void Put(OutputByteStream& os, Ch c) {
|
||||
CEREAL_RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1);
|
||||
RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1);
|
||||
os.Put(static_cast<typename OutputByteStream::Ch>(c));
|
||||
}
|
||||
};
|
||||
@ -268,44 +268,44 @@ struct UTF8 {
|
||||
template<typename CharType = wchar_t>
|
||||
struct UTF16 {
|
||||
typedef CharType Ch;
|
||||
CEREAL_RAPIDJSON_STATIC_ASSERT(sizeof(Ch) >= 2);
|
||||
RAPIDJSON_STATIC_ASSERT(sizeof(Ch) >= 2);
|
||||
|
||||
enum { supportUnicode = 1 };
|
||||
|
||||
template<typename OutputStream>
|
||||
static void Encode(OutputStream& os, unsigned codepoint) {
|
||||
CEREAL_RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputStream::Ch) >= 2);
|
||||
RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputStream::Ch) >= 2);
|
||||
if (codepoint <= 0xFFFF) {
|
||||
CEREAL_RAPIDJSON_ASSERT(codepoint < 0xD800 || codepoint > 0xDFFF); // Code point itself cannot be surrogate pair
|
||||
RAPIDJSON_ASSERT(codepoint < 0xD800 || codepoint > 0xDFFF); // Code point itself cannot be surrogate pair
|
||||
os.Put(static_cast<typename OutputStream::Ch>(codepoint));
|
||||
}
|
||||
else {
|
||||
CEREAL_RAPIDJSON_ASSERT(codepoint <= 0x10FFFF);
|
||||
RAPIDJSON_ASSERT(codepoint <= 0x10FFFF);
|
||||
unsigned v = codepoint - 0x10000;
|
||||
os.Put(static_cast<typename OutputStream::Ch>((v >> 10) | 0xD800));
|
||||
os.Put((v & 0x3FF) | 0xDC00);
|
||||
os.Put(static_cast<typename OutputStream::Ch>((v & 0x3FF) | 0xDC00));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
template<typename OutputStream>
|
||||
static void EncodeUnsafe(OutputStream& os, unsigned codepoint) {
|
||||
CEREAL_RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputStream::Ch) >= 2);
|
||||
RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputStream::Ch) >= 2);
|
||||
if (codepoint <= 0xFFFF) {
|
||||
CEREAL_RAPIDJSON_ASSERT(codepoint < 0xD800 || codepoint > 0xDFFF); // Code point itself cannot be surrogate pair
|
||||
RAPIDJSON_ASSERT(codepoint < 0xD800 || codepoint > 0xDFFF); // Code point itself cannot be surrogate pair
|
||||
PutUnsafe(os, static_cast<typename OutputStream::Ch>(codepoint));
|
||||
}
|
||||
else {
|
||||
CEREAL_RAPIDJSON_ASSERT(codepoint <= 0x10FFFF);
|
||||
RAPIDJSON_ASSERT(codepoint <= 0x10FFFF);
|
||||
unsigned v = codepoint - 0x10000;
|
||||
PutUnsafe(os, static_cast<typename OutputStream::Ch>((v >> 10) | 0xD800));
|
||||
PutUnsafe(os, (v & 0x3FF) | 0xDC00);
|
||||
PutUnsafe(os, static_cast<typename OutputStream::Ch>((v & 0x3FF) | 0xDC00));
|
||||
}
|
||||
}
|
||||
|
||||
template <typename InputStream>
|
||||
static bool Decode(InputStream& is, unsigned* codepoint) {
|
||||
CEREAL_RAPIDJSON_STATIC_ASSERT(sizeof(typename InputStream::Ch) >= 2);
|
||||
RAPIDJSON_STATIC_ASSERT(sizeof(typename InputStream::Ch) >= 2);
|
||||
typename InputStream::Ch c = is.Take();
|
||||
if (c < 0xD800 || c > 0xDFFF) {
|
||||
*codepoint = static_cast<unsigned>(c);
|
||||
@ -323,8 +323,8 @@ struct UTF16 {
|
||||
|
||||
template <typename InputStream, typename OutputStream>
|
||||
static bool Validate(InputStream& is, OutputStream& os) {
|
||||
CEREAL_RAPIDJSON_STATIC_ASSERT(sizeof(typename InputStream::Ch) >= 2);
|
||||
CEREAL_RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputStream::Ch) >= 2);
|
||||
RAPIDJSON_STATIC_ASSERT(sizeof(typename InputStream::Ch) >= 2);
|
||||
RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputStream::Ch) >= 2);
|
||||
typename InputStream::Ch c;
|
||||
os.Put(static_cast<typename OutputStream::Ch>(c = is.Take()));
|
||||
if (c < 0xD800 || c > 0xDFFF)
|
||||
@ -342,14 +342,14 @@ template<typename CharType = wchar_t>
|
||||
struct UTF16LE : UTF16<CharType> {
|
||||
template <typename InputByteStream>
|
||||
static CharType TakeBOM(InputByteStream& is) {
|
||||
CEREAL_RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1);
|
||||
RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1);
|
||||
CharType c = Take(is);
|
||||
return static_cast<uint16_t>(c) == 0xFEFFu ? Take(is) : c;
|
||||
}
|
||||
|
||||
template <typename InputByteStream>
|
||||
static CharType Take(InputByteStream& is) {
|
||||
CEREAL_RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1);
|
||||
RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1);
|
||||
unsigned c = static_cast<uint8_t>(is.Take());
|
||||
c |= static_cast<unsigned>(static_cast<uint8_t>(is.Take())) << 8;
|
||||
return static_cast<CharType>(c);
|
||||
@ -357,14 +357,14 @@ struct UTF16LE : UTF16<CharType> {
|
||||
|
||||
template <typename OutputByteStream>
|
||||
static void PutBOM(OutputByteStream& os) {
|
||||
CEREAL_RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1);
|
||||
RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1);
|
||||
os.Put(static_cast<typename OutputByteStream::Ch>(0xFFu));
|
||||
os.Put(static_cast<typename OutputByteStream::Ch>(0xFEu));
|
||||
}
|
||||
|
||||
template <typename OutputByteStream>
|
||||
static void Put(OutputByteStream& os, CharType c) {
|
||||
CEREAL_RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1);
|
||||
RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1);
|
||||
os.Put(static_cast<typename OutputByteStream::Ch>(static_cast<unsigned>(c) & 0xFFu));
|
||||
os.Put(static_cast<typename OutputByteStream::Ch>((static_cast<unsigned>(c) >> 8) & 0xFFu));
|
||||
}
|
||||
@ -375,29 +375,29 @@ template<typename CharType = wchar_t>
|
||||
struct UTF16BE : UTF16<CharType> {
|
||||
template <typename InputByteStream>
|
||||
static CharType TakeBOM(InputByteStream& is) {
|
||||
CEREAL_RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1);
|
||||
RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1);
|
||||
CharType c = Take(is);
|
||||
return static_cast<uint16_t>(c) == 0xFEFFu ? Take(is) : c;
|
||||
}
|
||||
|
||||
template <typename InputByteStream>
|
||||
static CharType Take(InputByteStream& is) {
|
||||
CEREAL_RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1);
|
||||
RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1);
|
||||
unsigned c = static_cast<unsigned>(static_cast<uint8_t>(is.Take())) << 8;
|
||||
c |= static_cast<uint8_t>(is.Take());
|
||||
c |= static_cast<unsigned>(static_cast<uint8_t>(is.Take()));
|
||||
return static_cast<CharType>(c);
|
||||
}
|
||||
|
||||
template <typename OutputByteStream>
|
||||
static void PutBOM(OutputByteStream& os) {
|
||||
CEREAL_RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1);
|
||||
RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1);
|
||||
os.Put(static_cast<typename OutputByteStream::Ch>(0xFEu));
|
||||
os.Put(static_cast<typename OutputByteStream::Ch>(0xFFu));
|
||||
}
|
||||
|
||||
template <typename OutputByteStream>
|
||||
static void Put(OutputByteStream& os, CharType c) {
|
||||
CEREAL_RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1);
|
||||
RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1);
|
||||
os.Put(static_cast<typename OutputByteStream::Ch>((static_cast<unsigned>(c) >> 8) & 0xFFu));
|
||||
os.Put(static_cast<typename OutputByteStream::Ch>(static_cast<unsigned>(c) & 0xFFu));
|
||||
}
|
||||
@ -417,27 +417,27 @@ struct UTF16BE : UTF16<CharType> {
|
||||
template<typename CharType = unsigned>
|
||||
struct UTF32 {
|
||||
typedef CharType Ch;
|
||||
CEREAL_RAPIDJSON_STATIC_ASSERT(sizeof(Ch) >= 4);
|
||||
RAPIDJSON_STATIC_ASSERT(sizeof(Ch) >= 4);
|
||||
|
||||
enum { supportUnicode = 1 };
|
||||
|
||||
template<typename OutputStream>
|
||||
static void Encode(OutputStream& os, unsigned codepoint) {
|
||||
CEREAL_RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputStream::Ch) >= 4);
|
||||
CEREAL_RAPIDJSON_ASSERT(codepoint <= 0x10FFFF);
|
||||
RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputStream::Ch) >= 4);
|
||||
RAPIDJSON_ASSERT(codepoint <= 0x10FFFF);
|
||||
os.Put(codepoint);
|
||||
}
|
||||
|
||||
template<typename OutputStream>
|
||||
static void EncodeUnsafe(OutputStream& os, unsigned codepoint) {
|
||||
CEREAL_RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputStream::Ch) >= 4);
|
||||
CEREAL_RAPIDJSON_ASSERT(codepoint <= 0x10FFFF);
|
||||
RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputStream::Ch) >= 4);
|
||||
RAPIDJSON_ASSERT(codepoint <= 0x10FFFF);
|
||||
PutUnsafe(os, codepoint);
|
||||
}
|
||||
|
||||
template <typename InputStream>
|
||||
static bool Decode(InputStream& is, unsigned* codepoint) {
|
||||
CEREAL_RAPIDJSON_STATIC_ASSERT(sizeof(typename InputStream::Ch) >= 4);
|
||||
RAPIDJSON_STATIC_ASSERT(sizeof(typename InputStream::Ch) >= 4);
|
||||
Ch c = is.Take();
|
||||
*codepoint = c;
|
||||
return c <= 0x10FFFF;
|
||||
@ -445,7 +445,7 @@ struct UTF32 {
|
||||
|
||||
template <typename InputStream, typename OutputStream>
|
||||
static bool Validate(InputStream& is, OutputStream& os) {
|
||||
CEREAL_RAPIDJSON_STATIC_ASSERT(sizeof(typename InputStream::Ch) >= 4);
|
||||
RAPIDJSON_STATIC_ASSERT(sizeof(typename InputStream::Ch) >= 4);
|
||||
Ch c;
|
||||
os.Put(c = is.Take());
|
||||
return c <= 0x10FFFF;
|
||||
@ -457,14 +457,14 @@ template<typename CharType = unsigned>
|
||||
struct UTF32LE : UTF32<CharType> {
|
||||
template <typename InputByteStream>
|
||||
static CharType TakeBOM(InputByteStream& is) {
|
||||
CEREAL_RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1);
|
||||
RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1);
|
||||
CharType c = Take(is);
|
||||
return static_cast<uint32_t>(c) == 0x0000FEFFu ? Take(is) : c;
|
||||
}
|
||||
|
||||
template <typename InputByteStream>
|
||||
static CharType Take(InputByteStream& is) {
|
||||
CEREAL_RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1);
|
||||
RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1);
|
||||
unsigned c = static_cast<uint8_t>(is.Take());
|
||||
c |= static_cast<unsigned>(static_cast<uint8_t>(is.Take())) << 8;
|
||||
c |= static_cast<unsigned>(static_cast<uint8_t>(is.Take())) << 16;
|
||||
@ -474,7 +474,7 @@ struct UTF32LE : UTF32<CharType> {
|
||||
|
||||
template <typename OutputByteStream>
|
||||
static void PutBOM(OutputByteStream& os) {
|
||||
CEREAL_RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1);
|
||||
RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1);
|
||||
os.Put(static_cast<typename OutputByteStream::Ch>(0xFFu));
|
||||
os.Put(static_cast<typename OutputByteStream::Ch>(0xFEu));
|
||||
os.Put(static_cast<typename OutputByteStream::Ch>(0x00u));
|
||||
@ -483,7 +483,7 @@ struct UTF32LE : UTF32<CharType> {
|
||||
|
||||
template <typename OutputByteStream>
|
||||
static void Put(OutputByteStream& os, CharType c) {
|
||||
CEREAL_RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1);
|
||||
RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1);
|
||||
os.Put(static_cast<typename OutputByteStream::Ch>(c & 0xFFu));
|
||||
os.Put(static_cast<typename OutputByteStream::Ch>((c >> 8) & 0xFFu));
|
||||
os.Put(static_cast<typename OutputByteStream::Ch>((c >> 16) & 0xFFu));
|
||||
@ -496,14 +496,14 @@ template<typename CharType = unsigned>
|
||||
struct UTF32BE : UTF32<CharType> {
|
||||
template <typename InputByteStream>
|
||||
static CharType TakeBOM(InputByteStream& is) {
|
||||
CEREAL_RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1);
|
||||
RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1);
|
||||
CharType c = Take(is);
|
||||
return static_cast<uint32_t>(c) == 0x0000FEFFu ? Take(is) : c;
|
||||
}
|
||||
|
||||
template <typename InputByteStream>
|
||||
static CharType Take(InputByteStream& is) {
|
||||
CEREAL_RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1);
|
||||
RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1);
|
||||
unsigned c = static_cast<unsigned>(static_cast<uint8_t>(is.Take())) << 24;
|
||||
c |= static_cast<unsigned>(static_cast<uint8_t>(is.Take())) << 16;
|
||||
c |= static_cast<unsigned>(static_cast<uint8_t>(is.Take())) << 8;
|
||||
@ -513,7 +513,7 @@ struct UTF32BE : UTF32<CharType> {
|
||||
|
||||
template <typename OutputByteStream>
|
||||
static void PutBOM(OutputByteStream& os) {
|
||||
CEREAL_RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1);
|
||||
RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1);
|
||||
os.Put(static_cast<typename OutputByteStream::Ch>(0x00u));
|
||||
os.Put(static_cast<typename OutputByteStream::Ch>(0x00u));
|
||||
os.Put(static_cast<typename OutputByteStream::Ch>(0xFEu));
|
||||
@ -522,7 +522,7 @@ struct UTF32BE : UTF32<CharType> {
|
||||
|
||||
template <typename OutputByteStream>
|
||||
static void Put(OutputByteStream& os, CharType c) {
|
||||
CEREAL_RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1);
|
||||
RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1);
|
||||
os.Put(static_cast<typename OutputByteStream::Ch>((c >> 24) & 0xFFu));
|
||||
os.Put(static_cast<typename OutputByteStream::Ch>((c >> 16) & 0xFFu));
|
||||
os.Put(static_cast<typename OutputByteStream::Ch>((c >> 8) & 0xFFu));
|
||||
@ -546,13 +546,13 @@ struct ASCII {
|
||||
|
||||
template<typename OutputStream>
|
||||
static void Encode(OutputStream& os, unsigned codepoint) {
|
||||
CEREAL_RAPIDJSON_ASSERT(codepoint <= 0x7F);
|
||||
RAPIDJSON_ASSERT(codepoint <= 0x7F);
|
||||
os.Put(static_cast<Ch>(codepoint & 0xFF));
|
||||
}
|
||||
|
||||
template<typename OutputStream>
|
||||
static void EncodeUnsafe(OutputStream& os, unsigned codepoint) {
|
||||
CEREAL_RAPIDJSON_ASSERT(codepoint <= 0x7F);
|
||||
RAPIDJSON_ASSERT(codepoint <= 0x7F);
|
||||
PutUnsafe(os, static_cast<Ch>(codepoint & 0xFF));
|
||||
}
|
||||
|
||||
@ -572,26 +572,26 @@ struct ASCII {
|
||||
|
||||
template <typename InputByteStream>
|
||||
static CharType TakeBOM(InputByteStream& is) {
|
||||
CEREAL_RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1);
|
||||
RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1);
|
||||
uint8_t c = static_cast<uint8_t>(Take(is));
|
||||
return static_cast<Ch>(c);
|
||||
}
|
||||
|
||||
template <typename InputByteStream>
|
||||
static Ch Take(InputByteStream& is) {
|
||||
CEREAL_RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1);
|
||||
RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1);
|
||||
return static_cast<Ch>(is.Take());
|
||||
}
|
||||
|
||||
template <typename OutputByteStream>
|
||||
static void PutBOM(OutputByteStream& os) {
|
||||
CEREAL_RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1);
|
||||
RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1);
|
||||
(void)os;
|
||||
}
|
||||
|
||||
template <typename OutputByteStream>
|
||||
static void Put(OutputByteStream& os, Ch c) {
|
||||
CEREAL_RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1);
|
||||
RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1);
|
||||
os.Put(static_cast<typename OutputByteStream::Ch>(c));
|
||||
}
|
||||
};
|
||||
@ -617,37 +617,37 @@ struct AutoUTF {
|
||||
|
||||
enum { supportUnicode = 1 };
|
||||
|
||||
#define CEREAL_RAPIDJSON_ENCODINGS_FUNC(x) UTF8<Ch>::x, UTF16LE<Ch>::x, UTF16BE<Ch>::x, UTF32LE<Ch>::x, UTF32BE<Ch>::x
|
||||
#define RAPIDJSON_ENCODINGS_FUNC(x) UTF8<Ch>::x, UTF16LE<Ch>::x, UTF16BE<Ch>::x, UTF32LE<Ch>::x, UTF32BE<Ch>::x
|
||||
|
||||
template<typename OutputStream>
|
||||
CEREAL_RAPIDJSON_FORCEINLINE static void Encode(OutputStream& os, unsigned codepoint) {
|
||||
static RAPIDJSON_FORCEINLINE void Encode(OutputStream& os, unsigned codepoint) {
|
||||
typedef void (*EncodeFunc)(OutputStream&, unsigned);
|
||||
static const EncodeFunc f[] = { CEREAL_RAPIDJSON_ENCODINGS_FUNC(Encode) };
|
||||
static const EncodeFunc f[] = { RAPIDJSON_ENCODINGS_FUNC(Encode) };
|
||||
(*f[os.GetType()])(os, codepoint);
|
||||
}
|
||||
|
||||
template<typename OutputStream>
|
||||
CEREAL_RAPIDJSON_FORCEINLINE static void EncodeUnsafe(OutputStream& os, unsigned codepoint) {
|
||||
static RAPIDJSON_FORCEINLINE void EncodeUnsafe(OutputStream& os, unsigned codepoint) {
|
||||
typedef void (*EncodeFunc)(OutputStream&, unsigned);
|
||||
static const EncodeFunc f[] = { CEREAL_RAPIDJSON_ENCODINGS_FUNC(EncodeUnsafe) };
|
||||
static const EncodeFunc f[] = { RAPIDJSON_ENCODINGS_FUNC(EncodeUnsafe) };
|
||||
(*f[os.GetType()])(os, codepoint);
|
||||
}
|
||||
|
||||
template <typename InputStream>
|
||||
CEREAL_RAPIDJSON_FORCEINLINE static bool Decode(InputStream& is, unsigned* codepoint) {
|
||||
static RAPIDJSON_FORCEINLINE bool Decode(InputStream& is, unsigned* codepoint) {
|
||||
typedef bool (*DecodeFunc)(InputStream&, unsigned*);
|
||||
static const DecodeFunc f[] = { CEREAL_RAPIDJSON_ENCODINGS_FUNC(Decode) };
|
||||
static const DecodeFunc f[] = { RAPIDJSON_ENCODINGS_FUNC(Decode) };
|
||||
return (*f[is.GetType()])(is, codepoint);
|
||||
}
|
||||
|
||||
template <typename InputStream, typename OutputStream>
|
||||
CEREAL_RAPIDJSON_FORCEINLINE static bool Validate(InputStream& is, OutputStream& os) {
|
||||
static RAPIDJSON_FORCEINLINE bool Validate(InputStream& is, OutputStream& os) {
|
||||
typedef bool (*ValidateFunc)(InputStream&, OutputStream&);
|
||||
static const ValidateFunc f[] = { CEREAL_RAPIDJSON_ENCODINGS_FUNC(Validate) };
|
||||
static const ValidateFunc f[] = { RAPIDJSON_ENCODINGS_FUNC(Validate) };
|
||||
return (*f[is.GetType()])(is, os);
|
||||
}
|
||||
|
||||
#undef CEREAL_RAPIDJSON_ENCODINGS_FUNC
|
||||
#undef RAPIDJSON_ENCODINGS_FUNC
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
@ -658,7 +658,7 @@ template<typename SourceEncoding, typename TargetEncoding>
|
||||
struct Transcoder {
|
||||
//! Take one Unicode codepoint from source encoding, convert it to target encoding and put it to the output stream.
|
||||
template<typename InputStream, typename OutputStream>
|
||||
CEREAL_RAPIDJSON_FORCEINLINE static bool Transcode(InputStream& is, OutputStream& os) {
|
||||
static RAPIDJSON_FORCEINLINE bool Transcode(InputStream& is, OutputStream& os) {
|
||||
unsigned codepoint;
|
||||
if (!SourceEncoding::Decode(is, &codepoint))
|
||||
return false;
|
||||
@ -667,7 +667,7 @@ struct Transcoder {
|
||||
}
|
||||
|
||||
template<typename InputStream, typename OutputStream>
|
||||
CEREAL_RAPIDJSON_FORCEINLINE static bool TranscodeUnsafe(InputStream& is, OutputStream& os) {
|
||||
static RAPIDJSON_FORCEINLINE bool TranscodeUnsafe(InputStream& is, OutputStream& os) {
|
||||
unsigned codepoint;
|
||||
if (!SourceEncoding::Decode(is, &codepoint))
|
||||
return false;
|
||||
@ -677,7 +677,7 @@ struct Transcoder {
|
||||
|
||||
//! Validate one Unicode codepoint from an encoded stream.
|
||||
template<typename InputStream, typename OutputStream>
|
||||
CEREAL_RAPIDJSON_FORCEINLINE static bool Validate(InputStream& is, OutputStream& os) {
|
||||
static RAPIDJSON_FORCEINLINE bool Validate(InputStream& is, OutputStream& os) {
|
||||
return Transcode(is, os); // Since source/target encoding is different, must transcode.
|
||||
}
|
||||
};
|
||||
@ -690,27 +690,27 @@ inline void PutUnsafe(Stream& stream, typename Stream::Ch c);
|
||||
template<typename Encoding>
|
||||
struct Transcoder<Encoding, Encoding> {
|
||||
template<typename InputStream, typename OutputStream>
|
||||
CEREAL_RAPIDJSON_FORCEINLINE static bool Transcode(InputStream& is, OutputStream& os) {
|
||||
static RAPIDJSON_FORCEINLINE bool Transcode(InputStream& is, OutputStream& os) {
|
||||
os.Put(is.Take()); // Just copy one code unit. This semantic is different from primary template class.
|
||||
return true;
|
||||
}
|
||||
|
||||
template<typename InputStream, typename OutputStream>
|
||||
CEREAL_RAPIDJSON_FORCEINLINE static bool TranscodeUnsafe(InputStream& is, OutputStream& os) {
|
||||
static RAPIDJSON_FORCEINLINE bool TranscodeUnsafe(InputStream& is, OutputStream& os) {
|
||||
PutUnsafe(os, is.Take()); // Just copy one code unit. This semantic is different from primary template class.
|
||||
return true;
|
||||
}
|
||||
|
||||
template<typename InputStream, typename OutputStream>
|
||||
CEREAL_RAPIDJSON_FORCEINLINE static bool Validate(InputStream& is, OutputStream& os) {
|
||||
static RAPIDJSON_FORCEINLINE bool Validate(InputStream& is, OutputStream& os) {
|
||||
return Encoding::Validate(is, os); // source/target encoding are the same
|
||||
}
|
||||
};
|
||||
|
||||
CEREAL_RAPIDJSON_NAMESPACE_END
|
||||
RAPIDJSON_NAMESPACE_END
|
||||
|
||||
#if defined(__GNUC__) || defined(_MSC_VER)
|
||||
CEREAL_RAPIDJSON_DIAG_POP
|
||||
#if defined(__GNUC__) || (defined(_MSC_VER) && !defined(__clang__))
|
||||
RAPIDJSON_DIAG_POP
|
||||
#endif
|
||||
|
||||
#endif // CEREAL_RAPIDJSON_ENCODINGS_H_
|
||||
#endif // RAPIDJSON_ENCODINGS_H_
|
||||
|
110
external/cereal/external/rapidjson/error/en.h
vendored
110
external/cereal/external/rapidjson/error/en.h
vendored
@ -1,6 +1,6 @@
|
||||
// Tencent is pleased to support the open source community by making RapidJSON available.
|
||||
//
|
||||
// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
|
||||
// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip.
|
||||
//
|
||||
// Licensed under the MIT License (the "License"); you may not use this file except
|
||||
// in compliance with the License. You may obtain a copy of the License at
|
||||
@ -12,63 +12,111 @@
|
||||
// CONDITIONS OF ANY KIND, either express or implied. See the License for the
|
||||
// specific language governing permissions and limitations under the License.
|
||||
|
||||
#ifndef CEREAL_RAPIDJSON_ERROR_EN_H_
|
||||
#define CEREAL_RAPIDJSON_ERROR_EN_H_
|
||||
#ifndef RAPIDJSON_ERROR_EN_H_
|
||||
#define RAPIDJSON_ERROR_EN_H_
|
||||
|
||||
#include "error.h"
|
||||
|
||||
#ifdef __clang__
|
||||
CEREAL_RAPIDJSON_DIAG_PUSH
|
||||
CEREAL_RAPIDJSON_DIAG_OFF(switch-enum)
|
||||
CEREAL_RAPIDJSON_DIAG_OFF(covered-switch-default)
|
||||
RAPIDJSON_DIAG_PUSH
|
||||
RAPIDJSON_DIAG_OFF(switch-enum)
|
||||
RAPIDJSON_DIAG_OFF(covered-switch-default)
|
||||
#endif
|
||||
|
||||
CEREAL_RAPIDJSON_NAMESPACE_BEGIN
|
||||
RAPIDJSON_NAMESPACE_BEGIN
|
||||
|
||||
//! Maps error code of parsing into error message.
|
||||
/*!
|
||||
\ingroup CEREAL_RAPIDJSON_ERRORS
|
||||
\ingroup RAPIDJSON_ERRORS
|
||||
\param parseErrorCode Error code obtained in parsing.
|
||||
\return the error message.
|
||||
\note User can make a copy of this function for localization.
|
||||
Using switch-case is safer for future modification of error codes.
|
||||
*/
|
||||
inline const CEREAL_RAPIDJSON_ERROR_CHARTYPE* GetParseError_En(ParseErrorCode parseErrorCode) {
|
||||
inline const RAPIDJSON_ERROR_CHARTYPE* GetParseError_En(ParseErrorCode parseErrorCode) {
|
||||
switch (parseErrorCode) {
|
||||
case kParseErrorNone: return CEREAL_RAPIDJSON_ERROR_STRING("No error.");
|
||||
case kParseErrorNone: return RAPIDJSON_ERROR_STRING("No error.");
|
||||
|
||||
case kParseErrorDocumentEmpty: return CEREAL_RAPIDJSON_ERROR_STRING("The document is empty.");
|
||||
case kParseErrorDocumentRootNotSingular: return CEREAL_RAPIDJSON_ERROR_STRING("The document root must not be followed by other values.");
|
||||
case kParseErrorDocumentEmpty: return RAPIDJSON_ERROR_STRING("The document is empty.");
|
||||
case kParseErrorDocumentRootNotSingular: return RAPIDJSON_ERROR_STRING("The document root must not be followed by other values.");
|
||||
|
||||
case kParseErrorValueInvalid: return CEREAL_RAPIDJSON_ERROR_STRING("Invalid value.");
|
||||
case kParseErrorValueInvalid: return RAPIDJSON_ERROR_STRING("Invalid value.");
|
||||
|
||||
case kParseErrorObjectMissName: return CEREAL_RAPIDJSON_ERROR_STRING("Missing a name for object member.");
|
||||
case kParseErrorObjectMissColon: return CEREAL_RAPIDJSON_ERROR_STRING("Missing a colon after a name of object member.");
|
||||
case kParseErrorObjectMissCommaOrCurlyBracket: return CEREAL_RAPIDJSON_ERROR_STRING("Missing a comma or '}' after an object member.");
|
||||
case kParseErrorObjectMissName: return RAPIDJSON_ERROR_STRING("Missing a name for object member.");
|
||||
case kParseErrorObjectMissColon: return RAPIDJSON_ERROR_STRING("Missing a colon after a name of object member.");
|
||||
case kParseErrorObjectMissCommaOrCurlyBracket: return RAPIDJSON_ERROR_STRING("Missing a comma or '}' after an object member.");
|
||||
|
||||
case kParseErrorArrayMissCommaOrSquareBracket: return CEREAL_RAPIDJSON_ERROR_STRING("Missing a comma or ']' after an array element.");
|
||||
case kParseErrorArrayMissCommaOrSquareBracket: return RAPIDJSON_ERROR_STRING("Missing a comma or ']' after an array element.");
|
||||
|
||||
case kParseErrorStringUnicodeEscapeInvalidHex: return CEREAL_RAPIDJSON_ERROR_STRING("Incorrect hex digit after \\u escape in string.");
|
||||
case kParseErrorStringUnicodeSurrogateInvalid: return CEREAL_RAPIDJSON_ERROR_STRING("The surrogate pair in string is invalid.");
|
||||
case kParseErrorStringEscapeInvalid: return CEREAL_RAPIDJSON_ERROR_STRING("Invalid escape character in string.");
|
||||
case kParseErrorStringMissQuotationMark: return CEREAL_RAPIDJSON_ERROR_STRING("Missing a closing quotation mark in string.");
|
||||
case kParseErrorStringInvalidEncoding: return CEREAL_RAPIDJSON_ERROR_STRING("Invalid encoding in string.");
|
||||
case kParseErrorStringUnicodeEscapeInvalidHex: return RAPIDJSON_ERROR_STRING("Incorrect hex digit after \\u escape in string.");
|
||||
case kParseErrorStringUnicodeSurrogateInvalid: return RAPIDJSON_ERROR_STRING("The surrogate pair in string is invalid.");
|
||||
case kParseErrorStringEscapeInvalid: return RAPIDJSON_ERROR_STRING("Invalid escape character in string.");
|
||||
case kParseErrorStringMissQuotationMark: return RAPIDJSON_ERROR_STRING("Missing a closing quotation mark in string.");
|
||||
case kParseErrorStringInvalidEncoding: return RAPIDJSON_ERROR_STRING("Invalid encoding in string.");
|
||||
|
||||
case kParseErrorNumberTooBig: return CEREAL_RAPIDJSON_ERROR_STRING("Number too big to be stored in double.");
|
||||
case kParseErrorNumberMissFraction: return CEREAL_RAPIDJSON_ERROR_STRING("Miss fraction part in number.");
|
||||
case kParseErrorNumberMissExponent: return CEREAL_RAPIDJSON_ERROR_STRING("Miss exponent in number.");
|
||||
case kParseErrorNumberTooBig: return RAPIDJSON_ERROR_STRING("Number too big to be stored in double.");
|
||||
case kParseErrorNumberMissFraction: return RAPIDJSON_ERROR_STRING("Miss fraction part in number.");
|
||||
case kParseErrorNumberMissExponent: return RAPIDJSON_ERROR_STRING("Miss exponent in number.");
|
||||
|
||||
case kParseErrorTermination: return CEREAL_RAPIDJSON_ERROR_STRING("Terminate parsing due to Handler error.");
|
||||
case kParseErrorUnspecificSyntaxError: return CEREAL_RAPIDJSON_ERROR_STRING("Unspecific syntax error.");
|
||||
case kParseErrorTermination: return RAPIDJSON_ERROR_STRING("Terminate parsing due to Handler error.");
|
||||
case kParseErrorUnspecificSyntaxError: return RAPIDJSON_ERROR_STRING("Unspecific syntax error.");
|
||||
|
||||
default: return CEREAL_RAPIDJSON_ERROR_STRING("Unknown error.");
|
||||
default: return RAPIDJSON_ERROR_STRING("Unknown error.");
|
||||
}
|
||||
}
|
||||
|
||||
CEREAL_RAPIDJSON_NAMESPACE_END
|
||||
//! Maps error code of validation into error message.
|
||||
/*!
|
||||
\ingroup RAPIDJSON_ERRORS
|
||||
\param validateErrorCode Error code obtained from validator.
|
||||
\return the error message.
|
||||
\note User can make a copy of this function for localization.
|
||||
Using switch-case is safer for future modification of error codes.
|
||||
*/
|
||||
inline const RAPIDJSON_ERROR_CHARTYPE* GetValidateError_En(ValidateErrorCode validateErrorCode) {
|
||||
switch (validateErrorCode) {
|
||||
case kValidateErrors: return RAPIDJSON_ERROR_STRING("One or more validation errors have occurred");
|
||||
case kValidateErrorNone: return RAPIDJSON_ERROR_STRING("No error.");
|
||||
|
||||
case kValidateErrorMultipleOf: return RAPIDJSON_ERROR_STRING("Number '%actual' is not a multiple of the 'multipleOf' value '%expected'.");
|
||||
case kValidateErrorMaximum: return RAPIDJSON_ERROR_STRING("Number '%actual' is greater than the 'maximum' value '%expected'.");
|
||||
case kValidateErrorExclusiveMaximum: return RAPIDJSON_ERROR_STRING("Number '%actual' is greater than or equal to the 'exclusiveMaximum' value '%expected'.");
|
||||
case kValidateErrorMinimum: return RAPIDJSON_ERROR_STRING("Number '%actual' is less than the 'minimum' value '%expected'.");
|
||||
case kValidateErrorExclusiveMinimum: return RAPIDJSON_ERROR_STRING("Number '%actual' is less than or equal to the 'exclusiveMinimum' value '%expected'.");
|
||||
|
||||
case kValidateErrorMaxLength: return RAPIDJSON_ERROR_STRING("String '%actual' is longer than the 'maxLength' value '%expected'.");
|
||||
case kValidateErrorMinLength: return RAPIDJSON_ERROR_STRING("String '%actual' is shorter than the 'minLength' value '%expected'.");
|
||||
case kValidateErrorPattern: return RAPIDJSON_ERROR_STRING("String '%actual' does not match the 'pattern' regular expression.");
|
||||
|
||||
case kValidateErrorMaxItems: return RAPIDJSON_ERROR_STRING("Array of length '%actual' is longer than the 'maxItems' value '%expected'.");
|
||||
case kValidateErrorMinItems: return RAPIDJSON_ERROR_STRING("Array of length '%actual' is shorter than the 'minItems' value '%expected'.");
|
||||
case kValidateErrorUniqueItems: return RAPIDJSON_ERROR_STRING("Array has duplicate items at indices '%duplicates' but 'uniqueItems' is true.");
|
||||
case kValidateErrorAdditionalItems: return RAPIDJSON_ERROR_STRING("Array has an additional item at index '%disallowed' that is not allowed by the schema.");
|
||||
|
||||
case kValidateErrorMaxProperties: return RAPIDJSON_ERROR_STRING("Object has '%actual' members which is more than 'maxProperties' value '%expected'.");
|
||||
case kValidateErrorMinProperties: return RAPIDJSON_ERROR_STRING("Object has '%actual' members which is less than 'minProperties' value '%expected'.");
|
||||
case kValidateErrorRequired: return RAPIDJSON_ERROR_STRING("Object is missing the following members required by the schema: '%missing'.");
|
||||
case kValidateErrorAdditionalProperties: return RAPIDJSON_ERROR_STRING("Object has an additional member '%disallowed' that is not allowed by the schema.");
|
||||
case kValidateErrorPatternProperties: return RAPIDJSON_ERROR_STRING("Object has 'patternProperties' that are not allowed by the schema.");
|
||||
case kValidateErrorDependencies: return RAPIDJSON_ERROR_STRING("Object has missing property or schema dependencies, refer to following errors.");
|
||||
|
||||
case kValidateErrorEnum: return RAPIDJSON_ERROR_STRING("Property has a value that is not one of its allowed enumerated values.");
|
||||
case kValidateErrorType: return RAPIDJSON_ERROR_STRING("Property has a type '%actual' that is not in the following list: '%expected'.");
|
||||
|
||||
case kValidateErrorOneOf: return RAPIDJSON_ERROR_STRING("Property did not match any of the sub-schemas specified by 'oneOf', refer to following errors.");
|
||||
case kValidateErrorOneOfMatch: return RAPIDJSON_ERROR_STRING("Property matched more than one of the sub-schemas specified by 'oneOf'.");
|
||||
case kValidateErrorAllOf: return RAPIDJSON_ERROR_STRING("Property did not match all of the sub-schemas specified by 'allOf', refer to following errors.");
|
||||
case kValidateErrorAnyOf: return RAPIDJSON_ERROR_STRING("Property did not match any of the sub-schemas specified by 'anyOf', refer to following errors.");
|
||||
case kValidateErrorNot: return RAPIDJSON_ERROR_STRING("Property matched the sub-schema specified by 'not'.");
|
||||
|
||||
default: return RAPIDJSON_ERROR_STRING("Unknown error.");
|
||||
}
|
||||
}
|
||||
|
||||
RAPIDJSON_NAMESPACE_END
|
||||
|
||||
#ifdef __clang__
|
||||
CEREAL_RAPIDJSON_DIAG_POP
|
||||
RAPIDJSON_DIAG_POP
|
||||
#endif
|
||||
|
||||
#endif // CEREAL_RAPIDJSON_ERROR_EN_H_
|
||||
#endif // RAPIDJSON_ERROR_EN_H_
|
||||
|
113
external/cereal/external/rapidjson/error/error.h
vendored
113
external/cereal/external/rapidjson/error/error.h
vendored
@ -1,6 +1,6 @@
|
||||
// Tencent is pleased to support the open source community by making RapidJSON available.
|
||||
//
|
||||
// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
|
||||
// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip.
|
||||
//
|
||||
// Licensed under the MIT License (the "License"); you may not use this file except
|
||||
// in compliance with the License. You may obtain a copy of the License at
|
||||
@ -12,53 +12,53 @@
|
||||
// CONDITIONS OF ANY KIND, either express or implied. See the License for the
|
||||
// specific language governing permissions and limitations under the License.
|
||||
|
||||
#ifndef CEREAL_RAPIDJSON_ERROR_ERROR_H_
|
||||
#define CEREAL_RAPIDJSON_ERROR_ERROR_H_
|
||||
#ifndef RAPIDJSON_ERROR_ERROR_H_
|
||||
#define RAPIDJSON_ERROR_ERROR_H_
|
||||
|
||||
#include "../rapidjson.h"
|
||||
|
||||
#ifdef __clang__
|
||||
CEREAL_RAPIDJSON_DIAG_PUSH
|
||||
CEREAL_RAPIDJSON_DIAG_OFF(padded)
|
||||
RAPIDJSON_DIAG_PUSH
|
||||
RAPIDJSON_DIAG_OFF(padded)
|
||||
#endif
|
||||
|
||||
/*! \file error.h */
|
||||
|
||||
/*! \defgroup CEREAL_RAPIDJSON_ERRORS RapidJSON error handling */
|
||||
/*! \defgroup RAPIDJSON_ERRORS RapidJSON error handling */
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// CEREAL_RAPIDJSON_ERROR_CHARTYPE
|
||||
// RAPIDJSON_ERROR_CHARTYPE
|
||||
|
||||
//! Character type of error messages.
|
||||
/*! \ingroup CEREAL_RAPIDJSON_ERRORS
|
||||
/*! \ingroup RAPIDJSON_ERRORS
|
||||
The default character type is \c char.
|
||||
On Windows, user can define this macro as \c TCHAR for supporting both
|
||||
unicode/non-unicode settings.
|
||||
*/
|
||||
#ifndef CEREAL_RAPIDJSON_ERROR_CHARTYPE
|
||||
#define CEREAL_RAPIDJSON_ERROR_CHARTYPE char
|
||||
#ifndef RAPIDJSON_ERROR_CHARTYPE
|
||||
#define RAPIDJSON_ERROR_CHARTYPE char
|
||||
#endif
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// CEREAL_RAPIDJSON_ERROR_STRING
|
||||
// RAPIDJSON_ERROR_STRING
|
||||
|
||||
//! Macro for converting string literial to \ref CEREAL_RAPIDJSON_ERROR_CHARTYPE[].
|
||||
/*! \ingroup CEREAL_RAPIDJSON_ERRORS
|
||||
//! Macro for converting string literial to \ref RAPIDJSON_ERROR_CHARTYPE[].
|
||||
/*! \ingroup RAPIDJSON_ERRORS
|
||||
By default this conversion macro does nothing.
|
||||
On Windows, user can define this macro as \c _T(x) for supporting both
|
||||
unicode/non-unicode settings.
|
||||
*/
|
||||
#ifndef CEREAL_RAPIDJSON_ERROR_STRING
|
||||
#define CEREAL_RAPIDJSON_ERROR_STRING(x) x
|
||||
#ifndef RAPIDJSON_ERROR_STRING
|
||||
#define RAPIDJSON_ERROR_STRING(x) x
|
||||
#endif
|
||||
|
||||
CEREAL_RAPIDJSON_NAMESPACE_BEGIN
|
||||
RAPIDJSON_NAMESPACE_BEGIN
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// ParseErrorCode
|
||||
|
||||
//! Error code of parsing.
|
||||
/*! \ingroup CEREAL_RAPIDJSON_ERRORS
|
||||
/*! \ingroup RAPIDJSON_ERRORS
|
||||
\see GenericReader::Parse, GenericReader::GetParseErrorCode
|
||||
*/
|
||||
enum ParseErrorCode {
|
||||
@ -91,7 +91,7 @@ enum ParseErrorCode {
|
||||
|
||||
//! Result of parsing (wraps ParseErrorCode)
|
||||
/*!
|
||||
\ingroup CEREAL_RAPIDJSON_ERRORS
|
||||
\ingroup RAPIDJSON_ERRORS
|
||||
\code
|
||||
Document doc;
|
||||
ParseResult ok = doc.Parse("[42]");
|
||||
@ -104,6 +104,8 @@ enum ParseErrorCode {
|
||||
\see GenericReader::Parse, GenericDocument::Parse
|
||||
*/
|
||||
struct ParseResult {
|
||||
//!! Unspecified boolean type
|
||||
typedef bool (ParseResult::*BooleanType)() const;
|
||||
public:
|
||||
//! Default constructor, no error.
|
||||
ParseResult() : code_(kParseErrorNone), offset_(0) {}
|
||||
@ -115,8 +117,8 @@ public:
|
||||
//! Get the error offset, if \ref IsError(), 0 otherwise.
|
||||
size_t Offset() const { return offset_; }
|
||||
|
||||
//! Conversion to \c bool, returns \c true, iff !\ref IsError().
|
||||
operator bool() const { return !IsError(); }
|
||||
//! Explicit conversion to \c bool, returns \c true, iff !\ref IsError().
|
||||
operator BooleanType() const { return !IsError() ? &ParseResult::IsError : NULL; }
|
||||
//! Whether the result is an error.
|
||||
bool IsError() const { return code_ != kParseErrorNone; }
|
||||
|
||||
@ -124,6 +126,10 @@ public:
|
||||
bool operator==(ParseErrorCode code) const { return code_ == code; }
|
||||
friend bool operator==(ParseErrorCode code, const ParseResult & err) { return code == err.code_; }
|
||||
|
||||
bool operator!=(const ParseResult& that) const { return !(*this == that); }
|
||||
bool operator!=(ParseErrorCode code) const { return !(*this == code); }
|
||||
friend bool operator!=(ParseErrorCode code, const ParseResult & err) { return err != code; }
|
||||
|
||||
//! Reset error code.
|
||||
void Clear() { Set(kParseErrorNone); }
|
||||
//! Update error code and offset.
|
||||
@ -135,21 +141,76 @@ private:
|
||||
};
|
||||
|
||||
//! Function pointer type of GetParseError().
|
||||
/*! \ingroup CEREAL_RAPIDJSON_ERRORS
|
||||
/*! \ingroup RAPIDJSON_ERRORS
|
||||
|
||||
This is the prototype for \c GetParseError_X(), where \c X is a locale.
|
||||
User can dynamically change locale in runtime, e.g.:
|
||||
\code
|
||||
GetParseErrorFunc GetParseError = GetParseError_En; // or whatever
|
||||
const CEREAL_RAPIDJSON_ERROR_CHARTYPE* s = GetParseError(document.GetParseErrorCode());
|
||||
const RAPIDJSON_ERROR_CHARTYPE* s = GetParseError(document.GetParseErrorCode());
|
||||
\endcode
|
||||
*/
|
||||
typedef const CEREAL_RAPIDJSON_ERROR_CHARTYPE* (*GetParseErrorFunc)(ParseErrorCode);
|
||||
typedef const RAPIDJSON_ERROR_CHARTYPE* (*GetParseErrorFunc)(ParseErrorCode);
|
||||
|
||||
CEREAL_RAPIDJSON_NAMESPACE_END
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// ValidateErrorCode
|
||||
|
||||
//! Error codes when validating.
|
||||
/*! \ingroup RAPIDJSON_ERRORS
|
||||
\see GenericSchemaValidator
|
||||
*/
|
||||
enum ValidateErrorCode {
|
||||
kValidateErrors = -1, //!< Top level error code when kValidateContinueOnErrorsFlag set.
|
||||
kValidateErrorNone = 0, //!< No error.
|
||||
|
||||
kValidateErrorMultipleOf, //!< Number is not a multiple of the 'multipleOf' value.
|
||||
kValidateErrorMaximum, //!< Number is greater than the 'maximum' value.
|
||||
kValidateErrorExclusiveMaximum, //!< Number is greater than or equal to the 'maximum' value.
|
||||
kValidateErrorMinimum, //!< Number is less than the 'minimum' value.
|
||||
kValidateErrorExclusiveMinimum, //!< Number is less than or equal to the 'minimum' value.
|
||||
|
||||
kValidateErrorMaxLength, //!< String is longer than the 'maxLength' value.
|
||||
kValidateErrorMinLength, //!< String is longer than the 'maxLength' value.
|
||||
kValidateErrorPattern, //!< String does not match the 'pattern' regular expression.
|
||||
|
||||
kValidateErrorMaxItems, //!< Array is longer than the 'maxItems' value.
|
||||
kValidateErrorMinItems, //!< Array is shorter than the 'minItems' value.
|
||||
kValidateErrorUniqueItems, //!< Array has duplicate items but 'uniqueItems' is true.
|
||||
kValidateErrorAdditionalItems, //!< Array has additional items that are not allowed by the schema.
|
||||
|
||||
kValidateErrorMaxProperties, //!< Object has more members than 'maxProperties' value.
|
||||
kValidateErrorMinProperties, //!< Object has less members than 'minProperties' value.
|
||||
kValidateErrorRequired, //!< Object is missing one or more members required by the schema.
|
||||
kValidateErrorAdditionalProperties, //!< Object has additional members that are not allowed by the schema.
|
||||
kValidateErrorPatternProperties, //!< See other errors.
|
||||
kValidateErrorDependencies, //!< Object has missing property or schema dependencies.
|
||||
|
||||
kValidateErrorEnum, //!< Property has a value that is not one of its allowed enumerated values
|
||||
kValidateErrorType, //!< Property has a type that is not allowed by the schema..
|
||||
|
||||
kValidateErrorOneOf, //!< Property did not match any of the sub-schemas specified by 'oneOf'.
|
||||
kValidateErrorOneOfMatch, //!< Property matched more than one of the sub-schemas specified by 'oneOf'.
|
||||
kValidateErrorAllOf, //!< Property did not match all of the sub-schemas specified by 'allOf'.
|
||||
kValidateErrorAnyOf, //!< Property did not match any of the sub-schemas specified by 'anyOf'.
|
||||
kValidateErrorNot //!< Property matched the sub-schema specified by 'not'.
|
||||
};
|
||||
|
||||
//! Function pointer type of GetValidateError().
|
||||
/*! \ingroup RAPIDJSON_ERRORS
|
||||
|
||||
This is the prototype for \c GetValidateError_X(), where \c X is a locale.
|
||||
User can dynamically change locale in runtime, e.g.:
|
||||
\code
|
||||
GetValidateErrorFunc GetValidateError = GetValidateError_En; // or whatever
|
||||
const RAPIDJSON_ERROR_CHARTYPE* s = GetValidateError(validator.GetInvalidSchemaCode());
|
||||
\endcode
|
||||
*/
|
||||
typedef const RAPIDJSON_ERROR_CHARTYPE* (*GetValidateErrorFunc)(ValidateErrorCode);
|
||||
|
||||
RAPIDJSON_NAMESPACE_END
|
||||
|
||||
#ifdef __clang__
|
||||
CEREAL_RAPIDJSON_DIAG_POP
|
||||
RAPIDJSON_DIAG_POP
|
||||
#endif
|
||||
|
||||
#endif // CEREAL_RAPIDJSON_ERROR_ERROR_H_
|
||||
#endif // RAPIDJSON_ERROR_ERROR_H_
|
||||
|
@ -1,6 +1,6 @@
|
||||
// Tencent is pleased to support the open source community by making RapidJSON available.
|
||||
//
|
||||
// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
|
||||
// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip.
|
||||
//
|
||||
// Licensed under the MIT License (the "License"); you may not use this file except
|
||||
// in compliance with the License. You may obtain a copy of the License at
|
||||
@ -12,20 +12,20 @@
|
||||
// CONDITIONS OF ANY KIND, either express or implied. See the License for the
|
||||
// specific language governing permissions and limitations under the License.
|
||||
|
||||
#ifndef CEREAL_RAPIDJSON_FILEREADSTREAM_H_
|
||||
#define CEREAL_RAPIDJSON_FILEREADSTREAM_H_
|
||||
#ifndef RAPIDJSON_FILEREADSTREAM_H_
|
||||
#define RAPIDJSON_FILEREADSTREAM_H_
|
||||
|
||||
#include "stream.h"
|
||||
#include <cstdio>
|
||||
|
||||
#ifdef __clang__
|
||||
CEREAL_RAPIDJSON_DIAG_PUSH
|
||||
CEREAL_RAPIDJSON_DIAG_OFF(padded)
|
||||
CEREAL_RAPIDJSON_DIAG_OFF(unreachable-code)
|
||||
CEREAL_RAPIDJSON_DIAG_OFF(missing-noreturn)
|
||||
RAPIDJSON_DIAG_PUSH
|
||||
RAPIDJSON_DIAG_OFF(padded)
|
||||
RAPIDJSON_DIAG_OFF(unreachable-code)
|
||||
RAPIDJSON_DIAG_OFF(missing-noreturn)
|
||||
#endif
|
||||
|
||||
CEREAL_RAPIDJSON_NAMESPACE_BEGIN
|
||||
RAPIDJSON_NAMESPACE_BEGIN
|
||||
|
||||
//! File byte stream for input using fread().
|
||||
/*!
|
||||
@ -42,8 +42,8 @@ public:
|
||||
\param bufferSize size of buffer in bytes. Must >=4 bytes.
|
||||
*/
|
||||
FileReadStream(std::FILE* fp, char* buffer, size_t bufferSize) : fp_(fp), buffer_(buffer), bufferSize_(bufferSize), bufferLast_(0), current_(buffer_), readCount_(0), count_(0), eof_(false) {
|
||||
CEREAL_RAPIDJSON_ASSERT(fp_ != 0);
|
||||
CEREAL_RAPIDJSON_ASSERT(bufferSize >= 4);
|
||||
RAPIDJSON_ASSERT(fp_ != 0);
|
||||
RAPIDJSON_ASSERT(bufferSize >= 4);
|
||||
Read();
|
||||
}
|
||||
|
||||
@ -52,14 +52,14 @@ public:
|
||||
size_t Tell() const { return count_ + static_cast<size_t>(current_ - buffer_); }
|
||||
|
||||
// Not implemented
|
||||
void Put(Ch) { CEREAL_RAPIDJSON_ASSERT(false); }
|
||||
void Flush() { CEREAL_RAPIDJSON_ASSERT(false); }
|
||||
Ch* PutBegin() { CEREAL_RAPIDJSON_ASSERT(false); return 0; }
|
||||
size_t PutEnd(Ch*) { CEREAL_RAPIDJSON_ASSERT(false); return 0; }
|
||||
void Put(Ch) { RAPIDJSON_ASSERT(false); }
|
||||
void Flush() { RAPIDJSON_ASSERT(false); }
|
||||
Ch* PutBegin() { RAPIDJSON_ASSERT(false); return 0; }
|
||||
size_t PutEnd(Ch*) { RAPIDJSON_ASSERT(false); return 0; }
|
||||
|
||||
// For encoding detection only.
|
||||
const Ch* Peek4() const {
|
||||
return (current_ + 4 <= bufferLast_) ? current_ : 0;
|
||||
return (current_ + 4 - !eof_ <= bufferLast_) ? current_ : 0;
|
||||
}
|
||||
|
||||
private:
|
||||
@ -68,7 +68,7 @@ private:
|
||||
++current_;
|
||||
else if (!eof_) {
|
||||
count_ += readCount_;
|
||||
readCount_ = fread(buffer_, 1, bufferSize_, fp_);
|
||||
readCount_ = std::fread(buffer_, 1, bufferSize_, fp_);
|
||||
bufferLast_ = buffer_ + readCount_ - 1;
|
||||
current_ = buffer_;
|
||||
|
||||
@ -90,10 +90,10 @@ private:
|
||||
bool eof_;
|
||||
};
|
||||
|
||||
CEREAL_RAPIDJSON_NAMESPACE_END
|
||||
RAPIDJSON_NAMESPACE_END
|
||||
|
||||
#ifdef __clang__
|
||||
CEREAL_RAPIDJSON_DIAG_POP
|
||||
RAPIDJSON_DIAG_POP
|
||||
#endif
|
||||
|
||||
#endif // CEREAL_RAPIDJSON_FILESTREAM_H_
|
||||
#endif // RAPIDJSON_FILESTREAM_H_
|
||||
|
@ -1,6 +1,6 @@
|
||||
// Tencent is pleased to support the open source community by making RapidJSON available.
|
||||
//
|
||||
// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
|
||||
// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip.
|
||||
//
|
||||
// Licensed under the MIT License (the "License"); you may not use this file except
|
||||
// in compliance with the License. You may obtain a copy of the License at
|
||||
@ -12,20 +12,20 @@
|
||||
// CONDITIONS OF ANY KIND, either express or implied. See the License for the
|
||||
// specific language governing permissions and limitations under the License.
|
||||
|
||||
#ifndef CEREAL_RAPIDJSON_FILEWRITESTREAM_H_
|
||||
#define CEREAL_RAPIDJSON_FILEWRITESTREAM_H_
|
||||
#ifndef RAPIDJSON_FILEWRITESTREAM_H_
|
||||
#define RAPIDJSON_FILEWRITESTREAM_H_
|
||||
|
||||
#include "stream.h"
|
||||
#include <cstdio>
|
||||
|
||||
#ifdef __clang__
|
||||
CEREAL_RAPIDJSON_DIAG_PUSH
|
||||
CEREAL_RAPIDJSON_DIAG_OFF(unreachable-code)
|
||||
RAPIDJSON_DIAG_PUSH
|
||||
RAPIDJSON_DIAG_OFF(unreachable-code)
|
||||
#endif
|
||||
|
||||
CEREAL_RAPIDJSON_NAMESPACE_BEGIN
|
||||
RAPIDJSON_NAMESPACE_BEGIN
|
||||
|
||||
//! Wrapper of C file stream for input using fread().
|
||||
//! Wrapper of C file stream for output using fwrite().
|
||||
/*!
|
||||
\note implements Stream concept
|
||||
*/
|
||||
@ -34,7 +34,7 @@ public:
|
||||
typedef char Ch; //!< Character type. Only support char.
|
||||
|
||||
FileWriteStream(std::FILE* fp, char* buffer, size_t bufferSize) : fp_(fp), buffer_(buffer), bufferEnd_(buffer + bufferSize), current_(buffer_) {
|
||||
CEREAL_RAPIDJSON_ASSERT(fp_ != 0);
|
||||
RAPIDJSON_ASSERT(fp_ != 0);
|
||||
}
|
||||
|
||||
void Put(char c) {
|
||||
@ -62,7 +62,7 @@ public:
|
||||
|
||||
void Flush() {
|
||||
if (current_ != buffer_) {
|
||||
size_t result = fwrite(buffer_, 1, static_cast<size_t>(current_ - buffer_), fp_);
|
||||
size_t result = std::fwrite(buffer_, 1, static_cast<size_t>(current_ - buffer_), fp_);
|
||||
if (result < static_cast<size_t>(current_ - buffer_)) {
|
||||
// failure deliberately ignored at this time
|
||||
// added to avoid warn_unused_result build errors
|
||||
@ -72,11 +72,11 @@ public:
|
||||
}
|
||||
|
||||
// Not implemented
|
||||
char Peek() const { CEREAL_RAPIDJSON_ASSERT(false); return 0; }
|
||||
char Take() { CEREAL_RAPIDJSON_ASSERT(false); return 0; }
|
||||
size_t Tell() const { CEREAL_RAPIDJSON_ASSERT(false); return 0; }
|
||||
char* PutBegin() { CEREAL_RAPIDJSON_ASSERT(false); return 0; }
|
||||
size_t PutEnd(char*) { CEREAL_RAPIDJSON_ASSERT(false); return 0; }
|
||||
char Peek() const { RAPIDJSON_ASSERT(false); return 0; }
|
||||
char Take() { RAPIDJSON_ASSERT(false); return 0; }
|
||||
size_t Tell() const { RAPIDJSON_ASSERT(false); return 0; }
|
||||
char* PutBegin() { RAPIDJSON_ASSERT(false); return 0; }
|
||||
size_t PutEnd(char*) { RAPIDJSON_ASSERT(false); return 0; }
|
||||
|
||||
private:
|
||||
// Prohibit copy constructor & assignment operator.
|
||||
@ -95,10 +95,10 @@ inline void PutN(FileWriteStream& stream, char c, size_t n) {
|
||||
stream.PutN(c, n);
|
||||
}
|
||||
|
||||
CEREAL_RAPIDJSON_NAMESPACE_END
|
||||
RAPIDJSON_NAMESPACE_END
|
||||
|
||||
#ifdef __clang__
|
||||
CEREAL_RAPIDJSON_DIAG_POP
|
||||
RAPIDJSON_DIAG_POP
|
||||
#endif
|
||||
|
||||
#endif // CEREAL_RAPIDJSON_FILESTREAM_H_
|
||||
#endif // RAPIDJSON_FILESTREAM_H_
|
||||
|
14
external/cereal/external/rapidjson/fwd.h
vendored
14
external/cereal/external/rapidjson/fwd.h
vendored
@ -1,6 +1,6 @@
|
||||
// Tencent is pleased to support the open source community by making RapidJSON available.
|
||||
//
|
||||
// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
|
||||
// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip.
|
||||
//
|
||||
// Licensed under the MIT License (the "License"); you may not use this file except
|
||||
// in compliance with the License. You may obtain a copy of the License at
|
||||
@ -12,12 +12,12 @@
|
||||
// CONDITIONS OF ANY KIND, either express or implied. See the License for the
|
||||
// specific language governing permissions and limitations under the License.
|
||||
|
||||
#ifndef CEREAL_RAPIDJSON_FWD_H_
|
||||
#define CEREAL_RAPIDJSON_FWD_H_
|
||||
#ifndef RAPIDJSON_FWD_H_
|
||||
#define RAPIDJSON_FWD_H_
|
||||
|
||||
#include "rapidjson.h"
|
||||
|
||||
CEREAL_RAPIDJSON_NAMESPACE_BEGIN
|
||||
RAPIDJSON_NAMESPACE_BEGIN
|
||||
|
||||
// encodings.h
|
||||
|
||||
@ -102,7 +102,7 @@ class PrettyWriter;
|
||||
// document.h
|
||||
|
||||
template <typename Encoding, typename Allocator>
|
||||
struct GenericMember;
|
||||
class GenericMember;
|
||||
|
||||
template <bool Const, typename Encoding, typename Allocator>
|
||||
class GenericMemberIterator;
|
||||
@ -146,6 +146,6 @@ class GenericSchemaValidator;
|
||||
|
||||
typedef GenericSchemaValidator<SchemaDocument, BaseReaderHandler<UTF8<char>, void>, CrtAllocator> SchemaValidator;
|
||||
|
||||
CEREAL_RAPIDJSON_NAMESPACE_END
|
||||
RAPIDJSON_NAMESPACE_END
|
||||
|
||||
#endif // CEREAL_RAPIDJSON_RAPIDJSONFWD_H_
|
||||
#endif // RAPIDJSON_RAPIDJSONFWD_H_
|
||||
|
@ -1,6 +1,6 @@
|
||||
// Tencent is pleased to support the open source community by making RapidJSON available.
|
||||
//
|
||||
// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
|
||||
// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip.
|
||||
//
|
||||
// Licensed under the MIT License (the "License"); you may not use this file except
|
||||
// in compliance with the License. You may obtain a copy of the License at
|
||||
@ -12,17 +12,21 @@
|
||||
// CONDITIONS OF ANY KIND, either express or implied. See the License for the
|
||||
// specific language governing permissions and limitations under the License.
|
||||
|
||||
#ifndef CEREAL_RAPIDJSON_BIGINTEGER_H_
|
||||
#define CEREAL_RAPIDJSON_BIGINTEGER_H_
|
||||
#ifndef RAPIDJSON_BIGINTEGER_H_
|
||||
#define RAPIDJSON_BIGINTEGER_H_
|
||||
|
||||
#include "../rapidjson.h"
|
||||
|
||||
#if defined(_MSC_VER) && defined(_M_AMD64)
|
||||
#if defined(_MSC_VER) && !defined(__INTEL_COMPILER) && defined(_M_AMD64)
|
||||
#include <intrin.h> // for _umul128
|
||||
#if !defined(_ARM64EC_)
|
||||
#pragma intrinsic(_umul128)
|
||||
#else
|
||||
#pragma comment(lib,"softintrin")
|
||||
#endif
|
||||
#endif
|
||||
|
||||
CEREAL_RAPIDJSON_NAMESPACE_BEGIN
|
||||
RAPIDJSON_NAMESPACE_BEGIN
|
||||
namespace internal {
|
||||
|
||||
class BigInteger {
|
||||
@ -37,8 +41,9 @@ public:
|
||||
digits_[0] = u;
|
||||
}
|
||||
|
||||
BigInteger(const char* decimals, size_t length) : count_(1) {
|
||||
CEREAL_RAPIDJSON_ASSERT(length > 0);
|
||||
template<typename Ch>
|
||||
BigInteger(const Ch* decimals, size_t length) : count_(1) {
|
||||
RAPIDJSON_ASSERT(length > 0);
|
||||
digits_[0] = 0;
|
||||
size_t i = 0;
|
||||
const size_t kMaxDigitPerIteration = 19; // 2^64 = 18446744073709551616 > 10^19
|
||||
@ -130,10 +135,10 @@ public:
|
||||
|
||||
size_t offset = shift / kTypeBit;
|
||||
size_t interShift = shift % kTypeBit;
|
||||
CEREAL_RAPIDJSON_ASSERT(count_ + offset <= kCapacity);
|
||||
RAPIDJSON_ASSERT(count_ + offset <= kCapacity);
|
||||
|
||||
if (interShift == 0) {
|
||||
std::memmove(&digits_[count_ - 1 + offset], &digits_[count_ - 1], count_ * sizeof(Type));
|
||||
std::memmove(digits_ + offset, digits_, count_ * sizeof(Type));
|
||||
count_ += offset;
|
||||
}
|
||||
else {
|
||||
@ -175,7 +180,7 @@ public:
|
||||
5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5
|
||||
};
|
||||
if (exp == 0) return *this;
|
||||
for (; exp >= 27; exp -= 27) *this *= CEREAL_RAPIDJSON_UINT64_C2(0X6765C793, 0XFA10079D); // 5^27
|
||||
for (; exp >= 27; exp -= 27) *this *= RAPIDJSON_UINT64_C2(0X6765C793, 0XFA10079D); // 5^27
|
||||
for (; exp >= 13; exp -= 13) *this *= static_cast<uint32_t>(1220703125u); // 5^13
|
||||
if (exp > 0) *this *= kPow5[exp - 1];
|
||||
return *this;
|
||||
@ -185,7 +190,7 @@ public:
|
||||
// Assume this != rhs
|
||||
bool Difference(const BigInteger& rhs, BigInteger* out) const {
|
||||
int cmp = Compare(rhs);
|
||||
CEREAL_RAPIDJSON_ASSERT(cmp != 0);
|
||||
RAPIDJSON_ASSERT(cmp != 0);
|
||||
const BigInteger *a, *b; // Makes a > b
|
||||
bool ret;
|
||||
if (cmp < 0) { a = &rhs; b = this; ret = true; }
|
||||
@ -217,11 +222,12 @@ public:
|
||||
}
|
||||
|
||||
size_t GetCount() const { return count_; }
|
||||
Type GetDigit(size_t index) const { CEREAL_RAPIDJSON_ASSERT(index < count_); return digits_[index]; }
|
||||
Type GetDigit(size_t index) const { RAPIDJSON_ASSERT(index < count_); return digits_[index]; }
|
||||
bool IsZero() const { return count_ == 1 && digits_[0] == 0; }
|
||||
|
||||
private:
|
||||
void AppendDecimal64(const char* begin, const char* end) {
|
||||
template<typename Ch>
|
||||
void AppendDecimal64(const Ch* begin, const Ch* end) {
|
||||
uint64_t u = ParseUint64(begin, end);
|
||||
if (IsZero())
|
||||
*this = u;
|
||||
@ -232,15 +238,16 @@ private:
|
||||
}
|
||||
|
||||
void PushBack(Type digit) {
|
||||
CEREAL_RAPIDJSON_ASSERT(count_ < kCapacity);
|
||||
RAPIDJSON_ASSERT(count_ < kCapacity);
|
||||
digits_[count_++] = digit;
|
||||
}
|
||||
|
||||
static uint64_t ParseUint64(const char* begin, const char* end) {
|
||||
template<typename Ch>
|
||||
static uint64_t ParseUint64(const Ch* begin, const Ch* end) {
|
||||
uint64_t r = 0;
|
||||
for (const char* p = begin; p != end; ++p) {
|
||||
CEREAL_RAPIDJSON_ASSERT(*p >= '0' && *p <= '9');
|
||||
r = r * 10u + static_cast<unsigned>(*p - '0');
|
||||
for (const Ch* p = begin; p != end; ++p) {
|
||||
RAPIDJSON_ASSERT(*p >= Ch('0') && *p <= Ch('9'));
|
||||
r = r * 10u + static_cast<unsigned>(*p - Ch('0'));
|
||||
}
|
||||
return r;
|
||||
}
|
||||
@ -285,6 +292,6 @@ private:
|
||||
};
|
||||
|
||||
} // namespace internal
|
||||
CEREAL_RAPIDJSON_NAMESPACE_END
|
||||
RAPIDJSON_NAMESPACE_END
|
||||
|
||||
#endif // CEREAL_RAPIDJSON_BIGINTEGER_H_
|
||||
#endif // RAPIDJSON_BIGINTEGER_H_
|
||||
|
71
external/cereal/external/rapidjson/internal/clzll.h
vendored
Normal file
71
external/cereal/external/rapidjson/internal/clzll.h
vendored
Normal file
@ -0,0 +1,71 @@
|
||||
// Tencent is pleased to support the open source community by making RapidJSON available.
|
||||
//
|
||||
// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip.
|
||||
//
|
||||
// Licensed under the MIT License (the "License"); you may not use this file except
|
||||
// in compliance with the License. You may obtain a copy of the License at
|
||||
//
|
||||
// http://opensource.org/licenses/MIT
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software distributed
|
||||
// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
|
||||
// CONDITIONS OF ANY KIND, either express or implied. See the License for the
|
||||
// specific language governing permissions and limitations under the License.
|
||||
|
||||
#ifndef RAPIDJSON_CLZLL_H_
|
||||
#define RAPIDJSON_CLZLL_H_
|
||||
|
||||
#include "../rapidjson.h"
|
||||
|
||||
#if defined(_MSC_VER) && !defined(UNDER_CE)
|
||||
#include <intrin.h>
|
||||
#if defined(_WIN64)
|
||||
#pragma intrinsic(_BitScanReverse64)
|
||||
#else
|
||||
#pragma intrinsic(_BitScanReverse)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
RAPIDJSON_NAMESPACE_BEGIN
|
||||
namespace internal {
|
||||
|
||||
inline uint32_t clzll(uint64_t x) {
|
||||
// Passing 0 to __builtin_clzll is UB in GCC and results in an
|
||||
// infinite loop in the software implementation.
|
||||
RAPIDJSON_ASSERT(x != 0);
|
||||
|
||||
#if defined(_MSC_VER) && !defined(UNDER_CE)
|
||||
unsigned long r = 0;
|
||||
#if defined(_WIN64)
|
||||
_BitScanReverse64(&r, x);
|
||||
#else
|
||||
// Scan the high 32 bits.
|
||||
if (_BitScanReverse(&r, static_cast<uint32_t>(x >> 32)))
|
||||
return 63 - (r + 32);
|
||||
|
||||
// Scan the low 32 bits.
|
||||
_BitScanReverse(&r, static_cast<uint32_t>(x & 0xFFFFFFFF));
|
||||
#endif // _WIN64
|
||||
|
||||
return 63 - r;
|
||||
#elif (defined(__GNUC__) && __GNUC__ >= 4) || RAPIDJSON_HAS_BUILTIN(__builtin_clzll)
|
||||
// __builtin_clzll wrapper
|
||||
return static_cast<uint32_t>(__builtin_clzll(x));
|
||||
#else
|
||||
// naive version
|
||||
uint32_t r = 0;
|
||||
while (!(x & (static_cast<uint64_t>(1) << 63))) {
|
||||
x <<= 1;
|
||||
++r;
|
||||
}
|
||||
|
||||
return r;
|
||||
#endif // _MSC_VER
|
||||
}
|
||||
|
||||
#define RAPIDJSON_CLZLL RAPIDJSON_NAMESPACE::internal::clzll
|
||||
|
||||
} // namespace internal
|
||||
RAPIDJSON_NAMESPACE_END
|
||||
|
||||
#endif // RAPIDJSON_CLZLL_H_
|
177
external/cereal/external/rapidjson/internal/diyfp.h
vendored
177
external/cereal/external/rapidjson/internal/diyfp.h
vendored
@ -1,43 +1,48 @@
|
||||
// Tencent is pleased to support the open source community by making RapidJSON available.
|
||||
//
|
||||
// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
|
||||
//
|
||||
// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip.
|
||||
//
|
||||
// Licensed under the MIT License (the "License"); you may not use this file except
|
||||
// in compliance with the License. You may obtain a copy of the License at
|
||||
//
|
||||
// http://opensource.org/licenses/MIT
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software distributed
|
||||
// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
|
||||
// CONDITIONS OF ANY KIND, either express or implied. See the License for the
|
||||
// Unless required by applicable law or agreed to in writing, software distributed
|
||||
// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
|
||||
// CONDITIONS OF ANY KIND, either express or implied. See the License for the
|
||||
// specific language governing permissions and limitations under the License.
|
||||
|
||||
// This is a C++ header-only implementation of Grisu2 algorithm from the publication:
|
||||
// Loitsch, Florian. "Printing floating-point numbers quickly and accurately with
|
||||
// integers." ACM Sigplan Notices 45.6 (2010): 233-243.
|
||||
|
||||
#ifndef CEREAL_RAPIDJSON_DIYFP_H_
|
||||
#define CEREAL_RAPIDJSON_DIYFP_H_
|
||||
#ifndef RAPIDJSON_DIYFP_H_
|
||||
#define RAPIDJSON_DIYFP_H_
|
||||
|
||||
#include "../rapidjson.h"
|
||||
#include "clzll.h"
|
||||
#include <limits>
|
||||
|
||||
#if defined(_MSC_VER) && defined(_M_AMD64)
|
||||
#if defined(_MSC_VER) && defined(_M_AMD64) && !defined(__INTEL_COMPILER)
|
||||
#include <intrin.h>
|
||||
#pragma intrinsic(_BitScanReverse64)
|
||||
#if !defined(_ARM64EC_)
|
||||
#pragma intrinsic(_umul128)
|
||||
#else
|
||||
#pragma comment(lib,"softintrin")
|
||||
#endif
|
||||
#endif
|
||||
|
||||
CEREAL_RAPIDJSON_NAMESPACE_BEGIN
|
||||
RAPIDJSON_NAMESPACE_BEGIN
|
||||
namespace internal {
|
||||
|
||||
#ifdef __GNUC__
|
||||
CEREAL_RAPIDJSON_DIAG_PUSH
|
||||
CEREAL_RAPIDJSON_DIAG_OFF(effc++)
|
||||
RAPIDJSON_DIAG_PUSH
|
||||
RAPIDJSON_DIAG_OFF(effc++)
|
||||
#endif
|
||||
|
||||
#ifdef __clang__
|
||||
CEREAL_RAPIDJSON_DIAG_PUSH
|
||||
CEREAL_RAPIDJSON_DIAG_OFF(padded)
|
||||
RAPIDJSON_DIAG_PUSH
|
||||
RAPIDJSON_DIAG_OFF(padded)
|
||||
#endif
|
||||
|
||||
struct DiyFp {
|
||||
@ -56,7 +61,7 @@ struct DiyFp {
|
||||
if (biased_e != 0) {
|
||||
f = significand + kDpHiddenBit;
|
||||
e = biased_e - kDpExponentBias;
|
||||
}
|
||||
}
|
||||
else {
|
||||
f = significand;
|
||||
e = kDpMinExponent + 1;
|
||||
@ -99,21 +104,8 @@ struct DiyFp {
|
||||
}
|
||||
|
||||
DiyFp Normalize() const {
|
||||
#if defined(_MSC_VER) && defined(_M_AMD64)
|
||||
unsigned long index;
|
||||
_BitScanReverse64(&index, f);
|
||||
return DiyFp(f << (63 - index), e - (63 - index));
|
||||
#elif defined(__GNUC__) && __GNUC__ >= 4
|
||||
int s = __builtin_clzll(f);
|
||||
int s = static_cast<int>(clzll(f));
|
||||
return DiyFp(f << s, e - s);
|
||||
#else
|
||||
DiyFp res = *this;
|
||||
while (!(res.f & (static_cast<uint64_t>(1) << 63))) {
|
||||
res.f <<= 1;
|
||||
res.e--;
|
||||
}
|
||||
return res;
|
||||
#endif
|
||||
}
|
||||
|
||||
DiyFp NormalizeBoundary() const {
|
||||
@ -141,7 +133,16 @@ struct DiyFp {
|
||||
double d;
|
||||
uint64_t u64;
|
||||
}u;
|
||||
const uint64_t be = (e == kDpDenormalExponent && (f & kDpHiddenBit) == 0) ? 0 :
|
||||
RAPIDJSON_ASSERT(f <= kDpHiddenBit + kDpSignificandMask);
|
||||
if (e < kDpDenormalExponent) {
|
||||
// Underflow.
|
||||
return 0.0;
|
||||
}
|
||||
if (e >= kDpMaxExponent) {
|
||||
// Overflow.
|
||||
return std::numeric_limits<double>::infinity();
|
||||
}
|
||||
const uint64_t be = (e == kDpDenormalExponent && (f & kDpHiddenBit) == 0) ? 0 :
|
||||
static_cast<uint64_t>(e + kDpExponentBias);
|
||||
u.u64 = (f & kDpSignificandMask) | (be << kDpSignificandSize);
|
||||
return u.d;
|
||||
@ -153,9 +154,9 @@ struct DiyFp {
|
||||
static const int kDpMaxExponent = 0x7FF - kDpExponentBias;
|
||||
static const int kDpMinExponent = -kDpExponentBias;
|
||||
static const int kDpDenormalExponent = -kDpExponentBias + 1;
|
||||
static const uint64_t kDpExponentMask = CEREAL_RAPIDJSON_UINT64_C2(0x7FF00000, 0x00000000);
|
||||
static const uint64_t kDpSignificandMask = CEREAL_RAPIDJSON_UINT64_C2(0x000FFFFF, 0xFFFFFFFF);
|
||||
static const uint64_t kDpHiddenBit = CEREAL_RAPIDJSON_UINT64_C2(0x00100000, 0x00000000);
|
||||
static const uint64_t kDpExponentMask = RAPIDJSON_UINT64_C2(0x7FF00000, 0x00000000);
|
||||
static const uint64_t kDpSignificandMask = RAPIDJSON_UINT64_C2(0x000FFFFF, 0xFFFFFFFF);
|
||||
static const uint64_t kDpHiddenBit = RAPIDJSON_UINT64_C2(0x00100000, 0x00000000);
|
||||
|
||||
uint64_t f;
|
||||
int e;
|
||||
@ -164,50 +165,50 @@ struct DiyFp {
|
||||
inline DiyFp GetCachedPowerByIndex(size_t index) {
|
||||
// 10^-348, 10^-340, ..., 10^340
|
||||
static const uint64_t kCachedPowers_F[] = {
|
||||
CEREAL_RAPIDJSON_UINT64_C2(0xfa8fd5a0, 0x081c0288), CEREAL_RAPIDJSON_UINT64_C2(0xbaaee17f, 0xa23ebf76),
|
||||
CEREAL_RAPIDJSON_UINT64_C2(0x8b16fb20, 0x3055ac76), CEREAL_RAPIDJSON_UINT64_C2(0xcf42894a, 0x5dce35ea),
|
||||
CEREAL_RAPIDJSON_UINT64_C2(0x9a6bb0aa, 0x55653b2d), CEREAL_RAPIDJSON_UINT64_C2(0xe61acf03, 0x3d1a45df),
|
||||
CEREAL_RAPIDJSON_UINT64_C2(0xab70fe17, 0xc79ac6ca), CEREAL_RAPIDJSON_UINT64_C2(0xff77b1fc, 0xbebcdc4f),
|
||||
CEREAL_RAPIDJSON_UINT64_C2(0xbe5691ef, 0x416bd60c), CEREAL_RAPIDJSON_UINT64_C2(0x8dd01fad, 0x907ffc3c),
|
||||
CEREAL_RAPIDJSON_UINT64_C2(0xd3515c28, 0x31559a83), CEREAL_RAPIDJSON_UINT64_C2(0x9d71ac8f, 0xada6c9b5),
|
||||
CEREAL_RAPIDJSON_UINT64_C2(0xea9c2277, 0x23ee8bcb), CEREAL_RAPIDJSON_UINT64_C2(0xaecc4991, 0x4078536d),
|
||||
CEREAL_RAPIDJSON_UINT64_C2(0x823c1279, 0x5db6ce57), CEREAL_RAPIDJSON_UINT64_C2(0xc2109436, 0x4dfb5637),
|
||||
CEREAL_RAPIDJSON_UINT64_C2(0x9096ea6f, 0x3848984f), CEREAL_RAPIDJSON_UINT64_C2(0xd77485cb, 0x25823ac7),
|
||||
CEREAL_RAPIDJSON_UINT64_C2(0xa086cfcd, 0x97bf97f4), CEREAL_RAPIDJSON_UINT64_C2(0xef340a98, 0x172aace5),
|
||||
CEREAL_RAPIDJSON_UINT64_C2(0xb23867fb, 0x2a35b28e), CEREAL_RAPIDJSON_UINT64_C2(0x84c8d4df, 0xd2c63f3b),
|
||||
CEREAL_RAPIDJSON_UINT64_C2(0xc5dd4427, 0x1ad3cdba), CEREAL_RAPIDJSON_UINT64_C2(0x936b9fce, 0xbb25c996),
|
||||
CEREAL_RAPIDJSON_UINT64_C2(0xdbac6c24, 0x7d62a584), CEREAL_RAPIDJSON_UINT64_C2(0xa3ab6658, 0x0d5fdaf6),
|
||||
CEREAL_RAPIDJSON_UINT64_C2(0xf3e2f893, 0xdec3f126), CEREAL_RAPIDJSON_UINT64_C2(0xb5b5ada8, 0xaaff80b8),
|
||||
CEREAL_RAPIDJSON_UINT64_C2(0x87625f05, 0x6c7c4a8b), CEREAL_RAPIDJSON_UINT64_C2(0xc9bcff60, 0x34c13053),
|
||||
CEREAL_RAPIDJSON_UINT64_C2(0x964e858c, 0x91ba2655), CEREAL_RAPIDJSON_UINT64_C2(0xdff97724, 0x70297ebd),
|
||||
CEREAL_RAPIDJSON_UINT64_C2(0xa6dfbd9f, 0xb8e5b88f), CEREAL_RAPIDJSON_UINT64_C2(0xf8a95fcf, 0x88747d94),
|
||||
CEREAL_RAPIDJSON_UINT64_C2(0xb9447093, 0x8fa89bcf), CEREAL_RAPIDJSON_UINT64_C2(0x8a08f0f8, 0xbf0f156b),
|
||||
CEREAL_RAPIDJSON_UINT64_C2(0xcdb02555, 0x653131b6), CEREAL_RAPIDJSON_UINT64_C2(0x993fe2c6, 0xd07b7fac),
|
||||
CEREAL_RAPIDJSON_UINT64_C2(0xe45c10c4, 0x2a2b3b06), CEREAL_RAPIDJSON_UINT64_C2(0xaa242499, 0x697392d3),
|
||||
CEREAL_RAPIDJSON_UINT64_C2(0xfd87b5f2, 0x8300ca0e), CEREAL_RAPIDJSON_UINT64_C2(0xbce50864, 0x92111aeb),
|
||||
CEREAL_RAPIDJSON_UINT64_C2(0x8cbccc09, 0x6f5088cc), CEREAL_RAPIDJSON_UINT64_C2(0xd1b71758, 0xe219652c),
|
||||
CEREAL_RAPIDJSON_UINT64_C2(0x9c400000, 0x00000000), CEREAL_RAPIDJSON_UINT64_C2(0xe8d4a510, 0x00000000),
|
||||
CEREAL_RAPIDJSON_UINT64_C2(0xad78ebc5, 0xac620000), CEREAL_RAPIDJSON_UINT64_C2(0x813f3978, 0xf8940984),
|
||||
CEREAL_RAPIDJSON_UINT64_C2(0xc097ce7b, 0xc90715b3), CEREAL_RAPIDJSON_UINT64_C2(0x8f7e32ce, 0x7bea5c70),
|
||||
CEREAL_RAPIDJSON_UINT64_C2(0xd5d238a4, 0xabe98068), CEREAL_RAPIDJSON_UINT64_C2(0x9f4f2726, 0x179a2245),
|
||||
CEREAL_RAPIDJSON_UINT64_C2(0xed63a231, 0xd4c4fb27), CEREAL_RAPIDJSON_UINT64_C2(0xb0de6538, 0x8cc8ada8),
|
||||
CEREAL_RAPIDJSON_UINT64_C2(0x83c7088e, 0x1aab65db), CEREAL_RAPIDJSON_UINT64_C2(0xc45d1df9, 0x42711d9a),
|
||||
CEREAL_RAPIDJSON_UINT64_C2(0x924d692c, 0xa61be758), CEREAL_RAPIDJSON_UINT64_C2(0xda01ee64, 0x1a708dea),
|
||||
CEREAL_RAPIDJSON_UINT64_C2(0xa26da399, 0x9aef774a), CEREAL_RAPIDJSON_UINT64_C2(0xf209787b, 0xb47d6b85),
|
||||
CEREAL_RAPIDJSON_UINT64_C2(0xb454e4a1, 0x79dd1877), CEREAL_RAPIDJSON_UINT64_C2(0x865b8692, 0x5b9bc5c2),
|
||||
CEREAL_RAPIDJSON_UINT64_C2(0xc83553c5, 0xc8965d3d), CEREAL_RAPIDJSON_UINT64_C2(0x952ab45c, 0xfa97a0b3),
|
||||
CEREAL_RAPIDJSON_UINT64_C2(0xde469fbd, 0x99a05fe3), CEREAL_RAPIDJSON_UINT64_C2(0xa59bc234, 0xdb398c25),
|
||||
CEREAL_RAPIDJSON_UINT64_C2(0xf6c69a72, 0xa3989f5c), CEREAL_RAPIDJSON_UINT64_C2(0xb7dcbf53, 0x54e9bece),
|
||||
CEREAL_RAPIDJSON_UINT64_C2(0x88fcf317, 0xf22241e2), CEREAL_RAPIDJSON_UINT64_C2(0xcc20ce9b, 0xd35c78a5),
|
||||
CEREAL_RAPIDJSON_UINT64_C2(0x98165af3, 0x7b2153df), CEREAL_RAPIDJSON_UINT64_C2(0xe2a0b5dc, 0x971f303a),
|
||||
CEREAL_RAPIDJSON_UINT64_C2(0xa8d9d153, 0x5ce3b396), CEREAL_RAPIDJSON_UINT64_C2(0xfb9b7cd9, 0xa4a7443c),
|
||||
CEREAL_RAPIDJSON_UINT64_C2(0xbb764c4c, 0xa7a44410), CEREAL_RAPIDJSON_UINT64_C2(0x8bab8eef, 0xb6409c1a),
|
||||
CEREAL_RAPIDJSON_UINT64_C2(0xd01fef10, 0xa657842c), CEREAL_RAPIDJSON_UINT64_C2(0x9b10a4e5, 0xe9913129),
|
||||
CEREAL_RAPIDJSON_UINT64_C2(0xe7109bfb, 0xa19c0c9d), CEREAL_RAPIDJSON_UINT64_C2(0xac2820d9, 0x623bf429),
|
||||
CEREAL_RAPIDJSON_UINT64_C2(0x80444b5e, 0x7aa7cf85), CEREAL_RAPIDJSON_UINT64_C2(0xbf21e440, 0x03acdd2d),
|
||||
CEREAL_RAPIDJSON_UINT64_C2(0x8e679c2f, 0x5e44ff8f), CEREAL_RAPIDJSON_UINT64_C2(0xd433179d, 0x9c8cb841),
|
||||
CEREAL_RAPIDJSON_UINT64_C2(0x9e19db92, 0xb4e31ba9), CEREAL_RAPIDJSON_UINT64_C2(0xeb96bf6e, 0xbadf77d9),
|
||||
CEREAL_RAPIDJSON_UINT64_C2(0xaf87023b, 0x9bf0ee6b)
|
||||
RAPIDJSON_UINT64_C2(0xfa8fd5a0, 0x081c0288), RAPIDJSON_UINT64_C2(0xbaaee17f, 0xa23ebf76),
|
||||
RAPIDJSON_UINT64_C2(0x8b16fb20, 0x3055ac76), RAPIDJSON_UINT64_C2(0xcf42894a, 0x5dce35ea),
|
||||
RAPIDJSON_UINT64_C2(0x9a6bb0aa, 0x55653b2d), RAPIDJSON_UINT64_C2(0xe61acf03, 0x3d1a45df),
|
||||
RAPIDJSON_UINT64_C2(0xab70fe17, 0xc79ac6ca), RAPIDJSON_UINT64_C2(0xff77b1fc, 0xbebcdc4f),
|
||||
RAPIDJSON_UINT64_C2(0xbe5691ef, 0x416bd60c), RAPIDJSON_UINT64_C2(0x8dd01fad, 0x907ffc3c),
|
||||
RAPIDJSON_UINT64_C2(0xd3515c28, 0x31559a83), RAPIDJSON_UINT64_C2(0x9d71ac8f, 0xada6c9b5),
|
||||
RAPIDJSON_UINT64_C2(0xea9c2277, 0x23ee8bcb), RAPIDJSON_UINT64_C2(0xaecc4991, 0x4078536d),
|
||||
RAPIDJSON_UINT64_C2(0x823c1279, 0x5db6ce57), RAPIDJSON_UINT64_C2(0xc2109436, 0x4dfb5637),
|
||||
RAPIDJSON_UINT64_C2(0x9096ea6f, 0x3848984f), RAPIDJSON_UINT64_C2(0xd77485cb, 0x25823ac7),
|
||||
RAPIDJSON_UINT64_C2(0xa086cfcd, 0x97bf97f4), RAPIDJSON_UINT64_C2(0xef340a98, 0x172aace5),
|
||||
RAPIDJSON_UINT64_C2(0xb23867fb, 0x2a35b28e), RAPIDJSON_UINT64_C2(0x84c8d4df, 0xd2c63f3b),
|
||||
RAPIDJSON_UINT64_C2(0xc5dd4427, 0x1ad3cdba), RAPIDJSON_UINT64_C2(0x936b9fce, 0xbb25c996),
|
||||
RAPIDJSON_UINT64_C2(0xdbac6c24, 0x7d62a584), RAPIDJSON_UINT64_C2(0xa3ab6658, 0x0d5fdaf6),
|
||||
RAPIDJSON_UINT64_C2(0xf3e2f893, 0xdec3f126), RAPIDJSON_UINT64_C2(0xb5b5ada8, 0xaaff80b8),
|
||||
RAPIDJSON_UINT64_C2(0x87625f05, 0x6c7c4a8b), RAPIDJSON_UINT64_C2(0xc9bcff60, 0x34c13053),
|
||||
RAPIDJSON_UINT64_C2(0x964e858c, 0x91ba2655), RAPIDJSON_UINT64_C2(0xdff97724, 0x70297ebd),
|
||||
RAPIDJSON_UINT64_C2(0xa6dfbd9f, 0xb8e5b88f), RAPIDJSON_UINT64_C2(0xf8a95fcf, 0x88747d94),
|
||||
RAPIDJSON_UINT64_C2(0xb9447093, 0x8fa89bcf), RAPIDJSON_UINT64_C2(0x8a08f0f8, 0xbf0f156b),
|
||||
RAPIDJSON_UINT64_C2(0xcdb02555, 0x653131b6), RAPIDJSON_UINT64_C2(0x993fe2c6, 0xd07b7fac),
|
||||
RAPIDJSON_UINT64_C2(0xe45c10c4, 0x2a2b3b06), RAPIDJSON_UINT64_C2(0xaa242499, 0x697392d3),
|
||||
RAPIDJSON_UINT64_C2(0xfd87b5f2, 0x8300ca0e), RAPIDJSON_UINT64_C2(0xbce50864, 0x92111aeb),
|
||||
RAPIDJSON_UINT64_C2(0x8cbccc09, 0x6f5088cc), RAPIDJSON_UINT64_C2(0xd1b71758, 0xe219652c),
|
||||
RAPIDJSON_UINT64_C2(0x9c400000, 0x00000000), RAPIDJSON_UINT64_C2(0xe8d4a510, 0x00000000),
|
||||
RAPIDJSON_UINT64_C2(0xad78ebc5, 0xac620000), RAPIDJSON_UINT64_C2(0x813f3978, 0xf8940984),
|
||||
RAPIDJSON_UINT64_C2(0xc097ce7b, 0xc90715b3), RAPIDJSON_UINT64_C2(0x8f7e32ce, 0x7bea5c70),
|
||||
RAPIDJSON_UINT64_C2(0xd5d238a4, 0xabe98068), RAPIDJSON_UINT64_C2(0x9f4f2726, 0x179a2245),
|
||||
RAPIDJSON_UINT64_C2(0xed63a231, 0xd4c4fb27), RAPIDJSON_UINT64_C2(0xb0de6538, 0x8cc8ada8),
|
||||
RAPIDJSON_UINT64_C2(0x83c7088e, 0x1aab65db), RAPIDJSON_UINT64_C2(0xc45d1df9, 0x42711d9a),
|
||||
RAPIDJSON_UINT64_C2(0x924d692c, 0xa61be758), RAPIDJSON_UINT64_C2(0xda01ee64, 0x1a708dea),
|
||||
RAPIDJSON_UINT64_C2(0xa26da399, 0x9aef774a), RAPIDJSON_UINT64_C2(0xf209787b, 0xb47d6b85),
|
||||
RAPIDJSON_UINT64_C2(0xb454e4a1, 0x79dd1877), RAPIDJSON_UINT64_C2(0x865b8692, 0x5b9bc5c2),
|
||||
RAPIDJSON_UINT64_C2(0xc83553c5, 0xc8965d3d), RAPIDJSON_UINT64_C2(0x952ab45c, 0xfa97a0b3),
|
||||
RAPIDJSON_UINT64_C2(0xde469fbd, 0x99a05fe3), RAPIDJSON_UINT64_C2(0xa59bc234, 0xdb398c25),
|
||||
RAPIDJSON_UINT64_C2(0xf6c69a72, 0xa3989f5c), RAPIDJSON_UINT64_C2(0xb7dcbf53, 0x54e9bece),
|
||||
RAPIDJSON_UINT64_C2(0x88fcf317, 0xf22241e2), RAPIDJSON_UINT64_C2(0xcc20ce9b, 0xd35c78a5),
|
||||
RAPIDJSON_UINT64_C2(0x98165af3, 0x7b2153df), RAPIDJSON_UINT64_C2(0xe2a0b5dc, 0x971f303a),
|
||||
RAPIDJSON_UINT64_C2(0xa8d9d153, 0x5ce3b396), RAPIDJSON_UINT64_C2(0xfb9b7cd9, 0xa4a7443c),
|
||||
RAPIDJSON_UINT64_C2(0xbb764c4c, 0xa7a44410), RAPIDJSON_UINT64_C2(0x8bab8eef, 0xb6409c1a),
|
||||
RAPIDJSON_UINT64_C2(0xd01fef10, 0xa657842c), RAPIDJSON_UINT64_C2(0x9b10a4e5, 0xe9913129),
|
||||
RAPIDJSON_UINT64_C2(0xe7109bfb, 0xa19c0c9d), RAPIDJSON_UINT64_C2(0xac2820d9, 0x623bf429),
|
||||
RAPIDJSON_UINT64_C2(0x80444b5e, 0x7aa7cf85), RAPIDJSON_UINT64_C2(0xbf21e440, 0x03acdd2d),
|
||||
RAPIDJSON_UINT64_C2(0x8e679c2f, 0x5e44ff8f), RAPIDJSON_UINT64_C2(0xd433179d, 0x9c8cb841),
|
||||
RAPIDJSON_UINT64_C2(0x9e19db92, 0xb4e31ba9), RAPIDJSON_UINT64_C2(0xeb96bf6e, 0xbadf77d9),
|
||||
RAPIDJSON_UINT64_C2(0xaf87023b, 0x9bf0ee6b)
|
||||
};
|
||||
static const int16_t kCachedPowers_E[] = {
|
||||
-1220, -1193, -1166, -1140, -1113, -1087, -1060, -1034, -1007, -980,
|
||||
@ -220,9 +221,10 @@ inline DiyFp GetCachedPowerByIndex(size_t index) {
|
||||
641, 667, 694, 720, 747, 774, 800, 827, 853, 880,
|
||||
907, 933, 960, 986, 1013, 1039, 1066
|
||||
};
|
||||
RAPIDJSON_ASSERT(index < 87);
|
||||
return DiyFp(kCachedPowers_F[index], kCachedPowers_E[index]);
|
||||
}
|
||||
|
||||
|
||||
inline DiyFp GetCachedPower(int e, int* K) {
|
||||
|
||||
//int k = static_cast<int>(ceil((-61 - e) * 0.30102999566398114)) + 374;
|
||||
@ -238,21 +240,22 @@ inline DiyFp GetCachedPower(int e, int* K) {
|
||||
}
|
||||
|
||||
inline DiyFp GetCachedPower10(int exp, int *outExp) {
|
||||
unsigned index = (static_cast<unsigned>(exp) + 348u) / 8u;
|
||||
*outExp = -348 + static_cast<int>(index) * 8;
|
||||
return GetCachedPowerByIndex(index);
|
||||
}
|
||||
RAPIDJSON_ASSERT(exp >= -348);
|
||||
unsigned index = static_cast<unsigned>(exp + 348) / 8u;
|
||||
*outExp = -348 + static_cast<int>(index) * 8;
|
||||
return GetCachedPowerByIndex(index);
|
||||
}
|
||||
|
||||
#ifdef __GNUC__
|
||||
CEREAL_RAPIDJSON_DIAG_POP
|
||||
RAPIDJSON_DIAG_POP
|
||||
#endif
|
||||
|
||||
#ifdef __clang__
|
||||
CEREAL_RAPIDJSON_DIAG_POP
|
||||
CEREAL_RAPIDJSON_DIAG_OFF(padded)
|
||||
RAPIDJSON_DIAG_POP
|
||||
RAPIDJSON_DIAG_OFF(padded)
|
||||
#endif
|
||||
|
||||
} // namespace internal
|
||||
CEREAL_RAPIDJSON_NAMESPACE_END
|
||||
RAPIDJSON_NAMESPACE_END
|
||||
|
||||
#endif // CEREAL_RAPIDJSON_DIYFP_H_
|
||||
#endif // RAPIDJSON_DIYFP_H_
|
||||
|
@ -1,6 +1,6 @@
|
||||
// Tencent is pleased to support the open source community by making RapidJSON available.
|
||||
//
|
||||
// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
|
||||
// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip.
|
||||
//
|
||||
// Licensed under the MIT License (the "License"); you may not use this file except
|
||||
// in compliance with the License. You may obtain a copy of the License at
|
||||
@ -16,20 +16,20 @@
|
||||
// Loitsch, Florian. "Printing floating-point numbers quickly and accurately with
|
||||
// integers." ACM Sigplan Notices 45.6 (2010): 233-243.
|
||||
|
||||
#ifndef CEREAL_RAPIDJSON_DTOA_
|
||||
#define CEREAL_RAPIDJSON_DTOA_
|
||||
#ifndef RAPIDJSON_DTOA_
|
||||
#define RAPIDJSON_DTOA_
|
||||
|
||||
#include "itoa.h" // GetDigitsLut()
|
||||
#include "diyfp.h"
|
||||
#include "ieee754.h"
|
||||
|
||||
CEREAL_RAPIDJSON_NAMESPACE_BEGIN
|
||||
RAPIDJSON_NAMESPACE_BEGIN
|
||||
namespace internal {
|
||||
|
||||
#ifdef __GNUC__
|
||||
CEREAL_RAPIDJSON_DIAG_PUSH
|
||||
CEREAL_RAPIDJSON_DIAG_OFF(effc++)
|
||||
CEREAL_RAPIDJSON_DIAG_OFF(array-bounds) // some gcc versions generate wrong warnings https://gcc.gnu.org/bugzilla/show_bug.cgi?id=59124
|
||||
RAPIDJSON_DIAG_PUSH
|
||||
RAPIDJSON_DIAG_OFF(effc++)
|
||||
RAPIDJSON_DIAG_OFF(array-bounds) // some gcc versions generate wrong warnings https://gcc.gnu.org/bugzilla/show_bug.cgi?id=59124
|
||||
#endif
|
||||
|
||||
inline void GrisuRound(char* buffer, int len, uint64_t delta, uint64_t rest, uint64_t ten_kappa, uint64_t wp_w) {
|
||||
@ -41,7 +41,7 @@ inline void GrisuRound(char* buffer, int len, uint64_t delta, uint64_t rest, uin
|
||||
}
|
||||
}
|
||||
|
||||
inline unsigned CountDecimalDigit32(uint32_t n) {
|
||||
inline int CountDecimalDigit32(uint32_t n) {
|
||||
// Simple pure C++ implementation was faster than __builtin_clz version in this situation.
|
||||
if (n < 10) return 1;
|
||||
if (n < 100) return 2;
|
||||
@ -58,12 +58,16 @@ inline unsigned CountDecimalDigit32(uint32_t n) {
|
||||
}
|
||||
|
||||
inline void DigitGen(const DiyFp& W, const DiyFp& Mp, uint64_t delta, char* buffer, int* len, int* K) {
|
||||
static const uint32_t kPow10[] = { 1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000, 1000000000 };
|
||||
static const uint64_t kPow10[] = { 1ULL, 10ULL, 100ULL, 1000ULL, 10000ULL, 100000ULL, 1000000ULL, 10000000ULL, 100000000ULL,
|
||||
1000000000ULL, 10000000000ULL, 100000000000ULL, 1000000000000ULL,
|
||||
10000000000000ULL, 100000000000000ULL, 1000000000000000ULL,
|
||||
10000000000000000ULL, 100000000000000000ULL, 1000000000000000000ULL,
|
||||
10000000000000000000ULL };
|
||||
const DiyFp one(uint64_t(1) << -Mp.e, Mp.e);
|
||||
const DiyFp wp_w = Mp - W;
|
||||
uint32_t p1 = static_cast<uint32_t>(Mp.f >> -one.e);
|
||||
uint64_t p2 = Mp.f & (one.f - 1);
|
||||
unsigned kappa = CountDecimalDigit32(p1); // kappa in [0, 9]
|
||||
int kappa = CountDecimalDigit32(p1); // kappa in [0, 9]
|
||||
*len = 0;
|
||||
|
||||
while (kappa > 0) {
|
||||
@ -86,7 +90,7 @@ inline void DigitGen(const DiyFp& W, const DiyFp& Mp, uint64_t delta, char* buff
|
||||
uint64_t tmp = (static_cast<uint64_t>(p1) << -one.e) + p2;
|
||||
if (tmp <= delta) {
|
||||
*K += kappa;
|
||||
GrisuRound(buffer, *len, delta, tmp, static_cast<uint64_t>(kPow10[kappa]) << -one.e, wp_w.f);
|
||||
GrisuRound(buffer, *len, delta, tmp, kPow10[kappa] << -one.e, wp_w.f);
|
||||
return;
|
||||
}
|
||||
}
|
||||
@ -102,8 +106,8 @@ inline void DigitGen(const DiyFp& W, const DiyFp& Mp, uint64_t delta, char* buff
|
||||
kappa--;
|
||||
if (p2 < delta) {
|
||||
*K += kappa;
|
||||
int index = -static_cast<int>(kappa);
|
||||
GrisuRound(buffer, *len, delta, p2, one.f, wp_w.f * (index < 9 ? kPow10[-static_cast<int>(kappa)] : 0));
|
||||
int index = -kappa;
|
||||
GrisuRound(buffer, *len, delta, p2, one.f, wp_w.f * (index < 20 ? kPow10[index] : 0));
|
||||
return;
|
||||
}
|
||||
}
|
||||
@ -214,7 +218,7 @@ inline char* Prettify(char* buffer, int length, int k, int maxDecimalPlaces) {
|
||||
}
|
||||
|
||||
inline char* dtoa(double value, char* buffer, int maxDecimalPlaces = 324) {
|
||||
CEREAL_RAPIDJSON_ASSERT(maxDecimalPlaces >= 1);
|
||||
RAPIDJSON_ASSERT(maxDecimalPlaces >= 1);
|
||||
Double d(value);
|
||||
if (d.IsZero()) {
|
||||
if (d.Sign())
|
||||
@ -236,10 +240,10 @@ inline char* dtoa(double value, char* buffer, int maxDecimalPlaces = 324) {
|
||||
}
|
||||
|
||||
#ifdef __GNUC__
|
||||
CEREAL_RAPIDJSON_DIAG_POP
|
||||
RAPIDJSON_DIAG_POP
|
||||
#endif
|
||||
|
||||
} // namespace internal
|
||||
CEREAL_RAPIDJSON_NAMESPACE_END
|
||||
RAPIDJSON_NAMESPACE_END
|
||||
|
||||
#endif // CEREAL_RAPIDJSON_DTOA_
|
||||
#endif // RAPIDJSON_DTOA_
|
||||
|
@ -1,6 +1,6 @@
|
||||
// Tencent is pleased to support the open source community by making RapidJSON available.
|
||||
//
|
||||
// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
|
||||
// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip.
|
||||
//
|
||||
// Licensed under the MIT License (the "License"); you may not use this file except
|
||||
// in compliance with the License. You may obtain a copy of the License at
|
||||
@ -12,12 +12,12 @@
|
||||
// CONDITIONS OF ANY KIND, either express or implied. See the License for the
|
||||
// specific language governing permissions and limitations under the License.
|
||||
|
||||
#ifndef CEREAL_RAPIDJSON_IEEE754_
|
||||
#define CEREAL_RAPIDJSON_IEEE754_
|
||||
#ifndef RAPIDJSON_IEEE754_
|
||||
#define RAPIDJSON_IEEE754_
|
||||
|
||||
#include "../rapidjson.h"
|
||||
|
||||
CEREAL_RAPIDJSON_NAMESPACE_BEGIN
|
||||
RAPIDJSON_NAMESPACE_BEGIN
|
||||
namespace internal {
|
||||
|
||||
class Double {
|
||||
@ -30,7 +30,7 @@ public:
|
||||
uint64_t Uint64Value() const { return u_; }
|
||||
|
||||
double NextPositiveDouble() const {
|
||||
CEREAL_RAPIDJSON_ASSERT(!Sign());
|
||||
RAPIDJSON_ASSERT(!Sign());
|
||||
return Double(u_ + 1).Value();
|
||||
}
|
||||
|
||||
@ -48,23 +48,23 @@ public:
|
||||
int IntegerExponent() const { return (IsNormal() ? Exponent() : kDenormalExponent) - kSignificandSize; }
|
||||
uint64_t ToBias() const { return (u_ & kSignMask) ? ~u_ + 1 : u_ | kSignMask; }
|
||||
|
||||
static unsigned EffectiveSignificandSize(int order) {
|
||||
static int EffectiveSignificandSize(int order) {
|
||||
if (order >= -1021)
|
||||
return 53;
|
||||
else if (order <= -1074)
|
||||
return 0;
|
||||
else
|
||||
return static_cast<unsigned>(order) + 1074;
|
||||
return order + 1074;
|
||||
}
|
||||
|
||||
private:
|
||||
static const int kSignificandSize = 52;
|
||||
static const int kExponentBias = 0x3FF;
|
||||
static const int kDenormalExponent = 1 - kExponentBias;
|
||||
static const uint64_t kSignMask = CEREAL_RAPIDJSON_UINT64_C2(0x80000000, 0x00000000);
|
||||
static const uint64_t kExponentMask = CEREAL_RAPIDJSON_UINT64_C2(0x7FF00000, 0x00000000);
|
||||
static const uint64_t kSignificandMask = CEREAL_RAPIDJSON_UINT64_C2(0x000FFFFF, 0xFFFFFFFF);
|
||||
static const uint64_t kHiddenBit = CEREAL_RAPIDJSON_UINT64_C2(0x00100000, 0x00000000);
|
||||
static const uint64_t kSignMask = RAPIDJSON_UINT64_C2(0x80000000, 0x00000000);
|
||||
static const uint64_t kExponentMask = RAPIDJSON_UINT64_C2(0x7FF00000, 0x00000000);
|
||||
static const uint64_t kSignificandMask = RAPIDJSON_UINT64_C2(0x000FFFFF, 0xFFFFFFFF);
|
||||
static const uint64_t kHiddenBit = RAPIDJSON_UINT64_C2(0x00100000, 0x00000000);
|
||||
|
||||
union {
|
||||
double d_;
|
||||
@ -73,6 +73,6 @@ private:
|
||||
};
|
||||
|
||||
} // namespace internal
|
||||
CEREAL_RAPIDJSON_NAMESPACE_END
|
||||
RAPIDJSON_NAMESPACE_END
|
||||
|
||||
#endif // CEREAL_RAPIDJSON_IEEE754_
|
||||
#endif // RAPIDJSON_IEEE754_
|
||||
|
@ -1,23 +1,23 @@
|
||||
// Tencent is pleased to support the open source community by making RapidJSON available.
|
||||
//
|
||||
// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
|
||||
//
|
||||
// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip.
|
||||
//
|
||||
// Licensed under the MIT License (the "License"); you may not use this file except
|
||||
// in compliance with the License. You may obtain a copy of the License at
|
||||
//
|
||||
// http://opensource.org/licenses/MIT
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software distributed
|
||||
// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
|
||||
// CONDITIONS OF ANY KIND, either express or implied. See the License for the
|
||||
// Unless required by applicable law or agreed to in writing, software distributed
|
||||
// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
|
||||
// CONDITIONS OF ANY KIND, either express or implied. See the License for the
|
||||
// specific language governing permissions and limitations under the License.
|
||||
|
||||
#ifndef CEREAL_RAPIDJSON_ITOA_
|
||||
#define CEREAL_RAPIDJSON_ITOA_
|
||||
#ifndef RAPIDJSON_ITOA_
|
||||
#define RAPIDJSON_ITOA_
|
||||
|
||||
#include "../rapidjson.h"
|
||||
|
||||
CEREAL_RAPIDJSON_NAMESPACE_BEGIN
|
||||
RAPIDJSON_NAMESPACE_BEGIN
|
||||
namespace internal {
|
||||
|
||||
inline const char* GetDigitsLut() {
|
||||
@ -37,12 +37,14 @@ inline const char* GetDigitsLut() {
|
||||
}
|
||||
|
||||
inline char* u32toa(uint32_t value, char* buffer) {
|
||||
RAPIDJSON_ASSERT(buffer != 0);
|
||||
|
||||
const char* cDigitsLut = GetDigitsLut();
|
||||
|
||||
if (value < 10000) {
|
||||
const uint32_t d1 = (value / 100) << 1;
|
||||
const uint32_t d2 = (value % 100) << 1;
|
||||
|
||||
|
||||
if (value >= 1000)
|
||||
*buffer++ = cDigitsLut[d1];
|
||||
if (value >= 100)
|
||||
@ -55,13 +57,13 @@ inline char* u32toa(uint32_t value, char* buffer) {
|
||||
// value = bbbbcccc
|
||||
const uint32_t b = value / 10000;
|
||||
const uint32_t c = value % 10000;
|
||||
|
||||
|
||||
const uint32_t d1 = (b / 100) << 1;
|
||||
const uint32_t d2 = (b % 100) << 1;
|
||||
|
||||
|
||||
const uint32_t d3 = (c / 100) << 1;
|
||||
const uint32_t d4 = (c % 100) << 1;
|
||||
|
||||
|
||||
if (value >= 10000000)
|
||||
*buffer++ = cDigitsLut[d1];
|
||||
if (value >= 1000000)
|
||||
@ -69,7 +71,7 @@ inline char* u32toa(uint32_t value, char* buffer) {
|
||||
if (value >= 100000)
|
||||
*buffer++ = cDigitsLut[d2];
|
||||
*buffer++ = cDigitsLut[d2 + 1];
|
||||
|
||||
|
||||
*buffer++ = cDigitsLut[d3];
|
||||
*buffer++ = cDigitsLut[d3 + 1];
|
||||
*buffer++ = cDigitsLut[d4];
|
||||
@ -77,10 +79,10 @@ inline char* u32toa(uint32_t value, char* buffer) {
|
||||
}
|
||||
else {
|
||||
// value = aabbbbcccc in decimal
|
||||
|
||||
|
||||
const uint32_t a = value / 100000000; // 1 to 42
|
||||
value %= 100000000;
|
||||
|
||||
|
||||
if (a >= 10) {
|
||||
const unsigned i = a << 1;
|
||||
*buffer++ = cDigitsLut[i];
|
||||
@ -91,13 +93,13 @@ inline char* u32toa(uint32_t value, char* buffer) {
|
||||
|
||||
const uint32_t b = value / 10000; // 0 to 9999
|
||||
const uint32_t c = value % 10000; // 0 to 9999
|
||||
|
||||
|
||||
const uint32_t d1 = (b / 100) << 1;
|
||||
const uint32_t d2 = (b % 100) << 1;
|
||||
|
||||
|
||||
const uint32_t d3 = (c / 100) << 1;
|
||||
const uint32_t d4 = (c % 100) << 1;
|
||||
|
||||
|
||||
*buffer++ = cDigitsLut[d1];
|
||||
*buffer++ = cDigitsLut[d1 + 1];
|
||||
*buffer++ = cDigitsLut[d2];
|
||||
@ -111,6 +113,7 @@ inline char* u32toa(uint32_t value, char* buffer) {
|
||||
}
|
||||
|
||||
inline char* i32toa(int32_t value, char* buffer) {
|
||||
RAPIDJSON_ASSERT(buffer != 0);
|
||||
uint32_t u = static_cast<uint32_t>(value);
|
||||
if (value < 0) {
|
||||
*buffer++ = '-';
|
||||
@ -121,6 +124,7 @@ inline char* i32toa(int32_t value, char* buffer) {
|
||||
}
|
||||
|
||||
inline char* u64toa(uint64_t value, char* buffer) {
|
||||
RAPIDJSON_ASSERT(buffer != 0);
|
||||
const char* cDigitsLut = GetDigitsLut();
|
||||
const uint64_t kTen8 = 100000000;
|
||||
const uint64_t kTen9 = kTen8 * 10;
|
||||
@ -131,13 +135,13 @@ inline char* u64toa(uint64_t value, char* buffer) {
|
||||
const uint64_t kTen14 = kTen8 * 1000000;
|
||||
const uint64_t kTen15 = kTen8 * 10000000;
|
||||
const uint64_t kTen16 = kTen8 * kTen8;
|
||||
|
||||
|
||||
if (value < kTen8) {
|
||||
uint32_t v = static_cast<uint32_t>(value);
|
||||
if (v < 10000) {
|
||||
const uint32_t d1 = (v / 100) << 1;
|
||||
const uint32_t d2 = (v % 100) << 1;
|
||||
|
||||
|
||||
if (v >= 1000)
|
||||
*buffer++ = cDigitsLut[d1];
|
||||
if (v >= 100)
|
||||
@ -150,13 +154,13 @@ inline char* u64toa(uint64_t value, char* buffer) {
|
||||
// value = bbbbcccc
|
||||
const uint32_t b = v / 10000;
|
||||
const uint32_t c = v % 10000;
|
||||
|
||||
|
||||
const uint32_t d1 = (b / 100) << 1;
|
||||
const uint32_t d2 = (b % 100) << 1;
|
||||
|
||||
|
||||
const uint32_t d3 = (c / 100) << 1;
|
||||
const uint32_t d4 = (c % 100) << 1;
|
||||
|
||||
|
||||
if (value >= 10000000)
|
||||
*buffer++ = cDigitsLut[d1];
|
||||
if (value >= 1000000)
|
||||
@ -164,7 +168,7 @@ inline char* u64toa(uint64_t value, char* buffer) {
|
||||
if (value >= 100000)
|
||||
*buffer++ = cDigitsLut[d2];
|
||||
*buffer++ = cDigitsLut[d2 + 1];
|
||||
|
||||
|
||||
*buffer++ = cDigitsLut[d3];
|
||||
*buffer++ = cDigitsLut[d3 + 1];
|
||||
*buffer++ = cDigitsLut[d4];
|
||||
@ -174,22 +178,22 @@ inline char* u64toa(uint64_t value, char* buffer) {
|
||||
else if (value < kTen16) {
|
||||
const uint32_t v0 = static_cast<uint32_t>(value / kTen8);
|
||||
const uint32_t v1 = static_cast<uint32_t>(value % kTen8);
|
||||
|
||||
|
||||
const uint32_t b0 = v0 / 10000;
|
||||
const uint32_t c0 = v0 % 10000;
|
||||
|
||||
|
||||
const uint32_t d1 = (b0 / 100) << 1;
|
||||
const uint32_t d2 = (b0 % 100) << 1;
|
||||
|
||||
|
||||
const uint32_t d3 = (c0 / 100) << 1;
|
||||
const uint32_t d4 = (c0 % 100) << 1;
|
||||
|
||||
const uint32_t b1 = v1 / 10000;
|
||||
const uint32_t c1 = v1 % 10000;
|
||||
|
||||
|
||||
const uint32_t d5 = (b1 / 100) << 1;
|
||||
const uint32_t d6 = (b1 % 100) << 1;
|
||||
|
||||
|
||||
const uint32_t d7 = (c1 / 100) << 1;
|
||||
const uint32_t d8 = (c1 % 100) << 1;
|
||||
|
||||
@ -207,9 +211,8 @@ inline char* u64toa(uint64_t value, char* buffer) {
|
||||
*buffer++ = cDigitsLut[d3 + 1];
|
||||
if (value >= kTen9)
|
||||
*buffer++ = cDigitsLut[d4];
|
||||
if (value >= kTen8)
|
||||
*buffer++ = cDigitsLut[d4 + 1];
|
||||
|
||||
|
||||
*buffer++ = cDigitsLut[d4 + 1];
|
||||
*buffer++ = cDigitsLut[d5];
|
||||
*buffer++ = cDigitsLut[d5 + 1];
|
||||
*buffer++ = cDigitsLut[d6];
|
||||
@ -222,7 +225,7 @@ inline char* u64toa(uint64_t value, char* buffer) {
|
||||
else {
|
||||
const uint32_t a = static_cast<uint32_t>(value / kTen16); // 1 to 1844
|
||||
value %= kTen16;
|
||||
|
||||
|
||||
if (a < 10)
|
||||
*buffer++ = static_cast<char>('0' + static_cast<char>(a));
|
||||
else if (a < 100) {
|
||||
@ -232,7 +235,7 @@ inline char* u64toa(uint64_t value, char* buffer) {
|
||||
}
|
||||
else if (a < 1000) {
|
||||
*buffer++ = static_cast<char>('0' + static_cast<char>(a / 100));
|
||||
|
||||
|
||||
const uint32_t i = (a % 100) << 1;
|
||||
*buffer++ = cDigitsLut[i];
|
||||
*buffer++ = cDigitsLut[i + 1];
|
||||
@ -245,28 +248,28 @@ inline char* u64toa(uint64_t value, char* buffer) {
|
||||
*buffer++ = cDigitsLut[j];
|
||||
*buffer++ = cDigitsLut[j + 1];
|
||||
}
|
||||
|
||||
|
||||
const uint32_t v0 = static_cast<uint32_t>(value / kTen8);
|
||||
const uint32_t v1 = static_cast<uint32_t>(value % kTen8);
|
||||
|
||||
|
||||
const uint32_t b0 = v0 / 10000;
|
||||
const uint32_t c0 = v0 % 10000;
|
||||
|
||||
|
||||
const uint32_t d1 = (b0 / 100) << 1;
|
||||
const uint32_t d2 = (b0 % 100) << 1;
|
||||
|
||||
|
||||
const uint32_t d3 = (c0 / 100) << 1;
|
||||
const uint32_t d4 = (c0 % 100) << 1;
|
||||
|
||||
|
||||
const uint32_t b1 = v1 / 10000;
|
||||
const uint32_t c1 = v1 % 10000;
|
||||
|
||||
|
||||
const uint32_t d5 = (b1 / 100) << 1;
|
||||
const uint32_t d6 = (b1 % 100) << 1;
|
||||
|
||||
|
||||
const uint32_t d7 = (c1 / 100) << 1;
|
||||
const uint32_t d8 = (c1 % 100) << 1;
|
||||
|
||||
|
||||
*buffer++ = cDigitsLut[d1];
|
||||
*buffer++ = cDigitsLut[d1 + 1];
|
||||
*buffer++ = cDigitsLut[d2];
|
||||
@ -284,11 +287,12 @@ inline char* u64toa(uint64_t value, char* buffer) {
|
||||
*buffer++ = cDigitsLut[d8];
|
||||
*buffer++ = cDigitsLut[d8 + 1];
|
||||
}
|
||||
|
||||
|
||||
return buffer;
|
||||
}
|
||||
|
||||
inline char* i64toa(int64_t value, char* buffer) {
|
||||
RAPIDJSON_ASSERT(buffer != 0);
|
||||
uint64_t u = static_cast<uint64_t>(value);
|
||||
if (value < 0) {
|
||||
*buffer++ = '-';
|
||||
@ -299,6 +303,6 @@ inline char* i64toa(int64_t value, char* buffer) {
|
||||
}
|
||||
|
||||
} // namespace internal
|
||||
CEREAL_RAPIDJSON_NAMESPACE_END
|
||||
RAPIDJSON_NAMESPACE_END
|
||||
|
||||
#endif // CEREAL_RAPIDJSON_ITOA_
|
||||
#endif // RAPIDJSON_ITOA_
|
||||
|
@ -1,6 +1,6 @@
|
||||
// Tencent is pleased to support the open source community by making RapidJSON available.
|
||||
//
|
||||
// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
|
||||
// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip.
|
||||
//
|
||||
// Licensed under the MIT License (the "License"); you may not use this file except
|
||||
// in compliance with the License. You may obtain a copy of the License at
|
||||
@ -12,26 +12,27 @@
|
||||
// CONDITIONS OF ANY KIND, either express or implied. See the License for the
|
||||
// specific language governing permissions and limitations under the License.
|
||||
|
||||
#ifndef CEREAL_RAPIDJSON_INTERNAL_META_H_
|
||||
#define CEREAL_RAPIDJSON_INTERNAL_META_H_
|
||||
#ifndef RAPIDJSON_INTERNAL_META_H_
|
||||
#define RAPIDJSON_INTERNAL_META_H_
|
||||
|
||||
#include "../rapidjson.h"
|
||||
|
||||
#ifdef __GNUC__
|
||||
CEREAL_RAPIDJSON_DIAG_PUSH
|
||||
CEREAL_RAPIDJSON_DIAG_OFF(effc++)
|
||||
#endif
|
||||
#if defined(_MSC_VER)
|
||||
CEREAL_RAPIDJSON_DIAG_PUSH
|
||||
CEREAL_RAPIDJSON_DIAG_OFF(6334)
|
||||
RAPIDJSON_DIAG_PUSH
|
||||
RAPIDJSON_DIAG_OFF(effc++)
|
||||
#endif
|
||||
|
||||
#if CEREAL_RAPIDJSON_HAS_CXX11_TYPETRAITS
|
||||
#if defined(_MSC_VER) && !defined(__clang__)
|
||||
RAPIDJSON_DIAG_PUSH
|
||||
RAPIDJSON_DIAG_OFF(6334)
|
||||
#endif
|
||||
|
||||
#if RAPIDJSON_HAS_CXX11_TYPETRAITS
|
||||
#include <type_traits>
|
||||
#endif
|
||||
|
||||
//@cond CEREAL_RAPIDJSON_INTERNAL
|
||||
CEREAL_RAPIDJSON_NAMESPACE_BEGIN
|
||||
//@cond RAPIDJSON_INTERNAL
|
||||
RAPIDJSON_NAMESPACE_BEGIN
|
||||
namespace internal {
|
||||
|
||||
// Helper to wrap/convert arbitrary types to void, useful for arbitrary type matching
|
||||
@ -96,7 +97,7 @@ template <typename T> struct IsPointer<T*> : TrueType {};
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// IsBaseOf
|
||||
//
|
||||
#if CEREAL_RAPIDJSON_HAS_CXX11_TYPETRAITS
|
||||
#if RAPIDJSON_HAS_CXX11_TYPETRAITS
|
||||
|
||||
template <typename B, typename D> struct IsBaseOf
|
||||
: BoolType< ::std::is_base_of<B,D>::value> {};
|
||||
@ -104,8 +105,8 @@ template <typename B, typename D> struct IsBaseOf
|
||||
#else // simplified version adopted from Boost
|
||||
|
||||
template<typename B, typename D> struct IsBaseOfImpl {
|
||||
CEREAL_RAPIDJSON_STATIC_ASSERT(sizeof(B) != 0);
|
||||
CEREAL_RAPIDJSON_STATIC_ASSERT(sizeof(D) != 0);
|
||||
RAPIDJSON_STATIC_ASSERT(sizeof(B) != 0);
|
||||
RAPIDJSON_STATIC_ASSERT(sizeof(D) != 0);
|
||||
|
||||
typedef char (&Yes)[1];
|
||||
typedef char (&No) [2];
|
||||
@ -125,7 +126,7 @@ template<typename B, typename D> struct IsBaseOfImpl {
|
||||
template <typename B, typename D> struct IsBaseOf
|
||||
: OrExpr<IsSame<B, D>, BoolExpr<IsBaseOfImpl<B, D> > >::Type {};
|
||||
|
||||
#endif // CEREAL_RAPIDJSON_HAS_CXX11_TYPETRAITS
|
||||
#endif // RAPIDJSON_HAS_CXX11_TYPETRAITS
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
@ -148,34 +149,38 @@ struct SfinaeTag {};
|
||||
template <typename T> struct RemoveSfinaeTag;
|
||||
template <typename T> struct RemoveSfinaeTag<SfinaeTag&(*)(T)> { typedef T Type; };
|
||||
|
||||
#define CEREAL_RAPIDJSON_REMOVEFPTR_(type) \
|
||||
typename ::CEREAL_RAPIDJSON_NAMESPACE::internal::RemoveSfinaeTag \
|
||||
< ::CEREAL_RAPIDJSON_NAMESPACE::internal::SfinaeTag&(*) type>::Type
|
||||
#define RAPIDJSON_REMOVEFPTR_(type) \
|
||||
typename ::RAPIDJSON_NAMESPACE::internal::RemoveSfinaeTag \
|
||||
< ::RAPIDJSON_NAMESPACE::internal::SfinaeTag&(*) type>::Type
|
||||
|
||||
#define CEREAL_RAPIDJSON_ENABLEIF(cond) \
|
||||
typename ::CEREAL_RAPIDJSON_NAMESPACE::internal::EnableIf \
|
||||
<CEREAL_RAPIDJSON_REMOVEFPTR_(cond)>::Type * = NULL
|
||||
#define RAPIDJSON_ENABLEIF(cond) \
|
||||
typename ::RAPIDJSON_NAMESPACE::internal::EnableIf \
|
||||
<RAPIDJSON_REMOVEFPTR_(cond)>::Type * = NULL
|
||||
|
||||
#define CEREAL_RAPIDJSON_DISABLEIF(cond) \
|
||||
typename ::CEREAL_RAPIDJSON_NAMESPACE::internal::DisableIf \
|
||||
<CEREAL_RAPIDJSON_REMOVEFPTR_(cond)>::Type * = NULL
|
||||
#define RAPIDJSON_DISABLEIF(cond) \
|
||||
typename ::RAPIDJSON_NAMESPACE::internal::DisableIf \
|
||||
<RAPIDJSON_REMOVEFPTR_(cond)>::Type * = NULL
|
||||
|
||||
#define CEREAL_RAPIDJSON_ENABLEIF_RETURN(cond,returntype) \
|
||||
typename ::CEREAL_RAPIDJSON_NAMESPACE::internal::EnableIf \
|
||||
<CEREAL_RAPIDJSON_REMOVEFPTR_(cond), \
|
||||
CEREAL_RAPIDJSON_REMOVEFPTR_(returntype)>::Type
|
||||
#define RAPIDJSON_ENABLEIF_RETURN(cond,returntype) \
|
||||
typename ::RAPIDJSON_NAMESPACE::internal::EnableIf \
|
||||
<RAPIDJSON_REMOVEFPTR_(cond), \
|
||||
RAPIDJSON_REMOVEFPTR_(returntype)>::Type
|
||||
|
||||
#define CEREAL_RAPIDJSON_DISABLEIF_RETURN(cond,returntype) \
|
||||
typename ::CEREAL_RAPIDJSON_NAMESPACE::internal::DisableIf \
|
||||
<CEREAL_RAPIDJSON_REMOVEFPTR_(cond), \
|
||||
CEREAL_RAPIDJSON_REMOVEFPTR_(returntype)>::Type
|
||||
#define RAPIDJSON_DISABLEIF_RETURN(cond,returntype) \
|
||||
typename ::RAPIDJSON_NAMESPACE::internal::DisableIf \
|
||||
<RAPIDJSON_REMOVEFPTR_(cond), \
|
||||
RAPIDJSON_REMOVEFPTR_(returntype)>::Type
|
||||
|
||||
} // namespace internal
|
||||
CEREAL_RAPIDJSON_NAMESPACE_END
|
||||
RAPIDJSON_NAMESPACE_END
|
||||
//@endcond
|
||||
|
||||
#if defined(__GNUC__) || defined(_MSC_VER)
|
||||
CEREAL_RAPIDJSON_DIAG_POP
|
||||
#if defined(_MSC_VER) && !defined(__clang__)
|
||||
RAPIDJSON_DIAG_POP
|
||||
#endif
|
||||
|
||||
#endif // CEREAL_RAPIDJSON_INTERNAL_META_H_
|
||||
#ifdef __GNUC__
|
||||
RAPIDJSON_DIAG_POP
|
||||
#endif
|
||||
|
||||
#endif // RAPIDJSON_INTERNAL_META_H_
|
||||
|
@ -1,6 +1,6 @@
|
||||
// Tencent is pleased to support the open source community by making RapidJSON available.
|
||||
//
|
||||
// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
|
||||
// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip.
|
||||
//
|
||||
// Licensed under the MIT License (the "License"); you may not use this file except
|
||||
// in compliance with the License. You may obtain a copy of the License at
|
||||
@ -12,12 +12,12 @@
|
||||
// CONDITIONS OF ANY KIND, either express or implied. See the License for the
|
||||
// specific language governing permissions and limitations under the License.
|
||||
|
||||
#ifndef CEREAL_RAPIDJSON_POW10_
|
||||
#define CEREAL_RAPIDJSON_POW10_
|
||||
#ifndef RAPIDJSON_POW10_
|
||||
#define RAPIDJSON_POW10_
|
||||
|
||||
#include "../rapidjson.h"
|
||||
|
||||
CEREAL_RAPIDJSON_NAMESPACE_BEGIN
|
||||
RAPIDJSON_NAMESPACE_BEGIN
|
||||
namespace internal {
|
||||
|
||||
//! Computes integer powers of 10 in double (10.0^n).
|
||||
@ -45,11 +45,11 @@ inline double Pow10(int n) {
|
||||
1e+281,1e+282,1e+283,1e+284,1e+285,1e+286,1e+287,1e+288,1e+289,1e+290,1e+291,1e+292,1e+293,1e+294,1e+295,1e+296,1e+297,1e+298,1e+299,1e+300,
|
||||
1e+301,1e+302,1e+303,1e+304,1e+305,1e+306,1e+307,1e+308
|
||||
};
|
||||
CEREAL_RAPIDJSON_ASSERT(n >= 0 && n <= 308);
|
||||
RAPIDJSON_ASSERT(n >= 0 && n <= 308);
|
||||
return e[n];
|
||||
}
|
||||
|
||||
} // namespace internal
|
||||
CEREAL_RAPIDJSON_NAMESPACE_END
|
||||
RAPIDJSON_NAMESPACE_END
|
||||
|
||||
#endif // CEREAL_RAPIDJSON_POW10_
|
||||
#endif // RAPIDJSON_POW10_
|
||||
|
372
external/cereal/external/rapidjson/internal/regex.h
vendored
372
external/cereal/external/rapidjson/internal/regex.h
vendored
@ -1,6 +1,6 @@
|
||||
// Tencent is pleased to support the open source community by making RapidJSON available.
|
||||
//
|
||||
// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
|
||||
// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip.
|
||||
//
|
||||
// Licensed under the MIT License (the "License"); you may not use this file except
|
||||
// in compliance with the License. You may obtain a copy of the License at
|
||||
@ -12,43 +12,68 @@
|
||||
// CONDITIONS OF ANY KIND, either express or implied. See the License for the
|
||||
// specific language governing permissions and limitations under the License.
|
||||
|
||||
#ifndef CEREAL_RAPIDJSON_INTERNAL_REGEX_H_
|
||||
#define CEREAL_RAPIDJSON_INTERNAL_REGEX_H_
|
||||
#ifndef RAPIDJSON_INTERNAL_REGEX_H_
|
||||
#define RAPIDJSON_INTERNAL_REGEX_H_
|
||||
|
||||
#include "../allocators.h"
|
||||
#include "../stream.h"
|
||||
#include "stack.h"
|
||||
|
||||
#ifdef __clang__
|
||||
CEREAL_RAPIDJSON_DIAG_PUSH
|
||||
CEREAL_RAPIDJSON_DIAG_OFF(padded)
|
||||
CEREAL_RAPIDJSON_DIAG_OFF(switch-enum)
|
||||
CEREAL_RAPIDJSON_DIAG_OFF(implicit-fallthrough)
|
||||
RAPIDJSON_DIAG_PUSH
|
||||
RAPIDJSON_DIAG_OFF(padded)
|
||||
RAPIDJSON_DIAG_OFF(switch-enum)
|
||||
#elif defined(_MSC_VER)
|
||||
RAPIDJSON_DIAG_PUSH
|
||||
RAPIDJSON_DIAG_OFF(4512) // assignment operator could not be generated
|
||||
#endif
|
||||
|
||||
#ifdef __GNUC__
|
||||
CEREAL_RAPIDJSON_DIAG_PUSH
|
||||
CEREAL_RAPIDJSON_DIAG_OFF(effc++)
|
||||
RAPIDJSON_DIAG_PUSH
|
||||
RAPIDJSON_DIAG_OFF(effc++)
|
||||
#endif
|
||||
|
||||
#ifdef _MSC_VER
|
||||
CEREAL_RAPIDJSON_DIAG_PUSH
|
||||
CEREAL_RAPIDJSON_DIAG_OFF(4512) // assignment operator could not be generated
|
||||
#ifndef RAPIDJSON_REGEX_VERBOSE
|
||||
#define RAPIDJSON_REGEX_VERBOSE 0
|
||||
#endif
|
||||
|
||||
#ifndef CEREAL_RAPIDJSON_REGEX_VERBOSE
|
||||
#define CEREAL_RAPIDJSON_REGEX_VERBOSE 0
|
||||
#endif
|
||||
|
||||
CEREAL_RAPIDJSON_NAMESPACE_BEGIN
|
||||
RAPIDJSON_NAMESPACE_BEGIN
|
||||
namespace internal {
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// DecodedStream
|
||||
|
||||
template <typename SourceStream, typename Encoding>
|
||||
class DecodedStream {
|
||||
public:
|
||||
DecodedStream(SourceStream& ss) : ss_(ss), codepoint_() { Decode(); }
|
||||
unsigned Peek() { return codepoint_; }
|
||||
unsigned Take() {
|
||||
unsigned c = codepoint_;
|
||||
if (c) // No further decoding when '\0'
|
||||
Decode();
|
||||
return c;
|
||||
}
|
||||
|
||||
private:
|
||||
void Decode() {
|
||||
if (!Encoding::Decode(ss_, &codepoint_))
|
||||
codepoint_ = 0;
|
||||
}
|
||||
|
||||
SourceStream& ss_;
|
||||
unsigned codepoint_;
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// GenericRegex
|
||||
|
||||
static const SizeType kRegexInvalidState = ~SizeType(0); //!< Represents an invalid index in GenericRegex::State::out, out1
|
||||
static const SizeType kRegexInvalidRange = ~SizeType(0);
|
||||
|
||||
template <typename Encoding, typename Allocator>
|
||||
class GenericRegexSearch;
|
||||
|
||||
//! Regular expression engine with subset of ECMAscript grammar.
|
||||
/*!
|
||||
Supported regular expression syntax:
|
||||
@ -84,45 +109,29 @@ static const SizeType kRegexInvalidRange = ~SizeType(0);
|
||||
template <typename Encoding, typename Allocator = CrtAllocator>
|
||||
class GenericRegex {
|
||||
public:
|
||||
typedef Encoding EncodingType;
|
||||
typedef typename Encoding::Ch Ch;
|
||||
template <typename, typename> friend class GenericRegexSearch;
|
||||
|
||||
GenericRegex(const Ch* source, Allocator* allocator = 0) :
|
||||
states_(allocator, 256), ranges_(allocator, 256), root_(kRegexInvalidState), stateCount_(), rangeCount_(),
|
||||
stateSet_(), state0_(allocator, 0), state1_(allocator, 0), anchorBegin_(), anchorEnd_()
|
||||
ownAllocator_(allocator ? 0 : RAPIDJSON_NEW(Allocator)()), allocator_(allocator ? allocator : ownAllocator_),
|
||||
states_(allocator_, 256), ranges_(allocator_, 256), root_(kRegexInvalidState), stateCount_(), rangeCount_(),
|
||||
anchorBegin_(), anchorEnd_()
|
||||
{
|
||||
GenericStringStream<Encoding> ss(source);
|
||||
DecodedStream<GenericStringStream<Encoding> > ds(ss);
|
||||
DecodedStream<GenericStringStream<Encoding>, Encoding> ds(ss);
|
||||
Parse(ds);
|
||||
}
|
||||
|
||||
~GenericRegex() {
|
||||
Allocator::Free(stateSet_);
|
||||
~GenericRegex()
|
||||
{
|
||||
RAPIDJSON_DELETE(ownAllocator_);
|
||||
}
|
||||
|
||||
bool IsValid() const {
|
||||
return root_ != kRegexInvalidState;
|
||||
}
|
||||
|
||||
template <typename InputStream>
|
||||
bool Match(InputStream& is) const {
|
||||
return SearchWithAnchoring(is, true, true);
|
||||
}
|
||||
|
||||
bool Match(const Ch* s) const {
|
||||
GenericStringStream<Encoding> is(s);
|
||||
return Match(is);
|
||||
}
|
||||
|
||||
template <typename InputStream>
|
||||
bool Search(InputStream& is) const {
|
||||
return SearchWithAnchoring(is, anchorBegin_, anchorEnd_);
|
||||
}
|
||||
|
||||
bool Search(const Ch* s) const {
|
||||
GenericStringStream<Encoding> is(s);
|
||||
return Search(is);
|
||||
}
|
||||
|
||||
private:
|
||||
enum Operator {
|
||||
kZeroOrOne,
|
||||
@ -157,54 +166,31 @@ private:
|
||||
SizeType minIndex;
|
||||
};
|
||||
|
||||
template <typename SourceStream>
|
||||
class DecodedStream {
|
||||
public:
|
||||
DecodedStream(SourceStream& ss) : ss_(ss), codepoint_() { Decode(); }
|
||||
unsigned Peek() { return codepoint_; }
|
||||
unsigned Take() {
|
||||
unsigned c = codepoint_;
|
||||
if (c) // No further decoding when '\0'
|
||||
Decode();
|
||||
return c;
|
||||
}
|
||||
|
||||
private:
|
||||
void Decode() {
|
||||
if (!Encoding::Decode(ss_, &codepoint_))
|
||||
codepoint_ = 0;
|
||||
}
|
||||
|
||||
SourceStream& ss_;
|
||||
unsigned codepoint_;
|
||||
};
|
||||
|
||||
State& GetState(SizeType index) {
|
||||
CEREAL_RAPIDJSON_ASSERT(index < stateCount_);
|
||||
RAPIDJSON_ASSERT(index < stateCount_);
|
||||
return states_.template Bottom<State>()[index];
|
||||
}
|
||||
|
||||
const State& GetState(SizeType index) const {
|
||||
CEREAL_RAPIDJSON_ASSERT(index < stateCount_);
|
||||
RAPIDJSON_ASSERT(index < stateCount_);
|
||||
return states_.template Bottom<State>()[index];
|
||||
}
|
||||
|
||||
Range& GetRange(SizeType index) {
|
||||
CEREAL_RAPIDJSON_ASSERT(index < rangeCount_);
|
||||
RAPIDJSON_ASSERT(index < rangeCount_);
|
||||
return ranges_.template Bottom<Range>()[index];
|
||||
}
|
||||
|
||||
const Range& GetRange(SizeType index) const {
|
||||
CEREAL_RAPIDJSON_ASSERT(index < rangeCount_);
|
||||
RAPIDJSON_ASSERT(index < rangeCount_);
|
||||
return ranges_.template Bottom<Range>()[index];
|
||||
}
|
||||
|
||||
template <typename InputStream>
|
||||
void Parse(DecodedStream<InputStream>& ds) {
|
||||
Allocator allocator;
|
||||
Stack<Allocator> operandStack(&allocator, 256); // Frag
|
||||
Stack<Allocator> operatorStack(&allocator, 256); // Operator
|
||||
Stack<Allocator> atomCountStack(&allocator, 256); // unsigned (Atom per parenthesis)
|
||||
void Parse(DecodedStream<InputStream, Encoding>& ds) {
|
||||
Stack<Allocator> operandStack(allocator_, 256); // Frag
|
||||
Stack<Allocator> operatorStack(allocator_, 256); // Operator
|
||||
Stack<Allocator> atomCountStack(allocator_, 256); // unsigned (Atom per parenthesis)
|
||||
|
||||
*atomCountStack.template Push<unsigned>() = 0;
|
||||
|
||||
@ -301,6 +287,7 @@ private:
|
||||
if (!CharacterEscape(ds, &codepoint))
|
||||
return; // Unsupported escape character
|
||||
// fall through to default
|
||||
RAPIDJSON_DELIBERATE_FALLTHROUGH;
|
||||
|
||||
default: // Pattern character
|
||||
PushOperand(operandStack, codepoint);
|
||||
@ -318,7 +305,7 @@ private:
|
||||
Patch(e->out, NewState(kRegexInvalidState, kRegexInvalidState, 0));
|
||||
root_ = e->start;
|
||||
|
||||
#if CEREAL_RAPIDJSON_REGEX_VERBOSE
|
||||
#if RAPIDJSON_REGEX_VERBOSE
|
||||
printf("root: %d\n", root_);
|
||||
for (SizeType i = 0; i < stateCount_ ; i++) {
|
||||
State& s = GetState(i);
|
||||
@ -327,14 +314,6 @@ private:
|
||||
printf("\n");
|
||||
#endif
|
||||
}
|
||||
|
||||
// Preallocate buffer for SearchWithAnchoring()
|
||||
CEREAL_RAPIDJSON_ASSERT(stateSet_ == 0);
|
||||
if (stateCount_ > 0) {
|
||||
stateSet_ = static_cast<unsigned*>(states_.GetAllocator().Malloc(GetStateSetSize()));
|
||||
state0_.template Reserve<SizeType>(stateCount_);
|
||||
state1_.template Reserve<SizeType>(stateCount_);
|
||||
}
|
||||
}
|
||||
|
||||
SizeType NewState(SizeType out, SizeType out1, unsigned codepoint) {
|
||||
@ -375,7 +354,7 @@ private:
|
||||
bool Eval(Stack<Allocator>& operandStack, Operator op) {
|
||||
switch (op) {
|
||||
case kConcatenation:
|
||||
CEREAL_RAPIDJSON_ASSERT(operandStack.GetSize() >= sizeof(Frag) * 2);
|
||||
RAPIDJSON_ASSERT(operandStack.GetSize() >= sizeof(Frag) * 2);
|
||||
{
|
||||
Frag e2 = *operandStack.template Pop<Frag>(1);
|
||||
Frag e1 = *operandStack.template Pop<Frag>(1);
|
||||
@ -413,8 +392,7 @@ private:
|
||||
}
|
||||
return false;
|
||||
|
||||
default:
|
||||
CEREAL_RAPIDJSON_ASSERT(op == kOneOrMore);
|
||||
case kOneOrMore:
|
||||
if (operandStack.GetSize() >= sizeof(Frag)) {
|
||||
Frag e = *operandStack.template Pop<Frag>(1);
|
||||
SizeType s = NewState(kRegexInvalidState, e.start, 0);
|
||||
@ -423,12 +401,16 @@ private:
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
||||
default:
|
||||
// syntax error (e.g. unclosed kLeftParenthesis)
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool EvalQuantifier(Stack<Allocator>& operandStack, unsigned n, unsigned m) {
|
||||
CEREAL_RAPIDJSON_ASSERT(n <= m);
|
||||
CEREAL_RAPIDJSON_ASSERT(operandStack.GetSize() >= sizeof(Frag));
|
||||
RAPIDJSON_ASSERT(n <= m);
|
||||
RAPIDJSON_ASSERT(operandStack.GetSize() >= sizeof(Frag));
|
||||
|
||||
if (n == 0) {
|
||||
if (m == 0) // a{0} not support
|
||||
@ -483,7 +465,7 @@ private:
|
||||
}
|
||||
|
||||
template <typename InputStream>
|
||||
bool ParseUnsigned(DecodedStream<InputStream>& ds, unsigned* u) {
|
||||
bool ParseUnsigned(DecodedStream<InputStream, Encoding>& ds, unsigned* u) {
|
||||
unsigned r = 0;
|
||||
if (ds.Peek() < '0' || ds.Peek() > '9')
|
||||
return false;
|
||||
@ -497,7 +479,7 @@ private:
|
||||
}
|
||||
|
||||
template <typename InputStream>
|
||||
bool ParseRange(DecodedStream<InputStream>& ds, SizeType* range) {
|
||||
bool ParseRange(DecodedStream<InputStream, Encoding>& ds, SizeType* range) {
|
||||
bool isBegin = true;
|
||||
bool negate = false;
|
||||
int step = 0;
|
||||
@ -519,7 +501,7 @@ private:
|
||||
return false; // Error: nothing inside []
|
||||
if (step == 2) { // Add trailing '-'
|
||||
SizeType r = NewRange('-');
|
||||
CEREAL_RAPIDJSON_ASSERT(current != kRegexInvalidRange);
|
||||
RAPIDJSON_ASSERT(current != kRegexInvalidRange);
|
||||
GetRange(current).next = r;
|
||||
}
|
||||
if (negate)
|
||||
@ -535,6 +517,7 @@ private:
|
||||
else if (!CharacterEscape(ds, &codepoint))
|
||||
return false;
|
||||
// fall through to default
|
||||
RAPIDJSON_DELIBERATE_FALLTHROUGH;
|
||||
|
||||
default:
|
||||
switch (step) {
|
||||
@ -544,6 +527,7 @@ private:
|
||||
break;
|
||||
}
|
||||
// fall through to step 0 for other characters
|
||||
RAPIDJSON_DELIBERATE_FALLTHROUGH;
|
||||
|
||||
case 0:
|
||||
{
|
||||
@ -558,7 +542,7 @@ private:
|
||||
break;
|
||||
|
||||
default:
|
||||
CEREAL_RAPIDJSON_ASSERT(step == 2);
|
||||
RAPIDJSON_ASSERT(step == 2);
|
||||
GetRange(current).end = codepoint;
|
||||
step = 0;
|
||||
}
|
||||
@ -575,7 +559,7 @@ private:
|
||||
}
|
||||
|
||||
template <typename InputStream>
|
||||
bool CharacterEscape(DecodedStream<InputStream>& ds, unsigned* escapedCodepoint) {
|
||||
bool CharacterEscape(DecodedStream<InputStream, Encoding>& ds, unsigned* escapedCodepoint) {
|
||||
unsigned codepoint;
|
||||
switch (codepoint = ds.Take()) {
|
||||
case '^':
|
||||
@ -603,72 +587,8 @@ private:
|
||||
}
|
||||
}
|
||||
|
||||
template <typename InputStream>
|
||||
bool SearchWithAnchoring(InputStream& is, bool anchorBegin, bool anchorEnd) const {
|
||||
CEREAL_RAPIDJSON_ASSERT(IsValid());
|
||||
DecodedStream<InputStream> ds(is);
|
||||
|
||||
state0_.Clear();
|
||||
Stack<Allocator> *current = &state0_, *next = &state1_;
|
||||
const size_t stateSetSize = GetStateSetSize();
|
||||
std::memset(stateSet_, 0, stateSetSize);
|
||||
|
||||
bool matched = AddState(*current, root_);
|
||||
unsigned codepoint;
|
||||
while (!current->Empty() && (codepoint = ds.Take()) != 0) {
|
||||
std::memset(stateSet_, 0, stateSetSize);
|
||||
next->Clear();
|
||||
matched = false;
|
||||
for (const SizeType* s = current->template Bottom<SizeType>(); s != current->template End<SizeType>(); ++s) {
|
||||
const State& sr = GetState(*s);
|
||||
if (sr.codepoint == codepoint ||
|
||||
sr.codepoint == kAnyCharacterClass ||
|
||||
(sr.codepoint == kRangeCharacterClass && MatchRange(sr.rangeStart, codepoint)))
|
||||
{
|
||||
matched = AddState(*next, sr.out) || matched;
|
||||
if (!anchorEnd && matched)
|
||||
return true;
|
||||
}
|
||||
if (!anchorBegin)
|
||||
AddState(*next, root_);
|
||||
}
|
||||
internal::Swap(current, next);
|
||||
}
|
||||
|
||||
return matched;
|
||||
}
|
||||
|
||||
size_t GetStateSetSize() const {
|
||||
return (stateCount_ + 31) / 32 * 4;
|
||||
}
|
||||
|
||||
// Return whether the added states is a match state
|
||||
bool AddState(Stack<Allocator>& l, SizeType index) const {
|
||||
CEREAL_RAPIDJSON_ASSERT(index != kRegexInvalidState);
|
||||
|
||||
const State& s = GetState(index);
|
||||
if (s.out1 != kRegexInvalidState) { // Split
|
||||
bool matched = AddState(l, s.out);
|
||||
return AddState(l, s.out1) || matched;
|
||||
}
|
||||
else if (!(stateSet_[index >> 5] & (1 << (index & 31)))) {
|
||||
stateSet_[index >> 5] |= (1 << (index & 31));
|
||||
*l.template PushUnsafe<SizeType>() = index;
|
||||
}
|
||||
return s.out == kRegexInvalidState; // by using PushUnsafe() above, we can ensure s is not validated due to reallocation.
|
||||
}
|
||||
|
||||
bool MatchRange(SizeType rangeIndex, unsigned codepoint) const {
|
||||
bool yes = (GetRange(rangeIndex).start & kRangeNegationFlag) == 0;
|
||||
while (rangeIndex != kRegexInvalidRange) {
|
||||
const Range& r = GetRange(rangeIndex);
|
||||
if (codepoint >= (r.start & ~kRangeNegationFlag) && codepoint <= r.end)
|
||||
return yes;
|
||||
rangeIndex = r.next;
|
||||
}
|
||||
return !yes;
|
||||
}
|
||||
|
||||
Allocator* ownAllocator_;
|
||||
Allocator* allocator_;
|
||||
Stack<Allocator> states_;
|
||||
Stack<Allocator> ranges_;
|
||||
SizeType root_;
|
||||
@ -678,24 +598,142 @@ private:
|
||||
static const unsigned kInfinityQuantifier = ~0u;
|
||||
|
||||
// For SearchWithAnchoring()
|
||||
uint32_t* stateSet_; // allocated by states_.GetAllocator()
|
||||
mutable Stack<Allocator> state0_;
|
||||
mutable Stack<Allocator> state1_;
|
||||
bool anchorBegin_;
|
||||
bool anchorEnd_;
|
||||
};
|
||||
|
||||
template <typename RegexType, typename Allocator = CrtAllocator>
|
||||
class GenericRegexSearch {
|
||||
public:
|
||||
typedef typename RegexType::EncodingType Encoding;
|
||||
typedef typename Encoding::Ch Ch;
|
||||
|
||||
GenericRegexSearch(const RegexType& regex, Allocator* allocator = 0) :
|
||||
regex_(regex), allocator_(allocator), ownAllocator_(0),
|
||||
state0_(allocator, 0), state1_(allocator, 0), stateSet_()
|
||||
{
|
||||
RAPIDJSON_ASSERT(regex_.IsValid());
|
||||
if (!allocator_)
|
||||
ownAllocator_ = allocator_ = RAPIDJSON_NEW(Allocator)();
|
||||
stateSet_ = static_cast<unsigned*>(allocator_->Malloc(GetStateSetSize()));
|
||||
state0_.template Reserve<SizeType>(regex_.stateCount_);
|
||||
state1_.template Reserve<SizeType>(regex_.stateCount_);
|
||||
}
|
||||
|
||||
~GenericRegexSearch() {
|
||||
Allocator::Free(stateSet_);
|
||||
RAPIDJSON_DELETE(ownAllocator_);
|
||||
}
|
||||
|
||||
template <typename InputStream>
|
||||
bool Match(InputStream& is) {
|
||||
return SearchWithAnchoring(is, true, true);
|
||||
}
|
||||
|
||||
bool Match(const Ch* s) {
|
||||
GenericStringStream<Encoding> is(s);
|
||||
return Match(is);
|
||||
}
|
||||
|
||||
template <typename InputStream>
|
||||
bool Search(InputStream& is) {
|
||||
return SearchWithAnchoring(is, regex_.anchorBegin_, regex_.anchorEnd_);
|
||||
}
|
||||
|
||||
bool Search(const Ch* s) {
|
||||
GenericStringStream<Encoding> is(s);
|
||||
return Search(is);
|
||||
}
|
||||
|
||||
private:
|
||||
typedef typename RegexType::State State;
|
||||
typedef typename RegexType::Range Range;
|
||||
|
||||
template <typename InputStream>
|
||||
bool SearchWithAnchoring(InputStream& is, bool anchorBegin, bool anchorEnd) {
|
||||
DecodedStream<InputStream, Encoding> ds(is);
|
||||
|
||||
state0_.Clear();
|
||||
Stack<Allocator> *current = &state0_, *next = &state1_;
|
||||
const size_t stateSetSize = GetStateSetSize();
|
||||
std::memset(stateSet_, 0, stateSetSize);
|
||||
|
||||
bool matched = AddState(*current, regex_.root_);
|
||||
unsigned codepoint;
|
||||
while (!current->Empty() && (codepoint = ds.Take()) != 0) {
|
||||
std::memset(stateSet_, 0, stateSetSize);
|
||||
next->Clear();
|
||||
matched = false;
|
||||
for (const SizeType* s = current->template Bottom<SizeType>(); s != current->template End<SizeType>(); ++s) {
|
||||
const State& sr = regex_.GetState(*s);
|
||||
if (sr.codepoint == codepoint ||
|
||||
sr.codepoint == RegexType::kAnyCharacterClass ||
|
||||
(sr.codepoint == RegexType::kRangeCharacterClass && MatchRange(sr.rangeStart, codepoint)))
|
||||
{
|
||||
matched = AddState(*next, sr.out) || matched;
|
||||
if (!anchorEnd && matched)
|
||||
return true;
|
||||
}
|
||||
if (!anchorBegin)
|
||||
AddState(*next, regex_.root_);
|
||||
}
|
||||
internal::Swap(current, next);
|
||||
}
|
||||
|
||||
return matched;
|
||||
}
|
||||
|
||||
size_t GetStateSetSize() const {
|
||||
return (regex_.stateCount_ + 31) / 32 * 4;
|
||||
}
|
||||
|
||||
// Return whether the added states is a match state
|
||||
bool AddState(Stack<Allocator>& l, SizeType index) {
|
||||
RAPIDJSON_ASSERT(index != kRegexInvalidState);
|
||||
|
||||
const State& s = regex_.GetState(index);
|
||||
if (s.out1 != kRegexInvalidState) { // Split
|
||||
bool matched = AddState(l, s.out);
|
||||
return AddState(l, s.out1) || matched;
|
||||
}
|
||||
else if (!(stateSet_[index >> 5] & (1u << (index & 31)))) {
|
||||
stateSet_[index >> 5] |= (1u << (index & 31));
|
||||
*l.template PushUnsafe<SizeType>() = index;
|
||||
}
|
||||
return s.out == kRegexInvalidState; // by using PushUnsafe() above, we can ensure s is not validated due to reallocation.
|
||||
}
|
||||
|
||||
bool MatchRange(SizeType rangeIndex, unsigned codepoint) const {
|
||||
bool yes = (regex_.GetRange(rangeIndex).start & RegexType::kRangeNegationFlag) == 0;
|
||||
while (rangeIndex != kRegexInvalidRange) {
|
||||
const Range& r = regex_.GetRange(rangeIndex);
|
||||
if (codepoint >= (r.start & ~RegexType::kRangeNegationFlag) && codepoint <= r.end)
|
||||
return yes;
|
||||
rangeIndex = r.next;
|
||||
}
|
||||
return !yes;
|
||||
}
|
||||
|
||||
const RegexType& regex_;
|
||||
Allocator* allocator_;
|
||||
Allocator* ownAllocator_;
|
||||
Stack<Allocator> state0_;
|
||||
Stack<Allocator> state1_;
|
||||
uint32_t* stateSet_;
|
||||
};
|
||||
|
||||
typedef GenericRegex<UTF8<> > Regex;
|
||||
typedef GenericRegexSearch<Regex> RegexSearch;
|
||||
|
||||
} // namespace internal
|
||||
CEREAL_RAPIDJSON_NAMESPACE_END
|
||||
RAPIDJSON_NAMESPACE_END
|
||||
|
||||
#ifdef __clang__
|
||||
CEREAL_RAPIDJSON_DIAG_POP
|
||||
#ifdef __GNUC__
|
||||
RAPIDJSON_DIAG_POP
|
||||
#endif
|
||||
|
||||
#ifdef _MSC_VER
|
||||
CEREAL_RAPIDJSON_DIAG_POP
|
||||
#if defined(__clang__) || defined(_MSC_VER)
|
||||
RAPIDJSON_DIAG_POP
|
||||
#endif
|
||||
|
||||
#endif // CEREAL_RAPIDJSON_INTERNAL_REGEX_H_
|
||||
#endif // RAPIDJSON_INTERNAL_REGEX_H_
|
||||
|
@ -1,6 +1,6 @@
|
||||
// Tencent is pleased to support the open source community by making RapidJSON available.
|
||||
//
|
||||
// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
|
||||
// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip.
|
||||
//
|
||||
// Licensed under the MIT License (the "License"); you may not use this file except
|
||||
// in compliance with the License. You may obtain a copy of the License at
|
||||
@ -12,18 +12,19 @@
|
||||
// CONDITIONS OF ANY KIND, either express or implied. See the License for the
|
||||
// specific language governing permissions and limitations under the License.
|
||||
|
||||
#ifndef CEREAL_RAPIDJSON_INTERNAL_STACK_H_
|
||||
#define CEREAL_RAPIDJSON_INTERNAL_STACK_H_
|
||||
#ifndef RAPIDJSON_INTERNAL_STACK_H_
|
||||
#define RAPIDJSON_INTERNAL_STACK_H_
|
||||
|
||||
#include "../allocators.h"
|
||||
#include "swap.h"
|
||||
#include <cstddef>
|
||||
|
||||
#if defined(__clang__)
|
||||
CEREAL_RAPIDJSON_DIAG_PUSH
|
||||
CEREAL_RAPIDJSON_DIAG_OFF(c++98-compat)
|
||||
RAPIDJSON_DIAG_PUSH
|
||||
RAPIDJSON_DIAG_OFF(c++98-compat)
|
||||
#endif
|
||||
|
||||
CEREAL_RAPIDJSON_NAMESPACE_BEGIN
|
||||
RAPIDJSON_NAMESPACE_BEGIN
|
||||
namespace internal {
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
@ -40,7 +41,7 @@ public:
|
||||
Stack(Allocator* allocator, size_t stackCapacity) : allocator_(allocator), ownAllocator_(0), stack_(0), stackTop_(0), stackEnd_(0), initialCapacity_(stackCapacity) {
|
||||
}
|
||||
|
||||
#if CEREAL_RAPIDJSON_HAS_CXX11_RVALUE_REFS
|
||||
#if RAPIDJSON_HAS_CXX11_RVALUE_REFS
|
||||
Stack(Stack&& rhs)
|
||||
: allocator_(rhs.allocator_),
|
||||
ownAllocator_(rhs.ownAllocator_),
|
||||
@ -62,7 +63,7 @@ public:
|
||||
Destroy();
|
||||
}
|
||||
|
||||
#if CEREAL_RAPIDJSON_HAS_CXX11_RVALUE_REFS
|
||||
#if RAPIDJSON_HAS_CXX11_RVALUE_REFS
|
||||
Stack& operator=(Stack&& rhs) {
|
||||
if (&rhs != this)
|
||||
{
|
||||
@ -86,7 +87,7 @@ public:
|
||||
}
|
||||
#endif
|
||||
|
||||
void Swap(Stack& rhs) CEREAL_RAPIDJSON_NOEXCEPT {
|
||||
void Swap(Stack& rhs) RAPIDJSON_NOEXCEPT {
|
||||
internal::Swap(allocator_, rhs.allocator_);
|
||||
internal::Swap(ownAllocator_, rhs.ownAllocator_);
|
||||
internal::Swap(stack_, rhs.stack_);
|
||||
@ -100,7 +101,7 @@ public:
|
||||
void ShrinkToFit() {
|
||||
if (Empty()) {
|
||||
// If the stack is empty, completely deallocate the memory.
|
||||
Allocator::Free(stack_);
|
||||
Allocator::Free(stack_); // NOLINT (+clang-analyzer-unix.Malloc)
|
||||
stack_ = 0;
|
||||
stackTop_ = 0;
|
||||
stackEnd_ = 0;
|
||||
@ -112,21 +113,22 @@ public:
|
||||
// Optimization note: try to minimize the size of this function for force inline.
|
||||
// Expansion is run very infrequently, so it is moved to another (probably non-inline) function.
|
||||
template<typename T>
|
||||
CEREAL_RAPIDJSON_FORCEINLINE void Reserve(size_t count = 1) {
|
||||
RAPIDJSON_FORCEINLINE void Reserve(size_t count = 1) {
|
||||
// Expand the stack if needed
|
||||
if (CEREAL_RAPIDJSON_UNLIKELY(stackTop_ + sizeof(T) * count > stackEnd_))
|
||||
if (RAPIDJSON_UNLIKELY(static_cast<std::ptrdiff_t>(sizeof(T) * count) > (stackEnd_ - stackTop_)))
|
||||
Expand<T>(count);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
CEREAL_RAPIDJSON_FORCEINLINE T* Push(size_t count = 1) {
|
||||
RAPIDJSON_FORCEINLINE T* Push(size_t count = 1) {
|
||||
Reserve<T>(count);
|
||||
return PushUnsafe<T>(count);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
CEREAL_RAPIDJSON_FORCEINLINE T* PushUnsafe(size_t count = 1) {
|
||||
CEREAL_RAPIDJSON_ASSERT(stackTop_ + sizeof(T) * count <= stackEnd_);
|
||||
RAPIDJSON_FORCEINLINE T* PushUnsafe(size_t count = 1) {
|
||||
RAPIDJSON_ASSERT(stackTop_);
|
||||
RAPIDJSON_ASSERT(static_cast<std::ptrdiff_t>(sizeof(T) * count) <= (stackEnd_ - stackTop_));
|
||||
T* ret = reinterpret_cast<T*>(stackTop_);
|
||||
stackTop_ += sizeof(T) * count;
|
||||
return ret;
|
||||
@ -134,20 +136,20 @@ public:
|
||||
|
||||
template<typename T>
|
||||
T* Pop(size_t count) {
|
||||
CEREAL_RAPIDJSON_ASSERT(GetSize() >= count * sizeof(T));
|
||||
RAPIDJSON_ASSERT(GetSize() >= count * sizeof(T));
|
||||
stackTop_ -= count * sizeof(T);
|
||||
return reinterpret_cast<T*>(stackTop_);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
T* Top() {
|
||||
CEREAL_RAPIDJSON_ASSERT(GetSize() >= sizeof(T));
|
||||
RAPIDJSON_ASSERT(GetSize() >= sizeof(T));
|
||||
return reinterpret_cast<T*>(stackTop_ - sizeof(T));
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
const T* Top() const {
|
||||
CEREAL_RAPIDJSON_ASSERT(GetSize() >= sizeof(T));
|
||||
RAPIDJSON_ASSERT(GetSize() >= sizeof(T));
|
||||
return reinterpret_cast<T*>(stackTop_ - sizeof(T));
|
||||
}
|
||||
|
||||
@ -168,7 +170,7 @@ public:
|
||||
}
|
||||
|
||||
Allocator& GetAllocator() {
|
||||
CEREAL_RAPIDJSON_ASSERT(allocator_);
|
||||
RAPIDJSON_ASSERT(allocator_);
|
||||
return *allocator_;
|
||||
}
|
||||
|
||||
@ -183,7 +185,7 @@ private:
|
||||
size_t newCapacity;
|
||||
if (stack_ == 0) {
|
||||
if (!allocator_)
|
||||
ownAllocator_ = allocator_ = CEREAL_RAPIDJSON_NEW(Allocator());
|
||||
ownAllocator_ = allocator_ = RAPIDJSON_NEW(Allocator)();
|
||||
newCapacity = initialCapacity_;
|
||||
} else {
|
||||
newCapacity = GetCapacity();
|
||||
@ -205,7 +207,7 @@ private:
|
||||
|
||||
void Destroy() {
|
||||
Allocator::Free(stack_);
|
||||
CEREAL_RAPIDJSON_DELETE(ownAllocator_); // Only delete if it is owned by the stack
|
||||
RAPIDJSON_DELETE(ownAllocator_); // Only delete if it is owned by the stack
|
||||
}
|
||||
|
||||
// Prohibit copy constructor & assignment operator.
|
||||
@ -221,10 +223,10 @@ private:
|
||||
};
|
||||
|
||||
} // namespace internal
|
||||
CEREAL_RAPIDJSON_NAMESPACE_END
|
||||
RAPIDJSON_NAMESPACE_END
|
||||
|
||||
#if defined(__clang__)
|
||||
CEREAL_RAPIDJSON_DIAG_POP
|
||||
RAPIDJSON_DIAG_POP
|
||||
#endif
|
||||
|
||||
#endif // CEREAL_RAPIDJSON_STACK_H_
|
||||
#endif // RAPIDJSON_STACK_H_
|
||||
|
@ -1,6 +1,6 @@
|
||||
// Tencent is pleased to support the open source community by making RapidJSON available.
|
||||
//
|
||||
// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
|
||||
// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip.
|
||||
//
|
||||
// Licensed under the MIT License (the "License"); you may not use this file except
|
||||
// in compliance with the License. You may obtain a copy of the License at
|
||||
@ -12,12 +12,13 @@
|
||||
// CONDITIONS OF ANY KIND, either express or implied. See the License for the
|
||||
// specific language governing permissions and limitations under the License.
|
||||
|
||||
#ifndef CEREAL_RAPIDJSON_INTERNAL_STRFUNC_H_
|
||||
#define CEREAL_RAPIDJSON_INTERNAL_STRFUNC_H_
|
||||
#ifndef RAPIDJSON_INTERNAL_STRFUNC_H_
|
||||
#define RAPIDJSON_INTERNAL_STRFUNC_H_
|
||||
|
||||
#include "../stream.h"
|
||||
#include <cwchar>
|
||||
|
||||
CEREAL_RAPIDJSON_NAMESPACE_BEGIN
|
||||
RAPIDJSON_NAMESPACE_BEGIN
|
||||
namespace internal {
|
||||
|
||||
//! Custom strlen() which works on different character types.
|
||||
@ -28,14 +29,41 @@ namespace internal {
|
||||
*/
|
||||
template <typename Ch>
|
||||
inline SizeType StrLen(const Ch* s) {
|
||||
RAPIDJSON_ASSERT(s != 0);
|
||||
const Ch* p = s;
|
||||
while (*p) ++p;
|
||||
return SizeType(p - s);
|
||||
}
|
||||
|
||||
template <>
|
||||
inline SizeType StrLen(const char* s) {
|
||||
return SizeType(std::strlen(s));
|
||||
}
|
||||
|
||||
template <>
|
||||
inline SizeType StrLen(const wchar_t* s) {
|
||||
return SizeType(std::wcslen(s));
|
||||
}
|
||||
|
||||
//! Custom strcmpn() which works on different character types.
|
||||
/*! \tparam Ch Character type (e.g. char, wchar_t, short)
|
||||
\param s1 Null-terminated input string.
|
||||
\param s2 Null-terminated input string.
|
||||
\return 0 if equal
|
||||
*/
|
||||
template<typename Ch>
|
||||
inline int StrCmp(const Ch* s1, const Ch* s2) {
|
||||
RAPIDJSON_ASSERT(s1 != 0);
|
||||
RAPIDJSON_ASSERT(s2 != 0);
|
||||
while(*s1 && (*s1 == *s2)) { s1++; s2++; }
|
||||
return static_cast<unsigned>(*s1) < static_cast<unsigned>(*s2) ? -1 : static_cast<unsigned>(*s1) > static_cast<unsigned>(*s2);
|
||||
}
|
||||
|
||||
//! Returns number of code points in a encoded string.
|
||||
template<typename Encoding>
|
||||
bool CountStringCodePoint(const typename Encoding::Ch* s, SizeType length, SizeType* outCount) {
|
||||
RAPIDJSON_ASSERT(s != 0);
|
||||
RAPIDJSON_ASSERT(outCount != 0);
|
||||
GenericStringStream<Encoding> is(s);
|
||||
const typename Encoding::Ch* end = s + length;
|
||||
SizeType count = 0;
|
||||
@ -50,6 +78,6 @@ bool CountStringCodePoint(const typename Encoding::Ch* s, SizeType length, SizeT
|
||||
}
|
||||
|
||||
} // namespace internal
|
||||
CEREAL_RAPIDJSON_NAMESPACE_END
|
||||
RAPIDJSON_NAMESPACE_END
|
||||
|
||||
#endif // CEREAL_RAPIDJSON_INTERNAL_STRFUNC_H_
|
||||
#endif // RAPIDJSON_INTERNAL_STRFUNC_H_
|
||||
|
138
external/cereal/external/rapidjson/internal/strtod.h
vendored
138
external/cereal/external/rapidjson/internal/strtod.h
vendored
@ -1,6 +1,6 @@
|
||||
// Tencent is pleased to support the open source community by making RapidJSON available.
|
||||
//
|
||||
// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
|
||||
// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip.
|
||||
//
|
||||
// Licensed under the MIT License (the "License"); you may not use this file except
|
||||
// in compliance with the License. You may obtain a copy of the License at
|
||||
@ -12,15 +12,17 @@
|
||||
// CONDITIONS OF ANY KIND, either express or implied. See the License for the
|
||||
// specific language governing permissions and limitations under the License.
|
||||
|
||||
#ifndef CEREAL_RAPIDJSON_STRTOD_
|
||||
#define CEREAL_RAPIDJSON_STRTOD_
|
||||
#ifndef RAPIDJSON_STRTOD_
|
||||
#define RAPIDJSON_STRTOD_
|
||||
|
||||
#include "ieee754.h"
|
||||
#include "biginteger.h"
|
||||
#include "diyfp.h"
|
||||
#include "pow10.h"
|
||||
#include <climits>
|
||||
#include <limits>
|
||||
|
||||
CEREAL_RAPIDJSON_NAMESPACE_BEGIN
|
||||
RAPIDJSON_NAMESPACE_BEGIN
|
||||
namespace internal {
|
||||
|
||||
inline double FastPath(double significand, int exp) {
|
||||
@ -126,46 +128,47 @@ inline bool StrtodFast(double d, int p, double* result) {
|
||||
}
|
||||
|
||||
// Compute an approximation and see if it is within 1/2 ULP
|
||||
inline bool StrtodDiyFp(const char* decimals, size_t length, size_t decimalPosition, int exp, double* result) {
|
||||
template<typename Ch>
|
||||
inline bool StrtodDiyFp(const Ch* decimals, int dLen, int dExp, double* result) {
|
||||
uint64_t significand = 0;
|
||||
size_t i = 0; // 2^64 - 1 = 18446744073709551615, 1844674407370955161 = 0x1999999999999999
|
||||
for (; i < length; i++) {
|
||||
if (significand > CEREAL_RAPIDJSON_UINT64_C2(0x19999999, 0x99999999) ||
|
||||
(significand == CEREAL_RAPIDJSON_UINT64_C2(0x19999999, 0x99999999) && decimals[i] > '5'))
|
||||
int i = 0; // 2^64 - 1 = 18446744073709551615, 1844674407370955161 = 0x1999999999999999
|
||||
for (; i < dLen; i++) {
|
||||
if (significand > RAPIDJSON_UINT64_C2(0x19999999, 0x99999999) ||
|
||||
(significand == RAPIDJSON_UINT64_C2(0x19999999, 0x99999999) && decimals[i] > Ch('5')))
|
||||
break;
|
||||
significand = significand * 10u + static_cast<unsigned>(decimals[i] - '0');
|
||||
significand = significand * 10u + static_cast<unsigned>(decimals[i] - Ch('0'));
|
||||
}
|
||||
|
||||
if (i < length && decimals[i] >= '5') // Rounding
|
||||
if (i < dLen && decimals[i] >= Ch('5')) // Rounding
|
||||
significand++;
|
||||
|
||||
size_t remaining = length - i;
|
||||
const unsigned kUlpShift = 3;
|
||||
const unsigned kUlp = 1 << kUlpShift;
|
||||
int remaining = dLen - i;
|
||||
const int kUlpShift = 3;
|
||||
const int kUlp = 1 << kUlpShift;
|
||||
int64_t error = (remaining == 0) ? 0 : kUlp / 2;
|
||||
|
||||
DiyFp v(significand, 0);
|
||||
v = v.Normalize();
|
||||
error <<= -v.e;
|
||||
|
||||
const int dExp = static_cast<int>(decimalPosition) - static_cast<int>(i) + exp;
|
||||
dExp += remaining;
|
||||
|
||||
int actualExp;
|
||||
DiyFp cachedPower = GetCachedPower10(dExp, &actualExp);
|
||||
if (actualExp != dExp) {
|
||||
static const DiyFp kPow10[] = {
|
||||
DiyFp(CEREAL_RAPIDJSON_UINT64_C2(0xa0000000, 00000000), -60), // 10^1
|
||||
DiyFp(CEREAL_RAPIDJSON_UINT64_C2(0xc8000000, 00000000), -57), // 10^2
|
||||
DiyFp(CEREAL_RAPIDJSON_UINT64_C2(0xfa000000, 00000000), -54), // 10^3
|
||||
DiyFp(CEREAL_RAPIDJSON_UINT64_C2(0x9c400000, 00000000), -50), // 10^4
|
||||
DiyFp(CEREAL_RAPIDJSON_UINT64_C2(0xc3500000, 00000000), -47), // 10^5
|
||||
DiyFp(CEREAL_RAPIDJSON_UINT64_C2(0xf4240000, 00000000), -44), // 10^6
|
||||
DiyFp(CEREAL_RAPIDJSON_UINT64_C2(0x98968000, 00000000), -40) // 10^7
|
||||
DiyFp(RAPIDJSON_UINT64_C2(0xa0000000, 0x00000000), -60), // 10^1
|
||||
DiyFp(RAPIDJSON_UINT64_C2(0xc8000000, 0x00000000), -57), // 10^2
|
||||
DiyFp(RAPIDJSON_UINT64_C2(0xfa000000, 0x00000000), -54), // 10^3
|
||||
DiyFp(RAPIDJSON_UINT64_C2(0x9c400000, 0x00000000), -50), // 10^4
|
||||
DiyFp(RAPIDJSON_UINT64_C2(0xc3500000, 0x00000000), -47), // 10^5
|
||||
DiyFp(RAPIDJSON_UINT64_C2(0xf4240000, 0x00000000), -44), // 10^6
|
||||
DiyFp(RAPIDJSON_UINT64_C2(0x98968000, 0x00000000), -40) // 10^7
|
||||
};
|
||||
int adjustment = dExp - actualExp - 1;
|
||||
CEREAL_RAPIDJSON_ASSERT(adjustment >= 0 && adjustment < 7);
|
||||
v = v * kPow10[adjustment];
|
||||
if (length + static_cast<unsigned>(adjustment)> 19u) // has more digits than decimal digits in 64-bit
|
||||
int adjustment = dExp - actualExp;
|
||||
RAPIDJSON_ASSERT(adjustment >= 1 && adjustment < 8);
|
||||
v = v * kPow10[adjustment - 1];
|
||||
if (dLen + adjustment > 19) // has more digits than decimal digits in 64-bit
|
||||
error += kUlp / 2;
|
||||
}
|
||||
|
||||
@ -177,17 +180,17 @@ inline bool StrtodDiyFp(const char* decimals, size_t length, size_t decimalPosit
|
||||
v = v.Normalize();
|
||||
error <<= oldExp - v.e;
|
||||
|
||||
const unsigned effectiveSignificandSize = Double::EffectiveSignificandSize(64 + v.e);
|
||||
unsigned precisionSize = 64 - effectiveSignificandSize;
|
||||
const int effectiveSignificandSize = Double::EffectiveSignificandSize(64 + v.e);
|
||||
int precisionSize = 64 - effectiveSignificandSize;
|
||||
if (precisionSize + kUlpShift >= 64) {
|
||||
unsigned scaleExp = (precisionSize + kUlpShift) - 63;
|
||||
int scaleExp = (precisionSize + kUlpShift) - 63;
|
||||
v.f >>= scaleExp;
|
||||
v.e += scaleExp;
|
||||
error = (error >> scaleExp) + 1 + static_cast<int>(kUlp);
|
||||
error = (error >> scaleExp) + 1 + kUlp;
|
||||
precisionSize -= scaleExp;
|
||||
}
|
||||
|
||||
DiyFp rounded(v.f >> precisionSize, v.e + static_cast<int>(precisionSize));
|
||||
DiyFp rounded(v.f >> precisionSize, v.e + precisionSize);
|
||||
const uint64_t precisionBits = (v.f & ((uint64_t(1) << precisionSize) - 1)) * kUlp;
|
||||
const uint64_t halfWay = (uint64_t(1) << (precisionSize - 1)) * kUlp;
|
||||
if (precisionBits >= halfWay + static_cast<unsigned>(error)) {
|
||||
@ -203,9 +206,10 @@ inline bool StrtodDiyFp(const char* decimals, size_t length, size_t decimalPosit
|
||||
return halfWay - static_cast<unsigned>(error) >= precisionBits || precisionBits >= halfWay + static_cast<unsigned>(error);
|
||||
}
|
||||
|
||||
inline double StrtodBigInteger(double approx, const char* decimals, size_t length, size_t decimalPosition, int exp) {
|
||||
const BigInteger dInt(decimals, length);
|
||||
const int dExp = static_cast<int>(decimalPosition) - static_cast<int>(length) + exp;
|
||||
template<typename Ch>
|
||||
inline double StrtodBigInteger(double approx, const Ch* decimals, int dLen, int dExp) {
|
||||
RAPIDJSON_ASSERT(dLen >= 0);
|
||||
const BigInteger dInt(decimals, static_cast<unsigned>(dLen));
|
||||
Double a(approx);
|
||||
int cmp = CheckWithinHalfULP(a.Value(), dInt, dExp);
|
||||
if (cmp < 0)
|
||||
@ -221,49 +225,69 @@ inline double StrtodBigInteger(double approx, const char* decimals, size_t lengt
|
||||
return a.NextPositiveDouble();
|
||||
}
|
||||
|
||||
inline double StrtodFullPrecision(double d, int p, const char* decimals, size_t length, size_t decimalPosition, int exp) {
|
||||
CEREAL_RAPIDJSON_ASSERT(d >= 0.0);
|
||||
CEREAL_RAPIDJSON_ASSERT(length >= 1);
|
||||
template<typename Ch>
|
||||
inline double StrtodFullPrecision(double d, int p, const Ch* decimals, size_t length, size_t decimalPosition, int exp) {
|
||||
RAPIDJSON_ASSERT(d >= 0.0);
|
||||
RAPIDJSON_ASSERT(length >= 1);
|
||||
|
||||
double result;
|
||||
double result = 0.0;
|
||||
if (StrtodFast(d, p, &result))
|
||||
return result;
|
||||
|
||||
RAPIDJSON_ASSERT(length <= INT_MAX);
|
||||
int dLen = static_cast<int>(length);
|
||||
|
||||
RAPIDJSON_ASSERT(length >= decimalPosition);
|
||||
RAPIDJSON_ASSERT(length - decimalPosition <= INT_MAX);
|
||||
int dExpAdjust = static_cast<int>(length - decimalPosition);
|
||||
|
||||
RAPIDJSON_ASSERT(exp >= INT_MIN + dExpAdjust);
|
||||
int dExp = exp - dExpAdjust;
|
||||
|
||||
// Make sure length+dExp does not overflow
|
||||
RAPIDJSON_ASSERT(dExp <= INT_MAX - dLen);
|
||||
|
||||
// Trim leading zeros
|
||||
while (*decimals == '0' && length > 1) {
|
||||
length--;
|
||||
while (dLen > 0 && *decimals == '0') {
|
||||
dLen--;
|
||||
decimals++;
|
||||
decimalPosition--;
|
||||
}
|
||||
|
||||
// Trim trailing zeros
|
||||
while (decimals[length - 1] == '0' && length > 1) {
|
||||
length--;
|
||||
decimalPosition--;
|
||||
exp++;
|
||||
while (dLen > 0 && decimals[dLen - 1] == '0') {
|
||||
dLen--;
|
||||
dExp++;
|
||||
}
|
||||
|
||||
if (dLen == 0) { // Buffer only contains zeros.
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
// Trim right-most digits
|
||||
const int kMaxDecimalDigit = 780;
|
||||
if (static_cast<int>(length) > kMaxDecimalDigit) {
|
||||
int delta = (static_cast<int>(length) - kMaxDecimalDigit);
|
||||
exp += delta;
|
||||
decimalPosition -= static_cast<unsigned>(delta);
|
||||
length = kMaxDecimalDigit;
|
||||
const int kMaxDecimalDigit = 767 + 1;
|
||||
if (dLen > kMaxDecimalDigit) {
|
||||
dExp += dLen - kMaxDecimalDigit;
|
||||
dLen = kMaxDecimalDigit;
|
||||
}
|
||||
|
||||
// If too small, underflow to zero
|
||||
if (int(length) + exp < -324)
|
||||
// If too small, underflow to zero.
|
||||
// Any x <= 10^-324 is interpreted as zero.
|
||||
if (dLen + dExp <= -324)
|
||||
return 0.0;
|
||||
|
||||
if (StrtodDiyFp(decimals, length, decimalPosition, exp, &result))
|
||||
// If too large, overflow to infinity.
|
||||
// Any x >= 10^309 is interpreted as +infinity.
|
||||
if (dLen + dExp > 309)
|
||||
return std::numeric_limits<double>::infinity();
|
||||
|
||||
if (StrtodDiyFp(decimals, dLen, dExp, &result))
|
||||
return result;
|
||||
|
||||
// Use approximation from StrtodDiyFp and make adjustment with BigInteger comparison
|
||||
return StrtodBigInteger(result, decimals, length, decimalPosition, exp);
|
||||
return StrtodBigInteger(result, decimals, dLen, dExp);
|
||||
}
|
||||
|
||||
} // namespace internal
|
||||
CEREAL_RAPIDJSON_NAMESPACE_END
|
||||
RAPIDJSON_NAMESPACE_END
|
||||
|
||||
#endif // CEREAL_RAPIDJSON_STRTOD_
|
||||
#endif // RAPIDJSON_STRTOD_
|
||||
|
@ -1,6 +1,6 @@
|
||||
// Tencent is pleased to support the open source community by making RapidJSON available.
|
||||
//
|
||||
// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
|
||||
// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip.
|
||||
//
|
||||
// Licensed under the MIT License (the "License"); you may not use this file except
|
||||
// in compliance with the License. You may obtain a copy of the License at
|
||||
@ -12,17 +12,17 @@
|
||||
// CONDITIONS OF ANY KIND, either express or implied. See the License for the
|
||||
// specific language governing permissions and limitations under the License.
|
||||
|
||||
#ifndef CEREAL_RAPIDJSON_INTERNAL_SWAP_H_
|
||||
#define CEREAL_RAPIDJSON_INTERNAL_SWAP_H_
|
||||
#ifndef RAPIDJSON_INTERNAL_SWAP_H_
|
||||
#define RAPIDJSON_INTERNAL_SWAP_H_
|
||||
|
||||
#include "../rapidjson.h"
|
||||
|
||||
#if defined(__clang__)
|
||||
CEREAL_RAPIDJSON_DIAG_PUSH
|
||||
CEREAL_RAPIDJSON_DIAG_OFF(c++98-compat)
|
||||
RAPIDJSON_DIAG_PUSH
|
||||
RAPIDJSON_DIAG_OFF(c++98-compat)
|
||||
#endif
|
||||
|
||||
CEREAL_RAPIDJSON_NAMESPACE_BEGIN
|
||||
RAPIDJSON_NAMESPACE_BEGIN
|
||||
namespace internal {
|
||||
|
||||
//! Custom swap() to avoid dependency on C++ <algorithm> header
|
||||
@ -30,17 +30,17 @@ namespace internal {
|
||||
\note This has the same semantics as std::swap().
|
||||
*/
|
||||
template <typename T>
|
||||
inline void Swap(T& a, T& b) CEREAL_RAPIDJSON_NOEXCEPT {
|
||||
inline void Swap(T& a, T& b) RAPIDJSON_NOEXCEPT {
|
||||
T tmp = a;
|
||||
a = b;
|
||||
b = tmp;
|
||||
}
|
||||
|
||||
} // namespace internal
|
||||
CEREAL_RAPIDJSON_NAMESPACE_END
|
||||
RAPIDJSON_NAMESPACE_END
|
||||
|
||||
#if defined(__clang__)
|
||||
CEREAL_RAPIDJSON_DIAG_POP
|
||||
RAPIDJSON_DIAG_POP
|
||||
#endif
|
||||
|
||||
#endif // CEREAL_RAPIDJSON_INTERNAL_SWAP_H_
|
||||
#endif // RAPIDJSON_INTERNAL_SWAP_H_
|
||||
|
124
external/cereal/external/rapidjson/istreamwrapper.h
vendored
124
external/cereal/external/rapidjson/istreamwrapper.h
vendored
@ -1,35 +1,33 @@
|
||||
// Tencent is pleased to support the open source community by making RapidJSON available.
|
||||
//
|
||||
// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
|
||||
//
|
||||
// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip.
|
||||
//
|
||||
// Licensed under the MIT License (the "License"); you may not use this file except
|
||||
// in compliance with the License. You may obtain a copy of the License at
|
||||
//
|
||||
// http://opensource.org/licenses/MIT
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software distributed
|
||||
// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
|
||||
// CONDITIONS OF ANY KIND, either express or implied. See the License for the
|
||||
// Unless required by applicable law or agreed to in writing, software distributed
|
||||
// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
|
||||
// CONDITIONS OF ANY KIND, either express or implied. See the License for the
|
||||
// specific language governing permissions and limitations under the License.
|
||||
|
||||
#ifndef CEREAL_RAPIDJSON_ISTREAMWRAPPER_H_
|
||||
#define CEREAL_RAPIDJSON_ISTREAMWRAPPER_H_
|
||||
#ifndef RAPIDJSON_ISTREAMWRAPPER_H_
|
||||
#define RAPIDJSON_ISTREAMWRAPPER_H_
|
||||
|
||||
#include "stream.h"
|
||||
#include <iosfwd>
|
||||
#include <ios>
|
||||
|
||||
#ifdef __clang__
|
||||
CEREAL_RAPIDJSON_DIAG_PUSH
|
||||
CEREAL_RAPIDJSON_DIAG_OFF(padded)
|
||||
RAPIDJSON_DIAG_PUSH
|
||||
RAPIDJSON_DIAG_OFF(padded)
|
||||
#elif defined(_MSC_VER)
|
||||
RAPIDJSON_DIAG_PUSH
|
||||
RAPIDJSON_DIAG_OFF(4351) // new behavior: elements of array 'array' will be default initialized
|
||||
#endif
|
||||
|
||||
#ifdef _MSC_VER
|
||||
CEREAL_RAPIDJSON_DIAG_PUSH
|
||||
CEREAL_RAPIDJSON_DIAG_OFF(4351) // new behavior: elements of array 'array' will be default initialized
|
||||
CEREAL_RAPIDJSON_DIAG_OFF(4127) // ignore assert(false) for triggering exception
|
||||
#endif
|
||||
|
||||
CEREAL_RAPIDJSON_NAMESPACE_BEGIN
|
||||
RAPIDJSON_NAMESPACE_BEGIN
|
||||
|
||||
//! Wrapper of \c std::basic_istream into RapidJSON's Stream concept.
|
||||
/*!
|
||||
@ -46,71 +44,85 @@ CEREAL_RAPIDJSON_NAMESPACE_BEGIN
|
||||
|
||||
\tparam StreamType Class derived from \c std::basic_istream.
|
||||
*/
|
||||
|
||||
|
||||
template <typename StreamType>
|
||||
class BasicIStreamWrapper {
|
||||
public:
|
||||
typedef typename StreamType::char_type Ch;
|
||||
BasicIStreamWrapper(StreamType& stream) : stream_(stream), count_(), peekBuffer_() {}
|
||||
|
||||
Ch Peek() const {
|
||||
typename StreamType::int_type c = stream_.peek();
|
||||
return CEREAL_RAPIDJSON_LIKELY(c != StreamType::traits_type::eof()) ? static_cast<Ch>(c) : '\0';
|
||||
//! Constructor.
|
||||
/*!
|
||||
\param stream stream opened for read.
|
||||
*/
|
||||
BasicIStreamWrapper(StreamType &stream) : stream_(stream), buffer_(peekBuffer_), bufferSize_(4), bufferLast_(0), current_(buffer_), readCount_(0), count_(0), eof_(false) {
|
||||
Read();
|
||||
}
|
||||
|
||||
Ch Take() {
|
||||
typename StreamType::int_type c = stream_.get();
|
||||
if (CEREAL_RAPIDJSON_LIKELY(c != StreamType::traits_type::eof())) {
|
||||
count_++;
|
||||
return static_cast<Ch>(c);
|
||||
}
|
||||
else
|
||||
return '\0';
|
||||
//! Constructor.
|
||||
/*!
|
||||
\param stream stream opened for read.
|
||||
\param buffer user-supplied buffer.
|
||||
\param bufferSize size of buffer in bytes. Must >=4 bytes.
|
||||
*/
|
||||
BasicIStreamWrapper(StreamType &stream, char* buffer, size_t bufferSize) : stream_(stream), buffer_(buffer), bufferSize_(bufferSize), bufferLast_(0), current_(buffer_), readCount_(0), count_(0), eof_(false) {
|
||||
RAPIDJSON_ASSERT(bufferSize >= 4);
|
||||
Read();
|
||||
}
|
||||
|
||||
// tellg() may return -1 when failed. So we count by ourself.
|
||||
size_t Tell() const { return count_; }
|
||||
Ch Peek() const { return *current_; }
|
||||
Ch Take() { Ch c = *current_; Read(); return c; }
|
||||
size_t Tell() const { return count_ + static_cast<size_t>(current_ - buffer_); }
|
||||
|
||||
Ch* PutBegin() { CEREAL_RAPIDJSON_ASSERT(false); return 0; }
|
||||
void Put(Ch) { CEREAL_RAPIDJSON_ASSERT(false); }
|
||||
void Flush() { CEREAL_RAPIDJSON_ASSERT(false); }
|
||||
size_t PutEnd(Ch*) { CEREAL_RAPIDJSON_ASSERT(false); return 0; }
|
||||
// Not implemented
|
||||
void Put(Ch) { RAPIDJSON_ASSERT(false); }
|
||||
void Flush() { RAPIDJSON_ASSERT(false); }
|
||||
Ch* PutBegin() { RAPIDJSON_ASSERT(false); return 0; }
|
||||
size_t PutEnd(Ch*) { RAPIDJSON_ASSERT(false); return 0; }
|
||||
|
||||
// For encoding detection only.
|
||||
const Ch* Peek4() const {
|
||||
CEREAL_RAPIDJSON_ASSERT(sizeof(Ch) == 1); // Only usable for byte stream.
|
||||
int i;
|
||||
bool hasError = false;
|
||||
for (i = 0; i < 4; ++i) {
|
||||
typename StreamType::int_type c = stream_.get();
|
||||
if (c == StreamType::traits_type::eof()) {
|
||||
hasError = true;
|
||||
stream_.clear();
|
||||
break;
|
||||
}
|
||||
peekBuffer_[i] = static_cast<Ch>(c);
|
||||
}
|
||||
for (--i; i >= 0; --i)
|
||||
stream_.putback(peekBuffer_[i]);
|
||||
return !hasError ? peekBuffer_ : 0;
|
||||
return (current_ + 4 - !eof_ <= bufferLast_) ? current_ : 0;
|
||||
}
|
||||
|
||||
private:
|
||||
BasicIStreamWrapper();
|
||||
BasicIStreamWrapper(const BasicIStreamWrapper&);
|
||||
BasicIStreamWrapper& operator=(const BasicIStreamWrapper&);
|
||||
|
||||
StreamType& stream_;
|
||||
size_t count_; //!< Number of characters read. Note:
|
||||
mutable Ch peekBuffer_[4];
|
||||
void Read() {
|
||||
if (current_ < bufferLast_)
|
||||
++current_;
|
||||
else if (!eof_) {
|
||||
count_ += readCount_;
|
||||
readCount_ = bufferSize_;
|
||||
bufferLast_ = buffer_ + readCount_ - 1;
|
||||
current_ = buffer_;
|
||||
|
||||
if (!stream_.read(buffer_, static_cast<std::streamsize>(bufferSize_))) {
|
||||
readCount_ = static_cast<size_t>(stream_.gcount());
|
||||
*(bufferLast_ = buffer_ + readCount_) = '\0';
|
||||
eof_ = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
StreamType &stream_;
|
||||
Ch peekBuffer_[4], *buffer_;
|
||||
size_t bufferSize_;
|
||||
Ch *bufferLast_;
|
||||
Ch *current_;
|
||||
size_t readCount_;
|
||||
size_t count_; //!< Number of characters read
|
||||
bool eof_;
|
||||
};
|
||||
|
||||
typedef BasicIStreamWrapper<std::istream> IStreamWrapper;
|
||||
typedef BasicIStreamWrapper<std::wistream> WIStreamWrapper;
|
||||
|
||||
#if defined(__clang__) || defined(_MSC_VER)
|
||||
CEREAL_RAPIDJSON_DIAG_POP
|
||||
RAPIDJSON_DIAG_POP
|
||||
#endif
|
||||
|
||||
CEREAL_RAPIDJSON_NAMESPACE_END
|
||||
RAPIDJSON_NAMESPACE_END
|
||||
|
||||
#endif // CEREAL_RAPIDJSON_ISTREAMWRAPPER_H_
|
||||
#endif // RAPIDJSON_ISTREAMWRAPPER_H_
|
||||
|
@ -1,6 +1,6 @@
|
||||
// Tencent is pleased to support the open source community by making RapidJSON available.
|
||||
//
|
||||
// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
|
||||
// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip.
|
||||
//
|
||||
// Licensed under the MIT License (the "License"); you may not use this file except
|
||||
// in compliance with the License. You may obtain a copy of the License at
|
||||
@ -12,13 +12,13 @@
|
||||
// CONDITIONS OF ANY KIND, either express or implied. See the License for the
|
||||
// specific language governing permissions and limitations under the License.
|
||||
|
||||
#ifndef CEREAL_RAPIDJSON_MEMORYBUFFER_H_
|
||||
#define CEREAL_RAPIDJSON_MEMORYBUFFER_H_
|
||||
#ifndef RAPIDJSON_MEMORYBUFFER_H_
|
||||
#define RAPIDJSON_MEMORYBUFFER_H_
|
||||
|
||||
#include "stream.h"
|
||||
#include "internal/stack.h"
|
||||
|
||||
CEREAL_RAPIDJSON_NAMESPACE_BEGIN
|
||||
RAPIDJSON_NAMESPACE_BEGIN
|
||||
|
||||
//! Represents an in-memory output byte stream.
|
||||
/*!
|
||||
@ -65,6 +65,6 @@ inline void PutN(MemoryBuffer& memoryBuffer, char c, size_t n) {
|
||||
std::memset(memoryBuffer.stack_.Push<char>(n), c, n * sizeof(c));
|
||||
}
|
||||
|
||||
CEREAL_RAPIDJSON_NAMESPACE_END
|
||||
RAPIDJSON_NAMESPACE_END
|
||||
|
||||
#endif // CEREAL_RAPIDJSON_MEMORYBUFFER_H_
|
||||
#endif // RAPIDJSON_MEMORYBUFFER_H_
|
||||
|
@ -1,34 +1,29 @@
|
||||
// Tencent is pleased to support the open source community by making RapidJSON available.
|
||||
//
|
||||
// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
|
||||
//
|
||||
// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip.
|
||||
//
|
||||
// Licensed under the MIT License (the "License"); you may not use this file except
|
||||
// in compliance with the License. You may obtain a copy of the License at
|
||||
//
|
||||
// http://opensource.org/licenses/MIT
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software distributed
|
||||
// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
|
||||
// CONDITIONS OF ANY KIND, either express or implied. See the License for the
|
||||
// Unless required by applicable law or agreed to in writing, software distributed
|
||||
// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
|
||||
// CONDITIONS OF ANY KIND, either express or implied. See the License for the
|
||||
// specific language governing permissions and limitations under the License.
|
||||
|
||||
#ifndef CEREAL_RAPIDJSON_MEMORYSTREAM_H_
|
||||
#define CEREAL_RAPIDJSON_MEMORYSTREAM_H_
|
||||
#ifndef RAPIDJSON_MEMORYSTREAM_H_
|
||||
#define RAPIDJSON_MEMORYSTREAM_H_
|
||||
|
||||
#include "stream.h"
|
||||
|
||||
#ifdef __clang__
|
||||
CEREAL_RAPIDJSON_DIAG_PUSH
|
||||
CEREAL_RAPIDJSON_DIAG_OFF(unreachable-code)
|
||||
CEREAL_RAPIDJSON_DIAG_OFF(missing-noreturn)
|
||||
RAPIDJSON_DIAG_PUSH
|
||||
RAPIDJSON_DIAG_OFF(unreachable-code)
|
||||
RAPIDJSON_DIAG_OFF(missing-noreturn)
|
||||
#endif
|
||||
|
||||
#ifdef _MSC_VER
|
||||
CEREAL_RAPIDJSON_DIAG_PUSH
|
||||
CEREAL_RAPIDJSON_DIAG_OFF( 4127 ) // ignore assert(false) for triggering exception
|
||||
#endif
|
||||
|
||||
CEREAL_RAPIDJSON_NAMESPACE_BEGIN
|
||||
RAPIDJSON_NAMESPACE_BEGIN
|
||||
|
||||
//! Represents an in-memory input byte stream.
|
||||
/*!
|
||||
@ -47,14 +42,14 @@ struct MemoryStream {
|
||||
|
||||
MemoryStream(const Ch *src, size_t size) : src_(src), begin_(src), end_(src + size), size_(size) {}
|
||||
|
||||
Ch Peek() const { return CEREAL_RAPIDJSON_UNLIKELY(src_ == end_) ? '\0' : *src_; }
|
||||
Ch Take() { return CEREAL_RAPIDJSON_UNLIKELY(src_ == end_) ? '\0' : *src_++; }
|
||||
Ch Peek() const { return RAPIDJSON_UNLIKELY(src_ == end_) ? '\0' : *src_; }
|
||||
Ch Take() { return RAPIDJSON_UNLIKELY(src_ == end_) ? '\0' : *src_++; }
|
||||
size_t Tell() const { return static_cast<size_t>(src_ - begin_); }
|
||||
|
||||
Ch* PutBegin() { CEREAL_RAPIDJSON_ASSERT(false); return 0; }
|
||||
void Put(Ch) { CEREAL_RAPIDJSON_ASSERT(false); }
|
||||
void Flush() { CEREAL_RAPIDJSON_ASSERT(false); }
|
||||
size_t PutEnd(Ch*) { CEREAL_RAPIDJSON_ASSERT(false); return 0; }
|
||||
Ch* PutBegin() { RAPIDJSON_ASSERT(false); return 0; }
|
||||
void Put(Ch) { RAPIDJSON_ASSERT(false); }
|
||||
void Flush() { RAPIDJSON_ASSERT(false); }
|
||||
size_t PutEnd(Ch*) { RAPIDJSON_ASSERT(false); return 0; }
|
||||
|
||||
// For encoding detection only.
|
||||
const Ch* Peek4() const {
|
||||
@ -67,10 +62,10 @@ struct MemoryStream {
|
||||
size_t size_; //!< Size of the stream.
|
||||
};
|
||||
|
||||
CEREAL_RAPIDJSON_NAMESPACE_END
|
||||
RAPIDJSON_NAMESPACE_END
|
||||
|
||||
#if defined(__clang__) || defined(_MSC_VER)
|
||||
CEREAL_RAPIDJSON_DIAG_POP
|
||||
#ifdef __clang__
|
||||
RAPIDJSON_DIAG_POP
|
||||
#endif
|
||||
|
||||
#endif // CEREAL_RAPIDJSON_MEMORYBUFFER_H_
|
||||
#endif // RAPIDJSON_MEMORYBUFFER_H_
|
||||
|
@ -1,6 +1,6 @@
|
||||
// Tencent is pleased to support the open source community by making RapidJSON available.
|
||||
//
|
||||
// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
|
||||
// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip.
|
||||
//
|
||||
// Licensed under the MIT License (the "License"); you may not use this file except
|
||||
// in compliance with the License. You may obtain a copy of the License at
|
||||
@ -12,18 +12,18 @@
|
||||
// CONDITIONS OF ANY KIND, either express or implied. See the License for the
|
||||
// specific language governing permissions and limitations under the License.
|
||||
|
||||
#ifndef CEREAL_RAPIDJSON_OSTREAMWRAPPER_H_
|
||||
#define CEREAL_RAPIDJSON_OSTREAMWRAPPER_H_
|
||||
#ifndef RAPIDJSON_OSTREAMWRAPPER_H_
|
||||
#define RAPIDJSON_OSTREAMWRAPPER_H_
|
||||
|
||||
#include "stream.h"
|
||||
#include <iosfwd>
|
||||
|
||||
#ifdef __clang__
|
||||
CEREAL_RAPIDJSON_DIAG_PUSH
|
||||
CEREAL_RAPIDJSON_DIAG_OFF(padded)
|
||||
RAPIDJSON_DIAG_PUSH
|
||||
RAPIDJSON_DIAG_OFF(padded)
|
||||
#endif
|
||||
|
||||
CEREAL_RAPIDJSON_NAMESPACE_BEGIN
|
||||
RAPIDJSON_NAMESPACE_BEGIN
|
||||
|
||||
//! Wrapper of \c std::basic_ostream into RapidJSON's Stream concept.
|
||||
/*!
|
||||
@ -56,11 +56,11 @@ public:
|
||||
}
|
||||
|
||||
// Not implemented
|
||||
char Peek() const { CEREAL_RAPIDJSON_ASSERT(false); return 0; }
|
||||
char Take() { CEREAL_RAPIDJSON_ASSERT(false); return 0; }
|
||||
size_t Tell() const { CEREAL_RAPIDJSON_ASSERT(false); return 0; }
|
||||
char* PutBegin() { CEREAL_RAPIDJSON_ASSERT(false); return 0; }
|
||||
size_t PutEnd(char*) { CEREAL_RAPIDJSON_ASSERT(false); return 0; }
|
||||
char Peek() const { RAPIDJSON_ASSERT(false); return 0; }
|
||||
char Take() { RAPIDJSON_ASSERT(false); return 0; }
|
||||
size_t Tell() const { RAPIDJSON_ASSERT(false); return 0; }
|
||||
char* PutBegin() { RAPIDJSON_ASSERT(false); return 0; }
|
||||
size_t PutEnd(char*) { RAPIDJSON_ASSERT(false); return 0; }
|
||||
|
||||
private:
|
||||
BasicOStreamWrapper(const BasicOStreamWrapper&);
|
||||
@ -73,9 +73,9 @@ typedef BasicOStreamWrapper<std::ostream> OStreamWrapper;
|
||||
typedef BasicOStreamWrapper<std::wostream> WOStreamWrapper;
|
||||
|
||||
#ifdef __clang__
|
||||
CEREAL_RAPIDJSON_DIAG_POP
|
||||
RAPIDJSON_DIAG_POP
|
||||
#endif
|
||||
|
||||
CEREAL_RAPIDJSON_NAMESPACE_END
|
||||
RAPIDJSON_NAMESPACE_END
|
||||
|
||||
#endif // CEREAL_RAPIDJSON_OSTREAMWRAPPER_H_
|
||||
#endif // RAPIDJSON_OSTREAMWRAPPER_H_
|
||||
|
272
external/cereal/external/rapidjson/pointer.h
vendored
272
external/cereal/external/rapidjson/pointer.h
vendored
@ -1,6 +1,6 @@
|
||||
// Tencent is pleased to support the open source community by making RapidJSON available.
|
||||
//
|
||||
// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
|
||||
// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip.
|
||||
//
|
||||
// Licensed under the MIT License (the "License"); you may not use this file except
|
||||
// in compliance with the License. You may obtain a copy of the License at
|
||||
@ -12,28 +12,27 @@
|
||||
// CONDITIONS OF ANY KIND, either express or implied. See the License for the
|
||||
// specific language governing permissions and limitations under the License.
|
||||
|
||||
#ifndef CEREAL_RAPIDJSON_POINTER_H_
|
||||
#define CEREAL_RAPIDJSON_POINTER_H_
|
||||
#ifndef RAPIDJSON_POINTER_H_
|
||||
#define RAPIDJSON_POINTER_H_
|
||||
|
||||
#include "document.h"
|
||||
#include "uri.h"
|
||||
#include "internal/itoa.h"
|
||||
|
||||
#ifdef __clang__
|
||||
CEREAL_RAPIDJSON_DIAG_PUSH
|
||||
CEREAL_RAPIDJSON_DIAG_OFF(switch-enum)
|
||||
RAPIDJSON_DIAG_PUSH
|
||||
RAPIDJSON_DIAG_OFF(switch-enum)
|
||||
#elif defined(_MSC_VER)
|
||||
RAPIDJSON_DIAG_PUSH
|
||||
RAPIDJSON_DIAG_OFF(4512) // assignment operator could not be generated
|
||||
#endif
|
||||
|
||||
#ifdef _MSC_VER
|
||||
CEREAL_RAPIDJSON_DIAG_PUSH
|
||||
CEREAL_RAPIDJSON_DIAG_OFF(4512) // assignment operator could not be generated
|
||||
#endif
|
||||
|
||||
CEREAL_RAPIDJSON_NAMESPACE_BEGIN
|
||||
RAPIDJSON_NAMESPACE_BEGIN
|
||||
|
||||
static const SizeType kPointerInvalidIndex = ~SizeType(0); //!< Represents an invalid index in GenericPointer::Token
|
||||
|
||||
//! Error code of parsing.
|
||||
/*! \ingroup CEREAL_RAPIDJSON_ERRORS
|
||||
/*! \ingroup RAPIDJSON_ERRORS
|
||||
\see GenericPointer::GenericPointer, GenericPointer::GetParseErrorCode
|
||||
*/
|
||||
enum PointerParseErrorCode {
|
||||
@ -82,6 +81,8 @@ class GenericPointer {
|
||||
public:
|
||||
typedef typename ValueType::EncodingType EncodingType; //!< Encoding type from Value
|
||||
typedef typename ValueType::Ch Ch; //!< Character type from Value
|
||||
typedef GenericUri<ValueType, Allocator> UriType;
|
||||
|
||||
|
||||
//! A token is the basic units of internal representation.
|
||||
/*!
|
||||
@ -117,12 +118,12 @@ public:
|
||||
Parse(source, internal::StrLen(source));
|
||||
}
|
||||
|
||||
#if CEREAL_RAPIDJSON_HAS_STDSTRING
|
||||
#if RAPIDJSON_HAS_STDSTRING
|
||||
//! Constructor that parses a string or URI fragment representation.
|
||||
/*!
|
||||
\param source A string or URI fragment representation of JSON pointer.
|
||||
\param allocator User supplied allocator for this pointer. If no allocator is provided, it creates a self-owned one.
|
||||
\note Requires the definition of the preprocessor symbol \ref CEREAL_RAPIDJSON_HAS_STDSTRING.
|
||||
\note Requires the definition of the preprocessor symbol \ref RAPIDJSON_HAS_STDSTRING.
|
||||
*/
|
||||
explicit GenericPointer(const std::basic_string<Ch>& source, Allocator* allocator = 0) : allocator_(allocator), ownAllocator_(), nameBuffer_(), tokens_(), tokenCount_(), parseErrorOffset_(), parseErrorCode_(kPointerParseErrorNone) {
|
||||
Parse(source.c_str(), source.size());
|
||||
@ -165,7 +166,12 @@ public:
|
||||
GenericPointer(const Token* tokens, size_t tokenCount) : allocator_(), ownAllocator_(), nameBuffer_(), tokens_(const_cast<Token*>(tokens)), tokenCount_(tokenCount), parseErrorOffset_(), parseErrorCode_(kPointerParseErrorNone) {}
|
||||
|
||||
//! Copy constructor.
|
||||
GenericPointer(const GenericPointer& rhs, Allocator* allocator = 0) : allocator_(allocator), ownAllocator_(), nameBuffer_(), tokens_(), tokenCount_(), parseErrorOffset_(), parseErrorCode_(kPointerParseErrorNone) {
|
||||
GenericPointer(const GenericPointer& rhs) : allocator_(), ownAllocator_(), nameBuffer_(), tokens_(), tokenCount_(), parseErrorOffset_(), parseErrorCode_(kPointerParseErrorNone) {
|
||||
*this = rhs;
|
||||
}
|
||||
|
||||
//! Copy constructor.
|
||||
GenericPointer(const GenericPointer& rhs, Allocator* allocator) : allocator_(allocator), ownAllocator_(), nameBuffer_(), tokens_(), tokenCount_(), parseErrorOffset_(), parseErrorCode_(kPointerParseErrorNone) {
|
||||
*this = rhs;
|
||||
}
|
||||
|
||||
@ -173,7 +179,7 @@ public:
|
||||
~GenericPointer() {
|
||||
if (nameBuffer_) // If user-supplied tokens constructor is used, nameBuffer_ is nullptr and tokens_ are not deallocated.
|
||||
Allocator::Free(tokens_);
|
||||
CEREAL_RAPIDJSON_DELETE(ownAllocator_);
|
||||
RAPIDJSON_DELETE(ownAllocator_);
|
||||
}
|
||||
|
||||
//! Assignment operator.
|
||||
@ -197,6 +203,36 @@ public:
|
||||
return *this;
|
||||
}
|
||||
|
||||
//! Swap the content of this pointer with an other.
|
||||
/*!
|
||||
\param other The pointer to swap with.
|
||||
\note Constant complexity.
|
||||
*/
|
||||
GenericPointer& Swap(GenericPointer& other) RAPIDJSON_NOEXCEPT {
|
||||
internal::Swap(allocator_, other.allocator_);
|
||||
internal::Swap(ownAllocator_, other.ownAllocator_);
|
||||
internal::Swap(nameBuffer_, other.nameBuffer_);
|
||||
internal::Swap(tokens_, other.tokens_);
|
||||
internal::Swap(tokenCount_, other.tokenCount_);
|
||||
internal::Swap(parseErrorOffset_, other.parseErrorOffset_);
|
||||
internal::Swap(parseErrorCode_, other.parseErrorCode_);
|
||||
return *this;
|
||||
}
|
||||
|
||||
//! free-standing swap function helper
|
||||
/*!
|
||||
Helper function to enable support for common swap implementation pattern based on \c std::swap:
|
||||
\code
|
||||
void swap(MyClass& a, MyClass& b) {
|
||||
using std::swap;
|
||||
swap(a.pointer, b.pointer);
|
||||
// ...
|
||||
}
|
||||
\endcode
|
||||
\see Swap()
|
||||
*/
|
||||
friend inline void swap(GenericPointer& a, GenericPointer& b) RAPIDJSON_NOEXCEPT { a.Swap(b); }
|
||||
|
||||
//@}
|
||||
|
||||
//!@name Append token
|
||||
@ -238,12 +274,12 @@ public:
|
||||
\return A new Pointer with appended token.
|
||||
*/
|
||||
template <typename T>
|
||||
CEREAL_RAPIDJSON_DISABLEIF_RETURN((internal::NotExpr<internal::IsSame<typename internal::RemoveConst<T>::Type, Ch> >), (GenericPointer))
|
||||
RAPIDJSON_DISABLEIF_RETURN((internal::NotExpr<internal::IsSame<typename internal::RemoveConst<T>::Type, Ch> >), (GenericPointer))
|
||||
Append(T* name, Allocator* allocator = 0) const {
|
||||
return Append(name, StrLen(name), allocator);
|
||||
return Append(name, internal::StrLen(name), allocator);
|
||||
}
|
||||
|
||||
#if CEREAL_RAPIDJSON_HAS_STDSTRING
|
||||
#if RAPIDJSON_HAS_STDSTRING
|
||||
//! Append a name token, and return a new Pointer
|
||||
/*!
|
||||
\param name Name to be appended.
|
||||
@ -274,7 +310,7 @@ public:
|
||||
else {
|
||||
Ch name[21];
|
||||
for (size_t i = 0; i <= length; i++)
|
||||
name[i] = buffer[i];
|
||||
name[i] = static_cast<Ch>(buffer[i]);
|
||||
Token token = { name, length, index };
|
||||
return Append(token, allocator);
|
||||
}
|
||||
@ -290,8 +326,8 @@ public:
|
||||
if (token.IsString())
|
||||
return Append(token.GetString(), token.GetStringLength(), allocator);
|
||||
else {
|
||||
CEREAL_RAPIDJSON_ASSERT(token.IsUint64());
|
||||
CEREAL_RAPIDJSON_ASSERT(token.GetUint64() <= SizeType(~0));
|
||||
RAPIDJSON_ASSERT(token.IsUint64());
|
||||
RAPIDJSON_ASSERT(token.GetUint64() <= SizeType(~0));
|
||||
return Append(static_cast<SizeType>(token.GetUint64()), allocator);
|
||||
}
|
||||
}
|
||||
@ -353,6 +389,33 @@ public:
|
||||
*/
|
||||
bool operator!=(const GenericPointer& rhs) const { return !(*this == rhs); }
|
||||
|
||||
//! Less than operator.
|
||||
/*!
|
||||
\note Invalid pointers are always greater than valid ones.
|
||||
*/
|
||||
bool operator<(const GenericPointer& rhs) const {
|
||||
if (!IsValid())
|
||||
return false;
|
||||
if (!rhs.IsValid())
|
||||
return true;
|
||||
|
||||
if (tokenCount_ != rhs.tokenCount_)
|
||||
return tokenCount_ < rhs.tokenCount_;
|
||||
|
||||
for (size_t i = 0; i < tokenCount_; i++) {
|
||||
if (tokens_[i].index != rhs.tokens_[i].index)
|
||||
return tokens_[i].index < rhs.tokens_[i].index;
|
||||
|
||||
if (tokens_[i].length != rhs.tokens_[i].length)
|
||||
return tokens_[i].length < rhs.tokens_[i].length;
|
||||
|
||||
if (int cmp = std::memcmp(tokens_[i].name, rhs.tokens_[i].name, sizeof(Ch) * tokens_[i].length))
|
||||
return cmp < 0;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
//@}
|
||||
|
||||
//!@name Stringify
|
||||
@ -399,7 +462,7 @@ public:
|
||||
\return The resolved newly created (a JSON Null value), or already exists value.
|
||||
*/
|
||||
ValueType& Create(ValueType& root, typename ValueType::AllocatorType& allocator, bool* alreadyExist = 0) const {
|
||||
CEREAL_RAPIDJSON_ASSERT(IsValid());
|
||||
RAPIDJSON_ASSERT(IsValid());
|
||||
ValueType* v = &root;
|
||||
bool exist = true;
|
||||
for (const Token *t = tokens_; t != tokens_ + tokenCount_; ++t) {
|
||||
@ -428,10 +491,11 @@ public:
|
||||
v = &((*v)[t->index]);
|
||||
}
|
||||
else {
|
||||
typename ValueType::MemberIterator m = v->FindMember(GenericStringRef<Ch>(t->name, t->length));
|
||||
typename ValueType::MemberIterator m = v->FindMember(GenericValue<EncodingType>(GenericStringRef<Ch>(t->name, t->length)));
|
||||
if (m == v->MemberEnd()) {
|
||||
v->AddMember(ValueType(t->name, t->length, allocator).Move(), ValueType().Move(), allocator);
|
||||
v = &(--v->MemberEnd())->value; // Assumes AddMember() appends at the end
|
||||
m = v->MemberEnd();
|
||||
v = &(--m)->value; // Assumes AddMember() appends at the end
|
||||
exist = false;
|
||||
}
|
||||
else
|
||||
@ -459,6 +523,70 @@ public:
|
||||
|
||||
//@}
|
||||
|
||||
//!@name Compute URI
|
||||
//@{
|
||||
|
||||
//! Compute the in-scope URI for a subtree.
|
||||
// For use with JSON pointers into JSON schema documents.
|
||||
/*!
|
||||
\param root Root value of a DOM sub-tree to be resolved. It can be any value other than document root.
|
||||
\param rootUri Root URI
|
||||
\param unresolvedTokenIndex If the pointer cannot resolve a token in the pointer, this parameter can obtain the index of unresolved token.
|
||||
\param allocator Allocator for Uris
|
||||
\return Uri if it can be resolved. Otherwise null.
|
||||
|
||||
\note
|
||||
There are only 3 situations when a URI cannot be resolved:
|
||||
1. A value in the path is not an array nor object.
|
||||
2. An object value does not contain the token.
|
||||
3. A token is out of range of an array value.
|
||||
|
||||
Use unresolvedTokenIndex to retrieve the token index.
|
||||
*/
|
||||
UriType GetUri(ValueType& root, const UriType& rootUri, size_t* unresolvedTokenIndex = 0, Allocator* allocator = 0) const {
|
||||
static const Ch kIdString[] = { 'i', 'd', '\0' };
|
||||
static const ValueType kIdValue(kIdString, 2);
|
||||
UriType base = UriType(rootUri, allocator);
|
||||
RAPIDJSON_ASSERT(IsValid());
|
||||
ValueType* v = &root;
|
||||
for (const Token *t = tokens_; t != tokens_ + tokenCount_; ++t) {
|
||||
switch (v->GetType()) {
|
||||
case kObjectType:
|
||||
{
|
||||
// See if we have an id, and if so resolve with the current base
|
||||
typename ValueType::MemberIterator m = v->FindMember(kIdValue);
|
||||
if (m != v->MemberEnd() && (m->value).IsString()) {
|
||||
UriType here = UriType(m->value, allocator).Resolve(base, allocator);
|
||||
base = here;
|
||||
}
|
||||
m = v->FindMember(GenericValue<EncodingType>(GenericStringRef<Ch>(t->name, t->length)));
|
||||
if (m == v->MemberEnd())
|
||||
break;
|
||||
v = &m->value;
|
||||
}
|
||||
continue;
|
||||
case kArrayType:
|
||||
if (t->index == kPointerInvalidIndex || t->index >= v->Size())
|
||||
break;
|
||||
v = &((*v)[t->index]);
|
||||
continue;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
// Error: unresolved token
|
||||
if (unresolvedTokenIndex)
|
||||
*unresolvedTokenIndex = static_cast<size_t>(t - tokens_);
|
||||
return UriType(allocator);
|
||||
}
|
||||
return base;
|
||||
}
|
||||
|
||||
UriType GetUri(const ValueType& root, const UriType& rootUri, size_t* unresolvedTokenIndex = 0, Allocator* allocator = 0) const {
|
||||
return GetUri(const_cast<ValueType&>(root), rootUri, unresolvedTokenIndex, allocator);
|
||||
}
|
||||
|
||||
|
||||
//!@name Query value
|
||||
//@{
|
||||
|
||||
@ -477,13 +605,13 @@ public:
|
||||
Use unresolvedTokenIndex to retrieve the token index.
|
||||
*/
|
||||
ValueType* Get(ValueType& root, size_t* unresolvedTokenIndex = 0) const {
|
||||
CEREAL_RAPIDJSON_ASSERT(IsValid());
|
||||
RAPIDJSON_ASSERT(IsValid());
|
||||
ValueType* v = &root;
|
||||
for (const Token *t = tokens_; t != tokens_ + tokenCount_; ++t) {
|
||||
switch (v->GetType()) {
|
||||
case kObjectType:
|
||||
{
|
||||
typename ValueType::MemberIterator m = v->FindMember(GenericStringRef<Ch>(t->name, t->length));
|
||||
typename ValueType::MemberIterator m = v->FindMember(GenericValue<EncodingType>(GenericStringRef<Ch>(t->name, t->length)));
|
||||
if (m == v->MemberEnd())
|
||||
break;
|
||||
v = &m->value;
|
||||
@ -532,22 +660,22 @@ public:
|
||||
*/
|
||||
ValueType& GetWithDefault(ValueType& root, const ValueType& defaultValue, typename ValueType::AllocatorType& allocator) const {
|
||||
bool alreadyExist;
|
||||
Value& v = Create(root, allocator, &alreadyExist);
|
||||
ValueType& v = Create(root, allocator, &alreadyExist);
|
||||
return alreadyExist ? v : v.CopyFrom(defaultValue, allocator);
|
||||
}
|
||||
|
||||
//! Query a value in a subtree with default null-terminated string.
|
||||
ValueType& GetWithDefault(ValueType& root, const Ch* defaultValue, typename ValueType::AllocatorType& allocator) const {
|
||||
bool alreadyExist;
|
||||
Value& v = Create(root, allocator, &alreadyExist);
|
||||
ValueType& v = Create(root, allocator, &alreadyExist);
|
||||
return alreadyExist ? v : v.SetString(defaultValue, allocator);
|
||||
}
|
||||
|
||||
#if CEREAL_RAPIDJSON_HAS_STDSTRING
|
||||
#if RAPIDJSON_HAS_STDSTRING
|
||||
//! Query a value in a subtree with default std::basic_string.
|
||||
ValueType& GetWithDefault(ValueType& root, const std::basic_string<Ch>& defaultValue, typename ValueType::AllocatorType& allocator) const {
|
||||
bool alreadyExist;
|
||||
Value& v = Create(root, allocator, &alreadyExist);
|
||||
ValueType& v = Create(root, allocator, &alreadyExist);
|
||||
return alreadyExist ? v : v.SetString(defaultValue, allocator);
|
||||
}
|
||||
#endif
|
||||
@ -557,7 +685,7 @@ public:
|
||||
\tparam T Either \ref Type, \c int, \c unsigned, \c int64_t, \c uint64_t, \c bool
|
||||
*/
|
||||
template <typename T>
|
||||
CEREAL_RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T>, internal::IsGenericValue<T> >), (ValueType&))
|
||||
RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T>, internal::IsGenericValue<T> >), (ValueType&))
|
||||
GetWithDefault(ValueType& root, T defaultValue, typename ValueType::AllocatorType& allocator) const {
|
||||
return GetWithDefault(root, ValueType(defaultValue).Move(), allocator);
|
||||
}
|
||||
@ -574,7 +702,7 @@ public:
|
||||
return GetWithDefault(document, defaultValue, document.GetAllocator());
|
||||
}
|
||||
|
||||
#if CEREAL_RAPIDJSON_HAS_STDSTRING
|
||||
#if RAPIDJSON_HAS_STDSTRING
|
||||
//! Query a value in a document with default std::basic_string.
|
||||
template <typename stackAllocator>
|
||||
ValueType& GetWithDefault(GenericDocument<EncodingType, typename ValueType::AllocatorType, stackAllocator>& document, const std::basic_string<Ch>& defaultValue) const {
|
||||
@ -587,7 +715,7 @@ public:
|
||||
\tparam T Either \ref Type, \c int, \c unsigned, \c int64_t, \c uint64_t, \c bool
|
||||
*/
|
||||
template <typename T, typename stackAllocator>
|
||||
CEREAL_RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T>, internal::IsGenericValue<T> >), (ValueType&))
|
||||
RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T>, internal::IsGenericValue<T> >), (ValueType&))
|
||||
GetWithDefault(GenericDocument<EncodingType, typename ValueType::AllocatorType, stackAllocator>& document, T defaultValue) const {
|
||||
return GetWithDefault(document, defaultValue, document.GetAllocator());
|
||||
}
|
||||
@ -621,7 +749,7 @@ public:
|
||||
return Create(root, allocator) = ValueType(value, allocator).Move();
|
||||
}
|
||||
|
||||
#if CEREAL_RAPIDJSON_HAS_STDSTRING
|
||||
#if RAPIDJSON_HAS_STDSTRING
|
||||
//! Set a std::basic_string in a subtree.
|
||||
ValueType& Set(ValueType& root, const std::basic_string<Ch>& value, typename ValueType::AllocatorType& allocator) const {
|
||||
return Create(root, allocator) = ValueType(value, allocator).Move();
|
||||
@ -633,7 +761,7 @@ public:
|
||||
\tparam T Either \ref Type, \c int, \c unsigned, \c int64_t, \c uint64_t, \c bool
|
||||
*/
|
||||
template <typename T>
|
||||
CEREAL_RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T>, internal::IsGenericValue<T> >), (ValueType&))
|
||||
RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T>, internal::IsGenericValue<T> >), (ValueType&))
|
||||
Set(ValueType& root, T value, typename ValueType::AllocatorType& allocator) const {
|
||||
return Create(root, allocator) = ValueType(value).Move();
|
||||
}
|
||||
@ -656,7 +784,7 @@ public:
|
||||
return Create(document) = ValueType(value, document.GetAllocator()).Move();
|
||||
}
|
||||
|
||||
#if CEREAL_RAPIDJSON_HAS_STDSTRING
|
||||
#if RAPIDJSON_HAS_STDSTRING
|
||||
//! Sets a std::basic_string in a document.
|
||||
template <typename stackAllocator>
|
||||
ValueType& Set(GenericDocument<EncodingType, typename ValueType::AllocatorType, stackAllocator>& document, const std::basic_string<Ch>& value) const {
|
||||
@ -669,7 +797,7 @@ public:
|
||||
\tparam T Either \ref Type, \c int, \c unsigned, \c int64_t, \c uint64_t, \c bool
|
||||
*/
|
||||
template <typename T, typename stackAllocator>
|
||||
CEREAL_RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T>, internal::IsGenericValue<T> >), (ValueType&))
|
||||
RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T>, internal::IsGenericValue<T> >), (ValueType&))
|
||||
Set(GenericDocument<EncodingType, typename ValueType::AllocatorType, stackAllocator>& document, T value) const {
|
||||
return Create(document) = value;
|
||||
}
|
||||
@ -709,7 +837,7 @@ public:
|
||||
\note Erasing with an empty pointer \c Pointer(""), i.e. the root, always fail and return false.
|
||||
*/
|
||||
bool Erase(ValueType& root) const {
|
||||
CEREAL_RAPIDJSON_ASSERT(IsValid());
|
||||
RAPIDJSON_ASSERT(IsValid());
|
||||
if (tokenCount_ == 0) // Cannot erase the root
|
||||
return false;
|
||||
|
||||
@ -719,7 +847,7 @@ public:
|
||||
switch (v->GetType()) {
|
||||
case kObjectType:
|
||||
{
|
||||
typename ValueType::MemberIterator m = v->FindMember(GenericStringRef<Ch>(t->name, t->length));
|
||||
typename ValueType::MemberIterator m = v->FindMember(GenericValue<EncodingType>(GenericStringRef<Ch>(t->name, t->length)));
|
||||
if (m == v->MemberEnd())
|
||||
return false;
|
||||
v = &m->value;
|
||||
@ -758,7 +886,7 @@ private:
|
||||
*/
|
||||
Ch* CopyFromRaw(const GenericPointer& rhs, size_t extraToken = 0, size_t extraNameBufferSize = 0) {
|
||||
if (!allocator_) // allocator is independently owned.
|
||||
ownAllocator_ = allocator_ = CEREAL_RAPIDJSON_NEW(Allocator());
|
||||
ownAllocator_ = allocator_ = RAPIDJSON_NEW(Allocator)();
|
||||
|
||||
size_t nameBufferSize = rhs.tokenCount_; // null terminators for tokens
|
||||
for (Token *t = rhs.tokens_; t != rhs.tokens_ + rhs.tokenCount_; ++t)
|
||||
@ -800,13 +928,13 @@ private:
|
||||
*/
|
||||
#endif
|
||||
void Parse(const Ch* source, size_t length) {
|
||||
CEREAL_RAPIDJSON_ASSERT(source != NULL);
|
||||
CEREAL_RAPIDJSON_ASSERT(nameBuffer_ == 0);
|
||||
CEREAL_RAPIDJSON_ASSERT(tokens_ == 0);
|
||||
RAPIDJSON_ASSERT(source != NULL);
|
||||
RAPIDJSON_ASSERT(nameBuffer_ == 0);
|
||||
RAPIDJSON_ASSERT(tokens_ == 0);
|
||||
|
||||
// Create own allocator if user did not supply.
|
||||
if (!allocator_)
|
||||
ownAllocator_ = allocator_ = CEREAL_RAPIDJSON_NEW(Allocator());
|
||||
ownAllocator_ = allocator_ = RAPIDJSON_NEW(Allocator)();
|
||||
|
||||
// Count number of '/' as tokenCount
|
||||
tokenCount_ = 0;
|
||||
@ -831,7 +959,7 @@ private:
|
||||
}
|
||||
|
||||
while (i < length) {
|
||||
CEREAL_RAPIDJSON_ASSERT(source[i] == '/');
|
||||
RAPIDJSON_ASSERT(source[i] == '/');
|
||||
i++; // consumes '/'
|
||||
|
||||
token->name = name;
|
||||
@ -918,7 +1046,7 @@ private:
|
||||
token++;
|
||||
}
|
||||
|
||||
CEREAL_RAPIDJSON_ASSERT(name <= nameBuffer_ + length); // Should not overflow buffer
|
||||
RAPIDJSON_ASSERT(name <= nameBuffer_ + length); // Should not overflow buffer
|
||||
parseErrorCode_ = kPointerParseErrorNone;
|
||||
return;
|
||||
|
||||
@ -939,7 +1067,7 @@ private:
|
||||
*/
|
||||
template<bool uriFragment, typename OutputStream>
|
||||
bool Stringify(OutputStream& os) const {
|
||||
CEREAL_RAPIDJSON_ASSERT(IsValid());
|
||||
RAPIDJSON_ASSERT(IsValid());
|
||||
|
||||
if (uriFragment)
|
||||
os.Put('#');
|
||||
@ -1029,8 +1157,8 @@ private:
|
||||
unsigned char u = static_cast<unsigned char>(c);
|
||||
static const char hexDigits[16] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
|
||||
os_.Put('%');
|
||||
os_.Put(hexDigits[u >> 4]);
|
||||
os_.Put(hexDigits[u & 15]);
|
||||
os_.Put(static_cast<typename OutputStream::Ch>(hexDigits[u >> 4]));
|
||||
os_.Put(static_cast<typename OutputStream::Ch>(hexDigits[u & 15]));
|
||||
}
|
||||
private:
|
||||
OutputStream& os_;
|
||||
@ -1109,7 +1237,7 @@ typename T::ValueType& GetValueByPointerWithDefault(T& root, const GenericPointe
|
||||
return pointer.GetWithDefault(root, defaultValue, a);
|
||||
}
|
||||
|
||||
#if CEREAL_RAPIDJSON_HAS_STDSTRING
|
||||
#if RAPIDJSON_HAS_STDSTRING
|
||||
template <typename T>
|
||||
typename T::ValueType& GetValueByPointerWithDefault(T& root, const GenericPointer<typename T::ValueType>& pointer, const std::basic_string<typename T::Ch>& defaultValue, typename T::AllocatorType& a) {
|
||||
return pointer.GetWithDefault(root, defaultValue, a);
|
||||
@ -1117,7 +1245,7 @@ typename T::ValueType& GetValueByPointerWithDefault(T& root, const GenericPointe
|
||||
#endif
|
||||
|
||||
template <typename T, typename T2>
|
||||
CEREAL_RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T2>, internal::IsGenericValue<T2> >), (typename T::ValueType&))
|
||||
RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T2>, internal::IsGenericValue<T2> >), (typename T::ValueType&))
|
||||
GetValueByPointerWithDefault(T& root, const GenericPointer<typename T::ValueType>& pointer, T2 defaultValue, typename T::AllocatorType& a) {
|
||||
return pointer.GetWithDefault(root, defaultValue, a);
|
||||
}
|
||||
@ -1132,7 +1260,7 @@ typename T::ValueType& GetValueByPointerWithDefault(T& root, const CharType(&sou
|
||||
return GenericPointer<typename T::ValueType>(source, N - 1).GetWithDefault(root, defaultValue, a);
|
||||
}
|
||||
|
||||
#if CEREAL_RAPIDJSON_HAS_STDSTRING
|
||||
#if RAPIDJSON_HAS_STDSTRING
|
||||
template <typename T, typename CharType, size_t N>
|
||||
typename T::ValueType& GetValueByPointerWithDefault(T& root, const CharType(&source)[N], const std::basic_string<typename T::Ch>& defaultValue, typename T::AllocatorType& a) {
|
||||
return GenericPointer<typename T::ValueType>(source, N - 1).GetWithDefault(root, defaultValue, a);
|
||||
@ -1140,7 +1268,7 @@ typename T::ValueType& GetValueByPointerWithDefault(T& root, const CharType(&sou
|
||||
#endif
|
||||
|
||||
template <typename T, typename CharType, size_t N, typename T2>
|
||||
CEREAL_RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T2>, internal::IsGenericValue<T2> >), (typename T::ValueType&))
|
||||
RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T2>, internal::IsGenericValue<T2> >), (typename T::ValueType&))
|
||||
GetValueByPointerWithDefault(T& root, const CharType(&source)[N], T2 defaultValue, typename T::AllocatorType& a) {
|
||||
return GenericPointer<typename T::ValueType>(source, N - 1).GetWithDefault(root, defaultValue, a);
|
||||
}
|
||||
@ -1157,7 +1285,7 @@ typename DocumentType::ValueType& GetValueByPointerWithDefault(DocumentType& doc
|
||||
return pointer.GetWithDefault(document, defaultValue);
|
||||
}
|
||||
|
||||
#if CEREAL_RAPIDJSON_HAS_STDSTRING
|
||||
#if RAPIDJSON_HAS_STDSTRING
|
||||
template <typename DocumentType>
|
||||
typename DocumentType::ValueType& GetValueByPointerWithDefault(DocumentType& document, const GenericPointer<typename DocumentType::ValueType>& pointer, const std::basic_string<typename DocumentType::Ch>& defaultValue) {
|
||||
return pointer.GetWithDefault(document, defaultValue);
|
||||
@ -1165,7 +1293,7 @@ typename DocumentType::ValueType& GetValueByPointerWithDefault(DocumentType& doc
|
||||
#endif
|
||||
|
||||
template <typename DocumentType, typename T2>
|
||||
CEREAL_RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T2>, internal::IsGenericValue<T2> >), (typename DocumentType::ValueType&))
|
||||
RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T2>, internal::IsGenericValue<T2> >), (typename DocumentType::ValueType&))
|
||||
GetValueByPointerWithDefault(DocumentType& document, const GenericPointer<typename DocumentType::ValueType>& pointer, T2 defaultValue) {
|
||||
return pointer.GetWithDefault(document, defaultValue);
|
||||
}
|
||||
@ -1180,7 +1308,7 @@ typename DocumentType::ValueType& GetValueByPointerWithDefault(DocumentType& doc
|
||||
return GenericPointer<typename DocumentType::ValueType>(source, N - 1).GetWithDefault(document, defaultValue);
|
||||
}
|
||||
|
||||
#if CEREAL_RAPIDJSON_HAS_STDSTRING
|
||||
#if RAPIDJSON_HAS_STDSTRING
|
||||
template <typename DocumentType, typename CharType, size_t N>
|
||||
typename DocumentType::ValueType& GetValueByPointerWithDefault(DocumentType& document, const CharType(&source)[N], const std::basic_string<typename DocumentType::Ch>& defaultValue) {
|
||||
return GenericPointer<typename DocumentType::ValueType>(source, N - 1).GetWithDefault(document, defaultValue);
|
||||
@ -1188,7 +1316,7 @@ typename DocumentType::ValueType& GetValueByPointerWithDefault(DocumentType& doc
|
||||
#endif
|
||||
|
||||
template <typename DocumentType, typename CharType, size_t N, typename T2>
|
||||
CEREAL_RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T2>, internal::IsGenericValue<T2> >), (typename DocumentType::ValueType&))
|
||||
RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T2>, internal::IsGenericValue<T2> >), (typename DocumentType::ValueType&))
|
||||
GetValueByPointerWithDefault(DocumentType& document, const CharType(&source)[N], T2 defaultValue) {
|
||||
return GenericPointer<typename DocumentType::ValueType>(source, N - 1).GetWithDefault(document, defaultValue);
|
||||
}
|
||||
@ -1210,7 +1338,7 @@ typename T::ValueType& SetValueByPointer(T& root, const GenericPointer<typename
|
||||
return pointer.Set(root, value, a);
|
||||
}
|
||||
|
||||
#if CEREAL_RAPIDJSON_HAS_STDSTRING
|
||||
#if RAPIDJSON_HAS_STDSTRING
|
||||
template <typename T>
|
||||
typename T::ValueType& SetValueByPointer(T& root, const GenericPointer<typename T::ValueType>& pointer, const std::basic_string<typename T::Ch>& value, typename T::AllocatorType& a) {
|
||||
return pointer.Set(root, value, a);
|
||||
@ -1218,7 +1346,7 @@ typename T::ValueType& SetValueByPointer(T& root, const GenericPointer<typename
|
||||
#endif
|
||||
|
||||
template <typename T, typename T2>
|
||||
CEREAL_RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T2>, internal::IsGenericValue<T2> >), (typename T::ValueType&))
|
||||
RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T2>, internal::IsGenericValue<T2> >), (typename T::ValueType&))
|
||||
SetValueByPointer(T& root, const GenericPointer<typename T::ValueType>& pointer, T2 value, typename T::AllocatorType& a) {
|
||||
return pointer.Set(root, value, a);
|
||||
}
|
||||
@ -1238,7 +1366,7 @@ typename T::ValueType& SetValueByPointer(T& root, const CharType(&source)[N], co
|
||||
return GenericPointer<typename T::ValueType>(source, N - 1).Set(root, value, a);
|
||||
}
|
||||
|
||||
#if CEREAL_RAPIDJSON_HAS_STDSTRING
|
||||
#if RAPIDJSON_HAS_STDSTRING
|
||||
template <typename T, typename CharType, size_t N>
|
||||
typename T::ValueType& SetValueByPointer(T& root, const CharType(&source)[N], const std::basic_string<typename T::Ch>& value, typename T::AllocatorType& a) {
|
||||
return GenericPointer<typename T::ValueType>(source, N - 1).Set(root, value, a);
|
||||
@ -1246,7 +1374,7 @@ typename T::ValueType& SetValueByPointer(T& root, const CharType(&source)[N], co
|
||||
#endif
|
||||
|
||||
template <typename T, typename CharType, size_t N, typename T2>
|
||||
CEREAL_RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T2>, internal::IsGenericValue<T2> >), (typename T::ValueType&))
|
||||
RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T2>, internal::IsGenericValue<T2> >), (typename T::ValueType&))
|
||||
SetValueByPointer(T& root, const CharType(&source)[N], T2 value, typename T::AllocatorType& a) {
|
||||
return GenericPointer<typename T::ValueType>(source, N - 1).Set(root, value, a);
|
||||
}
|
||||
@ -1268,7 +1396,7 @@ typename DocumentType::ValueType& SetValueByPointer(DocumentType& document, cons
|
||||
return pointer.Set(document, value);
|
||||
}
|
||||
|
||||
#if CEREAL_RAPIDJSON_HAS_STDSTRING
|
||||
#if RAPIDJSON_HAS_STDSTRING
|
||||
template <typename DocumentType>
|
||||
typename DocumentType::ValueType& SetValueByPointer(DocumentType& document, const GenericPointer<typename DocumentType::ValueType>& pointer, const std::basic_string<typename DocumentType::Ch>& value) {
|
||||
return pointer.Set(document, value);
|
||||
@ -1276,7 +1404,7 @@ typename DocumentType::ValueType& SetValueByPointer(DocumentType& document, cons
|
||||
#endif
|
||||
|
||||
template <typename DocumentType, typename T2>
|
||||
CEREAL_RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T2>, internal::IsGenericValue<T2> >), (typename DocumentType::ValueType&))
|
||||
RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T2>, internal::IsGenericValue<T2> >), (typename DocumentType::ValueType&))
|
||||
SetValueByPointer(DocumentType& document, const GenericPointer<typename DocumentType::ValueType>& pointer, T2 value) {
|
||||
return pointer.Set(document, value);
|
||||
}
|
||||
@ -1296,7 +1424,7 @@ typename DocumentType::ValueType& SetValueByPointer(DocumentType& document, cons
|
||||
return GenericPointer<typename DocumentType::ValueType>(source, N - 1).Set(document, value);
|
||||
}
|
||||
|
||||
#if CEREAL_RAPIDJSON_HAS_STDSTRING
|
||||
#if RAPIDJSON_HAS_STDSTRING
|
||||
template <typename DocumentType, typename CharType, size_t N>
|
||||
typename DocumentType::ValueType& SetValueByPointer(DocumentType& document, const CharType(&source)[N], const std::basic_string<typename DocumentType::Ch>& value) {
|
||||
return GenericPointer<typename DocumentType::ValueType>(source, N - 1).Set(document, value);
|
||||
@ -1304,7 +1432,7 @@ typename DocumentType::ValueType& SetValueByPointer(DocumentType& document, cons
|
||||
#endif
|
||||
|
||||
template <typename DocumentType, typename CharType, size_t N, typename T2>
|
||||
CEREAL_RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T2>, internal::IsGenericValue<T2> >), (typename DocumentType::ValueType&))
|
||||
RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T2>, internal::IsGenericValue<T2> >), (typename DocumentType::ValueType&))
|
||||
SetValueByPointer(DocumentType& document, const CharType(&source)[N], T2 value) {
|
||||
return GenericPointer<typename DocumentType::ValueType>(source, N - 1).Set(document, value);
|
||||
}
|
||||
@ -1345,14 +1473,10 @@ bool EraseValueByPointer(T& root, const CharType(&source)[N]) {
|
||||
|
||||
//@}
|
||||
|
||||
CEREAL_RAPIDJSON_NAMESPACE_END
|
||||
RAPIDJSON_NAMESPACE_END
|
||||
|
||||
#ifdef __clang__
|
||||
CEREAL_RAPIDJSON_DIAG_POP
|
||||
#if defined(__clang__) || defined(_MSC_VER)
|
||||
RAPIDJSON_DIAG_POP
|
||||
#endif
|
||||
|
||||
#ifdef _MSC_VER
|
||||
CEREAL_RAPIDJSON_DIAG_POP
|
||||
#endif
|
||||
|
||||
#endif // CEREAL_RAPIDJSON_POINTER_H_
|
||||
#endif // RAPIDJSON_POINTER_H_
|
||||
|
100
external/cereal/external/rapidjson/prettywriter.h
vendored
100
external/cereal/external/rapidjson/prettywriter.h
vendored
@ -1,6 +1,6 @@
|
||||
// Tencent is pleased to support the open source community by making RapidJSON available.
|
||||
//
|
||||
// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
|
||||
// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip.
|
||||
//
|
||||
// Licensed under the MIT License (the "License"); you may not use this file except
|
||||
// in compliance with the License. You may obtain a copy of the License at
|
||||
@ -12,17 +12,22 @@
|
||||
// CONDITIONS OF ANY KIND, either express or implied. See the License for the
|
||||
// specific language governing permissions and limitations under the License.
|
||||
|
||||
#ifndef CEREAL_RAPIDJSON_PRETTYWRITER_H_
|
||||
#define CEREAL_RAPIDJSON_PRETTYWRITER_H_
|
||||
#ifndef RAPIDJSON_PRETTYWRITER_H_
|
||||
#define RAPIDJSON_PRETTYWRITER_H_
|
||||
|
||||
#include "writer.h"
|
||||
|
||||
#ifdef __GNUC__
|
||||
CEREAL_RAPIDJSON_DIAG_PUSH
|
||||
CEREAL_RAPIDJSON_DIAG_OFF(effc++)
|
||||
RAPIDJSON_DIAG_PUSH
|
||||
RAPIDJSON_DIAG_OFF(effc++)
|
||||
#endif
|
||||
|
||||
CEREAL_RAPIDJSON_NAMESPACE_BEGIN
|
||||
#if defined(__clang__)
|
||||
RAPIDJSON_DIAG_PUSH
|
||||
RAPIDJSON_DIAG_OFF(c++98-compat)
|
||||
#endif
|
||||
|
||||
RAPIDJSON_NAMESPACE_BEGIN
|
||||
|
||||
//! Combination of PrettyWriter format flags.
|
||||
/*! \see PrettyWriter::SetFormatOptions
|
||||
@ -34,7 +39,7 @@ enum PrettyFormatOptions {
|
||||
|
||||
//! Writer with indentation and spacing.
|
||||
/*!
|
||||
\tparam OutputStream Type of ouptut os.
|
||||
\tparam OutputStream Type of output os.
|
||||
\tparam SourceEncoding Encoding of source string.
|
||||
\tparam TargetEncoding Encoding of output stream.
|
||||
\tparam StackAllocator Type of allocator for allocating memory of stack.
|
||||
@ -42,7 +47,7 @@ enum PrettyFormatOptions {
|
||||
template<typename OutputStream, typename SourceEncoding = UTF8<>, typename TargetEncoding = UTF8<>, typename StackAllocator = CrtAllocator, unsigned writeFlags = kWriteDefaultFlags>
|
||||
class PrettyWriter : public Writer<OutputStream, SourceEncoding, TargetEncoding, StackAllocator, writeFlags> {
|
||||
public:
|
||||
typedef Writer<OutputStream, SourceEncoding, TargetEncoding, StackAllocator> Base;
|
||||
typedef Writer<OutputStream, SourceEncoding, TargetEncoding, StackAllocator, writeFlags> Base;
|
||||
typedef typename Base::Ch Ch;
|
||||
|
||||
//! Constructor
|
||||
@ -55,7 +60,12 @@ public:
|
||||
|
||||
|
||||
explicit PrettyWriter(StackAllocator* allocator = 0, size_t levelDepth = Base::kDefaultLevelDepth) :
|
||||
Base(allocator, levelDepth), indentChar_(' '), indentCharCount_(4) {}
|
||||
Base(allocator, levelDepth), indentChar_(' '), indentCharCount_(4), formatOptions_(kFormatDefault) {}
|
||||
|
||||
#if RAPIDJSON_HAS_CXX11_RVALUE_REFS
|
||||
PrettyWriter(PrettyWriter&& rhs) :
|
||||
Base(std::forward<PrettyWriter>(rhs)), indentChar_(rhs.indentChar_), indentCharCount_(rhs.indentCharCount_), formatOptions_(rhs.formatOptions_) {}
|
||||
#endif
|
||||
|
||||
//! Set custom indentation.
|
||||
/*! \param indentChar Character for indentation. Must be whitespace character (' ', '\\t', '\\n', '\\r').
|
||||
@ -63,7 +73,7 @@ public:
|
||||
\note The default indentation is 4 spaces.
|
||||
*/
|
||||
PrettyWriter& SetIndent(Ch indentChar, unsigned indentCharCount) {
|
||||
CEREAL_RAPIDJSON_ASSERT(indentChar == ' ' || indentChar == '\t' || indentChar == '\n' || indentChar == '\r');
|
||||
RAPIDJSON_ASSERT(indentChar == ' ' || indentChar == '\t' || indentChar == '\n' || indentChar == '\r');
|
||||
indentChar_ = indentChar;
|
||||
indentCharCount_ = indentCharCount;
|
||||
return *this;
|
||||
@ -82,27 +92,29 @@ public:
|
||||
*/
|
||||
//@{
|
||||
|
||||
bool Null() { PrettyPrefix(kNullType); return Base::WriteNull(); }
|
||||
bool Bool(bool b) { PrettyPrefix(b ? kTrueType : kFalseType); return Base::WriteBool(b); }
|
||||
bool Int(int i) { PrettyPrefix(kNumberType); return Base::WriteInt(i); }
|
||||
bool Uint(unsigned u) { PrettyPrefix(kNumberType); return Base::WriteUint(u); }
|
||||
bool Int64(int64_t i64) { PrettyPrefix(kNumberType); return Base::WriteInt64(i64); }
|
||||
bool Uint64(uint64_t u64) { PrettyPrefix(kNumberType); return Base::WriteUint64(u64); }
|
||||
bool Double(double d) { PrettyPrefix(kNumberType); return Base::WriteDouble(d); }
|
||||
bool Null() { PrettyPrefix(kNullType); return Base::EndValue(Base::WriteNull()); }
|
||||
bool Bool(bool b) { PrettyPrefix(b ? kTrueType : kFalseType); return Base::EndValue(Base::WriteBool(b)); }
|
||||
bool Int(int i) { PrettyPrefix(kNumberType); return Base::EndValue(Base::WriteInt(i)); }
|
||||
bool Uint(unsigned u) { PrettyPrefix(kNumberType); return Base::EndValue(Base::WriteUint(u)); }
|
||||
bool Int64(int64_t i64) { PrettyPrefix(kNumberType); return Base::EndValue(Base::WriteInt64(i64)); }
|
||||
bool Uint64(uint64_t u64) { PrettyPrefix(kNumberType); return Base::EndValue(Base::WriteUint64(u64)); }
|
||||
bool Double(double d) { PrettyPrefix(kNumberType); return Base::EndValue(Base::WriteDouble(d)); }
|
||||
|
||||
bool RawNumber(const Ch* str, SizeType length, bool copy = false) {
|
||||
RAPIDJSON_ASSERT(str != 0);
|
||||
(void)copy;
|
||||
PrettyPrefix(kNumberType);
|
||||
return Base::WriteString(str, length);
|
||||
return Base::EndValue(Base::WriteString(str, length));
|
||||
}
|
||||
|
||||
bool String(const Ch* str, SizeType length, bool copy = false) {
|
||||
RAPIDJSON_ASSERT(str != 0);
|
||||
(void)copy;
|
||||
PrettyPrefix(kStringType);
|
||||
return Base::WriteString(str, length);
|
||||
return Base::EndValue(Base::WriteString(str, length));
|
||||
}
|
||||
|
||||
#if CEREAL_RAPIDJSON_HAS_STDSTRING
|
||||
#if RAPIDJSON_HAS_STDSTRING
|
||||
bool String(const std::basic_string<Ch>& str) {
|
||||
return String(str.data(), SizeType(str.size()));
|
||||
}
|
||||
@ -116,7 +128,7 @@ public:
|
||||
|
||||
bool Key(const Ch* str, SizeType length, bool copy = false) { return String(str, length, copy); }
|
||||
|
||||
#if CEREAL_RAPIDJSON_HAS_STDSTRING
|
||||
#if RAPIDJSON_HAS_STDSTRING
|
||||
bool Key(const std::basic_string<Ch>& str) {
|
||||
return Key(str.data(), SizeType(str.size()));
|
||||
}
|
||||
@ -124,19 +136,21 @@ public:
|
||||
|
||||
bool EndObject(SizeType memberCount = 0) {
|
||||
(void)memberCount;
|
||||
CEREAL_RAPIDJSON_ASSERT(Base::level_stack_.GetSize() >= sizeof(typename Base::Level));
|
||||
CEREAL_RAPIDJSON_ASSERT(!Base::level_stack_.template Top<typename Base::Level>()->inArray);
|
||||
RAPIDJSON_ASSERT(Base::level_stack_.GetSize() >= sizeof(typename Base::Level)); // not inside an Object
|
||||
RAPIDJSON_ASSERT(!Base::level_stack_.template Top<typename Base::Level>()->inArray); // currently inside an Array, not Object
|
||||
RAPIDJSON_ASSERT(0 == Base::level_stack_.template Top<typename Base::Level>()->valueCount % 2); // Object has a Key without a Value
|
||||
|
||||
bool empty = Base::level_stack_.template Pop<typename Base::Level>(1)->valueCount == 0;
|
||||
|
||||
if (!empty) {
|
||||
Base::os_->Put('\n');
|
||||
WriteIndent();
|
||||
}
|
||||
bool ret = Base::WriteEndObject();
|
||||
bool ret = Base::EndValue(Base::WriteEndObject());
|
||||
(void)ret;
|
||||
CEREAL_RAPIDJSON_ASSERT(ret == true);
|
||||
RAPIDJSON_ASSERT(ret == true);
|
||||
if (Base::level_stack_.Empty()) // end of json text
|
||||
Base::os_->Flush();
|
||||
Base::Flush();
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -148,19 +162,19 @@ public:
|
||||
|
||||
bool EndArray(SizeType memberCount = 0) {
|
||||
(void)memberCount;
|
||||
CEREAL_RAPIDJSON_ASSERT(Base::level_stack_.GetSize() >= sizeof(typename Base::Level));
|
||||
CEREAL_RAPIDJSON_ASSERT(Base::level_stack_.template Top<typename Base::Level>()->inArray);
|
||||
RAPIDJSON_ASSERT(Base::level_stack_.GetSize() >= sizeof(typename Base::Level));
|
||||
RAPIDJSON_ASSERT(Base::level_stack_.template Top<typename Base::Level>()->inArray);
|
||||
bool empty = Base::level_stack_.template Pop<typename Base::Level>(1)->valueCount == 0;
|
||||
|
||||
if (!empty && !(formatOptions_ & kFormatSingleLineArray)) {
|
||||
Base::os_->Put('\n');
|
||||
WriteIndent();
|
||||
}
|
||||
bool ret = Base::WriteEndArray();
|
||||
bool ret = Base::EndValue(Base::WriteEndArray());
|
||||
(void)ret;
|
||||
CEREAL_RAPIDJSON_ASSERT(ret == true);
|
||||
RAPIDJSON_ASSERT(ret == true);
|
||||
if (Base::level_stack_.Empty()) // end of json text
|
||||
Base::os_->Flush();
|
||||
Base::Flush();
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -184,7 +198,11 @@ public:
|
||||
\param type Type of the root of json.
|
||||
\note When using PrettyWriter::RawValue(), the result json may not be indented correctly.
|
||||
*/
|
||||
bool RawValue(const Ch* json, size_t length, Type type) { PrettyPrefix(type); return Base::WriteRawValue(json, length); }
|
||||
bool RawValue(const Ch* json, size_t length, Type type) {
|
||||
RAPIDJSON_ASSERT(json != 0);
|
||||
PrettyPrefix(type);
|
||||
return Base::EndValue(Base::WriteRawValue(json, length));
|
||||
}
|
||||
|
||||
protected:
|
||||
void PrettyPrefix(Type type) {
|
||||
@ -222,18 +240,18 @@ protected:
|
||||
WriteIndent();
|
||||
}
|
||||
if (!level->inArray && level->valueCount % 2 == 0)
|
||||
CEREAL_RAPIDJSON_ASSERT(type == kStringType); // if it's in object, then even number should be a name
|
||||
RAPIDJSON_ASSERT(type == kStringType); // if it's in object, then even number should be a name
|
||||
level->valueCount++;
|
||||
}
|
||||
else {
|
||||
CEREAL_RAPIDJSON_ASSERT(!Base::hasRoot_); // Should only has one and only one root.
|
||||
RAPIDJSON_ASSERT(!Base::hasRoot_); // Should only has one and only one root.
|
||||
Base::hasRoot_ = true;
|
||||
}
|
||||
}
|
||||
|
||||
void WriteIndent() {
|
||||
size_t count = (Base::level_stack_.GetSize() / sizeof(typename Base::Level)) * indentCharCount_;
|
||||
PutN(*Base::os_, static_cast<typename TargetEncoding::Ch>(indentChar_), count);
|
||||
PutN(*Base::os_, static_cast<typename OutputStream::Ch>(indentChar_), count);
|
||||
}
|
||||
|
||||
Ch indentChar_;
|
||||
@ -246,10 +264,14 @@ private:
|
||||
PrettyWriter& operator=(const PrettyWriter&);
|
||||
};
|
||||
|
||||
CEREAL_RAPIDJSON_NAMESPACE_END
|
||||
RAPIDJSON_NAMESPACE_END
|
||||
|
||||
#ifdef __GNUC__
|
||||
CEREAL_RAPIDJSON_DIAG_POP
|
||||
#if defined(__clang__)
|
||||
RAPIDJSON_DIAG_POP
|
||||
#endif
|
||||
|
||||
#endif // CEREAL_RAPIDJSON_CEREAL_RAPIDJSON_H_
|
||||
#ifdef __GNUC__
|
||||
RAPIDJSON_DIAG_POP
|
||||
#endif
|
||||
|
||||
#endif // RAPIDJSON_RAPIDJSON_H_
|
||||
|
638
external/cereal/external/rapidjson/rapidjson.h
vendored
638
external/cereal/external/rapidjson/rapidjson.h
vendored
@ -1,6 +1,6 @@
|
||||
// Tencent is pleased to support the open source community by making RapidJSON available.
|
||||
//
|
||||
// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
|
||||
// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip.
|
||||
//
|
||||
// Licensed under the MIT License (the "License"); you may not use this file except
|
||||
// in compliance with the License. You may obtain a copy of the License at
|
||||
@ -12,24 +12,24 @@
|
||||
// CONDITIONS OF ANY KIND, either express or implied. See the License for the
|
||||
// specific language governing permissions and limitations under the License.
|
||||
|
||||
#ifndef CEREAL_RAPIDJSON_CEREAL_RAPIDJSON_H_
|
||||
#define CEREAL_RAPIDJSON_CEREAL_RAPIDJSON_H_
|
||||
#ifndef RAPIDJSON_RAPIDJSON_H_
|
||||
#define RAPIDJSON_RAPIDJSON_H_
|
||||
|
||||
/*!\file rapidjson.h
|
||||
\brief common definitions and configuration
|
||||
|
||||
\see CEREAL_RAPIDJSON_CONFIG
|
||||
\see RAPIDJSON_CONFIG
|
||||
*/
|
||||
|
||||
/*! \defgroup CEREAL_RAPIDJSON_CONFIG RapidJSON configuration
|
||||
/*! \defgroup RAPIDJSON_CONFIG RapidJSON configuration
|
||||
\brief Configuration macros for library features
|
||||
|
||||
Some RapidJSON features are configurable to adapt the library to a wide
|
||||
variety of platforms, environments and usage scenarios. Most of the
|
||||
features can be configured in terms of overriden or predefined
|
||||
features can be configured in terms of overridden or predefined
|
||||
preprocessor macros at compile-time.
|
||||
|
||||
Some additional customization is available in the \ref CEREAL_RAPIDJSON_ERRORS APIs.
|
||||
Some additional customization is available in the \ref RAPIDJSON_ERRORS APIs.
|
||||
|
||||
\note These macros should be given on the compiler command-line
|
||||
(where applicable) to avoid inconsistent values when compiling
|
||||
@ -40,43 +40,48 @@
|
||||
#include <cstring> // memset(), memcpy(), memmove(), memcmp()
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// CEREAL_RAPIDJSON_VERSION_STRING
|
||||
// RAPIDJSON_VERSION_STRING
|
||||
//
|
||||
// ALWAYS synchronize the following 3 macros with corresponding variables in /CMakeLists.txt.
|
||||
//
|
||||
|
||||
//!@cond CEREAL_RAPIDJSON_HIDDEN_FROM_DOXYGEN
|
||||
//!@cond RAPIDJSON_HIDDEN_FROM_DOXYGEN
|
||||
// token stringification
|
||||
#define CEREAL_RAPIDJSON_STRINGIFY(x) CEREAL_RAPIDJSON_DO_STRINGIFY(x)
|
||||
#define CEREAL_RAPIDJSON_DO_STRINGIFY(x) #x
|
||||
#define RAPIDJSON_STRINGIFY(x) RAPIDJSON_DO_STRINGIFY(x)
|
||||
#define RAPIDJSON_DO_STRINGIFY(x) #x
|
||||
|
||||
// token concatenation
|
||||
#define RAPIDJSON_JOIN(X, Y) RAPIDJSON_DO_JOIN(X, Y)
|
||||
#define RAPIDJSON_DO_JOIN(X, Y) RAPIDJSON_DO_JOIN2(X, Y)
|
||||
#define RAPIDJSON_DO_JOIN2(X, Y) X##Y
|
||||
//!@endcond
|
||||
|
||||
/*! \def CEREAL_RAPIDJSON_MAJOR_VERSION
|
||||
\ingroup CEREAL_RAPIDJSON_CONFIG
|
||||
/*! \def RAPIDJSON_MAJOR_VERSION
|
||||
\ingroup RAPIDJSON_CONFIG
|
||||
\brief Major version of RapidJSON in integer.
|
||||
*/
|
||||
/*! \def CEREAL_RAPIDJSON_MINOR_VERSION
|
||||
\ingroup CEREAL_RAPIDJSON_CONFIG
|
||||
/*! \def RAPIDJSON_MINOR_VERSION
|
||||
\ingroup RAPIDJSON_CONFIG
|
||||
\brief Minor version of RapidJSON in integer.
|
||||
*/
|
||||
/*! \def CEREAL_RAPIDJSON_PATCH_VERSION
|
||||
\ingroup CEREAL_RAPIDJSON_CONFIG
|
||||
/*! \def RAPIDJSON_PATCH_VERSION
|
||||
\ingroup RAPIDJSON_CONFIG
|
||||
\brief Patch version of RapidJSON in integer.
|
||||
*/
|
||||
/*! \def CEREAL_RAPIDJSON_VERSION_STRING
|
||||
\ingroup CEREAL_RAPIDJSON_CONFIG
|
||||
/*! \def RAPIDJSON_VERSION_STRING
|
||||
\ingroup RAPIDJSON_CONFIG
|
||||
\brief Version of RapidJSON in "<major>.<minor>.<patch>" string format.
|
||||
*/
|
||||
#define CEREAL_RAPIDJSON_MAJOR_VERSION 1
|
||||
#define CEREAL_RAPIDJSON_MINOR_VERSION 0
|
||||
#define CEREAL_RAPIDJSON_PATCH_VERSION 2
|
||||
#define CEREAL_RAPIDJSON_VERSION_STRING \
|
||||
CEREAL_RAPIDJSON_STRINGIFY(CEREAL_RAPIDJSON_MAJOR_VERSION.CEREAL_RAPIDJSON_MINOR_VERSION.CEREAL_RAPIDJSON_PATCH_VERSION)
|
||||
#define RAPIDJSON_MAJOR_VERSION 1
|
||||
#define RAPIDJSON_MINOR_VERSION 1
|
||||
#define RAPIDJSON_PATCH_VERSION 0
|
||||
#define RAPIDJSON_VERSION_STRING \
|
||||
RAPIDJSON_STRINGIFY(RAPIDJSON_MAJOR_VERSION.RAPIDJSON_MINOR_VERSION.RAPIDJSON_PATCH_VERSION)
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// CEREAL_RAPIDJSON_NAMESPACE_(BEGIN|END)
|
||||
/*! \def CEREAL_RAPIDJSON_NAMESPACE
|
||||
\ingroup CEREAL_RAPIDJSON_CONFIG
|
||||
// RAPIDJSON_NAMESPACE_(BEGIN|END)
|
||||
/*! \def RAPIDJSON_NAMESPACE
|
||||
\ingroup RAPIDJSON_CONFIG
|
||||
\brief provide custom rapidjson namespace
|
||||
|
||||
In order to avoid symbol clashes and/or "One Definition Rule" errors
|
||||
@ -84,52 +89,65 @@
|
||||
a single binary, users can customize the name of the main RapidJSON
|
||||
namespace.
|
||||
|
||||
In case of a single nesting level, defining \c CEREAL_RAPIDJSON_NAMESPACE
|
||||
In case of a single nesting level, defining \c RAPIDJSON_NAMESPACE
|
||||
to a custom name (e.g. \c MyRapidJSON) is sufficient. If multiple
|
||||
levels are needed, both \ref CEREAL_RAPIDJSON_NAMESPACE_BEGIN and \ref
|
||||
CEREAL_RAPIDJSON_NAMESPACE_END need to be defined as well:
|
||||
levels are needed, both \ref RAPIDJSON_NAMESPACE_BEGIN and \ref
|
||||
RAPIDJSON_NAMESPACE_END need to be defined as well:
|
||||
|
||||
\code
|
||||
// in some .cpp file
|
||||
#define CEREAL_RAPIDJSON_NAMESPACE my::rapidjson
|
||||
#define CEREAL_RAPIDJSON_NAMESPACE_BEGIN namespace my { namespace rapidjson {
|
||||
#define CEREAL_RAPIDJSON_NAMESPACE_END } }
|
||||
#define RAPIDJSON_NAMESPACE my::rapidjson
|
||||
#define RAPIDJSON_NAMESPACE_BEGIN namespace my { namespace rapidjson {
|
||||
#define RAPIDJSON_NAMESPACE_END } }
|
||||
#include "rapidjson/..."
|
||||
\endcode
|
||||
|
||||
\see rapidjson
|
||||
*/
|
||||
/*! \def CEREAL_RAPIDJSON_NAMESPACE_BEGIN
|
||||
\ingroup CEREAL_RAPIDJSON_CONFIG
|
||||
/*! \def RAPIDJSON_NAMESPACE_BEGIN
|
||||
\ingroup RAPIDJSON_CONFIG
|
||||
\brief provide custom rapidjson namespace (opening expression)
|
||||
\see CEREAL_RAPIDJSON_NAMESPACE
|
||||
\see RAPIDJSON_NAMESPACE
|
||||
*/
|
||||
/*! \def CEREAL_RAPIDJSON_NAMESPACE_END
|
||||
\ingroup CEREAL_RAPIDJSON_CONFIG
|
||||
/*! \def RAPIDJSON_NAMESPACE_END
|
||||
\ingroup RAPIDJSON_CONFIG
|
||||
\brief provide custom rapidjson namespace (closing expression)
|
||||
\see CEREAL_RAPIDJSON_NAMESPACE
|
||||
\see RAPIDJSON_NAMESPACE
|
||||
*/
|
||||
#ifndef CEREAL_RAPIDJSON_NAMESPACE
|
||||
#define CEREAL_RAPIDJSON_NAMESPACE rapidjson
|
||||
#ifndef RAPIDJSON_NAMESPACE
|
||||
#define RAPIDJSON_NAMESPACE rapidjson
|
||||
#endif
|
||||
#ifndef CEREAL_RAPIDJSON_NAMESPACE_BEGIN
|
||||
#define CEREAL_RAPIDJSON_NAMESPACE_BEGIN namespace CEREAL_RAPIDJSON_NAMESPACE {
|
||||
#ifndef RAPIDJSON_NAMESPACE_BEGIN
|
||||
#define RAPIDJSON_NAMESPACE_BEGIN namespace RAPIDJSON_NAMESPACE {
|
||||
#endif
|
||||
#ifndef CEREAL_RAPIDJSON_NAMESPACE_END
|
||||
#define CEREAL_RAPIDJSON_NAMESPACE_END }
|
||||
#ifndef RAPIDJSON_NAMESPACE_END
|
||||
#define RAPIDJSON_NAMESPACE_END }
|
||||
#endif
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// CEREAL_RAPIDJSON_HAS_STDSTRING
|
||||
// __cplusplus macro
|
||||
|
||||
#ifndef CEREAL_RAPIDJSON_HAS_STDSTRING
|
||||
#ifdef CEREAL_RAPIDJSON_DOXYGEN_RUNNING
|
||||
#define CEREAL_RAPIDJSON_HAS_STDSTRING 1 // force generation of documentation
|
||||
//!@cond RAPIDJSON_HIDDEN_FROM_DOXYGEN
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
#define RAPIDJSON_CPLUSPLUS _MSVC_LANG
|
||||
#else
|
||||
#define CEREAL_RAPIDJSON_HAS_STDSTRING 0 // no std::string support by default
|
||||
#define RAPIDJSON_CPLUSPLUS __cplusplus
|
||||
#endif
|
||||
/*! \def CEREAL_RAPIDJSON_HAS_STDSTRING
|
||||
\ingroup CEREAL_RAPIDJSON_CONFIG
|
||||
|
||||
//!@endcond
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// RAPIDJSON_HAS_STDSTRING
|
||||
|
||||
#ifndef RAPIDJSON_HAS_STDSTRING
|
||||
#ifdef RAPIDJSON_DOXYGEN_RUNNING
|
||||
#define RAPIDJSON_HAS_STDSTRING 1 // force generation of documentation
|
||||
#else
|
||||
#define RAPIDJSON_HAS_STDSTRING 0 // no std::string support by default
|
||||
#endif
|
||||
/*! \def RAPIDJSON_HAS_STDSTRING
|
||||
\ingroup RAPIDJSON_CONFIG
|
||||
\brief Enable RapidJSON support for \c std::string
|
||||
|
||||
By defining this preprocessor symbol to \c 1, several convenience functions for using
|
||||
@ -138,27 +156,45 @@
|
||||
|
||||
\hideinitializer
|
||||
*/
|
||||
#endif // !defined(CEREAL_RAPIDJSON_HAS_STDSTRING)
|
||||
#endif // !defined(RAPIDJSON_HAS_STDSTRING)
|
||||
|
||||
#if CEREAL_RAPIDJSON_HAS_STDSTRING
|
||||
#if RAPIDJSON_HAS_STDSTRING
|
||||
#include <string>
|
||||
#endif // CEREAL_RAPIDJSON_HAS_STDSTRING
|
||||
#endif // RAPIDJSON_HAS_STDSTRING
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// CEREAL_RAPIDJSON_NO_INT64DEFINE
|
||||
// RAPIDJSON_USE_MEMBERSMAP
|
||||
|
||||
/*! \def CEREAL_RAPIDJSON_NO_INT64DEFINE
|
||||
\ingroup CEREAL_RAPIDJSON_CONFIG
|
||||
/*! \def RAPIDJSON_USE_MEMBERSMAP
|
||||
\ingroup RAPIDJSON_CONFIG
|
||||
\brief Enable RapidJSON support for object members handling in a \c std::multimap
|
||||
|
||||
By defining this preprocessor symbol to \c 1, \ref rapidjson::GenericValue object
|
||||
members are stored in a \c std::multimap for faster lookup and deletion times, a
|
||||
trade off with a slightly slower insertion time and a small object allocat(or)ed
|
||||
memory overhead.
|
||||
|
||||
\hideinitializer
|
||||
*/
|
||||
#ifndef RAPIDJSON_USE_MEMBERSMAP
|
||||
#define RAPIDJSON_USE_MEMBERSMAP 0 // not by default
|
||||
#endif
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// RAPIDJSON_NO_INT64DEFINE
|
||||
|
||||
/*! \def RAPIDJSON_NO_INT64DEFINE
|
||||
\ingroup RAPIDJSON_CONFIG
|
||||
\brief Use external 64-bit integer types.
|
||||
|
||||
RapidJSON requires the 64-bit integer types \c int64_t and \c uint64_t types
|
||||
to be available at global scope.
|
||||
|
||||
If users have their own definition, define CEREAL_RAPIDJSON_NO_INT64DEFINE to
|
||||
If users have their own definition, define RAPIDJSON_NO_INT64DEFINE to
|
||||
prevent RapidJSON from defining its own types.
|
||||
*/
|
||||
#ifndef CEREAL_RAPIDJSON_NO_INT64DEFINE
|
||||
//!@cond CEREAL_RAPIDJSON_HIDDEN_FROM_DOXYGEN
|
||||
#ifndef RAPIDJSON_NO_INT64DEFINE
|
||||
//!@cond RAPIDJSON_HIDDEN_FROM_DOXYGEN
|
||||
#if defined(_MSC_VER) && (_MSC_VER < 1800) // Visual Studio 2013
|
||||
#include "msinttypes/stdint.h"
|
||||
#include "msinttypes/inttypes.h"
|
||||
@ -168,116 +204,111 @@
|
||||
#include <inttypes.h>
|
||||
#endif
|
||||
//!@endcond
|
||||
#ifdef CEREAL_RAPIDJSON_DOXYGEN_RUNNING
|
||||
#define CEREAL_RAPIDJSON_NO_INT64DEFINE
|
||||
#ifdef RAPIDJSON_DOXYGEN_RUNNING
|
||||
#define RAPIDJSON_NO_INT64DEFINE
|
||||
#endif
|
||||
#endif // CEREAL_RAPIDJSON_NO_INT64TYPEDEF
|
||||
#endif // RAPIDJSON_NO_INT64TYPEDEF
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// CEREAL_RAPIDJSON_FORCEINLINE
|
||||
// RAPIDJSON_FORCEINLINE
|
||||
|
||||
#ifndef CEREAL_RAPIDJSON_FORCEINLINE
|
||||
//!@cond CEREAL_RAPIDJSON_HIDDEN_FROM_DOXYGEN
|
||||
#ifndef RAPIDJSON_FORCEINLINE
|
||||
//!@cond RAPIDJSON_HIDDEN_FROM_DOXYGEN
|
||||
#if defined(_MSC_VER) && defined(NDEBUG)
|
||||
#define CEREAL_RAPIDJSON_FORCEINLINE __forceinline
|
||||
#define RAPIDJSON_FORCEINLINE __forceinline
|
||||
#elif defined(__GNUC__) && __GNUC__ >= 4 && defined(NDEBUG)
|
||||
#define CEREAL_RAPIDJSON_FORCEINLINE __attribute__((always_inline))
|
||||
#define RAPIDJSON_FORCEINLINE __attribute__((always_inline))
|
||||
#else
|
||||
#define CEREAL_RAPIDJSON_FORCEINLINE
|
||||
#define RAPIDJSON_FORCEINLINE
|
||||
#endif
|
||||
//!@endcond
|
||||
#endif // CEREAL_RAPIDJSON_FORCEINLINE
|
||||
#endif // RAPIDJSON_FORCEINLINE
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// CEREAL_RAPIDJSON_ENDIAN
|
||||
#define CEREAL_RAPIDJSON_LITTLEENDIAN 0 //!< Little endian machine
|
||||
#define CEREAL_RAPIDJSON_BIGENDIAN 1 //!< Big endian machine
|
||||
// RAPIDJSON_ENDIAN
|
||||
#define RAPIDJSON_LITTLEENDIAN 0 //!< Little endian machine
|
||||
#define RAPIDJSON_BIGENDIAN 1 //!< Big endian machine
|
||||
|
||||
//! Endianness of the machine.
|
||||
/*!
|
||||
\def CEREAL_RAPIDJSON_ENDIAN
|
||||
\ingroup CEREAL_RAPIDJSON_CONFIG
|
||||
\def RAPIDJSON_ENDIAN
|
||||
\ingroup RAPIDJSON_CONFIG
|
||||
|
||||
GCC 4.6 provided macro for detecting endianness of the target machine. But other
|
||||
compilers may not have this. User can define CEREAL_RAPIDJSON_ENDIAN to either
|
||||
\ref CEREAL_RAPIDJSON_LITTLEENDIAN or \ref CEREAL_RAPIDJSON_BIGENDIAN.
|
||||
compilers may not have this. User can define RAPIDJSON_ENDIAN to either
|
||||
\ref RAPIDJSON_LITTLEENDIAN or \ref RAPIDJSON_BIGENDIAN.
|
||||
|
||||
Default detection implemented with reference to
|
||||
\li https://gcc.gnu.org/onlinedocs/gcc-4.6.0/cpp/Common-Predefined-Macros.html
|
||||
\li http://www.boost.org/doc/libs/1_42_0/boost/detail/endian.hpp
|
||||
*/
|
||||
#ifndef CEREAL_RAPIDJSON_ENDIAN
|
||||
#ifndef RAPIDJSON_ENDIAN
|
||||
// Detect with GCC 4.6's macro
|
||||
# ifdef __BYTE_ORDER__
|
||||
# if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
|
||||
# define CEREAL_RAPIDJSON_ENDIAN CEREAL_RAPIDJSON_LITTLEENDIAN
|
||||
# define RAPIDJSON_ENDIAN RAPIDJSON_LITTLEENDIAN
|
||||
# elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
|
||||
# define CEREAL_RAPIDJSON_ENDIAN CEREAL_RAPIDJSON_BIGENDIAN
|
||||
# define RAPIDJSON_ENDIAN RAPIDJSON_BIGENDIAN
|
||||
# else
|
||||
# error Unknown machine endianess detected. User needs to define CEREAL_RAPIDJSON_ENDIAN.
|
||||
# error Unknown machine endianness detected. User needs to define RAPIDJSON_ENDIAN.
|
||||
# endif // __BYTE_ORDER__
|
||||
// Detect with GLIBC's endian.h
|
||||
# elif defined(__GLIBC__)
|
||||
# include <endian.h>
|
||||
# if (__BYTE_ORDER == __LITTLE_ENDIAN)
|
||||
# define CEREAL_RAPIDJSON_ENDIAN CEREAL_RAPIDJSON_LITTLEENDIAN
|
||||
# define RAPIDJSON_ENDIAN RAPIDJSON_LITTLEENDIAN
|
||||
# elif (__BYTE_ORDER == __BIG_ENDIAN)
|
||||
# define CEREAL_RAPIDJSON_ENDIAN CEREAL_RAPIDJSON_BIGENDIAN
|
||||
# define RAPIDJSON_ENDIAN RAPIDJSON_BIGENDIAN
|
||||
# else
|
||||
# error Unknown machine endianess detected. User needs to define CEREAL_RAPIDJSON_ENDIAN.
|
||||
# error Unknown machine endianness detected. User needs to define RAPIDJSON_ENDIAN.
|
||||
# endif // __GLIBC__
|
||||
// Detect with _LITTLE_ENDIAN and _BIG_ENDIAN macro
|
||||
# elif defined(_LITTLE_ENDIAN) && !defined(_BIG_ENDIAN)
|
||||
# define CEREAL_RAPIDJSON_ENDIAN CEREAL_RAPIDJSON_LITTLEENDIAN
|
||||
# define RAPIDJSON_ENDIAN RAPIDJSON_LITTLEENDIAN
|
||||
# elif defined(_BIG_ENDIAN) && !defined(_LITTLE_ENDIAN)
|
||||
# define CEREAL_RAPIDJSON_ENDIAN CEREAL_RAPIDJSON_BIGENDIAN
|
||||
# define RAPIDJSON_ENDIAN RAPIDJSON_BIGENDIAN
|
||||
// Detect with architecture macros
|
||||
# elif defined(__sparc) || defined(__sparc__) || defined(_POWER) || defined(__powerpc__) || defined(__ppc__) || defined(__hpux) || defined(__hppa) || defined(_MIPSEB) || defined(_POWER) || defined(__s390__)
|
||||
# define CEREAL_RAPIDJSON_ENDIAN CEREAL_RAPIDJSON_BIGENDIAN
|
||||
# define RAPIDJSON_ENDIAN RAPIDJSON_BIGENDIAN
|
||||
# elif defined(__i386__) || defined(__alpha__) || defined(__ia64) || defined(__ia64__) || defined(_M_IX86) || defined(_M_IA64) || defined(_M_ALPHA) || defined(__amd64) || defined(__amd64__) || defined(_M_AMD64) || defined(__x86_64) || defined(__x86_64__) || defined(_M_X64) || defined(__bfin__)
|
||||
# define CEREAL_RAPIDJSON_ENDIAN CEREAL_RAPIDJSON_LITTLEENDIAN
|
||||
# elif defined(_MSC_VER) && defined(_M_ARM)
|
||||
# define CEREAL_RAPIDJSON_ENDIAN CEREAL_RAPIDJSON_LITTLEENDIAN
|
||||
# elif defined(CEREAL_RAPIDJSON_DOXYGEN_RUNNING)
|
||||
# define CEREAL_RAPIDJSON_ENDIAN
|
||||
# define RAPIDJSON_ENDIAN RAPIDJSON_LITTLEENDIAN
|
||||
# elif defined(_MSC_VER) && (defined(_M_ARM) || defined(_M_ARM64))
|
||||
# define RAPIDJSON_ENDIAN RAPIDJSON_LITTLEENDIAN
|
||||
# elif defined(RAPIDJSON_DOXYGEN_RUNNING)
|
||||
# define RAPIDJSON_ENDIAN
|
||||
# else
|
||||
# error Unknown machine endianess detected. User needs to define CEREAL_RAPIDJSON_ENDIAN.
|
||||
# error Unknown machine endianness detected. User needs to define RAPIDJSON_ENDIAN.
|
||||
# endif
|
||||
#endif // CEREAL_RAPIDJSON_ENDIAN
|
||||
#endif // RAPIDJSON_ENDIAN
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// CEREAL_RAPIDJSON_64BIT
|
||||
// RAPIDJSON_64BIT
|
||||
|
||||
//! Whether using 64-bit architecture
|
||||
#ifndef CEREAL_RAPIDJSON_64BIT
|
||||
#ifndef RAPIDJSON_64BIT
|
||||
#if defined(__LP64__) || (defined(__x86_64__) && defined(__ILP32__)) || defined(_WIN64) || defined(__EMSCRIPTEN__)
|
||||
#define CEREAL_RAPIDJSON_64BIT 1
|
||||
#define RAPIDJSON_64BIT 1
|
||||
#else
|
||||
#define CEREAL_RAPIDJSON_64BIT 0
|
||||
#define RAPIDJSON_64BIT 0
|
||||
#endif
|
||||
#endif // CEREAL_RAPIDJSON_64BIT
|
||||
#endif // RAPIDJSON_64BIT
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// CEREAL_RAPIDJSON_ALIGN
|
||||
// RAPIDJSON_ALIGN
|
||||
|
||||
//! Data alignment of the machine.
|
||||
/*! \ingroup CEREAL_RAPIDJSON_CONFIG
|
||||
/*! \ingroup RAPIDJSON_CONFIG
|
||||
\param x pointer to align
|
||||
|
||||
Some machines require strict data alignment. Currently the default uses 4 bytes
|
||||
alignment on 32-bit platforms and 8 bytes alignment for 64-bit platforms.
|
||||
User can customize by defining the CEREAL_RAPIDJSON_ALIGN function macro.
|
||||
Some machines require strict data alignment. The default is 8 bytes.
|
||||
User can customize by defining the RAPIDJSON_ALIGN function macro.
|
||||
*/
|
||||
#ifndef CEREAL_RAPIDJSON_ALIGN
|
||||
#if CEREAL_RAPIDJSON_64BIT == 1
|
||||
#define CEREAL_RAPIDJSON_ALIGN(x) (((x) + static_cast<uint64_t>(7u)) & ~static_cast<uint64_t>(7u))
|
||||
#else
|
||||
#define CEREAL_RAPIDJSON_ALIGN(x) (((x) + 3u) & ~3u)
|
||||
#endif
|
||||
#ifndef RAPIDJSON_ALIGN
|
||||
#define RAPIDJSON_ALIGN(x) (((x) + static_cast<size_t>(7u)) & ~static_cast<size_t>(7u))
|
||||
#endif
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// CEREAL_RAPIDJSON_UINT64_C2
|
||||
// RAPIDJSON_UINT64_C2
|
||||
|
||||
//! Construct a 64-bit literal by a pair of 32-bit integer.
|
||||
/*!
|
||||
@ -285,309 +316,404 @@
|
||||
UINT64_C() is C macro which cause compilation problems.
|
||||
Use this macro to define 64-bit constants by a pair of 32-bit integer.
|
||||
*/
|
||||
#ifndef CEREAL_RAPIDJSON_UINT64_C2
|
||||
#define CEREAL_RAPIDJSON_UINT64_C2(high32, low32) ((static_cast<uint64_t>(high32) << 32) | static_cast<uint64_t>(low32))
|
||||
#ifndef RAPIDJSON_UINT64_C2
|
||||
#define RAPIDJSON_UINT64_C2(high32, low32) ((static_cast<uint64_t>(high32) << 32) | static_cast<uint64_t>(low32))
|
||||
#endif
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// CEREAL_RAPIDJSON_48BITPOINTER_OPTIMIZATION
|
||||
// RAPIDJSON_48BITPOINTER_OPTIMIZATION
|
||||
|
||||
//! Use only lower 48-bit address for some pointers.
|
||||
/*!
|
||||
\ingroup CEREAL_RAPIDJSON_CONFIG
|
||||
\ingroup RAPIDJSON_CONFIG
|
||||
|
||||
This optimization uses the fact that current X86-64 architecture only implement lower 48-bit virtual address.
|
||||
The higher 16-bit can be used for storing other data.
|
||||
\c GenericValue uses this optimization to reduce its size form 24 bytes to 16 bytes in 64-bit architecture.
|
||||
*/
|
||||
#ifndef CEREAL_RAPIDJSON_48BITPOINTER_OPTIMIZATION
|
||||
#ifndef RAPIDJSON_48BITPOINTER_OPTIMIZATION
|
||||
#if defined(__amd64__) || defined(__amd64) || defined(__x86_64__) || defined(__x86_64) || defined(_M_X64) || defined(_M_AMD64)
|
||||
#define CEREAL_RAPIDJSON_48BITPOINTER_OPTIMIZATION 1
|
||||
#define RAPIDJSON_48BITPOINTER_OPTIMIZATION 1
|
||||
#else
|
||||
#define CEREAL_RAPIDJSON_48BITPOINTER_OPTIMIZATION 0
|
||||
#define RAPIDJSON_48BITPOINTER_OPTIMIZATION 0
|
||||
#endif
|
||||
#endif // CEREAL_RAPIDJSON_48BITPOINTER_OPTIMIZATION
|
||||
#endif // RAPIDJSON_48BITPOINTER_OPTIMIZATION
|
||||
|
||||
#if CEREAL_RAPIDJSON_48BITPOINTER_OPTIMIZATION == 1
|
||||
#if CEREAL_RAPIDJSON_64BIT != 1
|
||||
#error CEREAL_RAPIDJSON_48BITPOINTER_OPTIMIZATION can only be set to 1 when CEREAL_RAPIDJSON_64BIT=1
|
||||
#if RAPIDJSON_48BITPOINTER_OPTIMIZATION == 1
|
||||
#if RAPIDJSON_64BIT != 1
|
||||
#error RAPIDJSON_48BITPOINTER_OPTIMIZATION can only be set to 1 when RAPIDJSON_64BIT=1
|
||||
#endif
|
||||
#define CEREAL_RAPIDJSON_SETPOINTER(type, p, x) (p = reinterpret_cast<type *>((reinterpret_cast<uintptr_t>(p) & static_cast<uintptr_t>(CEREAL_RAPIDJSON_UINT64_C2(0xFFFF0000, 0x00000000))) | reinterpret_cast<uintptr_t>(reinterpret_cast<const void*>(x))))
|
||||
#define CEREAL_RAPIDJSON_GETPOINTER(type, p) (reinterpret_cast<type *>(reinterpret_cast<uintptr_t>(p) & static_cast<uintptr_t>(CEREAL_RAPIDJSON_UINT64_C2(0x0000FFFF, 0xFFFFFFFF))))
|
||||
#define RAPIDJSON_SETPOINTER(type, p, x) (p = reinterpret_cast<type *>((reinterpret_cast<uintptr_t>(p) & static_cast<uintptr_t>(RAPIDJSON_UINT64_C2(0xFFFF0000, 0x00000000))) | reinterpret_cast<uintptr_t>(reinterpret_cast<const void*>(x))))
|
||||
#define RAPIDJSON_GETPOINTER(type, p) (reinterpret_cast<type *>(reinterpret_cast<uintptr_t>(p) & static_cast<uintptr_t>(RAPIDJSON_UINT64_C2(0x0000FFFF, 0xFFFFFFFF))))
|
||||
#else
|
||||
#define CEREAL_RAPIDJSON_SETPOINTER(type, p, x) (p = (x))
|
||||
#define CEREAL_RAPIDJSON_GETPOINTER(type, p) (p)
|
||||
#define RAPIDJSON_SETPOINTER(type, p, x) (p = (x))
|
||||
#define RAPIDJSON_GETPOINTER(type, p) (p)
|
||||
#endif
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// CEREAL_RAPIDJSON_SSE2/CEREAL_RAPIDJSON_SSE42/CEREAL_RAPIDJSON_SIMD
|
||||
// RAPIDJSON_SSE2/RAPIDJSON_SSE42/RAPIDJSON_NEON/RAPIDJSON_SIMD
|
||||
|
||||
/*! \def CEREAL_RAPIDJSON_SIMD
|
||||
\ingroup CEREAL_RAPIDJSON_CONFIG
|
||||
\brief Enable SSE2/SSE4.2 optimization.
|
||||
/*! \def RAPIDJSON_SIMD
|
||||
\ingroup RAPIDJSON_CONFIG
|
||||
\brief Enable SSE2/SSE4.2/Neon optimization.
|
||||
|
||||
RapidJSON supports optimized implementations for some parsing operations
|
||||
based on the SSE2 or SSE4.2 SIMD extensions on modern Intel-compatible
|
||||
processors.
|
||||
based on the SSE2, SSE4.2 or NEon SIMD extensions on modern Intel
|
||||
or ARM compatible processors.
|
||||
|
||||
To enable these optimizations, two different symbols can be defined;
|
||||
To enable these optimizations, three different symbols can be defined;
|
||||
\code
|
||||
// Enable SSE2 optimization.
|
||||
#define CEREAL_RAPIDJSON_SSE2
|
||||
#define RAPIDJSON_SSE2
|
||||
|
||||
// Enable SSE4.2 optimization.
|
||||
#define CEREAL_RAPIDJSON_SSE42
|
||||
#define RAPIDJSON_SSE42
|
||||
\endcode
|
||||
|
||||
\c CEREAL_RAPIDJSON_SSE42 takes precedence, if both are defined.
|
||||
// Enable ARM Neon optimization.
|
||||
#define RAPIDJSON_NEON
|
||||
\endcode
|
||||
|
||||
\c RAPIDJSON_SSE42 takes precedence over SSE2, if both are defined.
|
||||
|
||||
If any of these symbols is defined, RapidJSON defines the macro
|
||||
\c CEREAL_RAPIDJSON_SIMD to indicate the availability of the optimized code.
|
||||
\c RAPIDJSON_SIMD to indicate the availability of the optimized code.
|
||||
*/
|
||||
#if defined(CEREAL_RAPIDJSON_SSE2) || defined(CEREAL_RAPIDJSON_SSE42) \
|
||||
|| defined(CEREAL_RAPIDJSON_DOXYGEN_RUNNING)
|
||||
#define CEREAL_RAPIDJSON_SIMD
|
||||
#if defined(RAPIDJSON_SSE2) || defined(RAPIDJSON_SSE42) \
|
||||
|| defined(RAPIDJSON_NEON) || defined(RAPIDJSON_DOXYGEN_RUNNING)
|
||||
#define RAPIDJSON_SIMD
|
||||
#endif
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// CEREAL_RAPIDJSON_NO_SIZETYPEDEFINE
|
||||
// RAPIDJSON_NO_SIZETYPEDEFINE
|
||||
|
||||
#ifndef CEREAL_RAPIDJSON_NO_SIZETYPEDEFINE
|
||||
/*! \def CEREAL_RAPIDJSON_NO_SIZETYPEDEFINE
|
||||
\ingroup CEREAL_RAPIDJSON_CONFIG
|
||||
#ifndef RAPIDJSON_NO_SIZETYPEDEFINE
|
||||
/*! \def RAPIDJSON_NO_SIZETYPEDEFINE
|
||||
\ingroup RAPIDJSON_CONFIG
|
||||
\brief User-provided \c SizeType definition.
|
||||
|
||||
In order to avoid using 32-bit size types for indexing strings and arrays,
|
||||
define this preprocessor symbol and provide the type rapidjson::SizeType
|
||||
before including RapidJSON:
|
||||
\code
|
||||
#define CEREAL_RAPIDJSON_NO_SIZETYPEDEFINE
|
||||
#define RAPIDJSON_NO_SIZETYPEDEFINE
|
||||
namespace rapidjson { typedef ::std::size_t SizeType; }
|
||||
#include "rapidjson/..."
|
||||
\endcode
|
||||
|
||||
\see rapidjson::SizeType
|
||||
*/
|
||||
#ifdef CEREAL_RAPIDJSON_DOXYGEN_RUNNING
|
||||
#define CEREAL_RAPIDJSON_NO_SIZETYPEDEFINE
|
||||
#ifdef RAPIDJSON_DOXYGEN_RUNNING
|
||||
#define RAPIDJSON_NO_SIZETYPEDEFINE
|
||||
#endif
|
||||
CEREAL_RAPIDJSON_NAMESPACE_BEGIN
|
||||
RAPIDJSON_NAMESPACE_BEGIN
|
||||
//! Size type (for string lengths, array sizes, etc.)
|
||||
/*! RapidJSON uses 32-bit array/string indices even on 64-bit platforms,
|
||||
instead of using \c size_t. Users may override the SizeType by defining
|
||||
\ref CEREAL_RAPIDJSON_NO_SIZETYPEDEFINE.
|
||||
\ref RAPIDJSON_NO_SIZETYPEDEFINE.
|
||||
*/
|
||||
typedef unsigned SizeType;
|
||||
CEREAL_RAPIDJSON_NAMESPACE_END
|
||||
RAPIDJSON_NAMESPACE_END
|
||||
#endif
|
||||
|
||||
// always import std::size_t to rapidjson namespace
|
||||
CEREAL_RAPIDJSON_NAMESPACE_BEGIN
|
||||
RAPIDJSON_NAMESPACE_BEGIN
|
||||
using std::size_t;
|
||||
CEREAL_RAPIDJSON_NAMESPACE_END
|
||||
RAPIDJSON_NAMESPACE_END
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// CEREAL_RAPIDJSON_ASSERT
|
||||
// RAPIDJSON_ASSERT
|
||||
|
||||
//! Assertion.
|
||||
/*! \ingroup CEREAL_RAPIDJSON_CONFIG
|
||||
/*! \ingroup RAPIDJSON_CONFIG
|
||||
By default, rapidjson uses C \c assert() for internal assertions.
|
||||
User can override it by defining CEREAL_RAPIDJSON_ASSERT(x) macro.
|
||||
User can override it by defining RAPIDJSON_ASSERT(x) macro.
|
||||
|
||||
\note Parsing errors are handled and can be customized by the
|
||||
\ref CEREAL_RAPIDJSON_ERRORS APIs.
|
||||
\ref RAPIDJSON_ERRORS APIs.
|
||||
*/
|
||||
#ifndef CEREAL_RAPIDJSON_ASSERT
|
||||
#ifndef RAPIDJSON_ASSERT
|
||||
#include <cassert>
|
||||
#define CEREAL_RAPIDJSON_ASSERT(x) assert(x)
|
||||
#endif // CEREAL_RAPIDJSON_ASSERT
|
||||
#define RAPIDJSON_ASSERT(x) assert(x)
|
||||
#endif // RAPIDJSON_ASSERT
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// CEREAL_RAPIDJSON_STATIC_ASSERT
|
||||
// RAPIDJSON_STATIC_ASSERT
|
||||
|
||||
// Adopt from boost
|
||||
#ifndef CEREAL_RAPIDJSON_STATIC_ASSERT
|
||||
// Prefer C++11 static_assert, if available
|
||||
#ifndef RAPIDJSON_STATIC_ASSERT
|
||||
#if RAPIDJSON_CPLUSPLUS >= 201103L || ( defined(_MSC_VER) && _MSC_VER >= 1800 )
|
||||
#define RAPIDJSON_STATIC_ASSERT(x) \
|
||||
static_assert(x, RAPIDJSON_STRINGIFY(x))
|
||||
#endif // C++11
|
||||
#endif // RAPIDJSON_STATIC_ASSERT
|
||||
|
||||
// Adopt C++03 implementation from boost
|
||||
#ifndef RAPIDJSON_STATIC_ASSERT
|
||||
#ifndef __clang__
|
||||
//!@cond CEREAL_RAPIDJSON_HIDDEN_FROM_DOXYGEN
|
||||
//!@cond RAPIDJSON_HIDDEN_FROM_DOXYGEN
|
||||
#endif
|
||||
CEREAL_RAPIDJSON_NAMESPACE_BEGIN
|
||||
RAPIDJSON_NAMESPACE_BEGIN
|
||||
template <bool x> struct STATIC_ASSERTION_FAILURE;
|
||||
template <> struct STATIC_ASSERTION_FAILURE<true> { enum { value = 1 }; };
|
||||
template<int x> struct StaticAssertTest {};
|
||||
CEREAL_RAPIDJSON_NAMESPACE_END
|
||||
template <size_t x> struct StaticAssertTest {};
|
||||
RAPIDJSON_NAMESPACE_END
|
||||
|
||||
#define CEREAL_RAPIDJSON_JOIN(X, Y) CEREAL_RAPIDJSON_DO_JOIN(X, Y)
|
||||
#define CEREAL_RAPIDJSON_DO_JOIN(X, Y) CEREAL_RAPIDJSON_DO_JOIN2(X, Y)
|
||||
#define CEREAL_RAPIDJSON_DO_JOIN2(X, Y) X##Y
|
||||
|
||||
#if defined(__GNUC__)
|
||||
#define CEREAL_RAPIDJSON_STATIC_ASSERT_UNUSED_ATTRIBUTE __attribute__((unused))
|
||||
#if defined(__GNUC__) || defined(__clang__)
|
||||
#define RAPIDJSON_STATIC_ASSERT_UNUSED_ATTRIBUTE __attribute__((unused))
|
||||
#else
|
||||
#define CEREAL_RAPIDJSON_STATIC_ASSERT_UNUSED_ATTRIBUTE
|
||||
#define RAPIDJSON_STATIC_ASSERT_UNUSED_ATTRIBUTE
|
||||
#endif
|
||||
#ifndef __clang__
|
||||
//!@endcond
|
||||
#endif
|
||||
|
||||
/*! \def CEREAL_RAPIDJSON_STATIC_ASSERT
|
||||
/*! \def RAPIDJSON_STATIC_ASSERT
|
||||
\brief (Internal) macro to check for conditions at compile-time
|
||||
\param x compile-time condition
|
||||
\hideinitializer
|
||||
*/
|
||||
#define CEREAL_RAPIDJSON_STATIC_ASSERT(x) \
|
||||
typedef ::CEREAL_RAPIDJSON_NAMESPACE::StaticAssertTest< \
|
||||
sizeof(::CEREAL_RAPIDJSON_NAMESPACE::STATIC_ASSERTION_FAILURE<bool(x) >)> \
|
||||
CEREAL_RAPIDJSON_JOIN(StaticAssertTypedef, __LINE__) CEREAL_RAPIDJSON_STATIC_ASSERT_UNUSED_ATTRIBUTE
|
||||
#endif
|
||||
#define RAPIDJSON_STATIC_ASSERT(x) \
|
||||
typedef ::RAPIDJSON_NAMESPACE::StaticAssertTest< \
|
||||
sizeof(::RAPIDJSON_NAMESPACE::STATIC_ASSERTION_FAILURE<bool(x) >)> \
|
||||
RAPIDJSON_JOIN(StaticAssertTypedef, __LINE__) RAPIDJSON_STATIC_ASSERT_UNUSED_ATTRIBUTE
|
||||
#endif // RAPIDJSON_STATIC_ASSERT
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// CEREAL_RAPIDJSON_LIKELY, CEREAL_RAPIDJSON_UNLIKELY
|
||||
// RAPIDJSON_LIKELY, RAPIDJSON_UNLIKELY
|
||||
|
||||
//! Compiler branching hint for expression with high probability to be true.
|
||||
/*!
|
||||
\ingroup CEREAL_RAPIDJSON_CONFIG
|
||||
\ingroup RAPIDJSON_CONFIG
|
||||
\param x Boolean expression likely to be true.
|
||||
*/
|
||||
#ifndef CEREAL_RAPIDJSON_LIKELY
|
||||
#ifndef RAPIDJSON_LIKELY
|
||||
#if defined(__GNUC__) || defined(__clang__)
|
||||
#define CEREAL_RAPIDJSON_LIKELY(x) __builtin_expect(!!(x), 1)
|
||||
#define RAPIDJSON_LIKELY(x) __builtin_expect(!!(x), 1)
|
||||
#else
|
||||
#define CEREAL_RAPIDJSON_LIKELY(x) (x)
|
||||
#define RAPIDJSON_LIKELY(x) (x)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
//! Compiler branching hint for expression with low probability to be true.
|
||||
/*!
|
||||
\ingroup CEREAL_RAPIDJSON_CONFIG
|
||||
\ingroup RAPIDJSON_CONFIG
|
||||
\param x Boolean expression unlikely to be true.
|
||||
*/
|
||||
#ifndef CEREAL_RAPIDJSON_UNLIKELY
|
||||
#ifndef RAPIDJSON_UNLIKELY
|
||||
#if defined(__GNUC__) || defined(__clang__)
|
||||
#define CEREAL_RAPIDJSON_UNLIKELY(x) __builtin_expect(!!(x), 0)
|
||||
#define RAPIDJSON_UNLIKELY(x) __builtin_expect(!!(x), 0)
|
||||
#else
|
||||
#define CEREAL_RAPIDJSON_UNLIKELY(x) (x)
|
||||
#define RAPIDJSON_UNLIKELY(x) (x)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Helpers
|
||||
|
||||
//!@cond CEREAL_RAPIDJSON_HIDDEN_FROM_DOXYGEN
|
||||
//!@cond RAPIDJSON_HIDDEN_FROM_DOXYGEN
|
||||
|
||||
#define CEREAL_RAPIDJSON_MULTILINEMACRO_BEGIN do {
|
||||
#define CEREAL_RAPIDJSON_MULTILINEMACRO_END \
|
||||
#define RAPIDJSON_MULTILINEMACRO_BEGIN do {
|
||||
#define RAPIDJSON_MULTILINEMACRO_END \
|
||||
} while((void)0, 0)
|
||||
|
||||
// adopted from Boost
|
||||
#define CEREAL_RAPIDJSON_VERSION_CODE(x,y,z) \
|
||||
#define RAPIDJSON_VERSION_CODE(x,y,z) \
|
||||
(((x)*100000) + ((y)*100) + (z))
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// CEREAL_RAPIDJSON_DIAG_PUSH/POP, CEREAL_RAPIDJSON_DIAG_OFF
|
||||
|
||||
#if defined(__GNUC__)
|
||||
#define CEREAL_RAPIDJSON_GNUC \
|
||||
CEREAL_RAPIDJSON_VERSION_CODE(__GNUC__,__GNUC_MINOR__,__GNUC_PATCHLEVEL__)
|
||||
#if defined(__has_builtin)
|
||||
#define RAPIDJSON_HAS_BUILTIN(x) __has_builtin(x)
|
||||
#else
|
||||
#define RAPIDJSON_HAS_BUILTIN(x) 0
|
||||
#endif
|
||||
|
||||
#if defined(__clang__) || (defined(CEREAL_RAPIDJSON_GNUC) && CEREAL_RAPIDJSON_GNUC >= CEREAL_RAPIDJSON_VERSION_CODE(4,2,0))
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// RAPIDJSON_DIAG_PUSH/POP, RAPIDJSON_DIAG_OFF
|
||||
|
||||
#define CEREAL_RAPIDJSON_PRAGMA(x) _Pragma(CEREAL_RAPIDJSON_STRINGIFY(x))
|
||||
#define CEREAL_RAPIDJSON_DIAG_PRAGMA(x) CEREAL_RAPIDJSON_PRAGMA(GCC diagnostic x)
|
||||
#define CEREAL_RAPIDJSON_DIAG_OFF(x) \
|
||||
CEREAL_RAPIDJSON_DIAG_PRAGMA(ignored CEREAL_RAPIDJSON_STRINGIFY(CEREAL_RAPIDJSON_JOIN(-W,x)))
|
||||
#if defined(__GNUC__)
|
||||
#define RAPIDJSON_GNUC \
|
||||
RAPIDJSON_VERSION_CODE(__GNUC__,__GNUC_MINOR__,__GNUC_PATCHLEVEL__)
|
||||
#endif
|
||||
|
||||
#if defined(__clang__) || (defined(RAPIDJSON_GNUC) && RAPIDJSON_GNUC >= RAPIDJSON_VERSION_CODE(4,2,0))
|
||||
|
||||
#define RAPIDJSON_PRAGMA(x) _Pragma(RAPIDJSON_STRINGIFY(x))
|
||||
#define RAPIDJSON_DIAG_PRAGMA(x) RAPIDJSON_PRAGMA(GCC diagnostic x)
|
||||
#define RAPIDJSON_DIAG_OFF(x) \
|
||||
RAPIDJSON_DIAG_PRAGMA(ignored RAPIDJSON_STRINGIFY(RAPIDJSON_JOIN(-W,x)))
|
||||
|
||||
// push/pop support in Clang and GCC>=4.6
|
||||
#if defined(__clang__) || (defined(CEREAL_RAPIDJSON_GNUC) && CEREAL_RAPIDJSON_GNUC >= CEREAL_RAPIDJSON_VERSION_CODE(4,6,0))
|
||||
#define CEREAL_RAPIDJSON_DIAG_PUSH CEREAL_RAPIDJSON_DIAG_PRAGMA(push)
|
||||
#define CEREAL_RAPIDJSON_DIAG_POP CEREAL_RAPIDJSON_DIAG_PRAGMA(pop)
|
||||
#if defined(__clang__) || (defined(RAPIDJSON_GNUC) && RAPIDJSON_GNUC >= RAPIDJSON_VERSION_CODE(4,6,0))
|
||||
#define RAPIDJSON_DIAG_PUSH RAPIDJSON_DIAG_PRAGMA(push)
|
||||
#define RAPIDJSON_DIAG_POP RAPIDJSON_DIAG_PRAGMA(pop)
|
||||
#else // GCC >= 4.2, < 4.6
|
||||
#define CEREAL_RAPIDJSON_DIAG_PUSH /* ignored */
|
||||
#define CEREAL_RAPIDJSON_DIAG_POP /* ignored */
|
||||
#define RAPIDJSON_DIAG_PUSH /* ignored */
|
||||
#define RAPIDJSON_DIAG_POP /* ignored */
|
||||
#endif
|
||||
|
||||
#elif defined(_MSC_VER)
|
||||
|
||||
// pragma (MSVC specific)
|
||||
#define CEREAL_RAPIDJSON_PRAGMA(x) __pragma(x)
|
||||
#define CEREAL_RAPIDJSON_DIAG_PRAGMA(x) CEREAL_RAPIDJSON_PRAGMA(warning(x))
|
||||
#define RAPIDJSON_PRAGMA(x) __pragma(x)
|
||||
#define RAPIDJSON_DIAG_PRAGMA(x) RAPIDJSON_PRAGMA(warning(x))
|
||||
|
||||
#define CEREAL_RAPIDJSON_DIAG_OFF(x) CEREAL_RAPIDJSON_DIAG_PRAGMA(disable: x)
|
||||
#define CEREAL_RAPIDJSON_DIAG_PUSH CEREAL_RAPIDJSON_DIAG_PRAGMA(push)
|
||||
#define CEREAL_RAPIDJSON_DIAG_POP CEREAL_RAPIDJSON_DIAG_PRAGMA(pop)
|
||||
#define RAPIDJSON_DIAG_OFF(x) RAPIDJSON_DIAG_PRAGMA(disable: x)
|
||||
#define RAPIDJSON_DIAG_PUSH RAPIDJSON_DIAG_PRAGMA(push)
|
||||
#define RAPIDJSON_DIAG_POP RAPIDJSON_DIAG_PRAGMA(pop)
|
||||
|
||||
#else
|
||||
|
||||
#define CEREAL_RAPIDJSON_DIAG_OFF(x) /* ignored */
|
||||
#define CEREAL_RAPIDJSON_DIAG_PUSH /* ignored */
|
||||
#define CEREAL_RAPIDJSON_DIAG_POP /* ignored */
|
||||
#define RAPIDJSON_DIAG_OFF(x) /* ignored */
|
||||
#define RAPIDJSON_DIAG_PUSH /* ignored */
|
||||
#define RAPIDJSON_DIAG_POP /* ignored */
|
||||
|
||||
#endif // CEREAL_RAPIDJSON_DIAG_*
|
||||
#endif // RAPIDJSON_DIAG_*
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// C++11 features
|
||||
|
||||
#ifndef CEREAL_RAPIDJSON_HAS_CXX11_RVALUE_REFS
|
||||
#if defined(__clang__)
|
||||
#ifndef RAPIDJSON_HAS_CXX11
|
||||
#define RAPIDJSON_HAS_CXX11 (RAPIDJSON_CPLUSPLUS >= 201103L)
|
||||
#endif
|
||||
|
||||
#ifndef RAPIDJSON_HAS_CXX11_RVALUE_REFS
|
||||
#if RAPIDJSON_HAS_CXX11
|
||||
#define RAPIDJSON_HAS_CXX11_RVALUE_REFS 1
|
||||
#elif defined(__clang__)
|
||||
#if __has_feature(cxx_rvalue_references) && \
|
||||
(defined(_LIBCPP_VERSION) || defined(__GLIBCXX__) && __GLIBCXX__ >= 20080306)
|
||||
#define CEREAL_RAPIDJSON_HAS_CXX11_RVALUE_REFS 1
|
||||
(defined(_MSC_VER) || defined(_LIBCPP_VERSION) || defined(__GLIBCXX__) && __GLIBCXX__ >= 20080306)
|
||||
#define RAPIDJSON_HAS_CXX11_RVALUE_REFS 1
|
||||
#else
|
||||
#define CEREAL_RAPIDJSON_HAS_CXX11_RVALUE_REFS 0
|
||||
#define RAPIDJSON_HAS_CXX11_RVALUE_REFS 0
|
||||
#endif
|
||||
#elif (defined(CEREAL_RAPIDJSON_GNUC) && (CEREAL_RAPIDJSON_GNUC >= CEREAL_RAPIDJSON_VERSION_CODE(4,3,0)) && defined(__GXX_EXPERIMENTAL_CXX0X__)) || \
|
||||
(defined(_MSC_VER) && _MSC_VER >= 1600)
|
||||
#elif (defined(RAPIDJSON_GNUC) && (RAPIDJSON_GNUC >= RAPIDJSON_VERSION_CODE(4,3,0)) && defined(__GXX_EXPERIMENTAL_CXX0X__)) || \
|
||||
(defined(_MSC_VER) && _MSC_VER >= 1600) || \
|
||||
(defined(__SUNPRO_CC) && __SUNPRO_CC >= 0x5140 && defined(__GXX_EXPERIMENTAL_CXX0X__))
|
||||
|
||||
#define CEREAL_RAPIDJSON_HAS_CXX11_RVALUE_REFS 1
|
||||
#define RAPIDJSON_HAS_CXX11_RVALUE_REFS 1
|
||||
#else
|
||||
#define CEREAL_RAPIDJSON_HAS_CXX11_RVALUE_REFS 0
|
||||
#define RAPIDJSON_HAS_CXX11_RVALUE_REFS 0
|
||||
#endif
|
||||
#endif // CEREAL_RAPIDJSON_HAS_CXX11_RVALUE_REFS
|
||||
#endif // RAPIDJSON_HAS_CXX11_RVALUE_REFS
|
||||
|
||||
#ifndef CEREAL_RAPIDJSON_HAS_CXX11_NOEXCEPT
|
||||
#if defined(__clang__)
|
||||
#define CEREAL_RAPIDJSON_HAS_CXX11_NOEXCEPT __has_feature(cxx_noexcept)
|
||||
#elif (defined(CEREAL_RAPIDJSON_GNUC) && (CEREAL_RAPIDJSON_GNUC >= CEREAL_RAPIDJSON_VERSION_CODE(4,6,0)) && defined(__GXX_EXPERIMENTAL_CXX0X__))
|
||||
// (defined(_MSC_VER) && _MSC_VER >= ????) // not yet supported
|
||||
#define CEREAL_RAPIDJSON_HAS_CXX11_NOEXCEPT 1
|
||||
#if RAPIDJSON_HAS_CXX11_RVALUE_REFS
|
||||
#include <utility> // std::move
|
||||
#endif
|
||||
|
||||
#ifndef RAPIDJSON_HAS_CXX11_NOEXCEPT
|
||||
#if RAPIDJSON_HAS_CXX11
|
||||
#define RAPIDJSON_HAS_CXX11_NOEXCEPT 1
|
||||
#elif defined(__clang__)
|
||||
#define RAPIDJSON_HAS_CXX11_NOEXCEPT __has_feature(cxx_noexcept)
|
||||
#elif (defined(RAPIDJSON_GNUC) && (RAPIDJSON_GNUC >= RAPIDJSON_VERSION_CODE(4,6,0)) && defined(__GXX_EXPERIMENTAL_CXX0X__)) || \
|
||||
(defined(_MSC_VER) && _MSC_VER >= 1900) || \
|
||||
(defined(__SUNPRO_CC) && __SUNPRO_CC >= 0x5140 && defined(__GXX_EXPERIMENTAL_CXX0X__))
|
||||
#define RAPIDJSON_HAS_CXX11_NOEXCEPT 1
|
||||
#else
|
||||
#define CEREAL_RAPIDJSON_HAS_CXX11_NOEXCEPT 0
|
||||
#define RAPIDJSON_HAS_CXX11_NOEXCEPT 0
|
||||
#endif
|
||||
#endif
|
||||
#if CEREAL_RAPIDJSON_HAS_CXX11_NOEXCEPT
|
||||
#define CEREAL_RAPIDJSON_NOEXCEPT noexcept
|
||||
#ifndef RAPIDJSON_NOEXCEPT
|
||||
#if RAPIDJSON_HAS_CXX11_NOEXCEPT
|
||||
#define RAPIDJSON_NOEXCEPT noexcept
|
||||
#else
|
||||
#define CEREAL_RAPIDJSON_NOEXCEPT /* noexcept */
|
||||
#endif // CEREAL_RAPIDJSON_HAS_CXX11_NOEXCEPT
|
||||
#define RAPIDJSON_NOEXCEPT throw()
|
||||
#endif // RAPIDJSON_HAS_CXX11_NOEXCEPT
|
||||
#endif
|
||||
|
||||
// no automatic detection, yet
|
||||
#ifndef CEREAL_RAPIDJSON_HAS_CXX11_TYPETRAITS
|
||||
#define CEREAL_RAPIDJSON_HAS_CXX11_TYPETRAITS 0
|
||||
#ifndef RAPIDJSON_HAS_CXX11_TYPETRAITS
|
||||
#if (defined(_MSC_VER) && _MSC_VER >= 1700)
|
||||
#define RAPIDJSON_HAS_CXX11_TYPETRAITS 1
|
||||
#else
|
||||
#define RAPIDJSON_HAS_CXX11_TYPETRAITS 0
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef CEREAL_RAPIDJSON_HAS_CXX11_RANGE_FOR
|
||||
#ifndef RAPIDJSON_HAS_CXX11_RANGE_FOR
|
||||
#if defined(__clang__)
|
||||
#define CEREAL_RAPIDJSON_HAS_CXX11_RANGE_FOR __has_feature(cxx_range_for)
|
||||
#elif (defined(CEREAL_RAPIDJSON_GNUC) && (CEREAL_RAPIDJSON_GNUC >= CEREAL_RAPIDJSON_VERSION_CODE(4,3,0)) && defined(__GXX_EXPERIMENTAL_CXX0X__)) || \
|
||||
(defined(_MSC_VER) && _MSC_VER >= 1700)
|
||||
#define CEREAL_RAPIDJSON_HAS_CXX11_RANGE_FOR 1
|
||||
#define RAPIDJSON_HAS_CXX11_RANGE_FOR __has_feature(cxx_range_for)
|
||||
#elif (defined(RAPIDJSON_GNUC) && (RAPIDJSON_GNUC >= RAPIDJSON_VERSION_CODE(4,6,0)) && defined(__GXX_EXPERIMENTAL_CXX0X__)) || \
|
||||
(defined(_MSC_VER) && _MSC_VER >= 1700) || \
|
||||
(defined(__SUNPRO_CC) && __SUNPRO_CC >= 0x5140 && defined(__GXX_EXPERIMENTAL_CXX0X__))
|
||||
#define RAPIDJSON_HAS_CXX11_RANGE_FOR 1
|
||||
#else
|
||||
#define CEREAL_RAPIDJSON_HAS_CXX11_RANGE_FOR 0
|
||||
#define RAPIDJSON_HAS_CXX11_RANGE_FOR 0
|
||||
#endif
|
||||
#endif // RAPIDJSON_HAS_CXX11_RANGE_FOR
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// C++17 features
|
||||
|
||||
#ifndef RAPIDJSON_HAS_CXX17
|
||||
#define RAPIDJSON_HAS_CXX17 (RAPIDJSON_CPLUSPLUS >= 201703L)
|
||||
#endif
|
||||
|
||||
#if RAPIDJSON_HAS_CXX17
|
||||
# define RAPIDJSON_DELIBERATE_FALLTHROUGH [[fallthrough]]
|
||||
#elif defined(__has_cpp_attribute)
|
||||
# if __has_cpp_attribute(clang::fallthrough)
|
||||
# define RAPIDJSON_DELIBERATE_FALLTHROUGH [[clang::fallthrough]]
|
||||
# elif __has_cpp_attribute(fallthrough)
|
||||
# define RAPIDJSON_DELIBERATE_FALLTHROUGH __attribute__((fallthrough))
|
||||
# else
|
||||
# define RAPIDJSON_DELIBERATE_FALLTHROUGH
|
||||
# endif
|
||||
#else
|
||||
# define RAPIDJSON_DELIBERATE_FALLTHROUGH
|
||||
#endif
|
||||
#endif // CEREAL_RAPIDJSON_HAS_CXX11_RANGE_FOR
|
||||
|
||||
//!@endcond
|
||||
|
||||
//! Assertion (in non-throwing contexts).
|
||||
/*! \ingroup RAPIDJSON_CONFIG
|
||||
Some functions provide a \c noexcept guarantee, if the compiler supports it.
|
||||
In these cases, the \ref RAPIDJSON_ASSERT macro cannot be overridden to
|
||||
throw an exception. This macro adds a separate customization point for
|
||||
such cases.
|
||||
|
||||
Defaults to C \c assert() (as \ref RAPIDJSON_ASSERT), if \c noexcept is
|
||||
supported, and to \ref RAPIDJSON_ASSERT otherwise.
|
||||
*/
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// RAPIDJSON_NOEXCEPT_ASSERT
|
||||
|
||||
#ifndef RAPIDJSON_NOEXCEPT_ASSERT
|
||||
#ifdef RAPIDJSON_ASSERT_THROWS
|
||||
#include <cassert>
|
||||
#define RAPIDJSON_NOEXCEPT_ASSERT(x) assert(x)
|
||||
#else
|
||||
#define RAPIDJSON_NOEXCEPT_ASSERT(x) RAPIDJSON_ASSERT(x)
|
||||
#endif // RAPIDJSON_ASSERT_THROWS
|
||||
#endif // RAPIDJSON_NOEXCEPT_ASSERT
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// malloc/realloc/free
|
||||
|
||||
#ifndef RAPIDJSON_MALLOC
|
||||
///! customization point for global \c malloc
|
||||
#define RAPIDJSON_MALLOC(size) std::malloc(size)
|
||||
#endif
|
||||
#ifndef RAPIDJSON_REALLOC
|
||||
///! customization point for global \c realloc
|
||||
#define RAPIDJSON_REALLOC(ptr, new_size) std::realloc(ptr, new_size)
|
||||
#endif
|
||||
#ifndef RAPIDJSON_FREE
|
||||
///! customization point for global \c free
|
||||
#define RAPIDJSON_FREE(ptr) std::free(ptr)
|
||||
#endif
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// new/delete
|
||||
|
||||
#ifndef CEREAL_RAPIDJSON_NEW
|
||||
#ifndef RAPIDJSON_NEW
|
||||
///! customization point for global \c new
|
||||
#define CEREAL_RAPIDJSON_NEW(x) new x
|
||||
#define RAPIDJSON_NEW(TypeName) new TypeName
|
||||
#endif
|
||||
#ifndef CEREAL_RAPIDJSON_DELETE
|
||||
#ifndef RAPIDJSON_DELETE
|
||||
///! customization point for global \c delete
|
||||
#define CEREAL_RAPIDJSON_DELETE(x) delete x
|
||||
#define RAPIDJSON_DELETE(x) delete x
|
||||
#endif
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
@ -595,9 +721,9 @@ CEREAL_RAPIDJSON_NAMESPACE_END
|
||||
|
||||
/*! \namespace rapidjson
|
||||
\brief main RapidJSON namespace
|
||||
\see CEREAL_RAPIDJSON_NAMESPACE
|
||||
\see RAPIDJSON_NAMESPACE
|
||||
*/
|
||||
CEREAL_RAPIDJSON_NAMESPACE_BEGIN
|
||||
RAPIDJSON_NAMESPACE_BEGIN
|
||||
|
||||
//! Type of JSON value
|
||||
enum Type {
|
||||
@ -610,6 +736,6 @@ enum Type {
|
||||
kNumberType = 6 //!< number
|
||||
};
|
||||
|
||||
CEREAL_RAPIDJSON_NAMESPACE_END
|
||||
RAPIDJSON_NAMESPACE_END
|
||||
|
||||
#endif // CEREAL_RAPIDJSON_CEREAL_RAPIDJSON_H_
|
||||
#endif // RAPIDJSON_RAPIDJSON_H_
|
||||
|
1101
external/cereal/external/rapidjson/reader.h
vendored
1101
external/cereal/external/rapidjson/reader.h
vendored
File diff suppressed because it is too large
Load Diff
1660
external/cereal/external/rapidjson/schema.h
vendored
1660
external/cereal/external/rapidjson/schema.h
vendored
File diff suppressed because it is too large
Load Diff
74
external/cereal/external/rapidjson/stream.h
vendored
74
external/cereal/external/rapidjson/stream.h
vendored
@ -1,25 +1,25 @@
|
||||
// Tencent is pleased to support the open source community by making RapidJSON available.
|
||||
//
|
||||
// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
|
||||
//
|
||||
// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip.
|
||||
//
|
||||
// Licensed under the MIT License (the "License"); you may not use this file except
|
||||
// in compliance with the License. You may obtain a copy of the License at
|
||||
//
|
||||
// http://opensource.org/licenses/MIT
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software distributed
|
||||
// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
|
||||
// CONDITIONS OF ANY KIND, either express or implied. See the License for the
|
||||
// Unless required by applicable law or agreed to in writing, software distributed
|
||||
// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
|
||||
// CONDITIONS OF ANY KIND, either express or implied. See the License for the
|
||||
// specific language governing permissions and limitations under the License.
|
||||
|
||||
#include "rapidjson.h"
|
||||
|
||||
#ifndef CEREAL_RAPIDJSON_STREAM_H_
|
||||
#define CEREAL_RAPIDJSON_STREAM_H_
|
||||
#ifndef RAPIDJSON_STREAM_H_
|
||||
#define RAPIDJSON_STREAM_H_
|
||||
|
||||
#include "encodings.h"
|
||||
|
||||
CEREAL_RAPIDJSON_NAMESPACE_BEGIN
|
||||
RAPIDJSON_NAMESPACE_BEGIN
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Stream
|
||||
@ -100,6 +100,50 @@ inline void PutN(Stream& stream, Ch c, size_t n) {
|
||||
PutUnsafe(stream, c);
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// GenericStreamWrapper
|
||||
|
||||
//! A Stream Wrapper
|
||||
/*! \tThis string stream is a wrapper for any stream by just forwarding any
|
||||
\treceived message to the origin stream.
|
||||
\note implements Stream concept
|
||||
*/
|
||||
|
||||
#if defined(_MSC_VER) && _MSC_VER <= 1800
|
||||
RAPIDJSON_DIAG_PUSH
|
||||
RAPIDJSON_DIAG_OFF(4702) // unreachable code
|
||||
RAPIDJSON_DIAG_OFF(4512) // assignment operator could not be generated
|
||||
#endif
|
||||
|
||||
template <typename InputStream, typename Encoding = UTF8<> >
|
||||
class GenericStreamWrapper {
|
||||
public:
|
||||
typedef typename Encoding::Ch Ch;
|
||||
GenericStreamWrapper(InputStream& is): is_(is) {}
|
||||
|
||||
Ch Peek() const { return is_.Peek(); }
|
||||
Ch Take() { return is_.Take(); }
|
||||
size_t Tell() { return is_.Tell(); }
|
||||
Ch* PutBegin() { return is_.PutBegin(); }
|
||||
void Put(Ch ch) { is_.Put(ch); }
|
||||
void Flush() { is_.Flush(); }
|
||||
size_t PutEnd(Ch* ch) { return is_.PutEnd(ch); }
|
||||
|
||||
// wrapper for MemoryStream
|
||||
const Ch* Peek4() const { return is_.Peek4(); }
|
||||
|
||||
// wrapper for AutoUTFInputStream
|
||||
UTFType GetType() const { return is_.GetType(); }
|
||||
bool HasBOM() const { return is_.HasBOM(); }
|
||||
|
||||
protected:
|
||||
InputStream& is_;
|
||||
};
|
||||
|
||||
#if defined(_MSC_VER) && _MSC_VER <= 1800
|
||||
RAPIDJSON_DIAG_POP
|
||||
#endif
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// StringStream
|
||||
|
||||
@ -116,10 +160,10 @@ struct GenericStringStream {
|
||||
Ch Take() { return *src_++; }
|
||||
size_t Tell() const { return static_cast<size_t>(src_ - head_); }
|
||||
|
||||
Ch* PutBegin() { CEREAL_RAPIDJSON_ASSERT(false); return 0; }
|
||||
void Put(Ch) { CEREAL_RAPIDJSON_ASSERT(false); }
|
||||
void Flush() { CEREAL_RAPIDJSON_ASSERT(false); }
|
||||
size_t PutEnd(Ch*) { CEREAL_RAPIDJSON_ASSERT(false); return 0; }
|
||||
Ch* PutBegin() { RAPIDJSON_ASSERT(false); return 0; }
|
||||
void Put(Ch) { RAPIDJSON_ASSERT(false); }
|
||||
void Flush() { RAPIDJSON_ASSERT(false); }
|
||||
size_t PutEnd(Ch*) { RAPIDJSON_ASSERT(false); return 0; }
|
||||
|
||||
const Ch* src_; //!< Current read position.
|
||||
const Ch* head_; //!< Original head of the string.
|
||||
@ -152,7 +196,7 @@ struct GenericInsituStringStream {
|
||||
size_t Tell() { return static_cast<size_t>(src_ - head_); }
|
||||
|
||||
// Write
|
||||
void Put(Ch c) { CEREAL_RAPIDJSON_ASSERT(dst_ != 0); *dst_++ = c; }
|
||||
void Put(Ch c) { RAPIDJSON_ASSERT(dst_ != 0); *dst_++ = c; }
|
||||
|
||||
Ch* PutBegin() { return dst_ = src_; }
|
||||
size_t PutEnd(Ch* begin) { return static_cast<size_t>(dst_ - begin); }
|
||||
@ -174,6 +218,6 @@ struct StreamTraits<GenericInsituStringStream<Encoding> > {
|
||||
//! Insitu string stream with UTF8 encoding.
|
||||
typedef GenericInsituStringStream<UTF8<> > InsituStringStream;
|
||||
|
||||
CEREAL_RAPIDJSON_NAMESPACE_END
|
||||
RAPIDJSON_NAMESPACE_END
|
||||
|
||||
#endif // CEREAL_RAPIDJSON_STREAM_H_
|
||||
#endif // RAPIDJSON_STREAM_H_
|
||||
|
@ -1,6 +1,6 @@
|
||||
// Tencent is pleased to support the open source community by making RapidJSON available.
|
||||
//
|
||||
// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
|
||||
// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip.
|
||||
//
|
||||
// Licensed under the MIT License (the "License"); you may not use this file except
|
||||
// in compliance with the License. You may obtain a copy of the License at
|
||||
@ -12,24 +12,24 @@
|
||||
// CONDITIONS OF ANY KIND, either express or implied. See the License for the
|
||||
// specific language governing permissions and limitations under the License.
|
||||
|
||||
#ifndef CEREAL_RAPIDJSON_STRINGBUFFER_H_
|
||||
#define CEREAL_RAPIDJSON_STRINGBUFFER_H_
|
||||
#ifndef RAPIDJSON_STRINGBUFFER_H_
|
||||
#define RAPIDJSON_STRINGBUFFER_H_
|
||||
|
||||
#include "stream.h"
|
||||
#include "internal/stack.h"
|
||||
|
||||
#if CEREAL_RAPIDJSON_HAS_CXX11_RVALUE_REFS
|
||||
#if RAPIDJSON_HAS_CXX11_RVALUE_REFS
|
||||
#include <utility> // std::move
|
||||
#endif
|
||||
|
||||
#include "internal/stack.h"
|
||||
|
||||
#if defined(__clang__)
|
||||
CEREAL_RAPIDJSON_DIAG_PUSH
|
||||
CEREAL_RAPIDJSON_DIAG_OFF(c++98-compat)
|
||||
RAPIDJSON_DIAG_PUSH
|
||||
RAPIDJSON_DIAG_OFF(c++98-compat)
|
||||
#endif
|
||||
|
||||
CEREAL_RAPIDJSON_NAMESPACE_BEGIN
|
||||
RAPIDJSON_NAMESPACE_BEGIN
|
||||
|
||||
//! Represents an in-memory output stream.
|
||||
/*!
|
||||
@ -44,7 +44,7 @@ public:
|
||||
|
||||
GenericStringBuffer(Allocator* allocator = 0, size_t capacity = kDefaultCapacity) : stack_(allocator, capacity) {}
|
||||
|
||||
#if CEREAL_RAPIDJSON_HAS_CXX11_RVALUE_REFS
|
||||
#if RAPIDJSON_HAS_CXX11_RVALUE_REFS
|
||||
GenericStringBuffer(GenericStringBuffer&& rhs) : stack_(std::move(rhs.stack_)) {}
|
||||
GenericStringBuffer& operator=(GenericStringBuffer&& rhs) {
|
||||
if (&rhs != this)
|
||||
@ -78,8 +78,12 @@ public:
|
||||
return stack_.template Bottom<Ch>();
|
||||
}
|
||||
|
||||
//! Get the size of string in bytes in the string buffer.
|
||||
size_t GetSize() const { return stack_.GetSize(); }
|
||||
|
||||
//! Get the length of string in Ch in the string buffer.
|
||||
size_t GetLength() const { return stack_.GetSize() / sizeof(Ch); }
|
||||
|
||||
static const size_t kDefaultCapacity = 256;
|
||||
mutable internal::Stack<Allocator> stack_;
|
||||
|
||||
@ -108,10 +112,10 @@ inline void PutN(GenericStringBuffer<UTF8<> >& stream, char c, size_t n) {
|
||||
std::memset(stream.stack_.Push<char>(n), c, n * sizeof(c));
|
||||
}
|
||||
|
||||
CEREAL_RAPIDJSON_NAMESPACE_END
|
||||
RAPIDJSON_NAMESPACE_END
|
||||
|
||||
#if defined(__clang__)
|
||||
CEREAL_RAPIDJSON_DIAG_POP
|
||||
RAPIDJSON_DIAG_POP
|
||||
#endif
|
||||
|
||||
#endif // CEREAL_RAPIDJSON_STRINGBUFFER_H_
|
||||
#endif // RAPIDJSON_STRINGBUFFER_H_
|
||||
|
481
external/cereal/external/rapidjson/uri.h
vendored
Normal file
481
external/cereal/external/rapidjson/uri.h
vendored
Normal file
@ -0,0 +1,481 @@
|
||||
// Tencent is pleased to support the open source community by making RapidJSON available.
|
||||
//
|
||||
// (C) Copyright IBM Corporation 2021
|
||||
//
|
||||
// Licensed under the MIT License (the "License"); you may not use this file except
|
||||
// in compliance with the License. You may obtain a copy of the License at
|
||||
//
|
||||
// http://opensource.org/licenses/MIT
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software distributed
|
||||
// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
|
||||
// CONDITIONS OF ANY KIND, either express or implied. See the License for the
|
||||
// specific language governing permissions and limitations under the License.
|
||||
|
||||
#ifndef RAPIDJSON_URI_H_
|
||||
#define RAPIDJSON_URI_H_
|
||||
|
||||
#include "internal/strfunc.h"
|
||||
|
||||
#if defined(__clang__)
|
||||
RAPIDJSON_DIAG_PUSH
|
||||
RAPIDJSON_DIAG_OFF(c++98-compat)
|
||||
#elif defined(_MSC_VER)
|
||||
RAPIDJSON_DIAG_OFF(4512) // assignment operator could not be generated
|
||||
#endif
|
||||
|
||||
RAPIDJSON_NAMESPACE_BEGIN
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// GenericUri
|
||||
|
||||
template <typename ValueType, typename Allocator=CrtAllocator>
|
||||
class GenericUri {
|
||||
public:
|
||||
typedef typename ValueType::Ch Ch;
|
||||
#if RAPIDJSON_HAS_STDSTRING
|
||||
typedef std::basic_string<Ch> String;
|
||||
#endif
|
||||
|
||||
//! Constructors
|
||||
GenericUri(Allocator* allocator = 0) : uri_(), base_(), scheme_(), auth_(), path_(), query_(), frag_(), allocator_(allocator), ownAllocator_() {
|
||||
}
|
||||
|
||||
GenericUri(const Ch* uri, SizeType len, Allocator* allocator = 0) : uri_(), base_(), scheme_(), auth_(), path_(), query_(), frag_(), allocator_(allocator), ownAllocator_() {
|
||||
Parse(uri, len);
|
||||
}
|
||||
|
||||
GenericUri(const Ch* uri, Allocator* allocator = 0) : uri_(), base_(), scheme_(), auth_(), path_(), query_(), frag_(), allocator_(allocator), ownAllocator_() {
|
||||
Parse(uri, internal::StrLen<Ch>(uri));
|
||||
}
|
||||
|
||||
// Use with specializations of GenericValue
|
||||
template<typename T> GenericUri(const T& uri, Allocator* allocator = 0) : uri_(), base_(), scheme_(), auth_(), path_(), query_(), frag_(), allocator_(allocator), ownAllocator_() {
|
||||
const Ch* u = uri.template Get<const Ch*>(); // TypeHelper from document.h
|
||||
Parse(u, internal::StrLen<Ch>(u));
|
||||
}
|
||||
|
||||
#if RAPIDJSON_HAS_STDSTRING
|
||||
GenericUri(const String& uri, Allocator* allocator = 0) : uri_(), base_(), scheme_(), auth_(), path_(), query_(), frag_(), allocator_(allocator), ownAllocator_() {
|
||||
Parse(uri.c_str(), internal::StrLen<Ch>(uri.c_str()));
|
||||
}
|
||||
#endif
|
||||
|
||||
//! Copy constructor
|
||||
GenericUri(const GenericUri& rhs) : uri_(), base_(), scheme_(), auth_(), path_(), query_(), frag_(), allocator_(), ownAllocator_() {
|
||||
*this = rhs;
|
||||
}
|
||||
|
||||
//! Copy constructor
|
||||
GenericUri(const GenericUri& rhs, Allocator* allocator) : uri_(), base_(), scheme_(), auth_(), path_(), query_(), frag_(), allocator_(allocator), ownAllocator_() {
|
||||
*this = rhs;
|
||||
}
|
||||
|
||||
//! Destructor.
|
||||
~GenericUri() {
|
||||
Free();
|
||||
RAPIDJSON_DELETE(ownAllocator_);
|
||||
}
|
||||
|
||||
//! Assignment operator
|
||||
GenericUri& operator=(const GenericUri& rhs) {
|
||||
if (this != &rhs) {
|
||||
// Do not delete ownAllocator
|
||||
Free();
|
||||
Allocate(rhs.GetStringLength());
|
||||
auth_ = CopyPart(scheme_, rhs.scheme_, rhs.GetSchemeStringLength());
|
||||
path_ = CopyPart(auth_, rhs.auth_, rhs.GetAuthStringLength());
|
||||
query_ = CopyPart(path_, rhs.path_, rhs.GetPathStringLength());
|
||||
frag_ = CopyPart(query_, rhs.query_, rhs.GetQueryStringLength());
|
||||
base_ = CopyPart(frag_, rhs.frag_, rhs.GetFragStringLength());
|
||||
uri_ = CopyPart(base_, rhs.base_, rhs.GetBaseStringLength());
|
||||
CopyPart(uri_, rhs.uri_, rhs.GetStringLength());
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
//! Getters
|
||||
// Use with specializations of GenericValue
|
||||
template<typename T> void Get(T& uri, Allocator& allocator) {
|
||||
uri.template Set<const Ch*>(this->GetString(), allocator); // TypeHelper from document.h
|
||||
}
|
||||
|
||||
const Ch* GetString() const { return uri_; }
|
||||
SizeType GetStringLength() const { return uri_ == 0 ? 0 : internal::StrLen<Ch>(uri_); }
|
||||
const Ch* GetBaseString() const { return base_; }
|
||||
SizeType GetBaseStringLength() const { return base_ == 0 ? 0 : internal::StrLen<Ch>(base_); }
|
||||
const Ch* GetSchemeString() const { return scheme_; }
|
||||
SizeType GetSchemeStringLength() const { return scheme_ == 0 ? 0 : internal::StrLen<Ch>(scheme_); }
|
||||
const Ch* GetAuthString() const { return auth_; }
|
||||
SizeType GetAuthStringLength() const { return auth_ == 0 ? 0 : internal::StrLen<Ch>(auth_); }
|
||||
const Ch* GetPathString() const { return path_; }
|
||||
SizeType GetPathStringLength() const { return path_ == 0 ? 0 : internal::StrLen<Ch>(path_); }
|
||||
const Ch* GetQueryString() const { return query_; }
|
||||
SizeType GetQueryStringLength() const { return query_ == 0 ? 0 : internal::StrLen<Ch>(query_); }
|
||||
const Ch* GetFragString() const { return frag_; }
|
||||
SizeType GetFragStringLength() const { return frag_ == 0 ? 0 : internal::StrLen<Ch>(frag_); }
|
||||
|
||||
#if RAPIDJSON_HAS_STDSTRING
|
||||
static String Get(const GenericUri& uri) { return String(uri.GetString(), uri.GetStringLength()); }
|
||||
static String GetBase(const GenericUri& uri) { return String(uri.GetBaseString(), uri.GetBaseStringLength()); }
|
||||
static String GetScheme(const GenericUri& uri) { return String(uri.GetSchemeString(), uri.GetSchemeStringLength()); }
|
||||
static String GetAuth(const GenericUri& uri) { return String(uri.GetAuthString(), uri.GetAuthStringLength()); }
|
||||
static String GetPath(const GenericUri& uri) { return String(uri.GetPathString(), uri.GetPathStringLength()); }
|
||||
static String GetQuery(const GenericUri& uri) { return String(uri.GetQueryString(), uri.GetQueryStringLength()); }
|
||||
static String GetFrag(const GenericUri& uri) { return String(uri.GetFragString(), uri.GetFragStringLength()); }
|
||||
#endif
|
||||
|
||||
//! Equality operators
|
||||
bool operator==(const GenericUri& rhs) const {
|
||||
return Match(rhs, true);
|
||||
}
|
||||
|
||||
bool operator!=(const GenericUri& rhs) const {
|
||||
return !Match(rhs, true);
|
||||
}
|
||||
|
||||
bool Match(const GenericUri& uri, bool full = true) const {
|
||||
Ch* s1;
|
||||
Ch* s2;
|
||||
if (full) {
|
||||
s1 = uri_;
|
||||
s2 = uri.uri_;
|
||||
} else {
|
||||
s1 = base_;
|
||||
s2 = uri.base_;
|
||||
}
|
||||
if (s1 == s2) return true;
|
||||
if (s1 == 0 || s2 == 0) return false;
|
||||
return internal::StrCmp<Ch>(s1, s2) == 0;
|
||||
}
|
||||
|
||||
//! Resolve this URI against another (base) URI in accordance with URI resolution rules.
|
||||
// See https://tools.ietf.org/html/rfc3986
|
||||
// Use for resolving an id or $ref with an in-scope id.
|
||||
// Returns a new GenericUri for the resolved URI.
|
||||
GenericUri Resolve(const GenericUri& baseuri, Allocator* allocator = 0) {
|
||||
GenericUri resuri;
|
||||
resuri.allocator_ = allocator;
|
||||
// Ensure enough space for combining paths
|
||||
resuri.Allocate(GetStringLength() + baseuri.GetStringLength() + 1); // + 1 for joining slash
|
||||
|
||||
if (!(GetSchemeStringLength() == 0)) {
|
||||
// Use all of this URI
|
||||
resuri.auth_ = CopyPart(resuri.scheme_, scheme_, GetSchemeStringLength());
|
||||
resuri.path_ = CopyPart(resuri.auth_, auth_, GetAuthStringLength());
|
||||
resuri.query_ = CopyPart(resuri.path_, path_, GetPathStringLength());
|
||||
resuri.frag_ = CopyPart(resuri.query_, query_, GetQueryStringLength());
|
||||
resuri.RemoveDotSegments();
|
||||
} else {
|
||||
// Use the base scheme
|
||||
resuri.auth_ = CopyPart(resuri.scheme_, baseuri.scheme_, baseuri.GetSchemeStringLength());
|
||||
if (!(GetAuthStringLength() == 0)) {
|
||||
// Use this auth, path, query
|
||||
resuri.path_ = CopyPart(resuri.auth_, auth_, GetAuthStringLength());
|
||||
resuri.query_ = CopyPart(resuri.path_, path_, GetPathStringLength());
|
||||
resuri.frag_ = CopyPart(resuri.query_, query_, GetQueryStringLength());
|
||||
resuri.RemoveDotSegments();
|
||||
} else {
|
||||
// Use the base auth
|
||||
resuri.path_ = CopyPart(resuri.auth_, baseuri.auth_, baseuri.GetAuthStringLength());
|
||||
if (GetPathStringLength() == 0) {
|
||||
// Use the base path
|
||||
resuri.query_ = CopyPart(resuri.path_, baseuri.path_, baseuri.GetPathStringLength());
|
||||
if (GetQueryStringLength() == 0) {
|
||||
// Use the base query
|
||||
resuri.frag_ = CopyPart(resuri.query_, baseuri.query_, baseuri.GetQueryStringLength());
|
||||
} else {
|
||||
// Use this query
|
||||
resuri.frag_ = CopyPart(resuri.query_, query_, GetQueryStringLength());
|
||||
}
|
||||
} else {
|
||||
if (path_[0] == '/') {
|
||||
// Absolute path - use all of this path
|
||||
resuri.query_ = CopyPart(resuri.path_, path_, GetPathStringLength());
|
||||
resuri.RemoveDotSegments();
|
||||
} else {
|
||||
// Relative path - append this path to base path after base path's last slash
|
||||
size_t pos = 0;
|
||||
if (!(baseuri.GetAuthStringLength() == 0) && baseuri.GetPathStringLength() == 0) {
|
||||
resuri.path_[pos] = '/';
|
||||
pos++;
|
||||
}
|
||||
size_t lastslashpos = baseuri.GetPathStringLength();
|
||||
while (lastslashpos > 0) {
|
||||
if (baseuri.path_[lastslashpos - 1] == '/') break;
|
||||
lastslashpos--;
|
||||
}
|
||||
std::memcpy(&resuri.path_[pos], baseuri.path_, lastslashpos * sizeof(Ch));
|
||||
pos += lastslashpos;
|
||||
resuri.query_ = CopyPart(&resuri.path_[pos], path_, GetPathStringLength());
|
||||
resuri.RemoveDotSegments();
|
||||
}
|
||||
// Use this query
|
||||
resuri.frag_ = CopyPart(resuri.query_, query_, GetQueryStringLength());
|
||||
}
|
||||
}
|
||||
}
|
||||
// Always use this frag
|
||||
resuri.base_ = CopyPart(resuri.frag_, frag_, GetFragStringLength());
|
||||
|
||||
// Re-constitute base_ and uri_
|
||||
resuri.SetBase();
|
||||
resuri.uri_ = resuri.base_ + resuri.GetBaseStringLength() + 1;
|
||||
resuri.SetUri();
|
||||
return resuri;
|
||||
}
|
||||
|
||||
//! Get the allocator of this GenericUri.
|
||||
Allocator& GetAllocator() { return *allocator_; }
|
||||
|
||||
private:
|
||||
// Allocate memory for a URI
|
||||
// Returns total amount allocated
|
||||
std::size_t Allocate(std::size_t len) {
|
||||
// Create own allocator if user did not supply.
|
||||
if (!allocator_)
|
||||
ownAllocator_ = allocator_ = RAPIDJSON_NEW(Allocator)();
|
||||
|
||||
// Allocate one block containing each part of the URI (5) plus base plus full URI, all null terminated.
|
||||
// Order: scheme, auth, path, query, frag, base, uri
|
||||
// Note need to set, increment, assign in 3 stages to avoid compiler warning bug.
|
||||
size_t total = (3 * len + 7) * sizeof(Ch);
|
||||
scheme_ = static_cast<Ch*>(allocator_->Malloc(total));
|
||||
*scheme_ = '\0';
|
||||
auth_ = scheme_;
|
||||
auth_++;
|
||||
*auth_ = '\0';
|
||||
path_ = auth_;
|
||||
path_++;
|
||||
*path_ = '\0';
|
||||
query_ = path_;
|
||||
query_++;
|
||||
*query_ = '\0';
|
||||
frag_ = query_;
|
||||
frag_++;
|
||||
*frag_ = '\0';
|
||||
base_ = frag_;
|
||||
base_++;
|
||||
*base_ = '\0';
|
||||
uri_ = base_;
|
||||
uri_++;
|
||||
*uri_ = '\0';
|
||||
return total;
|
||||
}
|
||||
|
||||
// Free memory for a URI
|
||||
void Free() {
|
||||
if (scheme_) {
|
||||
Allocator::Free(scheme_);
|
||||
scheme_ = 0;
|
||||
}
|
||||
}
|
||||
|
||||
// Parse a URI into constituent scheme, authority, path, query, & fragment parts
|
||||
// Supports URIs that match regex ^(([^:/?#]+):)?(//([^/?#]*))?([^?#]*)(\?([^#]*))?(#(.*))? as per
|
||||
// https://tools.ietf.org/html/rfc3986
|
||||
void Parse(const Ch* uri, std::size_t len) {
|
||||
std::size_t start = 0, pos1 = 0, pos2 = 0;
|
||||
Allocate(len);
|
||||
|
||||
// Look for scheme ([^:/?#]+):)?
|
||||
if (start < len) {
|
||||
while (pos1 < len) {
|
||||
if (uri[pos1] == ':') break;
|
||||
pos1++;
|
||||
}
|
||||
if (pos1 != len) {
|
||||
while (pos2 < len) {
|
||||
if (uri[pos2] == '/') break;
|
||||
if (uri[pos2] == '?') break;
|
||||
if (uri[pos2] == '#') break;
|
||||
pos2++;
|
||||
}
|
||||
if (pos1 < pos2) {
|
||||
pos1++;
|
||||
std::memcpy(scheme_, &uri[start], pos1 * sizeof(Ch));
|
||||
scheme_[pos1] = '\0';
|
||||
start = pos1;
|
||||
}
|
||||
}
|
||||
}
|
||||
// Look for auth (//([^/?#]*))?
|
||||
// Note need to set, increment, assign in 3 stages to avoid compiler warning bug.
|
||||
auth_ = scheme_ + GetSchemeStringLength();
|
||||
auth_++;
|
||||
*auth_ = '\0';
|
||||
if (start < len - 1 && uri[start] == '/' && uri[start + 1] == '/') {
|
||||
pos2 = start + 2;
|
||||
while (pos2 < len) {
|
||||
if (uri[pos2] == '/') break;
|
||||
if (uri[pos2] == '?') break;
|
||||
if (uri[pos2] == '#') break;
|
||||
pos2++;
|
||||
}
|
||||
std::memcpy(auth_, &uri[start], (pos2 - start) * sizeof(Ch));
|
||||
auth_[pos2 - start] = '\0';
|
||||
start = pos2;
|
||||
}
|
||||
// Look for path ([^?#]*)
|
||||
// Note need to set, increment, assign in 3 stages to avoid compiler warning bug.
|
||||
path_ = auth_ + GetAuthStringLength();
|
||||
path_++;
|
||||
*path_ = '\0';
|
||||
if (start < len) {
|
||||
pos2 = start;
|
||||
while (pos2 < len) {
|
||||
if (uri[pos2] == '?') break;
|
||||
if (uri[pos2] == '#') break;
|
||||
pos2++;
|
||||
}
|
||||
if (start != pos2) {
|
||||
std::memcpy(path_, &uri[start], (pos2 - start) * sizeof(Ch));
|
||||
path_[pos2 - start] = '\0';
|
||||
if (path_[0] == '/')
|
||||
RemoveDotSegments(); // absolute path - normalize
|
||||
start = pos2;
|
||||
}
|
||||
}
|
||||
// Look for query (\?([^#]*))?
|
||||
// Note need to set, increment, assign in 3 stages to avoid compiler warning bug.
|
||||
query_ = path_ + GetPathStringLength();
|
||||
query_++;
|
||||
*query_ = '\0';
|
||||
if (start < len && uri[start] == '?') {
|
||||
pos2 = start + 1;
|
||||
while (pos2 < len) {
|
||||
if (uri[pos2] == '#') break;
|
||||
pos2++;
|
||||
}
|
||||
if (start != pos2) {
|
||||
std::memcpy(query_, &uri[start], (pos2 - start) * sizeof(Ch));
|
||||
query_[pos2 - start] = '\0';
|
||||
start = pos2;
|
||||
}
|
||||
}
|
||||
// Look for fragment (#(.*))?
|
||||
// Note need to set, increment, assign in 3 stages to avoid compiler warning bug.
|
||||
frag_ = query_ + GetQueryStringLength();
|
||||
frag_++;
|
||||
*frag_ = '\0';
|
||||
if (start < len && uri[start] == '#') {
|
||||
std::memcpy(frag_, &uri[start], (len - start) * sizeof(Ch));
|
||||
frag_[len - start] = '\0';
|
||||
}
|
||||
|
||||
// Re-constitute base_ and uri_
|
||||
base_ = frag_ + GetFragStringLength() + 1;
|
||||
SetBase();
|
||||
uri_ = base_ + GetBaseStringLength() + 1;
|
||||
SetUri();
|
||||
}
|
||||
|
||||
// Reconstitute base
|
||||
void SetBase() {
|
||||
Ch* next = base_;
|
||||
std::memcpy(next, scheme_, GetSchemeStringLength() * sizeof(Ch));
|
||||
next+= GetSchemeStringLength();
|
||||
std::memcpy(next, auth_, GetAuthStringLength() * sizeof(Ch));
|
||||
next+= GetAuthStringLength();
|
||||
std::memcpy(next, path_, GetPathStringLength() * sizeof(Ch));
|
||||
next+= GetPathStringLength();
|
||||
std::memcpy(next, query_, GetQueryStringLength() * sizeof(Ch));
|
||||
next+= GetQueryStringLength();
|
||||
*next = '\0';
|
||||
}
|
||||
|
||||
// Reconstitute uri
|
||||
void SetUri() {
|
||||
Ch* next = uri_;
|
||||
std::memcpy(next, base_, GetBaseStringLength() * sizeof(Ch));
|
||||
next+= GetBaseStringLength();
|
||||
std::memcpy(next, frag_, GetFragStringLength() * sizeof(Ch));
|
||||
next+= GetFragStringLength();
|
||||
*next = '\0';
|
||||
}
|
||||
|
||||
// Copy a part from one GenericUri to another
|
||||
// Return the pointer to the next part to be copied to
|
||||
Ch* CopyPart(Ch* to, Ch* from, std::size_t len) {
|
||||
RAPIDJSON_ASSERT(to != 0);
|
||||
RAPIDJSON_ASSERT(from != 0);
|
||||
std::memcpy(to, from, len * sizeof(Ch));
|
||||
to[len] = '\0';
|
||||
Ch* next = to + len + 1;
|
||||
return next;
|
||||
}
|
||||
|
||||
// Remove . and .. segments from the path_ member.
|
||||
// https://tools.ietf.org/html/rfc3986
|
||||
// This is done in place as we are only removing segments.
|
||||
void RemoveDotSegments() {
|
||||
std::size_t pathlen = GetPathStringLength();
|
||||
std::size_t pathpos = 0; // Position in path_
|
||||
std::size_t newpos = 0; // Position in new path_
|
||||
|
||||
// Loop through each segment in original path_
|
||||
while (pathpos < pathlen) {
|
||||
// Get next segment, bounded by '/' or end
|
||||
size_t slashpos = 0;
|
||||
while ((pathpos + slashpos) < pathlen) {
|
||||
if (path_[pathpos + slashpos] == '/') break;
|
||||
slashpos++;
|
||||
}
|
||||
// Check for .. and . segments
|
||||
if (slashpos == 2 && path_[pathpos] == '.' && path_[pathpos + 1] == '.') {
|
||||
// Backup a .. segment in the new path_
|
||||
// We expect to find a previously added slash at the end or nothing
|
||||
RAPIDJSON_ASSERT(newpos == 0 || path_[newpos - 1] == '/');
|
||||
size_t lastslashpos = newpos;
|
||||
// Make sure we don't go beyond the start segment
|
||||
if (lastslashpos > 1) {
|
||||
// Find the next to last slash and back up to it
|
||||
lastslashpos--;
|
||||
while (lastslashpos > 0) {
|
||||
if (path_[lastslashpos - 1] == '/') break;
|
||||
lastslashpos--;
|
||||
}
|
||||
// Set the new path_ position
|
||||
newpos = lastslashpos;
|
||||
}
|
||||
} else if (slashpos == 1 && path_[pathpos] == '.') {
|
||||
// Discard . segment, leaves new path_ unchanged
|
||||
} else {
|
||||
// Move any other kind of segment to the new path_
|
||||
RAPIDJSON_ASSERT(newpos <= pathpos);
|
||||
std::memmove(&path_[newpos], &path_[pathpos], slashpos * sizeof(Ch));
|
||||
newpos += slashpos;
|
||||
// Add slash if not at end
|
||||
if ((pathpos + slashpos) < pathlen) {
|
||||
path_[newpos] = '/';
|
||||
newpos++;
|
||||
}
|
||||
}
|
||||
// Move to next segment
|
||||
pathpos += slashpos + 1;
|
||||
}
|
||||
path_[newpos] = '\0';
|
||||
}
|
||||
|
||||
Ch* uri_; // Everything
|
||||
Ch* base_; // Everything except fragment
|
||||
Ch* scheme_; // Includes the :
|
||||
Ch* auth_; // Includes the //
|
||||
Ch* path_; // Absolute if starts with /
|
||||
Ch* query_; // Includes the ?
|
||||
Ch* frag_; // Includes the #
|
||||
|
||||
Allocator* allocator_; //!< The current allocator. It is either user-supplied or equal to ownAllocator_.
|
||||
Allocator* ownAllocator_; //!< Allocator owned by this Uri.
|
||||
};
|
||||
|
||||
//! GenericUri for Value (UTF-8, default allocator).
|
||||
typedef GenericUri<Value> Uri;
|
||||
|
||||
RAPIDJSON_NAMESPACE_END
|
||||
|
||||
#if defined(__clang__)
|
||||
RAPIDJSON_DIAG_POP
|
||||
#endif
|
||||
|
||||
#endif // RAPIDJSON_URI_H_
|
240
external/cereal/external/rapidjson/writer.h
vendored
240
external/cereal/external/rapidjson/writer.h
vendored
@ -1,6 +1,6 @@
|
||||
// Tencent is pleased to support the open source community by making RapidJSON available.
|
||||
//
|
||||
// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
|
||||
// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip.
|
||||
//
|
||||
// Licensed under the MIT License (the "License"); you may not use this file except
|
||||
// in compliance with the License. You may obtain a copy of the License at
|
||||
@ -12,10 +12,12 @@
|
||||
// CONDITIONS OF ANY KIND, either express or implied. See the License for the
|
||||
// specific language governing permissions and limitations under the License.
|
||||
|
||||
#ifndef CEREAL_RAPIDJSON_WRITER_H_
|
||||
#define CEREAL_RAPIDJSON_WRITER_H_
|
||||
#ifndef RAPIDJSON_WRITER_H_
|
||||
#define RAPIDJSON_WRITER_H_
|
||||
|
||||
#include "stream.h"
|
||||
#include "internal/clzll.h"
|
||||
#include "internal/meta.h"
|
||||
#include "internal/stack.h"
|
||||
#include "internal/strfunc.h"
|
||||
#include "internal/dtoa.h"
|
||||
@ -23,48 +25,49 @@
|
||||
#include "stringbuffer.h"
|
||||
#include <new> // placement new
|
||||
|
||||
#if defined(CEREAL_RAPIDJSON_SIMD) && defined(_MSC_VER)
|
||||
#if defined(RAPIDJSON_SIMD) && defined(_MSC_VER)
|
||||
#include <intrin.h>
|
||||
#pragma intrinsic(_BitScanForward)
|
||||
#endif
|
||||
#ifdef CEREAL_RAPIDJSON_SSE42
|
||||
#ifdef RAPIDJSON_SSE42
|
||||
#include <nmmintrin.h>
|
||||
#elif defined(CEREAL_RAPIDJSON_SSE2)
|
||||
#elif defined(RAPIDJSON_SSE2)
|
||||
#include <emmintrin.h>
|
||||
#endif
|
||||
|
||||
#ifdef _MSC_VER
|
||||
CEREAL_RAPIDJSON_DIAG_PUSH
|
||||
CEREAL_RAPIDJSON_DIAG_OFF(4127) // conditional expression is constant
|
||||
#elif defined(RAPIDJSON_NEON)
|
||||
#include <arm_neon.h>
|
||||
#endif
|
||||
|
||||
#ifdef __clang__
|
||||
CEREAL_RAPIDJSON_DIAG_PUSH
|
||||
CEREAL_RAPIDJSON_DIAG_OFF(padded)
|
||||
CEREAL_RAPIDJSON_DIAG_OFF(unreachable-code)
|
||||
RAPIDJSON_DIAG_PUSH
|
||||
RAPIDJSON_DIAG_OFF(padded)
|
||||
RAPIDJSON_DIAG_OFF(unreachable-code)
|
||||
RAPIDJSON_DIAG_OFF(c++98-compat)
|
||||
#elif defined(_MSC_VER)
|
||||
RAPIDJSON_DIAG_PUSH
|
||||
RAPIDJSON_DIAG_OFF(4127) // conditional expression is constant
|
||||
#endif
|
||||
|
||||
CEREAL_RAPIDJSON_NAMESPACE_BEGIN
|
||||
RAPIDJSON_NAMESPACE_BEGIN
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// WriteFlag
|
||||
|
||||
/*! \def CEREAL_RAPIDJSON_WRITE_DEFAULT_FLAGS
|
||||
\ingroup CEREAL_RAPIDJSON_CONFIG
|
||||
/*! \def RAPIDJSON_WRITE_DEFAULT_FLAGS
|
||||
\ingroup RAPIDJSON_CONFIG
|
||||
\brief User-defined kWriteDefaultFlags definition.
|
||||
|
||||
User can define this as any \c WriteFlag combinations.
|
||||
*/
|
||||
#ifndef CEREAL_RAPIDJSON_WRITE_DEFAULT_FLAGS
|
||||
#define CEREAL_RAPIDJSON_WRITE_DEFAULT_FLAGS kWriteNoFlags
|
||||
#ifndef RAPIDJSON_WRITE_DEFAULT_FLAGS
|
||||
#define RAPIDJSON_WRITE_DEFAULT_FLAGS kWriteNoFlags
|
||||
#endif
|
||||
|
||||
//! Combination of writeFlags
|
||||
enum WriteFlag {
|
||||
kWriteNoFlags = 0, //!< No flags are set.
|
||||
kWriteValidateEncodingFlag = 1, //!< Validate encoding of JSON strings.
|
||||
kWriteNanAndInfFlag = 2, //!< Allow writing of Inf, -Inf and NaN.
|
||||
kWriteDefaultFlags = CEREAL_RAPIDJSON_WRITE_DEFAULT_FLAGS //!< Default write flags. Can be customized by defining CEREAL_RAPIDJSON_WRITE_DEFAULT_FLAGS
|
||||
kWriteNanAndInfFlag = 2, //!< Allow writing of Infinity, -Infinity and NaN.
|
||||
kWriteDefaultFlags = RAPIDJSON_WRITE_DEFAULT_FLAGS //!< Default write flags. Can be customized by defining RAPIDJSON_WRITE_DEFAULT_FLAGS
|
||||
};
|
||||
|
||||
//! JSON writer
|
||||
@ -103,6 +106,13 @@ public:
|
||||
Writer(StackAllocator* allocator = 0, size_t levelDepth = kDefaultLevelDepth) :
|
||||
os_(0), level_stack_(allocator, levelDepth * sizeof(Level)), maxDecimalPlaces_(kDefaultMaxDecimalPlaces), hasRoot_(false) {}
|
||||
|
||||
#if RAPIDJSON_HAS_CXX11_RVALUE_REFS
|
||||
Writer(Writer&& rhs) :
|
||||
os_(rhs.os_), level_stack_(std::move(rhs.level_stack_)), maxDecimalPlaces_(rhs.maxDecimalPlaces_), hasRoot_(rhs.hasRoot_) {
|
||||
rhs.os_ = 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
//! Reset the writer with a new stream.
|
||||
/*!
|
||||
This function reset the writer with a new stream and default settings,
|
||||
@ -184,18 +194,20 @@ public:
|
||||
bool Double(double d) { Prefix(kNumberType); return EndValue(WriteDouble(d)); }
|
||||
|
||||
bool RawNumber(const Ch* str, SizeType length, bool copy = false) {
|
||||
RAPIDJSON_ASSERT(str != 0);
|
||||
(void)copy;
|
||||
Prefix(kNumberType);
|
||||
return EndValue(WriteString(str, length));
|
||||
}
|
||||
|
||||
bool String(const Ch* str, SizeType length, bool copy = false) {
|
||||
RAPIDJSON_ASSERT(str != 0);
|
||||
(void)copy;
|
||||
Prefix(kStringType);
|
||||
return EndValue(WriteString(str, length));
|
||||
}
|
||||
|
||||
#if CEREAL_RAPIDJSON_HAS_STDSTRING
|
||||
#if RAPIDJSON_HAS_STDSTRING
|
||||
bool String(const std::basic_string<Ch>& str) {
|
||||
return String(str.data(), SizeType(str.size()));
|
||||
}
|
||||
@ -209,10 +221,18 @@ public:
|
||||
|
||||
bool Key(const Ch* str, SizeType length, bool copy = false) { return String(str, length, copy); }
|
||||
|
||||
#if RAPIDJSON_HAS_STDSTRING
|
||||
bool Key(const std::basic_string<Ch>& str)
|
||||
{
|
||||
return Key(str.data(), SizeType(str.size()));
|
||||
}
|
||||
#endif
|
||||
|
||||
bool EndObject(SizeType memberCount = 0) {
|
||||
(void)memberCount;
|
||||
CEREAL_RAPIDJSON_ASSERT(level_stack_.GetSize() >= sizeof(Level));
|
||||
CEREAL_RAPIDJSON_ASSERT(!level_stack_.template Top<Level>()->inArray);
|
||||
RAPIDJSON_ASSERT(level_stack_.GetSize() >= sizeof(Level)); // not inside an Object
|
||||
RAPIDJSON_ASSERT(!level_stack_.template Top<Level>()->inArray); // currently inside an Array, not Object
|
||||
RAPIDJSON_ASSERT(0 == level_stack_.template Top<Level>()->valueCount % 2); // Object has a Key without a Value
|
||||
level_stack_.template Pop<Level>(1);
|
||||
return EndValue(WriteEndObject());
|
||||
}
|
||||
@ -225,8 +245,8 @@ public:
|
||||
|
||||
bool EndArray(SizeType elementCount = 0) {
|
||||
(void)elementCount;
|
||||
CEREAL_RAPIDJSON_ASSERT(level_stack_.GetSize() >= sizeof(Level));
|
||||
CEREAL_RAPIDJSON_ASSERT(level_stack_.template Top<Level>()->inArray);
|
||||
RAPIDJSON_ASSERT(level_stack_.GetSize() >= sizeof(Level));
|
||||
RAPIDJSON_ASSERT(level_stack_.template Top<Level>()->inArray);
|
||||
level_stack_.template Pop<Level>(1);
|
||||
return EndValue(WriteEndArray());
|
||||
}
|
||||
@ -236,9 +256,9 @@ public:
|
||||
//@{
|
||||
|
||||
//! Simpler but slower overload.
|
||||
bool String(const Ch* str) { return String(str, internal::StrLen(str)); }
|
||||
bool Key(const Ch* str) { return Key(str, internal::StrLen(str)); }
|
||||
|
||||
bool String(const Ch* const& str) { return String(str, internal::StrLen(str)); }
|
||||
bool Key(const Ch* const& str) { return Key(str, internal::StrLen(str)); }
|
||||
|
||||
//@}
|
||||
|
||||
//! Write a raw JSON value.
|
||||
@ -249,7 +269,21 @@ public:
|
||||
\param length Length of the json.
|
||||
\param type Type of the root of json.
|
||||
*/
|
||||
bool RawValue(const Ch* json, size_t length, Type type) { Prefix(type); return EndValue(WriteRawValue(json, length)); }
|
||||
bool RawValue(const Ch* json, size_t length, Type type) {
|
||||
RAPIDJSON_ASSERT(json != 0);
|
||||
Prefix(type);
|
||||
return EndValue(WriteRawValue(json, length));
|
||||
}
|
||||
|
||||
//! Flush the output stream.
|
||||
/*!
|
||||
Allows the user to flush the output stream immediately.
|
||||
*/
|
||||
void Flush() {
|
||||
os_->Flush();
|
||||
}
|
||||
|
||||
static const size_t kDefaultLevelDepth = 32;
|
||||
|
||||
protected:
|
||||
//! Information for each nested level
|
||||
@ -259,8 +293,6 @@ protected:
|
||||
bool inArray; //!< true if in array, otherwise in object
|
||||
};
|
||||
|
||||
static const size_t kDefaultLevelDepth = 32;
|
||||
|
||||
bool WriteNull() {
|
||||
PutReserve(*os_, 4);
|
||||
PutUnsafe(*os_, 'n'); PutUnsafe(*os_, 'u'); PutUnsafe(*os_, 'l'); PutUnsafe(*os_, 'l'); return true;
|
||||
@ -283,7 +315,7 @@ protected:
|
||||
const char* end = internal::i32toa(i, buffer);
|
||||
PutReserve(*os_, static_cast<size_t>(end - buffer));
|
||||
for (const char* p = buffer; p != end; ++p)
|
||||
PutUnsafe(*os_, static_cast<typename TargetEncoding::Ch>(*p));
|
||||
PutUnsafe(*os_, static_cast<typename OutputStream::Ch>(*p));
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -292,7 +324,7 @@ protected:
|
||||
const char* end = internal::u32toa(u, buffer);
|
||||
PutReserve(*os_, static_cast<size_t>(end - buffer));
|
||||
for (const char* p = buffer; p != end; ++p)
|
||||
PutUnsafe(*os_, static_cast<typename TargetEncoding::Ch>(*p));
|
||||
PutUnsafe(*os_, static_cast<typename OutputStream::Ch>(*p));
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -301,7 +333,7 @@ protected:
|
||||
const char* end = internal::i64toa(i64, buffer);
|
||||
PutReserve(*os_, static_cast<size_t>(end - buffer));
|
||||
for (const char* p = buffer; p != end; ++p)
|
||||
PutUnsafe(*os_, static_cast<typename TargetEncoding::Ch>(*p));
|
||||
PutUnsafe(*os_, static_cast<typename OutputStream::Ch>(*p));
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -310,7 +342,7 @@ protected:
|
||||
char* end = internal::u64toa(u64, buffer);
|
||||
PutReserve(*os_, static_cast<size_t>(end - buffer));
|
||||
for (char* p = buffer; p != end; ++p)
|
||||
PutUnsafe(*os_, static_cast<typename TargetEncoding::Ch>(*p));
|
||||
PutUnsafe(*os_, static_cast<typename OutputStream::Ch>(*p));
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -338,12 +370,12 @@ protected:
|
||||
char* end = internal::dtoa(d, buffer, maxDecimalPlaces_);
|
||||
PutReserve(*os_, static_cast<size_t>(end - buffer));
|
||||
for (char* p = buffer; p != end; ++p)
|
||||
PutUnsafe(*os_, static_cast<typename TargetEncoding::Ch>(*p));
|
||||
PutUnsafe(*os_, static_cast<typename OutputStream::Ch>(*p));
|
||||
return true;
|
||||
}
|
||||
|
||||
bool WriteString(const Ch* str, SizeType length) {
|
||||
static const typename TargetEncoding::Ch hexDigits[16] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
|
||||
static const typename OutputStream::Ch hexDigits[16] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
|
||||
static const char escape[256] = {
|
||||
#define Z16 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
|
||||
//0 1 2 3 4 5 6 7 8 9 A B C D E F
|
||||
@ -368,7 +400,7 @@ protected:
|
||||
if (!TargetEncoding::supportUnicode && static_cast<unsigned>(c) >= 0x80) {
|
||||
// Unicode escaping
|
||||
unsigned codepoint;
|
||||
if (CEREAL_RAPIDJSON_UNLIKELY(!SourceEncoding::Decode(is, &codepoint)))
|
||||
if (RAPIDJSON_UNLIKELY(!SourceEncoding::Decode(is, &codepoint)))
|
||||
return false;
|
||||
PutUnsafe(*os_, '\\');
|
||||
PutUnsafe(*os_, 'u');
|
||||
@ -379,7 +411,7 @@ protected:
|
||||
PutUnsafe(*os_, hexDigits[(codepoint ) & 15]);
|
||||
}
|
||||
else {
|
||||
CEREAL_RAPIDJSON_ASSERT(codepoint >= 0x010000 && codepoint <= 0x10FFFF);
|
||||
RAPIDJSON_ASSERT(codepoint >= 0x010000 && codepoint <= 0x10FFFF);
|
||||
// Surrogate pair
|
||||
unsigned s = codepoint - 0x010000;
|
||||
unsigned lead = (s >> 10) + 0xD800;
|
||||
@ -396,10 +428,10 @@ protected:
|
||||
PutUnsafe(*os_, hexDigits[(trail ) & 15]);
|
||||
}
|
||||
}
|
||||
else if ((sizeof(Ch) == 1 || static_cast<unsigned>(c) < 256) && CEREAL_RAPIDJSON_UNLIKELY(escape[static_cast<unsigned char>(c)])) {
|
||||
else if ((sizeof(Ch) == 1 || static_cast<unsigned>(c) < 256) && RAPIDJSON_UNLIKELY(escape[static_cast<unsigned char>(c)])) {
|
||||
is.Take();
|
||||
PutUnsafe(*os_, '\\');
|
||||
PutUnsafe(*os_, static_cast<typename TargetEncoding::Ch>(escape[static_cast<unsigned char>(c)]));
|
||||
PutUnsafe(*os_, static_cast<typename OutputStream::Ch>(escape[static_cast<unsigned char>(c)]));
|
||||
if (escape[static_cast<unsigned char>(c)] == 'u') {
|
||||
PutUnsafe(*os_, '0');
|
||||
PutUnsafe(*os_, '0');
|
||||
@ -407,7 +439,7 @@ protected:
|
||||
PutUnsafe(*os_, hexDigits[static_cast<unsigned char>(c) & 0xF]);
|
||||
}
|
||||
}
|
||||
else if (CEREAL_RAPIDJSON_UNLIKELY(!(writeFlags & kWriteValidateEncodingFlag ?
|
||||
else if (RAPIDJSON_UNLIKELY(!(writeFlags & kWriteValidateEncodingFlag ?
|
||||
Transcoder<SourceEncoding, TargetEncoding>::Validate(is, *os_) :
|
||||
Transcoder<SourceEncoding, TargetEncoding>::TranscodeUnsafe(is, *os_))))
|
||||
return false;
|
||||
@ -417,7 +449,7 @@ protected:
|
||||
}
|
||||
|
||||
bool ScanWriteUnescapedString(GenericStringStream<SourceEncoding>& is, size_t length) {
|
||||
return CEREAL_RAPIDJSON_LIKELY(is.Tell() < length);
|
||||
return RAPIDJSON_LIKELY(is.Tell() < length);
|
||||
}
|
||||
|
||||
bool WriteStartObject() { os_->Put('{'); return true; }
|
||||
@ -427,16 +459,20 @@ protected:
|
||||
|
||||
bool WriteRawValue(const Ch* json, size_t length) {
|
||||
PutReserve(*os_, length);
|
||||
for (size_t i = 0; i < length; i++) {
|
||||
CEREAL_RAPIDJSON_ASSERT(json[i] != '\0');
|
||||
PutUnsafe(*os_, json[i]);
|
||||
GenericStringStream<SourceEncoding> is(json);
|
||||
while (RAPIDJSON_LIKELY(is.Tell() < length)) {
|
||||
RAPIDJSON_ASSERT(is.Peek() != '\0');
|
||||
if (RAPIDJSON_UNLIKELY(!(writeFlags & kWriteValidateEncodingFlag ?
|
||||
Transcoder<SourceEncoding, TargetEncoding>::Validate(is, *os_) :
|
||||
Transcoder<SourceEncoding, TargetEncoding>::TranscodeUnsafe(is, *os_))))
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void Prefix(Type type) {
|
||||
(void)type;
|
||||
if (CEREAL_RAPIDJSON_LIKELY(level_stack_.GetSize() != 0)) { // this value is not at root
|
||||
if (RAPIDJSON_LIKELY(level_stack_.GetSize() != 0)) { // this value is not at root
|
||||
Level* level = level_stack_.template Top<Level>();
|
||||
if (level->valueCount > 0) {
|
||||
if (level->inArray)
|
||||
@ -445,19 +481,19 @@ protected:
|
||||
os_->Put((level->valueCount % 2 == 0) ? ',' : ':');
|
||||
}
|
||||
if (!level->inArray && level->valueCount % 2 == 0)
|
||||
CEREAL_RAPIDJSON_ASSERT(type == kStringType); // if it's in object, then even number should be a name
|
||||
RAPIDJSON_ASSERT(type == kStringType); // if it's in object, then even number should be a name
|
||||
level->valueCount++;
|
||||
}
|
||||
else {
|
||||
CEREAL_RAPIDJSON_ASSERT(!hasRoot_); // Should only has one and only one root.
|
||||
RAPIDJSON_ASSERT(!hasRoot_); // Should only has one and only one root.
|
||||
hasRoot_ = true;
|
||||
}
|
||||
}
|
||||
|
||||
// Flush the value if it is the top level one.
|
||||
bool EndValue(bool ret) {
|
||||
if (CEREAL_RAPIDJSON_UNLIKELY(level_stack_.Empty())) // end of json text
|
||||
os_->Flush();
|
||||
if (RAPIDJSON_UNLIKELY(level_stack_.Empty())) // end of json text
|
||||
Flush();
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -509,7 +545,7 @@ inline bool Writer<StringBuffer>::WriteUint64(uint64_t u) {
|
||||
template<>
|
||||
inline bool Writer<StringBuffer>::WriteDouble(double d) {
|
||||
if (internal::Double(d).IsNanOrInf()) {
|
||||
// Note: This code path can only be reached if (CEREAL_RAPIDJSON_WRITE_DEFAULT_FLAGS & kWriteNanAndInfFlag).
|
||||
// Note: This code path can only be reached if (RAPIDJSON_WRITE_DEFAULT_FLAGS & kWriteNanAndInfFlag).
|
||||
if (!(kWriteDefaultFlags & kWriteNanAndInfFlag))
|
||||
return false;
|
||||
if (internal::Double(d).IsNan()) {
|
||||
@ -534,13 +570,13 @@ inline bool Writer<StringBuffer>::WriteDouble(double d) {
|
||||
return true;
|
||||
}
|
||||
|
||||
#if defined(CEREAL_RAPIDJSON_SSE2) || defined(CEREAL_RAPIDJSON_SSE42)
|
||||
#if defined(RAPIDJSON_SSE2) || defined(RAPIDJSON_SSE42)
|
||||
template<>
|
||||
inline bool Writer<StringBuffer>::ScanWriteUnescapedString(StringStream& is, size_t length) {
|
||||
if (length < 16)
|
||||
return CEREAL_RAPIDJSON_LIKELY(is.Tell() < length);
|
||||
return RAPIDJSON_LIKELY(is.Tell() < length);
|
||||
|
||||
if (!CEREAL_RAPIDJSON_LIKELY(is.Tell() < length))
|
||||
if (!RAPIDJSON_LIKELY(is.Tell() < length))
|
||||
return false;
|
||||
|
||||
const char* p = is.src_;
|
||||
@ -553,7 +589,7 @@ inline bool Writer<StringBuffer>::ScanWriteUnescapedString(StringStream& is, siz
|
||||
while (p != nextAligned)
|
||||
if (*p < 0x20 || *p == '\"' || *p == '\\') {
|
||||
is.src_ = p;
|
||||
return CEREAL_RAPIDJSON_LIKELY(is.Tell() < length);
|
||||
return RAPIDJSON_LIKELY(is.Tell() < length);
|
||||
}
|
||||
else
|
||||
os_->PutUnsafe(*p++);
|
||||
@ -561,7 +597,7 @@ inline bool Writer<StringBuffer>::ScanWriteUnescapedString(StringStream& is, siz
|
||||
// The rest of string using SIMD
|
||||
static const char dquote[16] = { '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"', '\"' };
|
||||
static const char bslash[16] = { '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\' };
|
||||
static const char space[16] = { 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19 };
|
||||
static const char space[16] = { 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F };
|
||||
const __m128i dq = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&dquote[0]));
|
||||
const __m128i bs = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&bslash[0]));
|
||||
const __m128i sp = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&space[0]));
|
||||
@ -570,10 +606,10 @@ inline bool Writer<StringBuffer>::ScanWriteUnescapedString(StringStream& is, siz
|
||||
const __m128i s = _mm_load_si128(reinterpret_cast<const __m128i *>(p));
|
||||
const __m128i t1 = _mm_cmpeq_epi8(s, dq);
|
||||
const __m128i t2 = _mm_cmpeq_epi8(s, bs);
|
||||
const __m128i t3 = _mm_cmpeq_epi8(_mm_max_epu8(s, sp), sp); // s < 0x20 <=> max(s, 0x19) == 0x19
|
||||
const __m128i t3 = _mm_cmpeq_epi8(_mm_max_epu8(s, sp), sp); // s < 0x20 <=> max(s, 0x1F) == 0x1F
|
||||
const __m128i x = _mm_or_si128(_mm_or_si128(t1, t2), t3);
|
||||
unsigned short r = static_cast<unsigned short>(_mm_movemask_epi8(x));
|
||||
if (CEREAL_RAPIDJSON_UNLIKELY(r != 0)) { // some of characters is escaped
|
||||
if (RAPIDJSON_UNLIKELY(r != 0)) { // some of characters is escaped
|
||||
SizeType len;
|
||||
#ifdef _MSC_VER // Find the index of first escaped
|
||||
unsigned long offset;
|
||||
@ -593,18 +629,82 @@ inline bool Writer<StringBuffer>::ScanWriteUnescapedString(StringStream& is, siz
|
||||
}
|
||||
|
||||
is.src_ = p;
|
||||
return CEREAL_RAPIDJSON_LIKELY(is.Tell() < length);
|
||||
return RAPIDJSON_LIKELY(is.Tell() < length);
|
||||
}
|
||||
#endif // defined(CEREAL_RAPIDJSON_SSE2) || defined(CEREAL_RAPIDJSON_SSE42)
|
||||
#elif defined(RAPIDJSON_NEON)
|
||||
template<>
|
||||
inline bool Writer<StringBuffer>::ScanWriteUnescapedString(StringStream& is, size_t length) {
|
||||
if (length < 16)
|
||||
return RAPIDJSON_LIKELY(is.Tell() < length);
|
||||
|
||||
CEREAL_RAPIDJSON_NAMESPACE_END
|
||||
if (!RAPIDJSON_LIKELY(is.Tell() < length))
|
||||
return false;
|
||||
|
||||
#ifdef _MSC_VER
|
||||
CEREAL_RAPIDJSON_DIAG_POP
|
||||
const char* p = is.src_;
|
||||
const char* end = is.head_ + length;
|
||||
const char* nextAligned = reinterpret_cast<const char*>((reinterpret_cast<size_t>(p) + 15) & static_cast<size_t>(~15));
|
||||
const char* endAligned = reinterpret_cast<const char*>(reinterpret_cast<size_t>(end) & static_cast<size_t>(~15));
|
||||
if (nextAligned > end)
|
||||
return true;
|
||||
|
||||
while (p != nextAligned)
|
||||
if (*p < 0x20 || *p == '\"' || *p == '\\') {
|
||||
is.src_ = p;
|
||||
return RAPIDJSON_LIKELY(is.Tell() < length);
|
||||
}
|
||||
else
|
||||
os_->PutUnsafe(*p++);
|
||||
|
||||
// The rest of string using SIMD
|
||||
const uint8x16_t s0 = vmovq_n_u8('"');
|
||||
const uint8x16_t s1 = vmovq_n_u8('\\');
|
||||
const uint8x16_t s2 = vmovq_n_u8('\b');
|
||||
const uint8x16_t s3 = vmovq_n_u8(32);
|
||||
|
||||
for (; p != endAligned; p += 16) {
|
||||
const uint8x16_t s = vld1q_u8(reinterpret_cast<const uint8_t *>(p));
|
||||
uint8x16_t x = vceqq_u8(s, s0);
|
||||
x = vorrq_u8(x, vceqq_u8(s, s1));
|
||||
x = vorrq_u8(x, vceqq_u8(s, s2));
|
||||
x = vorrq_u8(x, vcltq_u8(s, s3));
|
||||
|
||||
x = vrev64q_u8(x); // Rev in 64
|
||||
uint64_t low = vgetq_lane_u64(vreinterpretq_u64_u8(x), 0); // extract
|
||||
uint64_t high = vgetq_lane_u64(vreinterpretq_u64_u8(x), 1); // extract
|
||||
|
||||
SizeType len = 0;
|
||||
bool escaped = false;
|
||||
if (low == 0) {
|
||||
if (high != 0) {
|
||||
uint32_t lz = internal::clzll(high);
|
||||
len = 8 + (lz >> 3);
|
||||
escaped = true;
|
||||
}
|
||||
} else {
|
||||
uint32_t lz = internal::clzll(low);
|
||||
len = lz >> 3;
|
||||
escaped = true;
|
||||
}
|
||||
if (RAPIDJSON_UNLIKELY(escaped)) { // some of characters is escaped
|
||||
char* q = reinterpret_cast<char*>(os_->PushUnsafe(len));
|
||||
for (size_t i = 0; i < len; i++)
|
||||
q[i] = p[i];
|
||||
|
||||
p += len;
|
||||
break;
|
||||
}
|
||||
vst1q_u8(reinterpret_cast<uint8_t *>(os_->PushUnsafe(16)), s);
|
||||
}
|
||||
|
||||
is.src_ = p;
|
||||
return RAPIDJSON_LIKELY(is.Tell() < length);
|
||||
}
|
||||
#endif // RAPIDJSON_NEON
|
||||
|
||||
RAPIDJSON_NAMESPACE_END
|
||||
|
||||
#if defined(_MSC_VER) || defined(__clang__)
|
||||
RAPIDJSON_DIAG_POP
|
||||
#endif
|
||||
|
||||
#ifdef __clang__
|
||||
CEREAL_RAPIDJSON_DIAG_POP
|
||||
#endif
|
||||
|
||||
#endif // CEREAL_RAPIDJSON_CEREAL_RAPIDJSON_H_
|
||||
#endif // RAPIDJSON_RAPIDJSON_H_
|
||||
|
Loading…
x
Reference in New Issue
Block a user