mirror of
https://github.com/holub/mame
synced 2025-10-04 08:28:39 +03:00
update rapidjson library (nw)
This commit is contained in:
parent
dfad813239
commit
1f352c6af8
22
3rdparty/rapidjson/.gitattributes
vendored
Normal file
22
3rdparty/rapidjson/.gitattributes
vendored
Normal file
@ -0,0 +1,22 @@
|
||||
# Set the default behavior, in case people don't have core.autocrlf set.
|
||||
* text=auto
|
||||
|
||||
# Explicitly declare text files you want to always be normalized and converted
|
||||
# to native line endings on checkout.
|
||||
*.cpp text
|
||||
*.h text
|
||||
*.txt text
|
||||
*.md text
|
||||
*.cmake text
|
||||
*.svg text
|
||||
*.dot text
|
||||
*.yml text
|
||||
*.in text
|
||||
*.sh text
|
||||
*.autopkg text
|
||||
Dockerfile text
|
||||
|
||||
# Denote all files that are truly binary and should not be modified.
|
||||
*.png binary
|
||||
*.jpg binary
|
||||
*.json binary
|
181
3rdparty/rapidjson/.travis.yml
vendored
181
3rdparty/rapidjson/.travis.yml
vendored
@ -1,37 +1,164 @@
|
||||
language: cpp
|
||||
sudo: false
|
||||
cache:
|
||||
- ccache
|
||||
|
||||
compiler:
|
||||
- clang
|
||||
- gcc
|
||||
addons:
|
||||
apt:
|
||||
packages: &default_packages
|
||||
- cmake
|
||||
- valgrind
|
||||
|
||||
env:
|
||||
matrix:
|
||||
- CONF=debug ARCH=x86_64 CXX11=ON
|
||||
- CONF=release ARCH=x86_64 CXX11=ON
|
||||
- CONF=debug ARCH=x86 CXX11=ON
|
||||
- CONF=release ARCH=x86 CXX11=ON
|
||||
- CONF=debug ARCH=x86_64 CXX11=OFF
|
||||
- CONF=debug ARCH=x86 CXX11=OFF
|
||||
global:
|
||||
global:
|
||||
- USE_CCACHE=1
|
||||
- CCACHE_SLOPPINESS=pch_defines,time_macros
|
||||
- CCACHE_COMPRESS=1
|
||||
- CCACHE_MAXSIZE=100M
|
||||
- ARCH_FLAGS_x86='-m32' # #266: don't use SSE on 32-bit
|
||||
- ARCH_FLAGS_x86_64='-msse4.2' # use SSE4.2 on 64-bit
|
||||
- GITHUB_REPO='miloyip/rapidjson'
|
||||
- secure: "HrsaCb+N66EG1HR+LWH1u51SjaJyRwJEDzqJGYMB7LJ/bfqb9mWKF1fLvZGk46W5t7TVaXRDD5KHFx9DPWvKn4gRUVkwTHEy262ah5ORh8M6n/6VVVajeV/AYt2C0sswdkDBDO4Xq+xy5gdw3G8s1A4Inbm73pUh+6vx+7ltBbk="
|
||||
|
||||
before_install:
|
||||
- sudo apt-get update -qq
|
||||
- sudo apt-get install -qq cmake valgrind
|
||||
- sudo apt-get --no-install-recommends install doxygen # Don't install LaTeX stuffs
|
||||
- if [ "$ARCH" = "x86" ]; then sudo apt-get install -qq g++-multilib libc6-dbg:i386; fi
|
||||
- if [ "$CC" = "gcc" ] && [ "$CONF" = "debug" ]; then sudo pip install cpp-coveralls; export GCOV_FLAGS='--coverage'; fi
|
||||
|
||||
install: true
|
||||
matrix:
|
||||
include:
|
||||
# gcc
|
||||
- env: CONF=release ARCH=x86 CXX11=ON
|
||||
compiler: gcc
|
||||
addons:
|
||||
apt:
|
||||
packages:
|
||||
- *default_packages
|
||||
- g++-multilib
|
||||
- libc6-dbg:i386
|
||||
- env: CONF=release ARCH=x86_64 CXX11=ON
|
||||
compiler: gcc
|
||||
- env: CONF=debug ARCH=x86 CXX11=OFF
|
||||
compiler: gcc
|
||||
addons:
|
||||
apt:
|
||||
packages:
|
||||
- *default_packages
|
||||
- g++-multilib
|
||||
- libc6-dbg:i386
|
||||
- env: CONF=debug ARCH=x86_64 CXX11=OFF
|
||||
compiler: gcc
|
||||
# clang
|
||||
- env: CONF=debug ARCH=x86 CXX11=ON CCACHE_CPP2=yes
|
||||
compiler: clang
|
||||
addons:
|
||||
apt:
|
||||
sources:
|
||||
- llvm-toolchain-precise-3.7
|
||||
- ubuntu-toolchain-r-test
|
||||
packages:
|
||||
- *default_packages
|
||||
- g++-multilib
|
||||
- libc6-dbg:i386
|
||||
- clang-3.7
|
||||
- env: CONF=debug ARCH=x86_64 CXX11=ON CCACHE_CPP2=yes
|
||||
compiler: clang
|
||||
addons:
|
||||
apt:
|
||||
sources:
|
||||
- llvm-toolchain-precise-3.7
|
||||
- ubuntu-toolchain-r-test
|
||||
packages:
|
||||
- *default_packages
|
||||
- clang-3.7
|
||||
- env: CONF=debug ARCH=x86 CXX11=OFF CCACHE_CPP2=yes
|
||||
compiler: clang
|
||||
addons:
|
||||
apt:
|
||||
sources:
|
||||
- llvm-toolchain-precise-3.7
|
||||
- ubuntu-toolchain-r-test
|
||||
packages:
|
||||
- *default_packages
|
||||
- g++-multilib
|
||||
- libc6-dbg:i386
|
||||
- clang-3.7
|
||||
- env: CONF=debug ARCH=x86_64 CXX11=OFF CCACHE_CPP2=yes
|
||||
compiler: clang
|
||||
addons:
|
||||
apt:
|
||||
sources:
|
||||
- llvm-toolchain-precise-3.7
|
||||
- ubuntu-toolchain-r-test
|
||||
packages:
|
||||
- *default_packages
|
||||
- clang-3.7
|
||||
- env: CONF=release ARCH=x86 CXX11=ON CCACHE_CPP2=yes
|
||||
compiler: clang
|
||||
addons:
|
||||
apt:
|
||||
sources:
|
||||
- llvm-toolchain-precise-3.7
|
||||
- ubuntu-toolchain-r-test
|
||||
packages:
|
||||
- *default_packages
|
||||
- g++-multilib
|
||||
- libc6-dbg:i386
|
||||
- clang-3.7
|
||||
- env: CONF=release ARCH=x86_64 CXX11=ON CCACHE_CPP2=yes
|
||||
compiler: clang
|
||||
addons:
|
||||
apt:
|
||||
sources:
|
||||
- llvm-toolchain-precise-3.7
|
||||
- ubuntu-toolchain-r-test
|
||||
packages:
|
||||
- *default_packages
|
||||
- clang-3.7
|
||||
# coverage report
|
||||
- env: CONF=debug ARCH=x86 CXX11=ON GCOV_FLAGS='--coverage'
|
||||
compiler: gcc
|
||||
cache:
|
||||
- ccache
|
||||
- pip
|
||||
addons:
|
||||
apt:
|
||||
packages:
|
||||
- *default_packages
|
||||
- g++-multilib
|
||||
- libc6-dbg:i386
|
||||
after_success:
|
||||
- pip install --user cpp-coveralls
|
||||
- coveralls -r .. --gcov-options '\-lp' -e thirdparty -e example -e test -e build/CMakeFiles -e include/rapidjson/msinttypes -e include/rapidjson/internal/meta.h -e include/rapidjson/error/en.h
|
||||
- env: CONF=debug ARCH=x86_64 GCOV_FLAGS='--coverage'
|
||||
compiler: gcc
|
||||
cache:
|
||||
- ccache
|
||||
- pip
|
||||
addons:
|
||||
apt:
|
||||
packages:
|
||||
- *default_packages
|
||||
- g++-multilib
|
||||
- libc6-dbg:i386
|
||||
after_success:
|
||||
- pip install --user cpp-coveralls
|
||||
- coveralls -r .. --gcov-options '\-lp' -e thirdparty -e example -e test -e build/CMakeFiles -e include/rapidjson/msinttypes -e include/rapidjson/internal/meta.h -e include/rapidjson/error/en.h
|
||||
- script: # Documentation task
|
||||
- cd build
|
||||
- cmake .. -DRAPIDJSON_HAS_STDSTRING=ON -DCMAKE_VERBOSE_MAKEFILE=ON
|
||||
- make travis_doc
|
||||
cache: false
|
||||
addons:
|
||||
apt:
|
||||
packages:
|
||||
- doxygen
|
||||
|
||||
before_script:
|
||||
# hack to avoid Valgrind bug (https://bugs.kde.org/show_bug.cgi?id=326469),
|
||||
# exposed by merging PR#163 (using -march=native)
|
||||
- ccache -s
|
||||
# hack to avoid Valgrind bug (https://bugs.kde.org/show_bug.cgi?id=326469),
|
||||
# exposed by merging PR#163 (using -march=native)
|
||||
# TODO: Since this bug is already fixed. Remove this when valgrind can be upgraded.
|
||||
- sed -i "s/-march=native//" CMakeLists.txt
|
||||
- mkdir build
|
||||
|
||||
script:
|
||||
- if [ "$CXX" = "clang++" ]; then export CXX="clang++-3.7" CC="clang-3.7"; fi
|
||||
- >
|
||||
eval "ARCH_FLAGS=\${ARCH_FLAGS_${ARCH}}" ;
|
||||
(cd build && cmake
|
||||
@ -42,13 +169,7 @@ before_script:
|
||||
-DCMAKE_CXX_FLAGS="$ARCH_FLAGS $GCOV_FLAGS"
|
||||
-DCMAKE_EXE_LINKER_FLAGS=$GCOV_FLAGS
|
||||
..)
|
||||
|
||||
script:
|
||||
- cd build
|
||||
- make tests
|
||||
- make examples
|
||||
- ctest -V `[ "$CONF" = "release" ] || echo "-E perftest"`
|
||||
- make travis_doc
|
||||
|
||||
after_success:
|
||||
- coveralls -r .. --gcov-options '\-lp' -e thirdparty -e example -e test -e build/CMakeFiles -e include/rapidjson/msinttypes -e include/rapidjson/internal/meta.h -e include/rapidjson/error/en.h
|
||||
- make tests -j 2
|
||||
- make examples -j 2
|
||||
- ctest -j 2 -V `[ "$CONF" = "release" ] || echo "-E perftest"`
|
||||
|
9
3rdparty/rapidjson/CMakeLists.txt
vendored
9
3rdparty/rapidjson/CMakeLists.txt
vendored
@ -29,6 +29,15 @@ if(RAPIDJSON_HAS_STDSTRING)
|
||||
add_definitions(-DRAPIDJSON_HAS_STDSTRING)
|
||||
endif()
|
||||
|
||||
find_program(CCACHE_FOUND ccache)
|
||||
if(CCACHE_FOUND)
|
||||
set_property(GLOBAL PROPERTY RULE_LAUNCH_COMPILE ccache)
|
||||
set_property(GLOBAL PROPERTY RULE_LAUNCH_LINK ccache)
|
||||
if (CMAKE_CXX_COMPILER_ID MATCHES "Clang")
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Qunused-arguments -fcolor-diagnostics")
|
||||
endif()
|
||||
endif(CCACHE_FOUND)
|
||||
|
||||
if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU")
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -march=native -Wall -Wextra -Werror")
|
||||
if (RAPIDJSON_BUILD_CXX11)
|
||||
|
21
3rdparty/rapidjson/appveyor.yml
vendored
21
3rdparty/rapidjson/appveyor.yml
vendored
@ -1,3 +1,4 @@
|
||||
os: Visual Studio 2015 CTP
|
||||
version: 1.0.2.{build}
|
||||
|
||||
configuration:
|
||||
@ -6,13 +7,25 @@ configuration:
|
||||
|
||||
environment:
|
||||
matrix:
|
||||
- VS_VERSION: 11
|
||||
# - VS_VERSION: 9 2008
|
||||
# VS_PLATFORM: win32
|
||||
# - VS_VERSION: 9 2008
|
||||
# VS_PLATFORM: x64
|
||||
- VS_VERSION: 10 2010
|
||||
VS_PLATFORM: win32
|
||||
- VS_VERSION: 11
|
||||
- VS_VERSION: 10 2010
|
||||
VS_PLATFORM: x64
|
||||
- VS_VERSION: 12
|
||||
- VS_VERSION: 11 2012
|
||||
VS_PLATFORM: win32
|
||||
- VS_VERSION: 12
|
||||
- VS_VERSION: 11 2012
|
||||
VS_PLATFORM: x64
|
||||
- VS_VERSION: 12 2013
|
||||
VS_PLATFORM: win32
|
||||
- VS_VERSION: 12 2013
|
||||
VS_PLATFORM: x64
|
||||
- VS_VERSION: 14 2015
|
||||
VS_PLATFORM: win32
|
||||
- VS_VERSION: 14 2015
|
||||
VS_PLATFORM: x64
|
||||
|
||||
before_build:
|
||||
|
14
3rdparty/rapidjson/doc/schema.md
vendored
14
3rdparty/rapidjson/doc/schema.md
vendored
@ -2,17 +2,17 @@
|
||||
|
||||
## Status: experimental, shall be included in v1.1
|
||||
|
||||
JSON Schema is a draft standard for describing format of JSON. The schema itself is also a JSON. By validating a JSON with JSON Schema, your code can safely access the DOM without manually checking types, or whether a key exists, etc. It can also ensure that the serialized JSON conform to a specified schema.
|
||||
JSON Schema is a draft standard for describing the format of JSON data. The schema itself is also JSON data. By validating a JSON structure with JSON Schema, your code can safely access the DOM without manually checking types, or whether a key exists, etc. It can also ensure that the serialized JSON conform to a specified schema.
|
||||
|
||||
RapidJSON implemented a JSON Schema validator for [JSON Schema Draft v4](http://json-schema.org/documentation.html). If you do not familiar with JSON Schema, you may refer to [Understanding JSON Schema](http://spacetelescope.github.io/understanding-json-schema/).
|
||||
RapidJSON implemented a JSON Schema validator for [JSON Schema Draft v4](http://json-schema.org/documentation.html). If you are not familiar with JSON Schema, you may refer to [Understanding JSON Schema](http://spacetelescope.github.io/understanding-json-schema/).
|
||||
|
||||
[TOC]
|
||||
|
||||
## Basic Usage
|
||||
|
||||
First of all, you need to parse a JSON Schema into `Document`, and then compile the `Document` into `SchemaDocument`.
|
||||
First of all, you need to parse a JSON Schema into `Document`, and then compile the `Document` into a `SchemaDocument`.
|
||||
|
||||
Secondly, construct a `SchemaValidator` with the `SchedmaDocument`. It is similar to a `Writer` in the sense of handling SAX events. So, you can use `document.Accept(validator)` to validate a document, and then check the validity.
|
||||
Secondly, construct a `SchemaValidator` with the `SchemaDocument`. It is similar to a `Writer` in the sense of handling SAX events. So, you can use `document.Accept(validator)` to validate a document, and then check the validity.
|
||||
|
||||
~~~cpp
|
||||
#include "rapidjson/schema.h"
|
||||
@ -54,7 +54,7 @@ Some notes:
|
||||
|
||||
## Validation during parsing/serialization
|
||||
|
||||
Differ to most JSON Schema validator implementations, RapidJSON provides a SAX-based schema validator. Therefore, you can parse a JSON from a stream while validating it on the fly. If the validator encounters a JSON value that invalidates the supplied schema, the parsing will be terminated immediately. This design is especially useful for parsing large JSON files.
|
||||
Unlike most JSON Schema validator implementations, RapidJSON provides a SAX-based schema validator. Therefore, you can parse a JSON from a stream while validating it on the fly. If the validator encounters a JSON value that invalidates the supplied schema, the parsing will be terminated immediately. This design is especially useful for parsing large JSON files.
|
||||
|
||||
### DOM parsing
|
||||
|
||||
@ -111,7 +111,7 @@ if (!reader.Parse(stream, validator)) {
|
||||
}
|
||||
~~~
|
||||
|
||||
This is exactly the method used in [schemavalidator](example/schemavalidator/schemavalidator.cpp) example. The distinct advantage is low memory usage, no matter how big the JSON was (the memory usage depends on the complexity of the schema).
|
||||
This is exactly the method used in the [schemavalidator](example/schemavalidator/schemavalidator.cpp) example. The distinct advantage is low memory usage, no matter how big the JSON was (the memory usage depends on the complexity of the schema).
|
||||
|
||||
If you need to handle the SAX events further, then you need to use the template class `GenericSchemaValidator` to set the output handler of the validator:
|
||||
|
||||
@ -213,7 +213,7 @@ For C++11 compiler, it is also possible to use the `std::regex` by defining `RAP
|
||||
|
||||
## Performance
|
||||
|
||||
Most C++ JSON libraries have not yet supporting JSON Schema. So we tried to evaluate the performance of RapidJSON's JSON Schema validator according to [json-schema-benchmark](https://github.com/ebdrup/json-schema-benchmark), which tests 11 JavaScript libraries running on Node.js.
|
||||
Most C++ JSON libraries do not yet support JSON Schema. So we tried to evaluate the performance of RapidJSON's JSON Schema validator according to [json-schema-benchmark](https://github.com/ebdrup/json-schema-benchmark), which tests 11 JavaScript libraries running on Node.js.
|
||||
|
||||
That benchmark runs validations on [JSON Schema Test Suite](https://github.com/json-schema/JSON-Schema-Test-Suite), in which some test suites and tests are excluded. We made the same benchmarking procedure in [`schematest.cpp`](test/perftest/schematest.cpp).
|
||||
|
||||
|
8
3rdparty/rapidjson/docker/debian/Dockerfile
vendored
Normal file
8
3rdparty/rapidjson/docker/debian/Dockerfile
vendored
Normal file
@ -0,0 +1,8 @@
|
||||
# BUILD: docker build -t rapidjson-debian .
|
||||
# RUN: docker run -it -v "$PWD"/../..:/rapidjson rapidjson-debian
|
||||
|
||||
FROM debian:jessie
|
||||
|
||||
RUN apt-get update && apt-get install -y g++ cmake doxygen valgrind
|
||||
|
||||
ENTRYPOINT ["/bin/bash"]
|
10
3rdparty/rapidjson/example/CMakeLists.txt
vendored
10
3rdparty/rapidjson/example/CMakeLists.txt
vendored
@ -1,6 +1,3 @@
|
||||
# Copyright (c) 2011 Milo Yip (miloyip@gmail.com)
|
||||
# Copyright (c) 2013 Rafal Jeczalik (rjeczalik@gmail.com)
|
||||
# Distributed under the MIT License (see license.txt file)
|
||||
cmake_minimum_required(VERSION 2.8)
|
||||
|
||||
set(EXAMPLES
|
||||
@ -8,6 +5,7 @@ set(EXAMPLES
|
||||
condense
|
||||
jsonx
|
||||
messagereader
|
||||
parsebyparts
|
||||
pretty
|
||||
prettyauto
|
||||
schemavalidator
|
||||
@ -22,7 +20,7 @@ include_directories("../include/")
|
||||
add_definitions(-D__STDC_FORMAT_MACROS)
|
||||
|
||||
if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU")
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Werror -Wall -Wextra -Weffc++ -Wswitch-default")
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -pthread -Werror -Wall -Wextra -Weffc++ -Wswitch-default")
|
||||
elseif (CMAKE_CXX_COMPILER_ID MATCHES "Clang")
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Werror -Wall -Wextra -Weffc++ -Wswitch-default -Wfloat-equal -Wimplicit-fallthrough -Weverything")
|
||||
elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC")
|
||||
@ -33,4 +31,8 @@ foreach (example ${EXAMPLES})
|
||||
add_executable(${example} ${example}/${example}.cpp)
|
||||
endforeach()
|
||||
|
||||
if (CMAKE_CXX_COMPILER_ID MATCHES "Clang")
|
||||
target_link_libraries(parsebyparts pthread)
|
||||
endif()
|
||||
|
||||
add_custom_target(examples ALL DEPENDS ${EXAMPLES})
|
||||
|
@ -24,6 +24,7 @@ struct CapitalizeFilter {
|
||||
bool Int64(int64_t i) { return out_.Int64(i); }
|
||||
bool Uint64(uint64_t u) { return out_.Uint64(u); }
|
||||
bool Double(double d) { return out_.Double(d); }
|
||||
bool RawNumber(const char* str, SizeType length, bool copy) { return out_.RawNumber(str, length, copy); }
|
||||
bool String(const char* str, SizeType length, bool) {
|
||||
buffer_.clear();
|
||||
for (SizeType i = 0; i < length; i++)
|
||||
|
7
3rdparty/rapidjson/example/jsonx/jsonx.cpp
vendored
7
3rdparty/rapidjson/example/jsonx/jsonx.cpp
vendored
@ -57,6 +57,13 @@ public:
|
||||
return WriteNumberElement(buffer, sprintf(buffer, "%.17g", d));
|
||||
}
|
||||
|
||||
bool RawNumber(const char* str, SizeType length, bool) {
|
||||
return
|
||||
WriteStartElement("number") &&
|
||||
WriteEscapedText(str, length) &&
|
||||
WriteEndElement("number");
|
||||
}
|
||||
|
||||
bool String(const char* str, SizeType length, bool) {
|
||||
return
|
||||
WriteStartElement("string") &&
|
||||
|
172
3rdparty/rapidjson/example/parsebyparts/parsebyparts.cpp
vendored
Normal file
172
3rdparty/rapidjson/example/parsebyparts/parsebyparts.cpp
vendored
Normal file
@ -0,0 +1,172 @@
|
||||
// Example of parsing JSON to document by parts.
|
||||
|
||||
// Using C++11 threads
|
||||
#if __cplusplus >= 201103L || (defined(_MSC_VER) && _MSC_VER >= 1700)
|
||||
|
||||
#include "rapidjson/document.h"
|
||||
#include "rapidjson/error/en.h"
|
||||
#include "rapidjson/writer.h"
|
||||
#include "rapidjson/ostreamwrapper.h"
|
||||
#include <condition_variable>
|
||||
#include <iostream>
|
||||
#include <mutex>
|
||||
#include <thread>
|
||||
|
||||
using namespace rapidjson;
|
||||
|
||||
template<unsigned parseFlags = kParseDefaultFlags>
|
||||
class AsyncDocumentParser {
|
||||
public:
|
||||
AsyncDocumentParser(Document& d)
|
||||
: stream_(*this)
|
||||
, d_(d)
|
||||
, parseThread_(&AsyncDocumentParser::Parse, this)
|
||||
, mutex_()
|
||||
, notEmpty_()
|
||||
, finish_()
|
||||
, completed_()
|
||||
{}
|
||||
|
||||
~AsyncDocumentParser() {
|
||||
if (!parseThread_.joinable())
|
||||
return;
|
||||
|
||||
{
|
||||
std::unique_lock<std::mutex> lock(mutex_);
|
||||
|
||||
// Wait until the buffer is read up (or parsing is completed)
|
||||
while (!stream_.Empty() && !completed_)
|
||||
finish_.wait(lock);
|
||||
|
||||
// Automatically append '\0' as the terminator in the stream.
|
||||
static const char terminator[] = "";
|
||||
stream_.src_ = terminator;
|
||||
stream_.end_ = terminator + 1;
|
||||
notEmpty_.notify_one(); // unblock the AsyncStringStream
|
||||
}
|
||||
|
||||
parseThread_.join();
|
||||
}
|
||||
|
||||
void ParsePart(const char* buffer, size_t length) {
|
||||
std::unique_lock<std::mutex> lock(mutex_);
|
||||
|
||||
// Wait until the buffer is read up (or parsing is completed)
|
||||
while (!stream_.Empty() && !completed_)
|
||||
finish_.wait(lock);
|
||||
|
||||
// Stop further parsing if the parsing process is completed.
|
||||
if (completed_)
|
||||
return;
|
||||
|
||||
// Set the buffer to stream and unblock the AsyncStringStream
|
||||
stream_.src_ = buffer;
|
||||
stream_.end_ = buffer + length;
|
||||
notEmpty_.notify_one();
|
||||
}
|
||||
|
||||
private:
|
||||
void Parse() {
|
||||
d_.ParseStream<parseFlags>(stream_);
|
||||
|
||||
// The stream may not be fully read, notify finish anyway to unblock ParsePart()
|
||||
std::unique_lock<std::mutex> lock(mutex_);
|
||||
completed_ = true; // Parsing process is completed
|
||||
finish_.notify_one(); // Unblock ParsePart() or destructor if they are waiting.
|
||||
}
|
||||
|
||||
struct AsyncStringStream {
|
||||
typedef char Ch;
|
||||
|
||||
AsyncStringStream(AsyncDocumentParser& parser) : parser_(parser), src_(), end_(), count_() {}
|
||||
|
||||
char Peek() const {
|
||||
std::unique_lock<std::mutex> lock(parser_.mutex_);
|
||||
|
||||
// If nothing in stream, block to wait.
|
||||
while (Empty())
|
||||
parser_.notEmpty_.wait(lock);
|
||||
|
||||
return *src_;
|
||||
}
|
||||
|
||||
char Take() {
|
||||
std::unique_lock<std::mutex> lock(parser_.mutex_);
|
||||
|
||||
// If nothing in stream, block to wait.
|
||||
while (Empty())
|
||||
parser_.notEmpty_.wait(lock);
|
||||
|
||||
count_++;
|
||||
char c = *src_++;
|
||||
|
||||
// If all stream is read up, notify that the stream is finish.
|
||||
if (Empty())
|
||||
parser_.finish_.notify_one();
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
size_t Tell() const { return count_; }
|
||||
|
||||
// Not implemented
|
||||
char* PutBegin() { return 0; }
|
||||
void Put(char) {}
|
||||
void Flush() {}
|
||||
size_t PutEnd(char*) { return 0; }
|
||||
|
||||
bool Empty() const { return src_ == end_; }
|
||||
|
||||
AsyncDocumentParser& parser_;
|
||||
const char* src_; //!< Current read position.
|
||||
const char* end_; //!< End of buffer
|
||||
size_t count_; //!< Number of characters taken so far.
|
||||
};
|
||||
|
||||
AsyncStringStream stream_;
|
||||
Document& d_;
|
||||
std::thread parseThread_;
|
||||
std::mutex mutex_;
|
||||
std::condition_variable notEmpty_;
|
||||
std::condition_variable finish_;
|
||||
bool completed_;
|
||||
};
|
||||
|
||||
int main() {
|
||||
Document d;
|
||||
|
||||
{
|
||||
AsyncDocumentParser<> parser(d);
|
||||
|
||||
const char json1[] = " { \"hello\" : \"world\", \"t\" : tr";
|
||||
//const char json1[] = " { \"hello\" : \"world\", \"t\" : trX"; // Fot test parsing error
|
||||
const char json2[] = "ue, \"f\" : false, \"n\": null, \"i\":123, \"pi\": 3.14";
|
||||
const char json3[] = "16, \"a\":[1, 2, 3, 4] } ";
|
||||
|
||||
parser.ParsePart(json1, sizeof(json1) - 1);
|
||||
parser.ParsePart(json2, sizeof(json2) - 1);
|
||||
parser.ParsePart(json3, sizeof(json3) - 1);
|
||||
}
|
||||
|
||||
if (d.HasParseError()) {
|
||||
std::cout << "Error at offset " << d.GetErrorOffset() << ": " << GetParseError_En(d.GetParseError()) << std::endl;
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
// Stringify the JSON to cout
|
||||
OStreamWrapper os(std::cout);
|
||||
Writer<OStreamWrapper> writer(os);
|
||||
d.Accept(writer);
|
||||
std::cout << std::endl;
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
#else // Not supporting C++11
|
||||
|
||||
#include <iostream>
|
||||
int main() {
|
||||
std::cout << "This example requires C++11 compiler" << std::endl;
|
||||
}
|
||||
|
||||
#endif
|
@ -12,6 +12,10 @@ struct MyHandler {
|
||||
bool Int64(int64_t i) { cout << "Int64(" << i << ")" << endl; return true; }
|
||||
bool Uint64(uint64_t u) { cout << "Uint64(" << u << ")" << endl; return true; }
|
||||
bool Double(double d) { cout << "Double(" << d << ")" << endl; return true; }
|
||||
bool RawNumber(const char* str, SizeType length, bool copy) {
|
||||
cout << "Number(" << str << ", " << length << ", " << boolalpha << copy << ")" << endl;
|
||||
return true;
|
||||
}
|
||||
bool String(const char* str, SizeType length, bool copy) {
|
||||
cout << "String(" << str << ", " << length << ", " << boolalpha << copy << ")" << endl;
|
||||
return true;
|
||||
|
@ -9,26 +9,27 @@ int main() {
|
||||
StringBuffer s;
|
||||
Writer<StringBuffer> writer(s);
|
||||
|
||||
writer.StartObject();
|
||||
writer.String("hello");
|
||||
writer.String("world");
|
||||
writer.String("t");
|
||||
writer.StartObject(); // Between StartObject()/EndObject(),
|
||||
writer.Key("hello"); // output a key,
|
||||
writer.String("world"); // follow by a value.
|
||||
writer.Key("t");
|
||||
writer.Bool(true);
|
||||
writer.String("f");
|
||||
writer.Key("f");
|
||||
writer.Bool(false);
|
||||
writer.String("n");
|
||||
writer.Key("n");
|
||||
writer.Null();
|
||||
writer.String("i");
|
||||
writer.Key("i");
|
||||
writer.Uint(123);
|
||||
writer.String("pi");
|
||||
writer.Key("pi");
|
||||
writer.Double(3.1416);
|
||||
writer.String("a");
|
||||
writer.StartArray();
|
||||
writer.Key("a");
|
||||
writer.StartArray(); // Between StartArray()/EndArray(),
|
||||
for (unsigned i = 0; i < 4; i++)
|
||||
writer.Uint(i);
|
||||
writer.Uint(i); // all values are elements of the array.
|
||||
writer.EndArray();
|
||||
writer.EndObject();
|
||||
|
||||
// {"hello":"world","t":true,"f":false,"n":null,"i":123,"pi":3.1416,"a":[0,1,2,3]}
|
||||
cout << s.GetString() << endl;
|
||||
|
||||
return 0;
|
||||
|
661
3rdparty/rapidjson/include/rapidjson/document.h
vendored
661
3rdparty/rapidjson/include/rapidjson/document.h
vendored
File diff suppressed because it is too large
Load Diff
@ -16,6 +16,7 @@
|
||||
#define RAPIDJSON_ENCODEDSTREAM_H_
|
||||
|
||||
#include "stream.h"
|
||||
#include "memorystream.h"
|
||||
|
||||
#ifdef __GNUC__
|
||||
RAPIDJSON_DIAG_PUSH
|
||||
@ -62,6 +63,30 @@ private:
|
||||
Ch current_;
|
||||
};
|
||||
|
||||
//! Specialized for UTF8 MemoryStream.
|
||||
template <>
|
||||
class EncodedInputStream<UTF8<>, MemoryStream> {
|
||||
public:
|
||||
typedef UTF8<>::Ch Ch;
|
||||
|
||||
EncodedInputStream(MemoryStream& is) : is_(is) {
|
||||
if (static_cast<unsigned char>(is_.Peek()) == 0xEFu) is_.Take();
|
||||
if (static_cast<unsigned char>(is_.Peek()) == 0xBBu) is_.Take();
|
||||
if (static_cast<unsigned char>(is_.Peek()) == 0xBFu) is_.Take();
|
||||
}
|
||||
Ch Peek() const { return is_.Peek(); }
|
||||
Ch Take() { return is_.Take(); }
|
||||
size_t Tell() const { return is_.Tell(); }
|
||||
|
||||
// Not implemented
|
||||
void Put(Ch) {}
|
||||
void Flush() {}
|
||||
Ch* PutBegin() { return 0; }
|
||||
size_t PutEnd(Ch*) { return 0; }
|
||||
|
||||
MemoryStream& is_;
|
||||
};
|
||||
|
||||
//! Output byte stream wrapper with statically bound encoding.
|
||||
/*!
|
||||
\tparam Encoding The interpretation of encoding of the stream. Either UTF8, UTF16LE, UTF16BE, UTF32LE, UTF32BE.
|
||||
|
@ -29,6 +29,7 @@ namespace internal {
|
||||
#ifdef __GNUC__
|
||||
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) {
|
||||
@ -148,7 +149,7 @@ inline char* WriteExponent(int K, char* buffer) {
|
||||
inline char* Prettify(char* buffer, int length, int k, int maxDecimalPlaces) {
|
||||
const int kk = length + k; // 10^(kk-1) <= v < 10^kk
|
||||
|
||||
if (length <= kk && kk <= 21) {
|
||||
if (0 <= k && kk <= 21) {
|
||||
// 1234e7 -> 12340000000
|
||||
for (int i = length; i < kk; i++)
|
||||
buffer[i] = '0';
|
||||
@ -160,7 +161,7 @@ inline char* Prettify(char* buffer, int length, int k, int maxDecimalPlaces) {
|
||||
// 1234e-2 -> 12.34
|
||||
std::memmove(&buffer[kk + 1], &buffer[kk], static_cast<size_t>(length - kk));
|
||||
buffer[kk] = '.';
|
||||
if (length > kk + maxDecimalPlaces) {
|
||||
if (0 > k + maxDecimalPlaces) {
|
||||
// When maxDecimalPlaces = 2, 1.2345 -> 1.23, 1.102 -> 1.1
|
||||
// Remove extra trailing zeros (at least one) after truncation.
|
||||
for (int i = kk + maxDecimalPlaces; i > kk + 1; i--)
|
||||
@ -179,7 +180,7 @@ inline char* Prettify(char* buffer, int length, int k, int maxDecimalPlaces) {
|
||||
buffer[1] = '.';
|
||||
for (int i = 2; i < offset; i++)
|
||||
buffer[i] = '0';
|
||||
if (length + offset > maxDecimalPlaces) {
|
||||
if (length - kk > maxDecimalPlaces) {
|
||||
// When maxDecimalPlaces = 2, 0.123 -> 0.12, 0.102 -> 0.1
|
||||
// Remove extra trailing zeros (at least one) after truncation.
|
||||
for (int i = maxDecimalPlaces + 1; i > 2; i--)
|
||||
|
@ -20,6 +20,11 @@ RAPIDJSON_DIAG_PUSH
|
||||
RAPIDJSON_DIAG_OFF(padded)
|
||||
#endif
|
||||
|
||||
#ifdef _MSC_VER
|
||||
RAPIDJSON_DIAG_PUSH
|
||||
RAPIDJSON_DIAG_OFF(4351) // new behavior: elements of array 'array' will be default initialized
|
||||
#endif
|
||||
|
||||
RAPIDJSON_NAMESPACE_BEGIN
|
||||
|
||||
//! Wrapper of \c std::basic_istream into RapidJSON's Stream concept.
|
||||
@ -98,7 +103,7 @@ private:
|
||||
typedef BasicIStreamWrapper<std::istream> IStreamWrapper;
|
||||
typedef BasicIStreamWrapper<std::wistream> WIStreamWrapper;
|
||||
|
||||
#ifdef __clang__
|
||||
#if defined(__clang__) || defined(_MSC_VER)
|
||||
RAPIDJSON_DIAG_POP
|
||||
#endif
|
||||
|
||||
|
@ -42,8 +42,8 @@ struct MemoryStream {
|
||||
|
||||
MemoryStream(const Ch *src, size_t size) : src_(src), begin_(src), end_(src + size), size_(size) {}
|
||||
|
||||
Ch Peek() const { return (src_ == end_) ? '\0' : *src_; }
|
||||
Ch Take() { return (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() { RAPIDJSON_ASSERT(false); return 0; }
|
||||
|
@ -74,6 +74,12 @@ public:
|
||||
bool Uint64(uint64_t u64) { PrettyPrefix(kNumberType); return Base::WriteUint64(u64); }
|
||||
bool Double(double d) { PrettyPrefix(kNumberType); return Base::WriteDouble(d); }
|
||||
|
||||
bool RawNumber(const Ch* str, SizeType length, bool copy = false) {
|
||||
(void)copy;
|
||||
PrettyPrefix(kNumberType);
|
||||
return Base::WriteString(str, length);
|
||||
}
|
||||
|
||||
bool String(const Ch* str, SizeType length, bool copy = false) {
|
||||
(void)copy;
|
||||
PrettyPrefix(kStringType);
|
||||
|
50
3rdparty/rapidjson/include/rapidjson/rapidjson.h
vendored
50
3rdparty/rapidjson/include/rapidjson/rapidjson.h
vendored
@ -159,7 +159,7 @@
|
||||
*/
|
||||
#ifndef RAPIDJSON_NO_INT64DEFINE
|
||||
//!@cond RAPIDJSON_HIDDEN_FROM_DOXYGEN
|
||||
#ifdef _MSC_VER
|
||||
#if defined(_MSC_VER) && (_MSC_VER < 1800) // Visual Studio 2013
|
||||
#include "msinttypes/stdint.h"
|
||||
#include "msinttypes/inttypes.h"
|
||||
#else
|
||||
@ -265,7 +265,8 @@
|
||||
\param x pointer to align
|
||||
|
||||
Some machines require strict data alignment. Currently the default uses 4 bytes
|
||||
alignment. User can customize by defining the RAPIDJSON_ALIGN function macro.
|
||||
alignment on 32-bit platforms and 8 bytes alignment for 64-bit platforms.
|
||||
User can customize by defining the RAPIDJSON_ALIGN function macro.
|
||||
*/
|
||||
#ifndef RAPIDJSON_ALIGN
|
||||
#if RAPIDJSON_64BIT == 1
|
||||
@ -288,6 +289,36 @@
|
||||
#define RAPIDJSON_UINT64_C2(high32, low32) ((static_cast<uint64_t>(high32) << 32) | static_cast<uint64_t>(low32))
|
||||
#endif
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// RAPIDJSON_48BITPOINTER_OPTIMIZATION
|
||||
|
||||
//! Use only lower 48-bit address for some pointers.
|
||||
/*!
|
||||
\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 RAPIDJSON_48BITPOINTER_OPTIMIZATION
|
||||
#if defined(__amd64__) || defined(__amd64) || defined(__x86_64__) || defined(__x86_64) || defined(_M_X64) || defined(_M_AMD64)
|
||||
#define RAPIDJSON_48BITPOINTER_OPTIMIZATION 1
|
||||
#else
|
||||
#define RAPIDJSON_48BITPOINTER_OPTIMIZATION 0
|
||||
#endif
|
||||
#endif // RAPIDJSON_48BITPOINTER_OPTIMIZATION
|
||||
|
||||
#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 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 RAPIDJSON_SETPOINTER(type, p, x) (p = (x))
|
||||
#define RAPIDJSON_GETPOINTER(type, p) (p)
|
||||
#endif
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// RAPIDJSON_SSE2/RAPIDJSON_SSE42/RAPIDJSON_SIMD
|
||||
|
||||
@ -421,7 +452,7 @@ RAPIDJSON_NAMESPACE_END
|
||||
#if defined(__GNUC__) || defined(__clang__)
|
||||
#define RAPIDJSON_LIKELY(x) __builtin_expect(!!(x), 1)
|
||||
#else
|
||||
#define RAPIDJSON_LIKELY(x) x
|
||||
#define RAPIDJSON_LIKELY(x) (x)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
@ -434,7 +465,7 @@ RAPIDJSON_NAMESPACE_END
|
||||
#if defined(__GNUC__) || defined(__clang__)
|
||||
#define RAPIDJSON_UNLIKELY(x) __builtin_expect(!!(x), 0)
|
||||
#else
|
||||
#define RAPIDJSON_UNLIKELY(x) x
|
||||
#define RAPIDJSON_UNLIKELY(x) (x)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
@ -530,6 +561,17 @@ RAPIDJSON_NAMESPACE_END
|
||||
#define RAPIDJSON_HAS_CXX11_TYPETRAITS 0
|
||||
#endif
|
||||
|
||||
#ifndef RAPIDJSON_HAS_CXX11_RANGE_FOR
|
||||
#if defined(__clang__)
|
||||
#define RAPIDJSON_HAS_CXX11_RANGE_FOR __has_feature(cxx_range_for)
|
||||
#elif (defined(RAPIDJSON_GNUC) && (RAPIDJSON_GNUC >= RAPIDJSON_VERSION_CODE(4,3,0)) && defined(__GXX_EXPERIMENTAL_CXX0X__)) || \
|
||||
(defined(_MSC_VER) && _MSC_VER >= 1700)
|
||||
#define RAPIDJSON_HAS_CXX11_RANGE_FOR 1
|
||||
#else
|
||||
#define RAPIDJSON_HAS_CXX11_RANGE_FOR 0
|
||||
#endif
|
||||
#endif // RAPIDJSON_HAS_CXX11_RANGE_FOR
|
||||
|
||||
//!@endcond
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
126
3rdparty/rapidjson/include/rapidjson/reader.h
vendored
126
3rdparty/rapidjson/include/rapidjson/reader.h
vendored
@ -19,6 +19,7 @@
|
||||
|
||||
#include "allocators.h"
|
||||
#include "stream.h"
|
||||
#include "encodedstream.h"
|
||||
#include "internal/meta.h"
|
||||
#include "internal/stack.h"
|
||||
#include "internal/strtod.h"
|
||||
@ -147,6 +148,7 @@ enum ParseFlag {
|
||||
kParseStopWhenDoneFlag = 8, //!< After parsing a complete JSON root from stream, stop further processing the rest of stream. When this flag is used, parser will not generate kParseErrorDocumentRootNotSingular error.
|
||||
kParseFullPrecisionFlag = 16, //!< Parse number in full precision (but slower).
|
||||
kParseCommentsFlag = 32, //!< Allow one-line (//) and multi-line (/**/) comments.
|
||||
kParseNumbersAsStringsFlag = 64, //!< Parse all numbers (ints/doubles) as strings.
|
||||
kParseDefaultFlags = RAPIDJSON_PARSE_DEFAULT_FLAGS //!< Default parse flags. Can be customized by defining RAPIDJSON_PARSE_DEFAULT_FLAGS
|
||||
};
|
||||
|
||||
@ -168,6 +170,8 @@ concept Handler {
|
||||
bool Int64(int64_t i);
|
||||
bool Uint64(uint64_t i);
|
||||
bool Double(double d);
|
||||
/// enabled via kParseNumbersAsStringsFlag, string is not null-terminated (use length)
|
||||
bool RawNumber(const Ch* str, SizeType length, bool copy);
|
||||
bool String(const Ch* str, SizeType length, bool copy);
|
||||
bool StartObject();
|
||||
bool Key(const Ch* str, SizeType length, bool copy);
|
||||
@ -198,6 +202,8 @@ struct BaseReaderHandler {
|
||||
bool Int64(int64_t) { return static_cast<Override&>(*this).Default(); }
|
||||
bool Uint64(uint64_t) { return static_cast<Override&>(*this).Default(); }
|
||||
bool Double(double) { return static_cast<Override&>(*this).Default(); }
|
||||
/// enabled via kParseNumbersAsStringsFlag, string is not null-terminated (use length)
|
||||
bool RawNumber(const Ch* str, SizeType len, bool copy) { return static_cast<Override&>(*this).String(str, len, copy); }
|
||||
bool String(const Ch*, SizeType, bool) { return static_cast<Override&>(*this).Default(); }
|
||||
bool StartObject() { return static_cast<Override&>(*this).Default(); }
|
||||
bool Key(const Ch* str, SizeType len, bool copy) { return static_cast<Override&>(*this).String(str, len, copy); }
|
||||
@ -259,6 +265,12 @@ void SkipWhitespace(InputStream& is) {
|
||||
s.Take();
|
||||
}
|
||||
|
||||
inline const char* SkipWhitespace(const char* p, const char* end) {
|
||||
while (p != end && (*p == ' ' || *p == '\n' || *p == '\r' || *p == '\t'))
|
||||
++p;
|
||||
return p;
|
||||
}
|
||||
|
||||
#ifdef RAPIDJSON_SSE42
|
||||
//! Skip whitespace with SSE 4.2 pcmpistrm instruction, testing 16 8-byte characters at once.
|
||||
inline const char *SkipWhitespace_SIMD(const char* p) {
|
||||
@ -295,6 +307,34 @@ inline const char *SkipWhitespace_SIMD(const char* p) {
|
||||
}
|
||||
}
|
||||
|
||||
inline const char *SkipWhitespace_SIMD(const char* p, const char* end) {
|
||||
// Fast return for single non-whitespace
|
||||
if (p != end && (*p == ' ' || *p == '\n' || *p == '\r' || *p == '\t'))
|
||||
++p;
|
||||
else
|
||||
return p;
|
||||
|
||||
// The middle of string using SIMD
|
||||
static const char whitespace[16] = " \n\r\t";
|
||||
const __m128i w = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&whitespace[0]));
|
||||
|
||||
for (; p <= end - 16; p += 16) {
|
||||
const __m128i s = _mm_loadu_si128(reinterpret_cast<const __m128i *>(p));
|
||||
const int r = _mm_cvtsi128_si32(_mm_cmpistrm(w, s, _SIDD_UBYTE_OPS | _SIDD_CMP_EQUAL_ANY | _SIDD_BIT_MASK | _SIDD_NEGATIVE_POLARITY));
|
||||
if (r != 0) { // some of characters is non-whitespace
|
||||
#ifdef _MSC_VER // Find the index of first non-whitespace
|
||||
unsigned long offset;
|
||||
_BitScanForward(&offset, r);
|
||||
return p + offset;
|
||||
#else
|
||||
return p + __builtin_ffs(r) - 1;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
return SkipWhitespace(p, end);
|
||||
}
|
||||
|
||||
#elif defined(RAPIDJSON_SSE2)
|
||||
|
||||
//! Skip whitespace with SSE2 instructions, testing 16 8-byte characters at once.
|
||||
@ -342,6 +382,44 @@ inline const char *SkipWhitespace_SIMD(const char* p) {
|
||||
}
|
||||
}
|
||||
|
||||
inline const char *SkipWhitespace_SIMD(const char* p, const char* end) {
|
||||
// Fast return for single non-whitespace
|
||||
if (p != end && (*p == ' ' || *p == '\n' || *p == '\r' || *p == '\t'))
|
||||
++p;
|
||||
else
|
||||
return p;
|
||||
|
||||
// The rest of string
|
||||
#define C16(c) { c, c, c, c, c, c, c, c, c, c, c, c, c, c, c, c }
|
||||
static const char whitespaces[4][16] = { C16(' '), C16('\n'), C16('\r'), C16('\t') };
|
||||
#undef C16
|
||||
|
||||
const __m128i w0 = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&whitespaces[0][0]));
|
||||
const __m128i w1 = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&whitespaces[1][0]));
|
||||
const __m128i w2 = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&whitespaces[2][0]));
|
||||
const __m128i w3 = _mm_loadu_si128(reinterpret_cast<const __m128i *>(&whitespaces[3][0]));
|
||||
|
||||
for (; p <= end - 16; p += 16) {
|
||||
const __m128i s = _mm_loadu_si128(reinterpret_cast<const __m128i *>(p));
|
||||
__m128i x = _mm_cmpeq_epi8(s, w0);
|
||||
x = _mm_or_si128(x, _mm_cmpeq_epi8(s, w1));
|
||||
x = _mm_or_si128(x, _mm_cmpeq_epi8(s, w2));
|
||||
x = _mm_or_si128(x, _mm_cmpeq_epi8(s, w3));
|
||||
unsigned short r = static_cast<unsigned short>(~_mm_movemask_epi8(x));
|
||||
if (r != 0) { // some of characters may be non-whitespace
|
||||
#ifdef _MSC_VER // Find the index of first non-whitespace
|
||||
unsigned long offset;
|
||||
_BitScanForward(&offset, r);
|
||||
return p + offset;
|
||||
#else
|
||||
return p + __builtin_ffs(r) - 1;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
return SkipWhitespace(p, end);
|
||||
}
|
||||
|
||||
#endif // RAPIDJSON_SSE2
|
||||
|
||||
#ifdef RAPIDJSON_SIMD
|
||||
@ -354,6 +432,10 @@ template<> inline void SkipWhitespace(InsituStringStream& is) {
|
||||
template<> inline void SkipWhitespace(StringStream& is) {
|
||||
is.src_ = SkipWhitespace_SIMD(is.src_);
|
||||
}
|
||||
|
||||
template<> inline void SkipWhitespace(EncodedInputStream<UTF8<>, MemoryStream>& is) {
|
||||
is.is_.src_ = SkipWhitespace_SIMD(is.is_.src_, is.is_.end_);
|
||||
}
|
||||
#endif // RAPIDJSON_SIMD
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
@ -976,6 +1058,8 @@ private:
|
||||
RAPIDJSON_FORCEINLINE Ch Peek() const { return is.Peek(); }
|
||||
RAPIDJSON_FORCEINLINE Ch TakePush() { return is.Take(); }
|
||||
RAPIDJSON_FORCEINLINE Ch Take() { return is.Take(); }
|
||||
RAPIDJSON_FORCEINLINE void Push(char) {}
|
||||
|
||||
size_t Tell() { return is.Tell(); }
|
||||
size_t Length() { return 0; }
|
||||
const char* Pop() { return 0; }
|
||||
@ -998,6 +1082,10 @@ private:
|
||||
return Base::is.Take();
|
||||
}
|
||||
|
||||
RAPIDJSON_FORCEINLINE void Push(char c) {
|
||||
stackStream.Put(c);
|
||||
}
|
||||
|
||||
size_t Length() { return stackStream.Length(); }
|
||||
|
||||
const char* Pop() {
|
||||
@ -1012,7 +1100,11 @@ private:
|
||||
template<unsigned parseFlags, typename InputStream, typename Handler>
|
||||
void ParseNumber(InputStream& is, Handler& handler) {
|
||||
internal::StreamLocalCopy<InputStream> copy(is);
|
||||
NumberStream<InputStream, (parseFlags & kParseFullPrecisionFlag) != 0> s(*this, copy.s);
|
||||
NumberStream<InputStream,
|
||||
((parseFlags & kParseNumbersAsStringsFlag) != 0) ?
|
||||
((parseFlags & kParseInsituFlag) == 0) :
|
||||
((parseFlags & kParseFullPrecisionFlag) != 0)> s(*this, copy.s);
|
||||
|
||||
size_t startOffset = s.Tell();
|
||||
|
||||
// Parse minus
|
||||
@ -1099,6 +1191,9 @@ private:
|
||||
int expFrac = 0;
|
||||
size_t decimalPosition;
|
||||
if (Consume(s, '.')) {
|
||||
if (((parseFlags & kParseNumbersAsStringsFlag) != 0) && ((parseFlags & kParseInsituFlag) == 0)) {
|
||||
s.Push('.');
|
||||
}
|
||||
decimalPosition = s.Length();
|
||||
|
||||
if (RAPIDJSON_UNLIKELY(!(s.Peek() >= '0' && s.Peek() <= '9')))
|
||||
@ -1146,6 +1241,10 @@ private:
|
||||
// Parse exp = e [ minus / plus ] 1*DIGIT
|
||||
int exp = 0;
|
||||
if (Consume(s, 'e') || Consume(s, 'E')) {
|
||||
if ( ((parseFlags & kParseNumbersAsStringsFlag) != 0) && ((parseFlags & kParseInsituFlag) == 0) ) {
|
||||
s.Push( 'e' );
|
||||
}
|
||||
|
||||
if (!useDouble) {
|
||||
d = static_cast<double>(use64bit ? i64 : i);
|
||||
useDouble = true;
|
||||
@ -1186,6 +1285,30 @@ private:
|
||||
|
||||
// Finish parsing, call event according to the type of number.
|
||||
bool cont = true;
|
||||
|
||||
if (parseFlags & kParseNumbersAsStringsFlag) {
|
||||
if (parseFlags & kParseInsituFlag) {
|
||||
s.Pop(); // Pop stack no matter if it will be used or not.
|
||||
typename InputStream::Ch* head = is.PutBegin();
|
||||
const size_t length = s.Tell() - startOffset;
|
||||
RAPIDJSON_ASSERT(length <= 0xFFFFFFFF);
|
||||
// unable to insert the \0 character here, it will erase the comma after this number
|
||||
const typename TargetEncoding::Ch* const str = reinterpret_cast<typename TargetEncoding::Ch*>(head);
|
||||
cont = handler.RawNumber(str, SizeType(length), false);
|
||||
}
|
||||
else {
|
||||
StackStream<typename TargetEncoding::Ch> stackStream(stack_);
|
||||
SizeType numCharsToCopy = static_cast<SizeType>(s.Length());
|
||||
while (numCharsToCopy--) {
|
||||
Transcoder<SourceEncoding, TargetEncoding>::Transcode(is, stackStream);
|
||||
}
|
||||
stackStream.Put('\0');
|
||||
const typename TargetEncoding::Ch* str = stackStream.Pop();
|
||||
const SizeType length = static_cast<SizeType>(stackStream.Length()) - 1;
|
||||
cont = handler.RawNumber(str, SizeType(length), true);
|
||||
}
|
||||
}
|
||||
else {
|
||||
size_t length = s.Length();
|
||||
const char* decimal = s.Pop(); // Pop stack no matter if it will be used or not.
|
||||
|
||||
@ -1212,6 +1335,7 @@ private:
|
||||
cont = handler.Uint(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (RAPIDJSON_UNLIKELY(!cont))
|
||||
RAPIDJSON_PARSE_ERROR(kParseErrorTermination, startOffset);
|
||||
}
|
||||
|
30
3rdparty/rapidjson/include/rapidjson/schema.h
vendored
30
3rdparty/rapidjson/include/rapidjson/schema.h
vendored
@ -183,6 +183,11 @@ public:
|
||||
return WriteNumber(n);
|
||||
}
|
||||
|
||||
bool RawNumber(const Ch* str, SizeType len, bool) {
|
||||
WriteBuffer(kNumberType, str, len * sizeof(Ch));
|
||||
return true;
|
||||
}
|
||||
|
||||
bool String(const Ch* str, SizeType len, bool) {
|
||||
WriteBuffer(kStringType, str, len * sizeof(Ch));
|
||||
return true;
|
||||
@ -1322,7 +1327,7 @@ public:
|
||||
\param remoteProvider An optional remote schema document provider for resolving remote reference. Can be null.
|
||||
\param allocator An optional allocator instance for allocating memory. Can be null.
|
||||
*/
|
||||
GenericSchemaDocument(const ValueType& document, IRemoteSchemaDocumentProviderType* remoteProvider = 0, Allocator* allocator = 0) :
|
||||
GenericSchemaDocument(const ValueType& document, IRemoteSchemaDocumentProviderType* remoteProvider = 0, Allocator* allocator = 0) RAPIDJSON_NOEXCEPT :
|
||||
remoteProvider_(remoteProvider),
|
||||
allocator_(allocator),
|
||||
ownAllocator_(),
|
||||
@ -1357,6 +1362,22 @@ public:
|
||||
schemaRef_.ShrinkToFit(); // Deallocate all memory for ref
|
||||
}
|
||||
|
||||
#if RAPIDJSON_HAS_CXX11_RVALUE_REFS
|
||||
//! Move constructor in C++11
|
||||
GenericSchemaDocument(GenericSchemaDocument&& rhs) RAPIDJSON_NOEXCEPT :
|
||||
remoteProvider_(rhs.remoteProvider_),
|
||||
allocator_(rhs.allocator_),
|
||||
ownAllocator_(rhs.ownAllocator_),
|
||||
root_(rhs.root_),
|
||||
schemaMap_(std::move(rhs.schemaMap_)),
|
||||
schemaRef_(std::move(rhs.schemaRef_))
|
||||
{
|
||||
rhs.remoteProvider_ = 0;
|
||||
rhs.allocator_ = 0;
|
||||
rhs.ownAllocator_ = 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
//! Destructor
|
||||
~GenericSchemaDocument() {
|
||||
while (!schemaMap_.Empty())
|
||||
@ -1369,6 +1390,11 @@ public:
|
||||
const SchemaType& GetRoot() const { return *root_; }
|
||||
|
||||
private:
|
||||
//! Prohibit copying
|
||||
GenericSchemaDocument(const GenericSchemaDocument&);
|
||||
//! Prohibit assignment
|
||||
GenericSchemaDocument& operator=(const GenericSchemaDocument&);
|
||||
|
||||
struct SchemaRefEntry {
|
||||
SchemaRefEntry(const PointerType& s, const PointerType& t, const SchemaType** outSchema, Allocator *allocator) : source(s, allocator), target(t, allocator), schema(outSchema) {}
|
||||
PointerType source;
|
||||
@ -1658,6 +1684,8 @@ RAPIDJSON_MULTILINEMACRO_END
|
||||
bool Int64(int64_t i) { RAPIDJSON_SCHEMA_HANDLE_VALUE_(Int64, (CurrentContext(), i), (i)); }
|
||||
bool Uint64(uint64_t u) { RAPIDJSON_SCHEMA_HANDLE_VALUE_(Uint64, (CurrentContext(), u), (u)); }
|
||||
bool Double(double d) { RAPIDJSON_SCHEMA_HANDLE_VALUE_(Double, (CurrentContext(), d), (d)); }
|
||||
bool RawNumber(const Ch* str, SizeType length, bool copy)
|
||||
{ RAPIDJSON_SCHEMA_HANDLE_VALUE_(String, (CurrentContext(), str, length, copy), (str, length, copy)); }
|
||||
bool String(const Ch* str, SizeType length, bool copy)
|
||||
{ RAPIDJSON_SCHEMA_HANDLE_VALUE_(String, (CurrentContext(), str, length, copy), (str, length, copy)); }
|
||||
|
||||
|
16
3rdparty/rapidjson/include/rapidjson/writer.h
vendored
16
3rdparty/rapidjson/include/rapidjson/writer.h
vendored
@ -23,6 +23,16 @@
|
||||
#include "stringbuffer.h"
|
||||
#include <new> // placement new
|
||||
|
||||
#if defined(RAPIDJSON_SIMD) && defined(_MSC_VER)
|
||||
#include <intrin.h>
|
||||
#pragma intrinsic(_BitScanForward)
|
||||
#endif
|
||||
#ifdef RAPIDJSON_SSE42
|
||||
#include <nmmintrin.h>
|
||||
#elif defined(RAPIDJSON_SSE2)
|
||||
#include <emmintrin.h>
|
||||
#endif
|
||||
|
||||
#ifdef _MSC_VER
|
||||
RAPIDJSON_DIAG_PUSH
|
||||
RAPIDJSON_DIAG_OFF(4127) // conditional expression is constant
|
||||
@ -171,6 +181,12 @@ public:
|
||||
*/
|
||||
bool Double(double d) { Prefix(kNumberType); return WriteDouble(d); }
|
||||
|
||||
bool RawNumber(const Ch* str, SizeType length, bool copy = false) {
|
||||
(void)copy;
|
||||
Prefix(kNumberType);
|
||||
return WriteString(str, length);
|
||||
}
|
||||
|
||||
bool String(const Ch* str, SizeType length, bool copy = false) {
|
||||
(void)copy;
|
||||
Prefix(kStringType);
|
||||
|
@ -10,6 +10,15 @@ target_link_libraries(perftest ${TEST_LIBRARIES})
|
||||
|
||||
add_dependencies(tests perftest)
|
||||
|
||||
find_program(CCACHE_FOUND ccache)
|
||||
if(CCACHE_FOUND)
|
||||
set_property(GLOBAL PROPERTY RULE_LAUNCH_COMPILE ccache)
|
||||
set_property(GLOBAL PROPERTY RULE_LAUNCH_LINK ccache)
|
||||
if (CMAKE_CXX_COMPILER_ID MATCHES "Clang")
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Qunused-arguments -fcolor-diagnostics")
|
||||
endif()
|
||||
endif(CCACHE_FOUND)
|
||||
|
||||
IF(NOT (CMAKE_BUILD_TYPE STREQUAL "Debug"))
|
||||
add_test(NAME perftest
|
||||
COMMAND ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/perftest
|
||||
|
2
3rdparty/rapidjson/test/perftest/perftest.h
vendored
2
3rdparty/rapidjson/test/perftest/perftest.h
vendored
@ -30,6 +30,8 @@
|
||||
# define RAPIDJSON_SSE2
|
||||
#endif
|
||||
|
||||
#define RAPIDJSON_HAS_STDSTRING 1
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Google Test
|
||||
|
||||
|
@ -187,6 +187,25 @@ TEST_F(RapidJson, SIMD_SUFFIX(DocumentParse_MemoryPoolAllocator)) {
|
||||
}
|
||||
}
|
||||
|
||||
TEST_F(RapidJson, SIMD_SUFFIX(DocumentParseLength_MemoryPoolAllocator)) {
|
||||
for (size_t i = 0; i < kTrialCount; i++) {
|
||||
Document doc;
|
||||
doc.Parse(json_, length_);
|
||||
ASSERT_TRUE(doc.IsObject());
|
||||
}
|
||||
}
|
||||
|
||||
#if RAPIDJSON_HAS_STDSTRING
|
||||
TEST_F(RapidJson, SIMD_SUFFIX(DocumentParseStdString_MemoryPoolAllocator)) {
|
||||
const std::string s(json_, length_);
|
||||
for (size_t i = 0; i < kTrialCount; i++) {
|
||||
Document doc;
|
||||
doc.Parse(s);
|
||||
ASSERT_TRUE(doc.IsObject());
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
TEST_F(RapidJson, SIMD_SUFFIX(DocumentParseIterative_MemoryPoolAllocator)) {
|
||||
for (size_t i = 0; i < kTrialCount; i++) {
|
||||
Document doc;
|
||||
|
@ -25,6 +25,15 @@ set(UNITTEST_SOURCES
|
||||
valuetest.cpp
|
||||
writertest.cpp)
|
||||
|
||||
find_program(CCACHE_FOUND ccache)
|
||||
if(CCACHE_FOUND)
|
||||
set_property(GLOBAL PROPERTY RULE_LAUNCH_COMPILE ccache)
|
||||
set_property(GLOBAL PROPERTY RULE_LAUNCH_LINK ccache)
|
||||
if (CMAKE_CXX_COMPILER_ID MATCHES "Clang")
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Qunused-arguments -fcolor-diagnostics")
|
||||
endif()
|
||||
endif(CCACHE_FOUND)
|
||||
|
||||
if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU")
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Werror -Wall -Wextra -Weffc++ -Wswitch-default -Wfloat-equal")
|
||||
elseif (CMAKE_CXX_COMPILER_ID MATCHES "Clang")
|
||||
|
@ -34,6 +34,8 @@ void ParseCheck(DocumentType& doc) {
|
||||
typedef typename DocumentType::ValueType ValueType;
|
||||
|
||||
EXPECT_FALSE(doc.HasParseError());
|
||||
if (doc.HasParseError())
|
||||
printf("Error: %d at %zu\n", static_cast<int>(doc.GetParseError()), doc.GetErrorOffset());
|
||||
EXPECT_TRUE(static_cast<ParseResult>(doc));
|
||||
|
||||
EXPECT_TRUE(doc.IsObject());
|
||||
@ -93,6 +95,26 @@ void ParseTest() {
|
||||
doc.ParseInsitu(buffer);
|
||||
ParseCheck(doc);
|
||||
free(buffer);
|
||||
|
||||
// Parse(const Ch*, size_t)
|
||||
size_t length = strlen(json);
|
||||
buffer = reinterpret_cast<char*>(malloc(length * 2));
|
||||
memcpy(buffer, json, length);
|
||||
memset(buffer + length, 'X', length);
|
||||
#if RAPIDJSON_HAS_STDSTRING
|
||||
std::string s2(buffer, length); // backup buffer
|
||||
#endif
|
||||
doc.SetNull();
|
||||
doc.Parse(buffer, length);
|
||||
free(buffer);
|
||||
ParseCheck(doc);
|
||||
|
||||
#if RAPIDJSON_HAS_STDSTRING
|
||||
// Parse(std::string)
|
||||
doc.SetNull();
|
||||
doc.Parse(s2);
|
||||
ParseCheck(doc);
|
||||
#endif
|
||||
}
|
||||
|
||||
TEST(Document, Parse) {
|
||||
@ -140,6 +162,47 @@ static FILE* OpenEncodedFile(const char* filename) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
TEST(Document, Parse_Encoding) {
|
||||
const char* json = " { \"hello\" : \"world\", \"t\" : true , \"f\" : false, \"n\": null, \"i\":123, \"pi\": 3.1416, \"a\":[1, 2, 3, 4] } ";
|
||||
|
||||
typedef GenericDocument<UTF16<> > DocumentType;
|
||||
DocumentType doc;
|
||||
|
||||
// Parse<unsigned, SourceEncoding>(const SourceEncoding::Ch*)
|
||||
// doc.Parse<kParseDefaultFlags, UTF8<> >(json);
|
||||
// EXPECT_FALSE(doc.HasParseError());
|
||||
// EXPECT_EQ(0, StrCmp(doc[L"hello"].GetString(), L"world"));
|
||||
|
||||
// Parse<unsigned, SourceEncoding>(const SourceEncoding::Ch*, size_t)
|
||||
size_t length = strlen(json);
|
||||
char* buffer = reinterpret_cast<char*>(malloc(length * 2));
|
||||
memcpy(buffer, json, length);
|
||||
memset(buffer + length, 'X', length);
|
||||
#if RAPIDJSON_HAS_STDSTRING
|
||||
std::string s2(buffer, length); // backup buffer
|
||||
#endif
|
||||
doc.SetNull();
|
||||
doc.Parse<kParseDefaultFlags, UTF8<> >(buffer, length);
|
||||
free(buffer);
|
||||
EXPECT_FALSE(doc.HasParseError());
|
||||
if (doc.HasParseError())
|
||||
printf("Error: %d at %zu\n", static_cast<int>(doc.GetParseError()), doc.GetErrorOffset());
|
||||
EXPECT_EQ(0, StrCmp(doc[L"hello"].GetString(), L"world"));
|
||||
|
||||
#if RAPIDJSON_HAS_STDSTRING
|
||||
// Parse<unsigned, SourceEncoding>(std::string)
|
||||
doc.SetNull();
|
||||
|
||||
#if defined(_MSC_VER) && _MSC_VER < 1800
|
||||
doc.Parse<kParseDefaultFlags, UTF8<> >(s2.c_str()); // VS2010 or below cannot handle templated function overloading. Use const char* instead.
|
||||
#else
|
||||
doc.Parse<kParseDefaultFlags, UTF8<> >(s2);
|
||||
#endif
|
||||
EXPECT_FALSE(doc.HasParseError());
|
||||
EXPECT_EQ(0, StrCmp(doc[L"hello"].GetString(), L"world"));
|
||||
#endif
|
||||
}
|
||||
|
||||
TEST(Document, ParseStream_EncodedInputStream) {
|
||||
// UTF8 -> UTF16
|
||||
FILE* fp = OpenEncodedFile("utf8.json");
|
||||
|
@ -81,6 +81,12 @@ TEST(dtoa, maxDecimalPlaces) {
|
||||
TEST_DTOA(3, 2.225073858507201e-308, "0.0"); // Max subnormal positive double
|
||||
TEST_DTOA(3, 2.2250738585072014e-308, "0.0"); // Min normal positive double
|
||||
TEST_DTOA(3, 1.7976931348623157e308, "1.7976931348623157e308"); // Max double
|
||||
TEST_DTOA(5, -0.14000000000000001, "-0.14");
|
||||
TEST_DTOA(4, -0.14000000000000001, "-0.14");
|
||||
TEST_DTOA(3, -0.14000000000000001, "-0.14");
|
||||
TEST_DTOA(3, -0.10000000000000001, "-0.1");
|
||||
TEST_DTOA(2, -0.10000000000000001, "-0.1");
|
||||
TEST_DTOA(1, -0.10000000000000001, "-0.1");
|
||||
|
||||
#undef TEST_DTOA
|
||||
}
|
||||
|
72
3rdparty/rapidjson/test/unittest/readertest.cpp
vendored
72
3rdparty/rapidjson/test/unittest/readertest.cpp
vendored
@ -1170,6 +1170,8 @@ struct IterativeParsingReaderHandler {
|
||||
|
||||
bool Double(double) { RAPIDJSON_ASSERT(LogCount < LogCapacity); Logs[LogCount++] = LOG_DOUBLE; return true; }
|
||||
|
||||
bool RawNumber(const Ch*, SizeType, bool) { RAPIDJSON_ASSERT(LogCount < LogCapacity); Logs[LogCount++] = LOG_STRING; return true; }
|
||||
|
||||
bool String(const Ch*, SizeType, bool) { RAPIDJSON_ASSERT(LogCount < LogCapacity); Logs[LogCount++] = LOG_STRING; return true; }
|
||||
|
||||
bool StartObject() { RAPIDJSON_ASSERT(LogCount < LogCapacity); Logs[LogCount++] = LOG_STARTOBJECT; return true; }
|
||||
@ -1349,12 +1351,13 @@ struct TerminateHandler {
|
||||
bool Int64(int64_t) { return e != 4; }
|
||||
bool Uint64(uint64_t) { return e != 5; }
|
||||
bool Double(double) { return e != 6; }
|
||||
bool String(const char*, SizeType, bool) { return e != 7; }
|
||||
bool StartObject() { return e != 8; }
|
||||
bool Key(const char*, SizeType, bool) { return e != 9; }
|
||||
bool EndObject(SizeType) { return e != 10; }
|
||||
bool StartArray() { return e != 11; }
|
||||
bool EndArray(SizeType) { return e != 12; }
|
||||
bool RawNumber(const char*, SizeType, bool) { return e != 7; }
|
||||
bool String(const char*, SizeType, bool) { return e != 8; }
|
||||
bool StartObject() { return e != 9; }
|
||||
bool Key(const char*, SizeType, bool) { return e != 10; }
|
||||
bool EndObject(SizeType) { return e != 11; }
|
||||
bool StartArray() { return e != 12; }
|
||||
bool EndArray(SizeType) { return e != 13; }
|
||||
};
|
||||
|
||||
#define TEST_TERMINATION(e, json)\
|
||||
@ -1375,14 +1378,15 @@ TEST(Reader, ParseTerminationByHandler) {
|
||||
TEST_TERMINATION(4, "[-1234567890123456789");
|
||||
TEST_TERMINATION(5, "[1234567890123456789");
|
||||
TEST_TERMINATION(6, "[0.5]");
|
||||
TEST_TERMINATION(7, "[\"a\"");
|
||||
TEST_TERMINATION(8, "[{");
|
||||
TEST_TERMINATION(9, "[{\"a\"");
|
||||
TEST_TERMINATION(10, "[{}");
|
||||
TEST_TERMINATION(10, "[{\"a\":1}"); // non-empty object
|
||||
TEST_TERMINATION(11, "{\"a\":[");
|
||||
TEST_TERMINATION(12, "{\"a\":[]");
|
||||
TEST_TERMINATION(12, "{\"a\":[1]"); // non-empty array
|
||||
// RawNumber() is never called
|
||||
TEST_TERMINATION(8, "[\"a\"");
|
||||
TEST_TERMINATION(9, "[{");
|
||||
TEST_TERMINATION(10, "[{\"a\"");
|
||||
TEST_TERMINATION(11, "[{}");
|
||||
TEST_TERMINATION(11, "[{\"a\":1}"); // non-empty object
|
||||
TEST_TERMINATION(12, "{\"a\":[");
|
||||
TEST_TERMINATION(13, "{\"a\":[]");
|
||||
TEST_TERMINATION(13, "{\"a\":[1]"); // non-empty array
|
||||
}
|
||||
|
||||
TEST(Reader, ParseComments) {
|
||||
@ -1508,6 +1512,46 @@ TEST(Reader, UnrecognizedComment) {
|
||||
EXPECT_EQ(kParseErrorUnspecificSyntaxError, reader.GetParseErrorCode());
|
||||
}
|
||||
|
||||
struct NumbersAsStringsHandler {
|
||||
bool Null() { return true; }
|
||||
bool Bool(bool) { return true; }
|
||||
bool Int(int) { return true; }
|
||||
bool Uint(unsigned) { return true; }
|
||||
bool Int64(int64_t) { return true; }
|
||||
bool Uint64(uint64_t) { return true; }
|
||||
bool Double(double) { return true; }
|
||||
// 'str' is not null-terminated
|
||||
bool RawNumber(const char* str, SizeType length, bool) {
|
||||
EXPECT_TRUE(str != 0);
|
||||
EXPECT_TRUE(strncmp(str, "3.1416", length) == 0);
|
||||
return true;
|
||||
}
|
||||
bool String(const char*, SizeType, bool) { return true; }
|
||||
bool StartObject() { return true; }
|
||||
bool Key(const char*, SizeType, bool) { return true; }
|
||||
bool EndObject(SizeType) { return true; }
|
||||
bool StartArray() { return true; }
|
||||
bool EndArray(SizeType) { return true; }
|
||||
};
|
||||
|
||||
TEST(Reader, NumbersAsStrings) {
|
||||
{
|
||||
const char* json = "{ \"pi\": 3.1416 } ";
|
||||
StringStream s(json);
|
||||
NumbersAsStringsHandler h;
|
||||
Reader reader;
|
||||
EXPECT_TRUE(reader.Parse<kParseNumbersAsStringsFlag>(s, h));
|
||||
}
|
||||
{
|
||||
char* json = StrDup("{ \"pi\": 3.1416 } ");
|
||||
InsituStringStream s(json);
|
||||
NumbersAsStringsHandler h;
|
||||
Reader reader;
|
||||
EXPECT_TRUE(reader.Parse<kParseInsituFlag|kParseNumbersAsStringsFlag>(s, h));
|
||||
free(json);
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef __GNUC__
|
||||
RAPIDJSON_DIAG_POP
|
||||
#endif
|
||||
|
18
3rdparty/rapidjson/test/unittest/schematest.cpp
vendored
18
3rdparty/rapidjson/test/unittest/schematest.cpp
vendored
@ -1152,6 +1152,24 @@ TEST(SchemaValidatingWriter, Simple) {
|
||||
EXPECT_TRUE(validator.GetInvalidDocumentPointer() == SchemaDocument::PointerType(""));
|
||||
}
|
||||
|
||||
#if RAPIDJSON_HAS_CXX11_RVALUE_REFS
|
||||
|
||||
static SchemaDocument ReturnSchemaDocument() {
|
||||
Document sd;
|
||||
sd.Parse("{ \"type\": [\"number\", \"string\"] }");
|
||||
SchemaDocument s(sd);
|
||||
return s;
|
||||
}
|
||||
|
||||
TEST(Schema, Issue552) {
|
||||
SchemaDocument s = ReturnSchemaDocument();
|
||||
VALIDATE(s, "42", true);
|
||||
VALIDATE(s, "\"Life, the universe, and everything\"", true);
|
||||
INVALIDATE(s, "[\"Life\", \"the universe\", \"and everything\"]", "", "type", "");
|
||||
}
|
||||
|
||||
#endif // RAPIDJSON_HAS_CXX11_RVALUE_REFS
|
||||
|
||||
#ifdef __clang__
|
||||
RAPIDJSON_DIAG_POP
|
||||
#endif
|
||||
|
22
3rdparty/rapidjson/test/unittest/simdtest.cpp
vendored
22
3rdparty/rapidjson/test/unittest/simdtest.cpp
vendored
@ -73,6 +73,28 @@ TEST(SIMD, SIMD_SUFFIX(SkipWhitespace)) {
|
||||
TestSkipWhitespace<InsituStringStream>();
|
||||
}
|
||||
|
||||
TEST(SIMD, SIMD_SUFFIX(SkipWhitespace_EncodedMemoryStream)) {
|
||||
for (size_t step = 1; step < 32; step++) {
|
||||
char buffer[1024];
|
||||
for (size_t i = 0; i < 1024; i++)
|
||||
buffer[i] = " \t\r\n"[i % 4];
|
||||
for (size_t i = 0; i < 1024; i += step)
|
||||
buffer[i] = 'X';
|
||||
|
||||
MemoryStream ms(buffer, 1024);
|
||||
EncodedInputStream<UTF8<>, MemoryStream> s(ms);
|
||||
size_t i = 0;
|
||||
for (;;) {
|
||||
SkipWhitespace(s);
|
||||
if (s.Peek() == '\0')
|
||||
break;
|
||||
//EXPECT_EQ(i, s.Tell());
|
||||
EXPECT_EQ('X', s.Take());
|
||||
i += step;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct ScanCopyUnescapedStringHandler : BaseReaderHandler<UTF8<>, ScanCopyUnescapedStringHandler> {
|
||||
bool String(const char* str, size_t length, bool) {
|
||||
memcpy(buffer, str, length + 1);
|
||||
|
370
3rdparty/rapidjson/test/unittest/valuetest.cpp
vendored
370
3rdparty/rapidjson/test/unittest/valuetest.cpp
vendored
@ -23,6 +23,18 @@ RAPIDJSON_DIAG_OFF(c++98-compat)
|
||||
|
||||
using namespace rapidjson;
|
||||
|
||||
TEST(Value, Size) {
|
||||
if (sizeof(SizeType) == 4) {
|
||||
#if RAPIDJSON_48BITPOINTER_OPTIMIZATION
|
||||
EXPECT_EQ(16, sizeof(Value));
|
||||
#elif RAPIDJSON_64BIT
|
||||
EXPECT_EQ(24, sizeof(Value));
|
||||
#else
|
||||
EXPECT_EQ(16, sizeof(Value));
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
TEST(Value, DefaultConstructor) {
|
||||
Value x;
|
||||
EXPECT_EQ(kNullType, x.GetType());
|
||||
@ -335,6 +347,12 @@ TEST(Value, True) {
|
||||
Value z;
|
||||
z.SetBool(true);
|
||||
EXPECT_TRUE(z.IsTrue());
|
||||
|
||||
// Templated functions
|
||||
EXPECT_TRUE(z.Is<bool>());
|
||||
EXPECT_TRUE(z.Get<bool>());
|
||||
EXPECT_FALSE(z.Set<bool>(false).Get<bool>());
|
||||
EXPECT_TRUE(z.Set(true).Get<bool>());
|
||||
}
|
||||
|
||||
TEST(Value, False) {
|
||||
@ -414,6 +432,12 @@ TEST(Value, Int) {
|
||||
// operator=(int)
|
||||
z = 5678;
|
||||
EXPECT_EQ(5678, z.GetInt());
|
||||
|
||||
// Templated functions
|
||||
EXPECT_TRUE(z.Is<int>());
|
||||
EXPECT_EQ(5678, z.Get<int>());
|
||||
EXPECT_EQ(5679, z.Set(5679).Get<int>());
|
||||
EXPECT_EQ(5680, z.Set<int>(5680).Get<int>());
|
||||
}
|
||||
|
||||
TEST(Value, Uint) {
|
||||
@ -453,6 +477,12 @@ TEST(Value, Uint) {
|
||||
EXPECT_EQ(2147483648u, z.GetUint());
|
||||
EXPECT_FALSE(z.IsInt());
|
||||
EXPECT_TRUE(z.IsInt64()); // Issue 41: Incorrect parsing of unsigned int number types
|
||||
|
||||
// Templated functions
|
||||
EXPECT_TRUE(z.Is<unsigned>());
|
||||
EXPECT_EQ(2147483648u, z.Get<unsigned>());
|
||||
EXPECT_EQ(2147483649u, z.Set(2147483649u).Get<unsigned>());
|
||||
EXPECT_EQ(2147483650u, z.Set<unsigned>(2147483650u).Get<unsigned>());
|
||||
}
|
||||
|
||||
TEST(Value, Int64) {
|
||||
@ -505,8 +535,15 @@ TEST(Value, Int64) {
|
||||
EXPECT_FALSE(z.IsInt());
|
||||
EXPECT_NEAR(-2147483649.0, z.GetDouble(), 0.0);
|
||||
|
||||
z.SetInt64(static_cast<int64_t>(RAPIDJSON_UINT64_C2(0x80000000, 00000000)));
|
||||
int64_t i = static_cast<int64_t>(RAPIDJSON_UINT64_C2(0x80000000, 00000000));
|
||||
z.SetInt64(i);
|
||||
EXPECT_DOUBLE_EQ(-9223372036854775808.0, z.GetDouble());
|
||||
|
||||
// Templated functions
|
||||
EXPECT_TRUE(z.Is<int64_t>());
|
||||
EXPECT_EQ(i, z.Get<int64_t>());
|
||||
EXPECT_EQ(i - 1, z.Set(i - 1).Get<int64_t>());
|
||||
EXPECT_EQ(i - 2, z.Set<int64_t>(i - 2).Get<int64_t>());
|
||||
}
|
||||
|
||||
TEST(Value, Uint64) {
|
||||
@ -547,10 +584,17 @@ TEST(Value, Uint64) {
|
||||
EXPECT_FALSE(z.IsUint());
|
||||
EXPECT_TRUE(z.IsInt64());
|
||||
|
||||
z.SetUint64(RAPIDJSON_UINT64_C2(0x80000000, 0x00000000)); // 2^63 cannot cast as int64
|
||||
uint64_t u = RAPIDJSON_UINT64_C2(0x80000000, 0x00000000);
|
||||
z.SetUint64(u); // 2^63 cannot cast as int64
|
||||
EXPECT_FALSE(z.IsInt64());
|
||||
EXPECT_EQ(RAPIDJSON_UINT64_C2(0x80000000, 0x00000000), z.GetUint64()); // Issue 48
|
||||
EXPECT_EQ(u, z.GetUint64()); // Issue 48
|
||||
EXPECT_DOUBLE_EQ(9223372036854775808.0, z.GetDouble());
|
||||
|
||||
// Templated functions
|
||||
EXPECT_TRUE(z.Is<uint64_t>());
|
||||
EXPECT_EQ(u, z.Get<uint64_t>());
|
||||
EXPECT_EQ(u + 1, z.Set(u + 1).Get<uint64_t>());
|
||||
EXPECT_EQ(u + 2, z.Set<uint64_t>(u + 2).Get<uint64_t>());
|
||||
}
|
||||
|
||||
TEST(Value, Double) {
|
||||
@ -577,6 +621,12 @@ TEST(Value, Double) {
|
||||
|
||||
z = 56.78;
|
||||
EXPECT_NEAR(56.78, z.GetDouble(), 0.0);
|
||||
|
||||
// Templated functions
|
||||
EXPECT_TRUE(z.Is<double>());
|
||||
EXPECT_EQ(56.78, z.Get<double>());
|
||||
EXPECT_EQ(57.78, z.Set(57.78).Get<double>());
|
||||
EXPECT_EQ(58.78, z.Set<double>(58.78).Get<double>());
|
||||
}
|
||||
|
||||
TEST(Value, Float) {
|
||||
@ -602,18 +652,30 @@ TEST(Value, Float) {
|
||||
z.SetFloat(12.34f);
|
||||
EXPECT_NEAR(12.34f, z.GetFloat(), 0.0f);
|
||||
|
||||
// Issue 573
|
||||
z.SetInt(0);
|
||||
EXPECT_EQ(0.0f, z.GetFloat());
|
||||
|
||||
z = 56.78f;
|
||||
EXPECT_NEAR(56.78f, z.GetFloat(), 0.0f);
|
||||
|
||||
// Templated functions
|
||||
EXPECT_TRUE(z.Is<float>());
|
||||
EXPECT_EQ(56.78f, z.Get<float>());
|
||||
EXPECT_EQ(57.78f, z.Set(57.78f).Get<float>());
|
||||
EXPECT_EQ(58.78f, z.Set<float>(58.78f).Get<float>());
|
||||
}
|
||||
|
||||
TEST(Value, IsLosslessDouble) {
|
||||
EXPECT_TRUE(Value(12.34).IsLosslessDouble());
|
||||
EXPECT_TRUE(Value(-123).IsLosslessDouble());
|
||||
EXPECT_TRUE(Value(2147483648u).IsLosslessDouble());
|
||||
EXPECT_TRUE(Value(static_cast<int64_t>(-RAPIDJSON_UINT64_C2(0x40000000, 0x00000000))).IsLosslessDouble());
|
||||
EXPECT_TRUE(Value(-static_cast<int64_t>(RAPIDJSON_UINT64_C2(0x40000000, 0x00000000))).IsLosslessDouble());
|
||||
#if !(defined(_MSC_VER) && _MSC_VER < 1800) // VC2010 has problem
|
||||
EXPECT_TRUE(Value(RAPIDJSON_UINT64_C2(0xA0000000, 0x00000000)).IsLosslessDouble());
|
||||
#endif
|
||||
|
||||
EXPECT_FALSE(Value(static_cast<int64_t>(-RAPIDJSON_UINT64_C2(0x7FFFFFFF, 0xFFFFFFFF))).IsLosslessDouble());
|
||||
EXPECT_FALSE(Value(-static_cast<int64_t>(RAPIDJSON_UINT64_C2(0x7FFFFFFF, 0xFFFFFFFF))).IsLosslessDouble());
|
||||
EXPECT_FALSE(Value(RAPIDJSON_UINT64_C2(0xFFFFFFFF, 0xFFFFFFFF)).IsLosslessDouble());
|
||||
}
|
||||
|
||||
@ -724,6 +786,11 @@ TEST(Value, String) {
|
||||
EXPECT_STREQ("World", w.GetString());
|
||||
EXPECT_EQ(5u, w.GetStringLength());
|
||||
|
||||
// templated functions
|
||||
EXPECT_TRUE(z.Is<const char*>());
|
||||
EXPECT_STREQ(cstr, z.Get<const char*>());
|
||||
EXPECT_STREQ("Apple", z.Set<const char*>("Apple").Get<const char*>());
|
||||
|
||||
#if RAPIDJSON_HAS_STDSTRING
|
||||
{
|
||||
std::string str = "Hello World";
|
||||
@ -759,6 +826,14 @@ TEST(Value, String) {
|
||||
vs1 = StringRef(str);
|
||||
TestEqual(str, vs1);
|
||||
TestEqual(vs0, vs1);
|
||||
|
||||
// Templated function.
|
||||
EXPECT_TRUE(vs0.Is<std::string>());
|
||||
EXPECT_EQ(str, vs0.Get<std::string>());
|
||||
vs0.Set<std::string>(std::string("Apple"), allocator);
|
||||
EXPECT_EQ(std::string("Apple"), vs0.Get<std::string>());
|
||||
vs0.Set(std::string("Orange"), allocator);
|
||||
EXPECT_EQ(std::string("Orange"), vs0.Get<std::string>());
|
||||
}
|
||||
#endif // RAPIDJSON_HAS_STDSTRING
|
||||
}
|
||||
@ -769,25 +844,9 @@ TEST(Value, SetStringNullException) {
|
||||
EXPECT_THROW(v.SetString(0, 0), AssertException);
|
||||
}
|
||||
|
||||
TEST(Value, Array) {
|
||||
Value x(kArrayType);
|
||||
const Value& y = x;
|
||||
Value::AllocatorType allocator;
|
||||
|
||||
EXPECT_EQ(kArrayType, x.GetType());
|
||||
EXPECT_TRUE(x.IsArray());
|
||||
EXPECT_TRUE(x.Empty());
|
||||
EXPECT_EQ(0u, x.Size());
|
||||
EXPECT_TRUE(y.IsArray());
|
||||
EXPECT_TRUE(y.Empty());
|
||||
EXPECT_EQ(0u, y.Size());
|
||||
|
||||
EXPECT_FALSE(x.IsNull());
|
||||
EXPECT_FALSE(x.IsBool());
|
||||
EXPECT_FALSE(x.IsFalse());
|
||||
EXPECT_FALSE(x.IsTrue());
|
||||
EXPECT_FALSE(x.IsString());
|
||||
EXPECT_FALSE(x.IsObject());
|
||||
template <typename T, typename Allocator>
|
||||
static void TestArray(T& x, Allocator& allocator) {
|
||||
const T& y = x;
|
||||
|
||||
// PushBack()
|
||||
Value v;
|
||||
@ -834,7 +893,7 @@ TEST(Value, Array) {
|
||||
#endif
|
||||
|
||||
// iterator
|
||||
Value::ValueIterator itr = x.Begin();
|
||||
typename T::ValueIterator itr = x.Begin();
|
||||
EXPECT_TRUE(itr != x.End());
|
||||
EXPECT_TRUE(itr->IsNull());
|
||||
++itr;
|
||||
@ -853,7 +912,7 @@ TEST(Value, Array) {
|
||||
EXPECT_STREQ("foo", itr->GetString());
|
||||
|
||||
// const iterator
|
||||
Value::ConstValueIterator citr = y.Begin();
|
||||
typename T::ConstValueIterator citr = y.Begin();
|
||||
EXPECT_TRUE(citr != y.End());
|
||||
EXPECT_TRUE(citr->IsNull());
|
||||
++citr;
|
||||
@ -939,6 +998,29 @@ TEST(Value, Array) {
|
||||
EXPECT_EQ(i + removeCount, x[static_cast<SizeType>(i)][0].GetUint());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
TEST(Value, Array) {
|
||||
Value x(kArrayType);
|
||||
const Value& y = x;
|
||||
Value::AllocatorType allocator;
|
||||
|
||||
EXPECT_EQ(kArrayType, x.GetType());
|
||||
EXPECT_TRUE(x.IsArray());
|
||||
EXPECT_TRUE(x.Empty());
|
||||
EXPECT_EQ(0u, x.Size());
|
||||
EXPECT_TRUE(y.IsArray());
|
||||
EXPECT_TRUE(y.Empty());
|
||||
EXPECT_EQ(0u, y.Size());
|
||||
|
||||
EXPECT_FALSE(x.IsNull());
|
||||
EXPECT_FALSE(x.IsBool());
|
||||
EXPECT_FALSE(x.IsFalse());
|
||||
EXPECT_FALSE(x.IsTrue());
|
||||
EXPECT_FALSE(x.IsString());
|
||||
EXPECT_FALSE(x.IsObject());
|
||||
|
||||
TestArray(x, allocator);
|
||||
|
||||
// Working in gcc without C++11, but VS2013 cannot compile. To be diagnosed.
|
||||
// http://en.wikipedia.org/wiki/Erase-remove_idiom
|
||||
@ -962,19 +1044,96 @@ TEST(Value, Array) {
|
||||
EXPECT_TRUE(z.Empty());
|
||||
}
|
||||
|
||||
TEST(Value, Object) {
|
||||
Value x(kObjectType);
|
||||
const Value& y = x; // const version
|
||||
TEST(Value, ArrayHelper) {
|
||||
Value::AllocatorType allocator;
|
||||
{
|
||||
Value x(kArrayType);
|
||||
Value::Array a = x.GetArray();
|
||||
TestArray(a, allocator);
|
||||
}
|
||||
|
||||
EXPECT_EQ(kObjectType, x.GetType());
|
||||
EXPECT_TRUE(x.IsObject());
|
||||
EXPECT_TRUE(x.ObjectEmpty());
|
||||
EXPECT_EQ(0u, x.MemberCount());
|
||||
EXPECT_EQ(kObjectType, y.GetType());
|
||||
EXPECT_TRUE(y.IsObject());
|
||||
EXPECT_TRUE(y.ObjectEmpty());
|
||||
EXPECT_EQ(0u, y.MemberCount());
|
||||
{
|
||||
Value x(kArrayType);
|
||||
Value::Array a = x.GetArray();
|
||||
a.PushBack(1, allocator);
|
||||
|
||||
Value::Array a2(a); // copy constructor
|
||||
EXPECT_EQ(1, a2.Size());
|
||||
|
||||
Value::Array a3 = a;
|
||||
EXPECT_EQ(1, a3.Size());
|
||||
|
||||
Value::ConstArray y = static_cast<const Value&>(x).GetArray();
|
||||
(void)y;
|
||||
// y.PushBack(1, allocator); // should not compile
|
||||
|
||||
// Templated functions
|
||||
x.Clear();
|
||||
EXPECT_TRUE(x.Is<Value::Array>());
|
||||
EXPECT_TRUE(x.Is<Value::ConstArray>());
|
||||
a.PushBack(1, allocator);
|
||||
EXPECT_EQ(1, x.Get<Value::Array>()[0].GetInt());
|
||||
EXPECT_EQ(1, x.Get<Value::ConstArray>()[0].GetInt());
|
||||
|
||||
Value x2;
|
||||
x2.Set<Value::Array>(a);
|
||||
EXPECT_TRUE(x.IsArray()); // IsArray() is invariant after moving.
|
||||
EXPECT_EQ(1, x2.Get<Value::Array>()[0].GetInt());
|
||||
}
|
||||
|
||||
{
|
||||
Value y(kArrayType);
|
||||
y.PushBack(123, allocator);
|
||||
|
||||
Value x(y.GetArray()); // Construct value form array.
|
||||
EXPECT_TRUE(x.IsArray());
|
||||
EXPECT_EQ(123, x[0].GetInt());
|
||||
EXPECT_TRUE(y.IsArray()); // Invariant
|
||||
EXPECT_TRUE(y.Empty());
|
||||
}
|
||||
|
||||
{
|
||||
Value x(kArrayType);
|
||||
Value y(kArrayType);
|
||||
y.PushBack(123, allocator);
|
||||
x.PushBack(y.GetArray(), allocator); // Implicit constructor to convert Array to GenericValue
|
||||
|
||||
EXPECT_EQ(1, x.Size());
|
||||
EXPECT_EQ(123, x[0][0].GetInt());
|
||||
EXPECT_TRUE(y.IsArray());
|
||||
EXPECT_TRUE(y.Empty());
|
||||
}
|
||||
}
|
||||
|
||||
#if RAPIDJSON_HAS_CXX11_RANGE_FOR
|
||||
TEST(Value, ArrayHelperRangeFor) {
|
||||
Value::AllocatorType allocator;
|
||||
Value x(kArrayType);
|
||||
|
||||
for (int i = 0; i < 10; i++)
|
||||
x.PushBack(i, allocator);
|
||||
|
||||
{
|
||||
int i = 0;
|
||||
for (auto& v : x.GetArray())
|
||||
EXPECT_EQ(i++, v.GetInt());
|
||||
EXPECT_EQ(i, 10);
|
||||
}
|
||||
{
|
||||
int i = 0;
|
||||
for (const auto& v : const_cast<const Value&>(x).GetArray())
|
||||
EXPECT_EQ(i++, v.GetInt());
|
||||
EXPECT_EQ(i, 10);
|
||||
}
|
||||
|
||||
// Array a = x.GetArray();
|
||||
// Array ca = const_cast<const Value&>(x).GetArray();
|
||||
}
|
||||
#endif
|
||||
|
||||
template <typename T, typename Allocator>
|
||||
static void TestObject(T& x, Allocator& allocator) {
|
||||
const T& y = x; // const version
|
||||
|
||||
// AddMember()
|
||||
x.AddMember("A", "Apple", allocator);
|
||||
@ -1215,7 +1374,7 @@ TEST(Value, Object) {
|
||||
const unsigned n = 10;
|
||||
for (unsigned first = 0; first < n; first++) {
|
||||
for (unsigned last = first; last <= n; last++) {
|
||||
Value(kObjectType).Swap(x);
|
||||
x.RemoveAllMembers();
|
||||
for (unsigned i = 0; i < n; i++)
|
||||
x.AddMember(keys[i], Value(kArrayType).PushBack(i, allocator), allocator);
|
||||
|
||||
@ -1238,6 +1397,23 @@ TEST(Value, Object) {
|
||||
x.RemoveAllMembers();
|
||||
EXPECT_TRUE(x.ObjectEmpty());
|
||||
EXPECT_EQ(0u, x.MemberCount());
|
||||
}
|
||||
|
||||
TEST(Value, Object) {
|
||||
Value x(kObjectType);
|
||||
const Value& y = x; // const version
|
||||
Value::AllocatorType allocator;
|
||||
|
||||
EXPECT_EQ(kObjectType, x.GetType());
|
||||
EXPECT_TRUE(x.IsObject());
|
||||
EXPECT_TRUE(x.ObjectEmpty());
|
||||
EXPECT_EQ(0u, x.MemberCount());
|
||||
EXPECT_EQ(kObjectType, y.GetType());
|
||||
EXPECT_TRUE(y.IsObject());
|
||||
EXPECT_TRUE(y.ObjectEmpty());
|
||||
EXPECT_EQ(0u, y.MemberCount());
|
||||
|
||||
TestObject(x, allocator);
|
||||
|
||||
// SetObject()
|
||||
Value z;
|
||||
@ -1245,6 +1421,100 @@ TEST(Value, Object) {
|
||||
EXPECT_TRUE(z.IsObject());
|
||||
}
|
||||
|
||||
TEST(Value, ObjectHelper) {
|
||||
Value::AllocatorType allocator;
|
||||
{
|
||||
Value x(kObjectType);
|
||||
Value::Object o = x.GetObject();
|
||||
TestObject(o, allocator);
|
||||
}
|
||||
|
||||
{
|
||||
Value x(kObjectType);
|
||||
Value::Object o = x.GetObject();
|
||||
o.AddMember("1", 1, allocator);
|
||||
|
||||
Value::Object o2(o); // copy constructor
|
||||
EXPECT_EQ(1, o2.MemberCount());
|
||||
|
||||
Value::Object o3 = o;
|
||||
EXPECT_EQ(1, o3.MemberCount());
|
||||
|
||||
Value::ConstObject y = static_cast<const Value&>(x).GetObject();
|
||||
(void)y;
|
||||
// y.AddMember("1", 1, allocator); // should not compile
|
||||
|
||||
// Templated functions
|
||||
x.RemoveAllMembers();
|
||||
EXPECT_TRUE(x.Is<Value::Object>());
|
||||
EXPECT_TRUE(x.Is<Value::ConstObject>());
|
||||
o.AddMember("1", 1, allocator);
|
||||
EXPECT_EQ(1, x.Get<Value::Object>()["1"].GetInt());
|
||||
EXPECT_EQ(1, x.Get<Value::ConstObject>()["1"].GetInt());
|
||||
|
||||
Value x2;
|
||||
x2.Set<Value::Object>(o);
|
||||
EXPECT_TRUE(x.IsObject()); // IsObject() is invariant after moving
|
||||
EXPECT_EQ(1, x2.Get<Value::Object>()["1"].GetInt());
|
||||
}
|
||||
|
||||
{
|
||||
Value x(kObjectType);
|
||||
x.AddMember("a", "apple", allocator);
|
||||
Value y(x.GetObject());
|
||||
EXPECT_STREQ("apple", y["a"].GetString());
|
||||
EXPECT_TRUE(x.IsObject()); // Invariant
|
||||
}
|
||||
|
||||
{
|
||||
Value x(kObjectType);
|
||||
x.AddMember("a", "apple", allocator);
|
||||
Value y(kObjectType);
|
||||
y.AddMember("fruits", x.GetObject(), allocator);
|
||||
EXPECT_STREQ("apple", y["fruits"]["a"].GetString());
|
||||
EXPECT_TRUE(x.IsObject()); // Invariant
|
||||
}
|
||||
}
|
||||
|
||||
#if RAPIDJSON_HAS_CXX11_RANGE_FOR
|
||||
TEST(Value, ObjectHelperRangeFor) {
|
||||
Value::AllocatorType allocator;
|
||||
Value x(kObjectType);
|
||||
|
||||
for (int i = 0; i < 10; i++) {
|
||||
char name[10];
|
||||
Value n(name, static_cast<SizeType>(sprintf(name, "%d", i)), allocator);
|
||||
x.AddMember(n, i, allocator);
|
||||
}
|
||||
|
||||
{
|
||||
int i = 0;
|
||||
for (auto& m : x.GetObject()) {
|
||||
char name[10];
|
||||
sprintf(name, "%d", i);
|
||||
EXPECT_STREQ(name, m.name.GetString());
|
||||
EXPECT_EQ(i, m.value.GetInt());
|
||||
i++;
|
||||
}
|
||||
EXPECT_EQ(i, 10);
|
||||
}
|
||||
{
|
||||
int i = 0;
|
||||
for (const auto& m : const_cast<const Value&>(x).GetObject()) {
|
||||
char name[10];
|
||||
sprintf(name, "%d", i);
|
||||
EXPECT_STREQ(name, m.name.GetString());
|
||||
EXPECT_EQ(i, m.value.GetInt());
|
||||
i++;
|
||||
}
|
||||
EXPECT_EQ(i, 10);
|
||||
}
|
||||
|
||||
// Object a = x.GetObject();
|
||||
// Object ca = const_cast<const Value&>(x).GetObject();
|
||||
}
|
||||
#endif
|
||||
|
||||
TEST(Value, EraseMember_String) {
|
||||
Value::AllocatorType allocator;
|
||||
Value x(kObjectType);
|
||||
@ -1378,12 +1648,13 @@ struct TerminateHandler {
|
||||
bool Int64(int64_t) { return e != 4; }
|
||||
bool Uint64(uint64_t) { return e != 5; }
|
||||
bool Double(double) { return e != 6; }
|
||||
bool String(const char*, SizeType, bool) { return e != 7; }
|
||||
bool StartObject() { return e != 8; }
|
||||
bool Key(const char*, SizeType, bool) { return e != 9; }
|
||||
bool EndObject(SizeType) { return e != 10; }
|
||||
bool StartArray() { return e != 11; }
|
||||
bool EndArray(SizeType) { return e != 12; }
|
||||
bool RawNumber(const char*, SizeType, bool) { return e != 7; }
|
||||
bool String(const char*, SizeType, bool) { return e != 8; }
|
||||
bool StartObject() { return e != 9; }
|
||||
bool Key(const char*, SizeType, bool) { return e != 10; }
|
||||
bool EndObject(SizeType) { return e != 11; }
|
||||
bool StartArray() { return e != 12; }
|
||||
bool EndArray(SizeType) { return e != 13; }
|
||||
};
|
||||
|
||||
#define TEST_TERMINATION(e, json)\
|
||||
@ -1404,12 +1675,13 @@ TEST(Value, AcceptTerminationByHandler) {
|
||||
TEST_TERMINATION(4, "[-1234567890123456789]");
|
||||
TEST_TERMINATION(5, "[9223372036854775808]");
|
||||
TEST_TERMINATION(6, "[0.5]");
|
||||
TEST_TERMINATION(7, "[\"a\"]");
|
||||
TEST_TERMINATION(8, "[{}]");
|
||||
TEST_TERMINATION(9, "[{\"a\":1}]");
|
||||
TEST_TERMINATION(10, "[{}]");
|
||||
TEST_TERMINATION(11, "{\"a\":[]}");
|
||||
// RawNumber() is never called
|
||||
TEST_TERMINATION(8, "[\"a\"]");
|
||||
TEST_TERMINATION(9, "[{}]");
|
||||
TEST_TERMINATION(10, "[{\"a\":1}]");
|
||||
TEST_TERMINATION(11, "[{}]");
|
||||
TEST_TERMINATION(12, "{\"a\":[]}");
|
||||
TEST_TERMINATION(13, "{\"a\":[]}");
|
||||
}
|
||||
|
||||
struct ValueIntComparer {
|
||||
|
Loading…
Reference in New Issue
Block a user