Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/Ultimaker/CuraEngine.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGhostkeeper <Ghostkeeper@users.noreply.github.com>2022-04-14 15:54:56 +0300
committerGitHub <noreply@github.com>2022-04-14 15:54:56 +0300
commitcd0f2b138669b273ddf56ee95cfdbabafe3b21b5 (patch)
tree06ee69cac83062354e890f075bf5988a4132a146
parent4e6cc60b9b13707e67f85d13bc1281be279a7c54 (diff)
parent367214da7b39e00d3acda68502f428e79c0ece44 (diff)
Merge pull request #1639 from Ultimaker/CURA-8640_PyQt6_upgrade
Cura 8640 PyQt6 upgrade
-rw-r--r--CMakeLists.txt596
-rw-r--r--cmake/FindPolyclipping.cmake67
-rw-r--r--cmake/Findstb.cmake (renamed from cmake/FindStb.cmake)8
-rw-r--r--cmake/StandardProjectSettings.cmake299
-rw-r--r--conanfile.py37
-rw-r--r--libs/clipper/clipper.cpp4
-rw-r--r--libs/clipper/include/polyclipping/clipper.hpp (renamed from libs/clipper/clipper.hpp)812
-rw-r--r--libs/rapidjson/include/rapidjson/allocators.h (renamed from libs/rapidjson/allocators.h)498
-rw-r--r--libs/rapidjson/include/rapidjson/document.h (renamed from libs/rapidjson/document.h)3930
-rw-r--r--libs/rapidjson/include/rapidjson/encodedstream.h (renamed from libs/rapidjson/encodedstream.h)522
-rw-r--r--libs/rapidjson/include/rapidjson/encodings.h (renamed from libs/rapidjson/encodings.h)1250
-rw-r--r--libs/rapidjson/include/rapidjson/error/en.h (renamed from libs/rapidjson/error/en.h)0
-rw-r--r--libs/rapidjson/include/rapidjson/error/error.h (renamed from libs/rapidjson/error/error.h)0
-rw-r--r--libs/rapidjson/include/rapidjson/filereadstream.h (renamed from libs/rapidjson/filereadstream.h)176
-rw-r--r--libs/rapidjson/include/rapidjson/filewritestream.h (renamed from libs/rapidjson/filewritestream.h)182
-rw-r--r--libs/rapidjson/include/rapidjson/internal/biginteger.h (renamed from libs/rapidjson/internal/biginteger.h)0
-rw-r--r--libs/rapidjson/include/rapidjson/internal/diyfp.h (renamed from libs/rapidjson/internal/diyfp.h)0
-rw-r--r--libs/rapidjson/include/rapidjson/internal/dtoa.h (renamed from libs/rapidjson/internal/dtoa.h)0
-rw-r--r--libs/rapidjson/include/rapidjson/internal/ieee754.h (renamed from libs/rapidjson/internal/ieee754.h)0
-rw-r--r--libs/rapidjson/include/rapidjson/internal/itoa.h (renamed from libs/rapidjson/internal/itoa.h)0
-rw-r--r--libs/rapidjson/include/rapidjson/internal/meta.h (renamed from libs/rapidjson/internal/meta.h)366
-rw-r--r--libs/rapidjson/include/rapidjson/internal/pow10.h (renamed from libs/rapidjson/internal/pow10.h)106
-rw-r--r--libs/rapidjson/include/rapidjson/internal/stack.h (renamed from libs/rapidjson/internal/stack.h)354
-rw-r--r--libs/rapidjson/include/rapidjson/internal/strfunc.h (renamed from libs/rapidjson/internal/strfunc.h)74
-rw-r--r--libs/rapidjson/include/rapidjson/internal/strtod.h (renamed from libs/rapidjson/internal/strtod.h)0
-rw-r--r--libs/rapidjson/include/rapidjson/memorybuffer.h (renamed from libs/rapidjson/memorybuffer.h)0
-rw-r--r--libs/rapidjson/include/rapidjson/memorystream.h (renamed from libs/rapidjson/memorystream.h)0
-rw-r--r--libs/rapidjson/include/rapidjson/msinttypes/inttypes.h (renamed from libs/rapidjson/msinttypes/inttypes.h)0
-rw-r--r--libs/rapidjson/include/rapidjson/msinttypes/stdint.h (renamed from libs/rapidjson/msinttypes/stdint.h)0
-rw-r--r--libs/rapidjson/include/rapidjson/prettywriter.h (renamed from libs/rapidjson/prettywriter.h)414
-rw-r--r--libs/rapidjson/include/rapidjson/rapidjson.h (renamed from libs/rapidjson/rapidjson.h)1240
-rw-r--r--libs/rapidjson/include/rapidjson/reader.h (renamed from libs/rapidjson/reader.h)2880
-rw-r--r--libs/rapidjson/include/rapidjson/stringbuffer.h (renamed from libs/rapidjson/stringbuffer.h)186
-rw-r--r--libs/rapidjson/include/rapidjson/writer.h (renamed from libs/rapidjson/writer.h)790
-rw-r--r--src/communication/Listener.cpp2
-rw-r--r--src/communication/Listener.h2
-rw-r--r--src/infill/ImageBasedDensityProvider.cpp2
-rw-r--r--src/raft.cpp2
-rw-r--r--src/utils/Coord_t.h2
-rw-r--r--src/utils/IntPoint.h2
-rw-r--r--src/utils/polygon.h2
-rw-r--r--tests/ClipperTest.cpp2
-rw-r--r--tests/PathOrderMonotonicTest.cpp2
-rw-r--r--tests/utils/AABB3DTest.cpp2
-rw-r--r--tests/utils/AABBTest.cpp2
45 files changed, 7519 insertions, 7294 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 61fc83b30..a2be956f6 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -1,349 +1,312 @@
-#Copyright (c) 2021 Ultimaker B.V.
+#Copyright (c) 2022 Ultimaker B.V.
#CuraEngine is released under the terms of the AGPLv3 or higher.
-cmake_minimum_required(VERSION 3.8.0)
-
+cmake_minimum_required(VERSION 3.20)
project(CuraEngine)
-list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake")
-
+set(CURA_ENGINE_VERSION "master" CACHE STRING "Version name of Cura")
option(ENABLE_ARCUS "Enable support for ARCUS" ON)
-
-if (MSVC)
- option(MSVC_STATIC_RUNTIME "Link the MSVC runtime statically" OFF)
-endif()
-
-if(ENABLE_ARCUS)
- message(STATUS "Building with Arcus")
- # We want to have access to protobuf_generate_cpp and other FindProtobuf features.
- # However, if ProtobufConfig is used instead, there is a CMake option that controls
- # this, which defaults to OFF. We need to force this option to ON instead.
- set(protobuf_MODULE_COMPATIBLE ON CACHE INTERNAL "" FORCE)
- find_package(Protobuf 3.0.0 REQUIRED)
- find_package(Arcus REQUIRED)
- add_definitions(-DARCUS)
- find_program(PROTOC "protoc")
- if(${PROTOC} STREQUAL "PROTOC-NOTFOUND")
- message(FATAL_ERROR "Protobuf compiler missing")
- endif()
-endif()
-
-#For reading image files.
-find_package(Stb REQUIRED)
-include_directories(${Stb_INCLUDE_DIRS})
-
-#arachne needs boost polygon/voronoi
-find_package(Boost REQUIRED)
-include_directories(${Boost_INCLUDE_DIRS})
-
+option(BUILD_TESTS "Build with unit tests" OFF)
+option(ENABLE_MORE_COMPILER_OPTIMIZATION_FLAGS "Enable more optimization flags" ON)
option(USE_SYSTEM_LIBS "Use the system libraries if available" OFF)
-if(USE_SYSTEM_LIBS)
- find_package(RapidJSON CONFIG REQUIRED)
- find_package(Polyclipping REQUIRED)
-endif()
-
-# convert build type to upper case letters
-if(CMAKE_BUILD_TYPE)
- string(TOUPPER ${CMAKE_BUILD_TYPE} CMAKE_BUILD_TYPE_UPPER)
-endif()
-
-if(CMAKE_BUILD_TYPE_UPPER MATCHES "DEBUG")
- set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${CMAKE_CXX_FLAGS_DEBUG_INIT}")
-else()
- set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${CMAKE_CXX_FLAGS_RELEASE_INIT}")
-endif()
-
-set(CMAKE_CXX_STANDARD 17)
-
-if(APPLE AND CMAKE_CXX_COMPILER_ID MATCHES "Clang")
- set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -stdlib=libc++")
-endif()
+option(ENABLE_MORE_COMPILER_OPTIMIZATION_FLAGS "Enable more optimization flags" ON)
+option(EXTENSIVE_WARNINGS "Compile with all warnings" OFF)
-OPTION(SET_RPATH ON)
-
-if(SET_RPATH)
- if(NOT DEFINED LIB_SUFFIX)
- set(LIB_SUFFIX "")
- endif()
- set(CMAKE_INSTALL_RPATH "${CMAKE_INSTALL_PREFIX}/lib${LIB_SUFFIX}")
+if(NOT APPLE)
+ option(ENABLE_OPENMP "Use OpenMP for parallel code" ON)
endif()
-set(CURA_ENGINE_VERSION "master" CACHE STRING "Version name of Cura")
-
-option(BUILD_TESTS OFF)
+include(cmake/StandardProjectSettings.cmake)
-# Add a compiler flag to check the output for insane values if we are in debug mode.
-if(CMAKE_BUILD_TYPE_UPPER MATCHES "DEBUG" OR CMAKE_BUILD_TYPE_UPPER MATCHES "RELWITHDEBINFO")
- message(STATUS "Building debug release of CuraEngine.")
- if (NOT MSVC)
- set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wextra -O0 -g -fno-omit-frame-pointer")
- endif()
- add_definitions(-DASSERT_INSANE_OUTPUT)
- add_definitions(-DUSE_CPU_TIME)
- add_definitions(-DDEBUG)
-endif()
+# Create Protobuf files if Arcus is used
+if (ENABLE_ARCUS)
+ message(STATUS "Building with Arcus")
-if (MSVC)
- set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /permissive- /Zc:twoPhase- /EHsc /W3")
- if (MSVC_STATIC_RUNTIME)
- foreach(flag_var
- CMAKE_CXX_FLAGS
- CMAKE_CXX_FLAGS_DEBUG
- CMAKE_CXX_FLAGS_RELEASE
- CMAKE_CXX_FLAGS_MINSIZEREL
- CMAKE_CXX_FLAGS_RELWITHDEBINFO
- )
- if(${flag_var} MATCHES "/MD")
- string(REGEX REPLACE "/MD" "/MT" ${flag_var} "${${flag_var}}")
- endif()
- endforeach()
- endif()
-else()
- set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall") # Add warnings
-endif()
+ find_package(Arcus REQUIRED 5.0.0)
+ find_package(protobuf 3.15.0 QUIET)
+ if (NOT TARGET protobuf::protobuf)
+ find_package(Protobuf 3.15.0 REQUIRED)
+ else ()
+ add_library(Protobuf::protobuf ALIAS protobuf::protobuf)
+ endif ()
-option (ENABLE_MORE_COMPILER_OPTIMIZATION_FLAGS
- "Enable more optimization flags" ON)
-if (ENABLE_MORE_COMPILER_OPTIMIZATION_FLAGS AND NOT (CMAKE_BUILD_TYPE_UPPER MATCHES "DEBUG"))
- message (STATUS "Compile with more optimization flags")
- if (MSVC)
- set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS} /fp:fast")
- else()
- set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS} -Ofast -funroll-loops")
- endif()
+ protobuf_generate_cpp(engine_PB_SRCS engine_PB_HEADERS Cura.proto)
endif ()
-if(NOT APPLE AND NOT WIN32)
- set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -static-libstdc++")
-endif()
-
-if (WIN32)
- add_definitions(-DNOMINMAX)
-endif()
-
-option (ENABLE_OPENMP
- "Use OpenMP for parallel code" ON)
-
-if (ENABLE_OPENMP)
- FIND_PACKAGE( OpenMP )
- if( OPENMP_FOUND )
- set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${OpenMP_CXX_FLAGS}" )
- endif()
-endif()
-
-if(USE_SYSTEM_LIBS)
- include_directories(${Polyclipping_INCLUDE_DIRS} "${CMAKE_BINARY_DIR}" ${RAPIDJSON_INCLUDE_DIRS})
-else()
- include_directories("${CMAKE_CURRENT_BINARY_DIR}" libs libs/clipper)
- add_library(clipper STATIC libs/clipper/clipper.cpp)
-endif()
+### Compiling CuraEngine ###
+# First compile all of CuraEngine as library, allowing this to be re-used for tests.
set(engine_SRCS # Except main.cpp.
- src/Application.cpp
- src/bridge.cpp
- src/ConicalOverhang.cpp
- src/ExtruderTrain.cpp
- src/FffGcodeWriter.cpp
- src/FffPolygonGenerator.cpp
- src/FffProcessor.cpp
- src/gcodeExport.cpp
- src/GCodePathConfig.cpp
- src/infill.cpp
- src/InsetOrderOptimizer.cpp
- src/layerPart.cpp
- src/LayerPlan.cpp
- src/LayerPlanBuffer.cpp
- src/mesh.cpp
- src/MeshGroup.cpp
- src/Mold.cpp
- src/multiVolumes.cpp
- src/PathOrderPath.cpp
- src/Preheat.cpp
- src/PrimeTower.cpp
- src/raft.cpp
- src/Scene.cpp
- src/SkeletalTrapezoidation.cpp
- src/SkeletalTrapezoidationGraph.cpp
- src/skin.cpp
- src/SkirtBrim.cpp
- src/SupportInfillPart.cpp
- src/Slice.cpp
- src/sliceDataStorage.cpp
- src/slicer.cpp
- src/support.cpp
- src/timeEstimate.cpp
- src/TopSurface.cpp
- src/TreeModelVolumes.cpp
- src/TreeSupport.cpp
- src/WallsComputation.cpp
- src/Weaver.cpp
- src/Wireframe2gcode.cpp
- src/WallToolPaths.cpp
-
- src/BeadingStrategy/BeadingStrategy.cpp
- src/BeadingStrategy/BeadingStrategyFactory.cpp
- src/BeadingStrategy/DistributedBeadingStrategy.cpp
- src/BeadingStrategy/LimitedBeadingStrategy.cpp
- src/BeadingStrategy/RedistributeBeadingStrategy.cpp
- src/BeadingStrategy/WideningBeadingStrategy.cpp
- src/BeadingStrategy/OuterWallInsetBeadingStrategy.cpp
-
- src/communication/ArcusCommunication.cpp
- src/communication/ArcusCommunicationPrivate.cpp
- src/communication/CommandLine.cpp
- src/communication/Listener.cpp
-
- src/infill/ImageBasedDensityProvider.cpp
- src/infill/NoZigZagConnectorProcessor.cpp
- src/infill/ZigzagConnectorProcessor.cpp
- src/infill/LightningDistanceField.cpp
- src/infill/LightningGenerator.cpp
- src/infill/LightningLayer.cpp
- src/infill/LightningTreeNode.cpp
- src/infill/SierpinskiFill.cpp
- src/infill/SierpinskiFillProvider.cpp
- src/infill/SubDivCube.cpp
- src/infill/GyroidInfill.cpp
-
- src/pathPlanning/Comb.cpp
- src/pathPlanning/GCodePath.cpp
- src/pathPlanning/LinePolygonsCrossings.cpp
- src/pathPlanning/NozzleTempInsert.cpp
- src/pathPlanning/TimeMaterialEstimates.cpp
-
- src/progress/Progress.cpp
- src/progress/ProgressStageEstimator.cpp
-
- src/settings/AdaptiveLayerHeights.cpp
- src/settings/FlowTempGraph.cpp
- src/settings/PathConfigStorage.cpp
- src/settings/Settings.cpp
- src/settings/ZSeamConfig.cpp
-
- src/utils/AABB.cpp
- src/utils/AABB3D.cpp
- src/utils/Date.cpp
- src/utils/ExtrusionJunction.cpp
- src/utils/ExtrusionLine.cpp
- src/utils/ExtrusionSegment.cpp
- src/utils/FMatrix4x3.cpp
- src/utils/gettime.cpp
- src/utils/getpath.cpp
- src/utils/LinearAlg2D.cpp
- src/utils/ListPolyIt.cpp
- src/utils/logoutput.cpp
- src/utils/MinimumSpanningTree.cpp
- src/utils/Point3.cpp
- src/utils/PolygonConnector.cpp
- src/utils/PolygonsPointIndex.cpp
- src/utils/PolygonsSegmentIndex.cpp
- src/utils/polygonUtils.cpp
- src/utils/polygon.cpp
- src/utils/PolylineStitcher.cpp
- src/utils/ProximityPointLink.cpp
- src/utils/SVG.cpp
- src/utils/socket.cpp
- src/utils/SquareGrid.cpp
- src/utils/ToolpathVisualizer.cpp
- src/utils/VoronoiUtils.cpp
-)
+ src/Application.cpp
+ src/bridge.cpp
+ src/ConicalOverhang.cpp
+ src/ExtruderTrain.cpp
+ src/FffGcodeWriter.cpp
+ src/FffPolygonGenerator.cpp
+ src/FffProcessor.cpp
+ src/gcodeExport.cpp
+ src/GCodePathConfig.cpp
+ src/infill.cpp
+ src/InsetOrderOptimizer.cpp
+ src/layerPart.cpp
+ src/LayerPlan.cpp
+ src/LayerPlanBuffer.cpp
+ src/mesh.cpp
+ src/MeshGroup.cpp
+ src/Mold.cpp
+ src/multiVolumes.cpp
+ src/PathOrderPath.cpp
+ src/Preheat.cpp
+ src/PrimeTower.cpp
+ src/raft.cpp
+ src/Scene.cpp
+ src/SkeletalTrapezoidation.cpp
+ src/SkeletalTrapezoidationGraph.cpp
+ src/skin.cpp
+ src/SkirtBrim.cpp
+ src/SupportInfillPart.cpp
+ src/Slice.cpp
+ src/sliceDataStorage.cpp
+ src/slicer.cpp
+ src/support.cpp
+ src/timeEstimate.cpp
+ src/TopSurface.cpp
+ src/TreeModelVolumes.cpp
+ src/TreeSupport.cpp
+ src/WallsComputation.cpp
+ src/Weaver.cpp
+ src/Wireframe2gcode.cpp
+ src/WallToolPaths.cpp
+
+ src/BeadingStrategy/BeadingStrategy.cpp
+ src/BeadingStrategy/BeadingStrategyFactory.cpp
+ src/BeadingStrategy/DistributedBeadingStrategy.cpp
+ src/BeadingStrategy/LimitedBeadingStrategy.cpp
+ src/BeadingStrategy/RedistributeBeadingStrategy.cpp
+ src/BeadingStrategy/WideningBeadingStrategy.cpp
+ src/BeadingStrategy/OuterWallInsetBeadingStrategy.cpp
+
+ src/communication/ArcusCommunication.cpp
+ src/communication/ArcusCommunicationPrivate.cpp
+ src/communication/CommandLine.cpp
+ src/communication/Listener.cpp
+
+ src/infill/ImageBasedDensityProvider.cpp
+ src/infill/NoZigZagConnectorProcessor.cpp
+ src/infill/ZigzagConnectorProcessor.cpp
+ src/infill/LightningDistanceField.cpp
+ src/infill/LightningGenerator.cpp
+ src/infill/LightningLayer.cpp
+ src/infill/LightningTreeNode.cpp
+ src/infill/SierpinskiFill.cpp
+ src/infill/SierpinskiFillProvider.cpp
+ src/infill/SubDivCube.cpp
+ src/infill/GyroidInfill.cpp
+
+ src/pathPlanning/Comb.cpp
+ src/pathPlanning/GCodePath.cpp
+ src/pathPlanning/LinePolygonsCrossings.cpp
+ src/pathPlanning/NozzleTempInsert.cpp
+ src/pathPlanning/TimeMaterialEstimates.cpp
+
+ src/progress/Progress.cpp
+ src/progress/ProgressStageEstimator.cpp
+
+ src/settings/AdaptiveLayerHeights.cpp
+ src/settings/FlowTempGraph.cpp
+ src/settings/PathConfigStorage.cpp
+ src/settings/Settings.cpp
+ src/settings/ZSeamConfig.cpp
+
+ src/utils/AABB.cpp
+ src/utils/AABB3D.cpp
+ src/utils/Date.cpp
+ src/utils/ExtrusionJunction.cpp
+ src/utils/ExtrusionLine.cpp
+ src/utils/ExtrusionSegment.cpp
+ src/utils/FMatrix4x3.cpp
+ src/utils/gettime.cpp
+ src/utils/getpath.cpp
+ src/utils/LinearAlg2D.cpp
+ src/utils/ListPolyIt.cpp
+ src/utils/logoutput.cpp
+ src/utils/MinimumSpanningTree.cpp
+ src/utils/Point3.cpp
+ src/utils/PolygonConnector.cpp
+ src/utils/PolygonsPointIndex.cpp
+ src/utils/PolygonsSegmentIndex.cpp
+ src/utils/polygonUtils.cpp
+ src/utils/polygon.cpp
+ src/utils/PolylineStitcher.cpp
+ src/utils/ProximityPointLink.cpp
+ src/utils/SVG.cpp
+ src/utils/socket.cpp
+ src/utils/SquareGrid.cpp
+ src/utils/ToolpathVisualizer.cpp
+ src/utils/VoronoiUtils.cpp
+ )
# List of tests. For each test there must be a file tests/${NAME}.cpp.
set(engine_TEST
- ClipperTest
- ExtruderPlanTest
- GCodeExportTest
- InfillTest
- LayerPlanTest
- PathOrderOptimizerTest
- PathOrderMonotonicTest
- TimeEstimateCalculatorTest
- WallsComputationTest
-)
+ ClipperTest
+ ExtruderPlanTest
+ GCodeExportTest
+ InfillTest
+ LayerPlanTest
+ PathOrderOptimizerTest
+ PathOrderMonotonicTest
+ TimeEstimateCalculatorTest
+ WallsComputationTest
+ )
if (ENABLE_ARCUS)
set(engine_TEST_ARCUS
- ArcusCommunicationTest
- ArcusCommunicationPrivateTest
- )
+ ArcusCommunicationTest
+ ArcusCommunicationPrivateTest
+ )
endif ()
set(engine_TEST_INFILL
-)
+ )
set(engine_TEST_INTEGRATION
- SlicePhaseTest
-)
+ SlicePhaseTest
+ )
set(engine_TEST_SETTINGS
- SettingsTest
-)
+ SettingsTest
+ )
set(engine_TEST_UTILS
- AABBTest
- AABB3DTest
- ExtrusionLineTest
- IntPointTest
- LinearAlg2DTest
- MinimumSpanningTreeTest
- PolygonConnectorTest
- PolygonTest
- PolygonUtilsTest
- SparseGridTest
- StringTest
- UnionFindTest
-)
+ AABBTest
+ AABB3DTest
+ ExtrusionLineTest
+ IntPointTest
+ LinearAlg2DTest
+ MinimumSpanningTreeTest
+ PolygonConnectorTest
+ PolygonTest
+ PolygonUtilsTest
+ SparseGridTest
+ StringTest
+ UnionFindTest
+ )
# Helper classes for some tests.
set(engine_TEST_ARCUS_HELPERS
- tests/arcus/MockSocket.cpp
-)
+ tests/arcus/MockSocket.cpp
+ )
set(engine_TEST_HELPERS
- tests/ReadTestPolygons.cpp
-)
+ tests/ReadTestPolygons.cpp
+ )
-# Generating ProtoBuf protocol
-if (ENABLE_ARCUS)
- protobuf_generate_cpp(engine_PB_SRCS engine_PB_HEADERS Cura.proto)
-endif ()
+add_library(_CuraEngine STATIC ${engine_SRCS} ${engine_PB_SRCS})
+use_threads(_CuraEngine)
-# Compiling CuraEngine itself.
-add_library(_CuraEngine STATIC ${engine_SRCS} ${engine_PB_SRCS}) #First compile all of CuraEngine as library, allowing this to be re-used for tests.
+target_include_directories(_CuraEngine
+ PUBLIC
+ $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/src>
+ $<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>
+ $<BUILD_INTERFACE:${CMAKE_CURRENT_BINARY_DIR}> # Include Cura.pb.h
+ )
+target_compile_definitions(_CuraEngine
+ PUBLIC
+ $<$<BOOL:${BUILD_TESTS}>:BUILD_TESTS=1>
+ $<$<BOOL:${BUILD_TESTS}>:BUILD_TESTS>
+ $<$<BOOL:${ENABLE_ARCUS}>:ARCUS>
+ PRIVATE
+ VERSION=\"${CURA_ENGINE_VERSION}\"
+ $<$<BOOL:${WIN32}>:NOMINMAX>
+ $<$<CONFIG:Debug>:ASSERT_INSANE_OUTPUT>
+ $<$<CONFIG:Debug>:USE_CPU_TIME>
+ $<$<CONFIG:Debug>:DEBUG>
+ $<$<CONFIG:RelWithDebInfo>:ASSERT_INSANE_OUTPUT>
+ $<$<CONFIG:RelWithDebInfo>:USE_CPU_TIME>
+ $<$<CONFIG:RelWithDebInfo>:DEBUG>
+ )
+if(MSVC)
+ target_compile_options(_CuraEngine
+ PRIVATE
+ $<$<AND:$<BOOL:${ENABLE_MORE_COMPILER_OPTIMIZATION_FLAGS}>,$<CONFIG:Release>>:/fp:fast>
+ )
+else()
+ target_compile_options(_CuraEngine
+ PRIVATE
+ $<$<CONFIG:Debug>:-fno-omit-frame-pointer>
+ $<$<CONFIG:RelWithDebInfo>:-fno-omit-frame-pointer>
+ $<$<AND:$<BOOL:${ENABLE_MORE_COMPILER_OPTIMIZATION_FLAGS}>,$<CONFIG:Release>>:-Ofast>
+ $<$<AND:$<BOOL:${ENABLE_MORE_COMPILER_OPTIMIZATION_FLAGS}>,$<CONFIG:Release>>:-funroll-loops>
+ )
+endif()
-if (CuraEngine_Download_Stb)
- add_dependencies(_CuraEngine stb)
+set_project_standards(_CuraEngine)
+enable_sanitizers(_CuraEngine)
+set_rpath(TARGETS
+ _CuraEngine
+ PATHS
+ "$<$<PLATFORM_ID:Linux>:usr/bin>"
+ "$<$<PLATFORM_ID:Linux>:usr/bin/lib>"
+ "$<$<PLATFORM_ID:Darwin>:../lib>"
+ RELATIVE)
+
+if(${EXTENSIVE_WARNINGS})
+ set_project_warnings(_CuraEngine)
endif()
-if(USE_SYSTEM_LIBS)
- target_link_libraries(_CuraEngine ${Polyclipping_LIBRARIES})
-else()
- target_link_libraries(_CuraEngine clipper)
+
+if(NOT APPLE AND ENABLE_OPENMP)
+ find_package(OpenMP REQUIRED)
+ target_link_libraries(_CuraEngine PUBLIC OpenMP::OpenMP_CXX)
endif()
-if (ENABLE_ARCUS)
- target_link_libraries(_CuraEngine Arcus)
+if(ENABLE_ARCUS)
+ target_link_libraries(_CuraEngine PRIVATE Arcus protobuf::protobuf)
+endif()
+
+find_package(clipper 6.4.2 QUIET)
+if (NOT TARGET clipper::clipper)
+ add_library(clipper::clipper STATIC libs/clipper/clipper.cpp)
+ target_include_directories(clipper::clipper
+ PUBLIC
+ $<BUILD_INTERFACE:${CMAKE_SOURCE_DIR}/libs/clipper/include>
+ $<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>
+ )
endif ()
-set_target_properties(_CuraEngine PROPERTIES COMPILE_DEFINITIONS "VERSION=\"${CURA_ENGINE_VERSION}\"")
+find_package(rapidjson 1.1.0 QUIET)
+if (NOT TARGET rapidjson::rapidjson)
+ add_library(rapidjson::rapidjson INTERFACE)
+ target_include_directories(rapidjson::rapidjson
+ PUBLIC
+ $<BUILD_INTERFACE:${CMAKE_SOURCE_DIR}/libs/clipper/include>
+ $<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>
+ )
+endif()
-if(WIN32)
- message(STATUS "Using windres")
- set(RES_FILES "CuraEngine.rc")
- ENABLE_LANGUAGE(RC)
- if(NOT MSVC)
- SET(CMAKE_RC_COMPILER_INIT windres)
- SET(CMAKE_RC_COMPILE_OBJECT
- "<CMAKE_RC_COMPILER> <FLAGS> -O coff <DEFINES> -i <SOURCE> -o <OBJECT>"
- )
- endif()
-endif(WIN32)
+find_package(stb REQUIRED)
-if (UNIX)
- target_link_libraries(_CuraEngine pthread)
-endif()
+find_package(Boost REQUIRED 1.75.0)
+if (NOT TARGET Boost::boost) # Workaround for different namespace in non Conan find_packages
+ add_library(boost::boost ALIAS Boost::boost)
+endif ()
+
+target_link_libraries(_CuraEngine PRIVATE clipper::clipper rapidjson::rapidjson stb::stb boost::boost)
+
+if (WIN32)
+ message(STATUS "Using windres")
+ set(RES_FILES "CuraEngine.rc")
+ ENABLE_LANGUAGE(RC)
+ if (NOT MSVC)
+ SET(CMAKE_RC_COMPILER_INIT windres)
+ SET(CMAKE_RC_COMPILE_OBJECT
+ "<CMAKE_RC_COMPILER> <FLAGS> -O coff <DEFINES> -i <SOURCE> -o <OBJECT>"
+ )
+ endif ()
+endif (WIN32)
if (NOT WIN32)
- add_executable(CuraEngine src/main.cpp) # Then compile main.cpp as separate executable, and link the library to it.
-else()
- add_executable(CuraEngine src/main.cpp ${RES_FILES}) # ..., but don't forget the glitter!
-endif(NOT WIN32)
+ add_executable(CuraEngine src/main.cpp) # Then compile main.cpp as separate executable, and link the library to it.
+else ()
+ add_executable(CuraEngine src/main.cpp ${RES_FILES}) # ..., but don't forget the glitter!
+endif (NOT WIN32)
-target_link_libraries(CuraEngine _CuraEngine)
-set_target_properties(CuraEngine PROPERTIES COMPILE_DEFINITIONS "VERSION=\"${CURA_ENGINE_VERSION}\"")
+# Create the executable
+target_link_libraries(CuraEngine PRIVATE _CuraEngine)
+target_compile_definitions(CuraEngine PRIVATE VERSION=\"${CURA_ENGINE_VERSION}\")
# Compiling the test environment.
if (BUILD_TESTS)
@@ -352,7 +315,7 @@ if (BUILD_TESTS)
message(STATUS "Building tests...")
set(GTEST_USE_STATIC_LIBS true)
set(GMOCK_ROOT "${CMAKE_CURRENT_BINARY_DIR}/gmock")
- set(GMOCK_VER "1.8.0")
+ set(GMOCK_VER "1.8.1")
find_package(GMock REQUIRED)
include_directories(${GTEST_INCLUDE_DIRS})
include_directories(${GMOCK_INCLUDE_DIRS})
@@ -370,9 +333,9 @@ if (BUILD_TESTS)
target_link_libraries(${test} _CuraEngine ${GTEST_BOTH_LIBRARIES} ${GMOCK_BOTH_LIBRARIES})
add_test(NAME ${test} COMMAND "${test}" WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/tests/")
add_dependencies(build_all_tests ${test}) #Make sure that this gets built as part of the build_all_tests target.
- endforeach()
+ endforeach ()
if (ENABLE_ARCUS)
- foreach(test ${engine_TEST_ARCUS})
+ foreach (test ${engine_TEST_ARCUS})
add_executable(${test} tests/main.cpp ${engine_TEST_ARCUS_HELPERS} tests/arcus/${test}.cpp)
target_link_libraries(${test} _CuraEngine ${GTEST_BOTH_LIBRARIES} ${GMOCK_BOTH_LIBRARIES})
add_test(NAME ${test} COMMAND "${test}" WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/tests/")
@@ -384,39 +347,28 @@ if (BUILD_TESTS)
target_link_libraries(${test} _CuraEngine ${GTEST_BOTH_LIBRARIES} ${GMOCK_BOTH_LIBRARIES})
add_test(NAME ${test} COMMAND "${test}" WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/tests/")
add_dependencies(build_all_tests ${test}) #Make sure that this gets built as part of the build_all_tests target.
- endforeach()
+ endforeach ()
foreach (test ${engine_TEST_INTEGRATION})
add_executable(${test} tests/main.cpp tests/integration/${test}.cpp)
target_link_libraries(${test} _CuraEngine ${GTEST_BOTH_LIBRARIES} ${GMOCK_BOTH_LIBRARIES})
add_test(NAME ${test} COMMAND "${test}" WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/tests/")
add_dependencies(build_all_tests ${test}) #Make sure that this gets built as part of the build_all_tests target.
- endforeach()
+ endforeach ()
foreach (test ${engine_TEST_SETTINGS})
add_executable(${test} tests/main.cpp tests/settings/${test}.cpp)
target_link_libraries(${test} _CuraEngine ${GTEST_BOTH_LIBRARIES} ${GMOCK_BOTH_LIBRARIES})
add_test(NAME ${test} COMMAND "${test}" WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/tests/")
add_dependencies(build_all_tests ${test}) #Make sure that this gets built as part of the build_all_tests target.
- endforeach()
+ endforeach ()
foreach (test ${engine_TEST_UTILS})
add_executable(${test} tests/main.cpp tests/utils/${test}.cpp)
target_link_libraries(${test} _CuraEngine ${GTEST_BOTH_LIBRARIES} ${GMOCK_BOTH_LIBRARIES})
add_test(NAME ${test} COMMAND "${test}" WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/tests/")
add_dependencies(build_all_tests ${test}) #Make sure that this gets built as part of the build_all_tests target.
- endforeach()
-endif()
+ endforeach ()
+endif ()
# Installing CuraEngine.
include(GNUInstallDirs)
install(TARGETS CuraEngine DESTINATION "${CMAKE_INSTALL_BINDIR}")
-# For MinGW64 cross compiling on Debian, we create a ZIP package instead of a DEB
-# Because it's the Windows build system that should install the files.
-if (CMAKE_CROSSCOMPILING AND CMAKE_SYSTEM_NAME MATCHES "Windows")
- message(STATUS "Include MinGW64 posix DLLs for installation.")
- install(FILES
- /usr/lib/gcc/x86_64-w64-mingw32/8.3-posix/libgcc_s_seh-1.dll
- /usr/lib/gcc/x86_64-w64-mingw32/8.3-posix/libgomp-1.dll
- /usr/lib/gcc/x86_64-w64-mingw32/8.3-posix/libstdc++-6.dll
- DESTINATION bin
- COMPONENT runtime)
-endif ()
include(CPackConfig.cmake)
diff --git a/cmake/FindPolyclipping.cmake b/cmake/FindPolyclipping.cmake
deleted file mode 100644
index 7c88ab630..000000000
--- a/cmake/FindPolyclipping.cmake
+++ /dev/null
@@ -1,67 +0,0 @@
-#
-# - Try to find the polyclipping library
-# this will define
-#
-# Polyclipping_FOUND - polyclipping was found
-# Polyclipping_INCLUDE_DIRS - the polyclipping include directory
-# Polyclipping_LIBRARIES - The libraries needed to use polyclipping
-# Polyclipping_VERSION - The polyclipping library version
-
-#=============================================================================
-# Copyright (c) 2017 Christophe Giboudeaux <christophe@krop.fr>
-#
-#
-# Redistribution and use in source and binary forms, with or without
-# modification, are permitted provided that the following conditions
-# are met:
-#
-# 1. Redistributions of source code must retain the copyright
-# notice, this list of conditions and the following disclaimer.
-# 2. Redistributions in binary form must reproduce the copyright
-# notice, this list of conditions and the following disclaimer in the
-# documentation and/or other materials provided with the distribution.
-# 3. The name of the author may not be used to endorse or promote products
-# derived from this software without specific prior written permission.
-#
-# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
-# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
-# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
-# IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
-# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
-# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
-# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-#=============================================================================
-
-
-find_package(PkgConfig QUIET)
-pkg_check_modules(PC_Polyclipping QUIET polyclipping)
-
-find_path(Polyclipping_INCLUDE_DIRS
- NAMES clipper.hpp
- HINTS ${PC_Polyclipping_INCLUDE_DIRS}
-)
-
-find_library(Polyclipping_LIBRARIES
- NAMES polyclipping
- HINTS ${PC_Polyclipping_LIBRARY_DIRS}
-)
-
-if(EXISTS ${Polyclipping_INCLUDE_DIRS}/clipper.hpp)
- file(READ ${Polyclipping_INCLUDE_DIRS}/clipper.hpp CLIPPER_H_CONTENT)
- string(REGEX MATCH "#define CLIPPER_VERSION[ ]+\"[0-9]+.[0-9]+.[0-9]+\"" CLIPPER_H_VERSION_MATCH ${CLIPPER_H_CONTENT})
- string(REGEX REPLACE "^.*CLIPPER_VERSION[ ]+\"([0-9]+.[0-9]+.[0-9]+).*$" "\\1" Polyclipping_VERSION "${CLIPPER_H_VERSION_MATCH}")
-endif()
-
-include(FindPackageHandleStandardArgs)
-
-find_package_handle_standard_args(Polyclipping
- FOUND_VAR Polyclipping_FOUND
- REQUIRED_VARS Polyclipping_LIBRARIES Polyclipping_INCLUDE_DIRS
- VERSION_VAR Polyclipping_VERSION
-)
-
-mark_as_advanced(Polyclipping_LIBRARIES Polyclipping_INCLUDE_DIRS Polyclipping_VERSION)
-
diff --git a/cmake/FindStb.cmake b/cmake/Findstb.cmake
index b510d6b0e..e9f11f3cd 100644
--- a/cmake/FindStb.cmake
+++ b/cmake/Findstb.cmake
@@ -52,7 +52,7 @@ else()
INSTALL_COMMAND "" #Assume that the user doesn't want to install all dependencies on his system. We just need to get them for building the application.
)
set(CuraEngine_Download_Stb TRUE)
- set(Stb_INCLUDE_DIRS "${CMAKE_CURRENT_BINARY_DIR}/stb-prefix/src")
+ set(Stb_INCLUDE_DIRS "${CMAKE_CURRENT_BINARY_DIR}/stb-prefix/src/stb")
set(Stb_FOUND TRUE)
if(NOT Stb_FIND_QUIETLY)
message(STATUS "Created Stb installation at: ${Stb_INCLUDE_DIRS}")
@@ -67,3 +67,9 @@ else()
endif()
mark_as_advanced(Stb_INCLUDE_DIRS)
+add_library(stb::stb INTERFACE)
+target_include_directories(stb::stb
+ PUBLIC
+ $<BUILD_INTERFACE:${Stb_INCLUDE_DIRS}>
+ $<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>
+ )
diff --git a/cmake/StandardProjectSettings.cmake b/cmake/StandardProjectSettings.cmake
new file mode 100644
index 000000000..ef5acd0b9
--- /dev/null
+++ b/cmake/StandardProjectSettings.cmake
@@ -0,0 +1,299 @@
+include(GNUInstallDirs) # Standard install dirs
+
+# Generate compile_commands.json to make it easier to work with clang based tools
+message(STATUS "Generating compile commands to ${CMAKE_CURRENT_BINARY_DIR}/compile_commands.json")
+set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
+
+# Use C++17 Standard
+message(STATUS "Setting C++17 support with extensions off and standard required")
+set(CMAKE_CXX_STANDARD 17)
+set(CMAKE_CXX_EXTENSIONS OFF)
+set(CMAKE_CXX_STANDARD_REQUIRED ON)
+
+# Set common project options for the target
+function(set_project_standards project_name)
+ get_target_property(type ${project_name} TYPE)
+ if(CMAKE_CXX_COMPILER_ID MATCHES ".*Clang")
+ option(ENABLE_BUILD_WITH_TIME_TRACE "Enable -ftime-trace to generate time tracing .json files on clang" OFF)
+ if(ENABLE_BUILD_WITH_TIME_TRACE)
+ message(STATUS "Enabling time tracing for ${project_name}")
+ if (${type} STREQUAL "INTERFACE_LIBRARY")
+ add_compile_definitions(${project_name} INTERFACE -ftime-trace)
+ else()
+ add_compile_definitions(${project_name} PRIVATE -ftime-trace)
+ endif()
+ endif()
+ if (APPLE)
+ message(STATUS "Compiling ${project_name} against libc++")
+ if (${type} STREQUAL "INTERFACE_LIBRARY")
+ target_compile_options(${project_name} INTERFACE "-stdlib=libc++")
+ else()
+ target_compile_options(${project_name} PRIVATE "-stdlib=libc++")
+ endif()
+ endif()
+ endif()
+endfunction()
+
+function(set_rpath)
+ # Sets the RPATHS for targets (Linux and Windows, these can either be absolute paths or relative to the executable
+ # Usage:
+ # set_rpath(TARGETS <list of targets to set rpaths for>
+ # PATHS <list of paths>
+ # <optional> RELATIVE)
+ # if the RELATIVE option is used the paths will be specified from either $ORIGIN on Linux or @executable_path on Mac
+ set(options RELATIVE)
+ set(oneValueArgs )
+ set(multiValueArgs TARGETS PATHS)
+ cmake_parse_arguments(SET_RPATH "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
+ foreach(_target IN ITEMS ${SET_RPATH_TARGETS})
+ message(STATUS "Setting SKIP_BUILD_RPATH for target ${_target} to FALSE")
+ set_target_properties(${_target} PROPERTIES SKIP_BUILD_RPATH FALSE)
+ message(STATUS "Setting BUILD_WITH_INSTALL_RPATH for target ${_target} to FALSE")
+ set_target_properties(${_target} PROPERTIES BUILD_WITH_INSTALL_RPATH FALSE)
+ message(STATUS "Setting INSTALL_RPATH_USE_LINK_PATH for target ${_target} to TRUE")
+ set_target_properties(${_target} PROPERTIES INSTALL_RPATH_USE_LINK_PATH TRUE)
+ if(APPLE)
+ message(STATUS "Setting MACOSX_RPATH for target ${_target}")
+ set_target_properties(${_target} PROPERTIES MACOSX_RPATH ON)
+ endif()
+ if(SET_RPATH_RELATIVE)
+ list(PREPEND SET_RPATH_PATHS "")
+ if(APPLE)
+ list(TRANSFORM SET_RPATH_PATHS PREPEND "@executable_path/")
+ else(LINUX)
+ list(TRANSFORM SET_RPATH_PATHS PREPEND "\$ORIGIN/")
+ endif()
+ endif()
+ set_target_properties(${_target} PROPERTIES INSTALL_RPATH "${SET_RPATH_PATHS}")
+ message(STATUS "Setting install RPATH for target ${_target} to ${SET_RPATH_PATHS}")
+ endforeach()
+endfunction()
+
+# Ultimaker uniform Python linking method
+function(use_python project_name)
+ find_package(Python REQUIRED)
+ get_target_property(type ${project_name} TYPE)
+ if(${type} STREQUAL "INTERFACE_LIBRARY")
+ target_link_libraries(${project_name} INTERFACE Python::Python)
+ else()
+ target_link_libraries(${project_name} PRIVATE Python::Python)
+ endif()
+ message(STATUS "Linking and building ${project_name} against Python ${Python_VERSION}")
+endfunction()
+
+# Ultimaker uniform Thread linking method
+function(use_threads project_name)
+ message(STATUS "Enabling threading support for ${project_name}")
+ set(CMAKE_THREAD_PREFER_PTHREAD TRUE)
+ set(THREADS_PREFER_PTHREAD_FLAG TRUE)
+ find_package(Threads)
+ get_target_property(type ${project_name} TYPE)
+ if (${type} STREQUAL "INTERFACE_LIBRARY")
+ target_link_libraries(${project_name} INTERFACE Threads::Threads)
+ else()
+ target_link_libraries(${project_name} PRIVATE Threads::Threads)
+ endif()
+endfunction()
+
+# https://github.com/lefticus/cppbestpractices/blob/master/02-Use_the_Tools_Available.md
+function(set_project_warnings project_name)
+ message(STATUS "Setting warnings for ${project_name}")
+ set(MSVC_WARNINGS
+ /W4 # Baseline reasonable warnings
+ /w14242 # 'identifier': conversion from 'type1' to 'type1', possible loss of data
+ /w14254 # 'operator': conversion from 'type1:field_bits' to 'type2:field_bits', possible loss of data
+ /w14263 # 'function': member function does not override any base class virtual member function
+ /w14265 # 'classname': class has virtual functions, but destructor is not virtual instances of this class may not
+ # be destructed correctly
+ /w14287 # 'operator': unsigned/negative constant mismatch
+ /we4289 # nonstandard extension used: 'variable': loop control variable declared in the for-loop is used outside
+ # the for-loop scope
+ /w14296 # 'operator': expression is always 'boolean_value'
+ /w14311 # 'variable': pointer truncation from 'type1' to 'type2'
+ /w14545 # expression before comma evaluates to a function which is missing an argument list
+ /w14546 # function call before comma missing argument list
+ /w14547 # 'operator': operator before comma has no effect; expected operator with side-effect
+ /w14549 # 'operator': operator before comma has no effect; did you intend 'operator'?
+ /w14555 # expression has no effect; expected expression with side- effect
+ /w14619 # pragma warning: there is no warning number 'number'
+ /w14640 # Enable warning on thread un-safe static member initialization
+ /w14826 # Conversion from 'type1' to 'type_2' is sign-extended. This may cause unexpected runtime behavior.
+ /w14905 # wide string literal cast to 'LPSTR'
+ /w14906 # string literal cast to 'LPWSTR'
+ /w14928 # illegal copy-initialization; more than one user-defined conversion has been implicitly applied
+ /permissive- # standards conformance mode for MSVC compiler.
+ )
+
+ set(CLANG_WARNINGS
+ -Wall
+ -Wextra # reasonable and standard
+ -Wshadow # warn the user if a variable declaration shadows one from a parent context
+ -Wnon-virtual-dtor # warn the user if a class with virtual functions has a non-virtual destructor. This helps
+ # catch hard to track down memory errors
+ -Wold-style-cast # warn for c-style casts
+ -Wcast-align # warn for potential performance problem casts
+ -Wunused # warn on anything being unused
+ -Woverloaded-virtual # warn if you overload (not override) a virtual function
+ -Wpedantic # warn if non-standard C++ is used
+ -Wconversion # warn on type conversions that may lose data
+ -Wsign-conversion # warn on sign conversions
+ -Wnull-dereference # warn if a null dereference is detected
+ -Wdouble-promotion # warn if float is implicit promoted to double
+ -Wformat=2 # warn on security issues around functions that format output (ie printf)
+ )
+
+ set(GCC_WARNINGS
+ ${CLANG_WARNINGS}
+ -Wmisleading-indentation # warn if indentation implies blocks where blocks do not exist
+ -Wduplicated-cond # warn if if / else chain has duplicated conditions
+ -Wduplicated-branches # warn if if / else branches have duplicated code
+ -Wlogical-op # warn about logical operations being used where bitwise were probably wanted
+ -Wuseless-cast # warn if you perform a cast to the same type
+ )
+
+ if(MSVC)
+ set(PROJECT_WARNINGS ${MSVC_WARNINGS})
+ elseif(CMAKE_CXX_COMPILER_ID MATCHES ".*Clang")
+ set(PROJECT_WARNINGS ${CLANG_WARNINGS})
+ elseif(CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
+ set(PROJECT_WARNINGS ${GCC_WARNINGS})
+ else()
+ message(AUTHOR_WARNING "No compiler warnings set for '${CMAKE_CXX_COMPILER_ID}' compiler.")
+ endif()
+
+ get_target_property(type ${project_name} TYPE)
+ if (${type} STREQUAL "INTERFACE_LIBRARY")
+ target_compile_options(${project_name} INTERFACE ${PROJECT_WARNINGS})
+ else()
+ target_compile_options(${project_name} PRIVATE ${PROJECT_WARNINGS})
+ endif()
+endfunction()
+
+# This function will prevent in-source builds
+function(AssureOutOfSourceBuilds)
+ # make sure the user doesn't play dirty with symlinks
+ get_filename_component(srcdir "${CMAKE_SOURCE_DIR}" REALPATH)
+ get_filename_component(bindir "${CMAKE_BINARY_DIR}" REALPATH)
+
+ # disallow in-source builds
+ if("${srcdir}" STREQUAL "${bindir}")
+ message("######################################################")
+ message("Warning: in-source builds are disabled")
+ message("Please create a separate build directory and run cmake from there")
+ message("######################################################")
+ message(FATAL_ERROR "Quitting configuration")
+ endif()
+endfunction()
+
+option(ALLOW_IN_SOURCE_BUILD "Allow building in your source folder. Strongly discouraged" OFF)
+if(NOT ALLOW_IN_SOURCE_BUILD)
+ assureoutofsourcebuilds()
+endif()
+
+function(enable_sanitizers project_name)
+
+ if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU" OR CMAKE_CXX_COMPILER_ID MATCHES ".*Clang")
+ option(ENABLE_COVERAGE "Enable coverage reporting for gcc/clang" FALSE)
+
+ if(ENABLE_COVERAGE)
+ target_compile_options(${project_name} INTERFACE --coverage -O0 -g)
+ target_link_libraries(${project_name} INTERFACE --coverage)
+ endif()
+
+ set(SANITIZERS "")
+
+ option(ENABLE_SANITIZER_ADDRESS "Enable address sanitizer" FALSE)
+ if(ENABLE_SANITIZER_ADDRESS)
+ list(APPEND SANITIZERS "address")
+ endif()
+
+ option(ENABLE_SANITIZER_LEAK "Enable leak sanitizer" FALSE)
+ if(ENABLE_SANITIZER_LEAK)
+ list(APPEND SANITIZERS "leak")
+ endif()
+
+ option(ENABLE_SANITIZER_UNDEFINED_BEHAVIOR "Enable undefined behavior sanitizer" FALSE)
+ if(ENABLE_SANITIZER_UNDEFINED_BEHAVIOR)
+ list(APPEND SANITIZERS "undefined")
+ endif()
+
+ option(ENABLE_SANITIZER_THREAD "Enable thread sanitizer" FALSE)
+ if(ENABLE_SANITIZER_THREAD)
+ if("address" IN_LIST SANITIZERS OR "leak" IN_LIST SANITIZERS)
+ message(WARNING "Thread sanitizer does not work with Address and Leak sanitizer enabled")
+ else()
+ list(APPEND SANITIZERS "thread")
+ endif()
+ endif()
+
+ option(ENABLE_SANITIZER_MEMORY "Enable memory sanitizer" FALSE)
+ if(ENABLE_SANITIZER_MEMORY AND CMAKE_CXX_COMPILER_ID MATCHES ".*Clang")
+ if("address" IN_LIST SANITIZERS
+ OR "thread" IN_LIST SANITIZERS
+ OR "leak" IN_LIST SANITIZERS)
+ message(WARNING "Memory sanitizer does not work with Address, Thread and Leak sanitizer enabled")
+ else()
+ list(APPEND SANITIZERS "memory")
+ endif()
+ endif()
+
+ list(
+ JOIN
+ SANITIZERS
+ ","
+ LIST_OF_SANITIZERS)
+
+ endif()
+
+ if(LIST_OF_SANITIZERS)
+ if(NOT
+ "${LIST_OF_SANITIZERS}"
+ STREQUAL
+ "")
+ target_compile_options(${project_name} INTERFACE -fsanitize=${LIST_OF_SANITIZERS})
+ target_link_options(${project_name} INTERFACE -fsanitize=${LIST_OF_SANITIZERS})
+ endif()
+ endif()
+
+endfunction()
+
+option(ENABLE_CPPCHECK "Enable static analysis with cppcheck" OFF)
+option(ENABLE_CLANG_TIDY "Enable static analysis with clang-tidy" OFF)
+option(ENABLE_INCLUDE_WHAT_YOU_USE "Enable static analysis with include-what-you-use" OFF)
+
+if(ENABLE_CPPCHECK)
+ find_program(CPPCHECK cppcheck)
+ if(CPPCHECK)
+ message(STATUS "Using cppcheck")
+ set(CMAKE_CXX_CPPCHECK
+ ${CPPCHECK}
+ --suppress=missingInclude
+ --enable=all
+ --inline-suppr
+ --inconclusive
+ -i
+ ${CMAKE_SOURCE_DIR}/imgui/lib)
+ else()
+ message(WARNING "cppcheck requested but executable not found")
+ endif()
+endif()
+
+if(ENABLE_CLANG_TIDY)
+ find_program(CLANGTIDY clang-tidy)
+ if(CLANGTIDY)
+ message(STATUS "Using clang-tidy")
+ set(CMAKE_CXX_CLANG_TIDY ${CLANGTIDY} -extra-arg=-Wno-unknown-warning-option)
+ else()
+ message(WARNING "clang-tidy requested but executable not found")
+ endif()
+endif()
+
+if(ENABLE_INCLUDE_WHAT_YOU_USE)
+ find_program(INCLUDE_WHAT_YOU_USE include-what-you-use)
+ if(INCLUDE_WHAT_YOU_USE)
+ message(STATUS "Using include-what-you-use")
+ set(CMAKE_CXX_INCLUDE_WHAT_YOU_USE ${INCLUDE_WHAT_YOU_USE})
+ else()
+ message(WARNING "include-what-you-use requested but executable not found")
+ endif()
+endif() \ No newline at end of file
diff --git a/conanfile.py b/conanfile.py
new file mode 100644
index 000000000..c24806e1c
--- /dev/null
+++ b/conanfile.py
@@ -0,0 +1,37 @@
+from conan import ConanFile
+from conan.tools.cmake import CMakeToolchain, CMakeDeps
+
+
+required_conan_version = ">=1.46.2"
+
+
+class CuraBuildEnvironemtConan(ConanFile):
+ name = "cura-build-environment"
+ description = "Building Cura dependencies"
+ topics = ("conan", "python", "pypi", "pip")
+ settings = "os", "compiler", "build_type", "arch"
+ build_policy = "missing"
+
+ def configure(self):
+ self.options["boost"].header_only = True
+
+ def requirements(self):
+ self.requires("protobuf/3.17.1")
+ self.requires("clipper/6.4.2")
+ self.requires("boost/1.78.0")
+ self.requires("gtest/1.8.1")
+ self.requires("rapidjson/1.1.0")
+ self.requires("stb/20200203")
+
+ def generate(self):
+ cmake = CMakeDeps(self)
+ cmake.generate()
+
+ tc = CMakeToolchain(self)
+
+ # Don't use Visual Studio as the CMAKE_GENERATOR
+ if self.settings.compiler == "Visual Studio":
+ tc.blocks["generic_system"].values["generator_platform"] = None
+ tc.blocks["generic_system"].values["toolset"] = None
+
+ tc.generate()
diff --git a/libs/clipper/clipper.cpp b/libs/clipper/clipper.cpp
index 9d5caa18b..3701e9d70 100644
--- a/libs/clipper/clipper.cpp
+++ b/libs/clipper/clipper.cpp
@@ -38,9 +38,7 @@
* *
*******************************************************************************/
-#include "clipper.hpp"
-#include <cmath>
-#include <vector>
+#include "include/polyclipping/clipper.hpp"
#include <algorithm>
#include <stdexcept>
#include <cstring>
diff --git a/libs/clipper/clipper.hpp b/libs/clipper/include/polyclipping/clipper.hpp
index df1f8137d..5a19617bb 100644
--- a/libs/clipper/clipper.hpp
+++ b/libs/clipper/include/polyclipping/clipper.hpp
@@ -1,406 +1,406 @@
-/*******************************************************************************
-* *
-* Author : Angus Johnson *
-* Version : 6.4.2 *
-* Date : 27 February 2017 *
-* Website : http://www.angusj.com *
-* Copyright : Angus Johnson 2010-2017 *
-* *
-* License: *
-* Use, modification & distribution is subject to Boost Software License Ver 1. *
-* http://www.boost.org/LICENSE_1_0.txt *
-* *
-* Attributions: *
-* The code in this library is an extension of Bala Vatti's clipping algorithm: *
-* "A generic solution to polygon clipping" *
-* Communications of the ACM, Vol 35, Issue 7 (July 1992) pp 56-63. *
-* http://portal.acm.org/citation.cfm?id=129906 *
-* *
-* Computer graphics and geometric modeling: implementation and algorithms *
-* By Max K. Agoston *
-* Springer; 1 edition (January 4, 2005) *
-* http://books.google.com/books?q=vatti+clipping+agoston *
-* *
-* See also: *
-* "Polygon Offsetting by Computing Winding Numbers" *
-* Paper no. DETC2005-85513 pp. 565-575 *
-* ASME 2005 International Design Engineering Technical Conferences *
-* and Computers and Information in Engineering Conference (IDETC/CIE2005) *
-* September 24-28, 2005 , Long Beach, California, USA *
-* http://www.me.berkeley.edu/~mcmains/pubs/DAC05OffsetPolygon.pdf *
-* *
-*******************************************************************************/
-
-#ifndef clipper_hpp
-#define clipper_hpp
-
-#define CLIPPER_VERSION "6.4.2"
-
-//use_int32: When enabled 32bit ints are used instead of 64bit ints. This
-//improve performance but coordinate values are limited to the range +/- 46340
-//#define use_int32
-
-//use_xyz: adds a Z member to IntPoint. Adds a minor cost to perfomance.
-//#define use_xyz
-
-//use_lines: Enables line clipping. Adds a very minor cost to performance.
-#define use_lines
-
-//use_deprecated: Enables temporary support for the obsolete functions
-//#define use_deprecated
-
-#include <vector>
-#include <list>
-#include <set>
-#include <stdexcept>
-#include <cstring>
-#include <cstdlib>
-#include <ostream>
-#include <functional>
-#include <queue>
-
-namespace ClipperLib {
-
-enum ClipType { ctIntersection, ctUnion, ctDifference, ctXor };
-enum PolyType { ptSubject, ptClip };
-//By far the most widely used winding rules for polygon filling are
-//EvenOdd & NonZero (GDI, GDI+, XLib, OpenGL, Cairo, AGG, Quartz, SVG, Gr32)
-//Others rules include Positive, Negative and ABS_GTR_EQ_TWO (only in OpenGL)
-//see http://glprogramming.com/red/chapter11.html
-enum PolyFillType { pftEvenOdd, pftNonZero, pftPositive, pftNegative };
-
-#ifdef use_int32
- typedef int cInt;
- static cInt const loRange = 0x7FFF;
- static cInt const hiRange = 0x7FFF;
-#else
- typedef signed long long cInt;
- static cInt const loRange = 0x3FFFFFFF;
- static cInt const hiRange = 0x3FFFFFFFFFFFFFFFLL;
- typedef signed long long long64; //used by Int128 class
- typedef unsigned long long ulong64;
-
-#endif
-
-struct IntPoint {
- cInt X;
- cInt Y;
-#ifdef use_xyz
- cInt Z;
- IntPoint(cInt x = 0, cInt y = 0, cInt z = 0): X(x), Y(y), Z(z) {};
-#else
- IntPoint(cInt x = 0, cInt y = 0): X(x), Y(y) {};
-#endif
-
- friend inline bool operator== (const IntPoint& a, const IntPoint& b)
- {
- return a.X == b.X && a.Y == b.Y;
- }
- friend inline bool operator!= (const IntPoint& a, const IntPoint& b)
- {
- return a.X != b.X || a.Y != b.Y;
- }
-};
-//------------------------------------------------------------------------------
-
-typedef std::vector< IntPoint > Path;
-typedef std::vector< Path > Paths;
-
-inline Path& operator <<(Path& poly, const IntPoint& p) {poly.push_back(p); return poly;}
-inline Paths& operator <<(Paths& polys, const Path& p) {polys.push_back(p); return polys;}
-
-std::ostream& operator <<(std::ostream &s, const IntPoint &p);
-std::ostream& operator <<(std::ostream &s, const Path &p);
-std::ostream& operator <<(std::ostream &s, const Paths &p);
-
-struct DoublePoint
-{
- double X;
- double Y;
- DoublePoint(double x = 0, double y = 0) : X(x), Y(y) {}
- DoublePoint(IntPoint ip) : X((double)ip.X), Y((double)ip.Y) {}
-};
-//------------------------------------------------------------------------------
-
-#ifdef use_xyz
-typedef void (*ZFillCallback)(IntPoint& e1bot, IntPoint& e1top, IntPoint& e2bot, IntPoint& e2top, IntPoint& pt);
-#endif
-
-enum InitOptions {ioReverseSolution = 1, ioStrictlySimple = 2, ioPreserveCollinear = 4};
-enum JoinType {jtSquare, jtRound, jtMiter};
-enum EndType {etClosedPolygon, etClosedLine, etOpenButt, etOpenSquare, etOpenRound};
-
-class PolyNode;
-typedef std::vector< PolyNode* > PolyNodes;
-
-class PolyNode
-{
-public:
- PolyNode();
- virtual ~PolyNode(){};
- Path Contour;
- PolyNodes Childs;
- PolyNode* Parent;
- PolyNode* GetNext() const;
- bool IsHole() const;
- bool IsOpen() const;
- int ChildCount() const;
-private:
- //PolyNode& operator =(PolyNode& other);
- unsigned Index; //node index in Parent.Childs
- bool m_IsOpen;
- JoinType m_jointype;
- EndType m_endtype;
- PolyNode* GetNextSiblingUp() const;
- void AddChild(PolyNode& child);
- friend class Clipper; //to access Index
- friend class ClipperOffset;
-};
-
-class PolyTree: public PolyNode
-{
-public:
- ~PolyTree(){ Clear(); };
- PolyNode* GetFirst() const;
- void Clear();
- int Total() const;
-private:
- //PolyTree& operator =(PolyTree& other);
- PolyNodes AllNodes;
- friend class Clipper; //to access AllNodes
-};
-
-bool Orientation(const Path &poly);
-double Area(const Path &poly);
-int PointInPolygon(const IntPoint &pt, const Path &path);
-
-void SimplifyPolygon(const Path &in_poly, Paths &out_polys, PolyFillType fillType = pftEvenOdd);
-void SimplifyPolygons(const Paths &in_polys, Paths &out_polys, PolyFillType fillType = pftEvenOdd);
-void SimplifyPolygons(Paths &polys, PolyFillType fillType = pftEvenOdd);
-
-void CleanPolygon(const Path& in_poly, Path& out_poly, double distance = 1.415);
-void CleanPolygon(Path& poly, double distance = 1.415);
-void CleanPolygons(const Paths& in_polys, Paths& out_polys, double distance = 1.415);
-void CleanPolygons(Paths& polys, double distance = 1.415);
-
-void MinkowskiSum(const Path& pattern, const Path& path, Paths& solution, bool pathIsClosed);
-void MinkowskiSum(const Path& pattern, const Paths& paths, Paths& solution, bool pathIsClosed);
-void MinkowskiDiff(const Path& poly1, const Path& poly2, Paths& solution);
-
-void PolyTreeToPaths(const PolyTree& polytree, Paths& paths);
-void ClosedPathsFromPolyTree(const PolyTree& polytree, Paths& paths);
-void OpenPathsFromPolyTree(PolyTree& polytree, Paths& paths);
-
-void ReversePath(Path& p);
-void ReversePaths(Paths& p);
-
-struct IntRect { cInt left; cInt top; cInt right; cInt bottom; };
-
-//enums that are used internally ...
-enum EdgeSide { esLeft = 1, esRight = 2};
-
-//forward declarations (for stuff used internally) ...
-struct TEdge;
-struct IntersectNode;
-struct LocalMinimum;
-struct OutPt;
-struct OutRec;
-struct Join;
-
-typedef std::vector < OutRec* > PolyOutList;
-typedef std::vector < TEdge* > EdgeList;
-typedef std::vector < Join* > JoinList;
-typedef std::vector < IntersectNode* > IntersectList;
-
-//------------------------------------------------------------------------------
-
-//ClipperBase is the ancestor to the Clipper class. It should not be
-//instantiated directly. This class simply abstracts the conversion of sets of
-//polygon coordinates into edge objects that are stored in a LocalMinima list.
-class ClipperBase
-{
-public:
- ClipperBase();
- virtual ~ClipperBase();
- virtual bool AddPath(const Path &pg, PolyType PolyTyp, bool Closed);
- bool AddPaths(const Paths &ppg, PolyType PolyTyp, bool Closed);
- virtual void Clear();
- IntRect GetBounds();
- bool PreserveCollinear() {return m_PreserveCollinear;};
- void PreserveCollinear(bool value) {m_PreserveCollinear = value;};
-protected:
- void DisposeLocalMinimaList();
- TEdge* AddBoundsToLML(TEdge *e, bool IsClosed);
- virtual void Reset();
- TEdge* ProcessBound(TEdge* E, bool IsClockwise);
- void InsertScanbeam(const cInt Y);
- bool PopScanbeam(cInt &Y);
- bool LocalMinimaPending();
- bool PopLocalMinima(cInt Y, const LocalMinimum *&locMin);
- OutRec* CreateOutRec();
- void DisposeAllOutRecs();
- void DisposeOutRec(PolyOutList::size_type index);
- void SwapPositionsInAEL(TEdge *edge1, TEdge *edge2);
- void DeleteFromAEL(TEdge *e);
- void UpdateEdgeIntoAEL(TEdge *&e);
-
- typedef std::vector<LocalMinimum> MinimaList;
- MinimaList::iterator m_CurrentLM;
- MinimaList m_MinimaList;
-
- bool m_UseFullRange;
- EdgeList m_edges;
- bool m_PreserveCollinear;
- bool m_HasOpenPaths;
- PolyOutList m_PolyOuts;
- TEdge *m_ActiveEdges;
-
- typedef std::priority_queue<cInt> ScanbeamList;
- ScanbeamList m_Scanbeam;
-};
-//------------------------------------------------------------------------------
-
-class Clipper : public virtual ClipperBase
-{
-public:
- Clipper(int initOptions = 0);
- bool Execute(ClipType clipType,
- Paths &solution,
- PolyFillType fillType = pftEvenOdd);
- bool Execute(ClipType clipType,
- Paths &solution,
- PolyFillType subjFillType,
- PolyFillType clipFillType);
- bool Execute(ClipType clipType,
- PolyTree &polytree,
- PolyFillType fillType = pftEvenOdd);
- bool Execute(ClipType clipType,
- PolyTree &polytree,
- PolyFillType subjFillType,
- PolyFillType clipFillType);
- bool ReverseSolution() { return m_ReverseOutput; };
- void ReverseSolution(bool value) {m_ReverseOutput = value;};
- bool StrictlySimple() {return m_StrictSimple;};
- void StrictlySimple(bool value) {m_StrictSimple = value;};
- //set the callback function for z value filling on intersections (otherwise Z is 0)
-#ifdef use_xyz
- void ZFillFunction(ZFillCallback zFillFunc);
-#endif
-protected:
- virtual bool ExecuteInternal();
-private:
- JoinList m_Joins;
- JoinList m_GhostJoins;
- IntersectList m_IntersectList;
- ClipType m_ClipType;
- typedef std::list<cInt> MaximaList;
- MaximaList m_Maxima;
- TEdge *m_SortedEdges;
- bool m_ExecuteLocked;
- PolyFillType m_ClipFillType;
- PolyFillType m_SubjFillType;
- bool m_ReverseOutput;
- bool m_UsingPolyTree;
- bool m_StrictSimple;
-#ifdef use_xyz
- ZFillCallback m_ZFill; //custom callback
-#endif
- void SetWindingCount(TEdge& edge);
- bool IsEvenOddFillType(const TEdge& edge) const;
- bool IsEvenOddAltFillType(const TEdge& edge) const;
- void InsertLocalMinimaIntoAEL(const cInt botY);
- void InsertEdgeIntoAEL(TEdge *edge, TEdge* startEdge);
- void AddEdgeToSEL(TEdge *edge);
- bool PopEdgeFromSEL(TEdge *&edge);
- void CopyAELToSEL();
- void DeleteFromSEL(TEdge *e);
- void SwapPositionsInSEL(TEdge *edge1, TEdge *edge2);
- bool IsContributing(const TEdge& edge) const;
- bool IsTopHorz(const cInt XPos);
- void DoMaxima(TEdge *e);
- void ProcessHorizontals();
- void ProcessHorizontal(TEdge *horzEdge);
- void AddLocalMaxPoly(TEdge *e1, TEdge *e2, const IntPoint &pt);
- OutPt* AddLocalMinPoly(TEdge *e1, TEdge *e2, const IntPoint &pt);
- OutRec* GetOutRec(int idx);
- void AppendPolygon(TEdge *e1, TEdge *e2);
- void IntersectEdges(TEdge *e1, TEdge *e2, IntPoint &pt);
- OutPt* AddOutPt(TEdge *e, const IntPoint &pt);
- OutPt* GetLastOutPt(TEdge *e);
- bool ProcessIntersections(const cInt topY);
- void BuildIntersectList(const cInt topY);
- void ProcessIntersectList();
- void ProcessEdgesAtTopOfScanbeam(const cInt topY);
- void BuildResult(Paths& polys);
- void BuildResult2(PolyTree& polytree);
- void SetHoleState(TEdge *e, OutRec *outrec);
- void DisposeIntersectNodes();
- bool FixupIntersectionOrder();
- void FixupOutPolygon(OutRec &outrec);
- void FixupOutPolyline(OutRec &outrec);
- bool IsHole(TEdge *e);
- bool FindOwnerFromSplitRecs(OutRec &outRec, OutRec *&currOrfl);
- void FixHoleLinkage(OutRec &outrec);
- void AddJoin(OutPt *op1, OutPt *op2, const IntPoint offPt);
- void ClearJoins();
- void ClearGhostJoins();
- void AddGhostJoin(OutPt *op, const IntPoint offPt);
- bool JoinPoints(Join *j, OutRec* outRec1, OutRec* outRec2);
- void JoinCommonEdges();
- void DoSimplePolygons();
- void FixupFirstLefts1(OutRec* OldOutRec, OutRec* NewOutRec);
- void FixupFirstLefts2(OutRec* InnerOutRec, OutRec* OuterOutRec);
- void FixupFirstLefts3(OutRec* OldOutRec, OutRec* NewOutRec);
-#ifdef use_xyz
- void SetZ(IntPoint& pt, TEdge& e1, TEdge& e2);
-#endif
-};
-//------------------------------------------------------------------------------
-
-class ClipperOffset
-{
-public:
- ClipperOffset(double miterLimit = 2.0, double roundPrecision = 0.25);
- ~ClipperOffset();
- void AddPath(const Path& path, JoinType joinType, EndType endType);
- void AddPaths(const Paths& paths, JoinType joinType, EndType endType);
- void Execute(Paths& solution, double delta);
- void Execute(PolyTree& solution, double delta);
- void Clear();
- double MiterLimit;
- double ArcTolerance;
-private:
- Paths m_destPolys;
- Path m_srcPoly;
- Path m_destPoly;
- std::vector<DoublePoint> m_normals;
- double m_delta, m_sinA, m_sin, m_cos;
- double m_miterLim, m_StepsPerRad;
- IntPoint m_lowest;
- PolyNode m_polyNodes;
-
- void FixOrientations();
- void DoOffset(double delta);
- void OffsetPoint(int j, int& k, JoinType jointype);
- void DoSquare(int j, int k);
- void DoMiter(int j, int k, double r);
- void DoRound(int j, int k);
-};
-//------------------------------------------------------------------------------
-
-class clipperException : public std::exception
-{
- public:
- clipperException(const char* description): m_descr(description) {}
- virtual ~clipperException() throw() {}
- virtual const char* what() const throw() {return m_descr.c_str();}
- private:
- std::string m_descr;
-};
-//------------------------------------------------------------------------------
-
-} //ClipperLib namespace
-
-#endif //clipper_hpp
-
-
+/*******************************************************************************
+* *
+* Author : Angus Johnson *
+* Version : 6.4.2 *
+* Date : 27 February 2017 *
+* Website : http://www.angusj.com *
+* Copyright : Angus Johnson 2010-2017 *
+* *
+* License: *
+* Use, modification & distribution is subject to Boost Software License Ver 1. *
+* http://www.boost.org/LICENSE_1_0.txt *
+* *
+* Attributions: *
+* The code in this library is an extension of Bala Vatti's clipping algorithm: *
+* "A generic solution to polygon clipping" *
+* Communications of the ACM, Vol 35, Issue 7 (July 1992) pp 56-63. *
+* http://portal.acm.org/citation.cfm?id=129906 *
+* *
+* Computer graphics and geometric modeling: implementation and algorithms *
+* By Max K. Agoston *
+* Springer; 1 edition (January 4, 2005) *
+* http://books.google.com/books?q=vatti+clipping+agoston *
+* *
+* See also: *
+* "Polygon Offsetting by Computing Winding Numbers" *
+* Paper no. DETC2005-85513 pp. 565-575 *
+* ASME 2005 International Design Engineering Technical Conferences *
+* and Computers and Information in Engineering Conference (IDETC/CIE2005) *
+* September 24-28, 2005 , Long Beach, California, USA *
+* http://www.me.berkeley.edu/~mcmains/pubs/DAC05OffsetPolygon.pdf *
+* *
+*******************************************************************************/
+
+#ifndef clipper_hpp
+#define clipper_hpp
+
+#define CLIPPER_VERSION "6.4.2"
+
+//use_int32: When enabled 32bit ints are used instead of 64bit ints. This
+//improve performance but coordinate values are limited to the range +/- 46340
+//#define use_int32
+
+//use_xyz: adds a Z member to IntPoint. Adds a minor cost to perfomance.
+//#define use_xyz
+
+//use_lines: Enables line clipping. Adds a very minor cost to performance.
+#define use_lines
+
+//use_deprecated: Enables temporary support for the obsolete functions
+//#define use_deprecated
+
+#include <vector>
+#include <list>
+#include <set>
+#include <stdexcept>
+#include <cstring>
+#include <cstdlib>
+#include <ostream>
+#include <functional>
+#include <queue>
+
+namespace ClipperLib {
+
+enum ClipType { ctIntersection, ctUnion, ctDifference, ctXor };
+enum PolyType { ptSubject, ptClip };
+//By far the most widely used winding rules for polygon filling are
+//EvenOdd & NonZero (GDI, GDI+, XLib, OpenGL, Cairo, AGG, Quartz, SVG, Gr32)
+//Others rules include Positive, Negative and ABS_GTR_EQ_TWO (only in OpenGL)
+//see http://glprogramming.com/red/chapter11.html
+enum PolyFillType { pftEvenOdd, pftNonZero, pftPositive, pftNegative };
+
+#ifdef use_int32
+ typedef int cInt;
+ static cInt const loRange = 0x7FFF;
+ static cInt const hiRange = 0x7FFF;
+#else
+ typedef signed long long cInt;
+ static cInt const loRange = 0x3FFFFFFF;
+ static cInt const hiRange = 0x3FFFFFFFFFFFFFFFLL;
+ typedef signed long long long64; //used by Int128 class
+ typedef unsigned long long ulong64;
+
+#endif
+
+struct IntPoint {
+ cInt X;
+ cInt Y;
+#ifdef use_xyz
+ cInt Z;
+ IntPoint(cInt x = 0, cInt y = 0, cInt z = 0): X(x), Y(y), Z(z) {};
+#else
+ IntPoint(cInt x = 0, cInt y = 0): X(x), Y(y) {};
+#endif
+
+ friend inline bool operator== (const IntPoint& a, const IntPoint& b)
+ {
+ return a.X == b.X && a.Y == b.Y;
+ }
+ friend inline bool operator!= (const IntPoint& a, const IntPoint& b)
+ {
+ return a.X != b.X || a.Y != b.Y;
+ }
+};
+//------------------------------------------------------------------------------
+
+typedef std::vector< IntPoint > Path;
+typedef std::vector< Path > Paths;
+
+inline Path& operator <<(Path& poly, const IntPoint& p) {poly.push_back(p); return poly;}
+inline Paths& operator <<(Paths& polys, const Path& p) {polys.push_back(p); return polys;}
+
+std::ostream& operator <<(std::ostream &s, const IntPoint &p);
+std::ostream& operator <<(std::ostream &s, const Path &p);
+std::ostream& operator <<(std::ostream &s, const Paths &p);
+
+struct DoublePoint
+{
+ double X;
+ double Y;
+ DoublePoint(double x = 0, double y = 0) : X(x), Y(y) {}
+ DoublePoint(IntPoint ip) : X((double)ip.X), Y((double)ip.Y) {}
+};
+//------------------------------------------------------------------------------
+
+#ifdef use_xyz
+typedef void (*ZFillCallback)(IntPoint& e1bot, IntPoint& e1top, IntPoint& e2bot, IntPoint& e2top, IntPoint& pt);
+#endif
+
+enum InitOptions {ioReverseSolution = 1, ioStrictlySimple = 2, ioPreserveCollinear = 4};
+enum JoinType {jtSquare, jtRound, jtMiter};
+enum EndType {etClosedPolygon, etClosedLine, etOpenButt, etOpenSquare, etOpenRound};
+
+class PolyNode;
+typedef std::vector< PolyNode* > PolyNodes;
+
+class PolyNode
+{
+public:
+ PolyNode();
+ virtual ~PolyNode(){};
+ Path Contour;
+ PolyNodes Childs;
+ PolyNode* Parent;
+ PolyNode* GetNext() const;
+ bool IsHole() const;
+ bool IsOpen() const;
+ int ChildCount() const;
+private:
+ //PolyNode& operator =(PolyNode& other);
+ unsigned Index; //node index in Parent.Childs
+ bool m_IsOpen;
+ JoinType m_jointype;
+ EndType m_endtype;
+ PolyNode* GetNextSiblingUp() const;
+ void AddChild(PolyNode& child);
+ friend class Clipper; //to access Index
+ friend class ClipperOffset;
+};
+
+class PolyTree: public PolyNode
+{
+public:
+ ~PolyTree(){ Clear(); };
+ PolyNode* GetFirst() const;
+ void Clear();
+ int Total() const;
+private:
+ //PolyTree& operator =(PolyTree& other);
+ PolyNodes AllNodes;
+ friend class Clipper; //to access AllNodes
+};
+
+bool Orientation(const Path &poly);
+double Area(const Path &poly);
+int PointInPolygon(const IntPoint &pt, const Path &path);
+
+void SimplifyPolygon(const Path &in_poly, Paths &out_polys, PolyFillType fillType = pftEvenOdd);
+void SimplifyPolygons(const Paths &in_polys, Paths &out_polys, PolyFillType fillType = pftEvenOdd);
+void SimplifyPolygons(Paths &polys, PolyFillType fillType = pftEvenOdd);
+
+void CleanPolygon(const Path& in_poly, Path& out_poly, double distance = 1.415);
+void CleanPolygon(Path& poly, double distance = 1.415);
+void CleanPolygons(const Paths& in_polys, Paths& out_polys, double distance = 1.415);
+void CleanPolygons(Paths& polys, double distance = 1.415);
+
+void MinkowskiSum(const Path& pattern, const Path& path, Paths& solution, bool pathIsClosed);
+void MinkowskiSum(const Path& pattern, const Paths& paths, Paths& solution, bool pathIsClosed);
+void MinkowskiDiff(const Path& poly1, const Path& poly2, Paths& solution);
+
+void PolyTreeToPaths(const PolyTree& polytree, Paths& paths);
+void ClosedPathsFromPolyTree(const PolyTree& polytree, Paths& paths);
+void OpenPathsFromPolyTree(PolyTree& polytree, Paths& paths);
+
+void ReversePath(Path& p);
+void ReversePaths(Paths& p);
+
+struct IntRect { cInt left; cInt top; cInt right; cInt bottom; };
+
+//enums that are used internally ...
+enum EdgeSide { esLeft = 1, esRight = 2};
+
+//forward declarations (for stuff used internally) ...
+struct TEdge;
+struct IntersectNode;
+struct LocalMinimum;
+struct OutPt;
+struct OutRec;
+struct Join;
+
+typedef std::vector < OutRec* > PolyOutList;
+typedef std::vector < TEdge* > EdgeList;
+typedef std::vector < Join* > JoinList;
+typedef std::vector < IntersectNode* > IntersectList;
+
+//------------------------------------------------------------------------------
+
+//ClipperBase is the ancestor to the Clipper class. It should not be
+//instantiated directly. This class simply abstracts the conversion of sets of
+//polygon coordinates into edge objects that are stored in a LocalMinima list.
+class ClipperBase
+{
+public:
+ ClipperBase();
+ virtual ~ClipperBase();
+ virtual bool AddPath(const Path &pg, PolyType PolyTyp, bool Closed);
+ bool AddPaths(const Paths &ppg, PolyType PolyTyp, bool Closed);
+ virtual void Clear();
+ IntRect GetBounds();
+ bool PreserveCollinear() {return m_PreserveCollinear;};
+ void PreserveCollinear(bool value) {m_PreserveCollinear = value;};
+protected:
+ void DisposeLocalMinimaList();
+ TEdge* AddBoundsToLML(TEdge *e, bool IsClosed);
+ virtual void Reset();
+ TEdge* ProcessBound(TEdge* E, bool IsClockwise);
+ void InsertScanbeam(const cInt Y);
+ bool PopScanbeam(cInt &Y);
+ bool LocalMinimaPending();
+ bool PopLocalMinima(cInt Y, const LocalMinimum *&locMin);
+ OutRec* CreateOutRec();
+ void DisposeAllOutRecs();
+ void DisposeOutRec(PolyOutList::size_type index);
+ void SwapPositionsInAEL(TEdge *edge1, TEdge *edge2);
+ void DeleteFromAEL(TEdge *e);
+ void UpdateEdgeIntoAEL(TEdge *&e);
+
+ typedef std::vector<LocalMinimum> MinimaList;
+ MinimaList::iterator m_CurrentLM;
+ MinimaList m_MinimaList;
+
+ bool m_UseFullRange;
+ EdgeList m_edges;
+ bool m_PreserveCollinear;
+ bool m_HasOpenPaths;
+ PolyOutList m_PolyOuts;
+ TEdge *m_ActiveEdges;
+
+ typedef std::priority_queue<cInt> ScanbeamList;
+ ScanbeamList m_Scanbeam;
+};
+//------------------------------------------------------------------------------
+
+class Clipper : public virtual ClipperBase
+{
+public:
+ Clipper(int initOptions = 0);
+ bool Execute(ClipType clipType,
+ Paths &solution,
+ PolyFillType fillType = pftEvenOdd);
+ bool Execute(ClipType clipType,
+ Paths &solution,
+ PolyFillType subjFillType,
+ PolyFillType clipFillType);
+ bool Execute(ClipType clipType,
+ PolyTree &polytree,
+ PolyFillType fillType = pftEvenOdd);
+ bool Execute(ClipType clipType,
+ PolyTree &polytree,
+ PolyFillType subjFillType,
+ PolyFillType clipFillType);
+ bool ReverseSolution() { return m_ReverseOutput; };
+ void ReverseSolution(bool value) {m_ReverseOutput = value;};
+ bool StrictlySimple() {return m_StrictSimple;};
+ void StrictlySimple(bool value) {m_StrictSimple = value;};
+ //set the callback function for z value filling on intersections (otherwise Z is 0)
+#ifdef use_xyz
+ void ZFillFunction(ZFillCallback zFillFunc);
+#endif
+protected:
+ virtual bool ExecuteInternal();
+private:
+ JoinList m_Joins;
+ JoinList m_GhostJoins;
+ IntersectList m_IntersectList;
+ ClipType m_ClipType;
+ typedef std::list<cInt> MaximaList;
+ MaximaList m_Maxima;
+ TEdge *m_SortedEdges;
+ bool m_ExecuteLocked;
+ PolyFillType m_ClipFillType;
+ PolyFillType m_SubjFillType;
+ bool m_ReverseOutput;
+ bool m_UsingPolyTree;
+ bool m_StrictSimple;
+#ifdef use_xyz
+ ZFillCallback m_ZFill; //custom callback
+#endif
+ void SetWindingCount(TEdge& edge);
+ bool IsEvenOddFillType(const TEdge& edge) const;
+ bool IsEvenOddAltFillType(const TEdge& edge) const;
+ void InsertLocalMinimaIntoAEL(const cInt botY);
+ void InsertEdgeIntoAEL(TEdge *edge, TEdge* startEdge);
+ void AddEdgeToSEL(TEdge *edge);
+ bool PopEdgeFromSEL(TEdge *&edge);
+ void CopyAELToSEL();
+ void DeleteFromSEL(TEdge *e);
+ void SwapPositionsInSEL(TEdge *edge1, TEdge *edge2);
+ bool IsContributing(const TEdge& edge) const;
+ bool IsTopHorz(const cInt XPos);
+ void DoMaxima(TEdge *e);
+ void ProcessHorizontals();
+ void ProcessHorizontal(TEdge *horzEdge);
+ void AddLocalMaxPoly(TEdge *e1, TEdge *e2, const IntPoint &pt);
+ OutPt* AddLocalMinPoly(TEdge *e1, TEdge *e2, const IntPoint &pt);
+ OutRec* GetOutRec(int idx);
+ void AppendPolygon(TEdge *e1, TEdge *e2);
+ void IntersectEdges(TEdge *e1, TEdge *e2, IntPoint &pt);
+ OutPt* AddOutPt(TEdge *e, const IntPoint &pt);
+ OutPt* GetLastOutPt(TEdge *e);
+ bool ProcessIntersections(const cInt topY);
+ void BuildIntersectList(const cInt topY);
+ void ProcessIntersectList();
+ void ProcessEdgesAtTopOfScanbeam(const cInt topY);
+ void BuildResult(Paths& polys);
+ void BuildResult2(PolyTree& polytree);
+ void SetHoleState(TEdge *e, OutRec *outrec);
+ void DisposeIntersectNodes();
+ bool FixupIntersectionOrder();
+ void FixupOutPolygon(OutRec &outrec);
+ void FixupOutPolyline(OutRec &outrec);
+ bool IsHole(TEdge *e);
+ bool FindOwnerFromSplitRecs(OutRec &outRec, OutRec *&currOrfl);
+ void FixHoleLinkage(OutRec &outrec);
+ void AddJoin(OutPt *op1, OutPt *op2, const IntPoint offPt);
+ void ClearJoins();
+ void ClearGhostJoins();
+ void AddGhostJoin(OutPt *op, const IntPoint offPt);
+ bool JoinPoints(Join *j, OutRec* outRec1, OutRec* outRec2);
+ void JoinCommonEdges();
+ void DoSimplePolygons();
+ void FixupFirstLefts1(OutRec* OldOutRec, OutRec* NewOutRec);
+ void FixupFirstLefts2(OutRec* InnerOutRec, OutRec* OuterOutRec);
+ void FixupFirstLefts3(OutRec* OldOutRec, OutRec* NewOutRec);
+#ifdef use_xyz
+ void SetZ(IntPoint& pt, TEdge& e1, TEdge& e2);
+#endif
+};
+//------------------------------------------------------------------------------
+
+class ClipperOffset
+{
+public:
+ ClipperOffset(double miterLimit = 2.0, double roundPrecision = 0.25);
+ ~ClipperOffset();
+ void AddPath(const Path& path, JoinType joinType, EndType endType);
+ void AddPaths(const Paths& paths, JoinType joinType, EndType endType);
+ void Execute(Paths& solution, double delta);
+ void Execute(PolyTree& solution, double delta);
+ void Clear();
+ double MiterLimit;
+ double ArcTolerance;
+private:
+ Paths m_destPolys;
+ Path m_srcPoly;
+ Path m_destPoly;
+ std::vector<DoublePoint> m_normals;
+ double m_delta, m_sinA, m_sin, m_cos;
+ double m_miterLim, m_StepsPerRad;
+ IntPoint m_lowest;
+ PolyNode m_polyNodes;
+
+ void FixOrientations();
+ void DoOffset(double delta);
+ void OffsetPoint(int j, int& k, JoinType jointype);
+ void DoSquare(int j, int k);
+ void DoMiter(int j, int k, double r);
+ void DoRound(int j, int k);
+};
+//------------------------------------------------------------------------------
+
+class clipperException : public std::exception
+{
+ public:
+ clipperException(const char* description): m_descr(description) {}
+ virtual ~clipperException() throw() {}
+ virtual const char* what() const throw() {return m_descr.c_str();}
+ private:
+ std::string m_descr;
+};
+//------------------------------------------------------------------------------
+
+} //ClipperLib namespace
+
+#endif //clipper_hpp
+
+
diff --git a/libs/rapidjson/allocators.h b/libs/rapidjson/include/rapidjson/allocators.h
index d68b74c11..9184f01d2 100644
--- a/libs/rapidjson/allocators.h
+++ b/libs/rapidjson/include/rapidjson/allocators.h
@@ -1,249 +1,249 @@
-// Tencent is pleased to support the open source community by making RapidJSON available.
-//
-// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
-//
-// Licensed under the MIT License (the "License"); you may not use this file except
-// in compliance with the License. You may obtain a copy of the License at
-//
-// http://opensource.org/licenses/MIT
-//
-// Unless required by applicable law or agreed to in writing, software distributed
-// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
-// CONDITIONS OF ANY KIND, either express or implied. See the License for the
-// specific language governing permissions and limitations under the License.
-
-#ifndef RAPIDJSON_ALLOCATORS_H_
-#define RAPIDJSON_ALLOCATORS_H_
-
-#include "rapidjson.h"
-
-RAPIDJSON_NAMESPACE_BEGIN
-
-///////////////////////////////////////////////////////////////////////////////
-// Allocator
-
-/*! \class rapidjson::Allocator
- \brief Concept for allocating, resizing and freeing memory block.
-
- Note that Malloc() and Realloc() are non-static but Free() is static.
-
- So if an allocator need to support Free(), it needs to put its pointer in
- the header of memory block.
-
-\code
-concept Allocator {
- static const bool kNeedFree; //!< Whether this allocator needs to call Free().
-
- // Allocate a memory block.
- // \param size of the memory block in bytes.
- // \returns pointer to the memory block.
- void* Malloc(size_t size);
-
- // Resize a memory block.
- // \param originalPtr The pointer to current memory block. Null pointer is permitted.
- // \param originalSize The current size in bytes. (Design issue: since some allocator may not book-keep this, explicitly pass to it can save memory.)
- // \param newSize the new size in bytes.
- void* Realloc(void* originalPtr, size_t originalSize, size_t newSize);
-
- // Free a memory block.
- // \param pointer to the memory block. Null pointer is permitted.
- static void Free(void *ptr);
-};
-\endcode
-*/
-
-///////////////////////////////////////////////////////////////////////////////
-// CrtAllocator
-
-//! C-runtime library allocator.
-/*! This class is just wrapper for standard C library memory routines.
- \note implements Allocator concept
-*/
-class CrtAllocator {
-public:
- static const bool kNeedFree = true;
- void* Malloc(size_t size) {
- if (size) // behavior of malloc(0) is implementation defined.
- return std::malloc(size);
- else
- return NULL; // standardize to returning NULL.
- }
- void* Realloc(void* originalPtr, size_t originalSize, size_t newSize) { (void)originalSize; return std::realloc(originalPtr, newSize); }
- static void Free(void *ptr) { std::free(ptr); }
-};
-
-///////////////////////////////////////////////////////////////////////////////
-// MemoryPoolAllocator
-
-//! Default memory allocator used by the parser and DOM.
-/*! This allocator allocate memory blocks from pre-allocated memory chunks.
-
- It does not free memory blocks. And Realloc() only allocate new memory.
-
- The memory chunks are allocated by BaseAllocator, which is CrtAllocator by default.
-
- User may also supply a buffer as the first chunk.
-
- If the user-buffer is full then additional chunks are allocated by BaseAllocator.
-
- The user-buffer is not deallocated by this allocator.
-
- \tparam BaseAllocator the allocator type for allocating memory chunks. Default is CrtAllocator.
- \note implements Allocator concept
-*/
-template <typename BaseAllocator = CrtAllocator>
-class MemoryPoolAllocator {
-public:
- static const bool kNeedFree = false; //!< Tell users that no need to call Free() with this allocator. (concept Allocator)
-
- //! Constructor with chunkSize.
- /*! \param chunkSize The size of memory chunk. The default is kDefaultChunkSize.
- \param baseAllocator The allocator for allocating memory chunks.
- */
- MemoryPoolAllocator(size_t chunkSize = kDefaultChunkCapacity, BaseAllocator* baseAllocator = 0) :
- chunkHead_(0), chunk_capacity_(chunkSize), userBuffer_(0), baseAllocator_(baseAllocator), ownBaseAllocator_(0)
- {
- }
-
- //! Constructor with user-supplied buffer.
- /*! The user buffer will be used firstly. When it is full, memory pool allocates new chunk with chunk size.
-
- The user buffer will not be deallocated when this allocator is destructed.
-
- \param buffer User supplied buffer.
- \param size Size of the buffer in bytes. It must at least larger than sizeof(ChunkHeader).
- \param chunkSize The size of memory chunk. The default is kDefaultChunkSize.
- \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)
- {
- RAPIDJSON_ASSERT(buffer != 0);
- RAPIDJSON_ASSERT(size > sizeof(ChunkHeader));
- chunkHead_ = reinterpret_cast<ChunkHeader*>(buffer);
- chunkHead_->capacity = size - sizeof(ChunkHeader);
- chunkHead_->size = 0;
- chunkHead_->next = 0;
- }
-
- //! Destructor.
- /*! This deallocates all memory chunks, excluding the user-supplied buffer.
- */
- ~MemoryPoolAllocator() {
- Clear();
- RAPIDJSON_DELETE(ownBaseAllocator_);
- }
-
- //! Deallocates all memory chunks, excluding the user-supplied buffer.
- void Clear() {
- while(chunkHead_ != 0 && chunkHead_ != userBuffer_) {
- ChunkHeader* next = chunkHead_->next;
- baseAllocator_->Free(chunkHead_);
- chunkHead_ = next;
- }
- }
-
- //! Computes the total capacity of allocated memory chunks.
- /*! \return total capacity in bytes.
- */
- size_t Capacity() const {
- size_t capacity = 0;
- for (ChunkHeader* c = chunkHead_; c != 0; c = c->next)
- capacity += c->capacity;
- return capacity;
- }
-
- //! Computes the memory blocks allocated.
- /*! \return total used bytes.
- */
- size_t Size() const {
- size_t size = 0;
- for (ChunkHeader* c = chunkHead_; c != 0; c = c->next)
- size += c->size;
- return size;
- }
-
- //! Allocates a memory block. (concept Allocator)
- void* Malloc(size_t size) {
- if (!size)
- return NULL;
-
- size = RAPIDJSON_ALIGN(size);
- if (chunkHead_ == 0 || chunkHead_->size + size > chunkHead_->capacity)
- AddChunk(chunk_capacity_ > size ? chunk_capacity_ : size);
-
- void *buffer = reinterpret_cast<char *>(chunkHead_ + 1) + chunkHead_->size;
- chunkHead_->size += size;
- return buffer;
- }
-
- //! Resizes a memory block (concept Allocator)
- void* Realloc(void* originalPtr, size_t originalSize, size_t newSize) {
- if (originalPtr == 0)
- return Malloc(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 == (char *)(chunkHead_ + 1) + chunkHead_->size - originalSize) {
- size_t increment = static_cast<size_t>(newSize - originalSize);
- increment = RAPIDJSON_ALIGN(increment);
- if (chunkHead_->size + increment <= chunkHead_->capacity) {
- chunkHead_->size += increment;
- return originalPtr;
- }
- }
-
- // Realloc process: allocate and copy memory, do not free original buffer.
- void* newBuffer = Malloc(newSize);
- RAPIDJSON_ASSERT(newBuffer != 0); // Do not handle out-of-memory explicitly.
- if (originalSize)
- std::memcpy(newBuffer, originalPtr, originalSize);
- return newBuffer;
- }
-
- //! Frees a memory block (concept Allocator)
- static void Free(void *ptr) { (void)ptr; } // Do nothing
-
-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.
- */
- void AddChunk(size_t capacity) {
- if (!baseAllocator_)
- ownBaseAllocator_ = baseAllocator_ = RAPIDJSON_NEW(BaseAllocator());
- ChunkHeader* chunk = reinterpret_cast<ChunkHeader*>(baseAllocator_->Malloc(sizeof(ChunkHeader) + capacity));
- chunk->capacity = capacity;
- chunk->size = 0;
- chunk->next = chunkHead_;
- chunkHead_ = chunk;
- }
-
- static const int kDefaultChunkCapacity = 64 * 1024; //!< Default chunk capacity.
-
- //! 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.
-};
-
-RAPIDJSON_NAMESPACE_END
-
-#endif // RAPIDJSON_ENCODINGS_H_
+// Tencent is pleased to support the open source community by making RapidJSON available.
+//
+// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
+//
+// Licensed under the MIT License (the "License"); you may not use this file except
+// in compliance with the License. You may obtain a copy of the License at
+//
+// http://opensource.org/licenses/MIT
+//
+// Unless required by applicable law or agreed to in writing, software distributed
+// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
+// CONDITIONS OF ANY KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations under the License.
+
+#ifndef RAPIDJSON_ALLOCATORS_H_
+#define RAPIDJSON_ALLOCATORS_H_
+
+#include "rapidjson.h"
+
+RAPIDJSON_NAMESPACE_BEGIN
+
+///////////////////////////////////////////////////////////////////////////////
+// Allocator
+
+/*! \class rapidjson::Allocator
+ \brief Concept for allocating, resizing and freeing memory block.
+
+ Note that Malloc() and Realloc() are non-static but Free() is static.
+
+ So if an allocator need to support Free(), it needs to put its pointer in
+ the header of memory block.
+
+\code
+concept Allocator {
+ static const bool kNeedFree; //!< Whether this allocator needs to call Free().
+
+ // Allocate a memory block.
+ // \param size of the memory block in bytes.
+ // \returns pointer to the memory block.
+ void* Malloc(size_t size);
+
+ // Resize a memory block.
+ // \param originalPtr The pointer to current memory block. Null pointer is permitted.
+ // \param originalSize The current size in bytes. (Design issue: since some allocator may not book-keep this, explicitly pass to it can save memory.)
+ // \param newSize the new size in bytes.
+ void* Realloc(void* originalPtr, size_t originalSize, size_t newSize);
+
+ // Free a memory block.
+ // \param pointer to the memory block. Null pointer is permitted.
+ static void Free(void *ptr);
+};
+\endcode
+*/
+
+///////////////////////////////////////////////////////////////////////////////
+// CrtAllocator
+
+//! C-runtime library allocator.
+/*! This class is just wrapper for standard C library memory routines.
+ \note implements Allocator concept
+*/
+class CrtAllocator {
+public:
+ static const bool kNeedFree = true;
+ void* Malloc(size_t size) {
+ if (size) // behavior of malloc(0) is implementation defined.
+ return std::malloc(size);
+ else
+ return NULL; // standardize to returning NULL.
+ }
+ void* Realloc(void* originalPtr, size_t originalSize, size_t newSize) { (void)originalSize; return std::realloc(originalPtr, newSize); }
+ static void Free(void *ptr) { std::free(ptr); }
+};
+
+///////////////////////////////////////////////////////////////////////////////
+// MemoryPoolAllocator
+
+//! Default memory allocator used by the parser and DOM.
+/*! This allocator allocate memory blocks from pre-allocated memory chunks.
+
+ It does not free memory blocks. And Realloc() only allocate new memory.
+
+ The memory chunks are allocated by BaseAllocator, which is CrtAllocator by default.
+
+ User may also supply a buffer as the first chunk.
+
+ If the user-buffer is full then additional chunks are allocated by BaseAllocator.
+
+ The user-buffer is not deallocated by this allocator.
+
+ \tparam BaseAllocator the allocator type for allocating memory chunks. Default is CrtAllocator.
+ \note implements Allocator concept
+*/
+template <typename BaseAllocator = CrtAllocator>
+class MemoryPoolAllocator {
+public:
+ static const bool kNeedFree = false; //!< Tell users that no need to call Free() with this allocator. (concept Allocator)
+
+ //! Constructor with chunkSize.
+ /*! \param chunkSize The size of memory chunk. The default is kDefaultChunkSize.
+ \param baseAllocator The allocator for allocating memory chunks.
+ */
+ MemoryPoolAllocator(size_t chunkSize = kDefaultChunkCapacity, BaseAllocator* baseAllocator = 0) :
+ chunkHead_(0), chunk_capacity_(chunkSize), userBuffer_(0), baseAllocator_(baseAllocator), ownBaseAllocator_(0)
+ {
+ }
+
+ //! Constructor with user-supplied buffer.
+ /*! The user buffer will be used firstly. When it is full, memory pool allocates new chunk with chunk size.
+
+ The user buffer will not be deallocated when this allocator is destructed.
+
+ \param buffer User supplied buffer.
+ \param size Size of the buffer in bytes. It must at least larger than sizeof(ChunkHeader).
+ \param chunkSize The size of memory chunk. The default is kDefaultChunkSize.
+ \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)
+ {
+ RAPIDJSON_ASSERT(buffer != 0);
+ RAPIDJSON_ASSERT(size > sizeof(ChunkHeader));
+ chunkHead_ = reinterpret_cast<ChunkHeader*>(buffer);
+ chunkHead_->capacity = size - sizeof(ChunkHeader);
+ chunkHead_->size = 0;
+ chunkHead_->next = 0;
+ }
+
+ //! Destructor.
+ /*! This deallocates all memory chunks, excluding the user-supplied buffer.
+ */
+ ~MemoryPoolAllocator() {
+ Clear();
+ RAPIDJSON_DELETE(ownBaseAllocator_);
+ }
+
+ //! Deallocates all memory chunks, excluding the user-supplied buffer.
+ void Clear() {
+ while(chunkHead_ != 0 && chunkHead_ != userBuffer_) {
+ ChunkHeader* next = chunkHead_->next;
+ baseAllocator_->Free(chunkHead_);
+ chunkHead_ = next;
+ }
+ }
+
+ //! Computes the total capacity of allocated memory chunks.
+ /*! \return total capacity in bytes.
+ */
+ size_t Capacity() const {
+ size_t capacity = 0;
+ for (ChunkHeader* c = chunkHead_; c != 0; c = c->next)
+ capacity += c->capacity;
+ return capacity;
+ }
+
+ //! Computes the memory blocks allocated.
+ /*! \return total used bytes.
+ */
+ size_t Size() const {
+ size_t size = 0;
+ for (ChunkHeader* c = chunkHead_; c != 0; c = c->next)
+ size += c->size;
+ return size;
+ }
+
+ //! Allocates a memory block. (concept Allocator)
+ void* Malloc(size_t size) {
+ if (!size)
+ return NULL;
+
+ size = RAPIDJSON_ALIGN(size);
+ if (chunkHead_ == 0 || chunkHead_->size + size > chunkHead_->capacity)
+ AddChunk(chunk_capacity_ > size ? chunk_capacity_ : size);
+
+ void *buffer = reinterpret_cast<char *>(chunkHead_ + 1) + chunkHead_->size;
+ chunkHead_->size += size;
+ return buffer;
+ }
+
+ //! Resizes a memory block (concept Allocator)
+ void* Realloc(void* originalPtr, size_t originalSize, size_t newSize) {
+ if (originalPtr == 0)
+ return Malloc(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 == (char *)(chunkHead_ + 1) + chunkHead_->size - originalSize) {
+ size_t increment = static_cast<size_t>(newSize - originalSize);
+ increment = RAPIDJSON_ALIGN(increment);
+ if (chunkHead_->size + increment <= chunkHead_->capacity) {
+ chunkHead_->size += increment;
+ return originalPtr;
+ }
+ }
+
+ // Realloc process: allocate and copy memory, do not free original buffer.
+ void* newBuffer = Malloc(newSize);
+ RAPIDJSON_ASSERT(newBuffer != 0); // Do not handle out-of-memory explicitly.
+ if (originalSize)
+ std::memcpy(newBuffer, originalPtr, originalSize);
+ return newBuffer;
+ }
+
+ //! Frees a memory block (concept Allocator)
+ static void Free(void *ptr) { (void)ptr; } // Do nothing
+
+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.
+ */
+ void AddChunk(size_t capacity) {
+ if (!baseAllocator_)
+ ownBaseAllocator_ = baseAllocator_ = RAPIDJSON_NEW(BaseAllocator());
+ ChunkHeader* chunk = reinterpret_cast<ChunkHeader*>(baseAllocator_->Malloc(sizeof(ChunkHeader) + capacity));
+ chunk->capacity = capacity;
+ chunk->size = 0;
+ chunk->next = chunkHead_;
+ chunkHead_ = chunk;
+ }
+
+ static const int kDefaultChunkCapacity = 64 * 1024; //!< Default chunk capacity.
+
+ //! 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.
+};
+
+RAPIDJSON_NAMESPACE_END
+
+#endif // RAPIDJSON_ENCODINGS_H_
diff --git a/libs/rapidjson/document.h b/libs/rapidjson/include/rapidjson/document.h
index 8573f6b21..ccf64f98d 100644
--- a/libs/rapidjson/document.h
+++ b/libs/rapidjson/include/rapidjson/document.h
@@ -1,1965 +1,1965 @@
-// Tencent is pleased to support the open source community by making RapidJSON available.
-//
-// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
-//
-// Licensed under the MIT License (the "License"); you may not use this file except
-// in compliance with the License. You may obtain a copy of the License at
-//
-// http://opensource.org/licenses/MIT
-//
-// Unless required by applicable law or agreed to in writing, software distributed
-// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
-// CONDITIONS OF ANY KIND, either express or implied. See the License for the
-// specific language governing permissions and limitations under the License.
-
-#ifndef RAPIDJSON_DOCUMENT_H_
-#define RAPIDJSON_DOCUMENT_H_
-
-/*! \file document.h */
-
-#include "reader.h"
-#include "internal/meta.h"
-#include "internal/strfunc.h"
-#include <new> // placement new
-
-#ifdef _MSC_VER
-RAPIDJSON_DIAG_PUSH
-RAPIDJSON_DIAG_OFF(4127) // conditional expression is constant
-#elif defined(__GNUC__)
-RAPIDJSON_DIAG_PUSH
-RAPIDJSON_DIAG_OFF(effc++)
-#endif
-
-///////////////////////////////////////////////////////////////////////////////
-// 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
- \ref rapidjson::GenericValue with \c std::string are enabled, especially
- for construction and comparison.
-
- \hideinitializer
-*/
-#endif // !defined(RAPIDJSON_HAS_STDSTRING)
-
-#if RAPIDJSON_HAS_STDSTRING
-#include <string>
-#endif // RAPIDJSON_HAS_STDSTRING
-
-#ifndef RAPIDJSON_NOMEMBERITERATORCLASS
-#include <iterator> // std::iterator, std::random_access_iterator_tag
-#endif
-
-#if RAPIDJSON_HAS_CXX11_RVALUE_REFS
-#include <utility> // std::move
-#endif
-
-RAPIDJSON_NAMESPACE_BEGIN
-
-// Forward declaration.
-template <typename Encoding, typename Allocator>
-class GenericValue;
-
-//! Name-value pair in a JSON object value.
-/*!
- This class was internal to GenericValue. It used to be a inner struct.
- But a compiler (IBM XL C/C++ for AIX) have reported to have problem with that so it moved as a namespace scope struct.
- https://code.google.com/p/rapidjson/issues/detail?id=64
-*/
-template <typename Encoding, typename Allocator>
-struct GenericMember {
- GenericValue<Encoding, Allocator> name; //!< name of member (must be a string)
- GenericValue<Encoding, Allocator> value; //!< value of member.
-};
-
-///////////////////////////////////////////////////////////////////////////////
-// GenericMemberIterator
-
-#ifndef RAPIDJSON_NOMEMBERITERATORCLASS
-
-//! (Constant) member iterator for a JSON object value
-/*!
- \tparam Const Is this a constant iterator?
- \tparam Encoding Encoding of the value. (Even non-string values need to have the same encoding in a document)
- \tparam Allocator Allocator type for allocating memory of object, array and string.
-
- This class implements a Random Access Iterator for GenericMember elements
- of a GenericValue, see ISO/IEC 14882:2003(E) C++ standard, 24.1 [lib.iterator.requirements].
-
- \note This iterator implementation is mainly intended to avoid implicit
- conversions from iterator values to \c NULL,
- e.g. from GenericValue::FindMember.
-
- \note Define \c RAPIDJSON_NOMEMBERITERATORCLASS to fall back to a
- pointer-based implementation, if your platform doesn't provide
- the C++ <iterator> header.
-
- \see GenericMember, GenericValue::MemberIterator, GenericValue::ConstMemberIterator
- */
-template <bool Const, typename Encoding, typename Allocator>
-class GenericMemberIterator
- : public std::iterator<std::random_access_iterator_tag
- , typename internal::MaybeAddConst<Const,GenericMember<Encoding,Allocator> >::Type> {
-
- friend class GenericValue<Encoding,Allocator>;
- template <bool, typename, typename> friend class GenericMemberIterator;
-
- typedef GenericMember<Encoding,Allocator> PlainType;
- typedef typename internal::MaybeAddConst<Const,PlainType>::Type ValueType;
- typedef std::iterator<std::random_access_iterator_tag,ValueType> BaseType;
-
-public:
- //! Iterator type itself
- typedef GenericMemberIterator Iterator;
- //! Constant iterator type
- typedef GenericMemberIterator<true,Encoding,Allocator> ConstIterator;
- //! Non-constant iterator type
- typedef GenericMemberIterator<false,Encoding,Allocator> NonConstIterator;
-
- //! Pointer to (const) GenericMember
- typedef typename BaseType::pointer Pointer;
- //! Reference to (const) GenericMember
- typedef typename BaseType::reference Reference;
- //! Signed integer type (e.g. \c ptrdiff_t)
- typedef typename BaseType::difference_type DifferenceType;
-
- //! Default constructor (singular value)
- /*! Creates an iterator pointing to no element.
- \note All operations, except for comparisons, are undefined on such values.
- */
- GenericMemberIterator() : ptr_() {}
-
- //! Iterator conversions to more const
- /*!
- \param it (Non-const) iterator to copy from
-
- Allows the creation of an iterator from another GenericMemberIterator
- that is "less const". Especially, creating a non-constant iterator
- from a constant iterator are disabled:
- \li const -> non-const (not ok)
- \li const -> const (ok)
- \li non-const -> const (ok)
- \li non-const -> non-const (ok)
-
- \note If the \c Const template parameter is already \c false, this
- constructor effectively defines a regular copy-constructor.
- Otherwise, the copy constructor is implicitly defined.
- */
- GenericMemberIterator(const NonConstIterator & it) : ptr_(it.ptr_) {}
-
- //! @name stepping
- //@{
- Iterator& operator++(){ ++ptr_; return *this; }
- Iterator& operator--(){ --ptr_; return *this; }
- Iterator operator++(int){ Iterator old(*this); ++ptr_; return old; }
- Iterator operator--(int){ Iterator old(*this); --ptr_; return old; }
- //@}
-
- //! @name increment/decrement
- //@{
- Iterator operator+(DifferenceType n) const { return Iterator(ptr_+n); }
- Iterator operator-(DifferenceType n) const { return Iterator(ptr_-n); }
-
- Iterator& operator+=(DifferenceType n) { ptr_+=n; return *this; }
- Iterator& operator-=(DifferenceType n) { ptr_-=n; return *this; }
- //@}
-
- //! @name relations
- //@{
- bool operator==(ConstIterator that) const { return ptr_ == that.ptr_; }
- bool operator!=(ConstIterator that) const { return ptr_ != that.ptr_; }
- bool operator<=(ConstIterator that) const { return ptr_ <= that.ptr_; }
- bool operator>=(ConstIterator that) const { return ptr_ >= that.ptr_; }
- bool operator< (ConstIterator that) const { return ptr_ < that.ptr_; }
- bool operator> (ConstIterator that) const { return ptr_ > that.ptr_; }
- //@}
-
- //! @name dereference
- //@{
- Reference operator*() const { return *ptr_; }
- Pointer operator->() const { return ptr_; }
- Reference operator[](DifferenceType n) const { return ptr_[n]; }
- //@}
-
- //! Distance
- DifferenceType operator-(ConstIterator that) const { return ptr_-that.ptr_; }
-
-private:
- //! Internal constructor from plain pointer
- explicit GenericMemberIterator(Pointer p) : ptr_(p) {}
-
- Pointer ptr_; //!< raw pointer
-};
-
-#else // RAPIDJSON_NOMEMBERITERATORCLASS
-
-// class-based member iterator implementation disabled, use plain pointers
-
-template <bool Const, typename Encoding, typename Allocator>
-struct GenericMemberIterator;
-
-//! non-const GenericMemberIterator
-template <typename Encoding, typename Allocator>
-struct GenericMemberIterator<false,Encoding,Allocator> {
- //! use plain pointer as iterator type
- typedef GenericMember<Encoding,Allocator>* Iterator;
-};
-//! const GenericMemberIterator
-template <typename Encoding, typename Allocator>
-struct GenericMemberIterator<true,Encoding,Allocator> {
- //! use plain const pointer as iterator type
- typedef const GenericMember<Encoding,Allocator>* Iterator;
-};
-
-#endif // RAPIDJSON_NOMEMBERITERATORCLASS
-
-///////////////////////////////////////////////////////////////////////////////
-// GenericStringRef
-
-//! Reference to a constant string (not taking a copy)
-/*!
- \tparam CharType character type of the string
-
- This helper class is used to automatically infer constant string
- references for string literals, especially from \c const \b (!)
- character arrays.
-
- The main use is for creating JSON string values without copying the
- source string via an \ref Allocator. This requires that the referenced
- string pointers have a sufficient lifetime, which exceeds the lifetime
- of the associated GenericValue.
-
- \b Example
- \code
- Value v("foo"); // ok, no need to copy & calculate length
- const char foo[] = "foo";
- v.SetString(foo); // ok
-
- const char* bar = foo;
- // Value x(bar); // not ok, can't rely on bar's lifetime
- Value x(StringRef(bar)); // lifetime explicitly guaranteed by user
- Value y(StringRef(bar, 3)); // ok, explicitly pass length
- \endcode
-
- \see StringRef, GenericValue::SetString
-*/
-template<typename CharType>
-struct GenericStringRef {
- typedef CharType Ch; //!< character type of the string
-
- //! Create string reference from \c const character array
- /*!
- This constructor implicitly creates a constant string reference from
- a \c const character array. It has better performance than
- \ref StringRef(const CharType*) by inferring the string \ref length
- from the array length, and also supports strings containing null
- characters.
-
- \tparam N length of the string, automatically inferred
-
- \param str Constant character array, lifetime assumed to be longer
- than the use of the string in e.g. a GenericValue
-
- \post \ref s == str
-
- \note Constant complexity.
- \note There is a hidden, private overload to disallow references to
- non-const character arrays to be created via this constructor.
- By this, e.g. function-scope arrays used to be filled via
- \c snprintf are excluded from consideration.
- In such cases, the referenced string should be \b copied to the
- GenericValue instead.
- */
- template<SizeType N>
- GenericStringRef(const CharType (&str)[N]) RAPIDJSON_NOEXCEPT
- : s(str), length(N-1) {}
-
- //! Explicitly create string reference from \c const character pointer
- /*!
- This constructor can be used to \b explicitly create a reference to
- a constant string pointer.
-
- \see StringRef(const CharType*)
-
- \param str Constant character pointer, lifetime assumed to be longer
- than the use of the string in e.g. a GenericValue
-
- \post \ref s == str
-
- \note There is a hidden, private overload to disallow references to
- non-const character arrays to be created via this constructor.
- By this, e.g. function-scope arrays used to be filled via
- \c snprintf are excluded from consideration.
- In such cases, the referenced string should be \b copied to the
- GenericValue instead.
- */
- explicit GenericStringRef(const CharType* str)
- : s(str), length(internal::StrLen(str)){ RAPIDJSON_ASSERT(s != NULL); }
-
- //! Create constant string reference from pointer and length
- /*! \param str constant string, lifetime assumed to be longer than the use of the string in e.g. a GenericValue
- \param len length of the string, excluding the trailing NULL terminator
-
- \post \ref s == str && \ref length == len
- \note Constant complexity.
- */
- GenericStringRef(const CharType* str, SizeType len)
- : s(str), length(len) { RAPIDJSON_ASSERT(s != NULL); }
-
- GenericStringRef(const GenericStringRef& original) = default;
-
- //! implicit conversion to plain CharType pointer
- operator const Ch *() const { return s; }
-
- const Ch* const s; //!< plain CharType pointer
- const SizeType length; //!< length of the string (excluding the trailing NULL terminator)
-
-private:
- //! Disallow copy-assignment
- GenericStringRef operator=(const GenericStringRef&);
- //! Disallow construction from non-const array
- template<SizeType N>
- GenericStringRef(CharType (&str)[N]) /* = delete */;
-};
-
-//! Mark a character pointer as constant string
-/*! Mark a plain character pointer as a "string literal". This function
- can be used to avoid copying a character string to be referenced as a
- value in a JSON GenericValue object, if the string's lifetime is known
- to be valid long enough.
- \tparam CharType Character type of the string
- \param str Constant string, lifetime assumed to be longer than the use of the string in e.g. a GenericValue
- \return GenericStringRef string reference object
- \relatesalso GenericStringRef
-
- \see GenericValue::GenericValue(StringRefType), GenericValue::operator=(StringRefType), GenericValue::SetString(StringRefType), GenericValue::PushBack(StringRefType, Allocator&), GenericValue::AddMember
-*/
-template<typename CharType>
-inline GenericStringRef<CharType> StringRef(const CharType* str) {
- return GenericStringRef<CharType>(str, internal::StrLen(str));
-}
-
-//! Mark a character pointer as constant string
-/*! Mark a plain character pointer as a "string literal". This function
- can be used to avoid copying a character string to be referenced as a
- value in a JSON GenericValue object, if the string's lifetime is known
- to be valid long enough.
-
- This version has better performance with supplied length, and also
- supports string containing null characters.
-
- \tparam CharType character type of the string
- \param str Constant string, lifetime assumed to be longer than the use of the string in e.g. a GenericValue
- \param length The length of source string.
- \return GenericStringRef string reference object
- \relatesalso GenericStringRef
-*/
-template<typename CharType>
-inline GenericStringRef<CharType> StringRef(const CharType* str, size_t length) {
- return GenericStringRef<CharType>(str, SizeType(length));
-}
-
-#if RAPIDJSON_HAS_STDSTRING
-//! Mark a string object as constant string
-/*! Mark a string object (e.g. \c std::string) as a "string literal".
- This function can be used to avoid copying a string to be referenced as a
- value in a JSON GenericValue object, if the string's lifetime is known
- to be valid long enough.
-
- \tparam CharType character type of the string
- \param str Constant string, lifetime assumed to be longer than the use of the string in e.g. a GenericValue
- \return GenericStringRef string reference object
- \relatesalso GenericStringRef
- \note Requires the definition of the preprocessor symbol \ref RAPIDJSON_HAS_STDSTRING.
-*/
-template<typename CharType>
-inline GenericStringRef<CharType> StringRef(const std::basic_string<CharType>& str) {
- return GenericStringRef<CharType>(str.data(), SizeType(str.size()));
-}
-#endif
-
-///////////////////////////////////////////////////////////////////////////////
-// GenericValue type traits
-namespace internal {
-
-template <typename T, typename Encoding = void, typename Allocator = void>
-struct IsGenericValueImpl : FalseType {};
-
-// select candidates according to nested encoding and allocator types
-template <typename T> struct IsGenericValueImpl<T, typename Void<typename T::EncodingType>::Type, typename Void<typename T::AllocatorType>::Type>
- : IsBaseOf<GenericValue<typename T::EncodingType, typename T::AllocatorType>, T>::Type {};
-
-// helper to match arbitrary GenericValue instantiations, including derived classes
-template <typename T> struct IsGenericValue : IsGenericValueImpl<T>::Type {};
-
-} // namespace internal
-
-///////////////////////////////////////////////////////////////////////////////
-// GenericValue
-
-//! Represents a JSON value. Use Value for UTF8 encoding and default allocator.
-/*!
- A JSON value can be one of 7 types. This class is a variant type supporting
- these types.
-
- Use the Value if UTF8 and default allocator
-
- \tparam Encoding Encoding of the value. (Even non-string values need to have the same encoding in a document)
- \tparam Allocator Allocator type for allocating memory of object, array and string.
-*/
-template <typename Encoding, typename Allocator = MemoryPoolAllocator<> >
-class GenericValue {
-public:
- //! Name-value pair in an object.
- typedef GenericMember<Encoding, Allocator> Member;
- typedef Encoding EncodingType; //!< Encoding type from template parameter.
- typedef Allocator AllocatorType; //!< Allocator type from template parameter.
- typedef typename Encoding::Ch Ch; //!< Character type derived from Encoding.
- typedef GenericStringRef<Ch> StringRefType; //!< Reference to a constant string
- typedef typename GenericMemberIterator<false,Encoding,Allocator>::Iterator MemberIterator; //!< Member iterator for iterating in object.
- typedef typename GenericMemberIterator<true,Encoding,Allocator>::Iterator ConstMemberIterator; //!< Constant member iterator for iterating in object.
- typedef GenericValue* ValueIterator; //!< Value iterator for iterating in array.
- typedef const GenericValue* ConstValueIterator; //!< Constant value iterator for iterating in array.
-
- //!@name Constructors and destructor.
- //@{
-
- //! Default constructor creates a null value.
- GenericValue() RAPIDJSON_NOEXCEPT : data_(), flags_(kNullFlag) {}
-
-#if RAPIDJSON_HAS_CXX11_RVALUE_REFS
- //! Move constructor in C++11
- GenericValue(GenericValue&& rhs) RAPIDJSON_NOEXCEPT : data_(rhs.data_), flags_(rhs.flags_) {
- rhs.flags_ = kNullFlag; // give up contents
- }
-#endif
-
-private:
- //! Copy constructor is not permitted.
- GenericValue(const GenericValue& rhs);
-
-public:
-
- //! Constructor with JSON value type.
- /*! This creates a Value of specified type with default content.
- \param type Type of the value.
- \note Default content for number is zero.
- */
- explicit GenericValue(Type type) RAPIDJSON_NOEXCEPT : data_(), flags_() {
- static const unsigned defaultFlags[7] = {
- kNullFlag, kFalseFlag, kTrueFlag, kObjectFlag, kArrayFlag, kShortStringFlag,
- kNumberAnyFlag
- };
- RAPIDJSON_ASSERT(type <= kNumberType);
- flags_ = defaultFlags[type];
-
- // Use ShortString to store empty string.
- if (type == kStringType)
- data_.ss.SetLength(0);
- }
-
- //! Explicit copy constructor (with allocator)
- /*! Creates a copy of a Value by using the given Allocator
- \tparam SourceAllocator allocator of \c rhs
- \param rhs Value to copy from (read-only)
- \param allocator Allocator for allocating copied elements and buffers. Commonly use GenericDocument::GetAllocator().
- \see CopyFrom()
- */
- template< typename SourceAllocator >
- GenericValue(const GenericValue<Encoding, SourceAllocator>& rhs, Allocator & allocator);
-
- //! Constructor for boolean value.
- /*! \param b Boolean value
- \note This constructor is limited to \em real boolean values and rejects
- implicitly converted types like arbitrary pointers. Use an explicit cast
- to \c bool, if you want to construct a boolean JSON value in such cases.
- */
-#ifndef RAPIDJSON_DOXYGEN_RUNNING // hide SFINAE from Doxygen
- template <typename T>
- explicit GenericValue(T b, RAPIDJSON_ENABLEIF((internal::IsSame<T,bool>))) RAPIDJSON_NOEXCEPT
-#else
- explicit GenericValue(bool b) RAPIDJSON_NOEXCEPT
-#endif
- : data_(), flags_(b ? kTrueFlag : kFalseFlag) {
- // safe-guard against failing SFINAE
- RAPIDJSON_STATIC_ASSERT((internal::IsSame<bool,T>::Value));
- }
-
- //! Constructor for int value.
- explicit GenericValue(int i) RAPIDJSON_NOEXCEPT : data_(), flags_(kNumberIntFlag) {
- data_.n.i64 = i;
- if (i >= 0)
- flags_ |= kUintFlag | kUint64Flag;
- }
-
- //! Constructor for unsigned value.
- explicit GenericValue(unsigned u) RAPIDJSON_NOEXCEPT : data_(), flags_(kNumberUintFlag) {
- data_.n.u64 = u;
- if (!(u & 0x80000000))
- flags_ |= kIntFlag | kInt64Flag;
- }
-
- //! Constructor for int64_t value.
- explicit GenericValue(int64_t i64) RAPIDJSON_NOEXCEPT : data_(), flags_(kNumberInt64Flag) {
- data_.n.i64 = i64;
- if (i64 >= 0) {
- flags_ |= kNumberUint64Flag;
- if (!(static_cast<uint64_t>(i64) & RAPIDJSON_UINT64_C2(0xFFFFFFFF, 0x00000000)))
- flags_ |= kUintFlag;
- if (!(static_cast<uint64_t>(i64) & RAPIDJSON_UINT64_C2(0xFFFFFFFF, 0x80000000)))
- flags_ |= kIntFlag;
- }
- else if (i64 >= static_cast<int64_t>(RAPIDJSON_UINT64_C2(0xFFFFFFFF, 0x80000000)))
- flags_ |= kIntFlag;
- }
-
- //! Constructor for uint64_t value.
- explicit GenericValue(uint64_t u64) RAPIDJSON_NOEXCEPT : data_(), flags_(kNumberUint64Flag) {
- data_.n.u64 = u64;
- if (!(u64 & RAPIDJSON_UINT64_C2(0x80000000, 0x00000000)))
- flags_ |= kInt64Flag;
- if (!(u64 & RAPIDJSON_UINT64_C2(0xFFFFFFFF, 0x00000000)))
- flags_ |= kUintFlag;
- if (!(u64 & RAPIDJSON_UINT64_C2(0xFFFFFFFF, 0x80000000)))
- flags_ |= kIntFlag;
- }
-
- //! Constructor for double value.
- explicit GenericValue(double d) RAPIDJSON_NOEXCEPT : data_(), flags_(kNumberDoubleFlag) { data_.n.d = d; }
-
- //! Constructor for constant string (i.e. do not make a copy of string)
- GenericValue(const Ch* s, SizeType length) RAPIDJSON_NOEXCEPT : data_(), flags_() { SetStringRaw(StringRef(s, length)); }
-
- //! Constructor for constant string (i.e. do not make a copy of string)
- explicit GenericValue(StringRefType s) RAPIDJSON_NOEXCEPT : data_(), flags_() { SetStringRaw(s); }
-
- //! Constructor for copy-string (i.e. do make a copy of string)
- GenericValue(const Ch* s, SizeType length, Allocator& allocator) : data_(), flags_() { SetStringRaw(StringRef(s, length), allocator); }
-
- //! Constructor for copy-string (i.e. do make a copy of string)
- GenericValue(const Ch*s, Allocator& allocator) : data_(), flags_() { SetStringRaw(StringRef(s), allocator); }
-
-#if RAPIDJSON_HAS_STDSTRING
- //! Constructor for copy-string from a string object (i.e. do make a copy of string)
- /*! \note Requires the definition of the preprocessor symbol \ref RAPIDJSON_HAS_STDSTRING.
- */
- GenericValue(const std::basic_string<Ch>& s, Allocator& allocator) : data_(), flags_() { SetStringRaw(StringRef(s), allocator); }
-#endif
-
- //! Destructor.
- /*! Need to destruct elements of array, members of object, or copy-string.
- */
- ~GenericValue() {
- if (Allocator::kNeedFree) { // Shortcut by Allocator's trait
- switch(flags_) {
- case kArrayFlag:
- for (GenericValue* v = data_.a.elements; v != data_.a.elements + data_.a.size; ++v)
- v->~GenericValue();
- Allocator::Free(data_.a.elements);
- break;
-
- case kObjectFlag:
- for (MemberIterator m = MemberBegin(); m != MemberEnd(); ++m)
- m->~Member();
- Allocator::Free(data_.o.members);
- break;
-
- case kCopyStringFlag:
- Allocator::Free(const_cast<Ch*>(data_.s.str));
- break;
-
- default:
- break; // Do nothing for other types.
- }
- }
- }
-
- //@}
-
- //!@name Assignment operators
- //@{
-
- //! Assignment with move semantics.
- /*! \param rhs Source of the assignment. It will become a null value after assignment.
- */
- GenericValue& operator=(GenericValue& rhs) RAPIDJSON_NOEXCEPT {
- RAPIDJSON_ASSERT(this != &rhs);
- this->~GenericValue();
- RawAssign(rhs);
- return *this;
- }
-
-#if RAPIDJSON_HAS_CXX11_RVALUE_REFS
- //! Move assignment in C++11
- GenericValue& operator=(GenericValue&& rhs) RAPIDJSON_NOEXCEPT {
- return *this = rhs.Move();
- }
-#endif
-
- //! Assignment of constant string reference (no copy)
- /*! \param str Constant string reference to be assigned
- \note This overload is needed to avoid clashes with the generic primitive type assignment overload below.
- \see GenericStringRef, operator=(T)
- */
- GenericValue& operator=(StringRefType str) RAPIDJSON_NOEXCEPT {
- GenericValue s(str);
- return *this = s;
- }
-
- //! Assignment with primitive types.
- /*! \tparam T Either \ref Type, \c int, \c unsigned, \c int64_t, \c uint64_t
- \param value The value to be assigned.
-
- \note The source type \c T explicitly disallows all pointer types,
- especially (\c const) \ref Ch*. This helps avoiding implicitly
- referencing character strings with insufficient lifetime, use
- \ref SetString(const Ch*, Allocator&) (for copying) or
- \ref StringRef() (to explicitly mark the pointer as constant) instead.
- All other pointer types would implicitly convert to \c bool,
- use \ref SetBool() instead.
- */
- template <typename T>
- RAPIDJSON_DISABLEIF_RETURN((internal::IsPointer<T>), (GenericValue&))
- operator=(T value) {
- GenericValue v(value);
- return *this = v;
- }
-
- //! Deep-copy assignment from Value
- /*! Assigns a \b copy of the Value to the current Value object
- \tparam SourceAllocator Allocator type of \c rhs
- \param rhs Value to copy from (read-only)
- \param allocator Allocator to use for copying
- */
- template <typename SourceAllocator>
- GenericValue& CopyFrom(const GenericValue<Encoding, SourceAllocator>& rhs, Allocator& allocator) {
- RAPIDJSON_ASSERT((void*)this != (void const*)&rhs);
- this->~GenericValue();
- new (this) GenericValue(rhs, allocator);
- return *this;
- }
-
- //! Exchange the contents of this value with those of other.
- /*!
- \param other Another value.
- \note Constant complexity.
- */
- GenericValue& Swap(GenericValue& other) RAPIDJSON_NOEXCEPT {
- GenericValue temp;
- temp.RawAssign(*this);
- RawAssign(other);
- other.RawAssign(temp);
- return *this;
- }
-
- //! Prepare Value for move semantics
- /*! \return *this */
- GenericValue& Move() RAPIDJSON_NOEXCEPT { return *this; }
- //@}
-
- //!@name Equal-to and not-equal-to operators
- //@{
- //! Equal-to operator
- /*!
- \note If an object contains duplicated named member, comparing equality with any object is always \c false.
- \note Linear time complexity (number of all values in the subtree and total lengths of all strings).
- */
- template <typename SourceAllocator>
- bool operator==(const GenericValue<Encoding, SourceAllocator>& rhs) const {
- typedef GenericValue<Encoding, SourceAllocator> RhsType;
- if (GetType() != rhs.GetType())
- return false;
-
- switch (GetType()) {
- case kObjectType: // Warning: O(n^2) inner-loop
- if (data_.o.size != rhs.data_.o.size)
- return false;
- for (ConstMemberIterator lhsMemberItr = MemberBegin(); lhsMemberItr != MemberEnd(); ++lhsMemberItr) {
- typename RhsType::ConstMemberIterator rhsMemberItr = rhs.FindMember(lhsMemberItr->name);
- if (rhsMemberItr == rhs.MemberEnd() || lhsMemberItr->value != rhsMemberItr->value)
- return false;
- }
- return true;
-
- case kArrayType:
- if (data_.a.size != rhs.data_.a.size)
- return false;
- for (SizeType i = 0; i < data_.a.size; i++)
- if ((*this)[i] != rhs[i])
- return false;
- return true;
-
- case kStringType:
- return StringEqual(rhs);
-
- case kNumberType:
- if (IsDouble() || rhs.IsDouble()) {
- double a = GetDouble(); // May convert from integer to double.
- double b = rhs.GetDouble(); // Ditto
- return a >= b && a <= b; // Prevent -Wfloat-equal
- }
- else
- return data_.n.u64 == rhs.data_.n.u64;
-
- default: // kTrueType, kFalseType, kNullType
- return true;
- }
- }
-
- //! Equal-to operator with const C-string pointer
- bool operator==(const Ch* rhs) const { return *this == GenericValue(StringRef(rhs)); }
-
-#if RAPIDJSON_HAS_STDSTRING
- //! Equal-to operator with string object
- /*! \note Requires the definition of the preprocessor symbol \ref RAPIDJSON_HAS_STDSTRING.
- */
- bool operator==(const std::basic_string<Ch>& rhs) const { return *this == GenericValue(StringRef(rhs)); }
-#endif
-
- //! Equal-to operator with primitive types
- /*! \tparam T Either \ref Type, \c int, \c unsigned, \c int64_t, \c uint64_t, \c double, \c true, \c false
- */
- template <typename T> RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T>,internal::IsGenericValue<T> >), (bool)) operator==(const T& rhs) const { return *this == GenericValue(rhs); }
-
- //! Not-equal-to operator
- /*! \return !(*this == rhs)
- */
- template <typename SourceAllocator>
- bool operator!=(const GenericValue<Encoding, SourceAllocator>& rhs) const { return !(*this == rhs); }
-
- //! Not-equal-to operator with const C-string pointer
- bool operator!=(const Ch* rhs) const { return !(*this == rhs); }
-
- //! Not-equal-to operator with arbitrary types
- /*! \return !(*this == rhs)
- */
- template <typename T> RAPIDJSON_DISABLEIF_RETURN((internal::IsGenericValue<T>), (bool)) operator!=(const T& rhs) const { return !(*this == rhs); }
-
- //! Equal-to operator with arbitrary types (symmetric version)
- /*! \return (rhs == lhs)
- */
- template <typename T> friend RAPIDJSON_DISABLEIF_RETURN((internal::IsGenericValue<T>), (bool)) operator==(const T& lhs, const GenericValue& rhs) { return rhs == lhs; }
-
- //! Not-Equal-to operator with arbitrary types (symmetric version)
- /*! \return !(rhs == lhs)
- */
- template <typename T> friend RAPIDJSON_DISABLEIF_RETURN((internal::IsGenericValue<T>), (bool)) operator!=(const T& lhs, const GenericValue& rhs) { return !(rhs == lhs); }
- //@}
-
- //!@name Type
- //@{
-
- Type GetType() const { return static_cast<Type>(flags_ & kTypeMask); }
- bool IsNull() const { return flags_ == kNullFlag; }
- bool IsFalse() const { return flags_ == kFalseFlag; }
- bool IsTrue() const { return flags_ == kTrueFlag; }
- bool IsBool() const { return (flags_ & kBoolFlag) != 0; }
- bool IsObject() const { return flags_ == kObjectFlag; }
- bool IsArray() const { return flags_ == kArrayFlag; }
- bool IsNumber() const { return (flags_ & kNumberFlag) != 0; }
- bool IsInt() const { return (flags_ & kIntFlag) != 0; }
- bool IsUint() const { return (flags_ & kUintFlag) != 0; }
- bool IsInt64() const { return (flags_ & kInt64Flag) != 0; }
- bool IsUint64() const { return (flags_ & kUint64Flag) != 0; }
- bool IsDouble() const { return (flags_ & kDoubleFlag) != 0; }
- bool IsString() const { return (flags_ & kStringFlag) != 0; }
-
- //@}
-
- //!@name Null
- //@{
-
- GenericValue& SetNull() { this->~GenericValue(); new (this) GenericValue(); return *this; }
-
- //@}
-
- //!@name Bool
- //@{
-
- bool GetBool() const { RAPIDJSON_ASSERT(IsBool()); return flags_ == kTrueFlag; }
- //!< Set boolean value
- /*! \post IsBool() == true */
- GenericValue& SetBool(bool b) { this->~GenericValue(); new (this) GenericValue(b); return *this; }
-
- //@}
-
- //!@name Object
- //@{
-
- //! Set this value as an empty object.
- /*! \post IsObject() == true */
- GenericValue& SetObject() { this->~GenericValue(); new (this) GenericValue(kObjectType); return *this; }
-
- //! Get the number of members in the object.
- SizeType MemberCount() const { RAPIDJSON_ASSERT(IsObject()); return data_.o.size; }
-
- //! Check whether the object is empty.
- bool ObjectEmpty() const { RAPIDJSON_ASSERT(IsObject()); return data_.o.size == 0; }
-
- //! Get a value from an object associated with the name.
- /*! \pre IsObject() == true
- \tparam T Either \c Ch or \c const \c Ch (template used for disambiguation with \ref operator[](SizeType))
- \note In version 0.1x, if the member is not found, this function returns a null value. This makes issue 7.
- Since 0.2, if the name is not correct, it will assert.
- If user is unsure whether a member exists, user should use HasMember() first.
- A better approach is to use FindMember().
- \note Linear time complexity.
- */
- template <typename T>
- RAPIDJSON_DISABLEIF_RETURN((internal::NotExpr<internal::IsSame<typename internal::RemoveConst<T>::Type, Ch> >),(GenericValue&)) operator[](T* name) {
- GenericValue n(StringRef(name));
- return (*this)[n];
- }
- template <typename T>
- RAPIDJSON_DISABLEIF_RETURN((internal::NotExpr<internal::IsSame<typename internal::RemoveConst<T>::Type, Ch> >),(const GenericValue&)) operator[](T* name) const { return const_cast<GenericValue&>(*this)[name]; }
-
- //! Get a value from an object associated with the name.
- /*! \pre IsObject() == true
- \tparam SourceAllocator Allocator of the \c name value
-
- \note Compared to \ref operator[](T*), this version is faster because it does not need a StrLen().
- And it can also handle strings with embedded null characters.
-
- \note Linear time complexity.
- */
- template <typename SourceAllocator>
- GenericValue& operator[](const GenericValue<Encoding, SourceAllocator>& name) {
- MemberIterator member = FindMember(name);
- if (member != MemberEnd())
- return member->value;
- else {
- RAPIDJSON_ASSERT(false); // see above note
- static GenericValue NullValue;
- return NullValue;
- }
- }
- template <typename SourceAllocator>
- const GenericValue& operator[](const GenericValue<Encoding, SourceAllocator>& name) const { return const_cast<GenericValue&>(*this)[name]; }
-
- //! Const member iterator
- /*! \pre IsObject() == true */
- ConstMemberIterator MemberBegin() const { RAPIDJSON_ASSERT(IsObject()); return ConstMemberIterator(data_.o.members); }
- //! Const \em past-the-end member iterator
- /*! \pre IsObject() == true */
- ConstMemberIterator MemberEnd() const { RAPIDJSON_ASSERT(IsObject()); return ConstMemberIterator(data_.o.members + data_.o.size); }
- //! Member iterator
- /*! \pre IsObject() == true */
- MemberIterator MemberBegin() { RAPIDJSON_ASSERT(IsObject()); return MemberIterator(data_.o.members); }
- //! \em Past-the-end member iterator
- /*! \pre IsObject() == true */
- MemberIterator MemberEnd() { RAPIDJSON_ASSERT(IsObject()); return MemberIterator(data_.o.members + data_.o.size); }
-
- //! Check whether a member exists in the object.
- /*!
- \param name Member name to be searched.
- \pre IsObject() == true
- \return Whether a member with that name exists.
- \note It is better to use FindMember() directly if you need the obtain the value as well.
- \note Linear time complexity.
- */
- bool HasMember(const Ch* name) const { return FindMember(name) != MemberEnd(); }
-
- //! Check whether a member exists in the object with GenericValue name.
- /*!
- This version is faster because it does not need a StrLen(). It can also handle string with null character.
- \param name Member name to be searched.
- \pre IsObject() == true
- \return Whether a member with that name exists.
- \note It is better to use FindMember() directly if you need the obtain the value as well.
- \note Linear time complexity.
- */
- template <typename SourceAllocator>
- bool HasMember(const GenericValue<Encoding, SourceAllocator>& name) const { return FindMember(name) != MemberEnd(); }
-
- //! Find member by name.
- /*!
- \param name Member name to be searched.
- \pre IsObject() == true
- \return Iterator to member, if it exists.
- Otherwise returns \ref MemberEnd().
-
- \note Earlier versions of Rapidjson returned a \c NULL pointer, in case
- the requested member doesn't exist. For consistency with e.g.
- \c std::map, this has been changed to MemberEnd() now.
- \note Linear time complexity.
- */
- MemberIterator FindMember(const Ch* name) {
- GenericValue n(StringRef(name));
- return FindMember(n);
- }
-
- ConstMemberIterator FindMember(const Ch* name) const { return const_cast<GenericValue&>(*this).FindMember(name); }
-
- //! Find member by name.
- /*!
- This version is faster because it does not need a StrLen(). It can also handle string with null character.
- \param name Member name to be searched.
- \pre IsObject() == true
- \return Iterator to member, if it exists.
- Otherwise returns \ref MemberEnd().
-
- \note Earlier versions of Rapidjson returned a \c NULL pointer, in case
- the requested member doesn't exist. For consistency with e.g.
- \c std::map, this has been changed to MemberEnd() now.
- \note Linear time complexity.
- */
- template <typename SourceAllocator>
- MemberIterator FindMember(const GenericValue<Encoding, SourceAllocator>& name) {
- RAPIDJSON_ASSERT(IsObject());
- RAPIDJSON_ASSERT(name.IsString());
- MemberIterator member = MemberBegin();
- for ( ; member != MemberEnd(); ++member)
- if (name.StringEqual(member->name))
- break;
- return member;
- }
- template <typename SourceAllocator> ConstMemberIterator FindMember(const GenericValue<Encoding, SourceAllocator>& name) const { return const_cast<GenericValue&>(*this).FindMember(name); }
-
- //! Add a member (name-value pair) to the object.
- /*! \param name A string value as name of member.
- \param value Value of any type.
- \param allocator Allocator for reallocating memory. It must be the same one as used before. Commonly use GenericDocument::GetAllocator().
- \return The value itself for fluent API.
- \note The ownership of \c name and \c value will be transferred to this object on success.
- \pre IsObject() && name.IsString()
- \post name.IsNull() && value.IsNull()
- \note Amortized Constant time complexity.
- */
- GenericValue& AddMember(GenericValue& name, GenericValue& value, Allocator& allocator) {
- RAPIDJSON_ASSERT(IsObject());
- RAPIDJSON_ASSERT(name.IsString());
-
- Object& o = data_.o;
- if (o.size >= o.capacity) {
- if (o.capacity == 0) {
- o.capacity = kDefaultObjectCapacity;
- o.members = reinterpret_cast<Member*>(allocator.Malloc(o.capacity * sizeof(Member)));
- }
- else {
- SizeType oldCapacity = o.capacity;
- o.capacity += (oldCapacity + 1) / 2; // grow by factor 1.5
- o.members = reinterpret_cast<Member*>(allocator.Realloc(o.members, oldCapacity * sizeof(Member), o.capacity * sizeof(Member)));
- }
- }
- o.members[o.size].name.RawAssign(name);
- o.members[o.size].value.RawAssign(value);
- o.size++;
- return *this;
- }
-
- //! Add a constant string value as member (name-value pair) to the object.
- /*! \param name A string value as name of member.
- \param value constant string reference as value of member.
- \param allocator Allocator for reallocating memory. It must be the same one as used before. Commonly use GenericDocument::GetAllocator().
- \return The value itself for fluent API.
- \pre IsObject()
- \note This overload is needed to avoid clashes with the generic primitive type AddMember(GenericValue&,T,Allocator&) overload below.
- \note Amortized Constant time complexity.
- */
- GenericValue& AddMember(GenericValue& name, StringRefType value, Allocator& allocator) {
- GenericValue v(value);
- return AddMember(name, v, allocator);
- }
-
- //! Add any primitive value as member (name-value pair) to the object.
- /*! \tparam T Either \ref Type, \c int, \c unsigned, \c int64_t, \c uint64_t
- \param name A string value as name of member.
- \param value Value of primitive type \c T as value of member
- \param allocator Allocator for reallocating memory. Commonly use GenericDocument::GetAllocator().
- \return The value itself for fluent API.
- \pre IsObject()
-
- \note The source type \c T explicitly disallows all pointer types,
- especially (\c const) \ref Ch*. This helps avoiding implicitly
- referencing character strings with insufficient lifetime, use
- \ref AddMember(StringRefType, GenericValue&, Allocator&) or \ref
- AddMember(StringRefType, StringRefType, Allocator&).
- All other pointer types would implicitly convert to \c bool,
- use an explicit cast instead, if needed.
- \note Amortized Constant time complexity.
- */
- template <typename T>
- RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T>, internal::IsGenericValue<T> >), (GenericValue&))
- AddMember(GenericValue& name, T value, Allocator& allocator) {
- GenericValue v(value);
- return AddMember(name, v, allocator);
- }
-
-#if RAPIDJSON_HAS_CXX11_RVALUE_REFS
- GenericValue& AddMember(GenericValue&& name, GenericValue&& value, Allocator& allocator) {
- return AddMember(name, value, allocator);
- }
- GenericValue& AddMember(GenericValue&& name, GenericValue& value, Allocator& allocator) {
- return AddMember(name, value, allocator);
- }
- GenericValue& AddMember(GenericValue& name, GenericValue&& value, Allocator& allocator) {
- return AddMember(name, value, allocator);
- }
- GenericValue& AddMember(StringRefType name, GenericValue&& value, Allocator& allocator) {
- GenericValue n(name);
- return AddMember(n, value, allocator);
- }
-#endif // RAPIDJSON_HAS_CXX11_RVALUE_REFS
-
-
- //! Add a member (name-value pair) to the object.
- /*! \param name A constant string reference as name of member.
- \param value Value of any type.
- \param allocator Allocator for reallocating memory. It must be the same one as used before. Commonly use GenericDocument::GetAllocator().
- \return The value itself for fluent API.
- \note The ownership of \c value will be transferred to this object on success.
- \pre IsObject()
- \post value.IsNull()
- \note Amortized Constant time complexity.
- */
- GenericValue& AddMember(StringRefType name, GenericValue& value, Allocator& allocator) {
- GenericValue n(name);
- return AddMember(n, value, allocator);
- }
-
- //! Add a constant string value as member (name-value pair) to the object.
- /*! \param name A constant string reference as name of member.
- \param value constant string reference as value of member.
- \param allocator Allocator for reallocating memory. It must be the same one as used before. Commonly use GenericDocument::GetAllocator().
- \return The value itself for fluent API.
- \pre IsObject()
- \note This overload is needed to avoid clashes with the generic primitive type AddMember(StringRefType,T,Allocator&) overload below.
- \note Amortized Constant time complexity.
- */
- GenericValue& AddMember(StringRefType name, StringRefType value, Allocator& allocator) {
- GenericValue v(value);
- return AddMember(name, v, allocator);
- }
-
- //! Add any primitive value as member (name-value pair) to the object.
- /*! \tparam T Either \ref Type, \c int, \c unsigned, \c int64_t, \c uint64_t
- \param name A constant string reference as name of member.
- \param value Value of primitive type \c T as value of member
- \param allocator Allocator for reallocating memory. Commonly use GenericDocument::GetAllocator().
- \return The value itself for fluent API.
- \pre IsObject()
-
- \note The source type \c T explicitly disallows all pointer types,
- especially (\c const) \ref Ch*. This helps avoiding implicitly
- referencing character strings with insufficient lifetime, use
- \ref AddMember(StringRefType, GenericValue&, Allocator&) or \ref
- AddMember(StringRefType, StringRefType, Allocator&).
- All other pointer types would implicitly convert to \c bool,
- use an explicit cast instead, if needed.
- \note Amortized Constant time complexity.
- */
- template <typename T>
- RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T>, internal::IsGenericValue<T> >), (GenericValue&))
- AddMember(StringRefType name, T value, Allocator& allocator) {
- GenericValue n(name);
- return AddMember(n, value, allocator);
- }
-
- //! Remove all members in the object.
- /*! This function do not deallocate memory in the object, i.e. the capacity is unchanged.
- \note Linear time complexity.
- */
- void RemoveAllMembers() {
- RAPIDJSON_ASSERT(IsObject());
- for (MemberIterator m = MemberBegin(); m != MemberEnd(); ++m)
- m->~Member();
- data_.o.size = 0;
- }
-
- //! Remove a member in object by its name.
- /*! \param name Name of member to be removed.
- \return Whether the member existed.
- \note This function may reorder the object members. Use \ref
- EraseMember(ConstMemberIterator) if you need to preserve the
- relative order of the remaining members.
- \note Linear time complexity.
- */
- bool RemoveMember(const Ch* name) {
- GenericValue n(StringRef(name));
- return RemoveMember(n);
- }
-
- template <typename SourceAllocator>
- bool RemoveMember(const GenericValue<Encoding, SourceAllocator>& name) {
- MemberIterator m = FindMember(name);
- if (m != MemberEnd()) {
- RemoveMember(m);
- return true;
- }
- else
- return false;
- }
-
- //! Remove a member in object by iterator.
- /*! \param m member iterator (obtained by FindMember() or MemberBegin()).
- \return the new iterator after removal.
- \note This function may reorder the object members. Use \ref
- EraseMember(ConstMemberIterator) if you need to preserve the
- relative order of the remaining members.
- \note Constant time complexity.
- */
- MemberIterator RemoveMember(MemberIterator m) {
- RAPIDJSON_ASSERT(IsObject());
- RAPIDJSON_ASSERT(data_.o.size > 0);
- RAPIDJSON_ASSERT(data_.o.members != 0);
- RAPIDJSON_ASSERT(m >= MemberBegin() && m < MemberEnd());
-
- MemberIterator last(data_.o.members + (data_.o.size - 1));
- if (data_.o.size > 1 && m != last) {
- // Move the last one to this place
- *m = *last;
- }
- else {
- // Only one left, just destroy
- m->~Member();
- }
- --data_.o.size;
- return m;
- }
-
- //! Remove a member from an object by iterator.
- /*! \param pos iterator to the member to remove
- \pre IsObject() == true && \ref MemberBegin() <= \c pos < \ref MemberEnd()
- \return Iterator following the removed element.
- If the iterator \c pos refers to the last element, the \ref MemberEnd() iterator is returned.
- \note This function preserves the relative order of the remaining object
- members. If you do not need this, use the more efficient \ref RemoveMember(MemberIterator).
- \note Linear time complexity.
- */
- MemberIterator EraseMember(ConstMemberIterator pos) {
- return EraseMember(pos, pos +1);
- }
-
- //! Remove members in the range [first, last) from an object.
- /*! \param first iterator to the first member to remove
- \param last iterator following the last member to remove
- \pre IsObject() == true && \ref MemberBegin() <= \c first <= \c last <= \ref MemberEnd()
- \return Iterator following the last removed element.
- \note This function preserves the relative order of the remaining object
- members.
- \note Linear time complexity.
- */
- MemberIterator EraseMember(ConstMemberIterator first, ConstMemberIterator last) {
- RAPIDJSON_ASSERT(IsObject());
- RAPIDJSON_ASSERT(data_.o.size > 0);
- RAPIDJSON_ASSERT(data_.o.members != 0);
- RAPIDJSON_ASSERT(first >= MemberBegin());
- RAPIDJSON_ASSERT(first <= last);
- RAPIDJSON_ASSERT(last <= MemberEnd());
-
- MemberIterator pos = MemberBegin() + (first - MemberBegin());
- for (MemberIterator itr = pos; itr != last; ++itr)
- itr->~Member();
- std::memmove(&*pos, &*last, (MemberEnd() - last) * sizeof(Member));
- data_.o.size -= (last - first);
- return pos;
- }
-
- //@}
-
- //!@name Array
- //@{
-
- //! Set this value as an empty array.
- /*! \post IsArray == true */
- GenericValue& SetArray() { this->~GenericValue(); new (this) GenericValue(kArrayType); return *this; }
-
- //! Get the number of elements in array.
- SizeType Size() const { RAPIDJSON_ASSERT(IsArray()); return data_.a.size; }
-
- //! Get the capacity of array.
- SizeType Capacity() const { RAPIDJSON_ASSERT(IsArray()); return data_.a.capacity; }
-
- //! Check whether the array is empty.
- bool Empty() const { RAPIDJSON_ASSERT(IsArray()); return data_.a.size == 0; }
-
- //! Remove all elements in the array.
- /*! This function do not deallocate memory in the array, i.e. the capacity is unchanged.
- \note Linear time complexity.
- */
- void Clear() {
- RAPIDJSON_ASSERT(IsArray());
- for (SizeType i = 0; i < data_.a.size; ++i)
- data_.a.elements[i].~GenericValue();
- data_.a.size = 0;
- }
-
- //! Get an element from array by index.
- /*! \pre IsArray() == true
- \param index Zero-based index of element.
- \see operator[](T*)
- */
- GenericValue& operator[](SizeType index) {
- RAPIDJSON_ASSERT(IsArray());
- RAPIDJSON_ASSERT(index < data_.a.size);
- return data_.a.elements[index];
- }
- const GenericValue& operator[](SizeType index) const { return const_cast<GenericValue&>(*this)[index]; }
-
- //! Element iterator
- /*! \pre IsArray() == true */
- ValueIterator Begin() { RAPIDJSON_ASSERT(IsArray()); return data_.a.elements; }
- //! \em Past-the-end element iterator
- /*! \pre IsArray() == true */
- ValueIterator End() { RAPIDJSON_ASSERT(IsArray()); return data_.a.elements + data_.a.size; }
- //! Constant element iterator
- /*! \pre IsArray() == true */
- ConstValueIterator Begin() const { return const_cast<GenericValue&>(*this).Begin(); }
- //! Constant \em past-the-end element iterator
- /*! \pre IsArray() == true */
- ConstValueIterator End() const { return const_cast<GenericValue&>(*this).End(); }
-
- //! Request the array to have enough capacity to store elements.
- /*! \param newCapacity The capacity that the array at least need to have.
- \param allocator Allocator for reallocating memory. It must be the same one as used before. Commonly use GenericDocument::GetAllocator().
- \return The value itself for fluent API.
- \note Linear time complexity.
- */
- GenericValue& Reserve(SizeType newCapacity, Allocator &allocator) {
- RAPIDJSON_ASSERT(IsArray());
- if (newCapacity > data_.a.capacity) {
- data_.a.elements = (GenericValue*)allocator.Realloc(data_.a.elements, data_.a.capacity * sizeof(GenericValue), newCapacity * sizeof(GenericValue));
- data_.a.capacity = newCapacity;
- }
- return *this;
- }
-
- //! Append a GenericValue at the end of the array.
- /*! \param value Value to be appended.
- \param allocator Allocator for reallocating memory. It must be the same one as used before. Commonly use GenericDocument::GetAllocator().
- \pre IsArray() == true
- \post value.IsNull() == true
- \return The value itself for fluent API.
- \note The ownership of \c value will be transferred to this array on success.
- \note If the number of elements to be appended is known, calls Reserve() once first may be more efficient.
- \note Amortized constant time complexity.
- */
- GenericValue& PushBack(GenericValue& value, Allocator& allocator) {
- RAPIDJSON_ASSERT(IsArray());
- if (data_.a.size >= data_.a.capacity)
- Reserve(data_.a.capacity == 0 ? kDefaultArrayCapacity : (data_.a.capacity + (data_.a.capacity + 1) / 2), allocator);
- data_.a.elements[data_.a.size++].RawAssign(value);
- return *this;
- }
-
-#if RAPIDJSON_HAS_CXX11_RVALUE_REFS
- GenericValue& PushBack(GenericValue&& value, Allocator& allocator) {
- return PushBack(value, allocator);
- }
-#endif // RAPIDJSON_HAS_CXX11_RVALUE_REFS
-
- //! Append a constant string reference at the end of the array.
- /*! \param value Constant string reference to be appended.
- \param allocator Allocator for reallocating memory. It must be the same one used previously. Commonly use GenericDocument::GetAllocator().
- \pre IsArray() == true
- \return The value itself for fluent API.
- \note If the number of elements to be appended is known, calls Reserve() once first may be more efficient.
- \note Amortized constant time complexity.
- \see GenericStringRef
- */
- GenericValue& PushBack(StringRefType value, Allocator& allocator) {
- return (*this).template PushBack<StringRefType>(value, allocator);
- }
-
- //! Append a primitive value at the end of the array.
- /*! \tparam T Either \ref Type, \c int, \c unsigned, \c int64_t, \c uint64_t
- \param value Value of primitive type T to be appended.
- \param allocator Allocator for reallocating memory. It must be the same one as used before. Commonly use GenericDocument::GetAllocator().
- \pre IsArray() == true
- \return The value itself for fluent API.
- \note If the number of elements to be appended is known, calls Reserve() once first may be more efficient.
-
- \note The source type \c T explicitly disallows all pointer types,
- especially (\c const) \ref Ch*. This helps avoiding implicitly
- referencing character strings with insufficient lifetime, use
- \ref PushBack(GenericValue&, Allocator&) or \ref
- PushBack(StringRefType, Allocator&).
- All other pointer types would implicitly convert to \c bool,
- use an explicit cast instead, if needed.
- \note Amortized constant time complexity.
- */
- template <typename T>
- RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T>, internal::IsGenericValue<T> >), (GenericValue&))
- PushBack(T value, Allocator& allocator) {
- GenericValue v(value);
- return PushBack(v, allocator);
- }
-
- //! Remove the last element in the array.
- /*!
- \note Constant time complexity.
- */
- GenericValue& PopBack() {
- RAPIDJSON_ASSERT(IsArray());
- RAPIDJSON_ASSERT(!Empty());
- data_.a.elements[--data_.a.size].~GenericValue();
- return *this;
- }
-
- //! Remove an element of array by iterator.
- /*!
- \param pos iterator to the element to remove
- \pre IsArray() == true && \ref Begin() <= \c pos < \ref End()
- \return Iterator following the removed element. If the iterator pos refers to the last element, the End() iterator is returned.
- \note Linear time complexity.
- */
- ValueIterator Erase(ConstValueIterator pos) {
- return Erase(pos, pos + 1);
- }
-
- //! Remove elements in the range [first, last) of the array.
- /*!
- \param first iterator to the first element to remove
- \param last iterator following the last element to remove
- \pre IsArray() == true && \ref Begin() <= \c first <= \c last <= \ref End()
- \return Iterator following the last removed element.
- \note Linear time complexity.
- */
- ValueIterator Erase(ConstValueIterator first, ConstValueIterator last) {
- RAPIDJSON_ASSERT(IsArray());
- RAPIDJSON_ASSERT(data_.a.size > 0);
- RAPIDJSON_ASSERT(data_.a.elements != 0);
- RAPIDJSON_ASSERT(first >= Begin());
- RAPIDJSON_ASSERT(first <= last);
- RAPIDJSON_ASSERT(last <= End());
- ValueIterator pos = Begin() + (first - Begin());
- for (ValueIterator itr = pos; itr != last; ++itr)
- itr->~GenericValue();
- std::memmove(pos, last, (End() - last) * sizeof(GenericValue));
- data_.a.size -= (last - first);
- return pos;
- }
-
- //@}
-
- //!@name Number
- //@{
-
- int GetInt() const { RAPIDJSON_ASSERT(flags_ & kIntFlag); return data_.n.i.i; }
- unsigned GetUint() const { RAPIDJSON_ASSERT(flags_ & kUintFlag); return data_.n.u.u; }
- int64_t GetInt64() const { RAPIDJSON_ASSERT(flags_ & kInt64Flag); return data_.n.i64; }
- uint64_t GetUint64() const { RAPIDJSON_ASSERT(flags_ & kUint64Flag); return data_.n.u64; }
-
- double GetDouble() const {
- RAPIDJSON_ASSERT(IsNumber());
- if ((flags_ & kDoubleFlag) != 0) return data_.n.d; // exact type, no conversion.
- if ((flags_ & kIntFlag) != 0) return data_.n.i.i; // int -> double
- if ((flags_ & kUintFlag) != 0) return data_.n.u.u; // unsigned -> double
- if ((flags_ & kInt64Flag) != 0) return (double)data_.n.i64; // int64_t -> double (may lose precision)
- RAPIDJSON_ASSERT((flags_ & kUint64Flag) != 0); return (double)data_.n.u64; // uint64_t -> double (may lose precision)
- }
-
- GenericValue& SetInt(int i) { this->~GenericValue(); new (this) GenericValue(i); return *this; }
- GenericValue& SetUint(unsigned u) { this->~GenericValue(); new (this) GenericValue(u); return *this; }
- GenericValue& SetInt64(int64_t i64) { this->~GenericValue(); new (this) GenericValue(i64); return *this; }
- GenericValue& SetUint64(uint64_t u64) { this->~GenericValue(); new (this) GenericValue(u64); return *this; }
- GenericValue& SetDouble(double d) { this->~GenericValue(); new (this) GenericValue(d); return *this; }
-
- //@}
-
- //!@name String
- //@{
-
- const Ch* GetString() const { RAPIDJSON_ASSERT(IsString()); return ((flags_ & kInlineStrFlag) ? data_.ss.str : data_.s.str); }
-
- //! Get the length of string.
- /*! Since rapidjson permits "\\u0000" in the json string, strlen(v.GetString()) may not equal to v.GetStringLength().
- */
- SizeType GetStringLength() const { RAPIDJSON_ASSERT(IsString()); return ((flags_ & kInlineStrFlag) ? (data_.ss.GetLength()) : data_.s.length); }
-
- //! Set this value as a string without copying source string.
- /*! This version has better performance with supplied length, and also support string containing null character.
- \param s source string pointer.
- \param length The length of source string, excluding the trailing null terminator.
- \return The value itself for fluent API.
- \post IsString() == true && GetString() == s && GetStringLength() == length
- \see SetString(StringRefType)
- */
- GenericValue& SetString(const Ch* s, SizeType length) { return SetString(StringRef(s, length)); }
-
- //! Set this value as a string without copying source string.
- /*! \param s source string reference
- \return The value itself for fluent API.
- \post IsString() == true && GetString() == s && GetStringLength() == s.length
- */
- GenericValue& SetString(StringRefType s) { this->~GenericValue(); SetStringRaw(s); return *this; }
-
- //! Set this value as a string by copying from source string.
- /*! This version has better performance with supplied length, and also support string containing null character.
- \param s source string.
- \param length The length of source string, excluding the trailing null terminator.
- \param allocator Allocator for allocating copied buffer. Commonly use GenericDocument::GetAllocator().
- \return The value itself for fluent API.
- \post IsString() == true && GetString() != s && strcmp(GetString(),s) == 0 && GetStringLength() == length
- */
- GenericValue& SetString(const Ch* s, SizeType length, Allocator& allocator) { this->~GenericValue(); SetStringRaw(StringRef(s, length), allocator); return *this; }
-
- //! Set this value as a string by copying from source string.
- /*! \param s source string.
- \param allocator Allocator for allocating copied buffer. Commonly use GenericDocument::GetAllocator().
- \return The value itself for fluent API.
- \post IsString() == true && GetString() != s && strcmp(GetString(),s) == 0 && GetStringLength() == length
- */
- GenericValue& SetString(const Ch* s, Allocator& allocator) { return SetString(s, internal::StrLen(s), allocator); }
-
-#if RAPIDJSON_HAS_STDSTRING
- //! Set this value as a string by copying from source string.
- /*! \param s source string.
- \param allocator Allocator for allocating copied buffer. Commonly use GenericDocument::GetAllocator().
- \return The value itself for fluent API.
- \post IsString() == true && GetString() != s.data() && strcmp(GetString(),s.data() == 0 && GetStringLength() == s.size()
- \note Requires the definition of the preprocessor symbol \ref RAPIDJSON_HAS_STDSTRING.
- */
- GenericValue& SetString(const std::basic_string<Ch>& s, Allocator& allocator) { return SetString(s.data(), s.size(), allocator); }
-#endif
-
- //@}
-
- //! Generate events of this value to a Handler.
- /*! This function adopts the GoF visitor pattern.
- Typical usage is to output this JSON value as JSON text via Writer, which is a Handler.
- It can also be used to deep clone this value via GenericDocument, which is also a Handler.
- \tparam Handler type of handler.
- \param handler An object implementing concept Handler.
- */
- template <typename Handler>
- bool Accept(Handler& handler) const {
- switch(GetType()) {
- case kNullType: return handler.Null();
- case kFalseType: return handler.Bool(false);
- case kTrueType: return handler.Bool(true);
-
- case kObjectType:
- if (!handler.StartObject())
- return false;
- for (ConstMemberIterator m = MemberBegin(); m != MemberEnd(); ++m) {
- RAPIDJSON_ASSERT(m->name.IsString()); // User may change the type of name by MemberIterator.
- if (!handler.Key(m->name.GetString(), m->name.GetStringLength(), (m->name.flags_ & kCopyFlag) != 0))
- return false;
- if (!m->value.Accept(handler))
- return false;
- }
- return handler.EndObject(data_.o.size);
-
- case kArrayType:
- if (!handler.StartArray())
- return false;
- for (GenericValue* v = data_.a.elements; v != data_.a.elements + data_.a.size; ++v)
- if (!v->Accept(handler))
- return false;
- return handler.EndArray(data_.a.size);
-
- case kStringType:
- return handler.String(GetString(), GetStringLength(), (flags_ & kCopyFlag) != 0);
-
- default:
- RAPIDJSON_ASSERT(GetType() == kNumberType);
- if (IsInt()) return handler.Int(data_.n.i.i);
- else if (IsUint()) return handler.Uint(data_.n.u.u);
- else if (IsInt64()) return handler.Int64(data_.n.i64);
- else if (IsUint64()) return handler.Uint64(data_.n.u64);
- else return handler.Double(data_.n.d);
- }
- }
-
-private:
- template <typename, typename> friend class GenericValue;
- template <typename, typename, typename> friend class GenericDocument;
-
- enum {
- kBoolFlag = 0x100,
- kNumberFlag = 0x200,
- kIntFlag = 0x400,
- kUintFlag = 0x800,
- kInt64Flag = 0x1000,
- kUint64Flag = 0x2000,
- kDoubleFlag = 0x4000,
- kStringFlag = 0x100000,
- kCopyFlag = 0x200000,
- kInlineStrFlag = 0x400000,
-
- // Initial flags of different types.
- kNullFlag = kNullType,
- kTrueFlag = kTrueType | kBoolFlag,
- kFalseFlag = kFalseType | kBoolFlag,
- kNumberIntFlag = kNumberType | kNumberFlag | kIntFlag | kInt64Flag,
- kNumberUintFlag = kNumberType | kNumberFlag | kUintFlag | kUint64Flag | kInt64Flag,
- kNumberInt64Flag = kNumberType | kNumberFlag | kInt64Flag,
- kNumberUint64Flag = kNumberType | kNumberFlag | kUint64Flag,
- kNumberDoubleFlag = kNumberType | kNumberFlag | kDoubleFlag,
- kNumberAnyFlag = kNumberType | kNumberFlag | kIntFlag | kInt64Flag | kUintFlag | kUint64Flag | kDoubleFlag,
- kConstStringFlag = kStringType | kStringFlag,
- kCopyStringFlag = kStringType | kStringFlag | kCopyFlag,
- kShortStringFlag = kStringType | kStringFlag | kCopyFlag | kInlineStrFlag,
- kObjectFlag = kObjectType,
- kArrayFlag = kArrayType,
-
- kTypeMask = 0xFF // bitwise-and with mask of 0xFF can be optimized by compiler
- };
-
- static const SizeType kDefaultArrayCapacity = 16;
- static const SizeType kDefaultObjectCapacity = 16;
-
- struct String {
- const Ch* str;
- SizeType length;
- unsigned hashcode; //!< reserved
- }; // 12 bytes in 32-bit mode, 16 bytes in 64-bit mode
-
- // implementation detail: ShortString can represent zero-terminated strings up to MaxSize chars
- // (excluding the terminating zero) and store a value to determine the length of the contained
- // string in the last character str[LenPos] by storing "MaxSize - length" there. If the string
- // to store has the maximal length of MaxSize then str[LenPos] will be 0 and therefore act as
- // the string terminator as well. For getting the string length back from that value just use
- // "MaxSize - str[LenPos]".
- // This allows to store 11-chars strings in 32-bit mode and 15-chars strings in 64-bit mode
- // inline (for `UTF8`-encoded strings).
- struct ShortString {
- enum { MaxChars = sizeof(String) / sizeof(Ch), MaxSize = MaxChars - 1, LenPos = MaxSize };
- Ch str[MaxChars];
-
- inline static bool Usable(SizeType len) { return (MaxSize >= len); }
- inline void SetLength(SizeType len) { str[LenPos] = (Ch)(MaxSize - len); }
- inline SizeType GetLength() const { return (SizeType)(MaxSize - str[LenPos]); }
- }; // at most as many bytes as "String" above => 12 bytes in 32-bit mode, 16 bytes in 64-bit mode
-
- // By using proper binary layout, retrieval of different integer types do not need conversions.
- union Number {
-#if RAPIDJSON_ENDIAN == RAPIDJSON_LITTLEENDIAN
- struct I {
- int i;
- char padding[4];
- }i;
- struct U {
- unsigned u;
- char padding2[4];
- }u;
-#else
- struct I {
- char padding[4];
- int i;
- }i;
- struct U {
- char padding2[4];
- unsigned u;
- }u;
-#endif
- int64_t i64;
- uint64_t u64;
- double d;
- }; // 8 bytes
-
- struct Object {
- Member* members;
- SizeType size;
- SizeType capacity;
- }; // 12 bytes in 32-bit mode, 16 bytes in 64-bit mode
-
- struct Array {
- GenericValue* elements;
- SizeType size;
- SizeType capacity;
- }; // 12 bytes in 32-bit mode, 16 bytes in 64-bit mode
-
- union Data {
- String s;
- ShortString ss;
- Number n;
- Object o;
- Array a;
- }; // 12 bytes in 32-bit mode, 16 bytes in 64-bit mode
-
- // Initialize this value as array with initial data, without calling destructor.
- void SetArrayRaw(GenericValue* values, SizeType count, Allocator& allocator) {
- flags_ = kArrayFlag;
- if (count) {
- data_.a.elements = (GenericValue*)allocator.Malloc(count * sizeof(GenericValue));
- std::memcpy(data_.a.elements, values, count * sizeof(GenericValue));
- }
- else
- data_.a.elements = NULL;
- data_.a.size = data_.a.capacity = count;
- }
-
- //! Initialize this value as object with initial data, without calling destructor.
- void SetObjectRaw(Member* members, SizeType count, Allocator& allocator) {
- flags_ = kObjectFlag;
- if (count) {
- data_.o.members = (Member*)allocator.Malloc(count * sizeof(Member));
- std::memcpy(data_.o.members, members, count * sizeof(Member));
- }
- else
- data_.o.members = NULL;
- data_.o.size = data_.o.capacity = count;
- }
-
- //! Initialize this value as constant string, without calling destructor.
- void SetStringRaw(StringRefType s) RAPIDJSON_NOEXCEPT {
- flags_ = kConstStringFlag;
- data_.s.str = s;
- data_.s.length = s.length;
- }
-
- //! Initialize this value as copy string with initial data, without calling destructor.
- void SetStringRaw(StringRefType s, Allocator& allocator) {
- Ch* str = NULL;
- if(ShortString::Usable(s.length)) {
- flags_ = kShortStringFlag;
- data_.ss.SetLength(s.length);
- str = data_.ss.str;
- } else {
- flags_ = kCopyStringFlag;
- data_.s.length = s.length;
- str = (Ch *)allocator.Malloc((s.length + 1) * sizeof(Ch));
- data_.s.str = str;
- }
- std::memcpy(str, s, s.length * sizeof(Ch));
- str[s.length] = '\0';
- }
-
- //! Assignment without calling destructor
- void RawAssign(GenericValue& rhs) RAPIDJSON_NOEXCEPT {
- data_ = rhs.data_;
- flags_ = rhs.flags_;
- rhs.flags_ = kNullFlag;
- }
-
- template <typename SourceAllocator>
- bool StringEqual(const GenericValue<Encoding, SourceAllocator>& rhs) const {
- RAPIDJSON_ASSERT(IsString());
- RAPIDJSON_ASSERT(rhs.IsString());
-
- const SizeType len1 = GetStringLength();
- const SizeType len2 = rhs.GetStringLength();
- if(len1 != len2) { return false; }
-
- const Ch* const str1 = GetString();
- const Ch* const str2 = rhs.GetString();
- if(str1 == str2) { return true; } // fast path for constant string
-
- return (std::memcmp(str1, str2, sizeof(Ch) * len1) == 0);
- }
-
- Data data_;
- unsigned flags_;
-};
-
-//! GenericValue with UTF8 encoding
-typedef GenericValue<UTF8<> > Value;
-
-///////////////////////////////////////////////////////////////////////////////
-// GenericDocument
-
-//! A document for parsing JSON text as DOM.
-/*!
- \note implements Handler concept
- \tparam Encoding Encoding for both parsing and string storage.
- \tparam Allocator Allocator for allocating memory for the DOM
- \tparam StackAllocator Allocator for allocating memory for stack during parsing.
- \warning Although GenericDocument inherits from GenericValue, the API does \b not provide any virtual functions, especially no virtual destructor. To avoid memory leaks, do not \c delete a GenericDocument object via a pointer to a GenericValue.
-*/
-template <typename Encoding, typename Allocator = MemoryPoolAllocator<>, typename StackAllocator = CrtAllocator>
-class GenericDocument : public GenericValue<Encoding, Allocator> {
-public:
- typedef typename Encoding::Ch Ch; //!< Character type derived from Encoding.
- typedef GenericValue<Encoding, Allocator> ValueType; //!< Value type of the document.
- typedef Allocator AllocatorType; //!< Allocator type from template parameter.
-
- //! Constructor
- /*! \param allocator Optional allocator for allocating memory.
- \param stackCapacity Optional initial capacity of stack in bytes.
- \param stackAllocator Optional allocator for allocating memory for stack.
- */
- GenericDocument(Allocator* allocator = 0, size_t stackCapacity = kDefaultStackCapacity, StackAllocator* stackAllocator = 0) :
- allocator_(allocator), ownAllocator_(0), stack_(stackAllocator, stackCapacity), parseResult_()
- {
- if (!allocator_)
- ownAllocator_ = allocator_ = RAPIDJSON_NEW(Allocator());
- }
-
-#if RAPIDJSON_HAS_CXX11_RVALUE_REFS
- //! Move constructor in C++11
- GenericDocument(GenericDocument&& rhs) RAPIDJSON_NOEXCEPT
- : ValueType(std::move(rhs)),
- allocator_(rhs.allocator_),
- ownAllocator_(rhs.ownAllocator_),
- stack_(std::move(rhs.stack_)),
- parseResult_(rhs.parseResult_)
- {
- rhs.allocator_ = 0;
- rhs.ownAllocator_ = 0;
- rhs.parseResult_ = ParseResult();
- }
-#endif
-
- ~GenericDocument() {
- Destroy();
- }
-
-#if RAPIDJSON_HAS_CXX11_RVALUE_REFS
- //! Move assignment in C++11
- GenericDocument& operator=(GenericDocument&& rhs) RAPIDJSON_NOEXCEPT
- {
- // The cast to ValueType is necessary here, because otherwise it would
- // attempt to call GenericValue's templated assignment operator.
- ValueType::operator=(std::forward<ValueType>(rhs));
-
- // Calling the destructor here would prematurely call stack_'s destructor
- Destroy();
-
- allocator_ = rhs.allocator_;
- ownAllocator_ = rhs.ownAllocator_;
- stack_ = std::move(rhs.stack_);
- parseResult_ = rhs.parseResult_;
-
- rhs.allocator_ = 0;
- rhs.ownAllocator_ = 0;
- rhs.parseResult_ = ParseResult();
-
- return *this;
- }
-#endif
-
- //!@name Parse from stream
- //!@{
-
- //! Parse JSON text from an input stream (with Encoding conversion)
- /*! \tparam parseFlags Combination of \ref ParseFlag.
- \tparam SourceEncoding Encoding of input stream
- \tparam InputStream Type of input stream, implementing Stream concept
- \param is Input stream to be parsed.
- \return The document itself for fluent API.
- */
- template <unsigned parseFlags, typename SourceEncoding, typename InputStream>
- GenericDocument& ParseStream(InputStream& is) {
- ValueType::SetNull(); // Remove existing root if exist
- GenericReader<SourceEncoding, Encoding, Allocator> reader(&GetAllocator());
- ClearStackOnExit scope(*this);
- parseResult_ = reader.template Parse<parseFlags>(is, *this);
- if (parseResult_) {
- RAPIDJSON_ASSERT(stack_.GetSize() == sizeof(ValueType)); // Got one and only one root object
- this->RawAssign(*stack_.template Pop<ValueType>(1)); // Add this-> to prevent issue 13.
- }
- return *this;
- }
-
- //! Parse JSON text from an input stream
- /*! \tparam parseFlags Combination of \ref ParseFlag.
- \tparam InputStream Type of input stream, implementing Stream concept
- \param is Input stream to be parsed.
- \return The document itself for fluent API.
- */
- template <unsigned parseFlags, typename InputStream>
- GenericDocument& ParseStream(InputStream& is) {
- return ParseStream<parseFlags, Encoding, InputStream>(is);
- }
-
- //! Parse JSON text from an input stream (with \ref kParseDefaultFlags)
- /*! \tparam InputStream Type of input stream, implementing Stream concept
- \param is Input stream to be parsed.
- \return The document itself for fluent API.
- */
- template <typename InputStream>
- GenericDocument& ParseStream(InputStream& is) {
- return ParseStream<kParseDefaultFlags, Encoding, InputStream>(is);
- }
- //!@}
-
- //!@name Parse in-place from mutable string
- //!@{
-
- //! Parse JSON text from a mutable string
- /*! \tparam parseFlags Combination of \ref ParseFlag.
- \param str Mutable zero-terminated string to be parsed.
- \return The document itself for fluent API.
- */
- template <unsigned parseFlags>
- GenericDocument& ParseInsitu(Ch* str) {
- GenericInsituStringStream<Encoding> s(str);
- return ParseStream<parseFlags | kParseInsituFlag>(s);
- }
-
- //! Parse JSON text from a mutable string (with \ref kParseDefaultFlags)
- /*! \param str Mutable zero-terminated string to be parsed.
- \return The document itself for fluent API.
- */
- GenericDocument& ParseInsitu(Ch* str) {
- return ParseInsitu<kParseDefaultFlags>(str);
- }
- //!@}
-
- //!@name Parse from read-only string
- //!@{
-
- //! Parse JSON text from a read-only string (with Encoding conversion)
- /*! \tparam parseFlags Combination of \ref ParseFlag (must not contain \ref kParseInsituFlag).
- \tparam SourceEncoding Transcoding from input Encoding
- \param str Read-only zero-terminated string to be parsed.
- */
- template <unsigned parseFlags, typename SourceEncoding>
- GenericDocument& Parse(const Ch* str) {
- RAPIDJSON_ASSERT(!(parseFlags & kParseInsituFlag));
- GenericStringStream<SourceEncoding> s(str);
- return ParseStream<parseFlags, SourceEncoding>(s);
- }
-
- //! Parse JSON text from a read-only string
- /*! \tparam parseFlags Combination of \ref ParseFlag (must not contain \ref kParseInsituFlag).
- \param str Read-only zero-terminated string to be parsed.
- */
- template <unsigned parseFlags>
- GenericDocument& Parse(const Ch* str) {
- return Parse<parseFlags, Encoding>(str);
- }
-
- //! Parse JSON text from a read-only string (with \ref kParseDefaultFlags)
- /*! \param str Read-only zero-terminated string to be parsed.
- */
- GenericDocument& Parse(const Ch* str) {
- return Parse<kParseDefaultFlags>(str);
- }
- //!@}
-
- //!@name Handling parse errors
- //!@{
-
- //! Whether a parse error has occured in the last parsing.
- bool HasParseError() const { return parseResult_.IsError(); }
-
- //! Get the \ref ParseErrorCode of last parsing.
- ParseErrorCode GetParseError() const { return parseResult_.Code(); }
-
- //! Get the position of last parsing error in input, 0 otherwise.
- size_t GetErrorOffset() const { return parseResult_.Offset(); }
-
- //!@}
-
- //! Get the allocator of this document.
- Allocator& GetAllocator() { return *allocator_; }
-
- //! Get the capacity of stack in bytes.
- size_t GetStackCapacity() const { return stack_.GetCapacity(); }
-
-private:
- // clear stack on any exit from ParseStream, e.g. due to exception
- struct ClearStackOnExit {
- explicit ClearStackOnExit(GenericDocument& d) : d_(d) {}
- ~ClearStackOnExit() { d_.ClearStack(); }
- private:
- ClearStackOnExit(const ClearStackOnExit&);
- ClearStackOnExit& operator=(const ClearStackOnExit&);
- GenericDocument& d_;
- };
-
- // callers of the following private Handler functions
- template <typename,typename,typename> friend class GenericReader; // for parsing
- template <typename, typename> friend class GenericValue; // for deep copying
-
- // Implementation of Handler
- bool Null() { new (stack_.template Push<ValueType>()) ValueType(); return true; }
- bool Bool(bool b) { new (stack_.template Push<ValueType>()) ValueType(b); return true; }
- bool Int(int i) { new (stack_.template Push<ValueType>()) ValueType(i); return true; }
- bool Uint(unsigned i) { new (stack_.template Push<ValueType>()) ValueType(i); return true; }
- bool Int64(int64_t i) { new (stack_.template Push<ValueType>()) ValueType(i); return true; }
- bool Uint64(uint64_t i) { new (stack_.template Push<ValueType>()) ValueType(i); return true; }
- bool Double(double d) { new (stack_.template Push<ValueType>()) ValueType(d); return true; }
-
- bool String(const Ch* str, SizeType length, bool copy) {
- if (copy)
- new (stack_.template Push<ValueType>()) ValueType(str, length, GetAllocator());
- else
- new (stack_.template Push<ValueType>()) ValueType(str, length);
- return true;
- }
-
- bool StartObject() { new (stack_.template Push<ValueType>()) ValueType(kObjectType); return true; }
-
- bool Key(const Ch* str, SizeType length, bool copy) { return String(str, length, copy); }
-
- bool EndObject(SizeType memberCount) {
- typename ValueType::Member* members = stack_.template Pop<typename ValueType::Member>(memberCount);
- stack_.template Top<ValueType>()->SetObjectRaw(members, (SizeType)memberCount, GetAllocator());
- return true;
- }
-
- bool StartArray() { new (stack_.template Push<ValueType>()) ValueType(kArrayType); return true; }
-
- bool EndArray(SizeType elementCount) {
- ValueType* elements = stack_.template Pop<ValueType>(elementCount);
- stack_.template Top<ValueType>()->SetArrayRaw(elements, elementCount, GetAllocator());
- return true;
- }
-
-private:
- //! Prohibit copying
- GenericDocument(const GenericDocument&);
- //! Prohibit assignment
- GenericDocument& operator=(const GenericDocument&);
-
- void ClearStack() {
- if (Allocator::kNeedFree)
- while (stack_.GetSize() > 0) // Here assumes all elements in stack array are GenericValue (Member is actually 2 GenericValue objects)
- (stack_.template Pop<ValueType>(1))->~ValueType();
- else
- stack_.Clear();
- stack_.ShrinkToFit();
- }
-
- void Destroy() {
- RAPIDJSON_DELETE(ownAllocator_);
- }
-
- static const size_t kDefaultStackCapacity = 1024;
- Allocator* allocator_;
- Allocator* ownAllocator_;
- internal::Stack<StackAllocator> stack_;
- ParseResult parseResult_;
-};
-
-//! GenericDocument with UTF8 encoding
-typedef GenericDocument<UTF8<> > Document;
-
-// defined here due to the dependency on GenericDocument
-template <typename Encoding, typename Allocator>
-template <typename SourceAllocator>
-inline
-GenericValue<Encoding,Allocator>::GenericValue(const GenericValue<Encoding,SourceAllocator>& rhs, Allocator& allocator)
-{
- switch (rhs.GetType()) {
- case kObjectType:
- case kArrayType: { // perform deep copy via SAX Handler
- GenericDocument<Encoding,Allocator> d(&allocator);
- rhs.Accept(d);
- RawAssign(*d.stack_.template Pop<GenericValue>(1));
- }
- break;
- case kStringType:
- if (rhs.flags_ == kConstStringFlag) {
- flags_ = rhs.flags_;
- data_ = *reinterpret_cast<const Data*>(&rhs.data_);
- } else {
- SetStringRaw(StringRef(rhs.GetString(), rhs.GetStringLength()), allocator);
- }
- break;
- default: // kNumberType, kTrueType, kFalseType, kNullType
- flags_ = rhs.flags_;
- data_ = *reinterpret_cast<const Data*>(&rhs.data_);
- }
-}
-
-RAPIDJSON_NAMESPACE_END
-
-#if defined(_MSC_VER) || defined(__GNUC__)
-RAPIDJSON_DIAG_POP
-#endif
-
-#endif // RAPIDJSON_DOCUMENT_H_
+// Tencent is pleased to support the open source community by making RapidJSON available.
+//
+// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
+//
+// Licensed under the MIT License (the "License"); you may not use this file except
+// in compliance with the License. You may obtain a copy of the License at
+//
+// http://opensource.org/licenses/MIT
+//
+// Unless required by applicable law or agreed to in writing, software distributed
+// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
+// CONDITIONS OF ANY KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations under the License.
+
+#ifndef RAPIDJSON_DOCUMENT_H_
+#define RAPIDJSON_DOCUMENT_H_
+
+/*! \file document.h */
+
+#include "reader.h"
+#include "internal/meta.h"
+#include "internal/strfunc.h"
+#include <new> // placement new
+
+#ifdef _MSC_VER
+RAPIDJSON_DIAG_PUSH
+RAPIDJSON_DIAG_OFF(4127) // conditional expression is constant
+#elif defined(__GNUC__)
+RAPIDJSON_DIAG_PUSH
+RAPIDJSON_DIAG_OFF(effc++)
+#endif
+
+///////////////////////////////////////////////////////////////////////////////
+// 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
+ \ref rapidjson::GenericValue with \c std::string are enabled, especially
+ for construction and comparison.
+
+ \hideinitializer
+*/
+#endif // !defined(RAPIDJSON_HAS_STDSTRING)
+
+#if RAPIDJSON_HAS_STDSTRING
+#include <string>
+#endif // RAPIDJSON_HAS_STDSTRING
+
+#ifndef RAPIDJSON_NOMEMBERITERATORCLASS
+#include <iterator> // std::iterator, std::random_access_iterator_tag
+#endif
+
+#if RAPIDJSON_HAS_CXX11_RVALUE_REFS
+#include <utility> // std::move
+#endif
+
+RAPIDJSON_NAMESPACE_BEGIN
+
+// Forward declaration.
+template <typename Encoding, typename Allocator>
+class GenericValue;
+
+//! Name-value pair in a JSON object value.
+/*!
+ This class was internal to GenericValue. It used to be a inner struct.
+ But a compiler (IBM XL C/C++ for AIX) have reported to have problem with that so it moved as a namespace scope struct.
+ https://code.google.com/p/rapidjson/issues/detail?id=64
+*/
+template <typename Encoding, typename Allocator>
+struct GenericMember {
+ GenericValue<Encoding, Allocator> name; //!< name of member (must be a string)
+ GenericValue<Encoding, Allocator> value; //!< value of member.
+};
+
+///////////////////////////////////////////////////////////////////////////////
+// GenericMemberIterator
+
+#ifndef RAPIDJSON_NOMEMBERITERATORCLASS
+
+//! (Constant) member iterator for a JSON object value
+/*!
+ \tparam Const Is this a constant iterator?
+ \tparam Encoding Encoding of the value. (Even non-string values need to have the same encoding in a document)
+ \tparam Allocator Allocator type for allocating memory of object, array and string.
+
+ This class implements a Random Access Iterator for GenericMember elements
+ of a GenericValue, see ISO/IEC 14882:2003(E) C++ standard, 24.1 [lib.iterator.requirements].
+
+ \note This iterator implementation is mainly intended to avoid implicit
+ conversions from iterator values to \c NULL,
+ e.g. from GenericValue::FindMember.
+
+ \note Define \c RAPIDJSON_NOMEMBERITERATORCLASS to fall back to a
+ pointer-based implementation, if your platform doesn't provide
+ the C++ <iterator> header.
+
+ \see GenericMember, GenericValue::MemberIterator, GenericValue::ConstMemberIterator
+ */
+template <bool Const, typename Encoding, typename Allocator>
+class GenericMemberIterator
+ : public std::iterator<std::random_access_iterator_tag
+ , typename internal::MaybeAddConst<Const,GenericMember<Encoding,Allocator> >::Type> {
+
+ friend class GenericValue<Encoding,Allocator>;
+ template <bool, typename, typename> friend class GenericMemberIterator;
+
+ typedef GenericMember<Encoding,Allocator> PlainType;
+ typedef typename internal::MaybeAddConst<Const,PlainType>::Type ValueType;
+ typedef std::iterator<std::random_access_iterator_tag,ValueType> BaseType;
+
+public:
+ //! Iterator type itself
+ typedef GenericMemberIterator Iterator;
+ //! Constant iterator type
+ typedef GenericMemberIterator<true,Encoding,Allocator> ConstIterator;
+ //! Non-constant iterator type
+ typedef GenericMemberIterator<false,Encoding,Allocator> NonConstIterator;
+
+ //! Pointer to (const) GenericMember
+ typedef typename BaseType::pointer Pointer;
+ //! Reference to (const) GenericMember
+ typedef typename BaseType::reference Reference;
+ //! Signed integer type (e.g. \c ptrdiff_t)
+ typedef typename BaseType::difference_type DifferenceType;
+
+ //! Default constructor (singular value)
+ /*! Creates an iterator pointing to no element.
+ \note All operations, except for comparisons, are undefined on such values.
+ */
+ GenericMemberIterator() : ptr_() {}
+
+ //! Iterator conversions to more const
+ /*!
+ \param it (Non-const) iterator to copy from
+
+ Allows the creation of an iterator from another GenericMemberIterator
+ that is "less const". Especially, creating a non-constant iterator
+ from a constant iterator are disabled:
+ \li const -> non-const (not ok)
+ \li const -> const (ok)
+ \li non-const -> const (ok)
+ \li non-const -> non-const (ok)
+
+ \note If the \c Const template parameter is already \c false, this
+ constructor effectively defines a regular copy-constructor.
+ Otherwise, the copy constructor is implicitly defined.
+ */
+ GenericMemberIterator(const NonConstIterator & it) : ptr_(it.ptr_) {}
+
+ //! @name stepping
+ //@{
+ Iterator& operator++(){ ++ptr_; return *this; }
+ Iterator& operator--(){ --ptr_; return *this; }
+ Iterator operator++(int){ Iterator old(*this); ++ptr_; return old; }
+ Iterator operator--(int){ Iterator old(*this); --ptr_; return old; }
+ //@}
+
+ //! @name increment/decrement
+ //@{
+ Iterator operator+(DifferenceType n) const { return Iterator(ptr_+n); }
+ Iterator operator-(DifferenceType n) const { return Iterator(ptr_-n); }
+
+ Iterator& operator+=(DifferenceType n) { ptr_+=n; return *this; }
+ Iterator& operator-=(DifferenceType n) { ptr_-=n; return *this; }
+ //@}
+
+ //! @name relations
+ //@{
+ bool operator==(ConstIterator that) const { return ptr_ == that.ptr_; }
+ bool operator!=(ConstIterator that) const { return ptr_ != that.ptr_; }
+ bool operator<=(ConstIterator that) const { return ptr_ <= that.ptr_; }
+ bool operator>=(ConstIterator that) const { return ptr_ >= that.ptr_; }
+ bool operator< (ConstIterator that) const { return ptr_ < that.ptr_; }
+ bool operator> (ConstIterator that) const { return ptr_ > that.ptr_; }
+ //@}
+
+ //! @name dereference
+ //@{
+ Reference operator*() const { return *ptr_; }
+ Pointer operator->() const { return ptr_; }
+ Reference operator[](DifferenceType n) const { return ptr_[n]; }
+ //@}
+
+ //! Distance
+ DifferenceType operator-(ConstIterator that) const { return ptr_-that.ptr_; }
+
+private:
+ //! Internal constructor from plain pointer
+ explicit GenericMemberIterator(Pointer p) : ptr_(p) {}
+
+ Pointer ptr_; //!< raw pointer
+};
+
+#else // RAPIDJSON_NOMEMBERITERATORCLASS
+
+// class-based member iterator implementation disabled, use plain pointers
+
+template <bool Const, typename Encoding, typename Allocator>
+struct GenericMemberIterator;
+
+//! non-const GenericMemberIterator
+template <typename Encoding, typename Allocator>
+struct GenericMemberIterator<false,Encoding,Allocator> {
+ //! use plain pointer as iterator type
+ typedef GenericMember<Encoding,Allocator>* Iterator;
+};
+//! const GenericMemberIterator
+template <typename Encoding, typename Allocator>
+struct GenericMemberIterator<true,Encoding,Allocator> {
+ //! use plain const pointer as iterator type
+ typedef const GenericMember<Encoding,Allocator>* Iterator;
+};
+
+#endif // RAPIDJSON_NOMEMBERITERATORCLASS
+
+///////////////////////////////////////////////////////////////////////////////
+// GenericStringRef
+
+//! Reference to a constant string (not taking a copy)
+/*!
+ \tparam CharType character type of the string
+
+ This helper class is used to automatically infer constant string
+ references for string literals, especially from \c const \b (!)
+ character arrays.
+
+ The main use is for creating JSON string values without copying the
+ source string via an \ref Allocator. This requires that the referenced
+ string pointers have a sufficient lifetime, which exceeds the lifetime
+ of the associated GenericValue.
+
+ \b Example
+ \code
+ Value v("foo"); // ok, no need to copy & calculate length
+ const char foo[] = "foo";
+ v.SetString(foo); // ok
+
+ const char* bar = foo;
+ // Value x(bar); // not ok, can't rely on bar's lifetime
+ Value x(StringRef(bar)); // lifetime explicitly guaranteed by user
+ Value y(StringRef(bar, 3)); // ok, explicitly pass length
+ \endcode
+
+ \see StringRef, GenericValue::SetString
+*/
+template<typename CharType>
+struct GenericStringRef {
+ typedef CharType Ch; //!< character type of the string
+
+ //! Create string reference from \c const character array
+ /*!
+ This constructor implicitly creates a constant string reference from
+ a \c const character array. It has better performance than
+ \ref StringRef(const CharType*) by inferring the string \ref length
+ from the array length, and also supports strings containing null
+ characters.
+
+ \tparam N length of the string, automatically inferred
+
+ \param str Constant character array, lifetime assumed to be longer
+ than the use of the string in e.g. a GenericValue
+
+ \post \ref s == str
+
+ \note Constant complexity.
+ \note There is a hidden, private overload to disallow references to
+ non-const character arrays to be created via this constructor.
+ By this, e.g. function-scope arrays used to be filled via
+ \c snprintf are excluded from consideration.
+ In such cases, the referenced string should be \b copied to the
+ GenericValue instead.
+ */
+ template<SizeType N>
+ GenericStringRef(const CharType (&str)[N]) RAPIDJSON_NOEXCEPT
+ : s(str), length(N-1) {}
+
+ //! Explicitly create string reference from \c const character pointer
+ /*!
+ This constructor can be used to \b explicitly create a reference to
+ a constant string pointer.
+
+ \see StringRef(const CharType*)
+
+ \param str Constant character pointer, lifetime assumed to be longer
+ than the use of the string in e.g. a GenericValue
+
+ \post \ref s == str
+
+ \note There is a hidden, private overload to disallow references to
+ non-const character arrays to be created via this constructor.
+ By this, e.g. function-scope arrays used to be filled via
+ \c snprintf are excluded from consideration.
+ In such cases, the referenced string should be \b copied to the
+ GenericValue instead.
+ */
+ explicit GenericStringRef(const CharType* str)
+ : s(str), length(internal::StrLen(str)){ RAPIDJSON_ASSERT(s != NULL); }
+
+ //! Create constant string reference from pointer and length
+ /*! \param str constant string, lifetime assumed to be longer than the use of the string in e.g. a GenericValue
+ \param len length of the string, excluding the trailing NULL terminator
+
+ \post \ref s == str && \ref length == len
+ \note Constant complexity.
+ */
+ GenericStringRef(const CharType* str, SizeType len)
+ : s(str), length(len) { RAPIDJSON_ASSERT(s != NULL); }
+
+ GenericStringRef(const GenericStringRef& original) = default;
+
+ //! implicit conversion to plain CharType pointer
+ operator const Ch *() const { return s; }
+
+ const Ch* const s; //!< plain CharType pointer
+ const SizeType length; //!< length of the string (excluding the trailing NULL terminator)
+
+private:
+ //! Disallow copy-assignment
+ GenericStringRef operator=(const GenericStringRef&);
+ //! Disallow construction from non-const array
+ template<SizeType N>
+ GenericStringRef(CharType (&str)[N]) /* = delete */;
+};
+
+//! Mark a character pointer as constant string
+/*! Mark a plain character pointer as a "string literal". This function
+ can be used to avoid copying a character string to be referenced as a
+ value in a JSON GenericValue object, if the string's lifetime is known
+ to be valid long enough.
+ \tparam CharType Character type of the string
+ \param str Constant string, lifetime assumed to be longer than the use of the string in e.g. a GenericValue
+ \return GenericStringRef string reference object
+ \relatesalso GenericStringRef
+
+ \see GenericValue::GenericValue(StringRefType), GenericValue::operator=(StringRefType), GenericValue::SetString(StringRefType), GenericValue::PushBack(StringRefType, Allocator&), GenericValue::AddMember
+*/
+template<typename CharType>
+inline GenericStringRef<CharType> StringRef(const CharType* str) {
+ return GenericStringRef<CharType>(str, internal::StrLen(str));
+}
+
+//! Mark a character pointer as constant string
+/*! Mark a plain character pointer as a "string literal". This function
+ can be used to avoid copying a character string to be referenced as a
+ value in a JSON GenericValue object, if the string's lifetime is known
+ to be valid long enough.
+
+ This version has better performance with supplied length, and also
+ supports string containing null characters.
+
+ \tparam CharType character type of the string
+ \param str Constant string, lifetime assumed to be longer than the use of the string in e.g. a GenericValue
+ \param length The length of source string.
+ \return GenericStringRef string reference object
+ \relatesalso GenericStringRef
+*/
+template<typename CharType>
+inline GenericStringRef<CharType> StringRef(const CharType* str, size_t length) {
+ return GenericStringRef<CharType>(str, SizeType(length));
+}
+
+#if RAPIDJSON_HAS_STDSTRING
+//! Mark a string object as constant string
+/*! Mark a string object (e.g. \c std::string) as a "string literal".
+ This function can be used to avoid copying a string to be referenced as a
+ value in a JSON GenericValue object, if the string's lifetime is known
+ to be valid long enough.
+
+ \tparam CharType character type of the string
+ \param str Constant string, lifetime assumed to be longer than the use of the string in e.g. a GenericValue
+ \return GenericStringRef string reference object
+ \relatesalso GenericStringRef
+ \note Requires the definition of the preprocessor symbol \ref RAPIDJSON_HAS_STDSTRING.
+*/
+template<typename CharType>
+inline GenericStringRef<CharType> StringRef(const std::basic_string<CharType>& str) {
+ return GenericStringRef<CharType>(str.data(), SizeType(str.size()));
+}
+#endif
+
+///////////////////////////////////////////////////////////////////////////////
+// GenericValue type traits
+namespace internal {
+
+template <typename T, typename Encoding = void, typename Allocator = void>
+struct IsGenericValueImpl : FalseType {};
+
+// select candidates according to nested encoding and allocator types
+template <typename T> struct IsGenericValueImpl<T, typename Void<typename T::EncodingType>::Type, typename Void<typename T::AllocatorType>::Type>
+ : IsBaseOf<GenericValue<typename T::EncodingType, typename T::AllocatorType>, T>::Type {};
+
+// helper to match arbitrary GenericValue instantiations, including derived classes
+template <typename T> struct IsGenericValue : IsGenericValueImpl<T>::Type {};
+
+} // namespace internal
+
+///////////////////////////////////////////////////////////////////////////////
+// GenericValue
+
+//! Represents a JSON value. Use Value for UTF8 encoding and default allocator.
+/*!
+ A JSON value can be one of 7 types. This class is a variant type supporting
+ these types.
+
+ Use the Value if UTF8 and default allocator
+
+ \tparam Encoding Encoding of the value. (Even non-string values need to have the same encoding in a document)
+ \tparam Allocator Allocator type for allocating memory of object, array and string.
+*/
+template <typename Encoding, typename Allocator = MemoryPoolAllocator<> >
+class GenericValue {
+public:
+ //! Name-value pair in an object.
+ typedef GenericMember<Encoding, Allocator> Member;
+ typedef Encoding EncodingType; //!< Encoding type from template parameter.
+ typedef Allocator AllocatorType; //!< Allocator type from template parameter.
+ typedef typename Encoding::Ch Ch; //!< Character type derived from Encoding.
+ typedef GenericStringRef<Ch> StringRefType; //!< Reference to a constant string
+ typedef typename GenericMemberIterator<false,Encoding,Allocator>::Iterator MemberIterator; //!< Member iterator for iterating in object.
+ typedef typename GenericMemberIterator<true,Encoding,Allocator>::Iterator ConstMemberIterator; //!< Constant member iterator for iterating in object.
+ typedef GenericValue* ValueIterator; //!< Value iterator for iterating in array.
+ typedef const GenericValue* ConstValueIterator; //!< Constant value iterator for iterating in array.
+
+ //!@name Constructors and destructor.
+ //@{
+
+ //! Default constructor creates a null value.
+ GenericValue() RAPIDJSON_NOEXCEPT : data_(), flags_(kNullFlag) {}
+
+#if RAPIDJSON_HAS_CXX11_RVALUE_REFS
+ //! Move constructor in C++11
+ GenericValue(GenericValue&& rhs) RAPIDJSON_NOEXCEPT : data_(rhs.data_), flags_(rhs.flags_) {
+ rhs.flags_ = kNullFlag; // give up contents
+ }
+#endif
+
+private:
+ //! Copy constructor is not permitted.
+ GenericValue(const GenericValue& rhs);
+
+public:
+
+ //! Constructor with JSON value type.
+ /*! This creates a Value of specified type with default content.
+ \param type Type of the value.
+ \note Default content for number is zero.
+ */
+ explicit GenericValue(Type type) RAPIDJSON_NOEXCEPT : data_(), flags_() {
+ static const unsigned defaultFlags[7] = {
+ kNullFlag, kFalseFlag, kTrueFlag, kObjectFlag, kArrayFlag, kShortStringFlag,
+ kNumberAnyFlag
+ };
+ RAPIDJSON_ASSERT(type <= kNumberType);
+ flags_ = defaultFlags[type];
+
+ // Use ShortString to store empty string.
+ if (type == kStringType)
+ data_.ss.SetLength(0);
+ }
+
+ //! Explicit copy constructor (with allocator)
+ /*! Creates a copy of a Value by using the given Allocator
+ \tparam SourceAllocator allocator of \c rhs
+ \param rhs Value to copy from (read-only)
+ \param allocator Allocator for allocating copied elements and buffers. Commonly use GenericDocument::GetAllocator().
+ \see CopyFrom()
+ */
+ template< typename SourceAllocator >
+ GenericValue(const GenericValue<Encoding, SourceAllocator>& rhs, Allocator & allocator);
+
+ //! Constructor for boolean value.
+ /*! \param b Boolean value
+ \note This constructor is limited to \em real boolean values and rejects
+ implicitly converted types like arbitrary pointers. Use an explicit cast
+ to \c bool, if you want to construct a boolean JSON value in such cases.
+ */
+#ifndef RAPIDJSON_DOXYGEN_RUNNING // hide SFINAE from Doxygen
+ template <typename T>
+ explicit GenericValue(T b, RAPIDJSON_ENABLEIF((internal::IsSame<T,bool>))) RAPIDJSON_NOEXCEPT
+#else
+ explicit GenericValue(bool b) RAPIDJSON_NOEXCEPT
+#endif
+ : data_(), flags_(b ? kTrueFlag : kFalseFlag) {
+ // safe-guard against failing SFINAE
+ RAPIDJSON_STATIC_ASSERT((internal::IsSame<bool,T>::Value));
+ }
+
+ //! Constructor for int value.
+ explicit GenericValue(int i) RAPIDJSON_NOEXCEPT : data_(), flags_(kNumberIntFlag) {
+ data_.n.i64 = i;
+ if (i >= 0)
+ flags_ |= kUintFlag | kUint64Flag;
+ }
+
+ //! Constructor for unsigned value.
+ explicit GenericValue(unsigned u) RAPIDJSON_NOEXCEPT : data_(), flags_(kNumberUintFlag) {
+ data_.n.u64 = u;
+ if (!(u & 0x80000000))
+ flags_ |= kIntFlag | kInt64Flag;
+ }
+
+ //! Constructor for int64_t value.
+ explicit GenericValue(int64_t i64) RAPIDJSON_NOEXCEPT : data_(), flags_(kNumberInt64Flag) {
+ data_.n.i64 = i64;
+ if (i64 >= 0) {
+ flags_ |= kNumberUint64Flag;
+ if (!(static_cast<uint64_t>(i64) & RAPIDJSON_UINT64_C2(0xFFFFFFFF, 0x00000000)))
+ flags_ |= kUintFlag;
+ if (!(static_cast<uint64_t>(i64) & RAPIDJSON_UINT64_C2(0xFFFFFFFF, 0x80000000)))
+ flags_ |= kIntFlag;
+ }
+ else if (i64 >= static_cast<int64_t>(RAPIDJSON_UINT64_C2(0xFFFFFFFF, 0x80000000)))
+ flags_ |= kIntFlag;
+ }
+
+ //! Constructor for uint64_t value.
+ explicit GenericValue(uint64_t u64) RAPIDJSON_NOEXCEPT : data_(), flags_(kNumberUint64Flag) {
+ data_.n.u64 = u64;
+ if (!(u64 & RAPIDJSON_UINT64_C2(0x80000000, 0x00000000)))
+ flags_ |= kInt64Flag;
+ if (!(u64 & RAPIDJSON_UINT64_C2(0xFFFFFFFF, 0x00000000)))
+ flags_ |= kUintFlag;
+ if (!(u64 & RAPIDJSON_UINT64_C2(0xFFFFFFFF, 0x80000000)))
+ flags_ |= kIntFlag;
+ }
+
+ //! Constructor for double value.
+ explicit GenericValue(double d) RAPIDJSON_NOEXCEPT : data_(), flags_(kNumberDoubleFlag) { data_.n.d = d; }
+
+ //! Constructor for constant string (i.e. do not make a copy of string)
+ GenericValue(const Ch* s, SizeType length) RAPIDJSON_NOEXCEPT : data_(), flags_() { SetStringRaw(StringRef(s, length)); }
+
+ //! Constructor for constant string (i.e. do not make a copy of string)
+ explicit GenericValue(StringRefType s) RAPIDJSON_NOEXCEPT : data_(), flags_() { SetStringRaw(s); }
+
+ //! Constructor for copy-string (i.e. do make a copy of string)
+ GenericValue(const Ch* s, SizeType length, Allocator& allocator) : data_(), flags_() { SetStringRaw(StringRef(s, length), allocator); }
+
+ //! Constructor for copy-string (i.e. do make a copy of string)
+ GenericValue(const Ch*s, Allocator& allocator) : data_(), flags_() { SetStringRaw(StringRef(s), allocator); }
+
+#if RAPIDJSON_HAS_STDSTRING
+ //! Constructor for copy-string from a string object (i.e. do make a copy of string)
+ /*! \note Requires the definition of the preprocessor symbol \ref RAPIDJSON_HAS_STDSTRING.
+ */
+ GenericValue(const std::basic_string<Ch>& s, Allocator& allocator) : data_(), flags_() { SetStringRaw(StringRef(s), allocator); }
+#endif
+
+ //! Destructor.
+ /*! Need to destruct elements of array, members of object, or copy-string.
+ */
+ ~GenericValue() {
+ if (Allocator::kNeedFree) { // Shortcut by Allocator's trait
+ switch(flags_) {
+ case kArrayFlag:
+ for (GenericValue* v = data_.a.elements; v != data_.a.elements + data_.a.size; ++v)
+ v->~GenericValue();
+ Allocator::Free(data_.a.elements);
+ break;
+
+ case kObjectFlag:
+ for (MemberIterator m = MemberBegin(); m != MemberEnd(); ++m)
+ m->~Member();
+ Allocator::Free(data_.o.members);
+ break;
+
+ case kCopyStringFlag:
+ Allocator::Free(const_cast<Ch*>(data_.s.str));
+ break;
+
+ default:
+ break; // Do nothing for other types.
+ }
+ }
+ }
+
+ //@}
+
+ //!@name Assignment operators
+ //@{
+
+ //! Assignment with move semantics.
+ /*! \param rhs Source of the assignment. It will become a null value after assignment.
+ */
+ GenericValue& operator=(GenericValue& rhs) RAPIDJSON_NOEXCEPT {
+ RAPIDJSON_ASSERT(this != &rhs);
+ this->~GenericValue();
+ RawAssign(rhs);
+ return *this;
+ }
+
+#if RAPIDJSON_HAS_CXX11_RVALUE_REFS
+ //! Move assignment in C++11
+ GenericValue& operator=(GenericValue&& rhs) RAPIDJSON_NOEXCEPT {
+ return *this = rhs.Move();
+ }
+#endif
+
+ //! Assignment of constant string reference (no copy)
+ /*! \param str Constant string reference to be assigned
+ \note This overload is needed to avoid clashes with the generic primitive type assignment overload below.
+ \see GenericStringRef, operator=(T)
+ */
+ GenericValue& operator=(StringRefType str) RAPIDJSON_NOEXCEPT {
+ GenericValue s(str);
+ return *this = s;
+ }
+
+ //! Assignment with primitive types.
+ /*! \tparam T Either \ref Type, \c int, \c unsigned, \c int64_t, \c uint64_t
+ \param value The value to be assigned.
+
+ \note The source type \c T explicitly disallows all pointer types,
+ especially (\c const) \ref Ch*. This helps avoiding implicitly
+ referencing character strings with insufficient lifetime, use
+ \ref SetString(const Ch*, Allocator&) (for copying) or
+ \ref StringRef() (to explicitly mark the pointer as constant) instead.
+ All other pointer types would implicitly convert to \c bool,
+ use \ref SetBool() instead.
+ */
+ template <typename T>
+ RAPIDJSON_DISABLEIF_RETURN((internal::IsPointer<T>), (GenericValue&))
+ operator=(T value) {
+ GenericValue v(value);
+ return *this = v;
+ }
+
+ //! Deep-copy assignment from Value
+ /*! Assigns a \b copy of the Value to the current Value object
+ \tparam SourceAllocator Allocator type of \c rhs
+ \param rhs Value to copy from (read-only)
+ \param allocator Allocator to use for copying
+ */
+ template <typename SourceAllocator>
+ GenericValue& CopyFrom(const GenericValue<Encoding, SourceAllocator>& rhs, Allocator& allocator) {
+ RAPIDJSON_ASSERT((void*)this != (void const*)&rhs);
+ this->~GenericValue();
+ new (this) GenericValue(rhs, allocator);
+ return *this;
+ }
+
+ //! Exchange the contents of this value with those of other.
+ /*!
+ \param other Another value.
+ \note Constant complexity.
+ */
+ GenericValue& Swap(GenericValue& other) RAPIDJSON_NOEXCEPT {
+ GenericValue temp;
+ temp.RawAssign(*this);
+ RawAssign(other);
+ other.RawAssign(temp);
+ return *this;
+ }
+
+ //! Prepare Value for move semantics
+ /*! \return *this */
+ GenericValue& Move() RAPIDJSON_NOEXCEPT { return *this; }
+ //@}
+
+ //!@name Equal-to and not-equal-to operators
+ //@{
+ //! Equal-to operator
+ /*!
+ \note If an object contains duplicated named member, comparing equality with any object is always \c false.
+ \note Linear time complexity (number of all values in the subtree and total lengths of all strings).
+ */
+ template <typename SourceAllocator>
+ bool operator==(const GenericValue<Encoding, SourceAllocator>& rhs) const {
+ typedef GenericValue<Encoding, SourceAllocator> RhsType;
+ if (GetType() != rhs.GetType())
+ return false;
+
+ switch (GetType()) {
+ case kObjectType: // Warning: O(n^2) inner-loop
+ if (data_.o.size != rhs.data_.o.size)
+ return false;
+ for (ConstMemberIterator lhsMemberItr = MemberBegin(); lhsMemberItr != MemberEnd(); ++lhsMemberItr) {
+ typename RhsType::ConstMemberIterator rhsMemberItr = rhs.FindMember(lhsMemberItr->name);
+ if (rhsMemberItr == rhs.MemberEnd() || lhsMemberItr->value != rhsMemberItr->value)
+ return false;
+ }
+ return true;
+
+ case kArrayType:
+ if (data_.a.size != rhs.data_.a.size)
+ return false;
+ for (SizeType i = 0; i < data_.a.size; i++)
+ if ((*this)[i] != rhs[i])
+ return false;
+ return true;
+
+ case kStringType:
+ return StringEqual(rhs);
+
+ case kNumberType:
+ if (IsDouble() || rhs.IsDouble()) {
+ double a = GetDouble(); // May convert from integer to double.
+ double b = rhs.GetDouble(); // Ditto
+ return a >= b && a <= b; // Prevent -Wfloat-equal
+ }
+ else
+ return data_.n.u64 == rhs.data_.n.u64;
+
+ default: // kTrueType, kFalseType, kNullType
+ return true;
+ }
+ }
+
+ //! Equal-to operator with const C-string pointer
+ bool operator==(const Ch* rhs) const { return *this == GenericValue(StringRef(rhs)); }
+
+#if RAPIDJSON_HAS_STDSTRING
+ //! Equal-to operator with string object
+ /*! \note Requires the definition of the preprocessor symbol \ref RAPIDJSON_HAS_STDSTRING.
+ */
+ bool operator==(const std::basic_string<Ch>& rhs) const { return *this == GenericValue(StringRef(rhs)); }
+#endif
+
+ //! Equal-to operator with primitive types
+ /*! \tparam T Either \ref Type, \c int, \c unsigned, \c int64_t, \c uint64_t, \c double, \c true, \c false
+ */
+ template <typename T> RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T>,internal::IsGenericValue<T> >), (bool)) operator==(const T& rhs) const { return *this == GenericValue(rhs); }
+
+ //! Not-equal-to operator
+ /*! \return !(*this == rhs)
+ */
+ template <typename SourceAllocator>
+ bool operator!=(const GenericValue<Encoding, SourceAllocator>& rhs) const { return !(*this == rhs); }
+
+ //! Not-equal-to operator with const C-string pointer
+ bool operator!=(const Ch* rhs) const { return !(*this == rhs); }
+
+ //! Not-equal-to operator with arbitrary types
+ /*! \return !(*this == rhs)
+ */
+ template <typename T> RAPIDJSON_DISABLEIF_RETURN((internal::IsGenericValue<T>), (bool)) operator!=(const T& rhs) const { return !(*this == rhs); }
+
+ //! Equal-to operator with arbitrary types (symmetric version)
+ /*! \return (rhs == lhs)
+ */
+ template <typename T> friend RAPIDJSON_DISABLEIF_RETURN((internal::IsGenericValue<T>), (bool)) operator==(const T& lhs, const GenericValue& rhs) { return rhs == lhs; }
+
+ //! Not-Equal-to operator with arbitrary types (symmetric version)
+ /*! \return !(rhs == lhs)
+ */
+ template <typename T> friend RAPIDJSON_DISABLEIF_RETURN((internal::IsGenericValue<T>), (bool)) operator!=(const T& lhs, const GenericValue& rhs) { return !(rhs == lhs); }
+ //@}
+
+ //!@name Type
+ //@{
+
+ Type GetType() const { return static_cast<Type>(flags_ & kTypeMask); }
+ bool IsNull() const { return flags_ == kNullFlag; }
+ bool IsFalse() const { return flags_ == kFalseFlag; }
+ bool IsTrue() const { return flags_ == kTrueFlag; }
+ bool IsBool() const { return (flags_ & kBoolFlag) != 0; }
+ bool IsObject() const { return flags_ == kObjectFlag; }
+ bool IsArray() const { return flags_ == kArrayFlag; }
+ bool IsNumber() const { return (flags_ & kNumberFlag) != 0; }
+ bool IsInt() const { return (flags_ & kIntFlag) != 0; }
+ bool IsUint() const { return (flags_ & kUintFlag) != 0; }
+ bool IsInt64() const { return (flags_ & kInt64Flag) != 0; }
+ bool IsUint64() const { return (flags_ & kUint64Flag) != 0; }
+ bool IsDouble() const { return (flags_ & kDoubleFlag) != 0; }
+ bool IsString() const { return (flags_ & kStringFlag) != 0; }
+
+ //@}
+
+ //!@name Null
+ //@{
+
+ GenericValue& SetNull() { this->~GenericValue(); new (this) GenericValue(); return *this; }
+
+ //@}
+
+ //!@name Bool
+ //@{
+
+ bool GetBool() const { RAPIDJSON_ASSERT(IsBool()); return flags_ == kTrueFlag; }
+ //!< Set boolean value
+ /*! \post IsBool() == true */
+ GenericValue& SetBool(bool b) { this->~GenericValue(); new (this) GenericValue(b); return *this; }
+
+ //@}
+
+ //!@name Object
+ //@{
+
+ //! Set this value as an empty object.
+ /*! \post IsObject() == true */
+ GenericValue& SetObject() { this->~GenericValue(); new (this) GenericValue(kObjectType); return *this; }
+
+ //! Get the number of members in the object.
+ SizeType MemberCount() const { RAPIDJSON_ASSERT(IsObject()); return data_.o.size; }
+
+ //! Check whether the object is empty.
+ bool ObjectEmpty() const { RAPIDJSON_ASSERT(IsObject()); return data_.o.size == 0; }
+
+ //! Get a value from an object associated with the name.
+ /*! \pre IsObject() == true
+ \tparam T Either \c Ch or \c const \c Ch (template used for disambiguation with \ref operator[](SizeType))
+ \note In version 0.1x, if the member is not found, this function returns a null value. This makes issue 7.
+ Since 0.2, if the name is not correct, it will assert.
+ If user is unsure whether a member exists, user should use HasMember() first.
+ A better approach is to use FindMember().
+ \note Linear time complexity.
+ */
+ template <typename T>
+ RAPIDJSON_DISABLEIF_RETURN((internal::NotExpr<internal::IsSame<typename internal::RemoveConst<T>::Type, Ch> >),(GenericValue&)) operator[](T* name) {
+ GenericValue n(StringRef(name));
+ return (*this)[n];
+ }
+ template <typename T>
+ RAPIDJSON_DISABLEIF_RETURN((internal::NotExpr<internal::IsSame<typename internal::RemoveConst<T>::Type, Ch> >),(const GenericValue&)) operator[](T* name) const { return const_cast<GenericValue&>(*this)[name]; }
+
+ //! Get a value from an object associated with the name.
+ /*! \pre IsObject() == true
+ \tparam SourceAllocator Allocator of the \c name value
+
+ \note Compared to \ref operator[](T*), this version is faster because it does not need a StrLen().
+ And it can also handle strings with embedded null characters.
+
+ \note Linear time complexity.
+ */
+ template <typename SourceAllocator>
+ GenericValue& operator[](const GenericValue<Encoding, SourceAllocator>& name) {
+ MemberIterator member = FindMember(name);
+ if (member != MemberEnd())
+ return member->value;
+ else {
+ RAPIDJSON_ASSERT(false); // see above note
+ static GenericValue NullValue;
+ return NullValue;
+ }
+ }
+ template <typename SourceAllocator>
+ const GenericValue& operator[](const GenericValue<Encoding, SourceAllocator>& name) const { return const_cast<GenericValue&>(*this)[name]; }
+
+ //! Const member iterator
+ /*! \pre IsObject() == true */
+ ConstMemberIterator MemberBegin() const { RAPIDJSON_ASSERT(IsObject()); return ConstMemberIterator(data_.o.members); }
+ //! Const \em past-the-end member iterator
+ /*! \pre IsObject() == true */
+ ConstMemberIterator MemberEnd() const { RAPIDJSON_ASSERT(IsObject()); return ConstMemberIterator(data_.o.members + data_.o.size); }
+ //! Member iterator
+ /*! \pre IsObject() == true */
+ MemberIterator MemberBegin() { RAPIDJSON_ASSERT(IsObject()); return MemberIterator(data_.o.members); }
+ //! \em Past-the-end member iterator
+ /*! \pre IsObject() == true */
+ MemberIterator MemberEnd() { RAPIDJSON_ASSERT(IsObject()); return MemberIterator(data_.o.members + data_.o.size); }
+
+ //! Check whether a member exists in the object.
+ /*!
+ \param name Member name to be searched.
+ \pre IsObject() == true
+ \return Whether a member with that name exists.
+ \note It is better to use FindMember() directly if you need the obtain the value as well.
+ \note Linear time complexity.
+ */
+ bool HasMember(const Ch* name) const { return FindMember(name) != MemberEnd(); }
+
+ //! Check whether a member exists in the object with GenericValue name.
+ /*!
+ This version is faster because it does not need a StrLen(). It can also handle string with null character.
+ \param name Member name to be searched.
+ \pre IsObject() == true
+ \return Whether a member with that name exists.
+ \note It is better to use FindMember() directly if you need the obtain the value as well.
+ \note Linear time complexity.
+ */
+ template <typename SourceAllocator>
+ bool HasMember(const GenericValue<Encoding, SourceAllocator>& name) const { return FindMember(name) != MemberEnd(); }
+
+ //! Find member by name.
+ /*!
+ \param name Member name to be searched.
+ \pre IsObject() == true
+ \return Iterator to member, if it exists.
+ Otherwise returns \ref MemberEnd().
+
+ \note Earlier versions of Rapidjson returned a \c NULL pointer, in case
+ the requested member doesn't exist. For consistency with e.g.
+ \c std::map, this has been changed to MemberEnd() now.
+ \note Linear time complexity.
+ */
+ MemberIterator FindMember(const Ch* name) {
+ GenericValue n(StringRef(name));
+ return FindMember(n);
+ }
+
+ ConstMemberIterator FindMember(const Ch* name) const { return const_cast<GenericValue&>(*this).FindMember(name); }
+
+ //! Find member by name.
+ /*!
+ This version is faster because it does not need a StrLen(). It can also handle string with null character.
+ \param name Member name to be searched.
+ \pre IsObject() == true
+ \return Iterator to member, if it exists.
+ Otherwise returns \ref MemberEnd().
+
+ \note Earlier versions of Rapidjson returned a \c NULL pointer, in case
+ the requested member doesn't exist. For consistency with e.g.
+ \c std::map, this has been changed to MemberEnd() now.
+ \note Linear time complexity.
+ */
+ template <typename SourceAllocator>
+ MemberIterator FindMember(const GenericValue<Encoding, SourceAllocator>& name) {
+ RAPIDJSON_ASSERT(IsObject());
+ RAPIDJSON_ASSERT(name.IsString());
+ MemberIterator member = MemberBegin();
+ for ( ; member != MemberEnd(); ++member)
+ if (name.StringEqual(member->name))
+ break;
+ return member;
+ }
+ template <typename SourceAllocator> ConstMemberIterator FindMember(const GenericValue<Encoding, SourceAllocator>& name) const { return const_cast<GenericValue&>(*this).FindMember(name); }
+
+ //! Add a member (name-value pair) to the object.
+ /*! \param name A string value as name of member.
+ \param value Value of any type.
+ \param allocator Allocator for reallocating memory. It must be the same one as used before. Commonly use GenericDocument::GetAllocator().
+ \return The value itself for fluent API.
+ \note The ownership of \c name and \c value will be transferred to this object on success.
+ \pre IsObject() && name.IsString()
+ \post name.IsNull() && value.IsNull()
+ \note Amortized Constant time complexity.
+ */
+ GenericValue& AddMember(GenericValue& name, GenericValue& value, Allocator& allocator) {
+ RAPIDJSON_ASSERT(IsObject());
+ RAPIDJSON_ASSERT(name.IsString());
+
+ Object& o = data_.o;
+ if (o.size >= o.capacity) {
+ if (o.capacity == 0) {
+ o.capacity = kDefaultObjectCapacity;
+ o.members = reinterpret_cast<Member*>(allocator.Malloc(o.capacity * sizeof(Member)));
+ }
+ else {
+ SizeType oldCapacity = o.capacity;
+ o.capacity += (oldCapacity + 1) / 2; // grow by factor 1.5
+ o.members = reinterpret_cast<Member*>(allocator.Realloc(o.members, oldCapacity * sizeof(Member), o.capacity * sizeof(Member)));
+ }
+ }
+ o.members[o.size].name.RawAssign(name);
+ o.members[o.size].value.RawAssign(value);
+ o.size++;
+ return *this;
+ }
+
+ //! Add a constant string value as member (name-value pair) to the object.
+ /*! \param name A string value as name of member.
+ \param value constant string reference as value of member.
+ \param allocator Allocator for reallocating memory. It must be the same one as used before. Commonly use GenericDocument::GetAllocator().
+ \return The value itself for fluent API.
+ \pre IsObject()
+ \note This overload is needed to avoid clashes with the generic primitive type AddMember(GenericValue&,T,Allocator&) overload below.
+ \note Amortized Constant time complexity.
+ */
+ GenericValue& AddMember(GenericValue& name, StringRefType value, Allocator& allocator) {
+ GenericValue v(value);
+ return AddMember(name, v, allocator);
+ }
+
+ //! Add any primitive value as member (name-value pair) to the object.
+ /*! \tparam T Either \ref Type, \c int, \c unsigned, \c int64_t, \c uint64_t
+ \param name A string value as name of member.
+ \param value Value of primitive type \c T as value of member
+ \param allocator Allocator for reallocating memory. Commonly use GenericDocument::GetAllocator().
+ \return The value itself for fluent API.
+ \pre IsObject()
+
+ \note The source type \c T explicitly disallows all pointer types,
+ especially (\c const) \ref Ch*. This helps avoiding implicitly
+ referencing character strings with insufficient lifetime, use
+ \ref AddMember(StringRefType, GenericValue&, Allocator&) or \ref
+ AddMember(StringRefType, StringRefType, Allocator&).
+ All other pointer types would implicitly convert to \c bool,
+ use an explicit cast instead, if needed.
+ \note Amortized Constant time complexity.
+ */
+ template <typename T>
+ RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T>, internal::IsGenericValue<T> >), (GenericValue&))
+ AddMember(GenericValue& name, T value, Allocator& allocator) {
+ GenericValue v(value);
+ return AddMember(name, v, allocator);
+ }
+
+#if RAPIDJSON_HAS_CXX11_RVALUE_REFS
+ GenericValue& AddMember(GenericValue&& name, GenericValue&& value, Allocator& allocator) {
+ return AddMember(name, value, allocator);
+ }
+ GenericValue& AddMember(GenericValue&& name, GenericValue& value, Allocator& allocator) {
+ return AddMember(name, value, allocator);
+ }
+ GenericValue& AddMember(GenericValue& name, GenericValue&& value, Allocator& allocator) {
+ return AddMember(name, value, allocator);
+ }
+ GenericValue& AddMember(StringRefType name, GenericValue&& value, Allocator& allocator) {
+ GenericValue n(name);
+ return AddMember(n, value, allocator);
+ }
+#endif // RAPIDJSON_HAS_CXX11_RVALUE_REFS
+
+
+ //! Add a member (name-value pair) to the object.
+ /*! \param name A constant string reference as name of member.
+ \param value Value of any type.
+ \param allocator Allocator for reallocating memory. It must be the same one as used before. Commonly use GenericDocument::GetAllocator().
+ \return The value itself for fluent API.
+ \note The ownership of \c value will be transferred to this object on success.
+ \pre IsObject()
+ \post value.IsNull()
+ \note Amortized Constant time complexity.
+ */
+ GenericValue& AddMember(StringRefType name, GenericValue& value, Allocator& allocator) {
+ GenericValue n(name);
+ return AddMember(n, value, allocator);
+ }
+
+ //! Add a constant string value as member (name-value pair) to the object.
+ /*! \param name A constant string reference as name of member.
+ \param value constant string reference as value of member.
+ \param allocator Allocator for reallocating memory. It must be the same one as used before. Commonly use GenericDocument::GetAllocator().
+ \return The value itself for fluent API.
+ \pre IsObject()
+ \note This overload is needed to avoid clashes with the generic primitive type AddMember(StringRefType,T,Allocator&) overload below.
+ \note Amortized Constant time complexity.
+ */
+ GenericValue& AddMember(StringRefType name, StringRefType value, Allocator& allocator) {
+ GenericValue v(value);
+ return AddMember(name, v, allocator);
+ }
+
+ //! Add any primitive value as member (name-value pair) to the object.
+ /*! \tparam T Either \ref Type, \c int, \c unsigned, \c int64_t, \c uint64_t
+ \param name A constant string reference as name of member.
+ \param value Value of primitive type \c T as value of member
+ \param allocator Allocator for reallocating memory. Commonly use GenericDocument::GetAllocator().
+ \return The value itself for fluent API.
+ \pre IsObject()
+
+ \note The source type \c T explicitly disallows all pointer types,
+ especially (\c const) \ref Ch*. This helps avoiding implicitly
+ referencing character strings with insufficient lifetime, use
+ \ref AddMember(StringRefType, GenericValue&, Allocator&) or \ref
+ AddMember(StringRefType, StringRefType, Allocator&).
+ All other pointer types would implicitly convert to \c bool,
+ use an explicit cast instead, if needed.
+ \note Amortized Constant time complexity.
+ */
+ template <typename T>
+ RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T>, internal::IsGenericValue<T> >), (GenericValue&))
+ AddMember(StringRefType name, T value, Allocator& allocator) {
+ GenericValue n(name);
+ return AddMember(n, value, allocator);
+ }
+
+ //! Remove all members in the object.
+ /*! This function do not deallocate memory in the object, i.e. the capacity is unchanged.
+ \note Linear time complexity.
+ */
+ void RemoveAllMembers() {
+ RAPIDJSON_ASSERT(IsObject());
+ for (MemberIterator m = MemberBegin(); m != MemberEnd(); ++m)
+ m->~Member();
+ data_.o.size = 0;
+ }
+
+ //! Remove a member in object by its name.
+ /*! \param name Name of member to be removed.
+ \return Whether the member existed.
+ \note This function may reorder the object members. Use \ref
+ EraseMember(ConstMemberIterator) if you need to preserve the
+ relative order of the remaining members.
+ \note Linear time complexity.
+ */
+ bool RemoveMember(const Ch* name) {
+ GenericValue n(StringRef(name));
+ return RemoveMember(n);
+ }
+
+ template <typename SourceAllocator>
+ bool RemoveMember(const GenericValue<Encoding, SourceAllocator>& name) {
+ MemberIterator m = FindMember(name);
+ if (m != MemberEnd()) {
+ RemoveMember(m);
+ return true;
+ }
+ else
+ return false;
+ }
+
+ //! Remove a member in object by iterator.
+ /*! \param m member iterator (obtained by FindMember() or MemberBegin()).
+ \return the new iterator after removal.
+ \note This function may reorder the object members. Use \ref
+ EraseMember(ConstMemberIterator) if you need to preserve the
+ relative order of the remaining members.
+ \note Constant time complexity.
+ */
+ MemberIterator RemoveMember(MemberIterator m) {
+ RAPIDJSON_ASSERT(IsObject());
+ RAPIDJSON_ASSERT(data_.o.size > 0);
+ RAPIDJSON_ASSERT(data_.o.members != 0);
+ RAPIDJSON_ASSERT(m >= MemberBegin() && m < MemberEnd());
+
+ MemberIterator last(data_.o.members + (data_.o.size - 1));
+ if (data_.o.size > 1 && m != last) {
+ // Move the last one to this place
+ *m = *last;
+ }
+ else {
+ // Only one left, just destroy
+ m->~Member();
+ }
+ --data_.o.size;
+ return m;
+ }
+
+ //! Remove a member from an object by iterator.
+ /*! \param pos iterator to the member to remove
+ \pre IsObject() == true && \ref MemberBegin() <= \c pos < \ref MemberEnd()
+ \return Iterator following the removed element.
+ If the iterator \c pos refers to the last element, the \ref MemberEnd() iterator is returned.
+ \note This function preserves the relative order of the remaining object
+ members. If you do not need this, use the more efficient \ref RemoveMember(MemberIterator).
+ \note Linear time complexity.
+ */
+ MemberIterator EraseMember(ConstMemberIterator pos) {
+ return EraseMember(pos, pos +1);
+ }
+
+ //! Remove members in the range [first, last) from an object.
+ /*! \param first iterator to the first member to remove
+ \param last iterator following the last member to remove
+ \pre IsObject() == true && \ref MemberBegin() <= \c first <= \c last <= \ref MemberEnd()
+ \return Iterator following the last removed element.
+ \note This function preserves the relative order of the remaining object
+ members.
+ \note Linear time complexity.
+ */
+ MemberIterator EraseMember(ConstMemberIterator first, ConstMemberIterator last) {
+ RAPIDJSON_ASSERT(IsObject());
+ RAPIDJSON_ASSERT(data_.o.size > 0);
+ RAPIDJSON_ASSERT(data_.o.members != 0);
+ RAPIDJSON_ASSERT(first >= MemberBegin());
+ RAPIDJSON_ASSERT(first <= last);
+ RAPIDJSON_ASSERT(last <= MemberEnd());
+
+ MemberIterator pos = MemberBegin() + (first - MemberBegin());
+ for (MemberIterator itr = pos; itr != last; ++itr)
+ itr->~Member();
+ std::memmove(&*pos, &*last, (MemberEnd() - last) * sizeof(Member));
+ data_.o.size -= (last - first);
+ return pos;
+ }
+
+ //@}
+
+ //!@name Array
+ //@{
+
+ //! Set this value as an empty array.
+ /*! \post IsArray == true */
+ GenericValue& SetArray() { this->~GenericValue(); new (this) GenericValue(kArrayType); return *this; }
+
+ //! Get the number of elements in array.
+ SizeType Size() const { RAPIDJSON_ASSERT(IsArray()); return data_.a.size; }
+
+ //! Get the capacity of array.
+ SizeType Capacity() const { RAPIDJSON_ASSERT(IsArray()); return data_.a.capacity; }
+
+ //! Check whether the array is empty.
+ bool Empty() const { RAPIDJSON_ASSERT(IsArray()); return data_.a.size == 0; }
+
+ //! Remove all elements in the array.
+ /*! This function do not deallocate memory in the array, i.e. the capacity is unchanged.
+ \note Linear time complexity.
+ */
+ void Clear() {
+ RAPIDJSON_ASSERT(IsArray());
+ for (SizeType i = 0; i < data_.a.size; ++i)
+ data_.a.elements[i].~GenericValue();
+ data_.a.size = 0;
+ }
+
+ //! Get an element from array by index.
+ /*! \pre IsArray() == true
+ \param index Zero-based index of element.
+ \see operator[](T*)
+ */
+ GenericValue& operator[](SizeType index) {
+ RAPIDJSON_ASSERT(IsArray());
+ RAPIDJSON_ASSERT(index < data_.a.size);
+ return data_.a.elements[index];
+ }
+ const GenericValue& operator[](SizeType index) const { return const_cast<GenericValue&>(*this)[index]; }
+
+ //! Element iterator
+ /*! \pre IsArray() == true */
+ ValueIterator Begin() { RAPIDJSON_ASSERT(IsArray()); return data_.a.elements; }
+ //! \em Past-the-end element iterator
+ /*! \pre IsArray() == true */
+ ValueIterator End() { RAPIDJSON_ASSERT(IsArray()); return data_.a.elements + data_.a.size; }
+ //! Constant element iterator
+ /*! \pre IsArray() == true */
+ ConstValueIterator Begin() const { return const_cast<GenericValue&>(*this).Begin(); }
+ //! Constant \em past-the-end element iterator
+ /*! \pre IsArray() == true */
+ ConstValueIterator End() const { return const_cast<GenericValue&>(*this).End(); }
+
+ //! Request the array to have enough capacity to store elements.
+ /*! \param newCapacity The capacity that the array at least need to have.
+ \param allocator Allocator for reallocating memory. It must be the same one as used before. Commonly use GenericDocument::GetAllocator().
+ \return The value itself for fluent API.
+ \note Linear time complexity.
+ */
+ GenericValue& Reserve(SizeType newCapacity, Allocator &allocator) {
+ RAPIDJSON_ASSERT(IsArray());
+ if (newCapacity > data_.a.capacity) {
+ data_.a.elements = (GenericValue*)allocator.Realloc(data_.a.elements, data_.a.capacity * sizeof(GenericValue), newCapacity * sizeof(GenericValue));
+ data_.a.capacity = newCapacity;
+ }
+ return *this;
+ }
+
+ //! Append a GenericValue at the end of the array.
+ /*! \param value Value to be appended.
+ \param allocator Allocator for reallocating memory. It must be the same one as used before. Commonly use GenericDocument::GetAllocator().
+ \pre IsArray() == true
+ \post value.IsNull() == true
+ \return The value itself for fluent API.
+ \note The ownership of \c value will be transferred to this array on success.
+ \note If the number of elements to be appended is known, calls Reserve() once first may be more efficient.
+ \note Amortized constant time complexity.
+ */
+ GenericValue& PushBack(GenericValue& value, Allocator& allocator) {
+ RAPIDJSON_ASSERT(IsArray());
+ if (data_.a.size >= data_.a.capacity)
+ Reserve(data_.a.capacity == 0 ? kDefaultArrayCapacity : (data_.a.capacity + (data_.a.capacity + 1) / 2), allocator);
+ data_.a.elements[data_.a.size++].RawAssign(value);
+ return *this;
+ }
+
+#if RAPIDJSON_HAS_CXX11_RVALUE_REFS
+ GenericValue& PushBack(GenericValue&& value, Allocator& allocator) {
+ return PushBack(value, allocator);
+ }
+#endif // RAPIDJSON_HAS_CXX11_RVALUE_REFS
+
+ //! Append a constant string reference at the end of the array.
+ /*! \param value Constant string reference to be appended.
+ \param allocator Allocator for reallocating memory. It must be the same one used previously. Commonly use GenericDocument::GetAllocator().
+ \pre IsArray() == true
+ \return The value itself for fluent API.
+ \note If the number of elements to be appended is known, calls Reserve() once first may be more efficient.
+ \note Amortized constant time complexity.
+ \see GenericStringRef
+ */
+ GenericValue& PushBack(StringRefType value, Allocator& allocator) {
+ return (*this).template PushBack<StringRefType>(value, allocator);
+ }
+
+ //! Append a primitive value at the end of the array.
+ /*! \tparam T Either \ref Type, \c int, \c unsigned, \c int64_t, \c uint64_t
+ \param value Value of primitive type T to be appended.
+ \param allocator Allocator for reallocating memory. It must be the same one as used before. Commonly use GenericDocument::GetAllocator().
+ \pre IsArray() == true
+ \return The value itself for fluent API.
+ \note If the number of elements to be appended is known, calls Reserve() once first may be more efficient.
+
+ \note The source type \c T explicitly disallows all pointer types,
+ especially (\c const) \ref Ch*. This helps avoiding implicitly
+ referencing character strings with insufficient lifetime, use
+ \ref PushBack(GenericValue&, Allocator&) or \ref
+ PushBack(StringRefType, Allocator&).
+ All other pointer types would implicitly convert to \c bool,
+ use an explicit cast instead, if needed.
+ \note Amortized constant time complexity.
+ */
+ template <typename T>
+ RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr<internal::IsPointer<T>, internal::IsGenericValue<T> >), (GenericValue&))
+ PushBack(T value, Allocator& allocator) {
+ GenericValue v(value);
+ return PushBack(v, allocator);
+ }
+
+ //! Remove the last element in the array.
+ /*!
+ \note Constant time complexity.
+ */
+ GenericValue& PopBack() {
+ RAPIDJSON_ASSERT(IsArray());
+ RAPIDJSON_ASSERT(!Empty());
+ data_.a.elements[--data_.a.size].~GenericValue();
+ return *this;
+ }
+
+ //! Remove an element of array by iterator.
+ /*!
+ \param pos iterator to the element to remove
+ \pre IsArray() == true && \ref Begin() <= \c pos < \ref End()
+ \return Iterator following the removed element. If the iterator pos refers to the last element, the End() iterator is returned.
+ \note Linear time complexity.
+ */
+ ValueIterator Erase(ConstValueIterator pos) {
+ return Erase(pos, pos + 1);
+ }
+
+ //! Remove elements in the range [first, last) of the array.
+ /*!
+ \param first iterator to the first element to remove
+ \param last iterator following the last element to remove
+ \pre IsArray() == true && \ref Begin() <= \c first <= \c last <= \ref End()
+ \return Iterator following the last removed element.
+ \note Linear time complexity.
+ */
+ ValueIterator Erase(ConstValueIterator first, ConstValueIterator last) {
+ RAPIDJSON_ASSERT(IsArray());
+ RAPIDJSON_ASSERT(data_.a.size > 0);
+ RAPIDJSON_ASSERT(data_.a.elements != 0);
+ RAPIDJSON_ASSERT(first >= Begin());
+ RAPIDJSON_ASSERT(first <= last);
+ RAPIDJSON_ASSERT(last <= End());
+ ValueIterator pos = Begin() + (first - Begin());
+ for (ValueIterator itr = pos; itr != last; ++itr)
+ itr->~GenericValue();
+ std::memmove(pos, last, (End() - last) * sizeof(GenericValue));
+ data_.a.size -= (last - first);
+ return pos;
+ }
+
+ //@}
+
+ //!@name Number
+ //@{
+
+ int GetInt() const { RAPIDJSON_ASSERT(flags_ & kIntFlag); return data_.n.i.i; }
+ unsigned GetUint() const { RAPIDJSON_ASSERT(flags_ & kUintFlag); return data_.n.u.u; }
+ int64_t GetInt64() const { RAPIDJSON_ASSERT(flags_ & kInt64Flag); return data_.n.i64; }
+ uint64_t GetUint64() const { RAPIDJSON_ASSERT(flags_ & kUint64Flag); return data_.n.u64; }
+
+ double GetDouble() const {
+ RAPIDJSON_ASSERT(IsNumber());
+ if ((flags_ & kDoubleFlag) != 0) return data_.n.d; // exact type, no conversion.
+ if ((flags_ & kIntFlag) != 0) return data_.n.i.i; // int -> double
+ if ((flags_ & kUintFlag) != 0) return data_.n.u.u; // unsigned -> double
+ if ((flags_ & kInt64Flag) != 0) return (double)data_.n.i64; // int64_t -> double (may lose precision)
+ RAPIDJSON_ASSERT((flags_ & kUint64Flag) != 0); return (double)data_.n.u64; // uint64_t -> double (may lose precision)
+ }
+
+ GenericValue& SetInt(int i) { this->~GenericValue(); new (this) GenericValue(i); return *this; }
+ GenericValue& SetUint(unsigned u) { this->~GenericValue(); new (this) GenericValue(u); return *this; }
+ GenericValue& SetInt64(int64_t i64) { this->~GenericValue(); new (this) GenericValue(i64); return *this; }
+ GenericValue& SetUint64(uint64_t u64) { this->~GenericValue(); new (this) GenericValue(u64); return *this; }
+ GenericValue& SetDouble(double d) { this->~GenericValue(); new (this) GenericValue(d); return *this; }
+
+ //@}
+
+ //!@name String
+ //@{
+
+ const Ch* GetString() const { RAPIDJSON_ASSERT(IsString()); return ((flags_ & kInlineStrFlag) ? data_.ss.str : data_.s.str); }
+
+ //! Get the length of string.
+ /*! Since rapidjson permits "\\u0000" in the json string, strlen(v.GetString()) may not equal to v.GetStringLength().
+ */
+ SizeType GetStringLength() const { RAPIDJSON_ASSERT(IsString()); return ((flags_ & kInlineStrFlag) ? (data_.ss.GetLength()) : data_.s.length); }
+
+ //! Set this value as a string without copying source string.
+ /*! This version has better performance with supplied length, and also support string containing null character.
+ \param s source string pointer.
+ \param length The length of source string, excluding the trailing null terminator.
+ \return The value itself for fluent API.
+ \post IsString() == true && GetString() == s && GetStringLength() == length
+ \see SetString(StringRefType)
+ */
+ GenericValue& SetString(const Ch* s, SizeType length) { return SetString(StringRef(s, length)); }
+
+ //! Set this value as a string without copying source string.
+ /*! \param s source string reference
+ \return The value itself for fluent API.
+ \post IsString() == true && GetString() == s && GetStringLength() == s.length
+ */
+ GenericValue& SetString(StringRefType s) { this->~GenericValue(); SetStringRaw(s); return *this; }
+
+ //! Set this value as a string by copying from source string.
+ /*! This version has better performance with supplied length, and also support string containing null character.
+ \param s source string.
+ \param length The length of source string, excluding the trailing null terminator.
+ \param allocator Allocator for allocating copied buffer. Commonly use GenericDocument::GetAllocator().
+ \return The value itself for fluent API.
+ \post IsString() == true && GetString() != s && strcmp(GetString(),s) == 0 && GetStringLength() == length
+ */
+ GenericValue& SetString(const Ch* s, SizeType length, Allocator& allocator) { this->~GenericValue(); SetStringRaw(StringRef(s, length), allocator); return *this; }
+
+ //! Set this value as a string by copying from source string.
+ /*! \param s source string.
+ \param allocator Allocator for allocating copied buffer. Commonly use GenericDocument::GetAllocator().
+ \return The value itself for fluent API.
+ \post IsString() == true && GetString() != s && strcmp(GetString(),s) == 0 && GetStringLength() == length
+ */
+ GenericValue& SetString(const Ch* s, Allocator& allocator) { return SetString(s, internal::StrLen(s), allocator); }
+
+#if RAPIDJSON_HAS_STDSTRING
+ //! Set this value as a string by copying from source string.
+ /*! \param s source string.
+ \param allocator Allocator for allocating copied buffer. Commonly use GenericDocument::GetAllocator().
+ \return The value itself for fluent API.
+ \post IsString() == true && GetString() != s.data() && strcmp(GetString(),s.data() == 0 && GetStringLength() == s.size()
+ \note Requires the definition of the preprocessor symbol \ref RAPIDJSON_HAS_STDSTRING.
+ */
+ GenericValue& SetString(const std::basic_string<Ch>& s, Allocator& allocator) { return SetString(s.data(), s.size(), allocator); }
+#endif
+
+ //@}
+
+ //! Generate events of this value to a Handler.
+ /*! This function adopts the GoF visitor pattern.
+ Typical usage is to output this JSON value as JSON text via Writer, which is a Handler.
+ It can also be used to deep clone this value via GenericDocument, which is also a Handler.
+ \tparam Handler type of handler.
+ \param handler An object implementing concept Handler.
+ */
+ template <typename Handler>
+ bool Accept(Handler& handler) const {
+ switch(GetType()) {
+ case kNullType: return handler.Null();
+ case kFalseType: return handler.Bool(false);
+ case kTrueType: return handler.Bool(true);
+
+ case kObjectType:
+ if (!handler.StartObject())
+ return false;
+ for (ConstMemberIterator m = MemberBegin(); m != MemberEnd(); ++m) {
+ RAPIDJSON_ASSERT(m->name.IsString()); // User may change the type of name by MemberIterator.
+ if (!handler.Key(m->name.GetString(), m->name.GetStringLength(), (m->name.flags_ & kCopyFlag) != 0))
+ return false;
+ if (!m->value.Accept(handler))
+ return false;
+ }
+ return handler.EndObject(data_.o.size);
+
+ case kArrayType:
+ if (!handler.StartArray())
+ return false;
+ for (GenericValue* v = data_.a.elements; v != data_.a.elements + data_.a.size; ++v)
+ if (!v->Accept(handler))
+ return false;
+ return handler.EndArray(data_.a.size);
+
+ case kStringType:
+ return handler.String(GetString(), GetStringLength(), (flags_ & kCopyFlag) != 0);
+
+ default:
+ RAPIDJSON_ASSERT(GetType() == kNumberType);
+ if (IsInt()) return handler.Int(data_.n.i.i);
+ else if (IsUint()) return handler.Uint(data_.n.u.u);
+ else if (IsInt64()) return handler.Int64(data_.n.i64);
+ else if (IsUint64()) return handler.Uint64(data_.n.u64);
+ else return handler.Double(data_.n.d);
+ }
+ }
+
+private:
+ template <typename, typename> friend class GenericValue;
+ template <typename, typename, typename> friend class GenericDocument;
+
+ enum {
+ kBoolFlag = 0x100,
+ kNumberFlag = 0x200,
+ kIntFlag = 0x400,
+ kUintFlag = 0x800,
+ kInt64Flag = 0x1000,
+ kUint64Flag = 0x2000,
+ kDoubleFlag = 0x4000,
+ kStringFlag = 0x100000,
+ kCopyFlag = 0x200000,
+ kInlineStrFlag = 0x400000,
+
+ // Initial flags of different types.
+ kNullFlag = kNullType,
+ kTrueFlag = kTrueType | kBoolFlag,
+ kFalseFlag = kFalseType | kBoolFlag,
+ kNumberIntFlag = kNumberType | kNumberFlag | kIntFlag | kInt64Flag,
+ kNumberUintFlag = kNumberType | kNumberFlag | kUintFlag | kUint64Flag | kInt64Flag,
+ kNumberInt64Flag = kNumberType | kNumberFlag | kInt64Flag,
+ kNumberUint64Flag = kNumberType | kNumberFlag | kUint64Flag,
+ kNumberDoubleFlag = kNumberType | kNumberFlag | kDoubleFlag,
+ kNumberAnyFlag = kNumberType | kNumberFlag | kIntFlag | kInt64Flag | kUintFlag | kUint64Flag | kDoubleFlag,
+ kConstStringFlag = kStringType | kStringFlag,
+ kCopyStringFlag = kStringType | kStringFlag | kCopyFlag,
+ kShortStringFlag = kStringType | kStringFlag | kCopyFlag | kInlineStrFlag,
+ kObjectFlag = kObjectType,
+ kArrayFlag = kArrayType,
+
+ kTypeMask = 0xFF // bitwise-and with mask of 0xFF can be optimized by compiler
+ };
+
+ static const SizeType kDefaultArrayCapacity = 16;
+ static const SizeType kDefaultObjectCapacity = 16;
+
+ struct String {
+ const Ch* str;
+ SizeType length;
+ unsigned hashcode; //!< reserved
+ }; // 12 bytes in 32-bit mode, 16 bytes in 64-bit mode
+
+ // implementation detail: ShortString can represent zero-terminated strings up to MaxSize chars
+ // (excluding the terminating zero) and store a value to determine the length of the contained
+ // string in the last character str[LenPos] by storing "MaxSize - length" there. If the string
+ // to store has the maximal length of MaxSize then str[LenPos] will be 0 and therefore act as
+ // the string terminator as well. For getting the string length back from that value just use
+ // "MaxSize - str[LenPos]".
+ // This allows to store 11-chars strings in 32-bit mode and 15-chars strings in 64-bit mode
+ // inline (for `UTF8`-encoded strings).
+ struct ShortString {
+ enum { MaxChars = sizeof(String) / sizeof(Ch), MaxSize = MaxChars - 1, LenPos = MaxSize };
+ Ch str[MaxChars];
+
+ inline static bool Usable(SizeType len) { return (MaxSize >= len); }
+ inline void SetLength(SizeType len) { str[LenPos] = (Ch)(MaxSize - len); }
+ inline SizeType GetLength() const { return (SizeType)(MaxSize - str[LenPos]); }
+ }; // at most as many bytes as "String" above => 12 bytes in 32-bit mode, 16 bytes in 64-bit mode
+
+ // By using proper binary layout, retrieval of different integer types do not need conversions.
+ union Number {
+#if RAPIDJSON_ENDIAN == RAPIDJSON_LITTLEENDIAN
+ struct I {
+ int i;
+ char padding[4];
+ }i;
+ struct U {
+ unsigned u;
+ char padding2[4];
+ }u;
+#else
+ struct I {
+ char padding[4];
+ int i;
+ }i;
+ struct U {
+ char padding2[4];
+ unsigned u;
+ }u;
+#endif
+ int64_t i64;
+ uint64_t u64;
+ double d;
+ }; // 8 bytes
+
+ struct Object {
+ Member* members;
+ SizeType size;
+ SizeType capacity;
+ }; // 12 bytes in 32-bit mode, 16 bytes in 64-bit mode
+
+ struct Array {
+ GenericValue* elements;
+ SizeType size;
+ SizeType capacity;
+ }; // 12 bytes in 32-bit mode, 16 bytes in 64-bit mode
+
+ union Data {
+ String s;
+ ShortString ss;
+ Number n;
+ Object o;
+ Array a;
+ }; // 12 bytes in 32-bit mode, 16 bytes in 64-bit mode
+
+ // Initialize this value as array with initial data, without calling destructor.
+ void SetArrayRaw(GenericValue* values, SizeType count, Allocator& allocator) {
+ flags_ = kArrayFlag;
+ if (count) {
+ data_.a.elements = (GenericValue*)allocator.Malloc(count * sizeof(GenericValue));
+ std::memcpy(data_.a.elements, values, count * sizeof(GenericValue));
+ }
+ else
+ data_.a.elements = NULL;
+ data_.a.size = data_.a.capacity = count;
+ }
+
+ //! Initialize this value as object with initial data, without calling destructor.
+ void SetObjectRaw(Member* members, SizeType count, Allocator& allocator) {
+ flags_ = kObjectFlag;
+ if (count) {
+ data_.o.members = (Member*)allocator.Malloc(count * sizeof(Member));
+ std::memcpy(data_.o.members, members, count * sizeof(Member));
+ }
+ else
+ data_.o.members = NULL;
+ data_.o.size = data_.o.capacity = count;
+ }
+
+ //! Initialize this value as constant string, without calling destructor.
+ void SetStringRaw(StringRefType s) RAPIDJSON_NOEXCEPT {
+ flags_ = kConstStringFlag;
+ data_.s.str = s;
+ data_.s.length = s.length;
+ }
+
+ //! Initialize this value as copy string with initial data, without calling destructor.
+ void SetStringRaw(StringRefType s, Allocator& allocator) {
+ Ch* str = NULL;
+ if(ShortString::Usable(s.length)) {
+ flags_ = kShortStringFlag;
+ data_.ss.SetLength(s.length);
+ str = data_.ss.str;
+ } else {
+ flags_ = kCopyStringFlag;
+ data_.s.length = s.length;
+ str = (Ch *)allocator.Malloc((s.length + 1) * sizeof(Ch));
+ data_.s.str = str;
+ }
+ std::memcpy(str, s, s.length * sizeof(Ch));
+ str[s.length] = '\0';
+ }
+
+ //! Assignment without calling destructor
+ void RawAssign(GenericValue& rhs) RAPIDJSON_NOEXCEPT {
+ data_ = rhs.data_;
+ flags_ = rhs.flags_;
+ rhs.flags_ = kNullFlag;
+ }
+
+ template <typename SourceAllocator>
+ bool StringEqual(const GenericValue<Encoding, SourceAllocator>& rhs) const {
+ RAPIDJSON_ASSERT(IsString());
+ RAPIDJSON_ASSERT(rhs.IsString());
+
+ const SizeType len1 = GetStringLength();
+ const SizeType len2 = rhs.GetStringLength();
+ if(len1 != len2) { return false; }
+
+ const Ch* const str1 = GetString();
+ const Ch* const str2 = rhs.GetString();
+ if(str1 == str2) { return true; } // fast path for constant string
+
+ return (std::memcmp(str1, str2, sizeof(Ch) * len1) == 0);
+ }
+
+ Data data_;
+ unsigned flags_;
+};
+
+//! GenericValue with UTF8 encoding
+typedef GenericValue<UTF8<> > Value;
+
+///////////////////////////////////////////////////////////////////////////////
+// GenericDocument
+
+//! A document for parsing JSON text as DOM.
+/*!
+ \note implements Handler concept
+ \tparam Encoding Encoding for both parsing and string storage.
+ \tparam Allocator Allocator for allocating memory for the DOM
+ \tparam StackAllocator Allocator for allocating memory for stack during parsing.
+ \warning Although GenericDocument inherits from GenericValue, the API does \b not provide any virtual functions, especially no virtual destructor. To avoid memory leaks, do not \c delete a GenericDocument object via a pointer to a GenericValue.
+*/
+template <typename Encoding, typename Allocator = MemoryPoolAllocator<>, typename StackAllocator = CrtAllocator>
+class GenericDocument : public GenericValue<Encoding, Allocator> {
+public:
+ typedef typename Encoding::Ch Ch; //!< Character type derived from Encoding.
+ typedef GenericValue<Encoding, Allocator> ValueType; //!< Value type of the document.
+ typedef Allocator AllocatorType; //!< Allocator type from template parameter.
+
+ //! Constructor
+ /*! \param allocator Optional allocator for allocating memory.
+ \param stackCapacity Optional initial capacity of stack in bytes.
+ \param stackAllocator Optional allocator for allocating memory for stack.
+ */
+ GenericDocument(Allocator* allocator = 0, size_t stackCapacity = kDefaultStackCapacity, StackAllocator* stackAllocator = 0) :
+ allocator_(allocator), ownAllocator_(0), stack_(stackAllocator, stackCapacity), parseResult_()
+ {
+ if (!allocator_)
+ ownAllocator_ = allocator_ = RAPIDJSON_NEW(Allocator());
+ }
+
+#if RAPIDJSON_HAS_CXX11_RVALUE_REFS
+ //! Move constructor in C++11
+ GenericDocument(GenericDocument&& rhs) RAPIDJSON_NOEXCEPT
+ : ValueType(std::move(rhs)),
+ allocator_(rhs.allocator_),
+ ownAllocator_(rhs.ownAllocator_),
+ stack_(std::move(rhs.stack_)),
+ parseResult_(rhs.parseResult_)
+ {
+ rhs.allocator_ = 0;
+ rhs.ownAllocator_ = 0;
+ rhs.parseResult_ = ParseResult();
+ }
+#endif
+
+ ~GenericDocument() {
+ Destroy();
+ }
+
+#if RAPIDJSON_HAS_CXX11_RVALUE_REFS
+ //! Move assignment in C++11
+ GenericDocument& operator=(GenericDocument&& rhs) RAPIDJSON_NOEXCEPT
+ {
+ // The cast to ValueType is necessary here, because otherwise it would
+ // attempt to call GenericValue's templated assignment operator.
+ ValueType::operator=(std::forward<ValueType>(rhs));
+
+ // Calling the destructor here would prematurely call stack_'s destructor
+ Destroy();
+
+ allocator_ = rhs.allocator_;
+ ownAllocator_ = rhs.ownAllocator_;
+ stack_ = std::move(rhs.stack_);
+ parseResult_ = rhs.parseResult_;
+
+ rhs.allocator_ = 0;
+ rhs.ownAllocator_ = 0;
+ rhs.parseResult_ = ParseResult();
+
+ return *this;
+ }
+#endif
+
+ //!@name Parse from stream
+ //!@{
+
+ //! Parse JSON text from an input stream (with Encoding conversion)
+ /*! \tparam parseFlags Combination of \ref ParseFlag.
+ \tparam SourceEncoding Encoding of input stream
+ \tparam InputStream Type of input stream, implementing Stream concept
+ \param is Input stream to be parsed.
+ \return The document itself for fluent API.
+ */
+ template <unsigned parseFlags, typename SourceEncoding, typename InputStream>
+ GenericDocument& ParseStream(InputStream& is) {
+ ValueType::SetNull(); // Remove existing root if exist
+ GenericReader<SourceEncoding, Encoding, Allocator> reader(&GetAllocator());
+ ClearStackOnExit scope(*this);
+ parseResult_ = reader.template Parse<parseFlags>(is, *this);
+ if (parseResult_) {
+ RAPIDJSON_ASSERT(stack_.GetSize() == sizeof(ValueType)); // Got one and only one root object
+ this->RawAssign(*stack_.template Pop<ValueType>(1)); // Add this-> to prevent issue 13.
+ }
+ return *this;
+ }
+
+ //! Parse JSON text from an input stream
+ /*! \tparam parseFlags Combination of \ref ParseFlag.
+ \tparam InputStream Type of input stream, implementing Stream concept
+ \param is Input stream to be parsed.
+ \return The document itself for fluent API.
+ */
+ template <unsigned parseFlags, typename InputStream>
+ GenericDocument& ParseStream(InputStream& is) {
+ return ParseStream<parseFlags, Encoding, InputStream>(is);
+ }
+
+ //! Parse JSON text from an input stream (with \ref kParseDefaultFlags)
+ /*! \tparam InputStream Type of input stream, implementing Stream concept
+ \param is Input stream to be parsed.
+ \return The document itself for fluent API.
+ */
+ template <typename InputStream>
+ GenericDocument& ParseStream(InputStream& is) {
+ return ParseStream<kParseDefaultFlags, Encoding, InputStream>(is);
+ }
+ //!@}
+
+ //!@name Parse in-place from mutable string
+ //!@{
+
+ //! Parse JSON text from a mutable string
+ /*! \tparam parseFlags Combination of \ref ParseFlag.
+ \param str Mutable zero-terminated string to be parsed.
+ \return The document itself for fluent API.
+ */
+ template <unsigned parseFlags>
+ GenericDocument& ParseInsitu(Ch* str) {
+ GenericInsituStringStream<Encoding> s(str);
+ return ParseStream<parseFlags | kParseInsituFlag>(s);
+ }
+
+ //! Parse JSON text from a mutable string (with \ref kParseDefaultFlags)
+ /*! \param str Mutable zero-terminated string to be parsed.
+ \return The document itself for fluent API.
+ */
+ GenericDocument& ParseInsitu(Ch* str) {
+ return ParseInsitu<kParseDefaultFlags>(str);
+ }
+ //!@}
+
+ //!@name Parse from read-only string
+ //!@{
+
+ //! Parse JSON text from a read-only string (with Encoding conversion)
+ /*! \tparam parseFlags Combination of \ref ParseFlag (must not contain \ref kParseInsituFlag).
+ \tparam SourceEncoding Transcoding from input Encoding
+ \param str Read-only zero-terminated string to be parsed.
+ */
+ template <unsigned parseFlags, typename SourceEncoding>
+ GenericDocument& Parse(const Ch* str) {
+ RAPIDJSON_ASSERT(!(parseFlags & kParseInsituFlag));
+ GenericStringStream<SourceEncoding> s(str);
+ return ParseStream<parseFlags, SourceEncoding>(s);
+ }
+
+ //! Parse JSON text from a read-only string
+ /*! \tparam parseFlags Combination of \ref ParseFlag (must not contain \ref kParseInsituFlag).
+ \param str Read-only zero-terminated string to be parsed.
+ */
+ template <unsigned parseFlags>
+ GenericDocument& Parse(const Ch* str) {
+ return Parse<parseFlags, Encoding>(str);
+ }
+
+ //! Parse JSON text from a read-only string (with \ref kParseDefaultFlags)
+ /*! \param str Read-only zero-terminated string to be parsed.
+ */
+ GenericDocument& Parse(const Ch* str) {
+ return Parse<kParseDefaultFlags>(str);
+ }
+ //!@}
+
+ //!@name Handling parse errors
+ //!@{
+
+ //! Whether a parse error has occured in the last parsing.
+ bool HasParseError() const { return parseResult_.IsError(); }
+
+ //! Get the \ref ParseErrorCode of last parsing.
+ ParseErrorCode GetParseError() const { return parseResult_.Code(); }
+
+ //! Get the position of last parsing error in input, 0 otherwise.
+ size_t GetErrorOffset() const { return parseResult_.Offset(); }
+
+ //!@}
+
+ //! Get the allocator of this document.
+ Allocator& GetAllocator() { return *allocator_; }
+
+ //! Get the capacity of stack in bytes.
+ size_t GetStackCapacity() const { return stack_.GetCapacity(); }
+
+private:
+ // clear stack on any exit from ParseStream, e.g. due to exception
+ struct ClearStackOnExit {
+ explicit ClearStackOnExit(GenericDocument& d) : d_(d) {}
+ ~ClearStackOnExit() { d_.ClearStack(); }
+ private:
+ ClearStackOnExit(const ClearStackOnExit&);
+ ClearStackOnExit& operator=(const ClearStackOnExit&);
+ GenericDocument& d_;
+ };
+
+ // callers of the following private Handler functions
+ template <typename,typename,typename> friend class GenericReader; // for parsing
+ template <typename, typename> friend class GenericValue; // for deep copying
+
+ // Implementation of Handler
+ bool Null() { new (stack_.template Push<ValueType>()) ValueType(); return true; }
+ bool Bool(bool b) { new (stack_.template Push<ValueType>()) ValueType(b); return true; }
+ bool Int(int i) { new (stack_.template Push<ValueType>()) ValueType(i); return true; }
+ bool Uint(unsigned i) { new (stack_.template Push<ValueType>()) ValueType(i); return true; }
+ bool Int64(int64_t i) { new (stack_.template Push<ValueType>()) ValueType(i); return true; }
+ bool Uint64(uint64_t i) { new (stack_.template Push<ValueType>()) ValueType(i); return true; }
+ bool Double(double d) { new (stack_.template Push<ValueType>()) ValueType(d); return true; }
+
+ bool String(const Ch* str, SizeType length, bool copy) {
+ if (copy)
+ new (stack_.template Push<ValueType>()) ValueType(str, length, GetAllocator());
+ else
+ new (stack_.template Push<ValueType>()) ValueType(str, length);
+ return true;
+ }
+
+ bool StartObject() { new (stack_.template Push<ValueType>()) ValueType(kObjectType); return true; }
+
+ bool Key(const Ch* str, SizeType length, bool copy) { return String(str, length, copy); }
+
+ bool EndObject(SizeType memberCount) {
+ typename ValueType::Member* members = stack_.template Pop<typename ValueType::Member>(memberCount);
+ stack_.template Top<ValueType>()->SetObjectRaw(members, (SizeType)memberCount, GetAllocator());
+ return true;
+ }
+
+ bool StartArray() { new (stack_.template Push<ValueType>()) ValueType(kArrayType); return true; }
+
+ bool EndArray(SizeType elementCount) {
+ ValueType* elements = stack_.template Pop<ValueType>(elementCount);
+ stack_.template Top<ValueType>()->SetArrayRaw(elements, elementCount, GetAllocator());
+ return true;
+ }
+
+private:
+ //! Prohibit copying
+ GenericDocument(const GenericDocument&);
+ //! Prohibit assignment
+ GenericDocument& operator=(const GenericDocument&);
+
+ void ClearStack() {
+ if (Allocator::kNeedFree)
+ while (stack_.GetSize() > 0) // Here assumes all elements in stack array are GenericValue (Member is actually 2 GenericValue objects)
+ (stack_.template Pop<ValueType>(1))->~ValueType();
+ else
+ stack_.Clear();
+ stack_.ShrinkToFit();
+ }
+
+ void Destroy() {
+ RAPIDJSON_DELETE(ownAllocator_);
+ }
+
+ static const size_t kDefaultStackCapacity = 1024;
+ Allocator* allocator_;
+ Allocator* ownAllocator_;
+ internal::Stack<StackAllocator> stack_;
+ ParseResult parseResult_;
+};
+
+//! GenericDocument with UTF8 encoding
+typedef GenericDocument<UTF8<> > Document;
+
+// defined here due to the dependency on GenericDocument
+template <typename Encoding, typename Allocator>
+template <typename SourceAllocator>
+inline
+GenericValue<Encoding,Allocator>::GenericValue(const GenericValue<Encoding,SourceAllocator>& rhs, Allocator& allocator)
+{
+ switch (rhs.GetType()) {
+ case kObjectType:
+ case kArrayType: { // perform deep copy via SAX Handler
+ GenericDocument<Encoding,Allocator> d(&allocator);
+ rhs.Accept(d);
+ RawAssign(*d.stack_.template Pop<GenericValue>(1));
+ }
+ break;
+ case kStringType:
+ if (rhs.flags_ == kConstStringFlag) {
+ flags_ = rhs.flags_;
+ data_ = *reinterpret_cast<const Data*>(&rhs.data_);
+ } else {
+ SetStringRaw(StringRef(rhs.GetString(), rhs.GetStringLength()), allocator);
+ }
+ break;
+ default: // kNumberType, kTrueType, kFalseType, kNullType
+ flags_ = rhs.flags_;
+ data_ = *reinterpret_cast<const Data*>(&rhs.data_);
+ }
+}
+
+RAPIDJSON_NAMESPACE_END
+
+#if defined(_MSC_VER) || defined(__GNUC__)
+RAPIDJSON_DIAG_POP
+#endif
+
+#endif // RAPIDJSON_DOCUMENT_H_
diff --git a/libs/rapidjson/encodedstream.h b/libs/rapidjson/include/rapidjson/encodedstream.h
index 9a93b385f..7c8863fee 100644
--- a/libs/rapidjson/encodedstream.h
+++ b/libs/rapidjson/include/rapidjson/encodedstream.h
@@ -1,261 +1,261 @@
-// Tencent is pleased to support the open source community by making RapidJSON available.
-//
-// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
-//
-// Licensed under the MIT License (the "License"); you may not use this file except
-// in compliance with the License. You may obtain a copy of the License at
-//
-// http://opensource.org/licenses/MIT
-//
-// Unless required by applicable law or agreed to in writing, software distributed
-// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
-// CONDITIONS OF ANY KIND, either express or implied. See the License for the
-// specific language governing permissions and limitations under the License.
-
-#ifndef RAPIDJSON_ENCODEDSTREAM_H_
-#define RAPIDJSON_ENCODEDSTREAM_H_
-
-#include "rapidjson.h"
-
-#ifdef __GNUC__
-RAPIDJSON_DIAG_PUSH
-RAPIDJSON_DIAG_OFF(effc++)
-#endif
-
-RAPIDJSON_NAMESPACE_BEGIN
-
-//! Input byte stream wrapper with a statically bound encoding.
-/*!
- \tparam Encoding The interpretation of encoding of the stream. Either UTF8, UTF16LE, UTF16BE, UTF32LE, UTF32BE.
- \tparam InputByteStream Type of input byte stream. For example, FileReadStream.
-*/
-template <typename Encoding, typename InputByteStream>
-class EncodedInputStream {
- RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1);
-public:
- typedef typename Encoding::Ch Ch;
-
- EncodedInputStream(InputByteStream& is) : is_(is) {
- current_ = Encoding::TakeBOM(is_);
- }
-
- Ch Peek() const { return current_; }
- Ch Take() { Ch c = current_; current_ = Encoding::Take(is_); return c; }
- size_t Tell() const { return is_.Tell(); }
-
- // 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; }
-
-private:
- EncodedInputStream(const EncodedInputStream&);
- EncodedInputStream& operator=(const EncodedInputStream&);
-
- InputByteStream& is_;
- Ch current_;
-};
-
-//! Output byte stream wrapper with statically bound encoding.
-/*!
- \tparam Encoding The interpretation of encoding of the stream. Either UTF8, UTF16LE, UTF16BE, UTF32LE, UTF32BE.
- \tparam InputByteStream Type of input byte stream. For example, FileWriteStream.
-*/
-template <typename Encoding, typename OutputByteStream>
-class EncodedOutputStream {
- RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1);
-public:
- typedef typename Encoding::Ch Ch;
-
- EncodedOutputStream(OutputByteStream& os, bool putBOM = true) : os_(os) {
- if (putBOM)
- Encoding::PutBOM(os_);
- }
-
- void Put(Ch c) { Encoding::Put(os_, c); }
- void Flush() { os_.Flush(); }
-
- // Not implemented
- Ch Peek() const { RAPIDJSON_ASSERT(false); }
- Ch Take() { RAPIDJSON_ASSERT(false); }
- 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&);
- EncodedOutputStream& operator=(const EncodedOutputStream&);
-
- OutputByteStream& os_;
-};
-
-#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.
-/*!
- \tparam CharType Type of character for reading.
- \tparam InputByteStream type of input byte stream to be wrapped.
-*/
-template <typename CharType, typename InputByteStream>
-class AutoUTFInputStream {
- RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1);
-public:
- typedef CharType Ch;
-
- //! Constructor.
- /*!
- \param is input stream to be wrapped.
- \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) {
- RAPIDJSON_ASSERT(type >= kUTF8 && type <= kUTF32BE);
- DetectType();
- static const TakeFunc f[] = { RAPIDJSON_ENCODINGS_FUNC(Take) };
- takeFunc_ = f[type_];
- current_ = takeFunc_(*is_);
- }
-
- UTFType GetType() const { return type_; }
- bool HasBOM() const { return hasBOM_; }
-
- Ch Peek() const { return current_; }
- Ch Take() { Ch c = current_; current_ = takeFunc_(*is_); return c; }
- size_t Tell() const { return is_->Tell(); }
-
- // 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; }
-
-private:
- AutoUTFInputStream(const AutoUTFInputStream&);
- AutoUTFInputStream& operator=(const AutoUTFInputStream&);
-
- // Detect encoding type with BOM or RFC 4627
- void DetectType() {
- // BOM (Byte Order Mark):
- // 00 00 FE FF UTF-32BE
- // FF FE 00 00 UTF-32LE
- // FE FF UTF-16BE
- // FF FE UTF-16LE
- // EF BB BF UTF-8
-
- const unsigned char* c = (const unsigned char *)is_->Peek4();
- if (!c)
- return;
-
- unsigned bom = c[0] | (c[1] << 8) | (c[2] << 16) | (c[3] << 24);
- hasBOM_ = false;
- if (bom == 0xFFFE0000) { type_ = kUTF32BE; hasBOM_ = true; is_->Take(); is_->Take(); is_->Take(); is_->Take(); }
- else if (bom == 0x0000FEFF) { type_ = kUTF32LE; hasBOM_ = true; is_->Take(); is_->Take(); is_->Take(); is_->Take(); }
- else if ((bom & 0xFFFF) == 0xFFFE) { type_ = kUTF16BE; hasBOM_ = true; is_->Take(); is_->Take(); }
- else if ((bom & 0xFFFF) == 0xFEFF) { type_ = kUTF16LE; hasBOM_ = true; is_->Take(); is_->Take(); }
- else if ((bom & 0xFFFFFF) == 0xBFBBEF) { type_ = kUTF8; hasBOM_ = true; is_->Take(); is_->Take(); is_->Take(); }
-
- // RFC 4627: Section 3
- // "Since the first two characters of a JSON text will always be ASCII
- // characters [RFC0020], it is possible to determine whether an octet
- // stream is UTF-8, UTF-16 (BE or LE), or UTF-32 (BE or LE) by looking
- // at the pattern of nulls in the first four octets."
- // 00 00 00 xx UTF-32BE
- // 00 xx 00 xx UTF-16BE
- // xx 00 00 00 UTF-32LE
- // xx 00 xx 00 UTF-16LE
- // 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);
- switch (pattern) {
- case 0x08: type_ = kUTF32BE; break;
- case 0x0A: type_ = kUTF16BE; break;
- case 0x01: type_ = kUTF32LE; break;
- case 0x05: type_ = kUTF16LE; break;
- case 0x0F: type_ = kUTF8; break;
- default: break; // Use type defined by user.
- }
- }
-
- // Runtime check whether the size of character type is sufficient. It only perform checks with assertion.
- 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);
- InputByteStream* is_;
- UTFType type_;
- Ch current_;
- TakeFunc takeFunc_;
- bool hasBOM_;
-};
-
-//! Output stream wrapper with dynamically bound encoding and automatic encoding detection.
-/*!
- \tparam CharType Type of character for writing.
- \tparam InputByteStream type of output byte stream to be wrapped.
-*/
-template <typename CharType, typename OutputByteStream>
-class AutoUTFOutputStream {
- RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1);
-public:
- typedef CharType Ch;
-
- //! Constructor.
- /*!
- \param os output stream to be wrapped.
- \param type UTF encoding type.
- \param putBOM Whether to write BOM at the beginning of the stream.
- */
- AutoUTFOutputStream(OutputByteStream& os, UTFType type, bool putBOM) : os_(&os), type_(type) {
- 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) RAPIDJSON_ASSERT(sizeof(Ch) >= 2);
- if (type_ == kUTF32LE || type_ == kUTF32BE) RAPIDJSON_ASSERT(sizeof(Ch) >= 4);
-
- static const PutFunc f[] = { RAPIDJSON_ENCODINGS_FUNC(Put) };
- putFunc_ = f[type_];
-
- if (putBOM)
- PutBOM();
- }
-
- UTFType GetType() const { return type_; }
-
- void Put(Ch c) { putFunc_(*os_, c); }
- void Flush() { os_->Flush(); }
-
- // Not implemented
- Ch Peek() const { RAPIDJSON_ASSERT(false); }
- Ch Take() { RAPIDJSON_ASSERT(false); }
- 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&);
- AutoUTFOutputStream& operator=(const AutoUTFOutputStream&);
-
- void PutBOM() {
- typedef void (*PutBOMFunc)(OutputByteStream&);
- static const PutBOMFunc f[] = { RAPIDJSON_ENCODINGS_FUNC(PutBOM) };
- f[type_](*os_);
- }
-
- typedef void (*PutFunc)(OutputByteStream&, Ch);
-
- OutputByteStream* os_;
- UTFType type_;
- PutFunc putFunc_;
-};
-
-#undef RAPIDJSON_ENCODINGS_FUNC
-
-RAPIDJSON_NAMESPACE_END
-
-#ifdef __GNUC__
-RAPIDJSON_DIAG_POP
-#endif
-
-#endif // RAPIDJSON_FILESTREAM_H_
+// Tencent is pleased to support the open source community by making RapidJSON available.
+//
+// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
+//
+// Licensed under the MIT License (the "License"); you may not use this file except
+// in compliance with the License. You may obtain a copy of the License at
+//
+// http://opensource.org/licenses/MIT
+//
+// Unless required by applicable law or agreed to in writing, software distributed
+// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
+// CONDITIONS OF ANY KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations under the License.
+
+#ifndef RAPIDJSON_ENCODEDSTREAM_H_
+#define RAPIDJSON_ENCODEDSTREAM_H_
+
+#include "rapidjson.h"
+
+#ifdef __GNUC__
+RAPIDJSON_DIAG_PUSH
+RAPIDJSON_DIAG_OFF(effc++)
+#endif
+
+RAPIDJSON_NAMESPACE_BEGIN
+
+//! Input byte stream wrapper with a statically bound encoding.
+/*!
+ \tparam Encoding The interpretation of encoding of the stream. Either UTF8, UTF16LE, UTF16BE, UTF32LE, UTF32BE.
+ \tparam InputByteStream Type of input byte stream. For example, FileReadStream.
+*/
+template <typename Encoding, typename InputByteStream>
+class EncodedInputStream {
+ RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1);
+public:
+ typedef typename Encoding::Ch Ch;
+
+ EncodedInputStream(InputByteStream& is) : is_(is) {
+ current_ = Encoding::TakeBOM(is_);
+ }
+
+ Ch Peek() const { return current_; }
+ Ch Take() { Ch c = current_; current_ = Encoding::Take(is_); return c; }
+ size_t Tell() const { return is_.Tell(); }
+
+ // 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; }
+
+private:
+ EncodedInputStream(const EncodedInputStream&);
+ EncodedInputStream& operator=(const EncodedInputStream&);
+
+ InputByteStream& is_;
+ Ch current_;
+};
+
+//! Output byte stream wrapper with statically bound encoding.
+/*!
+ \tparam Encoding The interpretation of encoding of the stream. Either UTF8, UTF16LE, UTF16BE, UTF32LE, UTF32BE.
+ \tparam InputByteStream Type of input byte stream. For example, FileWriteStream.
+*/
+template <typename Encoding, typename OutputByteStream>
+class EncodedOutputStream {
+ RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1);
+public:
+ typedef typename Encoding::Ch Ch;
+
+ EncodedOutputStream(OutputByteStream& os, bool putBOM = true) : os_(os) {
+ if (putBOM)
+ Encoding::PutBOM(os_);
+ }
+
+ void Put(Ch c) { Encoding::Put(os_, c); }
+ void Flush() { os_.Flush(); }
+
+ // Not implemented
+ Ch Peek() const { RAPIDJSON_ASSERT(false); }
+ Ch Take() { RAPIDJSON_ASSERT(false); }
+ 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&);
+ EncodedOutputStream& operator=(const EncodedOutputStream&);
+
+ OutputByteStream& os_;
+};
+
+#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.
+/*!
+ \tparam CharType Type of character for reading.
+ \tparam InputByteStream type of input byte stream to be wrapped.
+*/
+template <typename CharType, typename InputByteStream>
+class AutoUTFInputStream {
+ RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1);
+public:
+ typedef CharType Ch;
+
+ //! Constructor.
+ /*!
+ \param is input stream to be wrapped.
+ \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) {
+ RAPIDJSON_ASSERT(type >= kUTF8 && type <= kUTF32BE);
+ DetectType();
+ static const TakeFunc f[] = { RAPIDJSON_ENCODINGS_FUNC(Take) };
+ takeFunc_ = f[type_];
+ current_ = takeFunc_(*is_);
+ }
+
+ UTFType GetType() const { return type_; }
+ bool HasBOM() const { return hasBOM_; }
+
+ Ch Peek() const { return current_; }
+ Ch Take() { Ch c = current_; current_ = takeFunc_(*is_); return c; }
+ size_t Tell() const { return is_->Tell(); }
+
+ // 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; }
+
+private:
+ AutoUTFInputStream(const AutoUTFInputStream&);
+ AutoUTFInputStream& operator=(const AutoUTFInputStream&);
+
+ // Detect encoding type with BOM or RFC 4627
+ void DetectType() {
+ // BOM (Byte Order Mark):
+ // 00 00 FE FF UTF-32BE
+ // FF FE 00 00 UTF-32LE
+ // FE FF UTF-16BE
+ // FF FE UTF-16LE
+ // EF BB BF UTF-8
+
+ const unsigned char* c = (const unsigned char *)is_->Peek4();
+ if (!c)
+ return;
+
+ unsigned bom = c[0] | (c[1] << 8) | (c[2] << 16) | (c[3] << 24);
+ hasBOM_ = false;
+ if (bom == 0xFFFE0000) { type_ = kUTF32BE; hasBOM_ = true; is_->Take(); is_->Take(); is_->Take(); is_->Take(); }
+ else if (bom == 0x0000FEFF) { type_ = kUTF32LE; hasBOM_ = true; is_->Take(); is_->Take(); is_->Take(); is_->Take(); }
+ else if ((bom & 0xFFFF) == 0xFFFE) { type_ = kUTF16BE; hasBOM_ = true; is_->Take(); is_->Take(); }
+ else if ((bom & 0xFFFF) == 0xFEFF) { type_ = kUTF16LE; hasBOM_ = true; is_->Take(); is_->Take(); }
+ else if ((bom & 0xFFFFFF) == 0xBFBBEF) { type_ = kUTF8; hasBOM_ = true; is_->Take(); is_->Take(); is_->Take(); }
+
+ // RFC 4627: Section 3
+ // "Since the first two characters of a JSON text will always be ASCII
+ // characters [RFC0020], it is possible to determine whether an octet
+ // stream is UTF-8, UTF-16 (BE or LE), or UTF-32 (BE or LE) by looking
+ // at the pattern of nulls in the first four octets."
+ // 00 00 00 xx UTF-32BE
+ // 00 xx 00 xx UTF-16BE
+ // xx 00 00 00 UTF-32LE
+ // xx 00 xx 00 UTF-16LE
+ // 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);
+ switch (pattern) {
+ case 0x08: type_ = kUTF32BE; break;
+ case 0x0A: type_ = kUTF16BE; break;
+ case 0x01: type_ = kUTF32LE; break;
+ case 0x05: type_ = kUTF16LE; break;
+ case 0x0F: type_ = kUTF8; break;
+ default: break; // Use type defined by user.
+ }
+ }
+
+ // Runtime check whether the size of character type is sufficient. It only perform checks with assertion.
+ 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);
+ InputByteStream* is_;
+ UTFType type_;
+ Ch current_;
+ TakeFunc takeFunc_;
+ bool hasBOM_;
+};
+
+//! Output stream wrapper with dynamically bound encoding and automatic encoding detection.
+/*!
+ \tparam CharType Type of character for writing.
+ \tparam InputByteStream type of output byte stream to be wrapped.
+*/
+template <typename CharType, typename OutputByteStream>
+class AutoUTFOutputStream {
+ RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1);
+public:
+ typedef CharType Ch;
+
+ //! Constructor.
+ /*!
+ \param os output stream to be wrapped.
+ \param type UTF encoding type.
+ \param putBOM Whether to write BOM at the beginning of the stream.
+ */
+ AutoUTFOutputStream(OutputByteStream& os, UTFType type, bool putBOM) : os_(&os), type_(type) {
+ 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) RAPIDJSON_ASSERT(sizeof(Ch) >= 2);
+ if (type_ == kUTF32LE || type_ == kUTF32BE) RAPIDJSON_ASSERT(sizeof(Ch) >= 4);
+
+ static const PutFunc f[] = { RAPIDJSON_ENCODINGS_FUNC(Put) };
+ putFunc_ = f[type_];
+
+ if (putBOM)
+ PutBOM();
+ }
+
+ UTFType GetType() const { return type_; }
+
+ void Put(Ch c) { putFunc_(*os_, c); }
+ void Flush() { os_->Flush(); }
+
+ // Not implemented
+ Ch Peek() const { RAPIDJSON_ASSERT(false); }
+ Ch Take() { RAPIDJSON_ASSERT(false); }
+ 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&);
+ AutoUTFOutputStream& operator=(const AutoUTFOutputStream&);
+
+ void PutBOM() {
+ typedef void (*PutBOMFunc)(OutputByteStream&);
+ static const PutBOMFunc f[] = { RAPIDJSON_ENCODINGS_FUNC(PutBOM) };
+ f[type_](*os_);
+ }
+
+ typedef void (*PutFunc)(OutputByteStream&, Ch);
+
+ OutputByteStream* os_;
+ UTFType type_;
+ PutFunc putFunc_;
+};
+
+#undef RAPIDJSON_ENCODINGS_FUNC
+
+RAPIDJSON_NAMESPACE_END
+
+#ifdef __GNUC__
+RAPIDJSON_DIAG_POP
+#endif
+
+#endif // RAPIDJSON_FILESTREAM_H_
diff --git a/libs/rapidjson/encodings.h b/libs/rapidjson/include/rapidjson/encodings.h
index bc3cd8139..90b46ed32 100644
--- a/libs/rapidjson/encodings.h
+++ b/libs/rapidjson/include/rapidjson/encodings.h
@@ -1,625 +1,625 @@
-// Tencent is pleased to support the open source community by making RapidJSON available.
-//
-// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
-//
-// Licensed under the MIT License (the "License"); you may not use this file except
-// in compliance with the License. You may obtain a copy of the License at
-//
-// http://opensource.org/licenses/MIT
-//
-// Unless required by applicable law or agreed to in writing, software distributed
-// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
-// CONDITIONS OF ANY KIND, either express or implied. See the License for the
-// specific language governing permissions and limitations under the License.
-
-#ifndef RAPIDJSON_ENCODINGS_H_
-#define RAPIDJSON_ENCODINGS_H_
-
-#include "rapidjson.h"
-
-#ifdef _MSC_VER
-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__)
-RAPIDJSON_DIAG_PUSH
-RAPIDJSON_DIAG_OFF(effc++)
-RAPIDJSON_DIAG_OFF(overflow)
-#endif
-
-RAPIDJSON_NAMESPACE_BEGIN
-
-///////////////////////////////////////////////////////////////////////////////
-// Encoding
-
-/*! \class rapidjson::Encoding
- \brief Concept for encoding of Unicode characters.
-
-\code
-concept Encoding {
- typename Ch; //! Type of character. A "character" is actually a code unit in unicode's definition.
-
- enum { supportUnicode = 1 }; // or 0 if not supporting unicode
-
- //! \brief Encode a Unicode codepoint to an output stream.
- //! \param os Output stream.
- //! \param codepoint An unicode codepoint, ranging from 0x0 to 0x10FFFF inclusively.
- template<typename OutputStream>
- static void Encode(OutputStream& os, unsigned codepoint);
-
- //! \brief Decode a Unicode codepoint from an input stream.
- //! \param is Input stream.
- //! \param codepoint Output of the unicode codepoint.
- //! \return true if a valid codepoint can be decoded from the stream.
- template <typename InputStream>
- static bool Decode(InputStream& is, unsigned* codepoint);
-
- //! \brief Validate one Unicode codepoint from an encoded stream.
- //! \param is Input stream to obtain codepoint.
- //! \param os Output for copying one codepoint.
- //! \return true if it is valid.
- //! \note This function just validating and copying the codepoint without actually decode it.
- template <typename InputStream, typename OutputStream>
- static bool Validate(InputStream& is, OutputStream& os);
-
- // The following functions are deal with byte streams.
-
- //! Take a character from input byte stream, skip BOM if exist.
- template <typename InputByteStream>
- static CharType TakeBOM(InputByteStream& is);
-
- //! Take a character from input byte stream.
- template <typename InputByteStream>
- static Ch Take(InputByteStream& is);
-
- //! Put BOM to output byte stream.
- template <typename OutputByteStream>
- static void PutBOM(OutputByteStream& os);
-
- //! Put a character to output byte stream.
- template <typename OutputByteStream>
- static void Put(OutputByteStream& os, Ch c);
-};
-\endcode
-*/
-
-///////////////////////////////////////////////////////////////////////////////
-// UTF8
-
-//! UTF-8 encoding.
-/*! http://en.wikipedia.org/wiki/UTF-8
- http://tools.ietf.org/html/rfc3629
- \tparam CharType Code unit for storing 8-bit UTF-8 data. Default is char.
- \note implements Encoding concept
-*/
-template<typename CharType = char>
-struct UTF8 {
- typedef CharType Ch;
-
- enum { supportUnicode = 1 };
-
- template<typename OutputStream>
- static void Encode(OutputStream& os, unsigned codepoint) {
- if (codepoint <= 0x7F)
- os.Put(static_cast<Ch>(codepoint & 0xFF));
- else if (codepoint <= 0x7FF) {
- os.Put(static_cast<Ch>(0xC0 | ((codepoint >> 6) & 0xFF)));
- os.Put(static_cast<Ch>(0x80 | ((codepoint & 0x3F))));
- }
- else if (codepoint <= 0xFFFF) {
- os.Put(static_cast<Ch>(0xE0 | ((codepoint >> 12) & 0xFF)));
- os.Put(static_cast<Ch>(0x80 | ((codepoint >> 6) & 0x3F)));
- os.Put(static_cast<Ch>(0x80 | (codepoint & 0x3F)));
- }
- else {
- 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)));
- os.Put(static_cast<Ch>(0x80 | (codepoint & 0x3F)));
- }
- }
-
- template <typename InputStream>
- static bool Decode(InputStream& is, unsigned* codepoint) {
-#define COPY() c = is.Take(); *codepoint = (*codepoint << 6) | ((unsigned char)c & 0x3Fu)
-#define TRANS(mask) result &= ((GetRange((unsigned char)c) & mask) != 0)
-#define TAIL() COPY(); TRANS(0x70)
- Ch c = is.Take();
- if (!(c & 0x80)) {
- *codepoint = (unsigned char)c;
- return true;
- }
-
- unsigned char type = GetRange((unsigned char)c);
- *codepoint = (0xFF >> type) & (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;
- default: return false;
- }
-#undef COPY
-#undef TRANS
-#undef 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((unsigned char)c) & mask) != 0)
-#define TAIL() COPY(); TRANS(0x70)
- Ch c;
- COPY();
- if (!(c & 0x80))
- return true;
-
- bool result = true;
- switch (GetRange((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;
- default: return false;
- }
-#undef COPY
-#undef TRANS
-#undef TAIL
- }
-
- static unsigned char GetRange(unsigned char c) {
- // Referring to DFA of http://bjoern.hoehrmann.de/utf-8/decoder/dfa/
- // With new mapping 1 -> 0x10, 7 -> 0x20, 9 -> 0x40, such that AND operation can test multiple types.
- static const unsigned char type[] = {
- 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
- 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
- 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
- 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
- 0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,
- 0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,
- 0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,
- 0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,
- 8,8,2,2,2,2,2,2,2,2,2,2,2,2,2,2, 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
- 10,3,3,3,3,3,3,3,3,3,3,3,3,4,3,3, 11,6,6,6,5,8,8,8,8,8,8,8,8,8,8,8,
- };
- return type[c];
- }
-
- template <typename InputByteStream>
- static CharType TakeBOM(InputByteStream& is) {
- RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1);
- Ch c = Take(is);
- if ((unsigned char)c != 0xEFu) return c;
- c = is.Take();
- if ((unsigned char)c != 0xBBu) return c;
- c = is.Take();
- if ((unsigned char)c != 0xBFu) return c;
- c = is.Take();
- return c;
- }
-
- template <typename InputByteStream>
- static Ch Take(InputByteStream& is) {
- RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1);
- return is.Take();
- }
-
- template <typename OutputByteStream>
- static void PutBOM(OutputByteStream& os) {
- RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1);
- os.Put(0xEFu); os.Put(0xBBu); os.Put(0xBFu);
- }
-
- template <typename OutputByteStream>
- static void Put(OutputByteStream& os, Ch c) {
- RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1);
- os.Put(static_cast<typename OutputByteStream::Ch>(c));
- }
-};
-
-///////////////////////////////////////////////////////////////////////////////
-// UTF16
-
-//! UTF-16 encoding.
-/*! http://en.wikipedia.org/wiki/UTF-16
- http://tools.ietf.org/html/rfc2781
- \tparam CharType Type for storing 16-bit UTF-16 data. Default is wchar_t. C++11 may use char16_t instead.
- \note implements Encoding concept
-
- \note For in-memory access, no need to concern endianness. The code units and code points are represented by CPU's endianness.
- For streaming, use UTF16LE and UTF16BE, which handle endianness.
-*/
-template<typename CharType = wchar_t>
-struct UTF16 {
- typedef CharType Ch;
- RAPIDJSON_STATIC_ASSERT(sizeof(Ch) >= 2);
-
- enum { supportUnicode = 1 };
-
- template<typename OutputStream>
- static void Encode(OutputStream& os, unsigned codepoint) {
- RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputStream::Ch) >= 2);
- if (codepoint <= 0xFFFF) {
- RAPIDJSON_ASSERT(codepoint < 0xD800 || codepoint > 0xDFFF); // Code point itself cannot be surrogate pair
- os.Put(static_cast<typename OutputStream::Ch>(codepoint));
- }
- else {
- RAPIDJSON_ASSERT(codepoint <= 0x10FFFF);
- unsigned v = codepoint - 0x10000;
- os.Put(static_cast<typename OutputStream::Ch>((v >> 10) | 0xD800));
- os.Put((v & 0x3FF) | 0xDC00);
- }
- }
-
- template <typename InputStream>
- static bool Decode(InputStream& is, unsigned* codepoint) {
- RAPIDJSON_STATIC_ASSERT(sizeof(typename InputStream::Ch) >= 2);
- Ch c = is.Take();
- if (c < 0xD800 || c > 0xDFFF) {
- *codepoint = c;
- return true;
- }
- else if (c <= 0xDBFF) {
- *codepoint = (c & 0x3FF) << 10;
- c = is.Take();
- *codepoint |= (c & 0x3FF);
- *codepoint += 0x10000;
- return c >= 0xDC00 && c <= 0xDFFF;
- }
- return false;
- }
-
- template <typename InputStream, typename OutputStream>
- static bool Validate(InputStream& is, OutputStream& os) {
- RAPIDJSON_STATIC_ASSERT(sizeof(typename InputStream::Ch) >= 2);
- RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputStream::Ch) >= 2);
- Ch c;
- os.Put(c = is.Take());
- if (c < 0xD800 || c > 0xDFFF)
- return true;
- else if (c <= 0xDBFF) {
- os.Put(c = is.Take());
- return c >= 0xDC00 && c <= 0xDFFF;
- }
- return false;
- }
-};
-
-//! UTF-16 little endian encoding.
-template<typename CharType = wchar_t>
-struct UTF16LE : UTF16<CharType> {
- template <typename InputByteStream>
- static CharType TakeBOM(InputByteStream& is) {
- RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1);
- CharType c = Take(is);
- return (unsigned short)c == 0xFEFFu ? Take(is) : c;
- }
-
- template <typename InputByteStream>
- static CharType Take(InputByteStream& is) {
- RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1);
- CharType c = (unsigned char)is.Take();
- c |= (unsigned char)is.Take() << 8;
- return c;
- }
-
- template <typename OutputByteStream>
- static void PutBOM(OutputByteStream& os) {
- RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1);
- os.Put(0xFFu); os.Put(0xFEu);
- }
-
- template <typename OutputByteStream>
- static void Put(OutputByteStream& os, CharType c) {
- RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1);
- os.Put(c & 0xFFu);
- os.Put((c >> 8) & 0xFFu);
- }
-};
-
-//! UTF-16 big endian encoding.
-template<typename CharType = wchar_t>
-struct UTF16BE : UTF16<CharType> {
- template <typename InputByteStream>
- static CharType TakeBOM(InputByteStream& is) {
- RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1);
- CharType c = Take(is);
- return (unsigned short)c == 0xFEFFu ? Take(is) : c;
- }
-
- template <typename InputByteStream>
- static CharType Take(InputByteStream& is) {
- RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1);
- CharType c = (unsigned char)is.Take() << 8;
- c |= (unsigned char)is.Take();
- return c;
- }
-
- template <typename OutputByteStream>
- static void PutBOM(OutputByteStream& os) {
- RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1);
- os.Put(0xFEu); os.Put(0xFFu);
- }
-
- template <typename OutputByteStream>
- static void Put(OutputByteStream& os, CharType c) {
- RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1);
- os.Put((c >> 8) & 0xFFu);
- os.Put(c & 0xFFu);
- }
-};
-
-///////////////////////////////////////////////////////////////////////////////
-// UTF32
-
-//! UTF-32 encoding.
-/*! http://en.wikipedia.org/wiki/UTF-32
- \tparam CharType Type for storing 32-bit UTF-32 data. Default is unsigned. C++11 may use char32_t instead.
- \note implements Encoding concept
-
- \note For in-memory access, no need to concern endianness. The code units and code points are represented by CPU's endianness.
- For streaming, use UTF32LE and UTF32BE, which handle endianness.
-*/
-template<typename CharType = unsigned>
-struct UTF32 {
- typedef CharType Ch;
- RAPIDJSON_STATIC_ASSERT(sizeof(Ch) >= 4);
-
- enum { supportUnicode = 1 };
-
- template<typename OutputStream>
- static void Encode(OutputStream& os, unsigned codepoint) {
- RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputStream::Ch) >= 4);
- RAPIDJSON_ASSERT(codepoint <= 0x10FFFF);
- os.Put(codepoint);
- }
-
- template <typename InputStream>
- static bool Decode(InputStream& is, unsigned* codepoint) {
- RAPIDJSON_STATIC_ASSERT(sizeof(typename InputStream::Ch) >= 4);
- Ch c = is.Take();
- *codepoint = c;
- return c <= 0x10FFFF;
- }
-
- template <typename InputStream, typename OutputStream>
- static bool Validate(InputStream& is, OutputStream& os) {
- RAPIDJSON_STATIC_ASSERT(sizeof(typename InputStream::Ch) >= 4);
- Ch c;
- os.Put(c = is.Take());
- return c <= 0x10FFFF;
- }
-};
-
-//! UTF-32 little endian enocoding.
-template<typename CharType = unsigned>
-struct UTF32LE : UTF32<CharType> {
- template <typename InputByteStream>
- static CharType TakeBOM(InputByteStream& is) {
- RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1);
- CharType c = Take(is);
- return (unsigned)c == 0x0000FEFFu ? Take(is) : c;
- }
-
- template <typename InputByteStream>
- static CharType Take(InputByteStream& is) {
- RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1);
- CharType c = (unsigned char)is.Take();
- c |= (unsigned char)is.Take() << 8;
- c |= (unsigned char)is.Take() << 16;
- c |= (unsigned char)is.Take() << 24;
- return c;
- }
-
- template <typename OutputByteStream>
- static void PutBOM(OutputByteStream& os) {
- RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1);
- os.Put(0xFFu); os.Put(0xFEu); os.Put(0x00u); os.Put(0x00u);
- }
-
- template <typename OutputByteStream>
- static void Put(OutputByteStream& os, CharType c) {
- RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1);
- os.Put(c & 0xFFu);
- os.Put((c >> 8) & 0xFFu);
- os.Put((c >> 16) & 0xFFu);
- os.Put((c >> 24) & 0xFFu);
- }
-};
-
-//! UTF-32 big endian encoding.
-template<typename CharType = unsigned>
-struct UTF32BE : UTF32<CharType> {
- template <typename InputByteStream>
- static CharType TakeBOM(InputByteStream& is) {
- RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1);
- CharType c = Take(is);
- return (unsigned)c == 0x0000FEFFu ? Take(is) : c;
- }
-
- template <typename InputByteStream>
- static CharType Take(InputByteStream& is) {
- RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1);
- CharType c = (unsigned char)is.Take() << 24;
- c |= (unsigned char)is.Take() << 16;
- c |= (unsigned char)is.Take() << 8;
- c |= (unsigned char)is.Take();
- return c;
- }
-
- template <typename OutputByteStream>
- static void PutBOM(OutputByteStream& os) {
- RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1);
- os.Put(0x00u); os.Put(0x00u); os.Put(0xFEu); os.Put(0xFFu);
- }
-
- template <typename OutputByteStream>
- static void Put(OutputByteStream& os, CharType c) {
- RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1);
- os.Put((c >> 24) & 0xFFu);
- os.Put((c >> 16) & 0xFFu);
- os.Put((c >> 8) & 0xFFu);
- os.Put(c & 0xFFu);
- }
-};
-
-///////////////////////////////////////////////////////////////////////////////
-// ASCII
-
-//! ASCII encoding.
-/*! http://en.wikipedia.org/wiki/ASCII
- \tparam CharType Code unit for storing 7-bit ASCII data. Default is char.
- \note implements Encoding concept
-*/
-template<typename CharType = char>
-struct ASCII {
- typedef CharType Ch;
-
- enum { supportUnicode = 0 };
-
- template<typename OutputStream>
- static void Encode(OutputStream& os, unsigned codepoint) {
- RAPIDJSON_ASSERT(codepoint <= 0x7F);
- os.Put(static_cast<Ch>(codepoint & 0xFF));
- }
-
- template <typename InputStream>
- static bool Decode(InputStream& is, unsigned* codepoint) {
- unsigned char c = static_cast<unsigned char>(is.Take());
- *codepoint = c;
- return c <= 0X7F;
- }
-
- template <typename InputStream, typename OutputStream>
- static bool Validate(InputStream& is, OutputStream& os) {
- unsigned char c = is.Take();
- os.Put(c);
- return c <= 0x7F;
- }
-
- template <typename InputByteStream>
- static CharType TakeBOM(InputByteStream& is) {
- RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1);
- Ch c = Take(is);
- return c;
- }
-
- template <typename InputByteStream>
- static Ch Take(InputByteStream& is) {
- RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1);
- return is.Take();
- }
-
- template <typename OutputByteStream>
- static void PutBOM(OutputByteStream& os) {
- RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1);
- (void)os;
- }
-
- template <typename OutputByteStream>
- static void Put(OutputByteStream& os, Ch c) {
- RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1);
- os.Put(static_cast<typename OutputByteStream::Ch>(c));
- }
-};
-
-///////////////////////////////////////////////////////////////////////////////
-// AutoUTF
-
-//! Runtime-specified UTF encoding type of a stream.
-enum UTFType {
- kUTF8 = 0, //!< UTF-8.
- kUTF16LE = 1, //!< UTF-16 little endian.
- kUTF16BE = 2, //!< UTF-16 big endian.
- kUTF32LE = 3, //!< UTF-32 little endian.
- kUTF32BE = 4 //!< UTF-32 big endian.
-};
-
-//! Dynamically select encoding according to stream's runtime-specified UTF encoding type.
-/*! \note This class can be used with AutoUTFInputtStream and AutoUTFOutputStream, which provides GetType().
-*/
-template<typename CharType>
-struct AutoUTF {
- typedef CharType Ch;
-
- enum { supportUnicode = 1 };
-
-#define RAPIDJSON_ENCODINGS_FUNC(x) UTF8<Ch>::x, UTF16LE<Ch>::x, UTF16BE<Ch>::x, UTF32LE<Ch>::x, UTF32BE<Ch>::x
-
- template<typename OutputStream>
- RAPIDJSON_FORCEINLINE static void Encode(OutputStream& os, unsigned codepoint) {
- typedef void (*EncodeFunc)(OutputStream&, unsigned);
- static const EncodeFunc f[] = { RAPIDJSON_ENCODINGS_FUNC(Encode) };
- (*f[os.GetType()])(os, codepoint);
- }
-
- template <typename InputStream>
- RAPIDJSON_FORCEINLINE static bool Decode(InputStream& is, unsigned* codepoint) {
- typedef bool (*DecodeFunc)(InputStream&, unsigned*);
- static const DecodeFunc f[] = { RAPIDJSON_ENCODINGS_FUNC(Decode) };
- return (*f[is.GetType()])(is, codepoint);
- }
-
- template <typename InputStream, typename OutputStream>
- RAPIDJSON_FORCEINLINE static bool Validate(InputStream& is, OutputStream& os) {
- typedef bool (*ValidateFunc)(InputStream&, OutputStream&);
- static const ValidateFunc f[] = { RAPIDJSON_ENCODINGS_FUNC(Validate) };
- return (*f[is.GetType()])(is, os);
- }
-
-#undef RAPIDJSON_ENCODINGS_FUNC
-};
-
-///////////////////////////////////////////////////////////////////////////////
-// Transcoder
-
-//! Encoding conversion.
-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>
- RAPIDJSON_FORCEINLINE static bool Transcode(InputStream& is, OutputStream& os) {
- unsigned codepoint;
- if (!SourceEncoding::Decode(is, &codepoint))
- return false;
- TargetEncoding::Encode(os, codepoint);
- return true;
- }
-
- //! Validate one Unicode codepoint from an encoded stream.
- template<typename InputStream, typename OutputStream>
- RAPIDJSON_FORCEINLINE static bool Validate(InputStream& is, OutputStream& os) {
- return Transcode(is, os); // Since source/target encoding is different, must transcode.
- }
-};
-
-//! Specialization of Transcoder with same source and target encoding.
-template<typename Encoding>
-struct Transcoder<Encoding, Encoding> {
- template<typename InputStream, typename OutputStream>
- RAPIDJSON_FORCEINLINE static bool Transcode(InputStream& is, OutputStream& os) {
- os.Put(is.Take()); // Just copy one code unit. This semantic is different from primary template class.
- return true;
- }
-
- template<typename InputStream, typename OutputStream>
- RAPIDJSON_FORCEINLINE static bool Validate(InputStream& is, OutputStream& os) {
- return Encoding::Validate(is, os); // source/target encoding are the same
- }
-};
-
-RAPIDJSON_NAMESPACE_END
-
-#if defined(__GNUC__) || defined(_MSV_VER)
-RAPIDJSON_DIAG_POP
-#endif
-
-#endif // RAPIDJSON_ENCODINGS_H_
+// Tencent is pleased to support the open source community by making RapidJSON available.
+//
+// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
+//
+// Licensed under the MIT License (the "License"); you may not use this file except
+// in compliance with the License. You may obtain a copy of the License at
+//
+// http://opensource.org/licenses/MIT
+//
+// Unless required by applicable law or agreed to in writing, software distributed
+// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
+// CONDITIONS OF ANY KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations under the License.
+
+#ifndef RAPIDJSON_ENCODINGS_H_
+#define RAPIDJSON_ENCODINGS_H_
+
+#include "rapidjson.h"
+
+#ifdef _MSC_VER
+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__)
+RAPIDJSON_DIAG_PUSH
+RAPIDJSON_DIAG_OFF(effc++)
+RAPIDJSON_DIAG_OFF(overflow)
+#endif
+
+RAPIDJSON_NAMESPACE_BEGIN
+
+///////////////////////////////////////////////////////////////////////////////
+// Encoding
+
+/*! \class rapidjson::Encoding
+ \brief Concept for encoding of Unicode characters.
+
+\code
+concept Encoding {
+ typename Ch; //! Type of character. A "character" is actually a code unit in unicode's definition.
+
+ enum { supportUnicode = 1 }; // or 0 if not supporting unicode
+
+ //! \brief Encode a Unicode codepoint to an output stream.
+ //! \param os Output stream.
+ //! \param codepoint An unicode codepoint, ranging from 0x0 to 0x10FFFF inclusively.
+ template<typename OutputStream>
+ static void Encode(OutputStream& os, unsigned codepoint);
+
+ //! \brief Decode a Unicode codepoint from an input stream.
+ //! \param is Input stream.
+ //! \param codepoint Output of the unicode codepoint.
+ //! \return true if a valid codepoint can be decoded from the stream.
+ template <typename InputStream>
+ static bool Decode(InputStream& is, unsigned* codepoint);
+
+ //! \brief Validate one Unicode codepoint from an encoded stream.
+ //! \param is Input stream to obtain codepoint.
+ //! \param os Output for copying one codepoint.
+ //! \return true if it is valid.
+ //! \note This function just validating and copying the codepoint without actually decode it.
+ template <typename InputStream, typename OutputStream>
+ static bool Validate(InputStream& is, OutputStream& os);
+
+ // The following functions are deal with byte streams.
+
+ //! Take a character from input byte stream, skip BOM if exist.
+ template <typename InputByteStream>
+ static CharType TakeBOM(InputByteStream& is);
+
+ //! Take a character from input byte stream.
+ template <typename InputByteStream>
+ static Ch Take(InputByteStream& is);
+
+ //! Put BOM to output byte stream.
+ template <typename OutputByteStream>
+ static void PutBOM(OutputByteStream& os);
+
+ //! Put a character to output byte stream.
+ template <typename OutputByteStream>
+ static void Put(OutputByteStream& os, Ch c);
+};
+\endcode
+*/
+
+///////////////////////////////////////////////////////////////////////////////
+// UTF8
+
+//! UTF-8 encoding.
+/*! http://en.wikipedia.org/wiki/UTF-8
+ http://tools.ietf.org/html/rfc3629
+ \tparam CharType Code unit for storing 8-bit UTF-8 data. Default is char.
+ \note implements Encoding concept
+*/
+template<typename CharType = char>
+struct UTF8 {
+ typedef CharType Ch;
+
+ enum { supportUnicode = 1 };
+
+ template<typename OutputStream>
+ static void Encode(OutputStream& os, unsigned codepoint) {
+ if (codepoint <= 0x7F)
+ os.Put(static_cast<Ch>(codepoint & 0xFF));
+ else if (codepoint <= 0x7FF) {
+ os.Put(static_cast<Ch>(0xC0 | ((codepoint >> 6) & 0xFF)));
+ os.Put(static_cast<Ch>(0x80 | ((codepoint & 0x3F))));
+ }
+ else if (codepoint <= 0xFFFF) {
+ os.Put(static_cast<Ch>(0xE0 | ((codepoint >> 12) & 0xFF)));
+ os.Put(static_cast<Ch>(0x80 | ((codepoint >> 6) & 0x3F)));
+ os.Put(static_cast<Ch>(0x80 | (codepoint & 0x3F)));
+ }
+ else {
+ 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)));
+ os.Put(static_cast<Ch>(0x80 | (codepoint & 0x3F)));
+ }
+ }
+
+ template <typename InputStream>
+ static bool Decode(InputStream& is, unsigned* codepoint) {
+#define COPY() c = is.Take(); *codepoint = (*codepoint << 6) | ((unsigned char)c & 0x3Fu)
+#define TRANS(mask) result &= ((GetRange((unsigned char)c) & mask) != 0)
+#define TAIL() COPY(); TRANS(0x70)
+ Ch c = is.Take();
+ if (!(c & 0x80)) {
+ *codepoint = (unsigned char)c;
+ return true;
+ }
+
+ unsigned char type = GetRange((unsigned char)c);
+ *codepoint = (0xFF >> type) & (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;
+ default: return false;
+ }
+#undef COPY
+#undef TRANS
+#undef 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((unsigned char)c) & mask) != 0)
+#define TAIL() COPY(); TRANS(0x70)
+ Ch c;
+ COPY();
+ if (!(c & 0x80))
+ return true;
+
+ bool result = true;
+ switch (GetRange((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;
+ default: return false;
+ }
+#undef COPY
+#undef TRANS
+#undef TAIL
+ }
+
+ static unsigned char GetRange(unsigned char c) {
+ // Referring to DFA of http://bjoern.hoehrmann.de/utf-8/decoder/dfa/
+ // With new mapping 1 -> 0x10, 7 -> 0x20, 9 -> 0x40, such that AND operation can test multiple types.
+ static const unsigned char type[] = {
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,
+ 0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,
+ 0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,
+ 0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,
+ 8,8,2,2,2,2,2,2,2,2,2,2,2,2,2,2, 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
+ 10,3,3,3,3,3,3,3,3,3,3,3,3,4,3,3, 11,6,6,6,5,8,8,8,8,8,8,8,8,8,8,8,
+ };
+ return type[c];
+ }
+
+ template <typename InputByteStream>
+ static CharType TakeBOM(InputByteStream& is) {
+ RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1);
+ Ch c = Take(is);
+ if ((unsigned char)c != 0xEFu) return c;
+ c = is.Take();
+ if ((unsigned char)c != 0xBBu) return c;
+ c = is.Take();
+ if ((unsigned char)c != 0xBFu) return c;
+ c = is.Take();
+ return c;
+ }
+
+ template <typename InputByteStream>
+ static Ch Take(InputByteStream& is) {
+ RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1);
+ return is.Take();
+ }
+
+ template <typename OutputByteStream>
+ static void PutBOM(OutputByteStream& os) {
+ RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1);
+ os.Put(0xEFu); os.Put(0xBBu); os.Put(0xBFu);
+ }
+
+ template <typename OutputByteStream>
+ static void Put(OutputByteStream& os, Ch c) {
+ RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1);
+ os.Put(static_cast<typename OutputByteStream::Ch>(c));
+ }
+};
+
+///////////////////////////////////////////////////////////////////////////////
+// UTF16
+
+//! UTF-16 encoding.
+/*! http://en.wikipedia.org/wiki/UTF-16
+ http://tools.ietf.org/html/rfc2781
+ \tparam CharType Type for storing 16-bit UTF-16 data. Default is wchar_t. C++11 may use char16_t instead.
+ \note implements Encoding concept
+
+ \note For in-memory access, no need to concern endianness. The code units and code points are represented by CPU's endianness.
+ For streaming, use UTF16LE and UTF16BE, which handle endianness.
+*/
+template<typename CharType = wchar_t>
+struct UTF16 {
+ typedef CharType Ch;
+ RAPIDJSON_STATIC_ASSERT(sizeof(Ch) >= 2);
+
+ enum { supportUnicode = 1 };
+
+ template<typename OutputStream>
+ static void Encode(OutputStream& os, unsigned codepoint) {
+ RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputStream::Ch) >= 2);
+ if (codepoint <= 0xFFFF) {
+ RAPIDJSON_ASSERT(codepoint < 0xD800 || codepoint > 0xDFFF); // Code point itself cannot be surrogate pair
+ os.Put(static_cast<typename OutputStream::Ch>(codepoint));
+ }
+ else {
+ RAPIDJSON_ASSERT(codepoint <= 0x10FFFF);
+ unsigned v = codepoint - 0x10000;
+ os.Put(static_cast<typename OutputStream::Ch>((v >> 10) | 0xD800));
+ os.Put((v & 0x3FF) | 0xDC00);
+ }
+ }
+
+ template <typename InputStream>
+ static bool Decode(InputStream& is, unsigned* codepoint) {
+ RAPIDJSON_STATIC_ASSERT(sizeof(typename InputStream::Ch) >= 2);
+ Ch c = is.Take();
+ if (c < 0xD800 || c > 0xDFFF) {
+ *codepoint = c;
+ return true;
+ }
+ else if (c <= 0xDBFF) {
+ *codepoint = (c & 0x3FF) << 10;
+ c = is.Take();
+ *codepoint |= (c & 0x3FF);
+ *codepoint += 0x10000;
+ return c >= 0xDC00 && c <= 0xDFFF;
+ }
+ return false;
+ }
+
+ template <typename InputStream, typename OutputStream>
+ static bool Validate(InputStream& is, OutputStream& os) {
+ RAPIDJSON_STATIC_ASSERT(sizeof(typename InputStream::Ch) >= 2);
+ RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputStream::Ch) >= 2);
+ Ch c;
+ os.Put(c = is.Take());
+ if (c < 0xD800 || c > 0xDFFF)
+ return true;
+ else if (c <= 0xDBFF) {
+ os.Put(c = is.Take());
+ return c >= 0xDC00 && c <= 0xDFFF;
+ }
+ return false;
+ }
+};
+
+//! UTF-16 little endian encoding.
+template<typename CharType = wchar_t>
+struct UTF16LE : UTF16<CharType> {
+ template <typename InputByteStream>
+ static CharType TakeBOM(InputByteStream& is) {
+ RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1);
+ CharType c = Take(is);
+ return (unsigned short)c == 0xFEFFu ? Take(is) : c;
+ }
+
+ template <typename InputByteStream>
+ static CharType Take(InputByteStream& is) {
+ RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1);
+ CharType c = (unsigned char)is.Take();
+ c |= (unsigned char)is.Take() << 8;
+ return c;
+ }
+
+ template <typename OutputByteStream>
+ static void PutBOM(OutputByteStream& os) {
+ RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1);
+ os.Put(0xFFu); os.Put(0xFEu);
+ }
+
+ template <typename OutputByteStream>
+ static void Put(OutputByteStream& os, CharType c) {
+ RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1);
+ os.Put(c & 0xFFu);
+ os.Put((c >> 8) & 0xFFu);
+ }
+};
+
+//! UTF-16 big endian encoding.
+template<typename CharType = wchar_t>
+struct UTF16BE : UTF16<CharType> {
+ template <typename InputByteStream>
+ static CharType TakeBOM(InputByteStream& is) {
+ RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1);
+ CharType c = Take(is);
+ return (unsigned short)c == 0xFEFFu ? Take(is) : c;
+ }
+
+ template <typename InputByteStream>
+ static CharType Take(InputByteStream& is) {
+ RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1);
+ CharType c = (unsigned char)is.Take() << 8;
+ c |= (unsigned char)is.Take();
+ return c;
+ }
+
+ template <typename OutputByteStream>
+ static void PutBOM(OutputByteStream& os) {
+ RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1);
+ os.Put(0xFEu); os.Put(0xFFu);
+ }
+
+ template <typename OutputByteStream>
+ static void Put(OutputByteStream& os, CharType c) {
+ RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1);
+ os.Put((c >> 8) & 0xFFu);
+ os.Put(c & 0xFFu);
+ }
+};
+
+///////////////////////////////////////////////////////////////////////////////
+// UTF32
+
+//! UTF-32 encoding.
+/*! http://en.wikipedia.org/wiki/UTF-32
+ \tparam CharType Type for storing 32-bit UTF-32 data. Default is unsigned. C++11 may use char32_t instead.
+ \note implements Encoding concept
+
+ \note For in-memory access, no need to concern endianness. The code units and code points are represented by CPU's endianness.
+ For streaming, use UTF32LE and UTF32BE, which handle endianness.
+*/
+template<typename CharType = unsigned>
+struct UTF32 {
+ typedef CharType Ch;
+ RAPIDJSON_STATIC_ASSERT(sizeof(Ch) >= 4);
+
+ enum { supportUnicode = 1 };
+
+ template<typename OutputStream>
+ static void Encode(OutputStream& os, unsigned codepoint) {
+ RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputStream::Ch) >= 4);
+ RAPIDJSON_ASSERT(codepoint <= 0x10FFFF);
+ os.Put(codepoint);
+ }
+
+ template <typename InputStream>
+ static bool Decode(InputStream& is, unsigned* codepoint) {
+ RAPIDJSON_STATIC_ASSERT(sizeof(typename InputStream::Ch) >= 4);
+ Ch c = is.Take();
+ *codepoint = c;
+ return c <= 0x10FFFF;
+ }
+
+ template <typename InputStream, typename OutputStream>
+ static bool Validate(InputStream& is, OutputStream& os) {
+ RAPIDJSON_STATIC_ASSERT(sizeof(typename InputStream::Ch) >= 4);
+ Ch c;
+ os.Put(c = is.Take());
+ return c <= 0x10FFFF;
+ }
+};
+
+//! UTF-32 little endian enocoding.
+template<typename CharType = unsigned>
+struct UTF32LE : UTF32<CharType> {
+ template <typename InputByteStream>
+ static CharType TakeBOM(InputByteStream& is) {
+ RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1);
+ CharType c = Take(is);
+ return (unsigned)c == 0x0000FEFFu ? Take(is) : c;
+ }
+
+ template <typename InputByteStream>
+ static CharType Take(InputByteStream& is) {
+ RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1);
+ CharType c = (unsigned char)is.Take();
+ c |= (unsigned char)is.Take() << 8;
+ c |= (unsigned char)is.Take() << 16;
+ c |= (unsigned char)is.Take() << 24;
+ return c;
+ }
+
+ template <typename OutputByteStream>
+ static void PutBOM(OutputByteStream& os) {
+ RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1);
+ os.Put(0xFFu); os.Put(0xFEu); os.Put(0x00u); os.Put(0x00u);
+ }
+
+ template <typename OutputByteStream>
+ static void Put(OutputByteStream& os, CharType c) {
+ RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1);
+ os.Put(c & 0xFFu);
+ os.Put((c >> 8) & 0xFFu);
+ os.Put((c >> 16) & 0xFFu);
+ os.Put((c >> 24) & 0xFFu);
+ }
+};
+
+//! UTF-32 big endian encoding.
+template<typename CharType = unsigned>
+struct UTF32BE : UTF32<CharType> {
+ template <typename InputByteStream>
+ static CharType TakeBOM(InputByteStream& is) {
+ RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1);
+ CharType c = Take(is);
+ return (unsigned)c == 0x0000FEFFu ? Take(is) : c;
+ }
+
+ template <typename InputByteStream>
+ static CharType Take(InputByteStream& is) {
+ RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1);
+ CharType c = (unsigned char)is.Take() << 24;
+ c |= (unsigned char)is.Take() << 16;
+ c |= (unsigned char)is.Take() << 8;
+ c |= (unsigned char)is.Take();
+ return c;
+ }
+
+ template <typename OutputByteStream>
+ static void PutBOM(OutputByteStream& os) {
+ RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1);
+ os.Put(0x00u); os.Put(0x00u); os.Put(0xFEu); os.Put(0xFFu);
+ }
+
+ template <typename OutputByteStream>
+ static void Put(OutputByteStream& os, CharType c) {
+ RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1);
+ os.Put((c >> 24) & 0xFFu);
+ os.Put((c >> 16) & 0xFFu);
+ os.Put((c >> 8) & 0xFFu);
+ os.Put(c & 0xFFu);
+ }
+};
+
+///////////////////////////////////////////////////////////////////////////////
+// ASCII
+
+//! ASCII encoding.
+/*! http://en.wikipedia.org/wiki/ASCII
+ \tparam CharType Code unit for storing 7-bit ASCII data. Default is char.
+ \note implements Encoding concept
+*/
+template<typename CharType = char>
+struct ASCII {
+ typedef CharType Ch;
+
+ enum { supportUnicode = 0 };
+
+ template<typename OutputStream>
+ static void Encode(OutputStream& os, unsigned codepoint) {
+ RAPIDJSON_ASSERT(codepoint <= 0x7F);
+ os.Put(static_cast<Ch>(codepoint & 0xFF));
+ }
+
+ template <typename InputStream>
+ static bool Decode(InputStream& is, unsigned* codepoint) {
+ unsigned char c = static_cast<unsigned char>(is.Take());
+ *codepoint = c;
+ return c <= 0X7F;
+ }
+
+ template <typename InputStream, typename OutputStream>
+ static bool Validate(InputStream& is, OutputStream& os) {
+ unsigned char c = is.Take();
+ os.Put(c);
+ return c <= 0x7F;
+ }
+
+ template <typename InputByteStream>
+ static CharType TakeBOM(InputByteStream& is) {
+ RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1);
+ Ch c = Take(is);
+ return c;
+ }
+
+ template <typename InputByteStream>
+ static Ch Take(InputByteStream& is) {
+ RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1);
+ return is.Take();
+ }
+
+ template <typename OutputByteStream>
+ static void PutBOM(OutputByteStream& os) {
+ RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1);
+ (void)os;
+ }
+
+ template <typename OutputByteStream>
+ static void Put(OutputByteStream& os, Ch c) {
+ RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1);
+ os.Put(static_cast<typename OutputByteStream::Ch>(c));
+ }
+};
+
+///////////////////////////////////////////////////////////////////////////////
+// AutoUTF
+
+//! Runtime-specified UTF encoding type of a stream.
+enum UTFType {
+ kUTF8 = 0, //!< UTF-8.
+ kUTF16LE = 1, //!< UTF-16 little endian.
+ kUTF16BE = 2, //!< UTF-16 big endian.
+ kUTF32LE = 3, //!< UTF-32 little endian.
+ kUTF32BE = 4 //!< UTF-32 big endian.
+};
+
+//! Dynamically select encoding according to stream's runtime-specified UTF encoding type.
+/*! \note This class can be used with AutoUTFInputtStream and AutoUTFOutputStream, which provides GetType().
+*/
+template<typename CharType>
+struct AutoUTF {
+ typedef CharType Ch;
+
+ enum { supportUnicode = 1 };
+
+#define RAPIDJSON_ENCODINGS_FUNC(x) UTF8<Ch>::x, UTF16LE<Ch>::x, UTF16BE<Ch>::x, UTF32LE<Ch>::x, UTF32BE<Ch>::x
+
+ template<typename OutputStream>
+ RAPIDJSON_FORCEINLINE static void Encode(OutputStream& os, unsigned codepoint) {
+ typedef void (*EncodeFunc)(OutputStream&, unsigned);
+ static const EncodeFunc f[] = { RAPIDJSON_ENCODINGS_FUNC(Encode) };
+ (*f[os.GetType()])(os, codepoint);
+ }
+
+ template <typename InputStream>
+ RAPIDJSON_FORCEINLINE static bool Decode(InputStream& is, unsigned* codepoint) {
+ typedef bool (*DecodeFunc)(InputStream&, unsigned*);
+ static const DecodeFunc f[] = { RAPIDJSON_ENCODINGS_FUNC(Decode) };
+ return (*f[is.GetType()])(is, codepoint);
+ }
+
+ template <typename InputStream, typename OutputStream>
+ RAPIDJSON_FORCEINLINE static bool Validate(InputStream& is, OutputStream& os) {
+ typedef bool (*ValidateFunc)(InputStream&, OutputStream&);
+ static const ValidateFunc f[] = { RAPIDJSON_ENCODINGS_FUNC(Validate) };
+ return (*f[is.GetType()])(is, os);
+ }
+
+#undef RAPIDJSON_ENCODINGS_FUNC
+};
+
+///////////////////////////////////////////////////////////////////////////////
+// Transcoder
+
+//! Encoding conversion.
+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>
+ RAPIDJSON_FORCEINLINE static bool Transcode(InputStream& is, OutputStream& os) {
+ unsigned codepoint;
+ if (!SourceEncoding::Decode(is, &codepoint))
+ return false;
+ TargetEncoding::Encode(os, codepoint);
+ return true;
+ }
+
+ //! Validate one Unicode codepoint from an encoded stream.
+ template<typename InputStream, typename OutputStream>
+ RAPIDJSON_FORCEINLINE static bool Validate(InputStream& is, OutputStream& os) {
+ return Transcode(is, os); // Since source/target encoding is different, must transcode.
+ }
+};
+
+//! Specialization of Transcoder with same source and target encoding.
+template<typename Encoding>
+struct Transcoder<Encoding, Encoding> {
+ template<typename InputStream, typename OutputStream>
+ RAPIDJSON_FORCEINLINE static bool Transcode(InputStream& is, OutputStream& os) {
+ os.Put(is.Take()); // Just copy one code unit. This semantic is different from primary template class.
+ return true;
+ }
+
+ template<typename InputStream, typename OutputStream>
+ RAPIDJSON_FORCEINLINE static bool Validate(InputStream& is, OutputStream& os) {
+ return Encoding::Validate(is, os); // source/target encoding are the same
+ }
+};
+
+RAPIDJSON_NAMESPACE_END
+
+#if defined(__GNUC__) || defined(_MSV_VER)
+RAPIDJSON_DIAG_POP
+#endif
+
+#endif // RAPIDJSON_ENCODINGS_H_
diff --git a/libs/rapidjson/error/en.h b/libs/rapidjson/include/rapidjson/error/en.h
index d5f9caab8..d5f9caab8 100644
--- a/libs/rapidjson/error/en.h
+++ b/libs/rapidjson/include/rapidjson/error/en.h
diff --git a/libs/rapidjson/error/error.h b/libs/rapidjson/include/rapidjson/error/error.h
index aa5700ca8..aa5700ca8 100644
--- a/libs/rapidjson/error/error.h
+++ b/libs/rapidjson/include/rapidjson/error/error.h
diff --git a/libs/rapidjson/filereadstream.h b/libs/rapidjson/include/rapidjson/filereadstream.h
index 78ee403b6..3913eb74b 100644
--- a/libs/rapidjson/filereadstream.h
+++ b/libs/rapidjson/include/rapidjson/filereadstream.h
@@ -1,88 +1,88 @@
-// Tencent is pleased to support the open source community by making RapidJSON available.
-//
-// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
-//
-// Licensed under the MIT License (the "License"); you may not use this file except
-// in compliance with the License. You may obtain a copy of the License at
-//
-// http://opensource.org/licenses/MIT
-//
-// Unless required by applicable law or agreed to in writing, software distributed
-// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
-// CONDITIONS OF ANY KIND, either express or implied. See the License for the
-// specific language governing permissions and limitations under the License.
-
-#ifndef RAPIDJSON_FILEREADSTREAM_H_
-#define RAPIDJSON_FILEREADSTREAM_H_
-
-#include "rapidjson.h"
-#include <cstdio>
-
-RAPIDJSON_NAMESPACE_BEGIN
-
-//! File byte stream for input using fread().
-/*!
- \note implements Stream concept
-*/
-class FileReadStream {
-public:
- typedef char Ch; //!< Character type (byte).
-
- //! Constructor.
- /*!
- \param fp File pointer opened for read.
- \param buffer user-supplied buffer.
- \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) {
- RAPIDJSON_ASSERT(fp_ != 0);
- RAPIDJSON_ASSERT(bufferSize >= 4);
- Read();
- }
-
- 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_); }
-
- // 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 {
- return (current_ + 4 <= bufferLast_) ? current_ : 0;
- }
-
-private:
- void Read() {
- if (current_ < bufferLast_)
- ++current_;
- else if (!eof_) {
- count_ += readCount_;
- readCount_ = fread(buffer_, 1, bufferSize_, fp_);
- bufferLast_ = buffer_ + readCount_ - 1;
- current_ = buffer_;
-
- if (readCount_ < bufferSize_) {
- buffer_[readCount_] = '\0';
- ++bufferLast_;
- eof_ = true;
- }
- }
- }
-
- std::FILE* fp_;
- Ch *buffer_;
- size_t bufferSize_;
- Ch *bufferLast_;
- Ch *current_;
- size_t readCount_;
- size_t count_; //!< Number of characters read
- bool eof_;
-};
-
-RAPIDJSON_NAMESPACE_END
-
-#endif // RAPIDJSON_FILESTREAM_H_
+// Tencent is pleased to support the open source community by making RapidJSON available.
+//
+// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
+//
+// Licensed under the MIT License (the "License"); you may not use this file except
+// in compliance with the License. You may obtain a copy of the License at
+//
+// http://opensource.org/licenses/MIT
+//
+// Unless required by applicable law or agreed to in writing, software distributed
+// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
+// CONDITIONS OF ANY KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations under the License.
+
+#ifndef RAPIDJSON_FILEREADSTREAM_H_
+#define RAPIDJSON_FILEREADSTREAM_H_
+
+#include "rapidjson.h"
+#include <cstdio>
+
+RAPIDJSON_NAMESPACE_BEGIN
+
+//! File byte stream for input using fread().
+/*!
+ \note implements Stream concept
+*/
+class FileReadStream {
+public:
+ typedef char Ch; //!< Character type (byte).
+
+ //! Constructor.
+ /*!
+ \param fp File pointer opened for read.
+ \param buffer user-supplied buffer.
+ \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) {
+ RAPIDJSON_ASSERT(fp_ != 0);
+ RAPIDJSON_ASSERT(bufferSize >= 4);
+ Read();
+ }
+
+ 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_); }
+
+ // 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 {
+ return (current_ + 4 <= bufferLast_) ? current_ : 0;
+ }
+
+private:
+ void Read() {
+ if (current_ < bufferLast_)
+ ++current_;
+ else if (!eof_) {
+ count_ += readCount_;
+ readCount_ = fread(buffer_, 1, bufferSize_, fp_);
+ bufferLast_ = buffer_ + readCount_ - 1;
+ current_ = buffer_;
+
+ if (readCount_ < bufferSize_) {
+ buffer_[readCount_] = '\0';
+ ++bufferLast_;
+ eof_ = true;
+ }
+ }
+ }
+
+ std::FILE* fp_;
+ Ch *buffer_;
+ size_t bufferSize_;
+ Ch *bufferLast_;
+ Ch *current_;
+ size_t readCount_;
+ size_t count_; //!< Number of characters read
+ bool eof_;
+};
+
+RAPIDJSON_NAMESPACE_END
+
+#endif // RAPIDJSON_FILESTREAM_H_
diff --git a/libs/rapidjson/filewritestream.h b/libs/rapidjson/include/rapidjson/filewritestream.h
index 31223b8b3..dfb9cbd02 100644
--- a/libs/rapidjson/filewritestream.h
+++ b/libs/rapidjson/include/rapidjson/filewritestream.h
@@ -1,91 +1,91 @@
-// Tencent is pleased to support the open source community by making RapidJSON available.
-//
-// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
-//
-// Licensed under the MIT License (the "License"); you may not use this file except
-// in compliance with the License. You may obtain a copy of the License at
-//
-// http://opensource.org/licenses/MIT
-//
-// Unless required by applicable law or agreed to in writing, software distributed
-// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
-// CONDITIONS OF ANY KIND, either express or implied. See the License for the
-// specific language governing permissions and limitations under the License.
-
-#ifndef RAPIDJSON_FILEWRITESTREAM_H_
-#define RAPIDJSON_FILEWRITESTREAM_H_
-
-#include "rapidjson.h"
-#include <cstdio>
-
-RAPIDJSON_NAMESPACE_BEGIN
-
-//! Wrapper of C file stream for input using fread().
-/*!
- \note implements Stream concept
-*/
-class FileWriteStream {
-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_) {
- RAPIDJSON_ASSERT(fp_ != 0);
- }
-
- void Put(char c) {
- if (current_ >= bufferEnd_)
- Flush();
-
- *current_++ = c;
- }
-
- void PutN(char c, size_t n) {
- size_t avail = static_cast<size_t>(bufferEnd_ - current_);
- while (n > avail) {
- std::memset(current_, c, avail);
- current_ += avail;
- Flush();
- n -= avail;
- avail = static_cast<size_t>(bufferEnd_ - current_);
- }
-
- if (n > 0) {
- std::memset(current_, c, n);
- current_ += n;
- }
- }
-
- void Flush() {
- if (current_ != buffer_) {
- fwrite(buffer_, 1, static_cast<size_t>(current_ - buffer_), fp_);
- current_ = buffer_;
- }
- }
-
- // Not implemented
- 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.
- FileWriteStream(const FileWriteStream&);
- FileWriteStream& operator=(const FileWriteStream&);
-
- std::FILE* fp_;
- char *buffer_;
- char *bufferEnd_;
- char *current_;
-};
-
-//! Implement specialized version of PutN() with memset() for better performance.
-template<>
-inline void PutN(FileWriteStream& stream, char c, size_t n) {
- stream.PutN(c, n);
-}
-
-RAPIDJSON_NAMESPACE_END
-
-#endif // RAPIDJSON_FILESTREAM_H_
+// Tencent is pleased to support the open source community by making RapidJSON available.
+//
+// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
+//
+// Licensed under the MIT License (the "License"); you may not use this file except
+// in compliance with the License. You may obtain a copy of the License at
+//
+// http://opensource.org/licenses/MIT
+//
+// Unless required by applicable law or agreed to in writing, software distributed
+// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
+// CONDITIONS OF ANY KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations under the License.
+
+#ifndef RAPIDJSON_FILEWRITESTREAM_H_
+#define RAPIDJSON_FILEWRITESTREAM_H_
+
+#include "rapidjson.h"
+#include <cstdio>
+
+RAPIDJSON_NAMESPACE_BEGIN
+
+//! Wrapper of C file stream for input using fread().
+/*!
+ \note implements Stream concept
+*/
+class FileWriteStream {
+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_) {
+ RAPIDJSON_ASSERT(fp_ != 0);
+ }
+
+ void Put(char c) {
+ if (current_ >= bufferEnd_)
+ Flush();
+
+ *current_++ = c;
+ }
+
+ void PutN(char c, size_t n) {
+ size_t avail = static_cast<size_t>(bufferEnd_ - current_);
+ while (n > avail) {
+ std::memset(current_, c, avail);
+ current_ += avail;
+ Flush();
+ n -= avail;
+ avail = static_cast<size_t>(bufferEnd_ - current_);
+ }
+
+ if (n > 0) {
+ std::memset(current_, c, n);
+ current_ += n;
+ }
+ }
+
+ void Flush() {
+ if (current_ != buffer_) {
+ fwrite(buffer_, 1, static_cast<size_t>(current_ - buffer_), fp_);
+ current_ = buffer_;
+ }
+ }
+
+ // Not implemented
+ 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.
+ FileWriteStream(const FileWriteStream&);
+ FileWriteStream& operator=(const FileWriteStream&);
+
+ std::FILE* fp_;
+ char *buffer_;
+ char *bufferEnd_;
+ char *current_;
+};
+
+//! Implement specialized version of PutN() with memset() for better performance.
+template<>
+inline void PutN(FileWriteStream& stream, char c, size_t n) {
+ stream.PutN(c, n);
+}
+
+RAPIDJSON_NAMESPACE_END
+
+#endif // RAPIDJSON_FILESTREAM_H_
diff --git a/libs/rapidjson/internal/biginteger.h b/libs/rapidjson/include/rapidjson/internal/biginteger.h
index 5baba9bec..5baba9bec 100644
--- a/libs/rapidjson/internal/biginteger.h
+++ b/libs/rapidjson/include/rapidjson/internal/biginteger.h
diff --git a/libs/rapidjson/internal/diyfp.h b/libs/rapidjson/include/rapidjson/internal/diyfp.h
index de3d1f01a..de3d1f01a 100644
--- a/libs/rapidjson/internal/diyfp.h
+++ b/libs/rapidjson/include/rapidjson/internal/diyfp.h
diff --git a/libs/rapidjson/internal/dtoa.h b/libs/rapidjson/include/rapidjson/internal/dtoa.h
index 2d8d2e46a..2d8d2e46a 100644
--- a/libs/rapidjson/internal/dtoa.h
+++ b/libs/rapidjson/include/rapidjson/internal/dtoa.h
diff --git a/libs/rapidjson/internal/ieee754.h b/libs/rapidjson/include/rapidjson/internal/ieee754.h
index 9a82880e4..9a82880e4 100644
--- a/libs/rapidjson/internal/ieee754.h
+++ b/libs/rapidjson/include/rapidjson/internal/ieee754.h
diff --git a/libs/rapidjson/internal/itoa.h b/libs/rapidjson/include/rapidjson/internal/itoa.h
index 01a4e7e72..01a4e7e72 100644
--- a/libs/rapidjson/internal/itoa.h
+++ b/libs/rapidjson/include/rapidjson/internal/itoa.h
diff --git a/libs/rapidjson/internal/meta.h b/libs/rapidjson/include/rapidjson/internal/meta.h
index 594e2597b..5c4358cba 100644
--- a/libs/rapidjson/internal/meta.h
+++ b/libs/rapidjson/include/rapidjson/internal/meta.h
@@ -1,183 +1,183 @@
-// Tencent is pleased to support the open source community by making RapidJSON available.
-//
-// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
-//
-// Licensed under the MIT License (the "License"); you may not use this file except
-// in compliance with the License. You may obtain a copy of the License at
-//
-// http://opensource.org/licenses/MIT
-//
-// Unless required by applicable law or agreed to in writing, software distributed
-// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
-// CONDITIONS OF ANY KIND, either express or implied. See the License for the
-// specific language governing permissions and limitations under the License.
-
-#ifndef RAPIDJSON_INTERNAL_META_H_
-#define RAPIDJSON_INTERNAL_META_H_
-
-#ifndef RAPIDJSON_RAPIDJSON_H_
-#error <rapidjson.h> not yet included. Do not include this file directly.
-#endif
-
-#ifdef __GNUC__
-RAPIDJSON_DIAG_PUSH
-RAPIDJSON_DIAG_OFF(effc++)
-#endif
-#if defined(_MSC_VER)
-RAPIDJSON_DIAG_PUSH
-RAPIDJSON_DIAG_OFF(6334)
-#endif
-
-#if RAPIDJSON_HAS_CXX11_TYPETRAITS
-#include <type_traits>
-#endif
-
-//@cond RAPIDJSON_INTERNAL
-RAPIDJSON_NAMESPACE_BEGIN
-namespace internal {
-
-// Helper to wrap/convert arbitrary types to void, useful for arbitrary type matching
-template <typename T> struct Void { typedef void Type; };
-
-///////////////////////////////////////////////////////////////////////////////
-// BoolType, TrueType, FalseType
-//
-template <bool Cond> struct BoolType {
- static const bool Value = Cond;
- typedef BoolType Type;
-};
-typedef BoolType<true> TrueType;
-typedef BoolType<false> FalseType;
-
-
-///////////////////////////////////////////////////////////////////////////////
-// SelectIf, BoolExpr, NotExpr, AndExpr, OrExpr
-//
-
-template <bool C> struct SelectIfImpl { template <typename T1, typename T2> struct Apply { typedef T1 Type; }; };
-template <> struct SelectIfImpl<false> { template <typename T1, typename T2> struct Apply { typedef T2 Type; }; };
-template <bool C, typename T1, typename T2> struct SelectIfCond : SelectIfImpl<C>::template Apply<T1,T2> {};
-template <typename C, typename T1, typename T2> struct SelectIf : SelectIfCond<C::Value, T1, T2> {};
-
-template <bool Cond1, bool Cond2> struct AndExprCond : FalseType {};
-template <> struct AndExprCond<true, true> : TrueType {};
-template <bool Cond1, bool Cond2> struct OrExprCond : TrueType {};
-template <> struct OrExprCond<false, false> : FalseType {};
-
-template <typename C> struct BoolExpr : SelectIf<C,TrueType,FalseType>::Type {};
-template <typename C> struct NotExpr : SelectIf<C,FalseType,TrueType>::Type {};
-template <typename C1, typename C2> struct AndExpr : AndExprCond<C1::Value, C2::Value>::Type {};
-template <typename C1, typename C2> struct OrExpr : OrExprCond<C1::Value, C2::Value>::Type {};
-
-
-///////////////////////////////////////////////////////////////////////////////
-// AddConst, MaybeAddConst, RemoveConst
-template <typename T> struct AddConst { typedef const T Type; };
-template <bool Constify, typename T> struct MaybeAddConst : SelectIfCond<Constify, const T, T> {};
-template <typename T> struct RemoveConst { typedef T Type; };
-template <typename T> struct RemoveConst<const T> { typedef T Type; };
-
-
-///////////////////////////////////////////////////////////////////////////////
-// IsSame, IsConst, IsMoreConst, IsPointer
-//
-template <typename T, typename U> struct IsSame : FalseType {};
-template <typename T> struct IsSame<T, T> : TrueType {};
-
-template <typename T> struct IsConst : FalseType {};
-template <typename T> struct IsConst<const T> : TrueType {};
-
-template <typename CT, typename T>
-struct IsMoreConst
- : AndExpr<IsSame<typename RemoveConst<CT>::Type, typename RemoveConst<T>::Type>,
- BoolType<IsConst<CT>::Value >= IsConst<T>::Value> >::Type {};
-
-template <typename T> struct IsPointer : FalseType {};
-template <typename T> struct IsPointer<T*> : TrueType {};
-
-///////////////////////////////////////////////////////////////////////////////
-// IsBaseOf
-//
-#if RAPIDJSON_HAS_CXX11_TYPETRAITS
-
-template <typename B, typename D> struct IsBaseOf
- : BoolType< ::std::is_base_of<B,D>::value> {};
-
-#else // simplified version adopted from Boost
-
-template<typename B, typename D> struct IsBaseOfImpl {
- RAPIDJSON_STATIC_ASSERT(sizeof(B) != 0);
- RAPIDJSON_STATIC_ASSERT(sizeof(D) != 0);
-
- typedef char (&Yes)[1];
- typedef char (&No) [2];
-
- template <typename T>
- static Yes Check(const D*, T);
- static No Check(const B*, int);
-
- struct Host {
- operator const B*() const;
- operator const D*();
- };
-
- enum { Value = (sizeof(Check(Host(), 0)) == sizeof(Yes)) };
-};
-
-template <typename B, typename D> struct IsBaseOf
- : OrExpr<IsSame<B, D>, BoolExpr<IsBaseOfImpl<B, D> > >::Type {};
-
-#endif // RAPIDJSON_HAS_CXX11_TYPETRAITS
-
-
-//////////////////////////////////////////////////////////////////////////
-// EnableIf / DisableIf
-//
-template <bool Condition, typename T = void> struct EnableIfCond { typedef T Type; };
-template <typename T> struct EnableIfCond<false, T> { /* empty */ };
-
-template <bool Condition, typename T = void> struct DisableIfCond { typedef T Type; };
-template <typename T> struct DisableIfCond<true, T> { /* empty */ };
-
-template <typename Condition, typename T = void>
-struct EnableIf : EnableIfCond<Condition::Value, T> {};
-
-template <typename Condition, typename T = void>
-struct DisableIf : DisableIfCond<Condition::Value, T> {};
-
-// SFINAE helpers
-struct SfinaeTag {};
-template <typename T> struct RemoveSfinaeTag;
-template <typename T> struct RemoveSfinaeTag<SfinaeTag&(*)(T)> { typedef T Type; };
-
-#define RAPIDJSON_REMOVEFPTR_(type) \
- typename ::RAPIDJSON_NAMESPACE::internal::RemoveSfinaeTag \
- < ::RAPIDJSON_NAMESPACE::internal::SfinaeTag&(*) type>::Type
-
-#define RAPIDJSON_ENABLEIF(cond) \
- typename ::RAPIDJSON_NAMESPACE::internal::EnableIf \
- <RAPIDJSON_REMOVEFPTR_(cond)>::Type * = NULL
-
-#define RAPIDJSON_DISABLEIF(cond) \
- typename ::RAPIDJSON_NAMESPACE::internal::DisableIf \
- <RAPIDJSON_REMOVEFPTR_(cond)>::Type * = NULL
-
-#define RAPIDJSON_ENABLEIF_RETURN(cond,returntype) \
- typename ::RAPIDJSON_NAMESPACE::internal::EnableIf \
- <RAPIDJSON_REMOVEFPTR_(cond), \
- RAPIDJSON_REMOVEFPTR_(returntype)>::Type
-
-#define RAPIDJSON_DISABLEIF_RETURN(cond,returntype) \
- typename ::RAPIDJSON_NAMESPACE::internal::DisableIf \
- <RAPIDJSON_REMOVEFPTR_(cond), \
- RAPIDJSON_REMOVEFPTR_(returntype)>::Type
-
-} // namespace internal
-RAPIDJSON_NAMESPACE_END
-//@endcond
-
-#if defined(__GNUC__) || defined(_MSC_VER)
-RAPIDJSON_DIAG_POP
-#endif
-
-#endif // RAPIDJSON_INTERNAL_META_H_
+// Tencent is pleased to support the open source community by making RapidJSON available.
+//
+// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
+//
+// Licensed under the MIT License (the "License"); you may not use this file except
+// in compliance with the License. You may obtain a copy of the License at
+//
+// http://opensource.org/licenses/MIT
+//
+// Unless required by applicable law or agreed to in writing, software distributed
+// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
+// CONDITIONS OF ANY KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations under the License.
+
+#ifndef RAPIDJSON_INTERNAL_META_H_
+#define RAPIDJSON_INTERNAL_META_H_
+
+#ifndef RAPIDJSON_RAPIDJSON_H_
+#error <rapidjson.h> not yet included. Do not include this file directly.
+#endif
+
+#ifdef __GNUC__
+RAPIDJSON_DIAG_PUSH
+RAPIDJSON_DIAG_OFF(effc++)
+#endif
+#if defined(_MSC_VER)
+RAPIDJSON_DIAG_PUSH
+RAPIDJSON_DIAG_OFF(6334)
+#endif
+
+#if RAPIDJSON_HAS_CXX11_TYPETRAITS
+#include <type_traits>
+#endif
+
+//@cond RAPIDJSON_INTERNAL
+RAPIDJSON_NAMESPACE_BEGIN
+namespace internal {
+
+// Helper to wrap/convert arbitrary types to void, useful for arbitrary type matching
+template <typename T> struct Void { typedef void Type; };
+
+///////////////////////////////////////////////////////////////////////////////
+// BoolType, TrueType, FalseType
+//
+template <bool Cond> struct BoolType {
+ static const bool Value = Cond;
+ typedef BoolType Type;
+};
+typedef BoolType<true> TrueType;
+typedef BoolType<false> FalseType;
+
+
+///////////////////////////////////////////////////////////////////////////////
+// SelectIf, BoolExpr, NotExpr, AndExpr, OrExpr
+//
+
+template <bool C> struct SelectIfImpl { template <typename T1, typename T2> struct Apply { typedef T1 Type; }; };
+template <> struct SelectIfImpl<false> { template <typename T1, typename T2> struct Apply { typedef T2 Type; }; };
+template <bool C, typename T1, typename T2> struct SelectIfCond : SelectIfImpl<C>::template Apply<T1,T2> {};
+template <typename C, typename T1, typename T2> struct SelectIf : SelectIfCond<C::Value, T1, T2> {};
+
+template <bool Cond1, bool Cond2> struct AndExprCond : FalseType {};
+template <> struct AndExprCond<true, true> : TrueType {};
+template <bool Cond1, bool Cond2> struct OrExprCond : TrueType {};
+template <> struct OrExprCond<false, false> : FalseType {};
+
+template <typename C> struct BoolExpr : SelectIf<C,TrueType,FalseType>::Type {};
+template <typename C> struct NotExpr : SelectIf<C,FalseType,TrueType>::Type {};
+template <typename C1, typename C2> struct AndExpr : AndExprCond<C1::Value, C2::Value>::Type {};
+template <typename C1, typename C2> struct OrExpr : OrExprCond<C1::Value, C2::Value>::Type {};
+
+
+///////////////////////////////////////////////////////////////////////////////
+// AddConst, MaybeAddConst, RemoveConst
+template <typename T> struct AddConst { typedef const T Type; };
+template <bool Constify, typename T> struct MaybeAddConst : SelectIfCond<Constify, const T, T> {};
+template <typename T> struct RemoveConst { typedef T Type; };
+template <typename T> struct RemoveConst<const T> { typedef T Type; };
+
+
+///////////////////////////////////////////////////////////////////////////////
+// IsSame, IsConst, IsMoreConst, IsPointer
+//
+template <typename T, typename U> struct IsSame : FalseType {};
+template <typename T> struct IsSame<T, T> : TrueType {};
+
+template <typename T> struct IsConst : FalseType {};
+template <typename T> struct IsConst<const T> : TrueType {};
+
+template <typename CT, typename T>
+struct IsMoreConst
+ : AndExpr<IsSame<typename RemoveConst<CT>::Type, typename RemoveConst<T>::Type>,
+ BoolType<IsConst<CT>::Value >= IsConst<T>::Value> >::Type {};
+
+template <typename T> struct IsPointer : FalseType {};
+template <typename T> struct IsPointer<T*> : TrueType {};
+
+///////////////////////////////////////////////////////////////////////////////
+// IsBaseOf
+//
+#if RAPIDJSON_HAS_CXX11_TYPETRAITS
+
+template <typename B, typename D> struct IsBaseOf
+ : BoolType< ::std::is_base_of<B,D>::value> {};
+
+#else // simplified version adopted from Boost
+
+template<typename B, typename D> struct IsBaseOfImpl {
+ RAPIDJSON_STATIC_ASSERT(sizeof(B) != 0);
+ RAPIDJSON_STATIC_ASSERT(sizeof(D) != 0);
+
+ typedef char (&Yes)[1];
+ typedef char (&No) [2];
+
+ template <typename T>
+ static Yes Check(const D*, T);
+ static No Check(const B*, int);
+
+ struct Host {
+ operator const B*() const;
+ operator const D*();
+ };
+
+ enum { Value = (sizeof(Check(Host(), 0)) == sizeof(Yes)) };
+};
+
+template <typename B, typename D> struct IsBaseOf
+ : OrExpr<IsSame<B, D>, BoolExpr<IsBaseOfImpl<B, D> > >::Type {};
+
+#endif // RAPIDJSON_HAS_CXX11_TYPETRAITS
+
+
+//////////////////////////////////////////////////////////////////////////
+// EnableIf / DisableIf
+//
+template <bool Condition, typename T = void> struct EnableIfCond { typedef T Type; };
+template <typename T> struct EnableIfCond<false, T> { /* empty */ };
+
+template <bool Condition, typename T = void> struct DisableIfCond { typedef T Type; };
+template <typename T> struct DisableIfCond<true, T> { /* empty */ };
+
+template <typename Condition, typename T = void>
+struct EnableIf : EnableIfCond<Condition::Value, T> {};
+
+template <typename Condition, typename T = void>
+struct DisableIf : DisableIfCond<Condition::Value, T> {};
+
+// SFINAE helpers
+struct SfinaeTag {};
+template <typename T> struct RemoveSfinaeTag;
+template <typename T> struct RemoveSfinaeTag<SfinaeTag&(*)(T)> { typedef T Type; };
+
+#define RAPIDJSON_REMOVEFPTR_(type) \
+ typename ::RAPIDJSON_NAMESPACE::internal::RemoveSfinaeTag \
+ < ::RAPIDJSON_NAMESPACE::internal::SfinaeTag&(*) type>::Type
+
+#define RAPIDJSON_ENABLEIF(cond) \
+ typename ::RAPIDJSON_NAMESPACE::internal::EnableIf \
+ <RAPIDJSON_REMOVEFPTR_(cond)>::Type * = NULL
+
+#define RAPIDJSON_DISABLEIF(cond) \
+ typename ::RAPIDJSON_NAMESPACE::internal::DisableIf \
+ <RAPIDJSON_REMOVEFPTR_(cond)>::Type * = NULL
+
+#define RAPIDJSON_ENABLEIF_RETURN(cond,returntype) \
+ typename ::RAPIDJSON_NAMESPACE::internal::EnableIf \
+ <RAPIDJSON_REMOVEFPTR_(cond), \
+ RAPIDJSON_REMOVEFPTR_(returntype)>::Type
+
+#define RAPIDJSON_DISABLEIF_RETURN(cond,returntype) \
+ typename ::RAPIDJSON_NAMESPACE::internal::DisableIf \
+ <RAPIDJSON_REMOVEFPTR_(cond), \
+ RAPIDJSON_REMOVEFPTR_(returntype)>::Type
+
+} // namespace internal
+RAPIDJSON_NAMESPACE_END
+//@endcond
+
+#if defined(__GNUC__) || defined(_MSC_VER)
+RAPIDJSON_DIAG_POP
+#endif
+
+#endif // RAPIDJSON_INTERNAL_META_H_
diff --git a/libs/rapidjson/internal/pow10.h b/libs/rapidjson/include/rapidjson/internal/pow10.h
index c552d9f8d..63e97110e 100644
--- a/libs/rapidjson/internal/pow10.h
+++ b/libs/rapidjson/include/rapidjson/internal/pow10.h
@@ -1,53 +1,53 @@
-// Tencent is pleased to support the open source community by making RapidJSON available.
-//
-// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
-//
-// Licensed under the MIT License (the "License"); you may not use this file except
-// in compliance with the License. You may obtain a copy of the License at
-//
-// http://opensource.org/licenses/MIT
-//
-// Unless required by applicable law or agreed to in writing, software distributed
-// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
-// CONDITIONS OF ANY KIND, either express or implied. See the License for the
-// specific language governing permissions and limitations under the License.
-
-#ifndef RAPIDJSON_POW10_
-#define RAPIDJSON_POW10_
-
-RAPIDJSON_NAMESPACE_BEGIN
-namespace internal {
-
-//! Computes integer powers of 10 in double (10.0^n).
-/*! This function uses lookup table for fast and accurate results.
- \param n non-negative exponent. Must <= 308.
- \return 10.0^n
-*/
-inline double Pow10(int n) {
- static const double e[] = { // 1e-0...1e308: 309 * 8 bytes = 2472 bytes
- 1e+0,
- 1e+1, 1e+2, 1e+3, 1e+4, 1e+5, 1e+6, 1e+7, 1e+8, 1e+9, 1e+10, 1e+11, 1e+12, 1e+13, 1e+14, 1e+15, 1e+16, 1e+17, 1e+18, 1e+19, 1e+20,
- 1e+21, 1e+22, 1e+23, 1e+24, 1e+25, 1e+26, 1e+27, 1e+28, 1e+29, 1e+30, 1e+31, 1e+32, 1e+33, 1e+34, 1e+35, 1e+36, 1e+37, 1e+38, 1e+39, 1e+40,
- 1e+41, 1e+42, 1e+43, 1e+44, 1e+45, 1e+46, 1e+47, 1e+48, 1e+49, 1e+50, 1e+51, 1e+52, 1e+53, 1e+54, 1e+55, 1e+56, 1e+57, 1e+58, 1e+59, 1e+60,
- 1e+61, 1e+62, 1e+63, 1e+64, 1e+65, 1e+66, 1e+67, 1e+68, 1e+69, 1e+70, 1e+71, 1e+72, 1e+73, 1e+74, 1e+75, 1e+76, 1e+77, 1e+78, 1e+79, 1e+80,
- 1e+81, 1e+82, 1e+83, 1e+84, 1e+85, 1e+86, 1e+87, 1e+88, 1e+89, 1e+90, 1e+91, 1e+92, 1e+93, 1e+94, 1e+95, 1e+96, 1e+97, 1e+98, 1e+99, 1e+100,
- 1e+101,1e+102,1e+103,1e+104,1e+105,1e+106,1e+107,1e+108,1e+109,1e+110,1e+111,1e+112,1e+113,1e+114,1e+115,1e+116,1e+117,1e+118,1e+119,1e+120,
- 1e+121,1e+122,1e+123,1e+124,1e+125,1e+126,1e+127,1e+128,1e+129,1e+130,1e+131,1e+132,1e+133,1e+134,1e+135,1e+136,1e+137,1e+138,1e+139,1e+140,
- 1e+141,1e+142,1e+143,1e+144,1e+145,1e+146,1e+147,1e+148,1e+149,1e+150,1e+151,1e+152,1e+153,1e+154,1e+155,1e+156,1e+157,1e+158,1e+159,1e+160,
- 1e+161,1e+162,1e+163,1e+164,1e+165,1e+166,1e+167,1e+168,1e+169,1e+170,1e+171,1e+172,1e+173,1e+174,1e+175,1e+176,1e+177,1e+178,1e+179,1e+180,
- 1e+181,1e+182,1e+183,1e+184,1e+185,1e+186,1e+187,1e+188,1e+189,1e+190,1e+191,1e+192,1e+193,1e+194,1e+195,1e+196,1e+197,1e+198,1e+199,1e+200,
- 1e+201,1e+202,1e+203,1e+204,1e+205,1e+206,1e+207,1e+208,1e+209,1e+210,1e+211,1e+212,1e+213,1e+214,1e+215,1e+216,1e+217,1e+218,1e+219,1e+220,
- 1e+221,1e+222,1e+223,1e+224,1e+225,1e+226,1e+227,1e+228,1e+229,1e+230,1e+231,1e+232,1e+233,1e+234,1e+235,1e+236,1e+237,1e+238,1e+239,1e+240,
- 1e+241,1e+242,1e+243,1e+244,1e+245,1e+246,1e+247,1e+248,1e+249,1e+250,1e+251,1e+252,1e+253,1e+254,1e+255,1e+256,1e+257,1e+258,1e+259,1e+260,
- 1e+261,1e+262,1e+263,1e+264,1e+265,1e+266,1e+267,1e+268,1e+269,1e+270,1e+271,1e+272,1e+273,1e+274,1e+275,1e+276,1e+277,1e+278,1e+279,1e+280,
- 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
- };
- RAPIDJSON_ASSERT(n >= 0 && n <= 308);
- return e[n];
-}
-
-} // namespace internal
-RAPIDJSON_NAMESPACE_END
-
-#endif // RAPIDJSON_POW10_
+// Tencent is pleased to support the open source community by making RapidJSON available.
+//
+// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
+//
+// Licensed under the MIT License (the "License"); you may not use this file except
+// in compliance with the License. You may obtain a copy of the License at
+//
+// http://opensource.org/licenses/MIT
+//
+// Unless required by applicable law or agreed to in writing, software distributed
+// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
+// CONDITIONS OF ANY KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations under the License.
+
+#ifndef RAPIDJSON_POW10_
+#define RAPIDJSON_POW10_
+
+RAPIDJSON_NAMESPACE_BEGIN
+namespace internal {
+
+//! Computes integer powers of 10 in double (10.0^n).
+/*! This function uses lookup table for fast and accurate results.
+ \param n non-negative exponent. Must <= 308.
+ \return 10.0^n
+*/
+inline double Pow10(int n) {
+ static const double e[] = { // 1e-0...1e308: 309 * 8 bytes = 2472 bytes
+ 1e+0,
+ 1e+1, 1e+2, 1e+3, 1e+4, 1e+5, 1e+6, 1e+7, 1e+8, 1e+9, 1e+10, 1e+11, 1e+12, 1e+13, 1e+14, 1e+15, 1e+16, 1e+17, 1e+18, 1e+19, 1e+20,
+ 1e+21, 1e+22, 1e+23, 1e+24, 1e+25, 1e+26, 1e+27, 1e+28, 1e+29, 1e+30, 1e+31, 1e+32, 1e+33, 1e+34, 1e+35, 1e+36, 1e+37, 1e+38, 1e+39, 1e+40,
+ 1e+41, 1e+42, 1e+43, 1e+44, 1e+45, 1e+46, 1e+47, 1e+48, 1e+49, 1e+50, 1e+51, 1e+52, 1e+53, 1e+54, 1e+55, 1e+56, 1e+57, 1e+58, 1e+59, 1e+60,
+ 1e+61, 1e+62, 1e+63, 1e+64, 1e+65, 1e+66, 1e+67, 1e+68, 1e+69, 1e+70, 1e+71, 1e+72, 1e+73, 1e+74, 1e+75, 1e+76, 1e+77, 1e+78, 1e+79, 1e+80,
+ 1e+81, 1e+82, 1e+83, 1e+84, 1e+85, 1e+86, 1e+87, 1e+88, 1e+89, 1e+90, 1e+91, 1e+92, 1e+93, 1e+94, 1e+95, 1e+96, 1e+97, 1e+98, 1e+99, 1e+100,
+ 1e+101,1e+102,1e+103,1e+104,1e+105,1e+106,1e+107,1e+108,1e+109,1e+110,1e+111,1e+112,1e+113,1e+114,1e+115,1e+116,1e+117,1e+118,1e+119,1e+120,
+ 1e+121,1e+122,1e+123,1e+124,1e+125,1e+126,1e+127,1e+128,1e+129,1e+130,1e+131,1e+132,1e+133,1e+134,1e+135,1e+136,1e+137,1e+138,1e+139,1e+140,
+ 1e+141,1e+142,1e+143,1e+144,1e+145,1e+146,1e+147,1e+148,1e+149,1e+150,1e+151,1e+152,1e+153,1e+154,1e+155,1e+156,1e+157,1e+158,1e+159,1e+160,
+ 1e+161,1e+162,1e+163,1e+164,1e+165,1e+166,1e+167,1e+168,1e+169,1e+170,1e+171,1e+172,1e+173,1e+174,1e+175,1e+176,1e+177,1e+178,1e+179,1e+180,
+ 1e+181,1e+182,1e+183,1e+184,1e+185,1e+186,1e+187,1e+188,1e+189,1e+190,1e+191,1e+192,1e+193,1e+194,1e+195,1e+196,1e+197,1e+198,1e+199,1e+200,
+ 1e+201,1e+202,1e+203,1e+204,1e+205,1e+206,1e+207,1e+208,1e+209,1e+210,1e+211,1e+212,1e+213,1e+214,1e+215,1e+216,1e+217,1e+218,1e+219,1e+220,
+ 1e+221,1e+222,1e+223,1e+224,1e+225,1e+226,1e+227,1e+228,1e+229,1e+230,1e+231,1e+232,1e+233,1e+234,1e+235,1e+236,1e+237,1e+238,1e+239,1e+240,
+ 1e+241,1e+242,1e+243,1e+244,1e+245,1e+246,1e+247,1e+248,1e+249,1e+250,1e+251,1e+252,1e+253,1e+254,1e+255,1e+256,1e+257,1e+258,1e+259,1e+260,
+ 1e+261,1e+262,1e+263,1e+264,1e+265,1e+266,1e+267,1e+268,1e+269,1e+270,1e+271,1e+272,1e+273,1e+274,1e+275,1e+276,1e+277,1e+278,1e+279,1e+280,
+ 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
+ };
+ RAPIDJSON_ASSERT(n >= 0 && n <= 308);
+ return e[n];
+}
+
+} // namespace internal
+RAPIDJSON_NAMESPACE_END
+
+#endif // RAPIDJSON_POW10_
diff --git a/libs/rapidjson/internal/stack.h b/libs/rapidjson/include/rapidjson/internal/stack.h
index 2f2c76a36..9b23ff921 100644
--- a/libs/rapidjson/internal/stack.h
+++ b/libs/rapidjson/include/rapidjson/internal/stack.h
@@ -1,177 +1,177 @@
-// Tencent is pleased to support the open source community by making RapidJSON available.
-//
-// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
-//
-// Licensed under the MIT License (the "License"); you may not use this file except
-// in compliance with the License. You may obtain a copy of the License at
-//
-// http://opensource.org/licenses/MIT
-//
-// Unless required by applicable law or agreed to in writing, software distributed
-// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
-// CONDITIONS OF ANY KIND, either express or implied. See the License for the
-// specific language governing permissions and limitations under the License.
-
-#ifndef RAPIDJSON_INTERNAL_STACK_H_
-#define RAPIDJSON_INTERNAL_STACK_H_
-
-RAPIDJSON_NAMESPACE_BEGIN
-namespace internal {
-
-///////////////////////////////////////////////////////////////////////////////
-// Stack
-
-//! A type-unsafe stack for storing different types of data.
-/*! \tparam Allocator Allocator for allocating stack memory.
-*/
-template <typename Allocator>
-class Stack {
-public:
- // Optimization note: Do not allocate memory for stack_ in constructor.
- // Do it lazily when first Push() -> Expand() -> Resize().
- Stack(Allocator* allocator, size_t stackCapacity) : allocator_(allocator), ownAllocator_(0), stack_(0), stackTop_(0), stackEnd_(0), initialCapacity_(stackCapacity) {
- RAPIDJSON_ASSERT(stackCapacity > 0);
- }
-
-#if RAPIDJSON_HAS_CXX11_RVALUE_REFS
- Stack(Stack&& rhs)
- : allocator_(rhs.allocator_),
- ownAllocator_(rhs.ownAllocator_),
- stack_(rhs.stack_),
- stackTop_(rhs.stackTop_),
- stackEnd_(rhs.stackEnd_),
- initialCapacity_(rhs.initialCapacity_)
- {
- rhs.allocator_ = 0;
- rhs.ownAllocator_ = 0;
- rhs.stack_ = 0;
- rhs.stackTop_ = 0;
- rhs.stackEnd_ = 0;
- rhs.initialCapacity_ = 0;
- }
-#endif
-
- ~Stack() {
- Destroy();
- }
-
-#if RAPIDJSON_HAS_CXX11_RVALUE_REFS
- Stack& operator=(Stack&& rhs) {
- if (&rhs != this)
- {
- Destroy();
-
- allocator_ = rhs.allocator_;
- ownAllocator_ = rhs.ownAllocator_;
- stack_ = rhs.stack_;
- stackTop_ = rhs.stackTop_;
- stackEnd_ = rhs.stackEnd_;
- initialCapacity_ = rhs.initialCapacity_;
-
- rhs.allocator_ = 0;
- rhs.ownAllocator_ = 0;
- rhs.stack_ = 0;
- rhs.stackTop_ = 0;
- rhs.stackEnd_ = 0;
- rhs.initialCapacity_ = 0;
- }
- return *this;
- }
-#endif
-
- void Clear() { stackTop_ = stack_; }
-
- void ShrinkToFit() {
- if (Empty()) {
- // If the stack is empty, completely deallocate the memory.
- Allocator::Free(stack_);
- stack_ = 0;
- stackTop_ = 0;
- stackEnd_ = 0;
- }
- else
- Resize(GetSize());
- }
-
- // 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>
- RAPIDJSON_FORCEINLINE T* Push(size_t count = 1) {
- // Expand the stack if needed
- if (stackTop_ + sizeof(T) * count >= stackEnd_)
- Expand<T>(count);
-
- T* ret = reinterpret_cast<T*>(stackTop_);
- stackTop_ += sizeof(T) * count;
- return ret;
- }
-
- template<typename T>
- T* Pop(size_t count) {
- RAPIDJSON_ASSERT(GetSize() >= count * sizeof(T));
- stackTop_ -= count * sizeof(T);
- return reinterpret_cast<T*>(stackTop_);
- }
-
- template<typename T>
- T* Top() {
- RAPIDJSON_ASSERT(GetSize() >= sizeof(T));
- return reinterpret_cast<T*>(stackTop_ - sizeof(T));
- }
-
- template<typename T>
- T* Bottom() { return (T*)stack_; }
-
- Allocator& GetAllocator() { return *allocator_; }
- bool Empty() const { return stackTop_ == stack_; }
- size_t GetSize() const { return static_cast<size_t>(stackTop_ - stack_); }
- size_t GetCapacity() const { return static_cast<size_t>(stackEnd_ - stack_); }
-
-private:
- template<typename T>
- void Expand(size_t count) {
- // Only expand the capacity if the current stack exists. Otherwise just create a stack with initial capacity.
- size_t newCapacity;
- if (stack_ == 0) {
- if (!allocator_)
- ownAllocator_ = allocator_ = RAPIDJSON_NEW(Allocator());
- newCapacity = initialCapacity_;
- } else {
- newCapacity = GetCapacity();
- newCapacity += (newCapacity + 1) / 2;
- }
- size_t newSize = GetSize() + sizeof(T) * count;
- if (newCapacity < newSize)
- newCapacity = newSize;
-
- Resize(newCapacity);
- }
-
- void Resize(size_t newCapacity) {
- const size_t size = GetSize(); // Backup the current size
- stack_ = (char*)allocator_->Realloc(stack_, GetCapacity(), newCapacity);
- stackTop_ = stack_ + size;
- stackEnd_ = stack_ + newCapacity;
- }
-
- void Destroy() {
- Allocator::Free(stack_);
- RAPIDJSON_DELETE(ownAllocator_); // Only delete if it is owned by the stack
- }
-
- // Prohibit copy constructor & assignment operator.
- Stack(const Stack&);
- Stack& operator=(const Stack&);
-
- Allocator* allocator_;
- Allocator* ownAllocator_;
- char *stack_;
- char *stackTop_;
- char *stackEnd_;
- size_t initialCapacity_;
-};
-
-} // namespace internal
-RAPIDJSON_NAMESPACE_END
-
-#endif // RAPIDJSON_STACK_H_
+// Tencent is pleased to support the open source community by making RapidJSON available.
+//
+// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
+//
+// Licensed under the MIT License (the "License"); you may not use this file except
+// in compliance with the License. You may obtain a copy of the License at
+//
+// http://opensource.org/licenses/MIT
+//
+// Unless required by applicable law or agreed to in writing, software distributed
+// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
+// CONDITIONS OF ANY KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations under the License.
+
+#ifndef RAPIDJSON_INTERNAL_STACK_H_
+#define RAPIDJSON_INTERNAL_STACK_H_
+
+RAPIDJSON_NAMESPACE_BEGIN
+namespace internal {
+
+///////////////////////////////////////////////////////////////////////////////
+// Stack
+
+//! A type-unsafe stack for storing different types of data.
+/*! \tparam Allocator Allocator for allocating stack memory.
+*/
+template <typename Allocator>
+class Stack {
+public:
+ // Optimization note: Do not allocate memory for stack_ in constructor.
+ // Do it lazily when first Push() -> Expand() -> Resize().
+ Stack(Allocator* allocator, size_t stackCapacity) : allocator_(allocator), ownAllocator_(0), stack_(0), stackTop_(0), stackEnd_(0), initialCapacity_(stackCapacity) {
+ RAPIDJSON_ASSERT(stackCapacity > 0);
+ }
+
+#if RAPIDJSON_HAS_CXX11_RVALUE_REFS
+ Stack(Stack&& rhs)
+ : allocator_(rhs.allocator_),
+ ownAllocator_(rhs.ownAllocator_),
+ stack_(rhs.stack_),
+ stackTop_(rhs.stackTop_),
+ stackEnd_(rhs.stackEnd_),
+ initialCapacity_(rhs.initialCapacity_)
+ {
+ rhs.allocator_ = 0;
+ rhs.ownAllocator_ = 0;
+ rhs.stack_ = 0;
+ rhs.stackTop_ = 0;
+ rhs.stackEnd_ = 0;
+ rhs.initialCapacity_ = 0;
+ }
+#endif
+
+ ~Stack() {
+ Destroy();
+ }
+
+#if RAPIDJSON_HAS_CXX11_RVALUE_REFS
+ Stack& operator=(Stack&& rhs) {
+ if (&rhs != this)
+ {
+ Destroy();
+
+ allocator_ = rhs.allocator_;
+ ownAllocator_ = rhs.ownAllocator_;
+ stack_ = rhs.stack_;
+ stackTop_ = rhs.stackTop_;
+ stackEnd_ = rhs.stackEnd_;
+ initialCapacity_ = rhs.initialCapacity_;
+
+ rhs.allocator_ = 0;
+ rhs.ownAllocator_ = 0;
+ rhs.stack_ = 0;
+ rhs.stackTop_ = 0;
+ rhs.stackEnd_ = 0;
+ rhs.initialCapacity_ = 0;
+ }
+ return *this;
+ }
+#endif
+
+ void Clear() { stackTop_ = stack_; }
+
+ void ShrinkToFit() {
+ if (Empty()) {
+ // If the stack is empty, completely deallocate the memory.
+ Allocator::Free(stack_);
+ stack_ = 0;
+ stackTop_ = 0;
+ stackEnd_ = 0;
+ }
+ else
+ Resize(GetSize());
+ }
+
+ // 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>
+ RAPIDJSON_FORCEINLINE T* Push(size_t count = 1) {
+ // Expand the stack if needed
+ if (stackTop_ + sizeof(T) * count >= stackEnd_)
+ Expand<T>(count);
+
+ T* ret = reinterpret_cast<T*>(stackTop_);
+ stackTop_ += sizeof(T) * count;
+ return ret;
+ }
+
+ template<typename T>
+ T* Pop(size_t count) {
+ RAPIDJSON_ASSERT(GetSize() >= count * sizeof(T));
+ stackTop_ -= count * sizeof(T);
+ return reinterpret_cast<T*>(stackTop_);
+ }
+
+ template<typename T>
+ T* Top() {
+ RAPIDJSON_ASSERT(GetSize() >= sizeof(T));
+ return reinterpret_cast<T*>(stackTop_ - sizeof(T));
+ }
+
+ template<typename T>
+ T* Bottom() { return (T*)stack_; }
+
+ Allocator& GetAllocator() { return *allocator_; }
+ bool Empty() const { return stackTop_ == stack_; }
+ size_t GetSize() const { return static_cast<size_t>(stackTop_ - stack_); }
+ size_t GetCapacity() const { return static_cast<size_t>(stackEnd_ - stack_); }
+
+private:
+ template<typename T>
+ void Expand(size_t count) {
+ // Only expand the capacity if the current stack exists. Otherwise just create a stack with initial capacity.
+ size_t newCapacity;
+ if (stack_ == 0) {
+ if (!allocator_)
+ ownAllocator_ = allocator_ = RAPIDJSON_NEW(Allocator());
+ newCapacity = initialCapacity_;
+ } else {
+ newCapacity = GetCapacity();
+ newCapacity += (newCapacity + 1) / 2;
+ }
+ size_t newSize = GetSize() + sizeof(T) * count;
+ if (newCapacity < newSize)
+ newCapacity = newSize;
+
+ Resize(newCapacity);
+ }
+
+ void Resize(size_t newCapacity) {
+ const size_t size = GetSize(); // Backup the current size
+ stack_ = (char*)allocator_->Realloc(stack_, GetCapacity(), newCapacity);
+ stackTop_ = stack_ + size;
+ stackEnd_ = stack_ + newCapacity;
+ }
+
+ void Destroy() {
+ Allocator::Free(stack_);
+ RAPIDJSON_DELETE(ownAllocator_); // Only delete if it is owned by the stack
+ }
+
+ // Prohibit copy constructor & assignment operator.
+ Stack(const Stack&);
+ Stack& operator=(const Stack&);
+
+ Allocator* allocator_;
+ Allocator* ownAllocator_;
+ char *stack_;
+ char *stackTop_;
+ char *stackEnd_;
+ size_t initialCapacity_;
+};
+
+} // namespace internal
+RAPIDJSON_NAMESPACE_END
+
+#endif // RAPIDJSON_STACK_H_
diff --git a/libs/rapidjson/internal/strfunc.h b/libs/rapidjson/include/rapidjson/internal/strfunc.h
index e6d1c2122..1dc21dd5c 100644
--- a/libs/rapidjson/internal/strfunc.h
+++ b/libs/rapidjson/include/rapidjson/internal/strfunc.h
@@ -1,37 +1,37 @@
-// Tencent is pleased to support the open source community by making RapidJSON available.
-//
-// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
-//
-// Licensed under the MIT License (the "License"); you may not use this file except
-// in compliance with the License. You may obtain a copy of the License at
-//
-// http://opensource.org/licenses/MIT
-//
-// Unless required by applicable law or agreed to in writing, software distributed
-// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
-// CONDITIONS OF ANY KIND, either express or implied. See the License for the
-// specific language governing permissions and limitations under the License.
-
-#ifndef RAPIDJSON_INTERNAL_STRFUNC_H_
-#define RAPIDJSON_INTERNAL_STRFUNC_H_
-
-RAPIDJSON_NAMESPACE_BEGIN
-namespace internal {
-
-//! Custom strlen() which works on different character types.
-/*! \tparam Ch Character type (e.g. char, wchar_t, short)
- \param s Null-terminated input string.
- \return Number of characters in the string.
- \note This has the same semantics as strlen(), the return value is not number of Unicode codepoints.
-*/
-template <typename Ch>
-inline SizeType StrLen(const Ch* s) {
- const Ch* p = s;
- while (*p) ++p;
- return SizeType(p - s);
-}
-
-} // namespace internal
-RAPIDJSON_NAMESPACE_END
-
-#endif // RAPIDJSON_INTERNAL_STRFUNC_H_
+// Tencent is pleased to support the open source community by making RapidJSON available.
+//
+// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
+//
+// Licensed under the MIT License (the "License"); you may not use this file except
+// in compliance with the License. You may obtain a copy of the License at
+//
+// http://opensource.org/licenses/MIT
+//
+// Unless required by applicable law or agreed to in writing, software distributed
+// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
+// CONDITIONS OF ANY KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations under the License.
+
+#ifndef RAPIDJSON_INTERNAL_STRFUNC_H_
+#define RAPIDJSON_INTERNAL_STRFUNC_H_
+
+RAPIDJSON_NAMESPACE_BEGIN
+namespace internal {
+
+//! Custom strlen() which works on different character types.
+/*! \tparam Ch Character type (e.g. char, wchar_t, short)
+ \param s Null-terminated input string.
+ \return Number of characters in the string.
+ \note This has the same semantics as strlen(), the return value is not number of Unicode codepoints.
+*/
+template <typename Ch>
+inline SizeType StrLen(const Ch* s) {
+ const Ch* p = s;
+ while (*p) ++p;
+ return SizeType(p - s);
+}
+
+} // namespace internal
+RAPIDJSON_NAMESPACE_END
+
+#endif // RAPIDJSON_INTERNAL_STRFUNC_H_
diff --git a/libs/rapidjson/internal/strtod.h b/libs/rapidjson/include/rapidjson/internal/strtod.h
index fa85286d4..fa85286d4 100644
--- a/libs/rapidjson/internal/strtod.h
+++ b/libs/rapidjson/include/rapidjson/internal/strtod.h
diff --git a/libs/rapidjson/memorybuffer.h b/libs/rapidjson/include/rapidjson/memorybuffer.h
index 2484b2185..2484b2185 100644
--- a/libs/rapidjson/memorybuffer.h
+++ b/libs/rapidjson/include/rapidjson/memorybuffer.h
diff --git a/libs/rapidjson/memorystream.h b/libs/rapidjson/include/rapidjson/memorystream.h
index 99feae5d7..99feae5d7 100644
--- a/libs/rapidjson/memorystream.h
+++ b/libs/rapidjson/include/rapidjson/memorystream.h
diff --git a/libs/rapidjson/msinttypes/inttypes.h b/libs/rapidjson/include/rapidjson/msinttypes/inttypes.h
index 18111286b..18111286b 100644
--- a/libs/rapidjson/msinttypes/inttypes.h
+++ b/libs/rapidjson/include/rapidjson/msinttypes/inttypes.h
diff --git a/libs/rapidjson/msinttypes/stdint.h b/libs/rapidjson/include/rapidjson/msinttypes/stdint.h
index a26fff4bf..a26fff4bf 100644
--- a/libs/rapidjson/msinttypes/stdint.h
+++ b/libs/rapidjson/include/rapidjson/msinttypes/stdint.h
diff --git a/libs/rapidjson/prettywriter.h b/libs/rapidjson/include/rapidjson/prettywriter.h
index fff888621..416dd492e 100644
--- a/libs/rapidjson/prettywriter.h
+++ b/libs/rapidjson/include/rapidjson/prettywriter.h
@@ -1,207 +1,207 @@
-// Tencent is pleased to support the open source community by making RapidJSON available.
-//
-// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
-//
-// Licensed under the MIT License (the "License"); you may not use this file except
-// in compliance with the License. You may obtain a copy of the License at
-//
-// http://opensource.org/licenses/MIT
-//
-// Unless required by applicable law or agreed to in writing, software distributed
-// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
-// CONDITIONS OF ANY KIND, either express or implied. See the License for the
-// specific language governing permissions and limitations under the License.
-
-#ifndef RAPIDJSON_PRETTYWRITER_H_
-#define RAPIDJSON_PRETTYWRITER_H_
-
-#include "writer.h"
-
-#ifdef __GNUC__
-RAPIDJSON_DIAG_PUSH
-RAPIDJSON_DIAG_OFF(effc++)
-#endif
-
-RAPIDJSON_NAMESPACE_BEGIN
-
-//! Writer with indentation and spacing.
-/*!
- \tparam OutputStream Type of ouptut os.
- \tparam SourceEncoding Encoding of source string.
- \tparam TargetEncoding Encoding of output stream.
- \tparam StackAllocator Type of allocator for allocating memory of stack.
-*/
-template<typename OutputStream, typename SourceEncoding = UTF8<>, typename TargetEncoding = UTF8<>, typename StackAllocator = CrtAllocator>
-class PrettyWriter : public Writer<OutputStream, SourceEncoding, TargetEncoding, StackAllocator> {
-public:
- typedef Writer<OutputStream, SourceEncoding, TargetEncoding, StackAllocator> Base;
- typedef typename Base::Ch Ch;
-
- //! Constructor
- /*! \param os Output stream.
- \param allocator User supplied allocator. If it is null, it will create a private one.
- \param levelDepth Initial capacity of stack.
- */
- PrettyWriter(OutputStream& os, StackAllocator* allocator = 0, size_t levelDepth = Base::kDefaultLevelDepth) :
- Base(os, allocator, levelDepth), indentChar_(' '), indentCharCount_(4) {}
-
- //! Set custom indentation.
- /*! \param indentChar Character for indentation. Must be whitespace character (' ', '\\t', '\\n', '\\r').
- \param indentCharCount Number of indent characters for each indentation level.
- \note The default indentation is 4 spaces.
- */
- PrettyWriter& SetIndent(Ch indentChar, unsigned indentCharCount) {
- RAPIDJSON_ASSERT(indentChar == ' ' || indentChar == '\t' || indentChar == '\n' || indentChar == '\r');
- indentChar_ = indentChar;
- indentCharCount_ = indentCharCount;
- return *this;
- }
-
- /*! @name Implementation of Handler
- \see Handler
- */
- //@{
-
- 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 String(const Ch* str, SizeType length, bool copy = false) {
- (void)copy;
- PrettyPrefix(kStringType);
- return Base::WriteString(str, length);
- }
-
-#if RAPIDJSON_HAS_STDSTRING
- bool String(const std::basic_string<Ch>& str) {
- return String(str.data(), SizeType(str.size()));
- }
-#endif
-
- bool StartObject() {
- PrettyPrefix(kObjectType);
- new (Base::level_stack_.template Push<typename Base::Level>()) typename Base::Level(false);
- return Base::WriteStartObject();
- }
-
- bool Key(const Ch* str, SizeType length, bool copy = false) { return String(str, length, copy); }
-
- bool EndObject(SizeType memberCount = 0) {
- (void)memberCount;
- 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) {
- Base::os_->Put('\n');
- WriteIndent();
- }
- bool ret = Base::WriteEndObject();
- (void)ret;
- RAPIDJSON_ASSERT(ret == true);
- if (Base::level_stack_.Empty()) // end of json text
- Base::os_->Flush();
- return true;
- }
-
- bool StartArray() {
- PrettyPrefix(kArrayType);
- new (Base::level_stack_.template Push<typename Base::Level>()) typename Base::Level(true);
- return Base::WriteStartArray();
- }
-
- bool EndArray(SizeType memberCount = 0) {
- (void)memberCount;
- 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) {
- Base::os_->Put('\n');
- WriteIndent();
- }
- bool ret = Base::WriteEndArray();
- (void)ret;
- RAPIDJSON_ASSERT(ret == true);
- if (Base::level_stack_.Empty()) // end of json text
- Base::os_->Flush();
- return true;
- }
-
- //@}
-
- /*! @name Convenience extensions */
- //@{
-
- //! 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)); }
-
- //@}
-protected:
- void PrettyPrefix(Type type) {
- (void)type;
- if (Base::level_stack_.GetSize() != 0) { // this value is not at root
- typename Base::Level* level = Base::level_stack_.template Top<typename Base::Level>();
-
- if (level->inArray) {
- if (level->valueCount > 0) {
- Base::os_->Put(','); // add comma if it is not the first element in array
- Base::os_->Put('\n');
- }
- else
- Base::os_->Put('\n');
- WriteIndent();
- }
- else { // in object
- if (level->valueCount > 0) {
- if (level->valueCount % 2 == 0) {
- Base::os_->Put(',');
- Base::os_->Put('\n');
- }
- else {
- Base::os_->Put(':');
- Base::os_->Put(' ');
- }
- }
- else
- Base::os_->Put('\n');
-
- if (level->valueCount % 2 == 0)
- WriteIndent();
- }
- if (!level->inArray && level->valueCount % 2 == 0)
- RAPIDJSON_ASSERT(type == kStringType); // if it's in object, then even number should be a name
- level->valueCount++;
- }
- else {
- 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_, indentChar_, count);
- }
-
- Ch indentChar_;
- unsigned indentCharCount_;
-
-private:
- // Prohibit copy constructor & assignment operator.
- PrettyWriter(const PrettyWriter&);
- PrettyWriter& operator=(const PrettyWriter&);
-};
-
-RAPIDJSON_NAMESPACE_END
-
-#ifdef __GNUC__
-RAPIDJSON_DIAG_POP
-#endif
-
-#endif // RAPIDJSON_RAPIDJSON_H_
+// Tencent is pleased to support the open source community by making RapidJSON available.
+//
+// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
+//
+// Licensed under the MIT License (the "License"); you may not use this file except
+// in compliance with the License. You may obtain a copy of the License at
+//
+// http://opensource.org/licenses/MIT
+//
+// Unless required by applicable law or agreed to in writing, software distributed
+// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
+// CONDITIONS OF ANY KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations under the License.
+
+#ifndef RAPIDJSON_PRETTYWRITER_H_
+#define RAPIDJSON_PRETTYWRITER_H_
+
+#include "writer.h"
+
+#ifdef __GNUC__
+RAPIDJSON_DIAG_PUSH
+RAPIDJSON_DIAG_OFF(effc++)
+#endif
+
+RAPIDJSON_NAMESPACE_BEGIN
+
+//! Writer with indentation and spacing.
+/*!
+ \tparam OutputStream Type of ouptut os.
+ \tparam SourceEncoding Encoding of source string.
+ \tparam TargetEncoding Encoding of output stream.
+ \tparam StackAllocator Type of allocator for allocating memory of stack.
+*/
+template<typename OutputStream, typename SourceEncoding = UTF8<>, typename TargetEncoding = UTF8<>, typename StackAllocator = CrtAllocator>
+class PrettyWriter : public Writer<OutputStream, SourceEncoding, TargetEncoding, StackAllocator> {
+public:
+ typedef Writer<OutputStream, SourceEncoding, TargetEncoding, StackAllocator> Base;
+ typedef typename Base::Ch Ch;
+
+ //! Constructor
+ /*! \param os Output stream.
+ \param allocator User supplied allocator. If it is null, it will create a private one.
+ \param levelDepth Initial capacity of stack.
+ */
+ PrettyWriter(OutputStream& os, StackAllocator* allocator = 0, size_t levelDepth = Base::kDefaultLevelDepth) :
+ Base(os, allocator, levelDepth), indentChar_(' '), indentCharCount_(4) {}
+
+ //! Set custom indentation.
+ /*! \param indentChar Character for indentation. Must be whitespace character (' ', '\\t', '\\n', '\\r').
+ \param indentCharCount Number of indent characters for each indentation level.
+ \note The default indentation is 4 spaces.
+ */
+ PrettyWriter& SetIndent(Ch indentChar, unsigned indentCharCount) {
+ RAPIDJSON_ASSERT(indentChar == ' ' || indentChar == '\t' || indentChar == '\n' || indentChar == '\r');
+ indentChar_ = indentChar;
+ indentCharCount_ = indentCharCount;
+ return *this;
+ }
+
+ /*! @name Implementation of Handler
+ \see Handler
+ */
+ //@{
+
+ 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 String(const Ch* str, SizeType length, bool copy = false) {
+ (void)copy;
+ PrettyPrefix(kStringType);
+ return Base::WriteString(str, length);
+ }
+
+#if RAPIDJSON_HAS_STDSTRING
+ bool String(const std::basic_string<Ch>& str) {
+ return String(str.data(), SizeType(str.size()));
+ }
+#endif
+
+ bool StartObject() {
+ PrettyPrefix(kObjectType);
+ new (Base::level_stack_.template Push<typename Base::Level>()) typename Base::Level(false);
+ return Base::WriteStartObject();
+ }
+
+ bool Key(const Ch* str, SizeType length, bool copy = false) { return String(str, length, copy); }
+
+ bool EndObject(SizeType memberCount = 0) {
+ (void)memberCount;
+ 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) {
+ Base::os_->Put('\n');
+ WriteIndent();
+ }
+ bool ret = Base::WriteEndObject();
+ (void)ret;
+ RAPIDJSON_ASSERT(ret == true);
+ if (Base::level_stack_.Empty()) // end of json text
+ Base::os_->Flush();
+ return true;
+ }
+
+ bool StartArray() {
+ PrettyPrefix(kArrayType);
+ new (Base::level_stack_.template Push<typename Base::Level>()) typename Base::Level(true);
+ return Base::WriteStartArray();
+ }
+
+ bool EndArray(SizeType memberCount = 0) {
+ (void)memberCount;
+ 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) {
+ Base::os_->Put('\n');
+ WriteIndent();
+ }
+ bool ret = Base::WriteEndArray();
+ (void)ret;
+ RAPIDJSON_ASSERT(ret == true);
+ if (Base::level_stack_.Empty()) // end of json text
+ Base::os_->Flush();
+ return true;
+ }
+
+ //@}
+
+ /*! @name Convenience extensions */
+ //@{
+
+ //! 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)); }
+
+ //@}
+protected:
+ void PrettyPrefix(Type type) {
+ (void)type;
+ if (Base::level_stack_.GetSize() != 0) { // this value is not at root
+ typename Base::Level* level = Base::level_stack_.template Top<typename Base::Level>();
+
+ if (level->inArray) {
+ if (level->valueCount > 0) {
+ Base::os_->Put(','); // add comma if it is not the first element in array
+ Base::os_->Put('\n');
+ }
+ else
+ Base::os_->Put('\n');
+ WriteIndent();
+ }
+ else { // in object
+ if (level->valueCount > 0) {
+ if (level->valueCount % 2 == 0) {
+ Base::os_->Put(',');
+ Base::os_->Put('\n');
+ }
+ else {
+ Base::os_->Put(':');
+ Base::os_->Put(' ');
+ }
+ }
+ else
+ Base::os_->Put('\n');
+
+ if (level->valueCount % 2 == 0)
+ WriteIndent();
+ }
+ if (!level->inArray && level->valueCount % 2 == 0)
+ RAPIDJSON_ASSERT(type == kStringType); // if it's in object, then even number should be a name
+ level->valueCount++;
+ }
+ else {
+ 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_, indentChar_, count);
+ }
+
+ Ch indentChar_;
+ unsigned indentCharCount_;
+
+private:
+ // Prohibit copy constructor & assignment operator.
+ PrettyWriter(const PrettyWriter&);
+ PrettyWriter& operator=(const PrettyWriter&);
+};
+
+RAPIDJSON_NAMESPACE_END
+
+#ifdef __GNUC__
+RAPIDJSON_DIAG_POP
+#endif
+
+#endif // RAPIDJSON_RAPIDJSON_H_
diff --git a/libs/rapidjson/rapidjson.h b/libs/rapidjson/include/rapidjson/rapidjson.h
index 4351aeae9..0b87c9e56 100644
--- a/libs/rapidjson/rapidjson.h
+++ b/libs/rapidjson/include/rapidjson/rapidjson.h
@@ -1,620 +1,620 @@
-// Tencent is pleased to support the open source community by making RapidJSON available.
-//
-// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
-//
-// Licensed under the MIT License (the "License"); you may not use this file except
-// in compliance with the License. You may obtain a copy of the License at
-//
-// http://opensource.org/licenses/MIT
-//
-// Unless required by applicable law or agreed to in writing, software distributed
-// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
-// CONDITIONS OF ANY KIND, either express or implied. See the License for the
-// specific language governing permissions and limitations under the License.
-
-#ifndef RAPIDJSON_RAPIDJSON_H_
-#define RAPIDJSON_RAPIDJSON_H_
-
-/*!\file rapidjson.h
- \brief common definitions and configuration
-
- \see RAPIDJSON_CONFIG
- */
-
-/*! \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
- preprocessor macros at compile-time.
-
- 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
- different translation units of a single application.
- */
-
-#include <cstdlib> // malloc(), realloc(), free(), size_t
-#include <cstring> // memset(), memcpy(), memmove(), memcmp()
-
-///////////////////////////////////////////////////////////////////////////////
-// 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
- between multiple inclusions of (different versions of) RapidJSON in
- a single binary, users can customize the name of the main 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 RAPIDJSON_NAMESPACE_BEGIN and \ref
- RAPIDJSON_NAMESPACE_END need to be defined as well:
-
- \code
- // in some .cpp file
- #define RAPIDJSON_NAMESPACE my::rapidjson
- #define RAPIDJSON_NAMESPACE_BEGIN namespace my { namespace rapidjson {
- #define RAPIDJSON_NAMESPACE_END } }
- #include "rapidjson/..."
- \endcode
-
- \see rapidjson
- */
-/*! \def RAPIDJSON_NAMESPACE_BEGIN
- \ingroup RAPIDJSON_CONFIG
- \brief provide custom rapidjson namespace (opening expression)
- \see RAPIDJSON_NAMESPACE
-*/
-/*! \def RAPIDJSON_NAMESPACE_END
- \ingroup RAPIDJSON_CONFIG
- \brief provide custom rapidjson namespace (closing expression)
- \see RAPIDJSON_NAMESPACE
-*/
-#ifndef RAPIDJSON_NAMESPACE
-#define RAPIDJSON_NAMESPACE rapidjson
-#endif
-#ifndef RAPIDJSON_NAMESPACE_BEGIN
-#define RAPIDJSON_NAMESPACE_BEGIN namespace RAPIDJSON_NAMESPACE {
-#endif
-#ifndef RAPIDJSON_NAMESPACE_END
-#define RAPIDJSON_NAMESPACE_END }
-#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 RAPIDJSON_NO_INT64DEFINE to
- prevent RapidJSON from defining its own types.
-*/
-#ifndef RAPIDJSON_NO_INT64DEFINE
-//!@cond RAPIDJSON_HIDDEN_FROM_DOXYGEN
-#ifdef _MSC_VER
-#include "msinttypes/stdint.h"
-#include "msinttypes/inttypes.h"
-#else
-// Other compilers should have this.
-#include <stdint.h>
-#include <inttypes.h>
-#endif
-//!@endcond
-#ifdef RAPIDJSON_DOXYGEN_RUNNING
-#define RAPIDJSON_NO_INT64DEFINE
-#endif
-#endif // RAPIDJSON_NO_INT64TYPEDEF
-
-///////////////////////////////////////////////////////////////////////////////
-// RAPIDJSON_FORCEINLINE
-
-#ifndef RAPIDJSON_FORCEINLINE
-//!@cond RAPIDJSON_HIDDEN_FROM_DOXYGEN
-#if defined(_MSC_VER) && !defined(NDEBUG)
-#define RAPIDJSON_FORCEINLINE __forceinline
-#elif defined(__GNUC__) && __GNUC__ >= 4 && !defined(NDEBUG)
-#define RAPIDJSON_FORCEINLINE __attribute__((always_inline))
-#else
-#define RAPIDJSON_FORCEINLINE
-#endif
-//!@endcond
-#endif // RAPIDJSON_FORCEINLINE
-
-///////////////////////////////////////////////////////////////////////////////
-// RAPIDJSON_ENDIAN
-#define RAPIDJSON_LITTLEENDIAN 0 //!< Little endian machine
-#define RAPIDJSON_BIGENDIAN 1 //!< Big endian machine
-
-//! Endianness of the machine.
-/*!
- \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 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 RAPIDJSON_ENDIAN
-// Detect with GCC 4.6's macro
-# ifdef __BYTE_ORDER__
-# if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
-# define RAPIDJSON_ENDIAN RAPIDJSON_LITTLEENDIAN
-# elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
-# define RAPIDJSON_ENDIAN RAPIDJSON_BIGENDIAN
-# else
-# error Unknown machine endianess 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 RAPIDJSON_ENDIAN RAPIDJSON_LITTLEENDIAN
-# elif (__BYTE_ORDER == __BIG_ENDIAN)
-# define RAPIDJSON_ENDIAN RAPIDJSON_BIGENDIAN
-# else
-# error Unknown machine endianess 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 RAPIDJSON_ENDIAN RAPIDJSON_LITTLEENDIAN
-# elif defined(_BIG_ENDIAN) && !defined(_LITTLE_ENDIAN)
-# 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 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 RAPIDJSON_ENDIAN RAPIDJSON_LITTLEENDIAN
-# elif defined(RAPIDJSON_DOXYGEN_RUNNING)
-# define RAPIDJSON_ENDIAN
-# else
-# error Unknown machine endianess detected. User needs to define RAPIDJSON_ENDIAN.
-# endif
-#endif // RAPIDJSON_ENDIAN
-
-///////////////////////////////////////////////////////////////////////////////
-// RAPIDJSON_64BIT
-
-//! Whether using 64-bit architecture
-#ifndef RAPIDJSON_64BIT
-#if defined(__LP64__) || defined(_WIN64)
-#define RAPIDJSON_64BIT 1
-#else
-#define RAPIDJSON_64BIT 0
-#endif
-#endif // RAPIDJSON_64BIT
-
-///////////////////////////////////////////////////////////////////////////////
-// RAPIDJSON_ALIGN
-
-//! Data alignment of the machine.
-/*! \ingroup RAPIDJSON_CONFIG
- \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.,
-*/
-#ifndef RAPIDJSON_ALIGN
-#define RAPIDJSON_ALIGN(x) ((x + 3u) & ~3u)
-#endif
-
-///////////////////////////////////////////////////////////////////////////////
-// RAPIDJSON_UINT64_C2
-
-//! Construct a 64-bit literal by a pair of 32-bit integer.
-/*!
- 64-bit literal with or without ULL suffix is prone to compiler warnings.
- 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 RAPIDJSON_UINT64_C2
-#define RAPIDJSON_UINT64_C2(high32, low32) ((static_cast<uint64_t>(high32) << 32) | static_cast<uint64_t>(low32))
-#endif
-
-///////////////////////////////////////////////////////////////////////////////
-// RAPIDJSON_SSE2/RAPIDJSON_SSE42/RAPIDJSON_SIMD
-
-/*! \def RAPIDJSON_SIMD
- \ingroup RAPIDJSON_CONFIG
- \brief Enable SSE2/SSE4.2 optimization.
-
- RapidJSON supports optimized implementations for some parsing operations
- based on the SSE2 or SSE4.2 SIMD extensions on modern Intel-compatible
- processors.
-
- To enable these optimizations, two different symbols can be defined;
- \code
- // Enable SSE2 optimization.
- #define RAPIDJSON_SSE2
-
- // Enable SSE4.2 optimization.
- #define RAPIDJSON_SSE42
- \endcode
-
- \c RAPIDJSON_SSE42 takes precedence, if both are defined.
-
- If any of these symbols is defined, RapidJSON defines the macro
- \c RAPIDJSON_SIMD to indicate the availability of the optimized code.
-*/
-#if defined(RAPIDJSON_SSE2) || defined(RAPIDJSON_SSE42) \
- || defined(RAPIDJSON_DOXYGEN_RUNNING)
-#define RAPIDJSON_SIMD
-#endif
-
-///////////////////////////////////////////////////////////////////////////////
-// RAPIDJSON_NO_SIZETYPEDEFINE
-
-#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 RAPIDJSON_NO_SIZETYPEDEFINE
- namespace rapidjson { typedef ::std::size_t SizeType; }
- #include "rapidjson/..."
- \endcode
-
- \see rapidjson::SizeType
-*/
-#ifdef RAPIDJSON_DOXYGEN_RUNNING
-#define RAPIDJSON_NO_SIZETYPEDEFINE
-#endif
-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 RAPIDJSON_NO_SIZETYPEDEFINE.
-*/
-typedef unsigned SizeType;
-RAPIDJSON_NAMESPACE_END
-#endif
-
-// always import std::size_t to rapidjson namespace
-RAPIDJSON_NAMESPACE_BEGIN
-using std::size_t;
-RAPIDJSON_NAMESPACE_END
-
-///////////////////////////////////////////////////////////////////////////////
-// RAPIDJSON_ASSERT
-
-//! Assertion.
-/*! \ingroup RAPIDJSON_CONFIG
- By default, rapidjson uses C \c assert() for internal assertions.
- User can override it by defining RAPIDJSON_ASSERT(x) macro.
-
- \note Parsing errors are handled and can be customized by the
- \ref RAPIDJSON_ERRORS APIs.
-*/
-#ifndef RAPIDJSON_ASSERT
-#include <cassert>
-#define RAPIDJSON_ASSERT(x) assert(x)
-#endif // RAPIDJSON_ASSERT
-
-///////////////////////////////////////////////////////////////////////////////
-// RAPIDJSON_STATIC_ASSERT
-
-// Adopt from boost
-#ifndef RAPIDJSON_STATIC_ASSERT
-//!@cond RAPIDJSON_HIDDEN_FROM_DOXYGEN
-RAPIDJSON_NAMESPACE_BEGIN
-template <bool x> struct STATIC_ASSERTION_FAILURE;
-template <> struct STATIC_ASSERTION_FAILURE<true> { enum { value = 1 }; };
-template<int x> struct StaticAssertTest {};
-RAPIDJSON_NAMESPACE_END
-
-#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
-
-#if defined(__GNUC__)
-#define RAPIDJSON_STATIC_ASSERT_UNUSED_ATTRIBUTE __attribute__((unused))
-#else
-#define RAPIDJSON_STATIC_ASSERT_UNUSED_ATTRIBUTE
-#endif
-//!@endcond
-
-/*! \def RAPIDJSON_STATIC_ASSERT
- \brief (Internal) macro to check for conditions at compile-time
- \param x compile-time condition
- \hideinitializer
- */
-#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
-
-///////////////////////////////////////////////////////////////////////////////
-// Helpers
-
-//!@cond RAPIDJSON_HIDDEN_FROM_DOXYGEN
-
-#define RAPIDJSON_MULTILINEMACRO_BEGIN do {
-#define RAPIDJSON_MULTILINEMACRO_END \
-} while((void)0, 0)
-
-// adopted from Boost
-#define RAPIDJSON_VERSION_CODE(x,y,z) \
- (((x)*100000) + ((y)*100) + (z))
-
-// token stringification
-#define RAPIDJSON_STRINGIFY(x) RAPIDJSON_DO_STRINGIFY(x)
-#define RAPIDJSON_DO_STRINGIFY(x) #x
-
-///////////////////////////////////////////////////////////////////////////////
-// RAPIDJSON_DIAG_PUSH/POP, RAPIDJSON_DIAG_OFF
-
-#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(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 RAPIDJSON_DIAG_PUSH /* ignored */
-#define RAPIDJSON_DIAG_POP /* ignored */
-#endif
-
-#elif defined(_MSC_VER)
-
-// pragma (MSVC specific)
-#define RAPIDJSON_PRAGMA(x) __pragma(x)
-#define RAPIDJSON_DIAG_PRAGMA(x) RAPIDJSON_PRAGMA(warning(x))
-
-#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 RAPIDJSON_DIAG_OFF(x) /* ignored */
-#define RAPIDJSON_DIAG_PUSH /* ignored */
-#define RAPIDJSON_DIAG_POP /* ignored */
-
-#endif // RAPIDJSON_DIAG_*
-
-///////////////////////////////////////////////////////////////////////////////
-// C++11 features
-
-#ifndef RAPIDJSON_HAS_CXX11_RVALUE_REFS
-#if defined(__clang__)
-#define RAPIDJSON_HAS_CXX11_RVALUE_REFS __has_feature(cxx_rvalue_references) && \
- (defined(_LIBCPP_VERSION) || defined(__GLIBCXX__) && __GLIBCXX__ >= 20080306)
-#elif (defined(RAPIDJSON_GNUC) && (RAPIDJSON_GNUC >= RAPIDJSON_VERSION_CODE(4,3,0)) && defined(__GXX_EXPERIMENTAL_CXX0X__)) || \
- (defined(_MSC_VER) && _MSC_VER >= 1600)
-
-#define RAPIDJSON_HAS_CXX11_RVALUE_REFS 1
-#else
-#define RAPIDJSON_HAS_CXX11_RVALUE_REFS 0
-#endif
-#endif // RAPIDJSON_HAS_CXX11_RVALUE_REFS
-
-#ifndef RAPIDJSON_HAS_CXX11_NOEXCEPT
-#if 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 >= ????) // not yet supported
-#define RAPIDJSON_HAS_CXX11_NOEXCEPT 1
-#else
-#define RAPIDJSON_HAS_CXX11_NOEXCEPT 0
-#endif
-#endif
-#if RAPIDJSON_HAS_CXX11_NOEXCEPT
-#define RAPIDJSON_NOEXCEPT noexcept
-#else
-#define RAPIDJSON_NOEXCEPT /* noexcept */
-#endif // RAPIDJSON_HAS_CXX11_NOEXCEPT
-
-// no automatic detection, yet
-#ifndef RAPIDJSON_HAS_CXX11_TYPETRAITS
-#define RAPIDJSON_HAS_CXX11_TYPETRAITS 0
-#endif
-
-//!@endcond
-
-///////////////////////////////////////////////////////////////////////////////
-// new/delete
-
-#ifndef RAPIDJSON_NEW
-///! customization point for global \c new
-#define RAPIDJSON_NEW(x) new x
-#endif
-#ifndef RAPIDJSON_DELETE
-///! customization point for global \c delete
-#define RAPIDJSON_DELETE(x) delete x
-#endif
-
-///////////////////////////////////////////////////////////////////////////////
-// Allocators and Encodings
-
-#include "allocators.h"
-#include "encodings.h"
-
-/*! \namespace rapidjson
- \brief main RapidJSON namespace
- \see RAPIDJSON_NAMESPACE
-*/
-RAPIDJSON_NAMESPACE_BEGIN
-
-///////////////////////////////////////////////////////////////////////////////
-// Stream
-
-/*! \class rapidjson::Stream
- \brief Concept for reading and writing characters.
-
- For read-only stream, no need to implement PutBegin(), Put(), Flush() and PutEnd().
-
- For write-only stream, only need to implement Put() and Flush().
-
-\code
-concept Stream {
- typename Ch; //!< Character type of the stream.
-
- //! Read the current character from stream without moving the read cursor.
- Ch Peek() const;
-
- //! Read the current character from stream and moving the read cursor to next character.
- Ch Take();
-
- //! Get the current read cursor.
- //! \return Number of characters read from start.
- size_t Tell();
-
- //! Begin writing operation at the current read pointer.
- //! \return The begin writer pointer.
- Ch* PutBegin();
-
- //! Write a character.
- void Put(Ch c);
-
- //! Flush the buffer.
- void Flush();
-
- //! End the writing operation.
- //! \param begin The begin write pointer returned by PutBegin().
- //! \return Number of characters written.
- size_t PutEnd(Ch* begin);
-}
-\endcode
-*/
-
-//! Provides additional information for stream.
-/*!
- By using traits pattern, this type provides a default configuration for stream.
- For custom stream, this type can be specialized for other configuration.
- See TEST(Reader, CustomStringStream) in readertest.cpp for example.
-*/
-template<typename Stream>
-struct StreamTraits {
- //! Whether to make local copy of stream for optimization during parsing.
- /*!
- By default, for safety, streams do not use local copy optimization.
- Stream that can be copied fast should specialize this, like StreamTraits<StringStream>.
- */
- enum { copyOptimization = 0 };
-};
-
-//! Put N copies of a character to a stream.
-template<typename Stream, typename Ch>
-inline void PutN(Stream& stream, Ch c, size_t n) {
- for (size_t i = 0; i < n; i++)
- stream.Put(c);
-}
-
-///////////////////////////////////////////////////////////////////////////////
-// StringStream
-
-//! Read-only string stream.
-/*! \note implements Stream concept
-*/
-template <typename Encoding>
-struct GenericStringStream {
- typedef typename Encoding::Ch Ch;
-
- GenericStringStream(const Ch *src) : src_(src), head_(src) {}
-
- Ch Peek() const { return *src_; }
- Ch Take() { return *src_++; }
- size_t Tell() const { return static_cast<size_t>(src_ - head_); }
-
- 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.
-};
-
-template <typename Encoding>
-struct StreamTraits<GenericStringStream<Encoding> > {
- enum { copyOptimization = 1 };
-};
-
-//! String stream with UTF8 encoding.
-typedef GenericStringStream<UTF8<> > StringStream;
-
-///////////////////////////////////////////////////////////////////////////////
-// InsituStringStream
-
-//! A read-write string stream.
-/*! This string stream is particularly designed for in-situ parsing.
- \note implements Stream concept
-*/
-template <typename Encoding>
-struct GenericInsituStringStream {
- typedef typename Encoding::Ch Ch;
-
- GenericInsituStringStream(Ch *src) : src_(src), dst_(0), head_(src) {}
-
- // Read
- Ch Peek() { return *src_; }
- Ch Take() { return *src_++; }
- size_t Tell() { return static_cast<size_t>(src_ - head_); }
-
- // Write
- 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); }
- void Flush() {}
-
- Ch* Push(size_t count) { Ch* begin = dst_; dst_ += count; return begin; }
- void Pop(size_t count) { dst_ -= count; }
-
- Ch* src_;
- Ch* dst_;
- Ch* head_;
-};
-
-template <typename Encoding>
-struct StreamTraits<GenericInsituStringStream<Encoding> > {
- enum { copyOptimization = 1 };
-};
-
-//! Insitu string stream with UTF8 encoding.
-typedef GenericInsituStringStream<UTF8<> > InsituStringStream;
-
-///////////////////////////////////////////////////////////////////////////////
-// Type
-
-//! Type of JSON value
-enum Type {
- kNullType = 0, //!< null
- kFalseType = 1, //!< false
- kTrueType = 2, //!< true
- kObjectType = 3, //!< object
- kArrayType = 4, //!< array
- kStringType = 5, //!< string
- kNumberType = 6 //!< number
-};
-
-RAPIDJSON_NAMESPACE_END
-
-#endif // RAPIDJSON_RAPIDJSON_H_
+// Tencent is pleased to support the open source community by making RapidJSON available.
+//
+// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
+//
+// Licensed under the MIT License (the "License"); you may not use this file except
+// in compliance with the License. You may obtain a copy of the License at
+//
+// http://opensource.org/licenses/MIT
+//
+// Unless required by applicable law or agreed to in writing, software distributed
+// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
+// CONDITIONS OF ANY KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations under the License.
+
+#ifndef RAPIDJSON_RAPIDJSON_H_
+#define RAPIDJSON_RAPIDJSON_H_
+
+/*!\file rapidjson.h
+ \brief common definitions and configuration
+
+ \see RAPIDJSON_CONFIG
+ */
+
+/*! \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
+ preprocessor macros at compile-time.
+
+ 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
+ different translation units of a single application.
+ */
+
+#include <cstdlib> // malloc(), realloc(), free(), size_t
+#include <cstring> // memset(), memcpy(), memmove(), memcmp()
+
+///////////////////////////////////////////////////////////////////////////////
+// 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
+ between multiple inclusions of (different versions of) RapidJSON in
+ a single binary, users can customize the name of the main 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 RAPIDJSON_NAMESPACE_BEGIN and \ref
+ RAPIDJSON_NAMESPACE_END need to be defined as well:
+
+ \code
+ // in some .cpp file
+ #define RAPIDJSON_NAMESPACE my::rapidjson
+ #define RAPIDJSON_NAMESPACE_BEGIN namespace my { namespace rapidjson {
+ #define RAPIDJSON_NAMESPACE_END } }
+ #include "rapidjson/..."
+ \endcode
+
+ \see rapidjson
+ */
+/*! \def RAPIDJSON_NAMESPACE_BEGIN
+ \ingroup RAPIDJSON_CONFIG
+ \brief provide custom rapidjson namespace (opening expression)
+ \see RAPIDJSON_NAMESPACE
+*/
+/*! \def RAPIDJSON_NAMESPACE_END
+ \ingroup RAPIDJSON_CONFIG
+ \brief provide custom rapidjson namespace (closing expression)
+ \see RAPIDJSON_NAMESPACE
+*/
+#ifndef RAPIDJSON_NAMESPACE
+#define RAPIDJSON_NAMESPACE rapidjson
+#endif
+#ifndef RAPIDJSON_NAMESPACE_BEGIN
+#define RAPIDJSON_NAMESPACE_BEGIN namespace RAPIDJSON_NAMESPACE {
+#endif
+#ifndef RAPIDJSON_NAMESPACE_END
+#define RAPIDJSON_NAMESPACE_END }
+#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 RAPIDJSON_NO_INT64DEFINE to
+ prevent RapidJSON from defining its own types.
+*/
+#ifndef RAPIDJSON_NO_INT64DEFINE
+//!@cond RAPIDJSON_HIDDEN_FROM_DOXYGEN
+#ifdef _MSC_VER
+#include "msinttypes/stdint.h"
+#include "msinttypes/inttypes.h"
+#else
+// Other compilers should have this.
+#include <stdint.h>
+#include <inttypes.h>
+#endif
+//!@endcond
+#ifdef RAPIDJSON_DOXYGEN_RUNNING
+#define RAPIDJSON_NO_INT64DEFINE
+#endif
+#endif // RAPIDJSON_NO_INT64TYPEDEF
+
+///////////////////////////////////////////////////////////////////////////////
+// RAPIDJSON_FORCEINLINE
+
+#ifndef RAPIDJSON_FORCEINLINE
+//!@cond RAPIDJSON_HIDDEN_FROM_DOXYGEN
+#if defined(_MSC_VER) && !defined(NDEBUG)
+#define RAPIDJSON_FORCEINLINE __forceinline
+#elif defined(__GNUC__) && __GNUC__ >= 4 && !defined(NDEBUG)
+#define RAPIDJSON_FORCEINLINE __attribute__((always_inline))
+#else
+#define RAPIDJSON_FORCEINLINE
+#endif
+//!@endcond
+#endif // RAPIDJSON_FORCEINLINE
+
+///////////////////////////////////////////////////////////////////////////////
+// RAPIDJSON_ENDIAN
+#define RAPIDJSON_LITTLEENDIAN 0 //!< Little endian machine
+#define RAPIDJSON_BIGENDIAN 1 //!< Big endian machine
+
+//! Endianness of the machine.
+/*!
+ \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 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 RAPIDJSON_ENDIAN
+// Detect with GCC 4.6's macro
+# ifdef __BYTE_ORDER__
+# if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
+# define RAPIDJSON_ENDIAN RAPIDJSON_LITTLEENDIAN
+# elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
+# define RAPIDJSON_ENDIAN RAPIDJSON_BIGENDIAN
+# else
+# error Unknown machine endianess 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 RAPIDJSON_ENDIAN RAPIDJSON_LITTLEENDIAN
+# elif (__BYTE_ORDER == __BIG_ENDIAN)
+# define RAPIDJSON_ENDIAN RAPIDJSON_BIGENDIAN
+# else
+# error Unknown machine endianess 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 RAPIDJSON_ENDIAN RAPIDJSON_LITTLEENDIAN
+# elif defined(_BIG_ENDIAN) && !defined(_LITTLE_ENDIAN)
+# 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 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 RAPIDJSON_ENDIAN RAPIDJSON_LITTLEENDIAN
+# elif defined(RAPIDJSON_DOXYGEN_RUNNING)
+# define RAPIDJSON_ENDIAN
+# else
+# error Unknown machine endianess detected. User needs to define RAPIDJSON_ENDIAN.
+# endif
+#endif // RAPIDJSON_ENDIAN
+
+///////////////////////////////////////////////////////////////////////////////
+// RAPIDJSON_64BIT
+
+//! Whether using 64-bit architecture
+#ifndef RAPIDJSON_64BIT
+#if defined(__LP64__) || defined(_WIN64)
+#define RAPIDJSON_64BIT 1
+#else
+#define RAPIDJSON_64BIT 0
+#endif
+#endif // RAPIDJSON_64BIT
+
+///////////////////////////////////////////////////////////////////////////////
+// RAPIDJSON_ALIGN
+
+//! Data alignment of the machine.
+/*! \ingroup RAPIDJSON_CONFIG
+ \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.,
+*/
+#ifndef RAPIDJSON_ALIGN
+#define RAPIDJSON_ALIGN(x) ((x + 3u) & ~3u)
+#endif
+
+///////////////////////////////////////////////////////////////////////////////
+// RAPIDJSON_UINT64_C2
+
+//! Construct a 64-bit literal by a pair of 32-bit integer.
+/*!
+ 64-bit literal with or without ULL suffix is prone to compiler warnings.
+ 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 RAPIDJSON_UINT64_C2
+#define RAPIDJSON_UINT64_C2(high32, low32) ((static_cast<uint64_t>(high32) << 32) | static_cast<uint64_t>(low32))
+#endif
+
+///////////////////////////////////////////////////////////////////////////////
+// RAPIDJSON_SSE2/RAPIDJSON_SSE42/RAPIDJSON_SIMD
+
+/*! \def RAPIDJSON_SIMD
+ \ingroup RAPIDJSON_CONFIG
+ \brief Enable SSE2/SSE4.2 optimization.
+
+ RapidJSON supports optimized implementations for some parsing operations
+ based on the SSE2 or SSE4.2 SIMD extensions on modern Intel-compatible
+ processors.
+
+ To enable these optimizations, two different symbols can be defined;
+ \code
+ // Enable SSE2 optimization.
+ #define RAPIDJSON_SSE2
+
+ // Enable SSE4.2 optimization.
+ #define RAPIDJSON_SSE42
+ \endcode
+
+ \c RAPIDJSON_SSE42 takes precedence, if both are defined.
+
+ If any of these symbols is defined, RapidJSON defines the macro
+ \c RAPIDJSON_SIMD to indicate the availability of the optimized code.
+*/
+#if defined(RAPIDJSON_SSE2) || defined(RAPIDJSON_SSE42) \
+ || defined(RAPIDJSON_DOXYGEN_RUNNING)
+#define RAPIDJSON_SIMD
+#endif
+
+///////////////////////////////////////////////////////////////////////////////
+// RAPIDJSON_NO_SIZETYPEDEFINE
+
+#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 RAPIDJSON_NO_SIZETYPEDEFINE
+ namespace rapidjson { typedef ::std::size_t SizeType; }
+ #include "rapidjson/..."
+ \endcode
+
+ \see rapidjson::SizeType
+*/
+#ifdef RAPIDJSON_DOXYGEN_RUNNING
+#define RAPIDJSON_NO_SIZETYPEDEFINE
+#endif
+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 RAPIDJSON_NO_SIZETYPEDEFINE.
+*/
+typedef unsigned SizeType;
+RAPIDJSON_NAMESPACE_END
+#endif
+
+// always import std::size_t to rapidjson namespace
+RAPIDJSON_NAMESPACE_BEGIN
+using std::size_t;
+RAPIDJSON_NAMESPACE_END
+
+///////////////////////////////////////////////////////////////////////////////
+// RAPIDJSON_ASSERT
+
+//! Assertion.
+/*! \ingroup RAPIDJSON_CONFIG
+ By default, rapidjson uses C \c assert() for internal assertions.
+ User can override it by defining RAPIDJSON_ASSERT(x) macro.
+
+ \note Parsing errors are handled and can be customized by the
+ \ref RAPIDJSON_ERRORS APIs.
+*/
+#ifndef RAPIDJSON_ASSERT
+#include <cassert>
+#define RAPIDJSON_ASSERT(x) assert(x)
+#endif // RAPIDJSON_ASSERT
+
+///////////////////////////////////////////////////////////////////////////////
+// RAPIDJSON_STATIC_ASSERT
+
+// Adopt from boost
+#ifndef RAPIDJSON_STATIC_ASSERT
+//!@cond RAPIDJSON_HIDDEN_FROM_DOXYGEN
+RAPIDJSON_NAMESPACE_BEGIN
+template <bool x> struct STATIC_ASSERTION_FAILURE;
+template <> struct STATIC_ASSERTION_FAILURE<true> { enum { value = 1 }; };
+template<int x> struct StaticAssertTest {};
+RAPIDJSON_NAMESPACE_END
+
+#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
+
+#if defined(__GNUC__)
+#define RAPIDJSON_STATIC_ASSERT_UNUSED_ATTRIBUTE __attribute__((unused))
+#else
+#define RAPIDJSON_STATIC_ASSERT_UNUSED_ATTRIBUTE
+#endif
+//!@endcond
+
+/*! \def RAPIDJSON_STATIC_ASSERT
+ \brief (Internal) macro to check for conditions at compile-time
+ \param x compile-time condition
+ \hideinitializer
+ */
+#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
+
+///////////////////////////////////////////////////////////////////////////////
+// Helpers
+
+//!@cond RAPIDJSON_HIDDEN_FROM_DOXYGEN
+
+#define RAPIDJSON_MULTILINEMACRO_BEGIN do {
+#define RAPIDJSON_MULTILINEMACRO_END \
+} while((void)0, 0)
+
+// adopted from Boost
+#define RAPIDJSON_VERSION_CODE(x,y,z) \
+ (((x)*100000) + ((y)*100) + (z))
+
+// token stringification
+#define RAPIDJSON_STRINGIFY(x) RAPIDJSON_DO_STRINGIFY(x)
+#define RAPIDJSON_DO_STRINGIFY(x) #x
+
+///////////////////////////////////////////////////////////////////////////////
+// RAPIDJSON_DIAG_PUSH/POP, RAPIDJSON_DIAG_OFF
+
+#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(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 RAPIDJSON_DIAG_PUSH /* ignored */
+#define RAPIDJSON_DIAG_POP /* ignored */
+#endif
+
+#elif defined(_MSC_VER)
+
+// pragma (MSVC specific)
+#define RAPIDJSON_PRAGMA(x) __pragma(x)
+#define RAPIDJSON_DIAG_PRAGMA(x) RAPIDJSON_PRAGMA(warning(x))
+
+#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 RAPIDJSON_DIAG_OFF(x) /* ignored */
+#define RAPIDJSON_DIAG_PUSH /* ignored */
+#define RAPIDJSON_DIAG_POP /* ignored */
+
+#endif // RAPIDJSON_DIAG_*
+
+///////////////////////////////////////////////////////////////////////////////
+// C++11 features
+
+#ifndef RAPIDJSON_HAS_CXX11_RVALUE_REFS
+#if defined(__clang__)
+#define RAPIDJSON_HAS_CXX11_RVALUE_REFS __has_feature(cxx_rvalue_references) && \
+ (defined(_LIBCPP_VERSION) || defined(__GLIBCXX__) && __GLIBCXX__ >= 20080306)
+#elif (defined(RAPIDJSON_GNUC) && (RAPIDJSON_GNUC >= RAPIDJSON_VERSION_CODE(4,3,0)) && defined(__GXX_EXPERIMENTAL_CXX0X__)) || \
+ (defined(_MSC_VER) && _MSC_VER >= 1600)
+
+#define RAPIDJSON_HAS_CXX11_RVALUE_REFS 1
+#else
+#define RAPIDJSON_HAS_CXX11_RVALUE_REFS 0
+#endif
+#endif // RAPIDJSON_HAS_CXX11_RVALUE_REFS
+
+#ifndef RAPIDJSON_HAS_CXX11_NOEXCEPT
+#if 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 >= ????) // not yet supported
+#define RAPIDJSON_HAS_CXX11_NOEXCEPT 1
+#else
+#define RAPIDJSON_HAS_CXX11_NOEXCEPT 0
+#endif
+#endif
+#if RAPIDJSON_HAS_CXX11_NOEXCEPT
+#define RAPIDJSON_NOEXCEPT noexcept
+#else
+#define RAPIDJSON_NOEXCEPT /* noexcept */
+#endif // RAPIDJSON_HAS_CXX11_NOEXCEPT
+
+// no automatic detection, yet
+#ifndef RAPIDJSON_HAS_CXX11_TYPETRAITS
+#define RAPIDJSON_HAS_CXX11_TYPETRAITS 0
+#endif
+
+//!@endcond
+
+///////////////////////////////////////////////////////////////////////////////
+// new/delete
+
+#ifndef RAPIDJSON_NEW
+///! customization point for global \c new
+#define RAPIDJSON_NEW(x) new x
+#endif
+#ifndef RAPIDJSON_DELETE
+///! customization point for global \c delete
+#define RAPIDJSON_DELETE(x) delete x
+#endif
+
+///////////////////////////////////////////////////////////////////////////////
+// Allocators and Encodings
+
+#include "allocators.h"
+#include "encodings.h"
+
+/*! \namespace rapidjson
+ \brief main RapidJSON namespace
+ \see RAPIDJSON_NAMESPACE
+*/
+RAPIDJSON_NAMESPACE_BEGIN
+
+///////////////////////////////////////////////////////////////////////////////
+// Stream
+
+/*! \class rapidjson::Stream
+ \brief Concept for reading and writing characters.
+
+ For read-only stream, no need to implement PutBegin(), Put(), Flush() and PutEnd().
+
+ For write-only stream, only need to implement Put() and Flush().
+
+\code
+concept Stream {
+ typename Ch; //!< Character type of the stream.
+
+ //! Read the current character from stream without moving the read cursor.
+ Ch Peek() const;
+
+ //! Read the current character from stream and moving the read cursor to next character.
+ Ch Take();
+
+ //! Get the current read cursor.
+ //! \return Number of characters read from start.
+ size_t Tell();
+
+ //! Begin writing operation at the current read pointer.
+ //! \return The begin writer pointer.
+ Ch* PutBegin();
+
+ //! Write a character.
+ void Put(Ch c);
+
+ //! Flush the buffer.
+ void Flush();
+
+ //! End the writing operation.
+ //! \param begin The begin write pointer returned by PutBegin().
+ //! \return Number of characters written.
+ size_t PutEnd(Ch* begin);
+}
+\endcode
+*/
+
+//! Provides additional information for stream.
+/*!
+ By using traits pattern, this type provides a default configuration for stream.
+ For custom stream, this type can be specialized for other configuration.
+ See TEST(Reader, CustomStringStream) in readertest.cpp for example.
+*/
+template<typename Stream>
+struct StreamTraits {
+ //! Whether to make local copy of stream for optimization during parsing.
+ /*!
+ By default, for safety, streams do not use local copy optimization.
+ Stream that can be copied fast should specialize this, like StreamTraits<StringStream>.
+ */
+ enum { copyOptimization = 0 };
+};
+
+//! Put N copies of a character to a stream.
+template<typename Stream, typename Ch>
+inline void PutN(Stream& stream, Ch c, size_t n) {
+ for (size_t i = 0; i < n; i++)
+ stream.Put(c);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// StringStream
+
+//! Read-only string stream.
+/*! \note implements Stream concept
+*/
+template <typename Encoding>
+struct GenericStringStream {
+ typedef typename Encoding::Ch Ch;
+
+ GenericStringStream(const Ch *src) : src_(src), head_(src) {}
+
+ Ch Peek() const { return *src_; }
+ Ch Take() { return *src_++; }
+ size_t Tell() const { return static_cast<size_t>(src_ - head_); }
+
+ 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.
+};
+
+template <typename Encoding>
+struct StreamTraits<GenericStringStream<Encoding> > {
+ enum { copyOptimization = 1 };
+};
+
+//! String stream with UTF8 encoding.
+typedef GenericStringStream<UTF8<> > StringStream;
+
+///////////////////////////////////////////////////////////////////////////////
+// InsituStringStream
+
+//! A read-write string stream.
+/*! This string stream is particularly designed for in-situ parsing.
+ \note implements Stream concept
+*/
+template <typename Encoding>
+struct GenericInsituStringStream {
+ typedef typename Encoding::Ch Ch;
+
+ GenericInsituStringStream(Ch *src) : src_(src), dst_(0), head_(src) {}
+
+ // Read
+ Ch Peek() { return *src_; }
+ Ch Take() { return *src_++; }
+ size_t Tell() { return static_cast<size_t>(src_ - head_); }
+
+ // Write
+ 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); }
+ void Flush() {}
+
+ Ch* Push(size_t count) { Ch* begin = dst_; dst_ += count; return begin; }
+ void Pop(size_t count) { dst_ -= count; }
+
+ Ch* src_;
+ Ch* dst_;
+ Ch* head_;
+};
+
+template <typename Encoding>
+struct StreamTraits<GenericInsituStringStream<Encoding> > {
+ enum { copyOptimization = 1 };
+};
+
+//! Insitu string stream with UTF8 encoding.
+typedef GenericInsituStringStream<UTF8<> > InsituStringStream;
+
+///////////////////////////////////////////////////////////////////////////////
+// Type
+
+//! Type of JSON value
+enum Type {
+ kNullType = 0, //!< null
+ kFalseType = 1, //!< false
+ kTrueType = 2, //!< true
+ kObjectType = 3, //!< object
+ kArrayType = 4, //!< array
+ kStringType = 5, //!< string
+ kNumberType = 6 //!< number
+};
+
+RAPIDJSON_NAMESPACE_END
+
+#endif // RAPIDJSON_RAPIDJSON_H_
diff --git a/libs/rapidjson/reader.h b/libs/rapidjson/include/rapidjson/reader.h
index 08297a08b..8d53db5c2 100644
--- a/libs/rapidjson/reader.h
+++ b/libs/rapidjson/include/rapidjson/reader.h
@@ -1,1440 +1,1440 @@
-// Tencent is pleased to support the open source community by making RapidJSON available.
-//
-// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
-//
-// Licensed under the MIT License (the "License"); you may not use this file except
-// in compliance with the License. You may obtain a copy of the License at
-//
-// http://opensource.org/licenses/MIT
-//
-// Unless required by applicable law or agreed to in writing, software distributed
-// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
-// CONDITIONS OF ANY KIND, either express or implied. See the License for the
-// specific language governing permissions and limitations under the License.
-
-#ifndef RAPIDJSON_READER_H_
-#define RAPIDJSON_READER_H_
-
-/*! \file reader.h */
-
-#include "rapidjson.h"
-#include "encodings.h"
-#include "internal/meta.h"
-#include "internal/stack.h"
-#include "internal/strtod.h"
-
-#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
-RAPIDJSON_DIAG_OFF(4702) // unreachable code
-#endif
-
-#ifdef __GNUC__
-RAPIDJSON_DIAG_PUSH
-RAPIDJSON_DIAG_OFF(effc++)
-#endif
-
-//!@cond RAPIDJSON_HIDDEN_FROM_DOXYGEN
-#define RAPIDJSON_NOTHING /* deliberately empty */
-#ifndef RAPIDJSON_PARSE_ERROR_EARLY_RETURN
-#define RAPIDJSON_PARSE_ERROR_EARLY_RETURN(value) \
- RAPIDJSON_MULTILINEMACRO_BEGIN \
- if (HasParseError()) { return value; } \
- RAPIDJSON_MULTILINEMACRO_END
-#endif
-#define RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID \
- RAPIDJSON_PARSE_ERROR_EARLY_RETURN(RAPIDJSON_NOTHING)
-//!@endcond
-
-/*! \def RAPIDJSON_PARSE_ERROR_NORETURN
- \ingroup RAPIDJSON_ERRORS
- \brief Macro to indicate a parse error.
- \param parseErrorCode \ref rapidjson::ParseErrorCode of the error
- \param offset position of the error in JSON input (\c size_t)
-
- This macros can be used as a customization point for the internal
- error handling mechanism of RapidJSON.
-
- A common usage model is to throw an exception instead of requiring the
- caller to explicitly check the \ref rapidjson::GenericReader::Parse's
- return value:
-
- \code
- #define RAPIDJSON_PARSE_ERROR_NORETURN(parseErrorCode,offset) \
- throw ParseException(parseErrorCode, #parseErrorCode, offset)
-
- #include <stdexcept> // std::runtime_error
- #include "rapidjson/error/error.h" // rapidjson::ParseResult
-
- struct ParseException : std::runtime_error, rapidjson::ParseResult {
- ParseException(rapidjson::ParseErrorCode code, const char* msg, size_t offset)
- : std::runtime_error(msg), ParseResult(code, offset) {}
- };
-
- #include "rapidjson/reader.h"
- \endcode
-
- \see RAPIDJSON_PARSE_ERROR, rapidjson::GenericReader::Parse
- */
-#ifndef RAPIDJSON_PARSE_ERROR_NORETURN
-#define RAPIDJSON_PARSE_ERROR_NORETURN(parseErrorCode, offset) \
- RAPIDJSON_MULTILINEMACRO_BEGIN \
- RAPIDJSON_ASSERT(!HasParseError()); /* Error can only be assigned once */ \
- SetParseError(parseErrorCode, offset); \
- RAPIDJSON_MULTILINEMACRO_END
-#endif
-
-/*! \def RAPIDJSON_PARSE_ERROR
- \ingroup RAPIDJSON_ERRORS
- \brief (Internal) macro to indicate and handle a parse error.
- \param parseErrorCode \ref rapidjson::ParseErrorCode of the error
- \param offset position of the error in JSON input (\c size_t)
-
- Invokes RAPIDJSON_PARSE_ERROR_NORETURN and stops the parsing.
-
- \see RAPIDJSON_PARSE_ERROR_NORETURN
- \hideinitializer
- */
-#ifndef RAPIDJSON_PARSE_ERROR
-#define RAPIDJSON_PARSE_ERROR(parseErrorCode, offset) \
- RAPIDJSON_MULTILINEMACRO_BEGIN \
- RAPIDJSON_PARSE_ERROR_NORETURN(parseErrorCode, offset); \
- RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID; \
- RAPIDJSON_MULTILINEMACRO_END
-#endif
-
-#include "error/error.h" // ParseErrorCode, ParseResult
-
-RAPIDJSON_NAMESPACE_BEGIN
-
-///////////////////////////////////////////////////////////////////////////////
-// ParseFlag
-
-/*! \def RAPIDJSON_PARSE_DEFAULT_FLAGS
- \ingroup RAPIDJSON_CONFIG
- \brief User-defined kParseDefaultFlags definition.
-
- User can define this as any \c ParseFlag combinations.
-*/
-#ifndef RAPIDJSON_PARSE_DEFAULT_FLAGS
-#define RAPIDJSON_PARSE_DEFAULT_FLAGS kParseNoFlags
-#endif
-
-//! Combination of parseFlags
-/*! \see Reader::Parse, Document::Parse, Document::ParseInsitu, Document::ParseStream
- */
-enum ParseFlag {
- kParseNoFlags = 0, //!< No flags are set.
- kParseInsituFlag = 1, //!< In-situ(destructive) parsing.
- kParseValidateEncodingFlag = 2, //!< Validate encoding of JSON strings.
- kParseIterativeFlag = 4, //!< Iterative(constant complexity in terms of function call stack size) parsing.
- 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).
- kParseDefaultFlags = RAPIDJSON_PARSE_DEFAULT_FLAGS //!< Default parse flags. Can be customized by defining RAPIDJSON_PARSE_DEFAULT_FLAGS
-};
-
-///////////////////////////////////////////////////////////////////////////////
-// Handler
-
-/*! \class rapidjson::Handler
- \brief Concept for receiving events from GenericReader upon parsing.
- The functions return true if no error occurs. If they return false,
- the event publisher should terminate the process.
-\code
-concept Handler {
- typename Ch;
-
- bool Null();
- bool Bool(bool b);
- bool Int(int i);
- bool Uint(unsigned i);
- bool Int64(int64_t i);
- bool Uint64(uint64_t i);
- bool Double(double d);
- bool String(const Ch* str, SizeType length, bool copy);
- bool StartObject();
- bool Key(const Ch* str, SizeType length, bool copy);
- bool EndObject(SizeType memberCount);
- bool StartArray();
- bool EndArray(SizeType elementCount);
-};
-\endcode
-*/
-///////////////////////////////////////////////////////////////////////////////
-// BaseReaderHandler
-
-//! Default implementation of Handler.
-/*! This can be used as base class of any reader handler.
- \note implements Handler concept
-*/
-template<typename Encoding = UTF8<>, typename Derived = void>
-struct BaseReaderHandler {
- typedef typename Encoding::Ch Ch;
-
- typedef typename internal::SelectIf<internal::IsSame<Derived, void>, BaseReaderHandler, Derived>::Type Override;
-
- bool Default() { return true; }
- bool Null() { return static_cast<Override&>(*this).Default(); }
- bool Bool(bool) { return static_cast<Override&>(*this).Default(); }
- bool Int(int) { return static_cast<Override&>(*this).Default(); }
- bool Uint(unsigned) { return static_cast<Override&>(*this).Default(); }
- 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(); }
- 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); }
- bool EndObject(SizeType) { return static_cast<Override&>(*this).Default(); }
- bool StartArray() { return static_cast<Override&>(*this).Default(); }
- bool EndArray(SizeType) { return static_cast<Override&>(*this).Default(); }
-};
-
-///////////////////////////////////////////////////////////////////////////////
-// StreamLocalCopy
-
-namespace internal {
-
-template<typename Stream, int = StreamTraits<Stream>::copyOptimization>
-class StreamLocalCopy;
-
-//! Do copy optimization.
-template<typename Stream>
-class StreamLocalCopy<Stream, 1> {
-public:
- StreamLocalCopy(Stream& original) : s(original), original_(original) {}
- ~StreamLocalCopy() { original_ = s; }
-
- Stream s;
-
-private:
- StreamLocalCopy& operator=(const StreamLocalCopy&) /* = delete */;
-
- Stream& original_;
-};
-
-//! Keep reference.
-template<typename Stream>
-class StreamLocalCopy<Stream, 0> {
-public:
- StreamLocalCopy(Stream& original) : s(original) {}
-
- Stream& s;
-
-private:
- StreamLocalCopy& operator=(const StreamLocalCopy&) /* = delete */;
-};
-
-} // namespace internal
-
-///////////////////////////////////////////////////////////////////////////////
-// SkipWhitespace
-
-//! Skip the JSON white spaces in a stream.
-/*! \param is A input stream for skipping white spaces.
- \note This function has SSE2/SSE4.2 specialization.
-*/
-template<typename InputStream>
-void SkipWhitespace(InputStream& is) {
- internal::StreamLocalCopy<InputStream> copy(is);
- InputStream& s(copy.s);
-
- while (s.Peek() == ' ' || s.Peek() == '\n' || s.Peek() == '\r' || s.Peek() == '\t')
- s.Take();
-}
-
-#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) {
- // Fast return for single non-whitespace
- if (*p == ' ' || *p == '\n' || *p == '\r' || *p == '\t')
- ++p;
- else
- return p;
-
- // 16-byte align to the next boundary
- const char* nextAligned = reinterpret_cast<const char*>((reinterpret_cast<size_t>(p) + 15) & ~15);
- while (p != nextAligned)
- if (*p == ' ' || *p == '\n' || *p == '\r' || *p == '\t')
- ++p;
- else
- return p;
-
- // The rest of string using SIMD
- static const char whitespace[16] = " \n\r\t";
- const __m128i w = _mm_load_si128((const __m128i *)&whitespace[0]);
-
- for (;; p += 16) {
- const __m128i s = _mm_load_si128((const __m128i *)p);
- const unsigned 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
- }
- }
-}
-
-#elif defined(RAPIDJSON_SSE2)
-
-//! Skip whitespace with SSE2 instructions, testing 16 8-byte characters at once.
-inline const char *SkipWhitespace_SIMD(const char* p) {
- // Fast return for single non-whitespace
- if (*p == ' ' || *p == '\n' || *p == '\r' || *p == '\t')
- ++p;
- else
- return p;
-
- // 16-byte align to the next boundary
- const char* nextAligned = reinterpret_cast<const char*>((reinterpret_cast<size_t>(p) + 15) & ~15);
- while (p != nextAligned)
- if (*p == ' ' || *p == '\n' || *p == '\r' || *p == '\t')
- ++p;
- else
- return p;
-
- // The rest of string
- static const char whitespaces[4][17] = {
- " ",
- "\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n",
- "\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r",
- "\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t"};
-
- const __m128i w0 = _mm_loadu_si128((const __m128i *)&whitespaces[0][0]);
- const __m128i w1 = _mm_loadu_si128((const __m128i *)&whitespaces[1][0]);
- const __m128i w2 = _mm_loadu_si128((const __m128i *)&whitespaces[2][0]);
- const __m128i w3 = _mm_loadu_si128((const __m128i *)&whitespaces[3][0]);
-
- for (;; p += 16) {
- const __m128i s = _mm_load_si128((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 = (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
- }
- }
-}
-
-#endif // RAPIDJSON_SSE2
-
-#ifdef RAPIDJSON_SIMD
-//! Template function specialization for InsituStringStream
-template<> inline void SkipWhitespace(InsituStringStream& is) {
- is.src_ = const_cast<char*>(SkipWhitespace_SIMD(is.src_));
-}
-
-//! Template function specialization for StringStream
-template<> inline void SkipWhitespace(StringStream& is) {
- is.src_ = SkipWhitespace_SIMD(is.src_);
-}
-#endif // RAPIDJSON_SIMD
-
-///////////////////////////////////////////////////////////////////////////////
-// GenericReader
-
-//! SAX-style JSON parser. Use \ref Reader for UTF8 encoding and default allocator.
-/*! GenericReader parses JSON text from a stream, and send events synchronously to an
- object implementing Handler concept.
-
- It needs to allocate a stack for storing a single decoded string during
- non-destructive parsing.
-
- For in-situ parsing, the decoded string is directly written to the source
- text string, no temporary buffer is required.
-
- A GenericReader object can be reused for parsing multiple JSON text.
-
- \tparam SourceEncoding Encoding of the input stream.
- \tparam TargetEncoding Encoding of the parse output.
- \tparam StackAllocator Allocator type for stack.
-*/
-template <typename SourceEncoding, typename TargetEncoding, typename StackAllocator = CrtAllocator>
-class GenericReader {
-public:
- typedef typename SourceEncoding::Ch Ch; //!< SourceEncoding character type
-
- //! Constructor.
- /*! \param stackAllocator Optional allocator for allocating stack memory. (Only use for non-destructive parsing)
- \param stackCapacity stack capacity in bytes for storing a single decoded string. (Only use for non-destructive parsing)
- */
- GenericReader(StackAllocator* stackAllocator = 0, size_t stackCapacity = kDefaultStackCapacity) : stack_(stackAllocator, stackCapacity), parseResult_() {}
-
- //! Parse JSON text.
- /*! \tparam parseFlags Combination of \ref ParseFlag.
- \tparam InputStream Type of input stream, implementing Stream concept.
- \tparam Handler Type of handler, implementing Handler concept.
- \param is Input stream to be parsed.
- \param handler The handler to receive events.
- \return Whether the parsing is successful.
- */
- template <unsigned parseFlags, typename InputStream, typename Handler>
- ParseResult Parse(InputStream& is, Handler& handler) {
- if (parseFlags & kParseIterativeFlag)
- return IterativeParse<parseFlags>(is, handler);
-
- parseResult_.Clear();
-
- ClearStackOnExit scope(*this);
-
- SkipWhitespace(is);
-
- if (is.Peek() == '\0') {
- RAPIDJSON_PARSE_ERROR_NORETURN(kParseErrorDocumentEmpty, is.Tell());
- RAPIDJSON_PARSE_ERROR_EARLY_RETURN(parseResult_);
- }
- else {
- ParseValue<parseFlags>(is, handler);
- RAPIDJSON_PARSE_ERROR_EARLY_RETURN(parseResult_);
-
- if (!(parseFlags & kParseStopWhenDoneFlag)) {
- SkipWhitespace(is);
-
- if (is.Peek() != '\0') {
- RAPIDJSON_PARSE_ERROR_NORETURN(kParseErrorDocumentRootNotSingular, is.Tell());
- RAPIDJSON_PARSE_ERROR_EARLY_RETURN(parseResult_);
- }
- }
- }
-
- return parseResult_;
- }
-
- //! Parse JSON text (with \ref kParseDefaultFlags)
- /*! \tparam InputStream Type of input stream, implementing Stream concept
- \tparam Handler Type of handler, implementing Handler concept.
- \param is Input stream to be parsed.
- \param handler The handler to receive events.
- \return Whether the parsing is successful.
- */
- template <typename InputStream, typename Handler>
- ParseResult Parse(InputStream& is, Handler& handler) {
- return Parse<kParseDefaultFlags>(is, handler);
- }
-
- //! Whether a parse error has occured in the last parsing.
- bool HasParseError() const { return parseResult_.IsError(); }
-
- //! Get the \ref ParseErrorCode of last parsing.
- ParseErrorCode GetParseErrorCode() const { return parseResult_.Code(); }
-
- //! Get the position of last parsing error in input, 0 otherwise.
- size_t GetErrorOffset() const { return parseResult_.Offset(); }
-
-protected:
- void SetParseError(ParseErrorCode code, size_t offset) { parseResult_.Set(code, offset); }
-
-private:
- // Prohibit copy constructor & assignment operator.
- GenericReader(const GenericReader&);
- GenericReader& operator=(const GenericReader&);
-
- void ClearStack() { stack_.Clear(); }
-
- // clear stack on any exit from ParseStream, e.g. due to exception
- struct ClearStackOnExit {
- explicit ClearStackOnExit(GenericReader& r) : r_(r) {}
- ~ClearStackOnExit() { r_.ClearStack(); }
- private:
- GenericReader& r_;
- ClearStackOnExit(const ClearStackOnExit&);
- ClearStackOnExit& operator=(const ClearStackOnExit&);
- };
-
- // Parse object: { string : value, ... }
- template<unsigned parseFlags, typename InputStream, typename Handler>
- void ParseObject(InputStream& is, Handler& handler) {
- RAPIDJSON_ASSERT(is.Peek() == '{');
- is.Take(); // Skip '{'
-
- if (!handler.StartObject())
- RAPIDJSON_PARSE_ERROR(kParseErrorTermination, is.Tell());
-
- SkipWhitespace(is);
-
- if (is.Peek() == '}') {
- is.Take();
- if (!handler.EndObject(0)) // empty object
- RAPIDJSON_PARSE_ERROR(kParseErrorTermination, is.Tell());
- return;
- }
-
- for (SizeType memberCount = 0;;) {
- if (is.Peek() != '"')
- RAPIDJSON_PARSE_ERROR(kParseErrorObjectMissName, is.Tell());
-
- ParseString<parseFlags>(is, handler, true);
- RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID;
-
- SkipWhitespace(is);
-
- if (is.Take() != ':')
- RAPIDJSON_PARSE_ERROR(kParseErrorObjectMissColon, is.Tell());
-
- SkipWhitespace(is);
-
- ParseValue<parseFlags>(is, handler);
- RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID;
-
- SkipWhitespace(is);
-
- ++memberCount;
-
- switch (is.Take()) {
- case ',': SkipWhitespace(is); break;
- case '}':
- if (!handler.EndObject(memberCount))
- RAPIDJSON_PARSE_ERROR(kParseErrorTermination, is.Tell());
- return;
- default: RAPIDJSON_PARSE_ERROR(kParseErrorObjectMissCommaOrCurlyBracket, is.Tell());
- }
- }
- }
-
- // Parse array: [ value, ... ]
- template<unsigned parseFlags, typename InputStream, typename Handler>
- void ParseArray(InputStream& is, Handler& handler) {
- RAPIDJSON_ASSERT(is.Peek() == '[');
- is.Take(); // Skip '['
-
- if (!handler.StartArray())
- RAPIDJSON_PARSE_ERROR(kParseErrorTermination, is.Tell());
-
- SkipWhitespace(is);
-
- if (is.Peek() == ']') {
- is.Take();
- if (!handler.EndArray(0)) // empty array
- RAPIDJSON_PARSE_ERROR(kParseErrorTermination, is.Tell());
- return;
- }
-
- for (SizeType elementCount = 0;;) {
- ParseValue<parseFlags>(is, handler);
- RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID;
-
- ++elementCount;
- SkipWhitespace(is);
-
- switch (is.Take()) {
- case ',': SkipWhitespace(is); break;
- case ']':
- if (!handler.EndArray(elementCount))
- RAPIDJSON_PARSE_ERROR(kParseErrorTermination, is.Tell());
- return;
- default: RAPIDJSON_PARSE_ERROR(kParseErrorArrayMissCommaOrSquareBracket, is.Tell());
- }
- }
- }
-
- template<unsigned parseFlags, typename InputStream, typename Handler>
- void ParseNull(InputStream& is, Handler& handler) {
- RAPIDJSON_ASSERT(is.Peek() == 'n');
- is.Take();
-
- if (is.Take() == 'u' && is.Take() == 'l' && is.Take() == 'l') {
- if (!handler.Null())
- RAPIDJSON_PARSE_ERROR(kParseErrorTermination, is.Tell());
- }
- else
- RAPIDJSON_PARSE_ERROR(kParseErrorValueInvalid, is.Tell() - 1);
- }
-
- template<unsigned parseFlags, typename InputStream, typename Handler>
- void ParseTrue(InputStream& is, Handler& handler) {
- RAPIDJSON_ASSERT(is.Peek() == 't');
- is.Take();
-
- if (is.Take() == 'r' && is.Take() == 'u' && is.Take() == 'e') {
- if (!handler.Bool(true))
- RAPIDJSON_PARSE_ERROR(kParseErrorTermination, is.Tell());
- }
- else
- RAPIDJSON_PARSE_ERROR(kParseErrorValueInvalid, is.Tell() - 1);
- }
-
- template<unsigned parseFlags, typename InputStream, typename Handler>
- void ParseFalse(InputStream& is, Handler& handler) {
- RAPIDJSON_ASSERT(is.Peek() == 'f');
- is.Take();
-
- if (is.Take() == 'a' && is.Take() == 'l' && is.Take() == 's' && is.Take() == 'e') {
- if (!handler.Bool(false))
- RAPIDJSON_PARSE_ERROR(kParseErrorTermination, is.Tell());
- }
- else
- RAPIDJSON_PARSE_ERROR(kParseErrorValueInvalid, is.Tell() - 1);
- }
-
- // Helper function to parse four hexidecimal digits in \uXXXX in ParseString().
- template<typename InputStream>
- unsigned ParseHex4(InputStream& is) {
- unsigned codepoint = 0;
- for (int i = 0; i < 4; i++) {
- Ch c = is.Take();
- codepoint <<= 4;
- codepoint += static_cast<unsigned>(c);
- if (c >= '0' && c <= '9')
- codepoint -= '0';
- else if (c >= 'A' && c <= 'F')
- codepoint -= 'A' - 10;
- else if (c >= 'a' && c <= 'f')
- codepoint -= 'a' - 10;
- else {
- RAPIDJSON_PARSE_ERROR_NORETURN(kParseErrorStringUnicodeEscapeInvalidHex, is.Tell() - 1);
- RAPIDJSON_PARSE_ERROR_EARLY_RETURN(0);
- }
- }
- return codepoint;
- }
-
- template <typename CharType>
- class StackStream {
- public:
- typedef CharType Ch;
-
- StackStream(internal::Stack<StackAllocator>& stack) : stack_(stack), length_(0) {}
- RAPIDJSON_FORCEINLINE void Put(Ch c) {
- *stack_.template Push<Ch>() = c;
- ++length_;
- }
- size_t Length() const { return length_; }
- Ch* Pop() {
- return stack_.template Pop<Ch>(length_);
- }
-
- private:
- StackStream(const StackStream&);
- StackStream& operator=(const StackStream&);
-
- internal::Stack<StackAllocator>& stack_;
- SizeType length_;
- };
-
- // Parse string and generate String event. Different code paths for kParseInsituFlag.
- template<unsigned parseFlags, typename InputStream, typename Handler>
- void ParseString(InputStream& is, Handler& handler, bool isKey = false) {
- internal::StreamLocalCopy<InputStream> copy(is);
- InputStream& s(copy.s);
-
- bool success = false;
- if (parseFlags & kParseInsituFlag) {
- typename InputStream::Ch *head = s.PutBegin();
- ParseStringToStream<parseFlags, SourceEncoding, SourceEncoding>(s, s);
- RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID;
- size_t length = s.PutEnd(head) - 1;
- RAPIDJSON_ASSERT(length <= 0xFFFFFFFF);
- const typename TargetEncoding::Ch* const str = (typename TargetEncoding::Ch*)head;
- success = (isKey ? handler.Key(str, SizeType(length), false) : handler.String(str, SizeType(length), false));
- }
- else {
- StackStream<typename TargetEncoding::Ch> stackStream(stack_);
- ParseStringToStream<parseFlags, SourceEncoding, TargetEncoding>(s, stackStream);
- RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID;
- SizeType length = static_cast<SizeType>(stackStream.Length()) - 1;
- const typename TargetEncoding::Ch* const str = stackStream.Pop();
- success = (isKey ? handler.Key(str, length, true) : handler.String(str, length, true));
- }
- if (!success)
- RAPIDJSON_PARSE_ERROR(kParseErrorTermination, s.Tell());
- }
-
- // Parse string to an output is
- // This function handles the prefix/suffix double quotes, escaping, and optional encoding validation.
- template<unsigned parseFlags, typename SEncoding, typename TEncoding, typename InputStream, typename OutputStream>
- RAPIDJSON_FORCEINLINE void ParseStringToStream(InputStream& is, OutputStream& os) {
-//!@cond RAPIDJSON_HIDDEN_FROM_DOXYGEN
-#define Z16 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
- static const char escape[256] = {
- Z16, Z16, 0, 0,'\"', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,'/',
- Z16, Z16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,'\\', 0, 0, 0,
- 0, 0,'\b', 0, 0, 0,'\f', 0, 0, 0, 0, 0, 0, 0,'\n', 0,
- 0, 0,'\r', 0,'\t', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- Z16, Z16, Z16, Z16, Z16, Z16, Z16, Z16
- };
-#undef Z16
-//!@endcond
-
- RAPIDJSON_ASSERT(is.Peek() == '\"');
- is.Take(); // Skip '\"'
-
- for (;;) {
- Ch c = is.Peek();
- if (c == '\\') { // Escape
- is.Take();
- Ch e = is.Take();
- if ((sizeof(Ch) == 1 || unsigned(e) < 256) && escape[(unsigned char)e]) {
- os.Put(escape[(unsigned char)e]);
- }
- else if (e == 'u') { // Unicode
- unsigned codepoint = ParseHex4(is);
- RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID;
- if (codepoint >= 0xD800 && codepoint <= 0xDBFF) {
- // Handle UTF-16 surrogate pair
- if (is.Take() != '\\' || is.Take() != 'u')
- RAPIDJSON_PARSE_ERROR(kParseErrorStringUnicodeSurrogateInvalid, is.Tell() - 2);
- unsigned codepoint2 = ParseHex4(is);
- RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID;
- if (codepoint2 < 0xDC00 || codepoint2 > 0xDFFF)
- RAPIDJSON_PARSE_ERROR(kParseErrorStringUnicodeSurrogateInvalid, is.Tell() - 2);
- codepoint = (((codepoint - 0xD800) << 10) | (codepoint2 - 0xDC00)) + 0x10000;
- }
- TEncoding::Encode(os, codepoint);
- }
- else
- RAPIDJSON_PARSE_ERROR(kParseErrorStringEscapeInvalid, is.Tell() - 1);
- }
- else if (c == '"') { // Closing double quote
- is.Take();
- os.Put('\0'); // null-terminate the string
- return;
- }
- else if (c == '\0')
- RAPIDJSON_PARSE_ERROR(kParseErrorStringMissQuotationMark, is.Tell() - 1);
- else if ((unsigned)c < 0x20) // RFC 4627: unescaped = %x20-21 / %x23-5B / %x5D-10FFFF
- RAPIDJSON_PARSE_ERROR(kParseErrorStringEscapeInvalid, is.Tell() - 1);
- else {
- if (parseFlags & kParseValidateEncodingFlag ?
- !Transcoder<SEncoding, TEncoding>::Validate(is, os) :
- !Transcoder<SEncoding, TEncoding>::Transcode(is, os))
- RAPIDJSON_PARSE_ERROR(kParseErrorStringInvalidEncoding, is.Tell());
- }
- }
- }
-
- template<typename InputStream, bool backup>
- class NumberStream;
-
- template<typename InputStream>
- class NumberStream<InputStream, false> {
- public:
- NumberStream(GenericReader& reader, InputStream& s) : is(s) { (void)reader; }
- ~NumberStream() {}
-
- RAPIDJSON_FORCEINLINE Ch Peek() const { return is.Peek(); }
- RAPIDJSON_FORCEINLINE Ch TakePush() { return is.Take(); }
- RAPIDJSON_FORCEINLINE Ch Take() { return is.Take(); }
- size_t Tell() { return is.Tell(); }
- size_t Length() { return 0; }
- const char* Pop() { return 0; }
-
- protected:
- NumberStream& operator=(const NumberStream&);
-
- InputStream& is;
- };
-
- template<typename InputStream>
- class NumberStream<InputStream, true> : public NumberStream<InputStream, false> {
- typedef NumberStream<InputStream, false> Base;
- public:
- NumberStream(GenericReader& reader, InputStream& is) : NumberStream<InputStream, false>(reader, is), stackStream(reader.stack_) {}
- ~NumberStream() {}
-
- RAPIDJSON_FORCEINLINE Ch TakePush() {
- stackStream.Put((char)Base::is.Peek());
- return Base::is.Take();
- }
-
- size_t Length() { return stackStream.Length(); }
-
- const char* Pop() {
- stackStream.Put('\0');
- return stackStream.Pop();
- }
-
- private:
- StackStream<char> stackStream;
- };
-
- 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);
-
- // Parse minus
- bool minus = false;
- if (s.Peek() == '-') {
- minus = true;
- s.Take();
- }
-
- // Parse int: zero / ( digit1-9 *DIGIT )
- unsigned i = 0;
- uint64_t i64 = 0;
- bool use64bit = false;
- int significandDigit = 0;
- if (s.Peek() == '0') {
- i = 0;
- s.TakePush();
- }
- else if (s.Peek() >= '1' && s.Peek() <= '9') {
- i = static_cast<unsigned>(s.TakePush() - '0');
-
- if (minus)
- while (s.Peek() >= '0' && s.Peek() <= '9') {
- if (i >= 214748364) { // 2^31 = 2147483648
- if (i != 214748364 || s.Peek() > '8') {
- i64 = i;
- use64bit = true;
- break;
- }
- }
- i = i * 10 + static_cast<unsigned>(s.TakePush() - '0');
- significandDigit++;
- }
- else
- while (s.Peek() >= '0' && s.Peek() <= '9') {
- if (i >= 429496729) { // 2^32 - 1 = 4294967295
- if (i != 429496729 || s.Peek() > '5') {
- i64 = i;
- use64bit = true;
- break;
- }
- }
- i = i * 10 + static_cast<unsigned>(s.TakePush() - '0');
- significandDigit++;
- }
- }
- else
- RAPIDJSON_PARSE_ERROR(kParseErrorValueInvalid, s.Tell());
-
- // Parse 64bit int
- bool useDouble = false;
- double d = 0.0;
- if (use64bit) {
- if (minus)
- while (s.Peek() >= '0' && s.Peek() <= '9') {
- if (i64 >= RAPIDJSON_UINT64_C2(0x0CCCCCCC, 0xCCCCCCCC)) // 2^63 = 9223372036854775808
- if (i64 != RAPIDJSON_UINT64_C2(0x0CCCCCCC, 0xCCCCCCCC) || s.Peek() > '8') {
- d = i64;
- useDouble = true;
- break;
- }
- i64 = i64 * 10 + static_cast<unsigned>(s.TakePush() - '0');
- significandDigit++;
- }
- else
- while (s.Peek() >= '0' && s.Peek() <= '9') {
- if (i64 >= RAPIDJSON_UINT64_C2(0x19999999, 0x99999999)) // 2^64 - 1 = 18446744073709551615
- if (i64 != RAPIDJSON_UINT64_C2(0x19999999, 0x99999999) || s.Peek() > '5') {
- d = i64;
- useDouble = true;
- break;
- }
- i64 = i64 * 10 + static_cast<unsigned>(s.TakePush() - '0');
- significandDigit++;
- }
- }
-
- // Force double for big integer
- if (useDouble) {
- while (s.Peek() >= '0' && s.Peek() <= '9') {
- if (d >= 1.7976931348623157e307) // DBL_MAX / 10.0
- RAPIDJSON_PARSE_ERROR(kParseErrorNumberTooBig, s.Tell());
- d = d * 10 + (s.TakePush() - '0');
- }
- }
-
- // Parse frac = decimal-point 1*DIGIT
- int expFrac = 0;
- size_t decimalPosition;
- if (s.Peek() == '.') {
- s.Take();
- decimalPosition = s.Length();
-
- if (!(s.Peek() >= '0' && s.Peek() <= '9'))
- RAPIDJSON_PARSE_ERROR(kParseErrorNumberMissFraction, s.Tell());
-
- if (!useDouble) {
-#if RAPIDJSON_64BIT
- // Use i64 to store significand in 64-bit architecture
- if (!use64bit)
- i64 = i;
-
- while (s.Peek() >= '0' && s.Peek() <= '9') {
- if (i64 > RAPIDJSON_UINT64_C2(0x1FFFFF, 0xFFFFFFFF)) // 2^53 - 1 for fast path
- break;
- else {
- i64 = i64 * 10 + static_cast<unsigned>(s.TakePush() - '0');
- --expFrac;
- if (i64 != 0)
- significandDigit++;
- }
- }
-
- d = (double)i64;
-#else
- // Use double to store significand in 32-bit architecture
- d = use64bit ? (double)i64 : (double)i;
-#endif
- useDouble = true;
- }
-
- while (s.Peek() >= '0' && s.Peek() <= '9') {
- if (significandDigit < 17) {
- d = d * 10.0 + (s.TakePush() - '0');
- --expFrac;
- if (d > 0.0)
- significandDigit++;
- }
- else
- s.TakePush();
- }
- }
- else
- decimalPosition = s.Length(); // decimal position at the end of integer.
-
- // Parse exp = e [ minus / plus ] 1*DIGIT
- int exp = 0;
- if (s.Peek() == 'e' || s.Peek() == 'E') {
- if (!useDouble) {
- d = use64bit ? i64 : i;
- useDouble = true;
- }
- s.Take();
-
- bool expMinus = false;
- if (s.Peek() == '+')
- s.Take();
- else if (s.Peek() == '-') {
- s.Take();
- expMinus = true;
- }
-
- if (s.Peek() >= '0' && s.Peek() <= '9') {
- exp = s.Take() - '0';
- while (s.Peek() >= '0' && s.Peek() <= '9') {
- exp = exp * 10 + (s.Take() - '0');
- if (exp > 308 && !expMinus) // exp > 308 should be rare, so it should be checked first.
- RAPIDJSON_PARSE_ERROR(kParseErrorNumberTooBig, s.Tell());
- }
- }
- else
- RAPIDJSON_PARSE_ERROR(kParseErrorNumberMissExponent, s.Tell());
-
- if (expMinus)
- exp = -exp;
- }
-
- // Finish parsing, call event according to the type of number.
- bool cont = true;
- size_t length = s.Length();
- const char* decimal = s.Pop(); // Pop stack no matter if it will be used or not.
-
- if (useDouble) {
- int p = exp + expFrac;
- if (parseFlags & kParseFullPrecisionFlag)
- d = internal::StrtodFullPrecision(d, p, decimal, length, decimalPosition, exp);
- else
- d = internal::StrtodNormalPrecision(d, p);
-
- cont = handler.Double(minus ? -d : d);
- }
- else {
- if (use64bit) {
- if (minus)
- cont = handler.Int64(-(int64_t)i64);
- else
- cont = handler.Uint64(i64);
- }
- else {
- if (minus)
- cont = handler.Int(-(int)i);
- else
- cont = handler.Uint(i);
- }
- }
- if (!cont)
- RAPIDJSON_PARSE_ERROR(kParseErrorTermination, s.Tell());
- }
-
- // Parse any JSON value
- template<unsigned parseFlags, typename InputStream, typename Handler>
- void ParseValue(InputStream& is, Handler& handler) {
- switch (is.Peek()) {
- case 'n': ParseNull <parseFlags>(is, handler); break;
- case 't': ParseTrue <parseFlags>(is, handler); break;
- case 'f': ParseFalse <parseFlags>(is, handler); break;
- case '"': ParseString<parseFlags>(is, handler); break;
- case '{': ParseObject<parseFlags>(is, handler); break;
- case '[': ParseArray <parseFlags>(is, handler); break;
- default : ParseNumber<parseFlags>(is, handler);
- }
- }
-
- // Iterative Parsing
-
- // States
- enum IterativeParsingState {
- IterativeParsingStartState = 0,
- IterativeParsingFinishState,
- IterativeParsingErrorState,
-
- // Object states
- IterativeParsingObjectInitialState,
- IterativeParsingMemberKeyState,
- IterativeParsingKeyValueDelimiterState,
- IterativeParsingMemberValueState,
- IterativeParsingMemberDelimiterState,
- IterativeParsingObjectFinishState,
-
- // Array states
- IterativeParsingArrayInitialState,
- IterativeParsingElementState,
- IterativeParsingElementDelimiterState,
- IterativeParsingArrayFinishState,
-
- // Single value state
- IterativeParsingValueState,
-
- cIterativeParsingStateCount
- };
-
- // Tokens
- enum Token {
- LeftBracketToken = 0,
- RightBracketToken,
-
- LeftCurlyBracketToken,
- RightCurlyBracketToken,
-
- CommaToken,
- ColonToken,
-
- StringToken,
- FalseToken,
- TrueToken,
- NullToken,
- NumberToken,
-
- kTokenCount
- };
-
- RAPIDJSON_FORCEINLINE Token Tokenize(Ch c) {
-
-//!@cond RAPIDJSON_HIDDEN_FROM_DOXYGEN
-#define N NumberToken
-#define N16 N,N,N,N,N,N,N,N,N,N,N,N,N,N,N,N
- // Maps from ASCII to Token
- static const unsigned char tokenMap[256] = {
- N16, // 00~0F
- N16, // 10~1F
- N, N, StringToken, N, N, N, N, N, N, N, N, N, CommaToken, N, N, N, // 20~2F
- N, N, N, N, N, N, N, N, N, N, ColonToken, N, N, N, N, N, // 30~3F
- N16, // 40~4F
- N, N, N, N, N, N, N, N, N, N, N, LeftBracketToken, N, RightBracketToken, N, N, // 50~5F
- N, N, N, N, N, N, FalseToken, N, N, N, N, N, N, N, NullToken, N, // 60~6F
- N, N, N, N, TrueToken, N, N, N, N, N, N, LeftCurlyBracketToken, N, RightCurlyBracketToken, N, N, // 70~7F
- N16, N16, N16, N16, N16, N16, N16, N16 // 80~FF
- };
-#undef N
-#undef N16
-//!@endcond
-
- if (sizeof(Ch) == 1 || unsigned(c) < 256)
- return (Token)tokenMap[(unsigned char)c];
- else
- return NumberToken;
- }
-
- RAPIDJSON_FORCEINLINE IterativeParsingState Predict(IterativeParsingState state, Token token) {
- // current state x one lookahead token -> new state
- static const char G[cIterativeParsingStateCount][kTokenCount] = {
- // Start
- {
- IterativeParsingArrayInitialState, // Left bracket
- IterativeParsingErrorState, // Right bracket
- IterativeParsingObjectInitialState, // Left curly bracket
- IterativeParsingErrorState, // Right curly bracket
- IterativeParsingErrorState, // Comma
- IterativeParsingErrorState, // Colon
- IterativeParsingValueState, // String
- IterativeParsingValueState, // False
- IterativeParsingValueState, // True
- IterativeParsingValueState, // Null
- IterativeParsingValueState // Number
- },
- // Finish(sink state)
- {
- IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState,
- IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState,
- IterativeParsingErrorState
- },
- // Error(sink state)
- {
- IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState,
- IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState,
- IterativeParsingErrorState
- },
- // ObjectInitial
- {
- IterativeParsingErrorState, // Left bracket
- IterativeParsingErrorState, // Right bracket
- IterativeParsingErrorState, // Left curly bracket
- IterativeParsingObjectFinishState, // Right curly bracket
- IterativeParsingErrorState, // Comma
- IterativeParsingErrorState, // Colon
- IterativeParsingMemberKeyState, // String
- IterativeParsingErrorState, // False
- IterativeParsingErrorState, // True
- IterativeParsingErrorState, // Null
- IterativeParsingErrorState // Number
- },
- // MemberKey
- {
- IterativeParsingErrorState, // Left bracket
- IterativeParsingErrorState, // Right bracket
- IterativeParsingErrorState, // Left curly bracket
- IterativeParsingErrorState, // Right curly bracket
- IterativeParsingErrorState, // Comma
- IterativeParsingKeyValueDelimiterState, // Colon
- IterativeParsingErrorState, // String
- IterativeParsingErrorState, // False
- IterativeParsingErrorState, // True
- IterativeParsingErrorState, // Null
- IterativeParsingErrorState // Number
- },
- // KeyValueDelimiter
- {
- IterativeParsingArrayInitialState, // Left bracket(push MemberValue state)
- IterativeParsingErrorState, // Right bracket
- IterativeParsingObjectInitialState, // Left curly bracket(push MemberValue state)
- IterativeParsingErrorState, // Right curly bracket
- IterativeParsingErrorState, // Comma
- IterativeParsingErrorState, // Colon
- IterativeParsingMemberValueState, // String
- IterativeParsingMemberValueState, // False
- IterativeParsingMemberValueState, // True
- IterativeParsingMemberValueState, // Null
- IterativeParsingMemberValueState // Number
- },
- // MemberValue
- {
- IterativeParsingErrorState, // Left bracket
- IterativeParsingErrorState, // Right bracket
- IterativeParsingErrorState, // Left curly bracket
- IterativeParsingObjectFinishState, // Right curly bracket
- IterativeParsingMemberDelimiterState, // Comma
- IterativeParsingErrorState, // Colon
- IterativeParsingErrorState, // String
- IterativeParsingErrorState, // False
- IterativeParsingErrorState, // True
- IterativeParsingErrorState, // Null
- IterativeParsingErrorState // Number
- },
- // MemberDelimiter
- {
- IterativeParsingErrorState, // Left bracket
- IterativeParsingErrorState, // Right bracket
- IterativeParsingErrorState, // Left curly bracket
- IterativeParsingErrorState, // Right curly bracket
- IterativeParsingErrorState, // Comma
- IterativeParsingErrorState, // Colon
- IterativeParsingMemberKeyState, // String
- IterativeParsingErrorState, // False
- IterativeParsingErrorState, // True
- IterativeParsingErrorState, // Null
- IterativeParsingErrorState // Number
- },
- // ObjectFinish(sink state)
- {
- IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState,
- IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState,
- IterativeParsingErrorState
- },
- // ArrayInitial
- {
- IterativeParsingArrayInitialState, // Left bracket(push Element state)
- IterativeParsingArrayFinishState, // Right bracket
- IterativeParsingObjectInitialState, // Left curly bracket(push Element state)
- IterativeParsingErrorState, // Right curly bracket
- IterativeParsingErrorState, // Comma
- IterativeParsingErrorState, // Colon
- IterativeParsingElementState, // String
- IterativeParsingElementState, // False
- IterativeParsingElementState, // True
- IterativeParsingElementState, // Null
- IterativeParsingElementState // Number
- },
- // Element
- {
- IterativeParsingErrorState, // Left bracket
- IterativeParsingArrayFinishState, // Right bracket
- IterativeParsingErrorState, // Left curly bracket
- IterativeParsingErrorState, // Right curly bracket
- IterativeParsingElementDelimiterState, // Comma
- IterativeParsingErrorState, // Colon
- IterativeParsingErrorState, // String
- IterativeParsingErrorState, // False
- IterativeParsingErrorState, // True
- IterativeParsingErrorState, // Null
- IterativeParsingErrorState // Number
- },
- // ElementDelimiter
- {
- IterativeParsingArrayInitialState, // Left bracket(push Element state)
- IterativeParsingErrorState, // Right bracket
- IterativeParsingObjectInitialState, // Left curly bracket(push Element state)
- IterativeParsingErrorState, // Right curly bracket
- IterativeParsingErrorState, // Comma
- IterativeParsingErrorState, // Colon
- IterativeParsingElementState, // String
- IterativeParsingElementState, // False
- IterativeParsingElementState, // True
- IterativeParsingElementState, // Null
- IterativeParsingElementState // Number
- },
- // ArrayFinish(sink state)
- {
- IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState,
- IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState,
- IterativeParsingErrorState
- },
- // Single Value (sink state)
- {
- IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState,
- IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState,
- IterativeParsingErrorState
- }
- }; // End of G
-
- return (IterativeParsingState)G[state][token];
- }
-
- // Make an advance in the token stream and state based on the candidate destination state which was returned by Transit().
- // May return a new state on state pop.
- template <unsigned parseFlags, typename InputStream, typename Handler>
- RAPIDJSON_FORCEINLINE IterativeParsingState Transit(IterativeParsingState src, Token token, IterativeParsingState dst, InputStream& is, Handler& handler) {
- (void)token;
-
- switch (dst) {
- case IterativeParsingErrorState:
- return dst;
-
- case IterativeParsingObjectInitialState:
- case IterativeParsingArrayInitialState:
- {
- // Push the state(Element or MemeberValue) if we are nested in another array or value of member.
- // In this way we can get the correct state on ObjectFinish or ArrayFinish by frame pop.
- IterativeParsingState n = src;
- if (src == IterativeParsingArrayInitialState || src == IterativeParsingElementDelimiterState)
- n = IterativeParsingElementState;
- else if (src == IterativeParsingKeyValueDelimiterState)
- n = IterativeParsingMemberValueState;
- // Push current state.
- *stack_.template Push<SizeType>(1) = n;
- // Initialize and push the member/element count.
- *stack_.template Push<SizeType>(1) = 0;
- // Call handler
- bool hr = (dst == IterativeParsingObjectInitialState) ? handler.StartObject() : handler.StartArray();
- // On handler short circuits the parsing.
- if (!hr) {
- RAPIDJSON_PARSE_ERROR_NORETURN(kParseErrorTermination, is.Tell());
- return IterativeParsingErrorState;
- }
- else {
- is.Take();
- return dst;
- }
- }
-
- case IterativeParsingMemberKeyState:
- ParseString<parseFlags>(is, handler, true);
- if (HasParseError())
- return IterativeParsingErrorState;
- else
- return dst;
-
- case IterativeParsingKeyValueDelimiterState:
- RAPIDJSON_ASSERT(token == ColonToken);
- is.Take();
- return dst;
-
- case IterativeParsingMemberValueState:
- // Must be non-compound value. Or it would be ObjectInitial or ArrayInitial state.
- ParseValue<parseFlags>(is, handler);
- if (HasParseError()) {
- return IterativeParsingErrorState;
- }
- return dst;
-
- case IterativeParsingElementState:
- // Must be non-compound value. Or it would be ObjectInitial or ArrayInitial state.
- ParseValue<parseFlags>(is, handler);
- if (HasParseError()) {
- return IterativeParsingErrorState;
- }
- return dst;
-
- case IterativeParsingMemberDelimiterState:
- case IterativeParsingElementDelimiterState:
- is.Take();
- // Update member/element count.
- *stack_.template Top<SizeType>() = *stack_.template Top<SizeType>() + 1;
- return dst;
-
- case IterativeParsingObjectFinishState:
- {
- // Get member count.
- SizeType c = *stack_.template Pop<SizeType>(1);
- // If the object is not empty, count the last member.
- if (src == IterativeParsingMemberValueState)
- ++c;
- // Restore the state.
- IterativeParsingState n = static_cast<IterativeParsingState>(*stack_.template Pop<SizeType>(1));
- // Transit to Finish state if this is the topmost scope.
- if (n == IterativeParsingStartState)
- n = IterativeParsingFinishState;
- // Call handler
- bool hr = handler.EndObject(c);
- // On handler short circuits the parsing.
- if (!hr) {
- RAPIDJSON_PARSE_ERROR_NORETURN(kParseErrorTermination, is.Tell());
- return IterativeParsingErrorState;
- }
- else {
- is.Take();
- return n;
- }
- }
-
- case IterativeParsingArrayFinishState:
- {
- // Get element count.
- SizeType c = *stack_.template Pop<SizeType>(1);
- // If the array is not empty, count the last element.
- if (src == IterativeParsingElementState)
- ++c;
- // Restore the state.
- IterativeParsingState n = static_cast<IterativeParsingState>(*stack_.template Pop<SizeType>(1));
- // Transit to Finish state if this is the topmost scope.
- if (n == IterativeParsingStartState)
- n = IterativeParsingFinishState;
- // Call handler
- bool hr = handler.EndArray(c);
- // On handler short circuits the parsing.
- if (!hr) {
- RAPIDJSON_PARSE_ERROR_NORETURN(kParseErrorTermination, is.Tell());
- return IterativeParsingErrorState;
- }
- else {
- is.Take();
- return n;
- }
- }
-
- default:
- // This branch is for IterativeParsingValueState actually.
- // Use `default:` rather than
- // `case IterativeParsingValueState:` is for code coverage.
-
- // The IterativeParsingStartState is not enumerated in this switch-case.
- // It is impossible for that case. And it can be caught by following assertion.
-
- // The IterativeParsingFinishState is not enumerated in this switch-case either.
- // It is a "derivative" state which cannot triggered from Predict() directly.
- // Therefore it cannot happen here. And it can be caught by following assertion.
- RAPIDJSON_ASSERT(dst == IterativeParsingValueState);
-
- // Must be non-compound value. Or it would be ObjectInitial or ArrayInitial state.
- ParseValue<parseFlags>(is, handler);
- if (HasParseError()) {
- return IterativeParsingErrorState;
- }
- return IterativeParsingFinishState;
- }
- }
-
- template <typename InputStream>
- void HandleError(IterativeParsingState src, InputStream& is) {
- if (HasParseError()) {
- // Error flag has been set.
- return;
- }
-
- switch (src) {
- case IterativeParsingStartState: RAPIDJSON_PARSE_ERROR(kParseErrorDocumentEmpty, is.Tell());
- case IterativeParsingFinishState: RAPIDJSON_PARSE_ERROR(kParseErrorDocumentRootNotSingular, is.Tell());
- case IterativeParsingObjectInitialState:
- case IterativeParsingMemberDelimiterState: RAPIDJSON_PARSE_ERROR(kParseErrorObjectMissName, is.Tell());
- case IterativeParsingMemberKeyState: RAPIDJSON_PARSE_ERROR(kParseErrorObjectMissColon, is.Tell());
- case IterativeParsingMemberValueState: RAPIDJSON_PARSE_ERROR(kParseErrorObjectMissCommaOrCurlyBracket, is.Tell());
- case IterativeParsingElementState: RAPIDJSON_PARSE_ERROR(kParseErrorArrayMissCommaOrSquareBracket, is.Tell());
- default: RAPIDJSON_PARSE_ERROR(kParseErrorUnspecificSyntaxError, is.Tell());
- }
- }
-
- template <unsigned parseFlags, typename InputStream, typename Handler>
- ParseResult IterativeParse(InputStream& is, Handler& handler) {
- parseResult_.Clear();
- ClearStackOnExit scope(*this);
- IterativeParsingState state = IterativeParsingStartState;
-
- SkipWhitespace(is);
- while (is.Peek() != '\0') {
- Token t = Tokenize(is.Peek());
- IterativeParsingState n = Predict(state, t);
- IterativeParsingState d = Transit<parseFlags>(state, t, n, is, handler);
-
- if (d == IterativeParsingErrorState) {
- HandleError(state, is);
- break;
- }
-
- state = d;
-
- // Do not further consume streams if a root JSON has been parsed.
- if ((parseFlags & kParseStopWhenDoneFlag) && state == IterativeParsingFinishState)
- break;
-
- SkipWhitespace(is);
- }
-
- // Handle the end of file.
- if (state != IterativeParsingFinishState)
- HandleError(state, is);
-
- return parseResult_;
- }
-
- static const size_t kDefaultStackCapacity = 256; //!< Default stack capacity in bytes for storing a single decoded string.
- internal::Stack<StackAllocator> stack_; //!< A stack for storing decoded string temporarily during non-destructive parsing.
- ParseResult parseResult_;
-}; // class GenericReader
-
-//! Reader with UTF8 encoding and default allocator.
-typedef GenericReader<UTF8<>, UTF8<> > Reader;
-
-RAPIDJSON_NAMESPACE_END
-
-#ifdef __GNUC__
-RAPIDJSON_DIAG_POP
-#endif
-
-#ifdef _MSC_VER
-RAPIDJSON_DIAG_POP
-#endif
-
-#endif // RAPIDJSON_READER_H_
+// Tencent is pleased to support the open source community by making RapidJSON available.
+//
+// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
+//
+// Licensed under the MIT License (the "License"); you may not use this file except
+// in compliance with the License. You may obtain a copy of the License at
+//
+// http://opensource.org/licenses/MIT
+//
+// Unless required by applicable law or agreed to in writing, software distributed
+// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
+// CONDITIONS OF ANY KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations under the License.
+
+#ifndef RAPIDJSON_READER_H_
+#define RAPIDJSON_READER_H_
+
+/*! \file reader.h */
+
+#include "rapidjson.h"
+#include "encodings.h"
+#include "internal/meta.h"
+#include "internal/stack.h"
+#include "internal/strtod.h"
+
+#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
+RAPIDJSON_DIAG_OFF(4702) // unreachable code
+#endif
+
+#ifdef __GNUC__
+RAPIDJSON_DIAG_PUSH
+RAPIDJSON_DIAG_OFF(effc++)
+#endif
+
+//!@cond RAPIDJSON_HIDDEN_FROM_DOXYGEN
+#define RAPIDJSON_NOTHING /* deliberately empty */
+#ifndef RAPIDJSON_PARSE_ERROR_EARLY_RETURN
+#define RAPIDJSON_PARSE_ERROR_EARLY_RETURN(value) \
+ RAPIDJSON_MULTILINEMACRO_BEGIN \
+ if (HasParseError()) { return value; } \
+ RAPIDJSON_MULTILINEMACRO_END
+#endif
+#define RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID \
+ RAPIDJSON_PARSE_ERROR_EARLY_RETURN(RAPIDJSON_NOTHING)
+//!@endcond
+
+/*! \def RAPIDJSON_PARSE_ERROR_NORETURN
+ \ingroup RAPIDJSON_ERRORS
+ \brief Macro to indicate a parse error.
+ \param parseErrorCode \ref rapidjson::ParseErrorCode of the error
+ \param offset position of the error in JSON input (\c size_t)
+
+ This macros can be used as a customization point for the internal
+ error handling mechanism of RapidJSON.
+
+ A common usage model is to throw an exception instead of requiring the
+ caller to explicitly check the \ref rapidjson::GenericReader::Parse's
+ return value:
+
+ \code
+ #define RAPIDJSON_PARSE_ERROR_NORETURN(parseErrorCode,offset) \
+ throw ParseException(parseErrorCode, #parseErrorCode, offset)
+
+ #include <stdexcept> // std::runtime_error
+ #include "rapidjson/error/error.h" // rapidjson::ParseResult
+
+ struct ParseException : std::runtime_error, rapidjson::ParseResult {
+ ParseException(rapidjson::ParseErrorCode code, const char* msg, size_t offset)
+ : std::runtime_error(msg), ParseResult(code, offset) {}
+ };
+
+ #include "rapidjson/reader.h"
+ \endcode
+
+ \see RAPIDJSON_PARSE_ERROR, rapidjson::GenericReader::Parse
+ */
+#ifndef RAPIDJSON_PARSE_ERROR_NORETURN
+#define RAPIDJSON_PARSE_ERROR_NORETURN(parseErrorCode, offset) \
+ RAPIDJSON_MULTILINEMACRO_BEGIN \
+ RAPIDJSON_ASSERT(!HasParseError()); /* Error can only be assigned once */ \
+ SetParseError(parseErrorCode, offset); \
+ RAPIDJSON_MULTILINEMACRO_END
+#endif
+
+/*! \def RAPIDJSON_PARSE_ERROR
+ \ingroup RAPIDJSON_ERRORS
+ \brief (Internal) macro to indicate and handle a parse error.
+ \param parseErrorCode \ref rapidjson::ParseErrorCode of the error
+ \param offset position of the error in JSON input (\c size_t)
+
+ Invokes RAPIDJSON_PARSE_ERROR_NORETURN and stops the parsing.
+
+ \see RAPIDJSON_PARSE_ERROR_NORETURN
+ \hideinitializer
+ */
+#ifndef RAPIDJSON_PARSE_ERROR
+#define RAPIDJSON_PARSE_ERROR(parseErrorCode, offset) \
+ RAPIDJSON_MULTILINEMACRO_BEGIN \
+ RAPIDJSON_PARSE_ERROR_NORETURN(parseErrorCode, offset); \
+ RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID; \
+ RAPIDJSON_MULTILINEMACRO_END
+#endif
+
+#include "error/error.h" // ParseErrorCode, ParseResult
+
+RAPIDJSON_NAMESPACE_BEGIN
+
+///////////////////////////////////////////////////////////////////////////////
+// ParseFlag
+
+/*! \def RAPIDJSON_PARSE_DEFAULT_FLAGS
+ \ingroup RAPIDJSON_CONFIG
+ \brief User-defined kParseDefaultFlags definition.
+
+ User can define this as any \c ParseFlag combinations.
+*/
+#ifndef RAPIDJSON_PARSE_DEFAULT_FLAGS
+#define RAPIDJSON_PARSE_DEFAULT_FLAGS kParseNoFlags
+#endif
+
+//! Combination of parseFlags
+/*! \see Reader::Parse, Document::Parse, Document::ParseInsitu, Document::ParseStream
+ */
+enum ParseFlag {
+ kParseNoFlags = 0, //!< No flags are set.
+ kParseInsituFlag = 1, //!< In-situ(destructive) parsing.
+ kParseValidateEncodingFlag = 2, //!< Validate encoding of JSON strings.
+ kParseIterativeFlag = 4, //!< Iterative(constant complexity in terms of function call stack size) parsing.
+ 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).
+ kParseDefaultFlags = RAPIDJSON_PARSE_DEFAULT_FLAGS //!< Default parse flags. Can be customized by defining RAPIDJSON_PARSE_DEFAULT_FLAGS
+};
+
+///////////////////////////////////////////////////////////////////////////////
+// Handler
+
+/*! \class rapidjson::Handler
+ \brief Concept for receiving events from GenericReader upon parsing.
+ The functions return true if no error occurs. If they return false,
+ the event publisher should terminate the process.
+\code
+concept Handler {
+ typename Ch;
+
+ bool Null();
+ bool Bool(bool b);
+ bool Int(int i);
+ bool Uint(unsigned i);
+ bool Int64(int64_t i);
+ bool Uint64(uint64_t i);
+ bool Double(double d);
+ bool String(const Ch* str, SizeType length, bool copy);
+ bool StartObject();
+ bool Key(const Ch* str, SizeType length, bool copy);
+ bool EndObject(SizeType memberCount);
+ bool StartArray();
+ bool EndArray(SizeType elementCount);
+};
+\endcode
+*/
+///////////////////////////////////////////////////////////////////////////////
+// BaseReaderHandler
+
+//! Default implementation of Handler.
+/*! This can be used as base class of any reader handler.
+ \note implements Handler concept
+*/
+template<typename Encoding = UTF8<>, typename Derived = void>
+struct BaseReaderHandler {
+ typedef typename Encoding::Ch Ch;
+
+ typedef typename internal::SelectIf<internal::IsSame<Derived, void>, BaseReaderHandler, Derived>::Type Override;
+
+ bool Default() { return true; }
+ bool Null() { return static_cast<Override&>(*this).Default(); }
+ bool Bool(bool) { return static_cast<Override&>(*this).Default(); }
+ bool Int(int) { return static_cast<Override&>(*this).Default(); }
+ bool Uint(unsigned) { return static_cast<Override&>(*this).Default(); }
+ 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(); }
+ 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); }
+ bool EndObject(SizeType) { return static_cast<Override&>(*this).Default(); }
+ bool StartArray() { return static_cast<Override&>(*this).Default(); }
+ bool EndArray(SizeType) { return static_cast<Override&>(*this).Default(); }
+};
+
+///////////////////////////////////////////////////////////////////////////////
+// StreamLocalCopy
+
+namespace internal {
+
+template<typename Stream, int = StreamTraits<Stream>::copyOptimization>
+class StreamLocalCopy;
+
+//! Do copy optimization.
+template<typename Stream>
+class StreamLocalCopy<Stream, 1> {
+public:
+ StreamLocalCopy(Stream& original) : s(original), original_(original) {}
+ ~StreamLocalCopy() { original_ = s; }
+
+ Stream s;
+
+private:
+ StreamLocalCopy& operator=(const StreamLocalCopy&) /* = delete */;
+
+ Stream& original_;
+};
+
+//! Keep reference.
+template<typename Stream>
+class StreamLocalCopy<Stream, 0> {
+public:
+ StreamLocalCopy(Stream& original) : s(original) {}
+
+ Stream& s;
+
+private:
+ StreamLocalCopy& operator=(const StreamLocalCopy&) /* = delete */;
+};
+
+} // namespace internal
+
+///////////////////////////////////////////////////////////////////////////////
+// SkipWhitespace
+
+//! Skip the JSON white spaces in a stream.
+/*! \param is A input stream for skipping white spaces.
+ \note This function has SSE2/SSE4.2 specialization.
+*/
+template<typename InputStream>
+void SkipWhitespace(InputStream& is) {
+ internal::StreamLocalCopy<InputStream> copy(is);
+ InputStream& s(copy.s);
+
+ while (s.Peek() == ' ' || s.Peek() == '\n' || s.Peek() == '\r' || s.Peek() == '\t')
+ s.Take();
+}
+
+#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) {
+ // Fast return for single non-whitespace
+ if (*p == ' ' || *p == '\n' || *p == '\r' || *p == '\t')
+ ++p;
+ else
+ return p;
+
+ // 16-byte align to the next boundary
+ const char* nextAligned = reinterpret_cast<const char*>((reinterpret_cast<size_t>(p) + 15) & ~15);
+ while (p != nextAligned)
+ if (*p == ' ' || *p == '\n' || *p == '\r' || *p == '\t')
+ ++p;
+ else
+ return p;
+
+ // The rest of string using SIMD
+ static const char whitespace[16] = " \n\r\t";
+ const __m128i w = _mm_load_si128((const __m128i *)&whitespace[0]);
+
+ for (;; p += 16) {
+ const __m128i s = _mm_load_si128((const __m128i *)p);
+ const unsigned 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
+ }
+ }
+}
+
+#elif defined(RAPIDJSON_SSE2)
+
+//! Skip whitespace with SSE2 instructions, testing 16 8-byte characters at once.
+inline const char *SkipWhitespace_SIMD(const char* p) {
+ // Fast return for single non-whitespace
+ if (*p == ' ' || *p == '\n' || *p == '\r' || *p == '\t')
+ ++p;
+ else
+ return p;
+
+ // 16-byte align to the next boundary
+ const char* nextAligned = reinterpret_cast<const char*>((reinterpret_cast<size_t>(p) + 15) & ~15);
+ while (p != nextAligned)
+ if (*p == ' ' || *p == '\n' || *p == '\r' || *p == '\t')
+ ++p;
+ else
+ return p;
+
+ // The rest of string
+ static const char whitespaces[4][17] = {
+ " ",
+ "\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n",
+ "\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r",
+ "\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t"};
+
+ const __m128i w0 = _mm_loadu_si128((const __m128i *)&whitespaces[0][0]);
+ const __m128i w1 = _mm_loadu_si128((const __m128i *)&whitespaces[1][0]);
+ const __m128i w2 = _mm_loadu_si128((const __m128i *)&whitespaces[2][0]);
+ const __m128i w3 = _mm_loadu_si128((const __m128i *)&whitespaces[3][0]);
+
+ for (;; p += 16) {
+ const __m128i s = _mm_load_si128((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 = (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
+ }
+ }
+}
+
+#endif // RAPIDJSON_SSE2
+
+#ifdef RAPIDJSON_SIMD
+//! Template function specialization for InsituStringStream
+template<> inline void SkipWhitespace(InsituStringStream& is) {
+ is.src_ = const_cast<char*>(SkipWhitespace_SIMD(is.src_));
+}
+
+//! Template function specialization for StringStream
+template<> inline void SkipWhitespace(StringStream& is) {
+ is.src_ = SkipWhitespace_SIMD(is.src_);
+}
+#endif // RAPIDJSON_SIMD
+
+///////////////////////////////////////////////////////////////////////////////
+// GenericReader
+
+//! SAX-style JSON parser. Use \ref Reader for UTF8 encoding and default allocator.
+/*! GenericReader parses JSON text from a stream, and send events synchronously to an
+ object implementing Handler concept.
+
+ It needs to allocate a stack for storing a single decoded string during
+ non-destructive parsing.
+
+ For in-situ parsing, the decoded string is directly written to the source
+ text string, no temporary buffer is required.
+
+ A GenericReader object can be reused for parsing multiple JSON text.
+
+ \tparam SourceEncoding Encoding of the input stream.
+ \tparam TargetEncoding Encoding of the parse output.
+ \tparam StackAllocator Allocator type for stack.
+*/
+template <typename SourceEncoding, typename TargetEncoding, typename StackAllocator = CrtAllocator>
+class GenericReader {
+public:
+ typedef typename SourceEncoding::Ch Ch; //!< SourceEncoding character type
+
+ //! Constructor.
+ /*! \param stackAllocator Optional allocator for allocating stack memory. (Only use for non-destructive parsing)
+ \param stackCapacity stack capacity in bytes for storing a single decoded string. (Only use for non-destructive parsing)
+ */
+ GenericReader(StackAllocator* stackAllocator = 0, size_t stackCapacity = kDefaultStackCapacity) : stack_(stackAllocator, stackCapacity), parseResult_() {}
+
+ //! Parse JSON text.
+ /*! \tparam parseFlags Combination of \ref ParseFlag.
+ \tparam InputStream Type of input stream, implementing Stream concept.
+ \tparam Handler Type of handler, implementing Handler concept.
+ \param is Input stream to be parsed.
+ \param handler The handler to receive events.
+ \return Whether the parsing is successful.
+ */
+ template <unsigned parseFlags, typename InputStream, typename Handler>
+ ParseResult Parse(InputStream& is, Handler& handler) {
+ if (parseFlags & kParseIterativeFlag)
+ return IterativeParse<parseFlags>(is, handler);
+
+ parseResult_.Clear();
+
+ ClearStackOnExit scope(*this);
+
+ SkipWhitespace(is);
+
+ if (is.Peek() == '\0') {
+ RAPIDJSON_PARSE_ERROR_NORETURN(kParseErrorDocumentEmpty, is.Tell());
+ RAPIDJSON_PARSE_ERROR_EARLY_RETURN(parseResult_);
+ }
+ else {
+ ParseValue<parseFlags>(is, handler);
+ RAPIDJSON_PARSE_ERROR_EARLY_RETURN(parseResult_);
+
+ if (!(parseFlags & kParseStopWhenDoneFlag)) {
+ SkipWhitespace(is);
+
+ if (is.Peek() != '\0') {
+ RAPIDJSON_PARSE_ERROR_NORETURN(kParseErrorDocumentRootNotSingular, is.Tell());
+ RAPIDJSON_PARSE_ERROR_EARLY_RETURN(parseResult_);
+ }
+ }
+ }
+
+ return parseResult_;
+ }
+
+ //! Parse JSON text (with \ref kParseDefaultFlags)
+ /*! \tparam InputStream Type of input stream, implementing Stream concept
+ \tparam Handler Type of handler, implementing Handler concept.
+ \param is Input stream to be parsed.
+ \param handler The handler to receive events.
+ \return Whether the parsing is successful.
+ */
+ template <typename InputStream, typename Handler>
+ ParseResult Parse(InputStream& is, Handler& handler) {
+ return Parse<kParseDefaultFlags>(is, handler);
+ }
+
+ //! Whether a parse error has occured in the last parsing.
+ bool HasParseError() const { return parseResult_.IsError(); }
+
+ //! Get the \ref ParseErrorCode of last parsing.
+ ParseErrorCode GetParseErrorCode() const { return parseResult_.Code(); }
+
+ //! Get the position of last parsing error in input, 0 otherwise.
+ size_t GetErrorOffset() const { return parseResult_.Offset(); }
+
+protected:
+ void SetParseError(ParseErrorCode code, size_t offset) { parseResult_.Set(code, offset); }
+
+private:
+ // Prohibit copy constructor & assignment operator.
+ GenericReader(const GenericReader&);
+ GenericReader& operator=(const GenericReader&);
+
+ void ClearStack() { stack_.Clear(); }
+
+ // clear stack on any exit from ParseStream, e.g. due to exception
+ struct ClearStackOnExit {
+ explicit ClearStackOnExit(GenericReader& r) : r_(r) {}
+ ~ClearStackOnExit() { r_.ClearStack(); }
+ private:
+ GenericReader& r_;
+ ClearStackOnExit(const ClearStackOnExit&);
+ ClearStackOnExit& operator=(const ClearStackOnExit&);
+ };
+
+ // Parse object: { string : value, ... }
+ template<unsigned parseFlags, typename InputStream, typename Handler>
+ void ParseObject(InputStream& is, Handler& handler) {
+ RAPIDJSON_ASSERT(is.Peek() == '{');
+ is.Take(); // Skip '{'
+
+ if (!handler.StartObject())
+ RAPIDJSON_PARSE_ERROR(kParseErrorTermination, is.Tell());
+
+ SkipWhitespace(is);
+
+ if (is.Peek() == '}') {
+ is.Take();
+ if (!handler.EndObject(0)) // empty object
+ RAPIDJSON_PARSE_ERROR(kParseErrorTermination, is.Tell());
+ return;
+ }
+
+ for (SizeType memberCount = 0;;) {
+ if (is.Peek() != '"')
+ RAPIDJSON_PARSE_ERROR(kParseErrorObjectMissName, is.Tell());
+
+ ParseString<parseFlags>(is, handler, true);
+ RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID;
+
+ SkipWhitespace(is);
+
+ if (is.Take() != ':')
+ RAPIDJSON_PARSE_ERROR(kParseErrorObjectMissColon, is.Tell());
+
+ SkipWhitespace(is);
+
+ ParseValue<parseFlags>(is, handler);
+ RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID;
+
+ SkipWhitespace(is);
+
+ ++memberCount;
+
+ switch (is.Take()) {
+ case ',': SkipWhitespace(is); break;
+ case '}':
+ if (!handler.EndObject(memberCount))
+ RAPIDJSON_PARSE_ERROR(kParseErrorTermination, is.Tell());
+ return;
+ default: RAPIDJSON_PARSE_ERROR(kParseErrorObjectMissCommaOrCurlyBracket, is.Tell());
+ }
+ }
+ }
+
+ // Parse array: [ value, ... ]
+ template<unsigned parseFlags, typename InputStream, typename Handler>
+ void ParseArray(InputStream& is, Handler& handler) {
+ RAPIDJSON_ASSERT(is.Peek() == '[');
+ is.Take(); // Skip '['
+
+ if (!handler.StartArray())
+ RAPIDJSON_PARSE_ERROR(kParseErrorTermination, is.Tell());
+
+ SkipWhitespace(is);
+
+ if (is.Peek() == ']') {
+ is.Take();
+ if (!handler.EndArray(0)) // empty array
+ RAPIDJSON_PARSE_ERROR(kParseErrorTermination, is.Tell());
+ return;
+ }
+
+ for (SizeType elementCount = 0;;) {
+ ParseValue<parseFlags>(is, handler);
+ RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID;
+
+ ++elementCount;
+ SkipWhitespace(is);
+
+ switch (is.Take()) {
+ case ',': SkipWhitespace(is); break;
+ case ']':
+ if (!handler.EndArray(elementCount))
+ RAPIDJSON_PARSE_ERROR(kParseErrorTermination, is.Tell());
+ return;
+ default: RAPIDJSON_PARSE_ERROR(kParseErrorArrayMissCommaOrSquareBracket, is.Tell());
+ }
+ }
+ }
+
+ template<unsigned parseFlags, typename InputStream, typename Handler>
+ void ParseNull(InputStream& is, Handler& handler) {
+ RAPIDJSON_ASSERT(is.Peek() == 'n');
+ is.Take();
+
+ if (is.Take() == 'u' && is.Take() == 'l' && is.Take() == 'l') {
+ if (!handler.Null())
+ RAPIDJSON_PARSE_ERROR(kParseErrorTermination, is.Tell());
+ }
+ else
+ RAPIDJSON_PARSE_ERROR(kParseErrorValueInvalid, is.Tell() - 1);
+ }
+
+ template<unsigned parseFlags, typename InputStream, typename Handler>
+ void ParseTrue(InputStream& is, Handler& handler) {
+ RAPIDJSON_ASSERT(is.Peek() == 't');
+ is.Take();
+
+ if (is.Take() == 'r' && is.Take() == 'u' && is.Take() == 'e') {
+ if (!handler.Bool(true))
+ RAPIDJSON_PARSE_ERROR(kParseErrorTermination, is.Tell());
+ }
+ else
+ RAPIDJSON_PARSE_ERROR(kParseErrorValueInvalid, is.Tell() - 1);
+ }
+
+ template<unsigned parseFlags, typename InputStream, typename Handler>
+ void ParseFalse(InputStream& is, Handler& handler) {
+ RAPIDJSON_ASSERT(is.Peek() == 'f');
+ is.Take();
+
+ if (is.Take() == 'a' && is.Take() == 'l' && is.Take() == 's' && is.Take() == 'e') {
+ if (!handler.Bool(false))
+ RAPIDJSON_PARSE_ERROR(kParseErrorTermination, is.Tell());
+ }
+ else
+ RAPIDJSON_PARSE_ERROR(kParseErrorValueInvalid, is.Tell() - 1);
+ }
+
+ // Helper function to parse four hexidecimal digits in \uXXXX in ParseString().
+ template<typename InputStream>
+ unsigned ParseHex4(InputStream& is) {
+ unsigned codepoint = 0;
+ for (int i = 0; i < 4; i++) {
+ Ch c = is.Take();
+ codepoint <<= 4;
+ codepoint += static_cast<unsigned>(c);
+ if (c >= '0' && c <= '9')
+ codepoint -= '0';
+ else if (c >= 'A' && c <= 'F')
+ codepoint -= 'A' - 10;
+ else if (c >= 'a' && c <= 'f')
+ codepoint -= 'a' - 10;
+ else {
+ RAPIDJSON_PARSE_ERROR_NORETURN(kParseErrorStringUnicodeEscapeInvalidHex, is.Tell() - 1);
+ RAPIDJSON_PARSE_ERROR_EARLY_RETURN(0);
+ }
+ }
+ return codepoint;
+ }
+
+ template <typename CharType>
+ class StackStream {
+ public:
+ typedef CharType Ch;
+
+ StackStream(internal::Stack<StackAllocator>& stack) : stack_(stack), length_(0) {}
+ RAPIDJSON_FORCEINLINE void Put(Ch c) {
+ *stack_.template Push<Ch>() = c;
+ ++length_;
+ }
+ size_t Length() const { return length_; }
+ Ch* Pop() {
+ return stack_.template Pop<Ch>(length_);
+ }
+
+ private:
+ StackStream(const StackStream&);
+ StackStream& operator=(const StackStream&);
+
+ internal::Stack<StackAllocator>& stack_;
+ SizeType length_;
+ };
+
+ // Parse string and generate String event. Different code paths for kParseInsituFlag.
+ template<unsigned parseFlags, typename InputStream, typename Handler>
+ void ParseString(InputStream& is, Handler& handler, bool isKey = false) {
+ internal::StreamLocalCopy<InputStream> copy(is);
+ InputStream& s(copy.s);
+
+ bool success = false;
+ if (parseFlags & kParseInsituFlag) {
+ typename InputStream::Ch *head = s.PutBegin();
+ ParseStringToStream<parseFlags, SourceEncoding, SourceEncoding>(s, s);
+ RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID;
+ size_t length = s.PutEnd(head) - 1;
+ RAPIDJSON_ASSERT(length <= 0xFFFFFFFF);
+ const typename TargetEncoding::Ch* const str = (typename TargetEncoding::Ch*)head;
+ success = (isKey ? handler.Key(str, SizeType(length), false) : handler.String(str, SizeType(length), false));
+ }
+ else {
+ StackStream<typename TargetEncoding::Ch> stackStream(stack_);
+ ParseStringToStream<parseFlags, SourceEncoding, TargetEncoding>(s, stackStream);
+ RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID;
+ SizeType length = static_cast<SizeType>(stackStream.Length()) - 1;
+ const typename TargetEncoding::Ch* const str = stackStream.Pop();
+ success = (isKey ? handler.Key(str, length, true) : handler.String(str, length, true));
+ }
+ if (!success)
+ RAPIDJSON_PARSE_ERROR(kParseErrorTermination, s.Tell());
+ }
+
+ // Parse string to an output is
+ // This function handles the prefix/suffix double quotes, escaping, and optional encoding validation.
+ template<unsigned parseFlags, typename SEncoding, typename TEncoding, typename InputStream, typename OutputStream>
+ RAPIDJSON_FORCEINLINE void ParseStringToStream(InputStream& is, OutputStream& os) {
+//!@cond RAPIDJSON_HIDDEN_FROM_DOXYGEN
+#define Z16 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
+ static const char escape[256] = {
+ Z16, Z16, 0, 0,'\"', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,'/',
+ Z16, Z16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,'\\', 0, 0, 0,
+ 0, 0,'\b', 0, 0, 0,'\f', 0, 0, 0, 0, 0, 0, 0,'\n', 0,
+ 0, 0,'\r', 0,'\t', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ Z16, Z16, Z16, Z16, Z16, Z16, Z16, Z16
+ };
+#undef Z16
+//!@endcond
+
+ RAPIDJSON_ASSERT(is.Peek() == '\"');
+ is.Take(); // Skip '\"'
+
+ for (;;) {
+ Ch c = is.Peek();
+ if (c == '\\') { // Escape
+ is.Take();
+ Ch e = is.Take();
+ if ((sizeof(Ch) == 1 || unsigned(e) < 256) && escape[(unsigned char)e]) {
+ os.Put(escape[(unsigned char)e]);
+ }
+ else if (e == 'u') { // Unicode
+ unsigned codepoint = ParseHex4(is);
+ RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID;
+ if (codepoint >= 0xD800 && codepoint <= 0xDBFF) {
+ // Handle UTF-16 surrogate pair
+ if (is.Take() != '\\' || is.Take() != 'u')
+ RAPIDJSON_PARSE_ERROR(kParseErrorStringUnicodeSurrogateInvalid, is.Tell() - 2);
+ unsigned codepoint2 = ParseHex4(is);
+ RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID;
+ if (codepoint2 < 0xDC00 || codepoint2 > 0xDFFF)
+ RAPIDJSON_PARSE_ERROR(kParseErrorStringUnicodeSurrogateInvalid, is.Tell() - 2);
+ codepoint = (((codepoint - 0xD800) << 10) | (codepoint2 - 0xDC00)) + 0x10000;
+ }
+ TEncoding::Encode(os, codepoint);
+ }
+ else
+ RAPIDJSON_PARSE_ERROR(kParseErrorStringEscapeInvalid, is.Tell() - 1);
+ }
+ else if (c == '"') { // Closing double quote
+ is.Take();
+ os.Put('\0'); // null-terminate the string
+ return;
+ }
+ else if (c == '\0')
+ RAPIDJSON_PARSE_ERROR(kParseErrorStringMissQuotationMark, is.Tell() - 1);
+ else if ((unsigned)c < 0x20) // RFC 4627: unescaped = %x20-21 / %x23-5B / %x5D-10FFFF
+ RAPIDJSON_PARSE_ERROR(kParseErrorStringEscapeInvalid, is.Tell() - 1);
+ else {
+ if (parseFlags & kParseValidateEncodingFlag ?
+ !Transcoder<SEncoding, TEncoding>::Validate(is, os) :
+ !Transcoder<SEncoding, TEncoding>::Transcode(is, os))
+ RAPIDJSON_PARSE_ERROR(kParseErrorStringInvalidEncoding, is.Tell());
+ }
+ }
+ }
+
+ template<typename InputStream, bool backup>
+ class NumberStream;
+
+ template<typename InputStream>
+ class NumberStream<InputStream, false> {
+ public:
+ NumberStream(GenericReader& reader, InputStream& s) : is(s) { (void)reader; }
+ ~NumberStream() {}
+
+ RAPIDJSON_FORCEINLINE Ch Peek() const { return is.Peek(); }
+ RAPIDJSON_FORCEINLINE Ch TakePush() { return is.Take(); }
+ RAPIDJSON_FORCEINLINE Ch Take() { return is.Take(); }
+ size_t Tell() { return is.Tell(); }
+ size_t Length() { return 0; }
+ const char* Pop() { return 0; }
+
+ protected:
+ NumberStream& operator=(const NumberStream&);
+
+ InputStream& is;
+ };
+
+ template<typename InputStream>
+ class NumberStream<InputStream, true> : public NumberStream<InputStream, false> {
+ typedef NumberStream<InputStream, false> Base;
+ public:
+ NumberStream(GenericReader& reader, InputStream& is) : NumberStream<InputStream, false>(reader, is), stackStream(reader.stack_) {}
+ ~NumberStream() {}
+
+ RAPIDJSON_FORCEINLINE Ch TakePush() {
+ stackStream.Put((char)Base::is.Peek());
+ return Base::is.Take();
+ }
+
+ size_t Length() { return stackStream.Length(); }
+
+ const char* Pop() {
+ stackStream.Put('\0');
+ return stackStream.Pop();
+ }
+
+ private:
+ StackStream<char> stackStream;
+ };
+
+ 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);
+
+ // Parse minus
+ bool minus = false;
+ if (s.Peek() == '-') {
+ minus = true;
+ s.Take();
+ }
+
+ // Parse int: zero / ( digit1-9 *DIGIT )
+ unsigned i = 0;
+ uint64_t i64 = 0;
+ bool use64bit = false;
+ int significandDigit = 0;
+ if (s.Peek() == '0') {
+ i = 0;
+ s.TakePush();
+ }
+ else if (s.Peek() >= '1' && s.Peek() <= '9') {
+ i = static_cast<unsigned>(s.TakePush() - '0');
+
+ if (minus)
+ while (s.Peek() >= '0' && s.Peek() <= '9') {
+ if (i >= 214748364) { // 2^31 = 2147483648
+ if (i != 214748364 || s.Peek() > '8') {
+ i64 = i;
+ use64bit = true;
+ break;
+ }
+ }
+ i = i * 10 + static_cast<unsigned>(s.TakePush() - '0');
+ significandDigit++;
+ }
+ else
+ while (s.Peek() >= '0' && s.Peek() <= '9') {
+ if (i >= 429496729) { // 2^32 - 1 = 4294967295
+ if (i != 429496729 || s.Peek() > '5') {
+ i64 = i;
+ use64bit = true;
+ break;
+ }
+ }
+ i = i * 10 + static_cast<unsigned>(s.TakePush() - '0');
+ significandDigit++;
+ }
+ }
+ else
+ RAPIDJSON_PARSE_ERROR(kParseErrorValueInvalid, s.Tell());
+
+ // Parse 64bit int
+ bool useDouble = false;
+ double d = 0.0;
+ if (use64bit) {
+ if (minus)
+ while (s.Peek() >= '0' && s.Peek() <= '9') {
+ if (i64 >= RAPIDJSON_UINT64_C2(0x0CCCCCCC, 0xCCCCCCCC)) // 2^63 = 9223372036854775808
+ if (i64 != RAPIDJSON_UINT64_C2(0x0CCCCCCC, 0xCCCCCCCC) || s.Peek() > '8') {
+ d = i64;
+ useDouble = true;
+ break;
+ }
+ i64 = i64 * 10 + static_cast<unsigned>(s.TakePush() - '0');
+ significandDigit++;
+ }
+ else
+ while (s.Peek() >= '0' && s.Peek() <= '9') {
+ if (i64 >= RAPIDJSON_UINT64_C2(0x19999999, 0x99999999)) // 2^64 - 1 = 18446744073709551615
+ if (i64 != RAPIDJSON_UINT64_C2(0x19999999, 0x99999999) || s.Peek() > '5') {
+ d = i64;
+ useDouble = true;
+ break;
+ }
+ i64 = i64 * 10 + static_cast<unsigned>(s.TakePush() - '0');
+ significandDigit++;
+ }
+ }
+
+ // Force double for big integer
+ if (useDouble) {
+ while (s.Peek() >= '0' && s.Peek() <= '9') {
+ if (d >= 1.7976931348623157e307) // DBL_MAX / 10.0
+ RAPIDJSON_PARSE_ERROR(kParseErrorNumberTooBig, s.Tell());
+ d = d * 10 + (s.TakePush() - '0');
+ }
+ }
+
+ // Parse frac = decimal-point 1*DIGIT
+ int expFrac = 0;
+ size_t decimalPosition;
+ if (s.Peek() == '.') {
+ s.Take();
+ decimalPosition = s.Length();
+
+ if (!(s.Peek() >= '0' && s.Peek() <= '9'))
+ RAPIDJSON_PARSE_ERROR(kParseErrorNumberMissFraction, s.Tell());
+
+ if (!useDouble) {
+#if RAPIDJSON_64BIT
+ // Use i64 to store significand in 64-bit architecture
+ if (!use64bit)
+ i64 = i;
+
+ while (s.Peek() >= '0' && s.Peek() <= '9') {
+ if (i64 > RAPIDJSON_UINT64_C2(0x1FFFFF, 0xFFFFFFFF)) // 2^53 - 1 for fast path
+ break;
+ else {
+ i64 = i64 * 10 + static_cast<unsigned>(s.TakePush() - '0');
+ --expFrac;
+ if (i64 != 0)
+ significandDigit++;
+ }
+ }
+
+ d = (double)i64;
+#else
+ // Use double to store significand in 32-bit architecture
+ d = use64bit ? (double)i64 : (double)i;
+#endif
+ useDouble = true;
+ }
+
+ while (s.Peek() >= '0' && s.Peek() <= '9') {
+ if (significandDigit < 17) {
+ d = d * 10.0 + (s.TakePush() - '0');
+ --expFrac;
+ if (d > 0.0)
+ significandDigit++;
+ }
+ else
+ s.TakePush();
+ }
+ }
+ else
+ decimalPosition = s.Length(); // decimal position at the end of integer.
+
+ // Parse exp = e [ minus / plus ] 1*DIGIT
+ int exp = 0;
+ if (s.Peek() == 'e' || s.Peek() == 'E') {
+ if (!useDouble) {
+ d = use64bit ? i64 : i;
+ useDouble = true;
+ }
+ s.Take();
+
+ bool expMinus = false;
+ if (s.Peek() == '+')
+ s.Take();
+ else if (s.Peek() == '-') {
+ s.Take();
+ expMinus = true;
+ }
+
+ if (s.Peek() >= '0' && s.Peek() <= '9') {
+ exp = s.Take() - '0';
+ while (s.Peek() >= '0' && s.Peek() <= '9') {
+ exp = exp * 10 + (s.Take() - '0');
+ if (exp > 308 && !expMinus) // exp > 308 should be rare, so it should be checked first.
+ RAPIDJSON_PARSE_ERROR(kParseErrorNumberTooBig, s.Tell());
+ }
+ }
+ else
+ RAPIDJSON_PARSE_ERROR(kParseErrorNumberMissExponent, s.Tell());
+
+ if (expMinus)
+ exp = -exp;
+ }
+
+ // Finish parsing, call event according to the type of number.
+ bool cont = true;
+ size_t length = s.Length();
+ const char* decimal = s.Pop(); // Pop stack no matter if it will be used or not.
+
+ if (useDouble) {
+ int p = exp + expFrac;
+ if (parseFlags & kParseFullPrecisionFlag)
+ d = internal::StrtodFullPrecision(d, p, decimal, length, decimalPosition, exp);
+ else
+ d = internal::StrtodNormalPrecision(d, p);
+
+ cont = handler.Double(minus ? -d : d);
+ }
+ else {
+ if (use64bit) {
+ if (minus)
+ cont = handler.Int64(-(int64_t)i64);
+ else
+ cont = handler.Uint64(i64);
+ }
+ else {
+ if (minus)
+ cont = handler.Int(-(int)i);
+ else
+ cont = handler.Uint(i);
+ }
+ }
+ if (!cont)
+ RAPIDJSON_PARSE_ERROR(kParseErrorTermination, s.Tell());
+ }
+
+ // Parse any JSON value
+ template<unsigned parseFlags, typename InputStream, typename Handler>
+ void ParseValue(InputStream& is, Handler& handler) {
+ switch (is.Peek()) {
+ case 'n': ParseNull <parseFlags>(is, handler); break;
+ case 't': ParseTrue <parseFlags>(is, handler); break;
+ case 'f': ParseFalse <parseFlags>(is, handler); break;
+ case '"': ParseString<parseFlags>(is, handler); break;
+ case '{': ParseObject<parseFlags>(is, handler); break;
+ case '[': ParseArray <parseFlags>(is, handler); break;
+ default : ParseNumber<parseFlags>(is, handler);
+ }
+ }
+
+ // Iterative Parsing
+
+ // States
+ enum IterativeParsingState {
+ IterativeParsingStartState = 0,
+ IterativeParsingFinishState,
+ IterativeParsingErrorState,
+
+ // Object states
+ IterativeParsingObjectInitialState,
+ IterativeParsingMemberKeyState,
+ IterativeParsingKeyValueDelimiterState,
+ IterativeParsingMemberValueState,
+ IterativeParsingMemberDelimiterState,
+ IterativeParsingObjectFinishState,
+
+ // Array states
+ IterativeParsingArrayInitialState,
+ IterativeParsingElementState,
+ IterativeParsingElementDelimiterState,
+ IterativeParsingArrayFinishState,
+
+ // Single value state
+ IterativeParsingValueState,
+
+ cIterativeParsingStateCount
+ };
+
+ // Tokens
+ enum Token {
+ LeftBracketToken = 0,
+ RightBracketToken,
+
+ LeftCurlyBracketToken,
+ RightCurlyBracketToken,
+
+ CommaToken,
+ ColonToken,
+
+ StringToken,
+ FalseToken,
+ TrueToken,
+ NullToken,
+ NumberToken,
+
+ kTokenCount
+ };
+
+ RAPIDJSON_FORCEINLINE Token Tokenize(Ch c) {
+
+//!@cond RAPIDJSON_HIDDEN_FROM_DOXYGEN
+#define N NumberToken
+#define N16 N,N,N,N,N,N,N,N,N,N,N,N,N,N,N,N
+ // Maps from ASCII to Token
+ static const unsigned char tokenMap[256] = {
+ N16, // 00~0F
+ N16, // 10~1F
+ N, N, StringToken, N, N, N, N, N, N, N, N, N, CommaToken, N, N, N, // 20~2F
+ N, N, N, N, N, N, N, N, N, N, ColonToken, N, N, N, N, N, // 30~3F
+ N16, // 40~4F
+ N, N, N, N, N, N, N, N, N, N, N, LeftBracketToken, N, RightBracketToken, N, N, // 50~5F
+ N, N, N, N, N, N, FalseToken, N, N, N, N, N, N, N, NullToken, N, // 60~6F
+ N, N, N, N, TrueToken, N, N, N, N, N, N, LeftCurlyBracketToken, N, RightCurlyBracketToken, N, N, // 70~7F
+ N16, N16, N16, N16, N16, N16, N16, N16 // 80~FF
+ };
+#undef N
+#undef N16
+//!@endcond
+
+ if (sizeof(Ch) == 1 || unsigned(c) < 256)
+ return (Token)tokenMap[(unsigned char)c];
+ else
+ return NumberToken;
+ }
+
+ RAPIDJSON_FORCEINLINE IterativeParsingState Predict(IterativeParsingState state, Token token) {
+ // current state x one lookahead token -> new state
+ static const char G[cIterativeParsingStateCount][kTokenCount] = {
+ // Start
+ {
+ IterativeParsingArrayInitialState, // Left bracket
+ IterativeParsingErrorState, // Right bracket
+ IterativeParsingObjectInitialState, // Left curly bracket
+ IterativeParsingErrorState, // Right curly bracket
+ IterativeParsingErrorState, // Comma
+ IterativeParsingErrorState, // Colon
+ IterativeParsingValueState, // String
+ IterativeParsingValueState, // False
+ IterativeParsingValueState, // True
+ IterativeParsingValueState, // Null
+ IterativeParsingValueState // Number
+ },
+ // Finish(sink state)
+ {
+ IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState,
+ IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState,
+ IterativeParsingErrorState
+ },
+ // Error(sink state)
+ {
+ IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState,
+ IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState,
+ IterativeParsingErrorState
+ },
+ // ObjectInitial
+ {
+ IterativeParsingErrorState, // Left bracket
+ IterativeParsingErrorState, // Right bracket
+ IterativeParsingErrorState, // Left curly bracket
+ IterativeParsingObjectFinishState, // Right curly bracket
+ IterativeParsingErrorState, // Comma
+ IterativeParsingErrorState, // Colon
+ IterativeParsingMemberKeyState, // String
+ IterativeParsingErrorState, // False
+ IterativeParsingErrorState, // True
+ IterativeParsingErrorState, // Null
+ IterativeParsingErrorState // Number
+ },
+ // MemberKey
+ {
+ IterativeParsingErrorState, // Left bracket
+ IterativeParsingErrorState, // Right bracket
+ IterativeParsingErrorState, // Left curly bracket
+ IterativeParsingErrorState, // Right curly bracket
+ IterativeParsingErrorState, // Comma
+ IterativeParsingKeyValueDelimiterState, // Colon
+ IterativeParsingErrorState, // String
+ IterativeParsingErrorState, // False
+ IterativeParsingErrorState, // True
+ IterativeParsingErrorState, // Null
+ IterativeParsingErrorState // Number
+ },
+ // KeyValueDelimiter
+ {
+ IterativeParsingArrayInitialState, // Left bracket(push MemberValue state)
+ IterativeParsingErrorState, // Right bracket
+ IterativeParsingObjectInitialState, // Left curly bracket(push MemberValue state)
+ IterativeParsingErrorState, // Right curly bracket
+ IterativeParsingErrorState, // Comma
+ IterativeParsingErrorState, // Colon
+ IterativeParsingMemberValueState, // String
+ IterativeParsingMemberValueState, // False
+ IterativeParsingMemberValueState, // True
+ IterativeParsingMemberValueState, // Null
+ IterativeParsingMemberValueState // Number
+ },
+ // MemberValue
+ {
+ IterativeParsingErrorState, // Left bracket
+ IterativeParsingErrorState, // Right bracket
+ IterativeParsingErrorState, // Left curly bracket
+ IterativeParsingObjectFinishState, // Right curly bracket
+ IterativeParsingMemberDelimiterState, // Comma
+ IterativeParsingErrorState, // Colon
+ IterativeParsingErrorState, // String
+ IterativeParsingErrorState, // False
+ IterativeParsingErrorState, // True
+ IterativeParsingErrorState, // Null
+ IterativeParsingErrorState // Number
+ },
+ // MemberDelimiter
+ {
+ IterativeParsingErrorState, // Left bracket
+ IterativeParsingErrorState, // Right bracket
+ IterativeParsingErrorState, // Left curly bracket
+ IterativeParsingErrorState, // Right curly bracket
+ IterativeParsingErrorState, // Comma
+ IterativeParsingErrorState, // Colon
+ IterativeParsingMemberKeyState, // String
+ IterativeParsingErrorState, // False
+ IterativeParsingErrorState, // True
+ IterativeParsingErrorState, // Null
+ IterativeParsingErrorState // Number
+ },
+ // ObjectFinish(sink state)
+ {
+ IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState,
+ IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState,
+ IterativeParsingErrorState
+ },
+ // ArrayInitial
+ {
+ IterativeParsingArrayInitialState, // Left bracket(push Element state)
+ IterativeParsingArrayFinishState, // Right bracket
+ IterativeParsingObjectInitialState, // Left curly bracket(push Element state)
+ IterativeParsingErrorState, // Right curly bracket
+ IterativeParsingErrorState, // Comma
+ IterativeParsingErrorState, // Colon
+ IterativeParsingElementState, // String
+ IterativeParsingElementState, // False
+ IterativeParsingElementState, // True
+ IterativeParsingElementState, // Null
+ IterativeParsingElementState // Number
+ },
+ // Element
+ {
+ IterativeParsingErrorState, // Left bracket
+ IterativeParsingArrayFinishState, // Right bracket
+ IterativeParsingErrorState, // Left curly bracket
+ IterativeParsingErrorState, // Right curly bracket
+ IterativeParsingElementDelimiterState, // Comma
+ IterativeParsingErrorState, // Colon
+ IterativeParsingErrorState, // String
+ IterativeParsingErrorState, // False
+ IterativeParsingErrorState, // True
+ IterativeParsingErrorState, // Null
+ IterativeParsingErrorState // Number
+ },
+ // ElementDelimiter
+ {
+ IterativeParsingArrayInitialState, // Left bracket(push Element state)
+ IterativeParsingErrorState, // Right bracket
+ IterativeParsingObjectInitialState, // Left curly bracket(push Element state)
+ IterativeParsingErrorState, // Right curly bracket
+ IterativeParsingErrorState, // Comma
+ IterativeParsingErrorState, // Colon
+ IterativeParsingElementState, // String
+ IterativeParsingElementState, // False
+ IterativeParsingElementState, // True
+ IterativeParsingElementState, // Null
+ IterativeParsingElementState // Number
+ },
+ // ArrayFinish(sink state)
+ {
+ IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState,
+ IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState,
+ IterativeParsingErrorState
+ },
+ // Single Value (sink state)
+ {
+ IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState,
+ IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState, IterativeParsingErrorState,
+ IterativeParsingErrorState
+ }
+ }; // End of G
+
+ return (IterativeParsingState)G[state][token];
+ }
+
+ // Make an advance in the token stream and state based on the candidate destination state which was returned by Transit().
+ // May return a new state on state pop.
+ template <unsigned parseFlags, typename InputStream, typename Handler>
+ RAPIDJSON_FORCEINLINE IterativeParsingState Transit(IterativeParsingState src, Token token, IterativeParsingState dst, InputStream& is, Handler& handler) {
+ (void)token;
+
+ switch (dst) {
+ case IterativeParsingErrorState:
+ return dst;
+
+ case IterativeParsingObjectInitialState:
+ case IterativeParsingArrayInitialState:
+ {
+ // Push the state(Element or MemeberValue) if we are nested in another array or value of member.
+ // In this way we can get the correct state on ObjectFinish or ArrayFinish by frame pop.
+ IterativeParsingState n = src;
+ if (src == IterativeParsingArrayInitialState || src == IterativeParsingElementDelimiterState)
+ n = IterativeParsingElementState;
+ else if (src == IterativeParsingKeyValueDelimiterState)
+ n = IterativeParsingMemberValueState;
+ // Push current state.
+ *stack_.template Push<SizeType>(1) = n;
+ // Initialize and push the member/element count.
+ *stack_.template Push<SizeType>(1) = 0;
+ // Call handler
+ bool hr = (dst == IterativeParsingObjectInitialState) ? handler.StartObject() : handler.StartArray();
+ // On handler short circuits the parsing.
+ if (!hr) {
+ RAPIDJSON_PARSE_ERROR_NORETURN(kParseErrorTermination, is.Tell());
+ return IterativeParsingErrorState;
+ }
+ else {
+ is.Take();
+ return dst;
+ }
+ }
+
+ case IterativeParsingMemberKeyState:
+ ParseString<parseFlags>(is, handler, true);
+ if (HasParseError())
+ return IterativeParsingErrorState;
+ else
+ return dst;
+
+ case IterativeParsingKeyValueDelimiterState:
+ RAPIDJSON_ASSERT(token == ColonToken);
+ is.Take();
+ return dst;
+
+ case IterativeParsingMemberValueState:
+ // Must be non-compound value. Or it would be ObjectInitial or ArrayInitial state.
+ ParseValue<parseFlags>(is, handler);
+ if (HasParseError()) {
+ return IterativeParsingErrorState;
+ }
+ return dst;
+
+ case IterativeParsingElementState:
+ // Must be non-compound value. Or it would be ObjectInitial or ArrayInitial state.
+ ParseValue<parseFlags>(is, handler);
+ if (HasParseError()) {
+ return IterativeParsingErrorState;
+ }
+ return dst;
+
+ case IterativeParsingMemberDelimiterState:
+ case IterativeParsingElementDelimiterState:
+ is.Take();
+ // Update member/element count.
+ *stack_.template Top<SizeType>() = *stack_.template Top<SizeType>() + 1;
+ return dst;
+
+ case IterativeParsingObjectFinishState:
+ {
+ // Get member count.
+ SizeType c = *stack_.template Pop<SizeType>(1);
+ // If the object is not empty, count the last member.
+ if (src == IterativeParsingMemberValueState)
+ ++c;
+ // Restore the state.
+ IterativeParsingState n = static_cast<IterativeParsingState>(*stack_.template Pop<SizeType>(1));
+ // Transit to Finish state if this is the topmost scope.
+ if (n == IterativeParsingStartState)
+ n = IterativeParsingFinishState;
+ // Call handler
+ bool hr = handler.EndObject(c);
+ // On handler short circuits the parsing.
+ if (!hr) {
+ RAPIDJSON_PARSE_ERROR_NORETURN(kParseErrorTermination, is.Tell());
+ return IterativeParsingErrorState;
+ }
+ else {
+ is.Take();
+ return n;
+ }
+ }
+
+ case IterativeParsingArrayFinishState:
+ {
+ // Get element count.
+ SizeType c = *stack_.template Pop<SizeType>(1);
+ // If the array is not empty, count the last element.
+ if (src == IterativeParsingElementState)
+ ++c;
+ // Restore the state.
+ IterativeParsingState n = static_cast<IterativeParsingState>(*stack_.template Pop<SizeType>(1));
+ // Transit to Finish state if this is the topmost scope.
+ if (n == IterativeParsingStartState)
+ n = IterativeParsingFinishState;
+ // Call handler
+ bool hr = handler.EndArray(c);
+ // On handler short circuits the parsing.
+ if (!hr) {
+ RAPIDJSON_PARSE_ERROR_NORETURN(kParseErrorTermination, is.Tell());
+ return IterativeParsingErrorState;
+ }
+ else {
+ is.Take();
+ return n;
+ }
+ }
+
+ default:
+ // This branch is for IterativeParsingValueState actually.
+ // Use `default:` rather than
+ // `case IterativeParsingValueState:` is for code coverage.
+
+ // The IterativeParsingStartState is not enumerated in this switch-case.
+ // It is impossible for that case. And it can be caught by following assertion.
+
+ // The IterativeParsingFinishState is not enumerated in this switch-case either.
+ // It is a "derivative" state which cannot triggered from Predict() directly.
+ // Therefore it cannot happen here. And it can be caught by following assertion.
+ RAPIDJSON_ASSERT(dst == IterativeParsingValueState);
+
+ // Must be non-compound value. Or it would be ObjectInitial or ArrayInitial state.
+ ParseValue<parseFlags>(is, handler);
+ if (HasParseError()) {
+ return IterativeParsingErrorState;
+ }
+ return IterativeParsingFinishState;
+ }
+ }
+
+ template <typename InputStream>
+ void HandleError(IterativeParsingState src, InputStream& is) {
+ if (HasParseError()) {
+ // Error flag has been set.
+ return;
+ }
+
+ switch (src) {
+ case IterativeParsingStartState: RAPIDJSON_PARSE_ERROR(kParseErrorDocumentEmpty, is.Tell());
+ case IterativeParsingFinishState: RAPIDJSON_PARSE_ERROR(kParseErrorDocumentRootNotSingular, is.Tell());
+ case IterativeParsingObjectInitialState:
+ case IterativeParsingMemberDelimiterState: RAPIDJSON_PARSE_ERROR(kParseErrorObjectMissName, is.Tell());
+ case IterativeParsingMemberKeyState: RAPIDJSON_PARSE_ERROR(kParseErrorObjectMissColon, is.Tell());
+ case IterativeParsingMemberValueState: RAPIDJSON_PARSE_ERROR(kParseErrorObjectMissCommaOrCurlyBracket, is.Tell());
+ case IterativeParsingElementState: RAPIDJSON_PARSE_ERROR(kParseErrorArrayMissCommaOrSquareBracket, is.Tell());
+ default: RAPIDJSON_PARSE_ERROR(kParseErrorUnspecificSyntaxError, is.Tell());
+ }
+ }
+
+ template <unsigned parseFlags, typename InputStream, typename Handler>
+ ParseResult IterativeParse(InputStream& is, Handler& handler) {
+ parseResult_.Clear();
+ ClearStackOnExit scope(*this);
+ IterativeParsingState state = IterativeParsingStartState;
+
+ SkipWhitespace(is);
+ while (is.Peek() != '\0') {
+ Token t = Tokenize(is.Peek());
+ IterativeParsingState n = Predict(state, t);
+ IterativeParsingState d = Transit<parseFlags>(state, t, n, is, handler);
+
+ if (d == IterativeParsingErrorState) {
+ HandleError(state, is);
+ break;
+ }
+
+ state = d;
+
+ // Do not further consume streams if a root JSON has been parsed.
+ if ((parseFlags & kParseStopWhenDoneFlag) && state == IterativeParsingFinishState)
+ break;
+
+ SkipWhitespace(is);
+ }
+
+ // Handle the end of file.
+ if (state != IterativeParsingFinishState)
+ HandleError(state, is);
+
+ return parseResult_;
+ }
+
+ static const size_t kDefaultStackCapacity = 256; //!< Default stack capacity in bytes for storing a single decoded string.
+ internal::Stack<StackAllocator> stack_; //!< A stack for storing decoded string temporarily during non-destructive parsing.
+ ParseResult parseResult_;
+}; // class GenericReader
+
+//! Reader with UTF8 encoding and default allocator.
+typedef GenericReader<UTF8<>, UTF8<> > Reader;
+
+RAPIDJSON_NAMESPACE_END
+
+#ifdef __GNUC__
+RAPIDJSON_DIAG_POP
+#endif
+
+#ifdef _MSC_VER
+RAPIDJSON_DIAG_POP
+#endif
+
+#endif // RAPIDJSON_READER_H_
diff --git a/libs/rapidjson/stringbuffer.h b/libs/rapidjson/include/rapidjson/stringbuffer.h
index e9be84909..1c9c80b79 100644
--- a/libs/rapidjson/stringbuffer.h
+++ b/libs/rapidjson/include/rapidjson/stringbuffer.h
@@ -1,93 +1,93 @@
-// Tencent is pleased to support the open source community by making RapidJSON available.
-//
-// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
-//
-// Licensed under the MIT License (the "License"); you may not use this file except
-// in compliance with the License. You may obtain a copy of the License at
-//
-// http://opensource.org/licenses/MIT
-//
-// Unless required by applicable law or agreed to in writing, software distributed
-// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
-// CONDITIONS OF ANY KIND, either express or implied. See the License for the
-// specific language governing permissions and limitations under the License.
-
-#ifndef RAPIDJSON_STRINGBUFFER_H_
-#define RAPIDJSON_STRINGBUFFER_H_
-
-#include "rapidjson.h"
-
-#if RAPIDJSON_HAS_CXX11_RVALUE_REFS
-#include <utility> // std::move
-#endif
-
-#include "internal/stack.h"
-
-RAPIDJSON_NAMESPACE_BEGIN
-
-//! Represents an in-memory output stream.
-/*!
- \tparam Encoding Encoding of the stream.
- \tparam Allocator type for allocating memory buffer.
- \note implements Stream concept
-*/
-template <typename Encoding, typename Allocator = CrtAllocator>
-class GenericStringBuffer {
-public:
- typedef typename Encoding::Ch Ch;
-
- GenericStringBuffer(Allocator* allocator = 0, size_t capacity = kDefaultCapacity) : stack_(allocator, capacity) {}
-
-#if RAPIDJSON_HAS_CXX11_RVALUE_REFS
- GenericStringBuffer(GenericStringBuffer&& rhs) : stack_(std::move(rhs.stack_)) {}
- GenericStringBuffer& operator=(GenericStringBuffer&& rhs) {
- if (&rhs != this)
- stack_ = std::move(rhs.stack_);
- return *this;
- }
-#endif
-
- void Put(Ch c) { *stack_.template Push<Ch>() = c; }
- void Flush() {}
-
- void Clear() { stack_.Clear(); }
- void ShrinkToFit() {
- // Push and pop a null terminator. This is safe.
- *stack_.template Push<Ch>() = '\0';
- stack_.ShrinkToFit();
- stack_.template Pop<Ch>(1);
- }
- Ch* Push(size_t count) { return stack_.template Push<Ch>(count); }
- void Pop(size_t count) { stack_.template Pop<Ch>(count); }
-
- const Ch* GetString() const {
- // Push and pop a null terminator. This is safe.
- *stack_.template Push<Ch>() = '\0';
- stack_.template Pop<Ch>(1);
-
- return stack_.template Bottom<Ch>();
- }
-
- size_t GetSize() const { return stack_.GetSize(); }
-
- static const size_t kDefaultCapacity = 256;
- mutable internal::Stack<Allocator> stack_;
-
-private:
- // Prohibit copy constructor & assignment operator.
- GenericStringBuffer(const GenericStringBuffer&);
- GenericStringBuffer& operator=(const GenericStringBuffer&);
-};
-
-//! String buffer with UTF8 encoding
-typedef GenericStringBuffer<UTF8<> > StringBuffer;
-
-//! Implement specialized version of PutN() with memset() for better performance.
-template<>
-inline void PutN(GenericStringBuffer<UTF8<> >& stream, char c, size_t n) {
- std::memset(stream.stack_.Push<char>(n), c, n * sizeof(c));
-}
-
-RAPIDJSON_NAMESPACE_END
-
-#endif // RAPIDJSON_STRINGBUFFER_H_
+// Tencent is pleased to support the open source community by making RapidJSON available.
+//
+// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
+//
+// Licensed under the MIT License (the "License"); you may not use this file except
+// in compliance with the License. You may obtain a copy of the License at
+//
+// http://opensource.org/licenses/MIT
+//
+// Unless required by applicable law or agreed to in writing, software distributed
+// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
+// CONDITIONS OF ANY KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations under the License.
+
+#ifndef RAPIDJSON_STRINGBUFFER_H_
+#define RAPIDJSON_STRINGBUFFER_H_
+
+#include "rapidjson.h"
+
+#if RAPIDJSON_HAS_CXX11_RVALUE_REFS
+#include <utility> // std::move
+#endif
+
+#include "internal/stack.h"
+
+RAPIDJSON_NAMESPACE_BEGIN
+
+//! Represents an in-memory output stream.
+/*!
+ \tparam Encoding Encoding of the stream.
+ \tparam Allocator type for allocating memory buffer.
+ \note implements Stream concept
+*/
+template <typename Encoding, typename Allocator = CrtAllocator>
+class GenericStringBuffer {
+public:
+ typedef typename Encoding::Ch Ch;
+
+ GenericStringBuffer(Allocator* allocator = 0, size_t capacity = kDefaultCapacity) : stack_(allocator, capacity) {}
+
+#if RAPIDJSON_HAS_CXX11_RVALUE_REFS
+ GenericStringBuffer(GenericStringBuffer&& rhs) : stack_(std::move(rhs.stack_)) {}
+ GenericStringBuffer& operator=(GenericStringBuffer&& rhs) {
+ if (&rhs != this)
+ stack_ = std::move(rhs.stack_);
+ return *this;
+ }
+#endif
+
+ void Put(Ch c) { *stack_.template Push<Ch>() = c; }
+ void Flush() {}
+
+ void Clear() { stack_.Clear(); }
+ void ShrinkToFit() {
+ // Push and pop a null terminator. This is safe.
+ *stack_.template Push<Ch>() = '\0';
+ stack_.ShrinkToFit();
+ stack_.template Pop<Ch>(1);
+ }
+ Ch* Push(size_t count) { return stack_.template Push<Ch>(count); }
+ void Pop(size_t count) { stack_.template Pop<Ch>(count); }
+
+ const Ch* GetString() const {
+ // Push and pop a null terminator. This is safe.
+ *stack_.template Push<Ch>() = '\0';
+ stack_.template Pop<Ch>(1);
+
+ return stack_.template Bottom<Ch>();
+ }
+
+ size_t GetSize() const { return stack_.GetSize(); }
+
+ static const size_t kDefaultCapacity = 256;
+ mutable internal::Stack<Allocator> stack_;
+
+private:
+ // Prohibit copy constructor & assignment operator.
+ GenericStringBuffer(const GenericStringBuffer&);
+ GenericStringBuffer& operator=(const GenericStringBuffer&);
+};
+
+//! String buffer with UTF8 encoding
+typedef GenericStringBuffer<UTF8<> > StringBuffer;
+
+//! Implement specialized version of PutN() with memset() for better performance.
+template<>
+inline void PutN(GenericStringBuffer<UTF8<> >& stream, char c, size_t n) {
+ std::memset(stream.stack_.Push<char>(n), c, n * sizeof(c));
+}
+
+RAPIDJSON_NAMESPACE_END
+
+#endif // RAPIDJSON_STRINGBUFFER_H_
diff --git a/libs/rapidjson/writer.h b/libs/rapidjson/include/rapidjson/writer.h
index 40cdb359f..e1eea38b9 100644
--- a/libs/rapidjson/writer.h
+++ b/libs/rapidjson/include/rapidjson/writer.h
@@ -1,395 +1,395 @@
-// Tencent is pleased to support the open source community by making RapidJSON available.
-//
-// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
-//
-// Licensed under the MIT License (the "License"); you may not use this file except
-// in compliance with the License. You may obtain a copy of the License at
-//
-// http://opensource.org/licenses/MIT
-//
-// Unless required by applicable law or agreed to in writing, software distributed
-// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
-// CONDITIONS OF ANY KIND, either express or implied. See the License for the
-// specific language governing permissions and limitations under the License.
-
-#ifndef RAPIDJSON_WRITER_H_
-#define RAPIDJSON_WRITER_H_
-
-#include "rapidjson.h"
-#include "internal/stack.h"
-#include "internal/strfunc.h"
-#include "internal/dtoa.h"
-#include "internal/itoa.h"
-#include "stringbuffer.h"
-#include <new> // placement new
-
-#if RAPIDJSON_HAS_STDSTRING
-#include <string>
-#endif
-
-#ifdef _MSC_VER
-RAPIDJSON_DIAG_PUSH
-RAPIDJSON_DIAG_OFF(4127) // conditional expression is constant
-#endif
-
-RAPIDJSON_NAMESPACE_BEGIN
-
-//! JSON writer
-/*! Writer implements the concept Handler.
- It generates JSON text by events to an output os.
-
- User may programmatically calls the functions of a writer to generate JSON text.
-
- On the other side, a writer can also be passed to objects that generates events,
-
- for example Reader::Parse() and Document::Accept().
-
- \tparam OutputStream Type of output stream.
- \tparam SourceEncoding Encoding of source string.
- \tparam TargetEncoding Encoding of output stream.
- \tparam StackAllocator Type of allocator for allocating memory of stack.
- \note implements Handler concept
-*/
-template<typename OutputStream, typename SourceEncoding = UTF8<>, typename TargetEncoding = UTF8<>, typename StackAllocator = CrtAllocator>
-class Writer {
-public:
- typedef typename SourceEncoding::Ch Ch;
-
- //! Constructor
- /*! \param os Output stream.
- \param stackAllocator User supplied allocator. If it is null, it will create a private one.
- \param levelDepth Initial capacity of stack.
- */
- explicit
- Writer(OutputStream& os, StackAllocator* stackAllocator = 0, size_t levelDepth = kDefaultLevelDepth) :
- os_(&os), level_stack_(stackAllocator, levelDepth * sizeof(Level)), hasRoot_(false) {}
-
- explicit
- Writer(StackAllocator* allocator = 0, size_t levelDepth = kDefaultLevelDepth) :
- os_(0), level_stack_(allocator, levelDepth * sizeof(Level)), hasRoot_(false) {}
-
- //! Reset the writer with a new stream.
- /*!
- This function reset the writer with a new stream and default settings,
- in order to make a Writer object reusable for output multiple JSONs.
-
- \param os New output stream.
- \code
- Writer<OutputStream> writer(os1);
- writer.StartObject();
- // ...
- writer.EndObject();
-
- writer.Reset(os2);
- writer.StartObject();
- // ...
- writer.EndObject();
- \endcode
- */
- void Reset(OutputStream& os) {
- os_ = &os;
- hasRoot_ = false;
- level_stack_.Clear();
- }
-
- //! Checks whether the output is a complete JSON.
- /*!
- A complete JSON has a complete root object or array.
- */
- bool IsComplete() const {
- return hasRoot_ && level_stack_.Empty();
- }
-
- /*!@name Implementation of Handler
- \see Handler
- */
- //@{
-
- bool Null() { Prefix(kNullType); return WriteNull(); }
- bool Bool(bool b) { Prefix(b ? kTrueType : kFalseType); return WriteBool(b); }
- bool Int(int i) { Prefix(kNumberType); return WriteInt(i); }
- bool Uint(unsigned u) { Prefix(kNumberType); return WriteUint(u); }
- bool Int64(int64_t i64) { Prefix(kNumberType); return WriteInt64(i64); }
- bool Uint64(uint64_t u64) { Prefix(kNumberType); return WriteUint64(u64); }
-
- //! Writes the given \c double value to the stream
- /*!
- \param d The value to be written.
- \return Whether it is succeed.
- */
- bool Double(double d) { Prefix(kNumberType); return WriteDouble(d); }
-
- bool String(const Ch* str, SizeType length, bool copy = false) {
- (void)copy;
- Prefix(kStringType);
- return WriteString(str, length);
- }
-
-#if RAPIDJSON_HAS_STDSTRING
- bool String(const std::basic_string<Ch>& str) {
- return String(str.data(), SizeType(str.size()));
- }
-#endif
-
- bool StartObject() {
- Prefix(kObjectType);
- new (level_stack_.template Push<Level>()) Level(false);
- return WriteStartObject();
- }
-
- bool Key(const Ch* str, SizeType length, bool copy = false) { return String(str, length, copy); }
-
- bool EndObject(SizeType memberCount = 0) {
- (void)memberCount;
- RAPIDJSON_ASSERT(level_stack_.GetSize() >= sizeof(Level));
- RAPIDJSON_ASSERT(!level_stack_.template Top<Level>()->inArray);
- level_stack_.template Pop<Level>(1);
- bool ret = WriteEndObject();
- if (level_stack_.Empty()) // end of json text
- os_->Flush();
- return ret;
- }
-
- bool StartArray() {
- Prefix(kArrayType);
- new (level_stack_.template Push<Level>()) Level(true);
- return WriteStartArray();
- }
-
- bool EndArray(SizeType elementCount = 0) {
- (void)elementCount;
- RAPIDJSON_ASSERT(level_stack_.GetSize() >= sizeof(Level));
- RAPIDJSON_ASSERT(level_stack_.template Top<Level>()->inArray);
- level_stack_.template Pop<Level>(1);
- bool ret = WriteEndArray();
- if (level_stack_.Empty()) // end of json text
- os_->Flush();
- return ret;
- }
- //@}
-
- /*! @name Convenience extensions */
- //@{
-
- //! 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)); }
-
- //@}
-
-protected:
- //! Information for each nested level
- struct Level {
- Level(bool inArray_) : valueCount(0), inArray(inArray_) {}
- size_t valueCount; //!< number of values in this level
- bool inArray; //!< true if in array, otherwise in object
- };
-
- static const size_t kDefaultLevelDepth = 32;
-
- bool WriteNull() {
- os_->Put('n'); os_->Put('u'); os_->Put('l'); os_->Put('l'); return true;
- }
-
- bool WriteBool(bool b) {
- if (b) {
- os_->Put('t'); os_->Put('r'); os_->Put('u'); os_->Put('e');
- }
- else {
- os_->Put('f'); os_->Put('a'); os_->Put('l'); os_->Put('s'); os_->Put('e');
- }
- return true;
- }
-
- bool WriteInt(int i) {
- char buffer[11];
- const char* end = internal::i32toa(i, buffer);
- for (const char* p = buffer; p != end; ++p)
- os_->Put(*p);
- return true;
- }
-
- bool WriteUint(unsigned u) {
- char buffer[10];
- const char* end = internal::u32toa(u, buffer);
- for (const char* p = buffer; p != end; ++p)
- os_->Put(*p);
- return true;
- }
-
- bool WriteInt64(int64_t i64) {
- char buffer[21];
- const char* end = internal::i64toa(i64, buffer);
- for (const char* p = buffer; p != end; ++p)
- os_->Put(*p);
- return true;
- }
-
- bool WriteUint64(uint64_t u64) {
- char buffer[20];
- char* end = internal::u64toa(u64, buffer);
- for (char* p = buffer; p != end; ++p)
- os_->Put(*p);
- return true;
- }
-
- bool WriteDouble(double d) {
- char buffer[25];
- char* end = internal::dtoa(d, buffer);
- for (char* p = buffer; p != end; ++p)
- os_->Put(*p);
- return true;
- }
-
- bool WriteString(const Ch* str, SizeType length) {
- static const char 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
- 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'b', 't', 'n', 'u', 'f', 'r', 'u', 'u', // 00
- 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', // 10
- 0, 0, '"', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 20
- Z16, Z16, // 30~4F
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,'\\', 0, 0, 0, // 50
- Z16, Z16, Z16, Z16, Z16, Z16, Z16, Z16, Z16, Z16 // 60~FF
-#undef Z16
- };
-
- os_->Put('\"');
- GenericStringStream<SourceEncoding> is(str);
- while (is.Tell() < length) {
- const Ch c = is.Peek();
- if (!TargetEncoding::supportUnicode && (unsigned)c >= 0x80) {
- // Unicode escaping
- unsigned codepoint;
- if (!SourceEncoding::Decode(is, &codepoint))
- return false;
- os_->Put('\\');
- os_->Put('u');
- if (codepoint <= 0xD7FF || (codepoint >= 0xE000 && codepoint <= 0xFFFF)) {
- os_->Put(hexDigits[(codepoint >> 12) & 15]);
- os_->Put(hexDigits[(codepoint >> 8) & 15]);
- os_->Put(hexDigits[(codepoint >> 4) & 15]);
- os_->Put(hexDigits[(codepoint ) & 15]);
- }
- else {
- RAPIDJSON_ASSERT(codepoint >= 0x010000 && codepoint <= 0x10FFFF);
- // Surrogate pair
- unsigned s = codepoint - 0x010000;
- unsigned lead = (s >> 10) + 0xD800;
- unsigned trail = (s & 0x3FF) + 0xDC00;
- os_->Put(hexDigits[(lead >> 12) & 15]);
- os_->Put(hexDigits[(lead >> 8) & 15]);
- os_->Put(hexDigits[(lead >> 4) & 15]);
- os_->Put(hexDigits[(lead ) & 15]);
- os_->Put('\\');
- os_->Put('u');
- os_->Put(hexDigits[(trail >> 12) & 15]);
- os_->Put(hexDigits[(trail >> 8) & 15]);
- os_->Put(hexDigits[(trail >> 4) & 15]);
- os_->Put(hexDigits[(trail ) & 15]);
- }
- }
- else if ((sizeof(Ch) == 1 || (unsigned)c < 256) && escape[(unsigned char)c]) {
- is.Take();
- os_->Put('\\');
- os_->Put(escape[(unsigned char)c]);
- if (escape[(unsigned char)c] == 'u') {
- os_->Put('0');
- os_->Put('0');
- os_->Put(hexDigits[(unsigned char)c >> 4]);
- os_->Put(hexDigits[(unsigned char)c & 0xF]);
- }
- }
- else
- if (!Transcoder<SourceEncoding, TargetEncoding>::Transcode(is, *os_))
- return false;
- }
- os_->Put('\"');
- return true;
- }
-
- bool WriteStartObject() { os_->Put('{'); return true; }
- bool WriteEndObject() { os_->Put('}'); return true; }
- bool WriteStartArray() { os_->Put('['); return true; }
- bool WriteEndArray() { os_->Put(']'); return true; }
-
- void Prefix(Type type) {
- (void)type;
- if (level_stack_.GetSize() != 0) { // this value is not at root
- Level* level = level_stack_.template Top<Level>();
- if (level->valueCount > 0) {
- if (level->inArray)
- os_->Put(','); // add comma if it is not the first element in array
- else // in object
- os_->Put((level->valueCount % 2 == 0) ? ',' : ':');
- }
- if (!level->inArray && level->valueCount % 2 == 0)
- RAPIDJSON_ASSERT(type == kStringType); // if it's in object, then even number should be a name
- level->valueCount++;
- }
- else {
- RAPIDJSON_ASSERT(!hasRoot_); // Should only has one and only one root.
- hasRoot_ = true;
- }
- }
-
- OutputStream* os_;
- internal::Stack<StackAllocator> level_stack_;
- bool hasRoot_;
-
-private:
- // Prohibit copy constructor & assignment operator.
- Writer(const Writer&);
- Writer& operator=(const Writer&);
-};
-
-// Full specialization for StringStream to prevent memory copying
-
-template<>
-inline bool Writer<StringBuffer>::WriteInt(int i) {
- char *buffer = os_->Push(11);
- const char* end = internal::i32toa(i, buffer);
- os_->Pop(11 - (end - buffer));
- return true;
-}
-
-template<>
-inline bool Writer<StringBuffer>::WriteUint(unsigned u) {
- char *buffer = os_->Push(10);
- const char* end = internal::u32toa(u, buffer);
- os_->Pop(10 - (end - buffer));
- return true;
-}
-
-template<>
-inline bool Writer<StringBuffer>::WriteInt64(int64_t i64) {
- char *buffer = os_->Push(21);
- const char* end = internal::i64toa(i64, buffer);
- os_->Pop(21 - (end - buffer));
- return true;
-}
-
-template<>
-inline bool Writer<StringBuffer>::WriteUint64(uint64_t u) {
- char *buffer = os_->Push(20);
- const char* end = internal::u64toa(u, buffer);
- os_->Pop(20 - (end - buffer));
- return true;
-}
-
-template<>
-inline bool Writer<StringBuffer>::WriteDouble(double d) {
- char *buffer = os_->Push(25);
- char* end = internal::dtoa(d, buffer);
- os_->Pop(25 - (end - buffer));
- return true;
-}
-
-RAPIDJSON_NAMESPACE_END
-
-#ifdef _MSC_VER
-RAPIDJSON_DIAG_POP
-#endif
-
-#endif // RAPIDJSON_RAPIDJSON_H_
+// Tencent is pleased to support the open source community by making RapidJSON available.
+//
+// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
+//
+// Licensed under the MIT License (the "License"); you may not use this file except
+// in compliance with the License. You may obtain a copy of the License at
+//
+// http://opensource.org/licenses/MIT
+//
+// Unless required by applicable law or agreed to in writing, software distributed
+// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
+// CONDITIONS OF ANY KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations under the License.
+
+#ifndef RAPIDJSON_WRITER_H_
+#define RAPIDJSON_WRITER_H_
+
+#include "rapidjson.h"
+#include "internal/stack.h"
+#include "internal/strfunc.h"
+#include "internal/dtoa.h"
+#include "internal/itoa.h"
+#include "stringbuffer.h"
+#include <new> // placement new
+
+#if RAPIDJSON_HAS_STDSTRING
+#include <string>
+#endif
+
+#ifdef _MSC_VER
+RAPIDJSON_DIAG_PUSH
+RAPIDJSON_DIAG_OFF(4127) // conditional expression is constant
+#endif
+
+RAPIDJSON_NAMESPACE_BEGIN
+
+//! JSON writer
+/*! Writer implements the concept Handler.
+ It generates JSON text by events to an output os.
+
+ User may programmatically calls the functions of a writer to generate JSON text.
+
+ On the other side, a writer can also be passed to objects that generates events,
+
+ for example Reader::Parse() and Document::Accept().
+
+ \tparam OutputStream Type of output stream.
+ \tparam SourceEncoding Encoding of source string.
+ \tparam TargetEncoding Encoding of output stream.
+ \tparam StackAllocator Type of allocator for allocating memory of stack.
+ \note implements Handler concept
+*/
+template<typename OutputStream, typename SourceEncoding = UTF8<>, typename TargetEncoding = UTF8<>, typename StackAllocator = CrtAllocator>
+class Writer {
+public:
+ typedef typename SourceEncoding::Ch Ch;
+
+ //! Constructor
+ /*! \param os Output stream.
+ \param stackAllocator User supplied allocator. If it is null, it will create a private one.
+ \param levelDepth Initial capacity of stack.
+ */
+ explicit
+ Writer(OutputStream& os, StackAllocator* stackAllocator = 0, size_t levelDepth = kDefaultLevelDepth) :
+ os_(&os), level_stack_(stackAllocator, levelDepth * sizeof(Level)), hasRoot_(false) {}
+
+ explicit
+ Writer(StackAllocator* allocator = 0, size_t levelDepth = kDefaultLevelDepth) :
+ os_(0), level_stack_(allocator, levelDepth * sizeof(Level)), hasRoot_(false) {}
+
+ //! Reset the writer with a new stream.
+ /*!
+ This function reset the writer with a new stream and default settings,
+ in order to make a Writer object reusable for output multiple JSONs.
+
+ \param os New output stream.
+ \code
+ Writer<OutputStream> writer(os1);
+ writer.StartObject();
+ // ...
+ writer.EndObject();
+
+ writer.Reset(os2);
+ writer.StartObject();
+ // ...
+ writer.EndObject();
+ \endcode
+ */
+ void Reset(OutputStream& os) {
+ os_ = &os;
+ hasRoot_ = false;
+ level_stack_.Clear();
+ }
+
+ //! Checks whether the output is a complete JSON.
+ /*!
+ A complete JSON has a complete root object or array.
+ */
+ bool IsComplete() const {
+ return hasRoot_ && level_stack_.Empty();
+ }
+
+ /*!@name Implementation of Handler
+ \see Handler
+ */
+ //@{
+
+ bool Null() { Prefix(kNullType); return WriteNull(); }
+ bool Bool(bool b) { Prefix(b ? kTrueType : kFalseType); return WriteBool(b); }
+ bool Int(int i) { Prefix(kNumberType); return WriteInt(i); }
+ bool Uint(unsigned u) { Prefix(kNumberType); return WriteUint(u); }
+ bool Int64(int64_t i64) { Prefix(kNumberType); return WriteInt64(i64); }
+ bool Uint64(uint64_t u64) { Prefix(kNumberType); return WriteUint64(u64); }
+
+ //! Writes the given \c double value to the stream
+ /*!
+ \param d The value to be written.
+ \return Whether it is succeed.
+ */
+ bool Double(double d) { Prefix(kNumberType); return WriteDouble(d); }
+
+ bool String(const Ch* str, SizeType length, bool copy = false) {
+ (void)copy;
+ Prefix(kStringType);
+ return WriteString(str, length);
+ }
+
+#if RAPIDJSON_HAS_STDSTRING
+ bool String(const std::basic_string<Ch>& str) {
+ return String(str.data(), SizeType(str.size()));
+ }
+#endif
+
+ bool StartObject() {
+ Prefix(kObjectType);
+ new (level_stack_.template Push<Level>()) Level(false);
+ return WriteStartObject();
+ }
+
+ bool Key(const Ch* str, SizeType length, bool copy = false) { return String(str, length, copy); }
+
+ bool EndObject(SizeType memberCount = 0) {
+ (void)memberCount;
+ RAPIDJSON_ASSERT(level_stack_.GetSize() >= sizeof(Level));
+ RAPIDJSON_ASSERT(!level_stack_.template Top<Level>()->inArray);
+ level_stack_.template Pop<Level>(1);
+ bool ret = WriteEndObject();
+ if (level_stack_.Empty()) // end of json text
+ os_->Flush();
+ return ret;
+ }
+
+ bool StartArray() {
+ Prefix(kArrayType);
+ new (level_stack_.template Push<Level>()) Level(true);
+ return WriteStartArray();
+ }
+
+ bool EndArray(SizeType elementCount = 0) {
+ (void)elementCount;
+ RAPIDJSON_ASSERT(level_stack_.GetSize() >= sizeof(Level));
+ RAPIDJSON_ASSERT(level_stack_.template Top<Level>()->inArray);
+ level_stack_.template Pop<Level>(1);
+ bool ret = WriteEndArray();
+ if (level_stack_.Empty()) // end of json text
+ os_->Flush();
+ return ret;
+ }
+ //@}
+
+ /*! @name Convenience extensions */
+ //@{
+
+ //! 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)); }
+
+ //@}
+
+protected:
+ //! Information for each nested level
+ struct Level {
+ Level(bool inArray_) : valueCount(0), inArray(inArray_) {}
+ size_t valueCount; //!< number of values in this level
+ bool inArray; //!< true if in array, otherwise in object
+ };
+
+ static const size_t kDefaultLevelDepth = 32;
+
+ bool WriteNull() {
+ os_->Put('n'); os_->Put('u'); os_->Put('l'); os_->Put('l'); return true;
+ }
+
+ bool WriteBool(bool b) {
+ if (b) {
+ os_->Put('t'); os_->Put('r'); os_->Put('u'); os_->Put('e');
+ }
+ else {
+ os_->Put('f'); os_->Put('a'); os_->Put('l'); os_->Put('s'); os_->Put('e');
+ }
+ return true;
+ }
+
+ bool WriteInt(int i) {
+ char buffer[11];
+ const char* end = internal::i32toa(i, buffer);
+ for (const char* p = buffer; p != end; ++p)
+ os_->Put(*p);
+ return true;
+ }
+
+ bool WriteUint(unsigned u) {
+ char buffer[10];
+ const char* end = internal::u32toa(u, buffer);
+ for (const char* p = buffer; p != end; ++p)
+ os_->Put(*p);
+ return true;
+ }
+
+ bool WriteInt64(int64_t i64) {
+ char buffer[21];
+ const char* end = internal::i64toa(i64, buffer);
+ for (const char* p = buffer; p != end; ++p)
+ os_->Put(*p);
+ return true;
+ }
+
+ bool WriteUint64(uint64_t u64) {
+ char buffer[20];
+ char* end = internal::u64toa(u64, buffer);
+ for (char* p = buffer; p != end; ++p)
+ os_->Put(*p);
+ return true;
+ }
+
+ bool WriteDouble(double d) {
+ char buffer[25];
+ char* end = internal::dtoa(d, buffer);
+ for (char* p = buffer; p != end; ++p)
+ os_->Put(*p);
+ return true;
+ }
+
+ bool WriteString(const Ch* str, SizeType length) {
+ static const char 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
+ 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'b', 't', 'n', 'u', 'f', 'r', 'u', 'u', // 00
+ 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', // 10
+ 0, 0, '"', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 20
+ Z16, Z16, // 30~4F
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,'\\', 0, 0, 0, // 50
+ Z16, Z16, Z16, Z16, Z16, Z16, Z16, Z16, Z16, Z16 // 60~FF
+#undef Z16
+ };
+
+ os_->Put('\"');
+ GenericStringStream<SourceEncoding> is(str);
+ while (is.Tell() < length) {
+ const Ch c = is.Peek();
+ if (!TargetEncoding::supportUnicode && (unsigned)c >= 0x80) {
+ // Unicode escaping
+ unsigned codepoint;
+ if (!SourceEncoding::Decode(is, &codepoint))
+ return false;
+ os_->Put('\\');
+ os_->Put('u');
+ if (codepoint <= 0xD7FF || (codepoint >= 0xE000 && codepoint <= 0xFFFF)) {
+ os_->Put(hexDigits[(codepoint >> 12) & 15]);
+ os_->Put(hexDigits[(codepoint >> 8) & 15]);
+ os_->Put(hexDigits[(codepoint >> 4) & 15]);
+ os_->Put(hexDigits[(codepoint ) & 15]);
+ }
+ else {
+ RAPIDJSON_ASSERT(codepoint >= 0x010000 && codepoint <= 0x10FFFF);
+ // Surrogate pair
+ unsigned s = codepoint - 0x010000;
+ unsigned lead = (s >> 10) + 0xD800;
+ unsigned trail = (s & 0x3FF) + 0xDC00;
+ os_->Put(hexDigits[(lead >> 12) & 15]);
+ os_->Put(hexDigits[(lead >> 8) & 15]);
+ os_->Put(hexDigits[(lead >> 4) & 15]);
+ os_->Put(hexDigits[(lead ) & 15]);
+ os_->Put('\\');
+ os_->Put('u');
+ os_->Put(hexDigits[(trail >> 12) & 15]);
+ os_->Put(hexDigits[(trail >> 8) & 15]);
+ os_->Put(hexDigits[(trail >> 4) & 15]);
+ os_->Put(hexDigits[(trail ) & 15]);
+ }
+ }
+ else if ((sizeof(Ch) == 1 || (unsigned)c < 256) && escape[(unsigned char)c]) {
+ is.Take();
+ os_->Put('\\');
+ os_->Put(escape[(unsigned char)c]);
+ if (escape[(unsigned char)c] == 'u') {
+ os_->Put('0');
+ os_->Put('0');
+ os_->Put(hexDigits[(unsigned char)c >> 4]);
+ os_->Put(hexDigits[(unsigned char)c & 0xF]);
+ }
+ }
+ else
+ if (!Transcoder<SourceEncoding, TargetEncoding>::Transcode(is, *os_))
+ return false;
+ }
+ os_->Put('\"');
+ return true;
+ }
+
+ bool WriteStartObject() { os_->Put('{'); return true; }
+ bool WriteEndObject() { os_->Put('}'); return true; }
+ bool WriteStartArray() { os_->Put('['); return true; }
+ bool WriteEndArray() { os_->Put(']'); return true; }
+
+ void Prefix(Type type) {
+ (void)type;
+ if (level_stack_.GetSize() != 0) { // this value is not at root
+ Level* level = level_stack_.template Top<Level>();
+ if (level->valueCount > 0) {
+ if (level->inArray)
+ os_->Put(','); // add comma if it is not the first element in array
+ else // in object
+ os_->Put((level->valueCount % 2 == 0) ? ',' : ':');
+ }
+ if (!level->inArray && level->valueCount % 2 == 0)
+ RAPIDJSON_ASSERT(type == kStringType); // if it's in object, then even number should be a name
+ level->valueCount++;
+ }
+ else {
+ RAPIDJSON_ASSERT(!hasRoot_); // Should only has one and only one root.
+ hasRoot_ = true;
+ }
+ }
+
+ OutputStream* os_;
+ internal::Stack<StackAllocator> level_stack_;
+ bool hasRoot_;
+
+private:
+ // Prohibit copy constructor & assignment operator.
+ Writer(const Writer&);
+ Writer& operator=(const Writer&);
+};
+
+// Full specialization for StringStream to prevent memory copying
+
+template<>
+inline bool Writer<StringBuffer>::WriteInt(int i) {
+ char *buffer = os_->Push(11);
+ const char* end = internal::i32toa(i, buffer);
+ os_->Pop(11 - (end - buffer));
+ return true;
+}
+
+template<>
+inline bool Writer<StringBuffer>::WriteUint(unsigned u) {
+ char *buffer = os_->Push(10);
+ const char* end = internal::u32toa(u, buffer);
+ os_->Pop(10 - (end - buffer));
+ return true;
+}
+
+template<>
+inline bool Writer<StringBuffer>::WriteInt64(int64_t i64) {
+ char *buffer = os_->Push(21);
+ const char* end = internal::i64toa(i64, buffer);
+ os_->Pop(21 - (end - buffer));
+ return true;
+}
+
+template<>
+inline bool Writer<StringBuffer>::WriteUint64(uint64_t u) {
+ char *buffer = os_->Push(20);
+ const char* end = internal::u64toa(u, buffer);
+ os_->Pop(20 - (end - buffer));
+ return true;
+}
+
+template<>
+inline bool Writer<StringBuffer>::WriteDouble(double d) {
+ char *buffer = os_->Push(25);
+ char* end = internal::dtoa(d, buffer);
+ os_->Pop(25 - (end - buffer));
+ return true;
+}
+
+RAPIDJSON_NAMESPACE_END
+
+#ifdef _MSC_VER
+RAPIDJSON_DIAG_POP
+#endif
+
+#endif // RAPIDJSON_RAPIDJSON_H_
diff --git a/src/communication/Listener.cpp b/src/communication/Listener.cpp
index 42217a403..ea501c9ae 100644
--- a/src/communication/Listener.cpp
+++ b/src/communication/Listener.cpp
@@ -11,7 +11,7 @@
namespace cura
{
-void Listener::stateChanged(Arcus::SocketState::SocketState)
+void Listener::stateChanged(Arcus::SocketState)
{
//Do nothing.
}
diff --git a/src/communication/Listener.h b/src/communication/Listener.h
index bd697928a..c20752356 100644
--- a/src/communication/Listener.h
+++ b/src/communication/Listener.h
@@ -20,7 +20,7 @@ public:
/*
* Changes the ``stateChanged`` signal to do nothing.
*/
- void stateChanged(Arcus::SocketState::SocketState) override;
+ void stateChanged(Arcus::SocketState) override;
/*
* Changes the ``messageReceived`` signal to do nothing.
diff --git a/src/infill/ImageBasedDensityProvider.cpp b/src/infill/ImageBasedDensityProvider.cpp
index 0917e9148..dcc13a9f4 100644
--- a/src/infill/ImageBasedDensityProvider.cpp
+++ b/src/infill/ImageBasedDensityProvider.cpp
@@ -4,7 +4,7 @@
#define STBI_FAILURE_USERMSG // enable user friendly bug messages for STB lib
#define STB_IMAGE_IMPLEMENTATION // needed in order to enable the implementation of libs/std_image.h
-#include <stb/stb_image.h>
+#include <stb_image.h>
#include "ImageBasedDensityProvider.h"
#include "SierpinskiFill.h"
diff --git a/src/raft.cpp b/src/raft.cpp
index 5bd86be47..3d9cf5a9c 100644
--- a/src/raft.cpp
+++ b/src/raft.cpp
@@ -1,7 +1,7 @@
//Copyright (c) 2022 Ultimaker B.V.
//CuraEngine is released under the terms of the AGPLv3 or higher.
-#include "clipper.hpp"
+#include <polyclipping/clipper.hpp>
#include "Application.h" //To get settings.
#include "ExtruderTrain.h"
diff --git a/src/utils/Coord_t.h b/src/utils/Coord_t.h
index 381dd1409..910efb941 100644
--- a/src/utils/Coord_t.h
+++ b/src/utils/Coord_t.h
@@ -6,7 +6,7 @@
//Include Clipper to get the ClipperLib::IntPoint definition, which we reuse as Point definition.
-#include "clipper.hpp"
+#include <polyclipping/clipper.hpp>
namespace cura
{
diff --git a/src/utils/IntPoint.h b/src/utils/IntPoint.h
index 2a7d0c818..281436c6b 100644
--- a/src/utils/IntPoint.h
+++ b/src/utils/IntPoint.h
@@ -11,7 +11,7 @@ Integer points are used to avoid floating point rounding errors, and because Cli
#define INLINE static inline
//Include Clipper to get the ClipperLib::IntPoint definition, which we reuse as Point definition.
-#include "clipper.hpp"
+#include <polyclipping/clipper.hpp>
#include <cmath>
#include <functional> // for hash function object
#include <iostream> // auto-serialization / auto-toString()
diff --git a/src/utils/polygon.h b/src/utils/polygon.h
index fbf122707..d6e0ded84 100644
--- a/src/utils/polygon.h
+++ b/src/utils/polygon.h
@@ -9,7 +9,7 @@
#include <assert.h>
#include <float.h>
#include <algorithm>
-#include "clipper.hpp"
+#include <polyclipping/clipper.hpp>
#include <algorithm> // std::reverse, fill_n array
#include <unordered_map>
diff --git a/tests/ClipperTest.cpp b/tests/ClipperTest.cpp
index 70dab767a..77e4e0d8b 100644
--- a/tests/ClipperTest.cpp
+++ b/tests/ClipperTest.cpp
@@ -3,7 +3,7 @@
#include <gtest/gtest.h>
-#include "clipper.hpp"
+#include <polyclipping/clipper.hpp>
#include <math.h>
// #define TEST_INFILL_SVG_OUTPUT
diff --git a/tests/PathOrderMonotonicTest.cpp b/tests/PathOrderMonotonicTest.cpp
index b6e53d682..b57107aea 100644
--- a/tests/PathOrderMonotonicTest.cpp
+++ b/tests/PathOrderMonotonicTest.cpp
@@ -4,7 +4,7 @@
#include <string>
#include <gtest/gtest.h>
-#include <clipper.hpp>
+#include <polyclipping/clipper.hpp>
#include "../src/infill.h"
#include "../src/utils/linearAlg2D.h"
diff --git a/tests/utils/AABB3DTest.cpp b/tests/utils/AABB3DTest.cpp
index bb1b2d0d1..5e8291398 100644
--- a/tests/utils/AABB3DTest.cpp
+++ b/tests/utils/AABB3DTest.cpp
@@ -2,7 +2,7 @@
//CuraEngine is released under the terms of the AGPLv3 or higher.
#include <gtest/gtest.h>
-#include <clipper.hpp>
+#include <polyclipping/clipper.hpp>
#include "../src/utils/AABB.h"
#include "../src/utils/AABB3D.h"
diff --git a/tests/utils/AABBTest.cpp b/tests/utils/AABBTest.cpp
index ad87b3923..4b809bf31 100644
--- a/tests/utils/AABBTest.cpp
+++ b/tests/utils/AABBTest.cpp
@@ -2,7 +2,7 @@
//CuraEngine is released under the terms of the AGPLv3 or higher.
#include <gtest/gtest.h>
-#include <clipper.hpp>
+#include <polyclipping/clipper.hpp>
#include <../src/utils/AABB.h>
#include <../src/utils/polygon.h>