From fe2c6fcb1a8bdf6e0b92eea428cadedac0b96d6a Mon Sep 17 00:00:00 2001 From: Pavel Rojtberg Date: Fri, 4 Jan 2019 22:43:39 +0100 Subject: [PATCH 1/5] add CMake based build and drop MSVC solutions --- CMakeLists.txt | 12 +++ FindOIS.cmake | 88 ++++++++++++++++++ FindPkgMacros.cmake | 165 ++++++++++++++++++++++++++++++++++ solutions/Planetscape.sln | 22 ----- solutions/Planetscape.vcxproj | 110 ----------------------- 5 files changed, 265 insertions(+), 132 deletions(-) create mode 100644 CMakeLists.txt create mode 100644 FindOIS.cmake create mode 100644 FindPkgMacros.cmake delete mode 100644 solutions/Planetscape.sln delete mode 100644 solutions/Planetscape.vcxproj diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..11ec63f --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,12 @@ +cmake_minimum_required(VERSION 3.3.0) + +project(Planetscape) + +set(CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}) + +find_package(OGRE REQUIRED) +find_package(OIS REQUIRED) + +add_executable(Planetscape src/BaseApplication.cpp src/PlanetScapeApplication.cpp) +target_include_directories(Planetscape PRIVATE src lib ${OIS_INCLUDE_DIRS}) +target_link_libraries(Planetscape PRIVATE OgreMain OgreBites ${OIS_LIBRARIES}) \ No newline at end of file diff --git a/FindOIS.cmake b/FindOIS.cmake new file mode 100644 index 0000000..7d00752 --- /dev/null +++ b/FindOIS.cmake @@ -0,0 +1,88 @@ +#------------------------------------------------------------------- +# This file is part of the CMake build system for OGRE +# (Object-oriented Graphics Rendering Engine) +# For the latest info, see http://www.ogre3d.org/ +# +# The contents of this file are placed in the public domain. Feel +# free to make use of it in any way you like. +#------------------------------------------------------------------- + +# - Try to find OIS +# Once done, this will define +# +# OIS_FOUND - system has OIS +# OIS_INCLUDE_DIRS - the OIS include directories +# OIS_LIBRARIES - link these to use OIS +# OIS_BINARY_REL / OIS_BINARY_DBG - DLL names (windows only) + +include(FindPkgMacros) +findpkg_begin(OIS) + +# Get path, convert backslashes as ${ENV_${var}} +getenv_path(OIS_HOME) +getenv_path(OGRE_SDK) +getenv_path(OGRE_HOME) +getenv_path(OGRE_SOURCE) +getenv_path(OGRE_DEPENDENCIES_DIR) + +# construct search paths +set(OIS_PREFIX_PATH ${OIS_HOME} ${ENV_OIS_HOME} + ${OGRE_DEPENDENCIES_DIR} ${ENV_OGRE_DEPENDENCIES_DIR} + ${OGRE_SOURCE}/iOSDependencies ${ENV_OGRE_SOURCE}/iOSDependencies + ${OGRE_SOURCE}/Dependencies ${ENV_OGRE_SOURCE}/Dependencies + ${OGRE_SDK} ${ENV_OGRE_SDK} + ${OGRE_HOME} ${ENV_OGRE_HOME}) +create_search_paths(OIS) +# redo search if prefix path changed +clear_if_changed(OIS_PREFIX_PATH + OIS_LIBRARY_FWK + OIS_LIBRARY_REL + OIS_LIBRARY_DBG + OIS_INCLUDE_DIR +) + +set(OIS_LIBRARY_NAMES OIS) +get_debug_names(OIS_LIBRARY_NAMES) + +use_pkgconfig(OIS_PKGC OIS) + +# For OIS, prefer static library over framework (important when referencing OIS source build) +set(CMAKE_FIND_FRAMEWORK "LAST") + +findpkg_framework(OIS) +if (OIS_HOME) + # OIS uses the 'includes' path for its headers in the source release, not 'include' + set(OIS_INC_SEARCH_PATH ${OIS_INC_SEARCH_PATH} ${OIS_HOME}/includes) +endif() +if (APPLE AND OIS_HOME) + # OIS source build on Mac stores libs in a different location + # Also this is for static build + set(OIS_LIB_SEARCH_PATH ${OIS_LIB_SEARCH_PATH} ${OIS_HOME}/Mac/XCode-2.2/build) +endif() +find_path(OIS_INCLUDE_DIR NAMES OIS.h HINTS ${OIS_INC_SEARCH_PATH} ${OIS_PKGC_INCLUDE_DIRS} PATH_SUFFIXES OIS) +find_library(OIS_LIBRARY_REL NAMES ${OIS_LIBRARY_NAMES} HINTS ${OIS_LIB_SEARCH_PATH} ${OIS_PKGC_LIBRARY_DIRS} PATH_SUFFIXES "" Release RelWithDebInfo MinSizeRel) +find_library(OIS_LIBRARY_DBG NAMES ${OIS_LIBRARY_NAMES_DBG} HINTS ${OIS_LIB_SEARCH_PATH} ${OIS_PKGC_LIBRARY_DIRS} PATH_SUFFIXES "" Debug) + +make_library_set(OIS_LIBRARY) + +if (WIN32) + set(OIS_BIN_SEARCH_PATH ${OGRE_DEPENDENCIES_DIR}/bin ${CMAKE_SOURCE_DIR}/Dependencies/bin ${OIS_HOME}/dll + ${ENV_OIS_HOME}/dll ${ENV_OGRE_DEPENDENCIES_DIR}/bin + ${OGRE_SOURCE}/Dependencies/bin ${ENV_OGRE_SOURCE}/Dependencies/bin + ${OGRE_SDK}/bin ${ENV_OGRE_SDK}/bin + ${OGRE_HOME}/bin ${ENV_OGRE_HOME}/bin) + find_file(OIS_BINARY_REL NAMES "OIS.dll" HINTS ${OIS_BIN_SEARCH_PATH} + PATH_SUFFIXES "" Release RelWithDebInfo MinSizeRel) + find_file(OIS_BINARY_DBG NAMES "OIS_d.dll" HINTS ${OIS_BIN_SEARCH_PATH} + PATH_SUFFIXES "" Debug ) +endif() +mark_as_advanced(OIS_BINARY_REL OIS_BINARY_DBG) + + +findpkg_finish(OIS) + +# add parent of OIS folder to support OIS/OIS.h +add_parent_dir(OIS_INCLUDE_DIRS OIS_INCLUDE_DIR) + +# Reset framework finding +set(CMAKE_FIND_FRAMEWORK "FIRST") diff --git a/FindPkgMacros.cmake b/FindPkgMacros.cmake new file mode 100644 index 0000000..374f84b --- /dev/null +++ b/FindPkgMacros.cmake @@ -0,0 +1,165 @@ +#------------------------------------------------------------------- +# This file is part of the CMake build system for OGRE +# (Object-oriented Graphics Rendering Engine) +# For the latest info, see http://www.ogre3d.org/ +# +# The contents of this file are placed in the public domain. Feel +# free to make use of it in any way you like. +#------------------------------------------------------------------- + +################################################################## +# Provides some common functionality for the FindPackage modules +################################################################## + +# Begin processing of package +macro(findpkg_begin PREFIX) + if (NOT ${PREFIX}_FIND_QUIETLY) + message(STATUS "Looking for ${PREFIX}...") + endif () +endmacro(findpkg_begin) + +# Display a status message unless FIND_QUIETLY is set +macro(pkg_message PREFIX) + if (NOT ${PREFIX}_FIND_QUIETLY) + message(STATUS ${ARGN}) + endif () +endmacro(pkg_message) + +# Get environment variable, define it as ENV_$var and make sure backslashes are converted to forward slashes +macro(getenv_path VAR) + set(ENV_${VAR} $ENV{${VAR}}) + # replace won't work if var is blank + if (ENV_${VAR}) + string( REGEX REPLACE "\\\\" "/" ENV_${VAR} ${ENV_${VAR}} ) + endif () +endmacro(getenv_path) + +# Construct search paths for includes and libraries from a PREFIX_PATH +macro(create_search_paths PREFIX) + foreach(dir ${${PREFIX}_PREFIX_PATH}) + set(${PREFIX}_INC_SEARCH_PATH ${${PREFIX}_INC_SEARCH_PATH} + ${dir}/include ${dir}/Include ${dir}/include/${PREFIX} ${dir}/Headers) + set(${PREFIX}_LIB_SEARCH_PATH ${${PREFIX}_LIB_SEARCH_PATH} + ${dir}/lib ${dir}/Lib ${dir}/lib/${PREFIX} ${dir}/Libs) + set(${PREFIX}_BIN_SEARCH_PATH ${${PREFIX}_BIN_SEARCH_PATH} + ${dir}/bin) + endforeach(dir) + if(ANDROID) + set(${PREFIX}_LIB_SEARCH_PATH ${${PREFIX}_LIB_SEARCH_PATH} ${OGRE_DEPENDENCIES_DIR}/lib/${ANDROID_ABI}) + endif() + set(${PREFIX}_FRAMEWORK_SEARCH_PATH ${${PREFIX}_PREFIX_PATH}) +endmacro(create_search_paths) + +# clear cache variables if a certain variable changed +macro(clear_if_changed TESTVAR) + # test against internal check variable + # HACK: Apparently, adding a variable to the cache cleans up the list + # a bit. We need to also remove any empty strings from the list, but + # at the same time ensure that we are actually dealing with a list. + list(APPEND ${TESTVAR} "") + list(REMOVE_ITEM ${TESTVAR} "") + if (NOT "${${TESTVAR}}" STREQUAL "${${TESTVAR}_INT_CHECK}") + message(STATUS "${TESTVAR} changed.") + foreach(var ${ARGN}) + set(${var} "NOTFOUND" CACHE STRING "x" FORCE) + endforeach(var) + endif () + set(${TESTVAR}_INT_CHECK ${${TESTVAR}} CACHE INTERNAL "x" FORCE) +endmacro(clear_if_changed) + +# Try to get some hints from pkg-config, if available +macro(use_pkgconfig PREFIX PKGNAME) + if(NOT ANDROID) + find_package(PkgConfig) + if (PKG_CONFIG_FOUND) + pkg_check_modules(${PREFIX} ${PKGNAME}) + endif () + endif() +endmacro (use_pkgconfig) + +# Couple a set of release AND debug libraries (or frameworks) +macro(make_library_set PREFIX) + if (${PREFIX}_FWK) + set(${PREFIX} ${${PREFIX}_FWK}) + elseif (${PREFIX}_REL AND ${PREFIX}_DBG) + set(${PREFIX} optimized ${${PREFIX}_REL} debug ${${PREFIX}_DBG}) + elseif (${PREFIX}_REL) + set(${PREFIX} ${${PREFIX}_REL}) + elseif (${PREFIX}_DBG) + set(${PREFIX} ${${PREFIX}_DBG}) + endif () +endmacro(make_library_set) + +# Generate debug names from given release names +macro(get_debug_names PREFIX) + foreach(i ${${PREFIX}}) + set(${PREFIX}_DBG ${${PREFIX}_DBG} ${i}d ${i}D ${i}_d ${i}_D ${i}_debug) + endforeach(i) +endmacro(get_debug_names) + +# Add the parent dir from DIR to VAR +macro(add_parent_dir VAR DIR) + get_filename_component(${DIR}_TEMP "${${DIR}}/.." ABSOLUTE) + set(${VAR} ${${VAR}} ${${DIR}_TEMP}) +endmacro(add_parent_dir) + +# Do the final processing for the package find. +macro(findpkg_finish PREFIX) + # skip if already processed during this run + if (NOT ${PREFIX}_FOUND) + if (${PREFIX}_INCLUDE_DIR AND ${PREFIX}_LIBRARY) + set(${PREFIX}_FOUND TRUE) + set(${PREFIX}_INCLUDE_DIRS ${${PREFIX}_INCLUDE_DIR}) + set(${PREFIX}_LIBRARIES ${${PREFIX}_LIBRARY}) + if (NOT ${PREFIX}_FIND_QUIETLY) + message(STATUS "Found ${PREFIX}: ${${PREFIX}_LIBRARIES}") + endif () + else () + if (NOT ${PREFIX}_FIND_QUIETLY) + message(STATUS "Could not locate ${PREFIX}") + endif () + if (${PREFIX}_FIND_REQUIRED) + message(FATAL_ERROR "Required library ${PREFIX} not found! Install the library (including dev packages) and try again. If the library is already installed, set the missing variables manually in cmake.") + endif () + endif () + + mark_as_advanced(${PREFIX}_INCLUDE_DIR ${PREFIX}_LIBRARY ${PREFIX}_LIBRARY_REL ${PREFIX}_LIBRARY_DBG ${PREFIX}_LIBRARY_FWK) + endif () +endmacro(findpkg_finish) + + +# Slightly customised framework finder +macro(findpkg_framework fwk) + if(APPLE) + set(${fwk}_FRAMEWORK_PATH + ${${fwk}_FRAMEWORK_SEARCH_PATH} + ${CMAKE_FRAMEWORK_PATH} + ~/Library/Frameworks + /Library/Frameworks + /System/Library/Frameworks + /Network/Library/Frameworks + ${CMAKE_CURRENT_SOURCE_DIR}/lib/macosx/Release + ${CMAKE_CURRENT_SOURCE_DIR}/lib/macosx/Debug + ) + # These could be arrays of paths, add each individually to the search paths + foreach(i ${OGRE_PREFIX_PATH}) + set(${fwk}_FRAMEWORK_PATH ${${fwk}_FRAMEWORK_PATH} ${i}/lib/macosx/Release ${i}/lib/macosx/Debug) + endforeach(i) + + foreach(i ${OGRE_PREFIX_BUILD}) + set(${fwk}_FRAMEWORK_PATH ${${fwk}_FRAMEWORK_PATH} ${i}/lib/macosx/Release ${i}/lib/macosx/Debug) + endforeach(i) + + foreach(dir ${${fwk}_FRAMEWORK_PATH}) + set(fwkpath ${dir}/${fwk}.framework) + if(EXISTS ${fwkpath}) + set(${fwk}_FRAMEWORK_INCLUDES ${${fwk}_FRAMEWORK_INCLUDES} + ${fwkpath}/Headers ${fwkpath}/PrivateHeaders) + set(${fwk}_FRAMEWORK_PATH ${dir}) + if (NOT ${fwk}_LIBRARY_FWK) + set(${fwk}_LIBRARY_FWK "-framework ${fwk}") + endif () + endif(EXISTS ${fwkpath}) + endforeach(dir) + endif(APPLE) +endmacro(findpkg_framework) diff --git a/solutions/Planetscape.sln b/solutions/Planetscape.sln deleted file mode 100644 index 3edbb13..0000000 --- a/solutions/Planetscape.sln +++ /dev/null @@ -1,22 +0,0 @@ - -Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 2013 -VisualStudioVersion = 12.0.31101.0 -MinimumVisualStudioVersion = 10.0.40219.1 -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Planetscape", "Planetscape.vcxproj", "{7BE1968A-4C19-4A58-A6C8-E02FFE4D1535}" -EndProject -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|Win32 = Debug|Win32 - Release|Win32 = Release|Win32 - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {7BE1968A-4C19-4A58-A6C8-E02FFE4D1535}.Debug|Win32.ActiveCfg = Debug|Win32 - {7BE1968A-4C19-4A58-A6C8-E02FFE4D1535}.Debug|Win32.Build.0 = Debug|Win32 - {7BE1968A-4C19-4A58-A6C8-E02FFE4D1535}.Release|Win32.ActiveCfg = Release|Win32 - {7BE1968A-4C19-4A58-A6C8-E02FFE4D1535}.Release|Win32.Build.0 = Release|Win32 - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection -EndGlobal diff --git a/solutions/Planetscape.vcxproj b/solutions/Planetscape.vcxproj deleted file mode 100644 index a0fda3e..0000000 --- a/solutions/Planetscape.vcxproj +++ /dev/null @@ -1,110 +0,0 @@ - - - - - Debug - Win32 - - - Release - Win32 - - - - {7BE1968A-4C19-4A58-A6C8-E02FFE4D1535} - Win32Proj - Planetscape - - - - Application - true - v120 - MultiByte - - - Application - false - v120 - true - MultiByte - - - - - - - - - - - - - true - - - false - - - - - - Level3 - Disabled - WIN32;_DEBUG;_WINDOWS;%(PreprocessorDefinitions) - $(OGRE_HOME)\Build\include;$(OGRE_HOME)\OgreMain\include;$(OGRE_HOME)\..\1.9.0-win-deps\include\OIS;$(OGRE_HOME)\..\1.9.0-win-deps\include\;$(OGRE_HOME)\Samples\Common\include;F:\Ogre\Builds\1_9_1_SDK\boost;$(OGRE_HOME)\Components\Overlay\include;../lib - - - Windows - true - $(OGRE_HOME)\Build\lib\$(Configuration);F:\Ogre\Builds\1_9_1_SDK\boost\lib;$(OGRE_HOME)\..\1.9.0-win-deps\lib\$(Configuration);%(AdditionalLibraryDirectories) - OgreMain_d.lib;OgreOverlay_d.lib;OIS_d.lib;%(AdditionalDependencies) - - - copy "$(OutDir)$(TargetFileName)" "$(OGRE_HOME)Build\Bin\$(Configuration)" - - - - - Level3 - - - MaxSpeed - true - true - WIN32;NDEBUG;_WINDOWS;%(PreprocessorDefinitions) - $(OGRE_HOME)\Build\include;$(OGRE_HOME)\OgreMain\include;$(OGRE_HOME)\..\1.9.0-win-deps\include\OIS;$(OGRE_HOME)\..\1.9.0-win-deps\include\;$(OGRE_HOME)\Samples\Common\include;F:\Ogre\Builds\1_9_1_SDK\boost;$(OGRE_HOME)\Components\Overlay\include;../lib - - - Windows - true - true - true - $(OGRE_HOME)\Build\lib\$(Configuration);F:\Ogre\Builds\1_9_1_SDK\boost\lib;$(OGRE_HOME)\..\1.9.0-win-deps\lib\$(Configuration);%(AdditionalLibraryDirectories) - OgreMain.lib;OgreOverlay.lib;OIS.lib;%(AdditionalDependencies) - - - copy "$(OutDir)$(TargetFileName)" "$(OGRE_HOME)Build\Bin\$(Configuration)" - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file From 6d209dfb940b7a4df3ee845b226e4484b3f9d1c8 Mon Sep 17 00:00:00 2001 From: Pavel Rojtberg Date: Fri, 4 Jan 2019 22:45:00 +0100 Subject: [PATCH 2/5] fix build with gcc --- CMakeLists.txt | 2 +- src/PlanetScapeApplication.cpp | 5 +++-- src/PlanetScapeApplication.h | 4 ++-- 3 files changed, 6 insertions(+), 5 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 11ec63f..75761ed 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -4,7 +4,7 @@ project(Planetscape) set(CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}) -find_package(OGRE REQUIRED) +find_package(OGRE 1.10 REQUIRED) find_package(OIS REQUIRED) add_executable(Planetscape src/BaseApplication.cpp src/PlanetScapeApplication.cpp) diff --git a/src/PlanetScapeApplication.cpp b/src/PlanetScapeApplication.cpp index 47c7eba..6f4c0ed 100644 --- a/src/PlanetScapeApplication.cpp +++ b/src/PlanetScapeApplication.cpp @@ -28,6 +28,7 @@ Tutorial Framework (for Ogre 1.9) #include #include #include +#include using namespace Ogre; @@ -215,7 +216,7 @@ void PlanetScapeApplication::reloadPlanetJson() data->close(); } -int PlanetScapeApplication::GetNoiseTypeFromString(std::string &val) +int PlanetScapeApplication::GetNoiseTypeFromString(const std::string &val) { int type = 0; @@ -236,7 +237,7 @@ int PlanetScapeApplication::GetNoiseTypeFromString(std::string &val) } } -int PlanetScapeApplication::GetBlendTypeFromString(std::string &val) +int PlanetScapeApplication::GetBlendTypeFromString(const std::string &val) { int type = 0; diff --git a/src/PlanetScapeApplication.h b/src/PlanetScapeApplication.h index c00aa7e..6f57f13 100644 --- a/src/PlanetScapeApplication.h +++ b/src/PlanetScapeApplication.h @@ -56,8 +56,8 @@ class PlanetScapeApplication : public BaseApplication void SetColorTableParamsFromJson(Ogre::GpuProgramParametersSharedPtr params); void SetWaterParamsFromJson(Ogre::GpuProgramParametersSharedPtr params); - int GetNoiseTypeFromString(std::string &val); - int GetBlendTypeFromString(std::string &val); + int GetNoiseTypeFromString(const std::string &val); + int GetBlendTypeFromString(const std::string &val); std::thread mThread; bool mShouldReload; From e3652dcff7e07c3a772f319df28422c8cbc37367 Mon Sep 17 00:00:00 2001 From: Pavel Rojtberg Date: Fri, 4 Jan 2019 23:35:45 +0100 Subject: [PATCH 3/5] port to ApplicationContext --- CMakeLists.txt | 9 +- FindOIS.cmake | 88 ------- FindPkgMacros.cmake | 165 ------------ src/BaseApplication.cpp | 458 --------------------------------- src/BaseApplication.h | 139 ---------- src/PlanetScapeApplication.cpp | 59 +++-- src/PlanetScapeApplication.h | 13 +- 7 files changed, 51 insertions(+), 880 deletions(-) delete mode 100644 FindOIS.cmake delete mode 100644 FindPkgMacros.cmake delete mode 100644 src/BaseApplication.cpp delete mode 100644 src/BaseApplication.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 75761ed..72d8d7c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -2,11 +2,8 @@ cmake_minimum_required(VERSION 3.3.0) project(Planetscape) -set(CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}) - find_package(OGRE 1.10 REQUIRED) -find_package(OIS REQUIRED) -add_executable(Planetscape src/BaseApplication.cpp src/PlanetScapeApplication.cpp) -target_include_directories(Planetscape PRIVATE src lib ${OIS_INCLUDE_DIRS}) -target_link_libraries(Planetscape PRIVATE OgreMain OgreBites ${OIS_LIBRARIES}) \ No newline at end of file +add_executable(Planetscape src/PlanetScapeApplication.cpp) +target_include_directories(Planetscape PRIVATE src lib) +target_link_libraries(Planetscape PRIVATE OgreMain OgreBites) \ No newline at end of file diff --git a/FindOIS.cmake b/FindOIS.cmake deleted file mode 100644 index 7d00752..0000000 --- a/FindOIS.cmake +++ /dev/null @@ -1,88 +0,0 @@ -#------------------------------------------------------------------- -# This file is part of the CMake build system for OGRE -# (Object-oriented Graphics Rendering Engine) -# For the latest info, see http://www.ogre3d.org/ -# -# The contents of this file are placed in the public domain. Feel -# free to make use of it in any way you like. -#------------------------------------------------------------------- - -# - Try to find OIS -# Once done, this will define -# -# OIS_FOUND - system has OIS -# OIS_INCLUDE_DIRS - the OIS include directories -# OIS_LIBRARIES - link these to use OIS -# OIS_BINARY_REL / OIS_BINARY_DBG - DLL names (windows only) - -include(FindPkgMacros) -findpkg_begin(OIS) - -# Get path, convert backslashes as ${ENV_${var}} -getenv_path(OIS_HOME) -getenv_path(OGRE_SDK) -getenv_path(OGRE_HOME) -getenv_path(OGRE_SOURCE) -getenv_path(OGRE_DEPENDENCIES_DIR) - -# construct search paths -set(OIS_PREFIX_PATH ${OIS_HOME} ${ENV_OIS_HOME} - ${OGRE_DEPENDENCIES_DIR} ${ENV_OGRE_DEPENDENCIES_DIR} - ${OGRE_SOURCE}/iOSDependencies ${ENV_OGRE_SOURCE}/iOSDependencies - ${OGRE_SOURCE}/Dependencies ${ENV_OGRE_SOURCE}/Dependencies - ${OGRE_SDK} ${ENV_OGRE_SDK} - ${OGRE_HOME} ${ENV_OGRE_HOME}) -create_search_paths(OIS) -# redo search if prefix path changed -clear_if_changed(OIS_PREFIX_PATH - OIS_LIBRARY_FWK - OIS_LIBRARY_REL - OIS_LIBRARY_DBG - OIS_INCLUDE_DIR -) - -set(OIS_LIBRARY_NAMES OIS) -get_debug_names(OIS_LIBRARY_NAMES) - -use_pkgconfig(OIS_PKGC OIS) - -# For OIS, prefer static library over framework (important when referencing OIS source build) -set(CMAKE_FIND_FRAMEWORK "LAST") - -findpkg_framework(OIS) -if (OIS_HOME) - # OIS uses the 'includes' path for its headers in the source release, not 'include' - set(OIS_INC_SEARCH_PATH ${OIS_INC_SEARCH_PATH} ${OIS_HOME}/includes) -endif() -if (APPLE AND OIS_HOME) - # OIS source build on Mac stores libs in a different location - # Also this is for static build - set(OIS_LIB_SEARCH_PATH ${OIS_LIB_SEARCH_PATH} ${OIS_HOME}/Mac/XCode-2.2/build) -endif() -find_path(OIS_INCLUDE_DIR NAMES OIS.h HINTS ${OIS_INC_SEARCH_PATH} ${OIS_PKGC_INCLUDE_DIRS} PATH_SUFFIXES OIS) -find_library(OIS_LIBRARY_REL NAMES ${OIS_LIBRARY_NAMES} HINTS ${OIS_LIB_SEARCH_PATH} ${OIS_PKGC_LIBRARY_DIRS} PATH_SUFFIXES "" Release RelWithDebInfo MinSizeRel) -find_library(OIS_LIBRARY_DBG NAMES ${OIS_LIBRARY_NAMES_DBG} HINTS ${OIS_LIB_SEARCH_PATH} ${OIS_PKGC_LIBRARY_DIRS} PATH_SUFFIXES "" Debug) - -make_library_set(OIS_LIBRARY) - -if (WIN32) - set(OIS_BIN_SEARCH_PATH ${OGRE_DEPENDENCIES_DIR}/bin ${CMAKE_SOURCE_DIR}/Dependencies/bin ${OIS_HOME}/dll - ${ENV_OIS_HOME}/dll ${ENV_OGRE_DEPENDENCIES_DIR}/bin - ${OGRE_SOURCE}/Dependencies/bin ${ENV_OGRE_SOURCE}/Dependencies/bin - ${OGRE_SDK}/bin ${ENV_OGRE_SDK}/bin - ${OGRE_HOME}/bin ${ENV_OGRE_HOME}/bin) - find_file(OIS_BINARY_REL NAMES "OIS.dll" HINTS ${OIS_BIN_SEARCH_PATH} - PATH_SUFFIXES "" Release RelWithDebInfo MinSizeRel) - find_file(OIS_BINARY_DBG NAMES "OIS_d.dll" HINTS ${OIS_BIN_SEARCH_PATH} - PATH_SUFFIXES "" Debug ) -endif() -mark_as_advanced(OIS_BINARY_REL OIS_BINARY_DBG) - - -findpkg_finish(OIS) - -# add parent of OIS folder to support OIS/OIS.h -add_parent_dir(OIS_INCLUDE_DIRS OIS_INCLUDE_DIR) - -# Reset framework finding -set(CMAKE_FIND_FRAMEWORK "FIRST") diff --git a/FindPkgMacros.cmake b/FindPkgMacros.cmake deleted file mode 100644 index 374f84b..0000000 --- a/FindPkgMacros.cmake +++ /dev/null @@ -1,165 +0,0 @@ -#------------------------------------------------------------------- -# This file is part of the CMake build system for OGRE -# (Object-oriented Graphics Rendering Engine) -# For the latest info, see http://www.ogre3d.org/ -# -# The contents of this file are placed in the public domain. Feel -# free to make use of it in any way you like. -#------------------------------------------------------------------- - -################################################################## -# Provides some common functionality for the FindPackage modules -################################################################## - -# Begin processing of package -macro(findpkg_begin PREFIX) - if (NOT ${PREFIX}_FIND_QUIETLY) - message(STATUS "Looking for ${PREFIX}...") - endif () -endmacro(findpkg_begin) - -# Display a status message unless FIND_QUIETLY is set -macro(pkg_message PREFIX) - if (NOT ${PREFIX}_FIND_QUIETLY) - message(STATUS ${ARGN}) - endif () -endmacro(pkg_message) - -# Get environment variable, define it as ENV_$var and make sure backslashes are converted to forward slashes -macro(getenv_path VAR) - set(ENV_${VAR} $ENV{${VAR}}) - # replace won't work if var is blank - if (ENV_${VAR}) - string( REGEX REPLACE "\\\\" "/" ENV_${VAR} ${ENV_${VAR}} ) - endif () -endmacro(getenv_path) - -# Construct search paths for includes and libraries from a PREFIX_PATH -macro(create_search_paths PREFIX) - foreach(dir ${${PREFIX}_PREFIX_PATH}) - set(${PREFIX}_INC_SEARCH_PATH ${${PREFIX}_INC_SEARCH_PATH} - ${dir}/include ${dir}/Include ${dir}/include/${PREFIX} ${dir}/Headers) - set(${PREFIX}_LIB_SEARCH_PATH ${${PREFIX}_LIB_SEARCH_PATH} - ${dir}/lib ${dir}/Lib ${dir}/lib/${PREFIX} ${dir}/Libs) - set(${PREFIX}_BIN_SEARCH_PATH ${${PREFIX}_BIN_SEARCH_PATH} - ${dir}/bin) - endforeach(dir) - if(ANDROID) - set(${PREFIX}_LIB_SEARCH_PATH ${${PREFIX}_LIB_SEARCH_PATH} ${OGRE_DEPENDENCIES_DIR}/lib/${ANDROID_ABI}) - endif() - set(${PREFIX}_FRAMEWORK_SEARCH_PATH ${${PREFIX}_PREFIX_PATH}) -endmacro(create_search_paths) - -# clear cache variables if a certain variable changed -macro(clear_if_changed TESTVAR) - # test against internal check variable - # HACK: Apparently, adding a variable to the cache cleans up the list - # a bit. We need to also remove any empty strings from the list, but - # at the same time ensure that we are actually dealing with a list. - list(APPEND ${TESTVAR} "") - list(REMOVE_ITEM ${TESTVAR} "") - if (NOT "${${TESTVAR}}" STREQUAL "${${TESTVAR}_INT_CHECK}") - message(STATUS "${TESTVAR} changed.") - foreach(var ${ARGN}) - set(${var} "NOTFOUND" CACHE STRING "x" FORCE) - endforeach(var) - endif () - set(${TESTVAR}_INT_CHECK ${${TESTVAR}} CACHE INTERNAL "x" FORCE) -endmacro(clear_if_changed) - -# Try to get some hints from pkg-config, if available -macro(use_pkgconfig PREFIX PKGNAME) - if(NOT ANDROID) - find_package(PkgConfig) - if (PKG_CONFIG_FOUND) - pkg_check_modules(${PREFIX} ${PKGNAME}) - endif () - endif() -endmacro (use_pkgconfig) - -# Couple a set of release AND debug libraries (or frameworks) -macro(make_library_set PREFIX) - if (${PREFIX}_FWK) - set(${PREFIX} ${${PREFIX}_FWK}) - elseif (${PREFIX}_REL AND ${PREFIX}_DBG) - set(${PREFIX} optimized ${${PREFIX}_REL} debug ${${PREFIX}_DBG}) - elseif (${PREFIX}_REL) - set(${PREFIX} ${${PREFIX}_REL}) - elseif (${PREFIX}_DBG) - set(${PREFIX} ${${PREFIX}_DBG}) - endif () -endmacro(make_library_set) - -# Generate debug names from given release names -macro(get_debug_names PREFIX) - foreach(i ${${PREFIX}}) - set(${PREFIX}_DBG ${${PREFIX}_DBG} ${i}d ${i}D ${i}_d ${i}_D ${i}_debug) - endforeach(i) -endmacro(get_debug_names) - -# Add the parent dir from DIR to VAR -macro(add_parent_dir VAR DIR) - get_filename_component(${DIR}_TEMP "${${DIR}}/.." ABSOLUTE) - set(${VAR} ${${VAR}} ${${DIR}_TEMP}) -endmacro(add_parent_dir) - -# Do the final processing for the package find. -macro(findpkg_finish PREFIX) - # skip if already processed during this run - if (NOT ${PREFIX}_FOUND) - if (${PREFIX}_INCLUDE_DIR AND ${PREFIX}_LIBRARY) - set(${PREFIX}_FOUND TRUE) - set(${PREFIX}_INCLUDE_DIRS ${${PREFIX}_INCLUDE_DIR}) - set(${PREFIX}_LIBRARIES ${${PREFIX}_LIBRARY}) - if (NOT ${PREFIX}_FIND_QUIETLY) - message(STATUS "Found ${PREFIX}: ${${PREFIX}_LIBRARIES}") - endif () - else () - if (NOT ${PREFIX}_FIND_QUIETLY) - message(STATUS "Could not locate ${PREFIX}") - endif () - if (${PREFIX}_FIND_REQUIRED) - message(FATAL_ERROR "Required library ${PREFIX} not found! Install the library (including dev packages) and try again. If the library is already installed, set the missing variables manually in cmake.") - endif () - endif () - - mark_as_advanced(${PREFIX}_INCLUDE_DIR ${PREFIX}_LIBRARY ${PREFIX}_LIBRARY_REL ${PREFIX}_LIBRARY_DBG ${PREFIX}_LIBRARY_FWK) - endif () -endmacro(findpkg_finish) - - -# Slightly customised framework finder -macro(findpkg_framework fwk) - if(APPLE) - set(${fwk}_FRAMEWORK_PATH - ${${fwk}_FRAMEWORK_SEARCH_PATH} - ${CMAKE_FRAMEWORK_PATH} - ~/Library/Frameworks - /Library/Frameworks - /System/Library/Frameworks - /Network/Library/Frameworks - ${CMAKE_CURRENT_SOURCE_DIR}/lib/macosx/Release - ${CMAKE_CURRENT_SOURCE_DIR}/lib/macosx/Debug - ) - # These could be arrays of paths, add each individually to the search paths - foreach(i ${OGRE_PREFIX_PATH}) - set(${fwk}_FRAMEWORK_PATH ${${fwk}_FRAMEWORK_PATH} ${i}/lib/macosx/Release ${i}/lib/macosx/Debug) - endforeach(i) - - foreach(i ${OGRE_PREFIX_BUILD}) - set(${fwk}_FRAMEWORK_PATH ${${fwk}_FRAMEWORK_PATH} ${i}/lib/macosx/Release ${i}/lib/macosx/Debug) - endforeach(i) - - foreach(dir ${${fwk}_FRAMEWORK_PATH}) - set(fwkpath ${dir}/${fwk}.framework) - if(EXISTS ${fwkpath}) - set(${fwk}_FRAMEWORK_INCLUDES ${${fwk}_FRAMEWORK_INCLUDES} - ${fwkpath}/Headers ${fwkpath}/PrivateHeaders) - set(${fwk}_FRAMEWORK_PATH ${dir}) - if (NOT ${fwk}_LIBRARY_FWK) - set(${fwk}_LIBRARY_FWK "-framework ${fwk}") - endif () - endif(EXISTS ${fwkpath}) - endforeach(dir) - endif(APPLE) -endmacro(findpkg_framework) diff --git a/src/BaseApplication.cpp b/src/BaseApplication.cpp deleted file mode 100644 index 977bf62..0000000 --- a/src/BaseApplication.cpp +++ /dev/null @@ -1,458 +0,0 @@ -/* ------------------------------------------------------------------------------ -Filename: BaseApplication.cpp ------------------------------------------------------------------------------ - -This source file is part of the - ___ __ __ _ _ _ - /___\__ _ _ __ ___ / / /\ \ (_) | _(_) - // // _` | '__/ _ \ \ \/ \/ / | |/ / | -/ \_// (_| | | | __/ \ /\ /| | <| | -\___/ \__, |_| \___| \/ \/ |_|_|\_\_| - |___/ -Tutorial Framework (for Ogre 1.9) -http://www.ogre3d.org/wiki/ ------------------------------------------------------------------------------ -*/ - -#include "BaseApplication.h" -#include -#include - -#if OGRE_PLATFORM == OGRE_PLATFORM_APPLE -#include -#endif - -//--------------------------------------------------------------------------- -BaseApplication::BaseApplication(void) - : mRoot(0), - mCamera(0), - mSceneMgr(0), - mWindow(0), - mResourcesCfg(Ogre::BLANKSTRING), - mPluginsCfg(Ogre::BLANKSTRING), - mTrayMgr(0), - mCameraMan(0), - mDetailsPanel(0), - mCursorWasVisible(false), - mShutDown(false), - mInputManager(0), - mMouse(0), - mKeyboard(0), - mOverlaySystem(0) -{ -#if OGRE_PLATFORM == OGRE_PLATFORM_APPLE - m_ResourcePath = Ogre::macBundlePath() + "/Contents/Resources/"; -#else - m_ResourcePath = ""; -#endif -} - -//--------------------------------------------------------------------------- -BaseApplication::~BaseApplication(void) -{ - if (mTrayMgr) delete mTrayMgr; - if (mCameraMan) delete mCameraMan; - if (mOverlaySystem) delete mOverlaySystem; - - // Remove ourself as a Window listener - Ogre::WindowEventUtilities::removeWindowEventListener(mWindow, this); - windowClosed(mWindow); - delete mRoot; -} - -//--------------------------------------------------------------------------- -bool BaseApplication::configure(void) -{ - // Show the configuration dialog and initialise the system. - // You can skip this and use root.restoreConfig() to load configuration - // settings if you were sure there are valid ones saved in ogre.cfg. - if(mRoot->showConfigDialog()) - { - // If returned true, user clicked OK so initialise. - // Here we choose to let the system create a default rendering window by passing 'true'. - mWindow = mRoot->initialise(true, "PlanetScapeApplication Render Window"); - - return true; - } - else - { - return false; - } -} -//--------------------------------------------------------------------------- -void BaseApplication::chooseSceneManager(void) -{ - // Get the SceneManager, in this case a generic one - mSceneMgr = mRoot->createSceneManager(Ogre::ST_GENERIC); - - // Initialize the OverlaySystem (changed for Ogre 1.9) - mOverlaySystem = new Ogre::OverlaySystem(); - mSceneMgr->addRenderQueueListener(mOverlaySystem); -} -//--------------------------------------------------------------------------- -void BaseApplication::createCamera(void) -{ - // Create the camera - mCamera = mSceneMgr->createCamera("PlayerCam"); - - // Position it at 500 in Z direction - mCamera->setPosition(Ogre::Vector3(0,0,80)); - // Look back along -Z - mCamera->lookAt(Ogre::Vector3(0,0,-300)); - mCamera->setNearClipDistance(5); - - mCameraMan = new OgreBites::SdkCameraMan(mCamera); // Create a default camera controller -} -//--------------------------------------------------------------------------- -void BaseApplication::createFrameListener(void) -{ - Ogre::LogManager::getSingletonPtr()->logMessage("*** Initializing OIS ***"); - OIS::ParamList pl; - size_t windowHnd = 0; - std::ostringstream windowHndStr; - - mWindow->getCustomAttribute("WINDOW", &windowHnd); - windowHndStr << windowHnd; - pl.insert(std::make_pair(std::string("WINDOW"), windowHndStr.str())); - - mInputManager = OIS::InputManager::createInputSystem(pl); - - mKeyboard = static_cast(mInputManager->createInputObject(OIS::OISKeyboard, true)); - mMouse = static_cast(mInputManager->createInputObject(OIS::OISMouse, true)); - - mMouse->setEventCallback(this); - mKeyboard->setEventCallback(this); - - // Set initial mouse clipping size - windowResized(mWindow); - - // Register as a Window listener - Ogre::WindowEventUtilities::addWindowEventListener(mWindow, this); - - mInputContext.mKeyboard = mKeyboard; - mInputContext.mMouse = mMouse; - mTrayMgr = new OgreBites::SdkTrayManager("InterfaceName", mWindow, mInputContext, this); - mTrayMgr->showFrameStats(OgreBites::TL_BOTTOMLEFT); - mTrayMgr->showLogo(OgreBites::TL_BOTTOMRIGHT); - mTrayMgr->hideCursor(); - - // Create a params panel for displaying sample details - Ogre::StringVector items; - items.push_back("cam.pX"); - items.push_back("cam.pY"); - items.push_back("cam.pZ"); - items.push_back(""); - items.push_back("cam.oW"); - items.push_back("cam.oX"); - items.push_back("cam.oY"); - items.push_back("cam.oZ"); - items.push_back(""); - items.push_back("Filtering"); - items.push_back("Poly Mode"); - - mDetailsPanel = mTrayMgr->createParamsPanel(OgreBites::TL_NONE, "DetailsPanel", 200, items); - mDetailsPanel->setParamValue(9, "Bilinear"); - mDetailsPanel->setParamValue(10, "Solid"); - mDetailsPanel->hide(); - - mRoot->addFrameListener(this); -} -//--------------------------------------------------------------------------- -void BaseApplication::destroyScene(void) -{ -} -//--------------------------------------------------------------------------- -void BaseApplication::createViewports(void) -{ - // Create one viewport, entire window - Ogre::Viewport* vp = mWindow->addViewport(mCamera); - vp->setBackgroundColour(Ogre::ColourValue(0,0,0)); - - // Alter the camera aspect ratio to match the viewport - mCamera->setAspectRatio(Ogre::Real(vp->getActualWidth()) / Ogre::Real(vp->getActualHeight())); -} -//--------------------------------------------------------------------------- -void BaseApplication::setupResources(void) -{ - // Load resource paths from config file - Ogre::ConfigFile cf; - cf.load(mResourcesCfg); - - // Go through all sections & settings in the file - Ogre::ConfigFile::SectionIterator seci = cf.getSectionIterator(); - - Ogre::String secName, typeName, archName; - while (seci.hasMoreElements()) - { - secName = seci.peekNextKey(); - Ogre::ConfigFile::SettingsMultiMap *settings = seci.getNext(); - Ogre::ConfigFile::SettingsMultiMap::iterator i; - for (i = settings->begin(); i != settings->end(); ++i) - { - typeName = i->first; - archName = i->second; - -#if OGRE_PLATFORM == OGRE_PLATFORM_APPLE - // OS X does not set the working directory relative to the app. - // In order to make things portable on OS X we need to provide - // the loading with it's own bundle path location. - if (!Ogre::StringUtil::startsWith(archName, "/", false)) // only adjust relative directories - archName = Ogre::String(Ogre::macBundlePath() + "/" + archName); -#endif - - Ogre::ResourceGroupManager::getSingleton().addResourceLocation( - archName, typeName, secName); - } - } -} -//--------------------------------------------------------------------------- -void BaseApplication::createResourceListener(void) -{ -} -//--------------------------------------------------------------------------- -void BaseApplication::loadResources(void) -{ - Ogre::ResourceGroupManager::getSingleton().initialiseAllResourceGroups(); -} -//--------------------------------------------------------------------------- -void BaseApplication::go(void) -{ -#ifdef _DEBUG -#ifndef OGRE_STATIC_LIB - mResourcesCfg = m_ResourcePath + "resources_d.cfg"; - mPluginsCfg = m_ResourcePath + "plugins_d.cfg"; -#else - mResourcesCfg = "resources_d.cfg"; - mPluginsCfg = "plugins_d.cfg"; -#endif -#else -#ifndef OGRE_STATIC_LIB - mResourcesCfg = m_ResourcePath + "resources.cfg"; - mPluginsCfg = m_ResourcePath + "plugins.cfg"; -#else - mResourcesCfg = "resources.cfg"; - mPluginsCfg = "plugins.cfg"; -#endif -#endif - - if (!setup()) - return; - - mRoot->startRendering(); - - // Clean up - destroyScene(); -} -//--------------------------------------------------------------------------- -bool BaseApplication::setup(void) -{ - mRoot = new Ogre::Root(mPluginsCfg); - - setupResources(); - - bool carryOn = configure(); - if (!carryOn) return false; - - chooseSceneManager(); - createCamera(); - createViewports(); - - // Set default mipmap level (NB some APIs ignore this) - Ogre::TextureManager::getSingleton().setDefaultNumMipmaps(5); - - // Create any resource listeners (for loading screens) - createResourceListener(); - // Load resources - loadResources(); - - // Create the scene - createScene(); - - createFrameListener(); - - return true; -}; -//--------------------------------------------------------------------------- -bool BaseApplication::frameRenderingQueued(const Ogre::FrameEvent& evt) -{ - if(mWindow->isClosed()) - return false; - - if(mShutDown) - return false; - - // Need to capture/update each device - mKeyboard->capture(); - mMouse->capture(); - - mTrayMgr->frameRenderingQueued(evt); - - if (!mTrayMgr->isDialogVisible()) - { - mCameraMan->frameRenderingQueued(evt); // If dialog isn't up, then update the camera - if (mDetailsPanel->isVisible()) // If details panel is visible, then update its contents - { - mDetailsPanel->setParamValue(0, Ogre::StringConverter::toString(mCamera->getDerivedPosition().x)); - mDetailsPanel->setParamValue(1, Ogre::StringConverter::toString(mCamera->getDerivedPosition().y)); - mDetailsPanel->setParamValue(2, Ogre::StringConverter::toString(mCamera->getDerivedPosition().z)); - mDetailsPanel->setParamValue(4, Ogre::StringConverter::toString(mCamera->getDerivedOrientation().w)); - mDetailsPanel->setParamValue(5, Ogre::StringConverter::toString(mCamera->getDerivedOrientation().x)); - mDetailsPanel->setParamValue(6, Ogre::StringConverter::toString(mCamera->getDerivedOrientation().y)); - mDetailsPanel->setParamValue(7, Ogre::StringConverter::toString(mCamera->getDerivedOrientation().z)); - } - } - - return true; -} -//--------------------------------------------------------------------------- -bool BaseApplication::keyPressed( const OIS::KeyEvent &arg ) -{ - if (mTrayMgr->isDialogVisible()) return true; // don't process any more keys if dialog is up - - if (arg.key == OIS::KC_F) // toggle visibility of advanced frame stats - { - mTrayMgr->toggleAdvancedFrameStats(); - } - else if (arg.key == OIS::KC_G) // toggle visibility of even rarer debugging details - { - if (mDetailsPanel->getTrayLocation() == OgreBites::TL_NONE) - { - mTrayMgr->moveWidgetToTray(mDetailsPanel, OgreBites::TL_TOPRIGHT, 0); - mDetailsPanel->show(); - } - else - { - mTrayMgr->removeWidgetFromTray(mDetailsPanel); - mDetailsPanel->hide(); - } - } - else if (arg.key == OIS::KC_T) // cycle polygon rendering mode - { - Ogre::String newVal; - Ogre::TextureFilterOptions tfo; - unsigned int aniso; - - switch (mDetailsPanel->getParamValue(9).asUTF8()[0]) - { - case 'B': - newVal = "Trilinear"; - tfo = Ogre::TFO_TRILINEAR; - aniso = 1; - break; - case 'T': - newVal = "Anisotropic"; - tfo = Ogre::TFO_ANISOTROPIC; - aniso = 8; - break; - case 'A': - newVal = "None"; - tfo = Ogre::TFO_NONE; - aniso = 1; - break; - default: - newVal = "Bilinear"; - tfo = Ogre::TFO_BILINEAR; - aniso = 1; - } - - Ogre::MaterialManager::getSingleton().setDefaultTextureFiltering(tfo); - Ogre::MaterialManager::getSingleton().setDefaultAnisotropy(aniso); - mDetailsPanel->setParamValue(9, newVal); - } - else if (arg.key == OIS::KC_R) // cycle polygon rendering mode - { - Ogre::String newVal; - Ogre::PolygonMode pm; - - switch (mCamera->getPolygonMode()) - { - case Ogre::PM_SOLID: - newVal = "Wireframe"; - pm = Ogre::PM_WIREFRAME; - break; - case Ogre::PM_WIREFRAME: - newVal = "Points"; - pm = Ogre::PM_POINTS; - break; - default: - newVal = "Solid"; - pm = Ogre::PM_SOLID; - } - - mCamera->setPolygonMode(pm); - mDetailsPanel->setParamValue(10, newVal); - } - else if(arg.key == OIS::KC_F5) // refresh all textures - { - Ogre::TextureManager::getSingleton().reloadAll(); - } - else if (arg.key == OIS::KC_SYSRQ) // take a screenshot - { - mWindow->writeContentsToTimestampedFile("screenshot", ".jpg"); - } - else if (arg.key == OIS::KC_ESCAPE) - { - mShutDown = true; - } - - mCameraMan->injectKeyDown(arg); - return true; -} -//--------------------------------------------------------------------------- -bool BaseApplication::keyReleased(const OIS::KeyEvent &arg) -{ - mCameraMan->injectKeyUp(arg); - return true; -} -//--------------------------------------------------------------------------- -bool BaseApplication::mouseMoved(const OIS::MouseEvent &arg) -{ - if (mTrayMgr->injectMouseMove(arg)) return true; - mCameraMan->injectMouseMove(arg); - return true; -} -//--------------------------------------------------------------------------- -bool BaseApplication::mousePressed(const OIS::MouseEvent &arg, OIS::MouseButtonID id) -{ - if (mTrayMgr->injectMouseDown(arg, id)) return true; - mCameraMan->injectMouseDown(arg, id); - return true; -} -//--------------------------------------------------------------------------- -bool BaseApplication::mouseReleased(const OIS::MouseEvent &arg, OIS::MouseButtonID id) -{ - if (mTrayMgr->injectMouseUp(arg, id)) return true; - mCameraMan->injectMouseUp(arg, id); - return true; -} -//--------------------------------------------------------------------------- -// Adjust mouse clipping area -void BaseApplication::windowResized(Ogre::RenderWindow* rw) -{ - unsigned int width, height, depth; - int left, top; - rw->getMetrics(width, height, depth, left, top); - - const OIS::MouseState &ms = mMouse->getMouseState(); - ms.width = width; - ms.height = height; -} -//--------------------------------------------------------------------------- -// Unattach OIS before window shutdown (very important under Linux) -void BaseApplication::windowClosed(Ogre::RenderWindow* rw) -{ - // Only close for window that created OIS (the main window in these demos) - if(rw == mWindow) - { - if(mInputManager) - { - mInputManager->destroyInputObject(mMouse); - mInputManager->destroyInputObject(mKeyboard); - - OIS::InputManager::destroyInputSystem(mInputManager); - mInputManager = 0; - } - } -} -//--------------------------------------------------------------------------- \ No newline at end of file diff --git a/src/BaseApplication.h b/src/BaseApplication.h deleted file mode 100644 index c9ee979..0000000 --- a/src/BaseApplication.h +++ /dev/null @@ -1,139 +0,0 @@ -/* ------------------------------------------------------------------------------ -Filename: BaseApplication.h ------------------------------------------------------------------------------ - -This source file is part of the - ___ __ __ _ _ _ - /___\__ _ _ __ ___ / / /\ \ (_) | _(_) - // // _` | '__/ _ \ \ \/ \/ / | |/ / | -/ \_// (_| | | | __/ \ /\ /| | <| | -\___/ \__, |_| \___| \/ \/ |_|_|\_\_| - |___/ -Tutorial Framework (for Ogre 1.9) -http://www.ogre3d.org/wiki/ ------------------------------------------------------------------------------ -*/ - -#ifndef __BaseApplication_h_ -#define __BaseApplication_h_ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#if OGRE_PLATFORM == OGRE_PLATFORM_APPLE -# include -# include -# include -# include - -# include -# include -#else -# include -# include -# include -# include - -# include -# include -#endif - -#ifdef OGRE_STATIC_LIB -# define OGRE_STATIC_GL -# if OGRE_PLATFORM == OGRE_PLATFORM_WIN32 -# define OGRE_STATIC_Direct3D9 -// D3D10 will only work on vista, so be careful about statically linking -# if OGRE_USE_D3D10 -# define OGRE_STATIC_Direct3D10 -# endif -# endif -# define OGRE_STATIC_BSPSceneManager -# define OGRE_STATIC_ParticleFX -# define OGRE_STATIC_CgProgramManager -# ifdef OGRE_USE_PCZ -# define OGRE_STATIC_PCZSceneManager -# define OGRE_STATIC_OctreeZone -# else -# define OGRE_STATIC_OctreeSceneManager -# endif -# include "OgreStaticPluginLoader.h" -#endif - -//--------------------------------------------------------------------------- - -class BaseApplication : public Ogre::FrameListener, public Ogre::WindowEventListener, public OIS::KeyListener, public OIS::MouseListener, OgreBites::SdkTrayListener -{ -public: - BaseApplication(void); - virtual ~BaseApplication(void); - - virtual void go(void); - -protected: - virtual bool setup(); - virtual bool configure(void); - virtual void chooseSceneManager(void); - virtual void createCamera(void); - virtual void createFrameListener(void); - virtual void createScene(void) = 0; // Override me! - virtual void destroyScene(void); - virtual void createViewports(void); - virtual void setupResources(void); - virtual void createResourceListener(void); - virtual void loadResources(void); - virtual bool frameRenderingQueued(const Ogre::FrameEvent& evt); - - virtual bool keyPressed(const OIS::KeyEvent &arg); - virtual bool keyReleased(const OIS::KeyEvent &arg); - virtual bool mouseMoved(const OIS::MouseEvent &arg); - virtual bool mousePressed(const OIS::MouseEvent &arg, OIS::MouseButtonID id); - virtual bool mouseReleased(const OIS::MouseEvent &arg, OIS::MouseButtonID id); - - // Adjust mouse clipping area - virtual void windowResized(Ogre::RenderWindow* rw); - // Unattach OIS before window shutdown (very important under Linux) - virtual void windowClosed(Ogre::RenderWindow* rw); - - Ogre::Root* mRoot; - Ogre::Camera* mCamera; - Ogre::SceneManager* mSceneMgr; - Ogre::RenderWindow* mWindow; - Ogre::String mResourcesCfg; - Ogre::String mPluginsCfg; - - Ogre::OverlaySystem* mOverlaySystem; - - // OgreBites - OgreBites::InputContext mInputContext; - OgreBites::SdkTrayManager* mTrayMgr; - OgreBites::SdkCameraMan* mCameraMan; // Basic camera controller - OgreBites::ParamsPanel* mDetailsPanel; // Sample details panel - bool mCursorWasVisible; // Was cursor visible before dialog appeared? - bool mShutDown; - - //OIS Input devices - OIS::InputManager* mInputManager; - OIS::Mouse* mMouse; - OIS::Keyboard* mKeyboard; - - // Added for Mac compatibility - Ogre::String m_ResourcePath; - -#ifdef OGRE_STATIC_LIB - Ogre::StaticPluginLoader m_StaticPluginLoader; -#endif -}; - -//--------------------------------------------------------------------------- - -#endif // #ifndef __BaseApplication_h_ - -//--------------------------------------------------------------------------- \ No newline at end of file diff --git a/src/PlanetScapeApplication.cpp b/src/PlanetScapeApplication.cpp index 6f4c0ed..803ff64 100644 --- a/src/PlanetScapeApplication.cpp +++ b/src/PlanetScapeApplication.cpp @@ -16,17 +16,8 @@ Tutorial Framework (for Ogre 1.9) */ #include "PlanetScapeApplication.h" -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include +#include +#include #include #include @@ -34,6 +25,7 @@ using namespace Ogre; //--------------------------------------------------------------------------- PlanetScapeApplication::PlanetScapeApplication(void) : +OgreBites::ApplicationContext("Planetscape"), mShutDownFileWatcher(false), mShouldReload(false), mThread() @@ -49,8 +41,31 @@ PlanetScapeApplication::~PlanetScapeApplication(void) } //--------------------------------------------------------------------------- -void PlanetScapeApplication::createScene(void) +void PlanetScapeApplication::setup() { + OgreBites::ApplicationContext::setup(); + + mSceneMgr = getRoot()->createSceneManager(); + mCamera = mSceneMgr->createCamera("PlayerCam"); + mCamera->setNearClipDistance(5); + mCamera->setAutoAspectRatio(true); + + auto camNode = mSceneMgr->getRootSceneNode()->createChildSceneNode(); + camNode->attachObject(mCamera); + // Position it at 500 in Z direction + camNode->setPosition(Ogre::Vector3(0,0,80)); + // Look back along -Z + camNode->lookAt(Ogre::Vector3(0,0,-300), Ogre::Node::TS_WORLD); + + auto camMan = new OgreBites::CameraMan(camNode); + camMan->setStyle(OgreBites::CS_ORBIT); + addInputListener(camMan); + addInputListener(this); + + // Create one viewport, entire window + Ogre::Viewport* vp = getRenderWindow()->addViewport(mCamera); + vp->setBackgroundColour(Ogre::ColourValue(0,0,0)); + Light *sun = mSceneMgr->createLight("Sun"); sun->setDiffuseColour(ColourValue(1.f, 1.f, 1.f, 1.f)); @@ -81,7 +96,7 @@ void PlanetScapeApplication::createScene(void) mPlanetMaterial = MaterialManager::getSingleton().create( "PlanetMaterial", ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME - ); + ).get(); mPlaneEntity->setMaterialName(mPlanetMaterial->getName()); mPlanetEntity->setMaterialName(mPlanetMaterial->getName()); @@ -175,18 +190,22 @@ bool PlanetScapeApplication::frameRenderingQueued(const Ogre::FrameEvent& evt) reload(); } - return BaseApplication::frameRenderingQueued(evt); + return OgreBites::ApplicationContext::frameRenderingQueued(evt); } -bool PlanetScapeApplication::keyReleased(const OIS::KeyEvent &arg) +bool PlanetScapeApplication::keyReleased(const OgreBites::KeyboardEvent& arg) { - if (arg.key == OIS::KC_L) { + switch (arg.keysym.sym) { + case 'l': reloadPlanetJson(); reload(); - return true; + break; + case 27: + getRoot()->queueEndRendering(); + break; } - return BaseApplication::keyReleased(arg); + return true; } void PlanetScapeApplication::reloadPlanetJson() @@ -573,7 +592,9 @@ extern "C" { PlanetScapeApplication app; try { - app.go(); + app.initApp(); + app.getRoot()->startRendering(); + app.closeApp(); } catch(Ogre::Exception& e) { #if OGRE_PLATFORM == OGRE_PLATFORM_WIN32 MessageBox(NULL, e.getFullDescription().c_str(), "An exception has occurred!", MB_OK | MB_ICONERROR | MB_TASKMODAL); diff --git a/src/PlanetScapeApplication.h b/src/PlanetScapeApplication.h index 6f57f13..2002466 100644 --- a/src/PlanetScapeApplication.h +++ b/src/PlanetScapeApplication.h @@ -18,30 +18,33 @@ Tutorial Framework (for Ogre 1.9) #ifndef __PlanetScapeApplication_h_ #define __PlanetScapeApplication_h_ -#include "BaseApplication.h" +#include #include "rapidjson/document.h" #include //--------------------------------------------------------------------------- -class PlanetScapeApplication : public BaseApplication +class PlanetScapeApplication : public OgreBites::ApplicationContext, public OgreBites::InputListener { public: PlanetScapeApplication(void); virtual ~PlanetScapeApplication(void); protected: - virtual void createScene(void); + virtual void setup(void); virtual bool frameRenderingQueued(const Ogre::FrameEvent& evt); - virtual bool keyReleased(const OIS::KeyEvent &arg); + virtual bool keyReleased(const OgreBites::KeyboardEvent &arg); void reload(); void reloadShader(); void reloadPlanetJson(); + Ogre::Camera* mCamera; + Ogre::SceneManager* mSceneMgr; + Ogre::Entity *mPlanetEntity; Ogre::Entity *mPlaneEntity; - Ogre::MaterialPtr mPlanetMaterial; + Ogre::Material* mPlanetMaterial; Ogre::SceneNode *mPlanetSceneNode; Ogre::SceneNode *mPlaneSceneNode; From 80465398a37664e80102c4573406aaf9b5ebbfca Mon Sep 17 00:00:00 2001 From: Pavel Rojtberg Date: Fri, 4 Jan 2019 23:38:54 +0100 Subject: [PATCH 4/5] re-add rapidjson as git submodule --- .gitmodules | 3 + CMakeLists.txt | 2 +- lib/rapidjson/allocators.h | 261 ---- lib/rapidjson/document.h | 2110 --------------------------- lib/rapidjson/encodedstream.h | 261 ---- lib/rapidjson/encodings.h | 625 -------- lib/rapidjson/error/en.h | 65 - lib/rapidjson/error/error.h | 146 -- lib/rapidjson/filereadstream.h | 88 -- lib/rapidjson/filewritestream.h | 95 -- lib/rapidjson/internal/biginteger.h | 290 ---- lib/rapidjson/internal/diyfp.h | 248 ---- lib/rapidjson/internal/dtoa.h | 217 --- lib/rapidjson/internal/ieee754.h | 77 - lib/rapidjson/internal/itoa.h | 304 ---- lib/rapidjson/internal/meta.h | 181 --- lib/rapidjson/internal/pow10.h | 55 - lib/rapidjson/internal/stack.h | 189 --- lib/rapidjson/internal/strfunc.h | 39 - lib/rapidjson/internal/strtod.h | 270 ---- lib/rapidjson/internal/swap.h | 37 - lib/rapidjson/memorybuffer.h | 70 - lib/rapidjson/memorystream.h | 61 - lib/rapidjson/msinttypes/inttypes.h | 316 ---- lib/rapidjson/msinttypes/stdint.h | 300 ---- lib/rapidjson/pointer.h | 1313 ----------------- lib/rapidjson/prettywriter.h | 207 --- lib/rapidjson/rapidjson.h | 654 --------- lib/rapidjson/reader.h | 1452 ------------------ lib/rapidjson/stringbuffer.h | 93 -- lib/rapidjson/writer.h | 395 ----- rapidjson | 1 + 32 files changed, 5 insertions(+), 10420 deletions(-) create mode 100644 .gitmodules delete mode 100644 lib/rapidjson/allocators.h delete mode 100644 lib/rapidjson/document.h delete mode 100644 lib/rapidjson/encodedstream.h delete mode 100644 lib/rapidjson/encodings.h delete mode 100644 lib/rapidjson/error/en.h delete mode 100644 lib/rapidjson/error/error.h delete mode 100644 lib/rapidjson/filereadstream.h delete mode 100644 lib/rapidjson/filewritestream.h delete mode 100644 lib/rapidjson/internal/biginteger.h delete mode 100644 lib/rapidjson/internal/diyfp.h delete mode 100644 lib/rapidjson/internal/dtoa.h delete mode 100644 lib/rapidjson/internal/ieee754.h delete mode 100644 lib/rapidjson/internal/itoa.h delete mode 100644 lib/rapidjson/internal/meta.h delete mode 100644 lib/rapidjson/internal/pow10.h delete mode 100644 lib/rapidjson/internal/stack.h delete mode 100644 lib/rapidjson/internal/strfunc.h delete mode 100644 lib/rapidjson/internal/strtod.h delete mode 100644 lib/rapidjson/internal/swap.h delete mode 100644 lib/rapidjson/memorybuffer.h delete mode 100644 lib/rapidjson/memorystream.h delete mode 100644 lib/rapidjson/msinttypes/inttypes.h delete mode 100644 lib/rapidjson/msinttypes/stdint.h delete mode 100644 lib/rapidjson/pointer.h delete mode 100644 lib/rapidjson/prettywriter.h delete mode 100644 lib/rapidjson/rapidjson.h delete mode 100644 lib/rapidjson/reader.h delete mode 100644 lib/rapidjson/stringbuffer.h delete mode 100644 lib/rapidjson/writer.h create mode 160000 rapidjson diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000..c4d9b0d --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "rapidjson"] + path = rapidjson + url = https://github.com/Tencent/rapidjson diff --git a/CMakeLists.txt b/CMakeLists.txt index 72d8d7c..389a136 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -5,5 +5,5 @@ project(Planetscape) find_package(OGRE 1.10 REQUIRED) add_executable(Planetscape src/PlanetScapeApplication.cpp) -target_include_directories(Planetscape PRIVATE src lib) +target_include_directories(Planetscape PRIVATE src rapidjson/include) target_link_libraries(Planetscape PRIVATE OgreMain OgreBites) \ No newline at end of file diff --git a/lib/rapidjson/allocators.h b/lib/rapidjson/allocators.h deleted file mode 100644 index 24e6044..0000000 --- a/lib/rapidjson/allocators.h +++ /dev/null @@ -1,261 +0,0 @@ -// 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; - if (newSize == 0) { - std::free(originalPtr); - return NULL; - } - 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 -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(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_ && chunkHead_ != userBuffer_) { - ChunkHeader* next = chunkHead_->next; - baseAllocator_->Free(chunkHead_); - chunkHead_ = next; - } - if (chunkHead_ && chunkHead_ == userBuffer_) - chunkHead_->size = 0; // Clear user buffer - } - - //! 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(chunkHead_) + RAPIDJSON_ALIGN(sizeof(ChunkHeader)) + 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); - - if (newSize == 0) - return NULL; - - // 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_) + RAPIDJSON_ALIGN(sizeof(ChunkHeader)) + chunkHead_->size - originalSize) { - size_t increment = static_cast(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(baseAllocator_->Malloc(RAPIDJSON_ALIGN(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/lib/rapidjson/document.h b/lib/rapidjson/document.h deleted file mode 100644 index 7ea505f..0000000 --- a/lib/rapidjson/document.h +++ /dev/null @@ -1,2110 +0,0 @@ -// 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 // 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 -#endif // RAPIDJSON_HAS_STDSTRING - -#ifndef RAPIDJSON_NOMEMBERITERATORCLASS -#include // std::iterator, std::random_access_iterator_tag -#endif - -#if RAPIDJSON_HAS_CXX11_RVALUE_REFS -#include // std::move -#endif - -RAPIDJSON_NAMESPACE_BEGIN - -// Forward declaration. -template -class GenericValue; - -template -class GenericDocument; - -//! 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 -struct GenericMember { - GenericValue name; //!< name of member (must be a string) - GenericValue 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++ header. - - \see GenericMember, GenericValue::MemberIterator, GenericValue::ConstMemberIterator - */ -template -class GenericMemberIterator - : public std::iterator >::Type> { - - friend class GenericValue; - template friend class GenericMemberIterator; - - typedef GenericMember PlainType; - typedef typename internal::MaybeAddConst::Type ValueType; - typedef std::iterator BaseType; - -public: - //! Iterator type itself - typedef GenericMemberIterator Iterator; - //! Constant iterator type - typedef GenericMemberIterator ConstIterator; - //! Non-constant iterator type - typedef GenericMemberIterator 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 -struct GenericMemberIterator; - -//! non-const GenericMemberIterator -template -struct GenericMemberIterator { - //! use plain pointer as iterator type - typedef GenericMember* Iterator; -}; -//! const GenericMemberIterator -template -struct GenericMemberIterator { - //! use plain const pointer as iterator type - typedef const GenericMember* 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 -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 - 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); } - - //! 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 - 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 -inline GenericStringRef StringRef(const CharType* str) { - return GenericStringRef(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 -inline GenericStringRef StringRef(const CharType* str, size_t length) { - return GenericStringRef(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 -inline GenericStringRef StringRef(const std::basic_string& str) { - return GenericStringRef(str.data(), SizeType(str.size())); -} -#endif - -/////////////////////////////////////////////////////////////////////////////// -// GenericValue type traits -namespace internal { - -template -struct IsGenericValueImpl : FalseType {}; - -// select candidates according to nested encoding and allocator types -template struct IsGenericValueImpl::Type, typename Void::Type> - : IsBaseOf, T>::Type {}; - -// helper to match arbitrary GenericValue instantiations, including derived classes -template struct IsGenericValue : IsGenericValueImpl::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 > -class GenericValue { -public: - //! Name-value pair in an object. - typedef GenericMember 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 StringRefType; //!< Reference to a constant string - typedef typename GenericMemberIterator::Iterator MemberIterator; //!< Member iterator for iterating in object. - typedef typename GenericMemberIterator::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. - typedef GenericValue ValueType; //!< Value type of itself. - - //!@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); - -#if RAPIDJSON_HAS_CXX11_RVALUE_REFS - //! Moving from a GenericDocument is not permitted. - template - GenericValue(GenericDocument&& rhs); - - //! Move assignment from a GenericDocument is not permitted. - template - GenericValue& operator=(GenericDocument&& rhs); -#endif - -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& 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 - explicit GenericValue(T b, RAPIDJSON_ENABLEIF((internal::IsSame))) 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::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(i64) & RAPIDJSON_UINT64_C2(0xFFFFFFFF, 0x00000000))) - flags_ |= kUintFlag; - if (!(static_cast(i64) & RAPIDJSON_UINT64_C2(0xFFFFFFFF, 0x80000000))) - flags_ |= kIntFlag; - } - else if (i64 >= static_cast(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& 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(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 - RAPIDJSON_DISABLEIF_RETURN((internal::IsPointer), (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 - GenericValue& CopyFrom(const GenericValue& 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; - } - - //! free-standing swap function helper - /*! - Helper function to enable support for common swap implementation pattern based on \c std::swap: - \code - void swap(MyClass& a, MyClass& b) { - using std::swap; - swap(a.value, b.value); - // ... - } - \endcode - \see Swap() - */ - friend inline void swap(GenericValue& a, GenericValue& b) RAPIDJSON_NOEXCEPT { a.Swap(b); } - - //! 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 - bool operator==(const GenericValue& rhs) const { - typedef GenericValue 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& 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 RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr,internal::IsGenericValue >), (bool)) operator==(const T& rhs) const { return *this == GenericValue(rhs); } - - //! Not-equal-to operator - /*! \return !(*this == rhs) - */ - template - bool operator!=(const GenericValue& 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 RAPIDJSON_DISABLEIF_RETURN((internal::IsGenericValue), (bool)) operator!=(const T& rhs) const { return !(*this == rhs); } - - //! Equal-to operator with arbitrary types (symmetric version) - /*! \return (rhs == lhs) - */ - template friend RAPIDJSON_DISABLEIF_RETURN((internal::IsGenericValue), (bool)) operator==(const T& lhs, const GenericValue& rhs) { return rhs == lhs; } - - //! Not-Equal-to operator with arbitrary types (symmetric version) - /*! \return !(rhs == lhs) - */ - template friend RAPIDJSON_DISABLEIF_RETURN((internal::IsGenericValue), (bool)) operator!=(const T& lhs, const GenericValue& rhs) { return !(rhs == lhs); } - //@} - - //!@name Type - //@{ - - Type GetType() const { return static_cast(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 - RAPIDJSON_DISABLEIF_RETURN((internal::NotExpr::Type, Ch> >),(GenericValue&)) operator[](T* name) { - GenericValue n(StringRef(name)); - return (*this)[n]; - } - template - RAPIDJSON_DISABLEIF_RETURN((internal::NotExpr::Type, Ch> >),(const GenericValue&)) operator[](T* name) const { return const_cast(*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 - GenericValue& operator[](const GenericValue& name) { - MemberIterator member = FindMember(name); - if (member != MemberEnd()) - return member->value; - else { - RAPIDJSON_ASSERT(false); // see above note - static GenericValue NullValue; - return NullValue; - } - } - template - const GenericValue& operator[](const GenericValue& name) const { return const_cast(*this)[name]; } - -#if RAPIDJSON_HAS_STDSTRING - //! Get a value from an object associated with name (string object). - GenericValue& operator[](const std::basic_string& name) { return (*this)[GenericValue(StringRef(name))]; } - const GenericValue& operator[](const std::basic_string& name) const { return (*this)[GenericValue(StringRef(name))]; } -#endif - - //! 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(); } - -#if RAPIDJSON_HAS_STDSTRING - //! Check whether a member exists in the object with string 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 std::basic_string& name) const { return FindMember(name) != MemberEnd(); } -#endif - - //! 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 - bool HasMember(const GenericValue& 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(*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 - MemberIterator FindMember(const GenericValue& name) { - RAPIDJSON_ASSERT(IsObject()); - RAPIDJSON_ASSERT(name.IsString()); - MemberIterator member = MemberBegin(); - for ( ; member != MemberEnd(); ++member) - if (name.StringEqual(member->name)) - break; - return member; - } - template ConstMemberIterator FindMember(const GenericValue& name) const { return const_cast(*this).FindMember(name); } - -#if RAPIDJSON_HAS_STDSTRING - //! Find member by string object name. - /*! - \param name Member name to be searched. - \pre IsObject() == true - \return Iterator to member, if it exists. - Otherwise returns \ref MemberEnd(). - */ - MemberIterator FindMember(const std::basic_string& name) { return FindMember(StringRef(name)); } - ConstMemberIterator FindMember(const std::basic_string& name) const { return FindMember(StringRef(name)); } -#endif - - //! 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(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(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); - } - -#if RAPIDJSON_HAS_STDSTRING - //! Add a string object 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, std::basic_string& value, Allocator& allocator) { - GenericValue v(value, allocator); - return AddMember(name, v, allocator); - } -#endif - - //! 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 - RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr, internal::IsGenericValue >), (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 - RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr, internal::IsGenericValue >), (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); - } - -#if RAPIDJSON_HAS_STDSTRING - bool RemoveMember(const std::basic_string& name) { return RemoveMember(GenericValue(StringRef(name))); } -#endif - - template - bool RemoveMember(const GenericValue& 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; - } - - //! Erase a member in object by its name. - /*! \param name Name of member to be removed. - \return Whether the member existed. - \note Linear time complexity. - */ - bool EraseMember(const Ch* name) { - GenericValue n(StringRef(name)); - return EraseMember(n); - } - -#if RAPIDJSON_HAS_STDSTRING - bool EraseMember(const std::basic_string& name) { return EraseMember(GenericValue(StringRef(name))); } -#endif - - template - bool EraseMember(const GenericValue& name) { - MemberIterator m = FindMember(name); - if (m != MemberEnd()) { - EraseMember(m); - return true; - } - else - return false; - } - - //@} - - //!@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(*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(*this).Begin(); } - //! Constant \em past-the-end element iterator - /*! \pre IsArray() == true */ - ConstValueIterator End() const { return const_cast(*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(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 - RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr, internal::IsGenericValue >), (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& s, Allocator& allocator) { return SetString(s.data(), SizeType(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 - 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 friend class GenericValue; - template 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 - bool StringEqual(const GenericValue& 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 > 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 StackAllocator = CrtAllocator> -class GenericDocument : public GenericValue { -public: - typedef typename Encoding::Ch Ch; //!< Character type derived from Encoding. - typedef GenericValue ValueType; //!< Value type of the document. - typedef Allocator AllocatorType; //!< Allocator type from template parameter. - - //! Constructor - /*! Creates an empty document of specified type. - \param type Mandatory type of object to create. - \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. - */ - explicit GenericDocument(Type type, Allocator* allocator = 0, size_t stackCapacity = kDefaultStackCapacity, StackAllocator* stackAllocator = 0) : - GenericValue(type), allocator_(allocator), ownAllocator_(0), stack_(stackAllocator, stackCapacity), parseResult_() - { - if (!allocator_) - ownAllocator_ = allocator_ = RAPIDJSON_NEW(Allocator()); - } - - //! Constructor - /*! Creates an empty document which type is Null. - \param allocator Optional allocator for allocating memory. - \param stackCapacity Optional initial capacity of stack in bytes. - \param stackAllocator Optional allocator for allocating memory for stack. - */ - GenericDocument(Allocator* allocator = 0, size_t stackCapacity = kDefaultStackCapacity, StackAllocator* stackAllocator = 0) : - 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::forward(rhs)), // explicit cast to avoid prohibited move from Document - 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(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 - - //! Exchange the contents of this document with those of another. - /*! - \param other Another document. - \note Constant complexity. - \see GenericValue::Swap - */ - GenericDocument& Swap(GenericDocument& rhs) RAPIDJSON_NOEXCEPT { - ValueType::Swap(rhs); - stack_.Swap(rhs.stack_); - internal::Swap(allocator_, rhs.allocator_); - internal::Swap(ownAllocator_, rhs.ownAllocator_); - internal::Swap(parseResult_, rhs.parseResult_); - return *this; - } - - //! free-standing swap function helper - /*! - Helper function to enable support for common swap implementation pattern based on \c std::swap: - \code - void swap(MyClass& a, MyClass& b) { - using std::swap; - swap(a.doc, b.doc); - // ... - } - \endcode - \see Swap() - */ - friend inline void swap(GenericDocument& a, GenericDocument& b) RAPIDJSON_NOEXCEPT { a.Swap(b); } - - //!@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 - GenericDocument& ParseStream(InputStream& is) { - ValueType::SetNull(); // Remove existing root if exist - GenericReader reader(&stack_.GetAllocator()); - ClearStackOnExit scope(*this); - parseResult_ = reader.template Parse(is, *this); - if (parseResult_) { - RAPIDJSON_ASSERT(stack_.GetSize() == sizeof(ValueType)); // Got one and only one root object - this->RawAssign(*stack_.template Pop(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 - GenericDocument& ParseStream(InputStream& is) { - return ParseStream(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 - GenericDocument& ParseStream(InputStream& is) { - return ParseStream(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 - GenericDocument& ParseInsitu(Ch* str) { - GenericInsituStringStream s(str); - return ParseStream(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(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 - GenericDocument& Parse(const Ch* str) { - RAPIDJSON_ASSERT(!(parseFlags & kParseInsituFlag)); - GenericStringStream s(str); - return ParseStream(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 - GenericDocument& Parse(const Ch* str) { - return Parse(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(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 friend class GenericReader; // for parsing - template friend class GenericValue; // for deep copying - - // Implementation of Handler - bool Null() { new (stack_.template Push()) ValueType(); return true; } - bool Bool(bool b) { new (stack_.template Push()) ValueType(b); return true; } - bool Int(int i) { new (stack_.template Push()) ValueType(i); return true; } - bool Uint(unsigned i) { new (stack_.template Push()) ValueType(i); return true; } - bool Int64(int64_t i) { new (stack_.template Push()) ValueType(i); return true; } - bool Uint64(uint64_t i) { new (stack_.template Push()) ValueType(i); return true; } - bool Double(double d) { new (stack_.template Push()) ValueType(d); return true; } - - bool String(const Ch* str, SizeType length, bool copy) { - if (copy) - new (stack_.template Push()) ValueType(str, length, GetAllocator()); - else - new (stack_.template Push()) ValueType(str, length); - return true; - } - - bool StartObject() { new (stack_.template Push()) 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(memberCount); - stack_.template Top()->SetObjectRaw(members, (SizeType)memberCount, GetAllocator()); - return true; - } - - bool StartArray() { new (stack_.template Push()) ValueType(kArrayType); return true; } - - bool EndArray(SizeType elementCount) { - ValueType* elements = stack_.template Pop(elementCount); - stack_.template Top()->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(1))->~ValueType(); - else - stack_.Clear(); - stack_.ShrinkToFit(); - } - - void Destroy() { - RAPIDJSON_DELETE(ownAllocator_); - } - - static const size_t kDefaultStackCapacity = 1024; - Allocator* allocator_; - Allocator* ownAllocator_; - internal::Stack stack_; - ParseResult parseResult_; -}; - -//! GenericDocument with UTF8 encoding -typedef GenericDocument > Document; - -// defined here due to the dependency on GenericDocument -template -template -inline -GenericValue::GenericValue(const GenericValue& rhs, Allocator& allocator) -{ - switch (rhs.GetType()) { - case kObjectType: - case kArrayType: { // perform deep copy via SAX Handler - GenericDocument d(&allocator); - rhs.Accept(d); - RawAssign(*d.stack_.template Pop(1)); - } - break; - case kStringType: - if (rhs.flags_ == kConstStringFlag) { - flags_ = rhs.flags_; - data_ = *reinterpret_cast(&rhs.data_); - } else { - SetStringRaw(StringRef(rhs.GetString(), rhs.GetStringLength()), allocator); - } - break; - default: // kNumberType, kTrueType, kFalseType, kNullType - flags_ = rhs.flags_; - data_ = *reinterpret_cast(&rhs.data_); - } -} - -RAPIDJSON_NAMESPACE_END - -#if defined(_MSC_VER) || defined(__GNUC__) -RAPIDJSON_DIAG_POP -#endif - -#endif // RAPIDJSON_DOCUMENT_H_ diff --git a/lib/rapidjson/encodedstream.h b/lib/rapidjson/encodedstream.h deleted file mode 100644 index 919171d..0000000 --- a/lib/rapidjson/encodedstream.h +++ /dev/null @@ -1,261 +0,0 @@ -// 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 -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 -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::x, UTF16LE::x, UTF16BE::x, UTF32LE::x, UTF32BE::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 -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 = static_cast(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 -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/lib/rapidjson/encodings.h b/lib/rapidjson/encodings.h deleted file mode 100644 index 90b46ed..0000000 --- a/lib/rapidjson/encodings.h +++ /dev/null @@ -1,625 +0,0 @@ -// 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 - 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 - 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 - 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 - static CharType TakeBOM(InputByteStream& is); - - //! Take a character from input byte stream. - template - static Ch Take(InputByteStream& is); - - //! Put BOM to output byte stream. - template - static void PutBOM(OutputByteStream& os); - - //! Put a character to output byte stream. - template - 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 -struct UTF8 { - typedef CharType Ch; - - enum { supportUnicode = 1 }; - - template - static void Encode(OutputStream& os, unsigned codepoint) { - if (codepoint <= 0x7F) - os.Put(static_cast(codepoint & 0xFF)); - else if (codepoint <= 0x7FF) { - os.Put(static_cast(0xC0 | ((codepoint >> 6) & 0xFF))); - os.Put(static_cast(0x80 | ((codepoint & 0x3F)))); - } - else if (codepoint <= 0xFFFF) { - os.Put(static_cast(0xE0 | ((codepoint >> 12) & 0xFF))); - os.Put(static_cast(0x80 | ((codepoint >> 6) & 0x3F))); - os.Put(static_cast(0x80 | (codepoint & 0x3F))); - } - else { - RAPIDJSON_ASSERT(codepoint <= 0x10FFFF); - os.Put(static_cast(0xF0 | ((codepoint >> 18) & 0xFF))); - os.Put(static_cast(0x80 | ((codepoint >> 12) & 0x3F))); - os.Put(static_cast(0x80 | ((codepoint >> 6) & 0x3F))); - os.Put(static_cast(0x80 | (codepoint & 0x3F))); - } - } - - template - 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 - 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 - 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 - static Ch Take(InputByteStream& is) { - RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1); - return is.Take(); - } - - template - static void PutBOM(OutputByteStream& os) { - RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1); - os.Put(0xEFu); os.Put(0xBBu); os.Put(0xBFu); - } - - template - static void Put(OutputByteStream& os, Ch c) { - RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1); - os.Put(static_cast(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 -struct UTF16 { - typedef CharType Ch; - RAPIDJSON_STATIC_ASSERT(sizeof(Ch) >= 2); - - enum { supportUnicode = 1 }; - - template - 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(codepoint)); - } - else { - RAPIDJSON_ASSERT(codepoint <= 0x10FFFF); - unsigned v = codepoint - 0x10000; - os.Put(static_cast((v >> 10) | 0xD800)); - os.Put((v & 0x3FF) | 0xDC00); - } - } - - template - 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 - 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 -struct UTF16LE : UTF16 { - template - 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 - 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 - static void PutBOM(OutputByteStream& os) { - RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1); - os.Put(0xFFu); os.Put(0xFEu); - } - - template - 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 -struct UTF16BE : UTF16 { - template - 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 - 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 - static void PutBOM(OutputByteStream& os) { - RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1); - os.Put(0xFEu); os.Put(0xFFu); - } - - template - 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 -struct UTF32 { - typedef CharType Ch; - RAPIDJSON_STATIC_ASSERT(sizeof(Ch) >= 4); - - enum { supportUnicode = 1 }; - - template - static void Encode(OutputStream& os, unsigned codepoint) { - RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputStream::Ch) >= 4); - RAPIDJSON_ASSERT(codepoint <= 0x10FFFF); - os.Put(codepoint); - } - - template - 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 - 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 -struct UTF32LE : UTF32 { - template - 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 - 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 - 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 - 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 -struct UTF32BE : UTF32 { - template - 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 - 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 - 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 - 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 -struct ASCII { - typedef CharType Ch; - - enum { supportUnicode = 0 }; - - template - static void Encode(OutputStream& os, unsigned codepoint) { - RAPIDJSON_ASSERT(codepoint <= 0x7F); - os.Put(static_cast(codepoint & 0xFF)); - } - - template - static bool Decode(InputStream& is, unsigned* codepoint) { - unsigned char c = static_cast(is.Take()); - *codepoint = c; - return c <= 0X7F; - } - - template - static bool Validate(InputStream& is, OutputStream& os) { - unsigned char c = is.Take(); - os.Put(c); - return c <= 0x7F; - } - - template - static CharType TakeBOM(InputByteStream& is) { - RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1); - Ch c = Take(is); - return c; - } - - template - static Ch Take(InputByteStream& is) { - RAPIDJSON_STATIC_ASSERT(sizeof(typename InputByteStream::Ch) == 1); - return is.Take(); - } - - template - static void PutBOM(OutputByteStream& os) { - RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1); - (void)os; - } - - template - static void Put(OutputByteStream& os, Ch c) { - RAPIDJSON_STATIC_ASSERT(sizeof(typename OutputByteStream::Ch) == 1); - os.Put(static_cast(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 -struct AutoUTF { - typedef CharType Ch; - - enum { supportUnicode = 1 }; - -#define RAPIDJSON_ENCODINGS_FUNC(x) UTF8::x, UTF16LE::x, UTF16BE::x, UTF32LE::x, UTF32BE::x - - template - 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 - 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 - 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 -struct Transcoder { - //! Take one Unicode codepoint from source encoding, convert it to target encoding and put it to the output stream. - template - 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 - 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 -struct Transcoder { - template - 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 - 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/lib/rapidjson/error/en.h b/lib/rapidjson/error/en.h deleted file mode 100644 index d5f9caa..0000000 --- a/lib/rapidjson/error/en.h +++ /dev/null @@ -1,65 +0,0 @@ -// 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_ERROR_EN_H__ -#define RAPIDJSON_ERROR_EN_H__ - -#include "error.h" - -RAPIDJSON_NAMESPACE_BEGIN - -//! Maps error code of parsing into error message. -/*! - \ingroup RAPIDJSON_ERRORS - \param parseErrorCode Error code obtained in parsing. - \return the error message. - \note User can make a copy of this function for localization. - Using switch-case is safer for future modification of error codes. -*/ -inline const RAPIDJSON_ERROR_CHARTYPE* GetParseError_En(ParseErrorCode parseErrorCode) { - switch (parseErrorCode) { - case kParseErrorNone: return RAPIDJSON_ERROR_STRING("No error."); - - case kParseErrorDocumentEmpty: return RAPIDJSON_ERROR_STRING("The document is empty."); - case kParseErrorDocumentRootNotSingular: return RAPIDJSON_ERROR_STRING("The document root must not follow by other values."); - - case kParseErrorValueInvalid: return RAPIDJSON_ERROR_STRING("Invalid value."); - - case kParseErrorObjectMissName: return RAPIDJSON_ERROR_STRING("Missing a name for object member."); - case kParseErrorObjectMissColon: return RAPIDJSON_ERROR_STRING("Missing a colon after a name of object member."); - case kParseErrorObjectMissCommaOrCurlyBracket: return RAPIDJSON_ERROR_STRING("Missing a comma or '}' after an object member."); - - case kParseErrorArrayMissCommaOrSquareBracket: return RAPIDJSON_ERROR_STRING("Missing a comma or ']' after an array element."); - - case kParseErrorStringUnicodeEscapeInvalidHex: return RAPIDJSON_ERROR_STRING("Incorrect hex digit after \\u escape in string."); - case kParseErrorStringUnicodeSurrogateInvalid: return RAPIDJSON_ERROR_STRING("The surrogate pair in string is invalid."); - case kParseErrorStringEscapeInvalid: return RAPIDJSON_ERROR_STRING("Invalid escape character in string."); - case kParseErrorStringMissQuotationMark: return RAPIDJSON_ERROR_STRING("Missing a closing quotation mark in string."); - case kParseErrorStringInvalidEncoding: return RAPIDJSON_ERROR_STRING("Invalid encoding in string."); - - case kParseErrorNumberTooBig: return RAPIDJSON_ERROR_STRING("Number too big to be stored in double."); - case kParseErrorNumberMissFraction: return RAPIDJSON_ERROR_STRING("Miss fraction part in number."); - case kParseErrorNumberMissExponent: return RAPIDJSON_ERROR_STRING("Miss exponent in number."); - - case kParseErrorTermination: return RAPIDJSON_ERROR_STRING("Terminate parsing due to Handler error."); - case kParseErrorUnspecificSyntaxError: return RAPIDJSON_ERROR_STRING("Unspecific syntax error."); - - default: - return RAPIDJSON_ERROR_STRING("Unknown error."); - } -} - -RAPIDJSON_NAMESPACE_END - -#endif // RAPIDJSON_ERROR_EN_H__ diff --git a/lib/rapidjson/error/error.h b/lib/rapidjson/error/error.h deleted file mode 100644 index f9094fb..0000000 --- a/lib/rapidjson/error/error.h +++ /dev/null @@ -1,146 +0,0 @@ -// 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_ERROR_ERROR_H__ -#define RAPIDJSON_ERROR_ERROR_H__ - -#include "../rapidjson.h" - -/*! \file error.h */ - -/*! \defgroup RAPIDJSON_ERRORS RapidJSON error handling */ - -/////////////////////////////////////////////////////////////////////////////// -// RAPIDJSON_ERROR_CHARTYPE - -//! Character type of error messages. -/*! \ingroup RAPIDJSON_ERRORS - The default character type is \c char. - On Windows, user can define this macro as \c TCHAR for supporting both - unicode/non-unicode settings. -*/ -#ifndef RAPIDJSON_ERROR_CHARTYPE -#define RAPIDJSON_ERROR_CHARTYPE char -#endif - -/////////////////////////////////////////////////////////////////////////////// -// RAPIDJSON_ERROR_STRING - -//! Macro for converting string literial to \ref RAPIDJSON_ERROR_CHARTYPE[]. -/*! \ingroup RAPIDJSON_ERRORS - By default this conversion macro does nothing. - On Windows, user can define this macro as \c _T(x) for supporting both - unicode/non-unicode settings. -*/ -#ifndef RAPIDJSON_ERROR_STRING -#define RAPIDJSON_ERROR_STRING(x) x -#endif - -RAPIDJSON_NAMESPACE_BEGIN - -/////////////////////////////////////////////////////////////////////////////// -// ParseErrorCode - -//! Error code of parsing. -/*! \ingroup RAPIDJSON_ERRORS - \see GenericReader::Parse, GenericReader::GetParseErrorCode -*/ -enum ParseErrorCode { - kParseErrorNone = 0, //!< No error. - - kParseErrorDocumentEmpty, //!< The document is empty. - kParseErrorDocumentRootNotSingular, //!< The document root must not follow by other values. - - kParseErrorValueInvalid, //!< Invalid value. - - kParseErrorObjectMissName, //!< Missing a name for object member. - kParseErrorObjectMissColon, //!< Missing a colon after a name of object member. - kParseErrorObjectMissCommaOrCurlyBracket, //!< Missing a comma or '}' after an object member. - - kParseErrorArrayMissCommaOrSquareBracket, //!< Missing a comma or ']' after an array element. - - kParseErrorStringUnicodeEscapeInvalidHex, //!< Incorrect hex digit after \\u escape in string. - kParseErrorStringUnicodeSurrogateInvalid, //!< The surrogate pair in string is invalid. - kParseErrorStringEscapeInvalid, //!< Invalid escape character in string. - kParseErrorStringMissQuotationMark, //!< Missing a closing quotation mark in string. - kParseErrorStringInvalidEncoding, //!< Invalid encoding in string. - - kParseErrorNumberTooBig, //!< Number too big to be stored in double. - kParseErrorNumberMissFraction, //!< Miss fraction part in number. - kParseErrorNumberMissExponent, //!< Miss exponent in number. - - kParseErrorTermination, //!< Parsing was terminated. - kParseErrorUnspecificSyntaxError //!< Unspecific syntax error. -}; - -//! Result of parsing (wraps ParseErrorCode) -/*! - \ingroup RAPIDJSON_ERRORS - \code - Document doc; - ParseResult ok = doc.Parse("[42]"); - if (!ok) { - fprintf(stderr, "JSON parse error: %s (%u)", - GetParseError_En(ok.Code()), ok.Offset()); - exit(EXIT_FAILURE); - } - \endcode - \see GenericReader::Parse, GenericDocument::Parse -*/ -struct ParseResult { - - //! Default constructor, no error. - ParseResult() : code_(kParseErrorNone), offset_(0) {} - //! Constructor to set an error. - ParseResult(ParseErrorCode code, size_t offset) : code_(code), offset_(offset) {} - - //! Get the error code. - ParseErrorCode Code() const { return code_; } - //! Get the error offset, if \ref IsError(), 0 otherwise. - size_t Offset() const { return offset_; } - - //! Conversion to \c bool, returns \c true, iff !\ref IsError(). - operator bool() const { return !IsError(); } - //! Whether the result is an error. - bool IsError() const { return code_ != kParseErrorNone; } - - bool operator==(const ParseResult& that) const { return code_ == that.code_; } - bool operator==(ParseErrorCode code) const { return code_ == code; } - friend bool operator==(ParseErrorCode code, const ParseResult & err) { return code == err.code_; } - - //! Reset error code. - void Clear() { Set(kParseErrorNone); } - //! Update error code and offset. - void Set(ParseErrorCode code, size_t offset = 0) { code_ = code; offset_ = offset; } - -private: - ParseErrorCode code_; - size_t offset_; -}; - -//! Function pointer type of GetParseError(). -/*! \ingroup RAPIDJSON_ERRORS - - This is the prototype for \c GetParseError_X(), where \c X is a locale. - User can dynamically change locale in runtime, e.g.: -\code - GetParseErrorFunc GetParseError = GetParseError_En; // or whatever - const RAPIDJSON_ERROR_CHARTYPE* s = GetParseError(document.GetParseErrorCode()); -\endcode -*/ -typedef const RAPIDJSON_ERROR_CHARTYPE* (*GetParseErrorFunc)(ParseErrorCode); - -RAPIDJSON_NAMESPACE_END - -#endif // RAPIDJSON_ERROR_ERROR_H__ diff --git a/lib/rapidjson/filereadstream.h b/lib/rapidjson/filereadstream.h deleted file mode 100644 index 3913eb7..0000000 --- a/lib/rapidjson/filereadstream.h +++ /dev/null @@ -1,88 +0,0 @@ -// 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 - -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(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/lib/rapidjson/filewritestream.h b/lib/rapidjson/filewritestream.h deleted file mode 100644 index afd7e19..0000000 --- a/lib/rapidjson/filewritestream.h +++ /dev/null @@ -1,95 +0,0 @@ -// 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 - -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(bufferEnd_ - current_); - while (n > avail) { - std::memset(current_, c, avail); - current_ += avail; - Flush(); - n -= avail; - avail = static_cast(bufferEnd_ - current_); - } - - if (n > 0) { - std::memset(current_, c, n); - current_ += n; - } - } - - void Flush() { - if (current_ != buffer_) { - size_t result = fwrite(buffer_, 1, static_cast(current_ - buffer_), fp_); - if (result < static_cast(current_ - buffer_)) { - // failure deliberately ignored at this time - // added to avoid warn_unused_result build errors - } - 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/lib/rapidjson/internal/biginteger.h b/lib/rapidjson/internal/biginteger.h deleted file mode 100644 index 4477cf5..0000000 --- a/lib/rapidjson/internal/biginteger.h +++ /dev/null @@ -1,290 +0,0 @@ -// 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_BIGINTEGER_H_ -#define RAPIDJSON_BIGINTEGER_H_ - -#include "../rapidjson.h" - -#if defined(_MSC_VER) && defined(_M_AMD64) -#include // for _umul128 -#pragma intrinsic(_umul128) -#endif - -RAPIDJSON_NAMESPACE_BEGIN -namespace internal { - -class BigInteger { -public: - typedef uint64_t Type; - - BigInteger(const BigInteger& rhs) : count_(rhs.count_) { - std::memcpy(digits_, rhs.digits_, count_ * sizeof(Type)); - } - - explicit BigInteger(uint64_t u) : count_(1) { - digits_[0] = u; - } - - BigInteger(const char* decimals, size_t length) : count_(1) { - RAPIDJSON_ASSERT(length > 0); - digits_[0] = 0; - size_t i = 0; - const size_t kMaxDigitPerIteration = 19; // 2^64 = 18446744073709551616 > 10^19 - while (length >= kMaxDigitPerIteration) { - AppendDecimal64(decimals + i, decimals + i + kMaxDigitPerIteration); - length -= kMaxDigitPerIteration; - i += kMaxDigitPerIteration; - } - - if (length > 0) - AppendDecimal64(decimals + i, decimals + i + length); - } - - BigInteger& operator=(const BigInteger &rhs) - { - if (this != &rhs) { - count_ = rhs.count_; - std::memcpy(digits_, rhs.digits_, count_ * sizeof(Type)); - } - return *this; - } - - BigInteger& operator=(uint64_t u) { - digits_[0] = u; - count_ = 1; - return *this; - } - - BigInteger& operator+=(uint64_t u) { - Type backup = digits_[0]; - digits_[0] += u; - for (size_t i = 0; i < count_ - 1; i++) { - if (digits_[i] >= backup) - return *this; // no carry - backup = digits_[i + 1]; - digits_[i + 1] += 1; - } - - // Last carry - if (digits_[count_ - 1] < backup) - PushBack(1); - - return *this; - } - - BigInteger& operator*=(uint64_t u) { - if (u == 0) return *this = 0; - if (u == 1) return *this; - if (*this == 1) return *this = u; - - uint64_t k = 0; - for (size_t i = 0; i < count_; i++) { - uint64_t hi; - digits_[i] = MulAdd64(digits_[i], u, k, &hi); - k = hi; - } - - if (k > 0) - PushBack(k); - - return *this; - } - - BigInteger& operator*=(uint32_t u) { - if (u == 0) return *this = 0; - if (u == 1) return *this; - if (*this == 1) return *this = u; - - uint64_t k = 0; - for (size_t i = 0; i < count_; i++) { - const uint64_t c = digits_[i] >> 32; - const uint64_t d = digits_[i] & 0xFFFFFFFF; - const uint64_t uc = u * c; - const uint64_t ud = u * d; - const uint64_t p0 = ud + k; - const uint64_t p1 = uc + (p0 >> 32); - digits_[i] = (p0 & 0xFFFFFFFF) | (p1 << 32); - k = p1 >> 32; - } - - if (k > 0) - PushBack(k); - - return *this; - } - - BigInteger& operator<<=(size_t shift) { - if (IsZero() || shift == 0) return *this; - - size_t offset = shift / kTypeBit; - size_t interShift = shift % kTypeBit; - RAPIDJSON_ASSERT(count_ + offset <= kCapacity); - - if (interShift == 0) { - std::memmove(&digits_[count_ - 1 + offset], &digits_[count_ - 1], count_ * sizeof(Type)); - count_ += offset; - } - else { - digits_[count_] = 0; - for (size_t i = count_; i > 0; i--) - digits_[i + offset] = (digits_[i] << interShift) | (digits_[i - 1] >> (kTypeBit - interShift)); - digits_[offset] = digits_[0] << interShift; - count_ += offset; - if (digits_[count_]) - count_++; - } - - std::memset(digits_, 0, offset * sizeof(Type)); - - return *this; - } - - bool operator==(const BigInteger& rhs) const { - return count_ == rhs.count_ && std::memcmp(digits_, rhs.digits_, count_ * sizeof(Type)) == 0; - } - - bool operator==(const Type rhs) const { - return count_ == 1 && digits_[0] == rhs; - } - - BigInteger& MultiplyPow5(unsigned exp) { - static const uint32_t kPow5[12] = { - 5, - 5 * 5, - 5 * 5 * 5, - 5 * 5 * 5 * 5, - 5 * 5 * 5 * 5 * 5, - 5 * 5 * 5 * 5 * 5 * 5, - 5 * 5 * 5 * 5 * 5 * 5 * 5, - 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5, - 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5, - 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5, - 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5, - 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 - }; - if (exp == 0) return *this; - for (; exp >= 27; exp -= 27) *this *= RAPIDJSON_UINT64_C2(0X6765C793, 0XFA10079D); // 5^27 - for (; exp >= 13; exp -= 13) *this *= static_cast(1220703125u); // 5^13 - if (exp > 0) *this *= kPow5[exp - 1]; - return *this; - } - - // Compute absolute difference of this and rhs. - // Assume this != rhs - bool Difference(const BigInteger& rhs, BigInteger* out) const { - int cmp = Compare(rhs); - RAPIDJSON_ASSERT(cmp != 0); - const BigInteger *a, *b; // Makes a > b - bool ret; - if (cmp < 0) { a = &rhs; b = this; ret = true; } - else { a = this; b = &rhs; ret = false; } - - Type borrow = 0; - for (size_t i = 0; i < a->count_; i++) { - Type d = a->digits_[i] - borrow; - if (i < b->count_) - d -= b->digits_[i]; - borrow = (d > a->digits_[i]) ? 1 : 0; - out->digits_[i] = d; - if (d != 0) - out->count_ = i + 1; - } - - return ret; - } - - int Compare(const BigInteger& rhs) const { - if (count_ != rhs.count_) - return count_ < rhs.count_ ? -1 : 1; - - for (size_t i = count_; i-- > 0;) - if (digits_[i] != rhs.digits_[i]) - return digits_[i] < rhs.digits_[i] ? -1 : 1; - - return 0; - } - - size_t GetCount() const { return count_; } - Type GetDigit(size_t index) const { RAPIDJSON_ASSERT(index < count_); return digits_[index]; } - bool IsZero() const { return count_ == 1 && digits_[0] == 0; } - -private: - void AppendDecimal64(const char* begin, const char* end) { - uint64_t u = ParseUint64(begin, end); - if (IsZero()) - *this = u; - else { - unsigned exp = static_cast(end - begin); - (MultiplyPow5(exp) <<= exp) += u; // *this = *this * 10^exp + u - } - } - - void PushBack(Type digit) { - RAPIDJSON_ASSERT(count_ < kCapacity); - digits_[count_++] = digit; - } - - static uint64_t ParseUint64(const char* begin, const char* end) { - uint64_t r = 0; - for (const char* p = begin; p != end; ++p) { - RAPIDJSON_ASSERT(*p >= '0' && *p <= '9'); - r = r * 10u + (unsigned)(*p - '0'); - } - return r; - } - - // Assume a * b + k < 2^128 - static uint64_t MulAdd64(uint64_t a, uint64_t b, uint64_t k, uint64_t* outHigh) { -#if defined(_MSC_VER) && defined(_M_AMD64) - uint64_t low = _umul128(a, b, outHigh) + k; - if (low < k) - (*outHigh)++; - return low; -#elif (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)) && defined(__x86_64__) - __extension__ typedef unsigned __int128 uint128; - uint128 p = static_cast(a) * static_cast(b); - p += k; - *outHigh = static_cast(p >> 64); - return static_cast(p); -#else - const uint64_t a0 = a & 0xFFFFFFFF, a1 = a >> 32, b0 = b & 0xFFFFFFFF, b1 = b >> 32; - uint64_t x0 = a0 * b0, x1 = a0 * b1, x2 = a1 * b0, x3 = a1 * b1; - x1 += (x0 >> 32); // can't give carry - x1 += x2; - if (x1 < x2) - x3 += (static_cast(1) << 32); - uint64_t lo = (x1 << 32) + (x0 & 0xFFFFFFFF); - uint64_t hi = x3 + (x1 >> 32); - - lo += k; - if (lo < k) - hi++; - *outHigh = hi; - return lo; -#endif - } - - static const size_t kBitCount = 3328; // 64bit * 54 > 10^1000 - static const size_t kCapacity = kBitCount / sizeof(Type); - static const size_t kTypeBit = sizeof(Type) * 8; - - Type digits_[kCapacity]; - size_t count_; -}; - -} // namespace internal -RAPIDJSON_NAMESPACE_END - -#endif // RAPIDJSON_BIGINTEGER_H_ diff --git a/lib/rapidjson/internal/diyfp.h b/lib/rapidjson/internal/diyfp.h deleted file mode 100644 index 7a55ee3..0000000 --- a/lib/rapidjson/internal/diyfp.h +++ /dev/null @@ -1,248 +0,0 @@ -// 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. - -// This is a C++ header-only implementation of Grisu2 algorithm from the publication: -// Loitsch, Florian. "Printing floating-point numbers quickly and accurately with -// integers." ACM Sigplan Notices 45.6 (2010): 233-243. - -#ifndef RAPIDJSON_DIYFP_H_ -#define RAPIDJSON_DIYFP_H_ - -#include "../rapidjson.h" - -#if defined(_MSC_VER) && defined(_M_AMD64) -#include -#pragma intrinsic(_BitScanReverse64) -#pragma intrinsic(_umul128) -#endif - -RAPIDJSON_NAMESPACE_BEGIN -namespace internal { - -#ifdef __GNUC__ -RAPIDJSON_DIAG_PUSH -RAPIDJSON_DIAG_OFF(effc++) -#endif - -struct DiyFp { - DiyFp() {} - - DiyFp(uint64_t fp, int exp) : f(fp), e(exp) {} - - explicit DiyFp(double d) { - union { - double d; - uint64_t u64; - } u = { d }; - - int biased_e = static_cast((u.u64 & kDpExponentMask) >> kDpSignificandSize); - uint64_t significand = (u.u64 & kDpSignificandMask); - if (biased_e != 0) { - f = significand + kDpHiddenBit; - e = biased_e - kDpExponentBias; - } - else { - f = significand; - e = kDpMinExponent + 1; - } - } - - DiyFp operator-(const DiyFp& rhs) const { - return DiyFp(f - rhs.f, e); - } - - DiyFp operator*(const DiyFp& rhs) const { -#if defined(_MSC_VER) && defined(_M_AMD64) - uint64_t h; - uint64_t l = _umul128(f, rhs.f, &h); - if (l & (uint64_t(1) << 63)) // rounding - h++; - return DiyFp(h, e + rhs.e + 64); -#elif (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)) && defined(__x86_64__) - __extension__ typedef unsigned __int128 uint128; - uint128 p = static_cast(f) * static_cast(rhs.f); - uint64_t h = static_cast(p >> 64); - uint64_t l = static_cast(p); - if (l & (uint64_t(1) << 63)) // rounding - h++; - return DiyFp(h, e + rhs.e + 64); -#else - const uint64_t M32 = 0xFFFFFFFF; - const uint64_t a = f >> 32; - const uint64_t b = f & M32; - const uint64_t c = rhs.f >> 32; - const uint64_t d = rhs.f & M32; - const uint64_t ac = a * c; - const uint64_t bc = b * c; - const uint64_t ad = a * d; - const uint64_t bd = b * d; - uint64_t tmp = (bd >> 32) + (ad & M32) + (bc & M32); - tmp += 1U << 31; /// mult_round - return DiyFp(ac + (ad >> 32) + (bc >> 32) + (tmp >> 32), e + rhs.e + 64); -#endif - } - - DiyFp Normalize() const { -#if defined(_MSC_VER) && defined(_M_AMD64) - unsigned long index; - _BitScanReverse64(&index, f); - return DiyFp(f << (63 - index), e - (63 - index)); -#elif defined(__GNUC__) && __GNUC__ >= 4 - int s = __builtin_clzll(f); - return DiyFp(f << s, e - s); -#else - DiyFp res = *this; - while (!(res.f & (static_cast(1) << 63))) { - res.f <<= 1; - res.e--; - } - return res; -#endif - } - - DiyFp NormalizeBoundary() const { - DiyFp res = *this; - while (!(res.f & (kDpHiddenBit << 1))) { - res.f <<= 1; - res.e--; - } - res.f <<= (kDiySignificandSize - kDpSignificandSize - 2); - res.e = res.e - (kDiySignificandSize - kDpSignificandSize - 2); - return res; - } - - void NormalizedBoundaries(DiyFp* minus, DiyFp* plus) const { - DiyFp pl = DiyFp((f << 1) + 1, e - 1).NormalizeBoundary(); - DiyFp mi = (f == kDpHiddenBit) ? DiyFp((f << 2) - 1, e - 2) : DiyFp((f << 1) - 1, e - 1); - mi.f <<= mi.e - pl.e; - mi.e = pl.e; - *plus = pl; - *minus = mi; - } - - double ToDouble() const { - union { - double d; - uint64_t u64; - }u; - const uint64_t be = (e == kDpDenormalExponent && (f & kDpHiddenBit) == 0) ? 0 : - static_cast(e + kDpExponentBias); - u.u64 = (f & kDpSignificandMask) | (be << kDpSignificandSize); - return u.d; - } - - static const int kDiySignificandSize = 64; - static const int kDpSignificandSize = 52; - static const int kDpExponentBias = 0x3FF + kDpSignificandSize; - static const int kDpMaxExponent = 0x7FF - kDpExponentBias; - static const int kDpMinExponent = -kDpExponentBias; - static const int kDpDenormalExponent = -kDpExponentBias + 1; - static const uint64_t kDpExponentMask = RAPIDJSON_UINT64_C2(0x7FF00000, 0x00000000); - static const uint64_t kDpSignificandMask = RAPIDJSON_UINT64_C2(0x000FFFFF, 0xFFFFFFFF); - static const uint64_t kDpHiddenBit = RAPIDJSON_UINT64_C2(0x00100000, 0x00000000); - - uint64_t f; - int e; -}; - -inline DiyFp GetCachedPowerByIndex(size_t index) { - // 10^-348, 10^-340, ..., 10^340 - static const uint64_t kCachedPowers_F[] = { - RAPIDJSON_UINT64_C2(0xfa8fd5a0, 0x081c0288), RAPIDJSON_UINT64_C2(0xbaaee17f, 0xa23ebf76), - RAPIDJSON_UINT64_C2(0x8b16fb20, 0x3055ac76), RAPIDJSON_UINT64_C2(0xcf42894a, 0x5dce35ea), - RAPIDJSON_UINT64_C2(0x9a6bb0aa, 0x55653b2d), RAPIDJSON_UINT64_C2(0xe61acf03, 0x3d1a45df), - RAPIDJSON_UINT64_C2(0xab70fe17, 0xc79ac6ca), RAPIDJSON_UINT64_C2(0xff77b1fc, 0xbebcdc4f), - RAPIDJSON_UINT64_C2(0xbe5691ef, 0x416bd60c), RAPIDJSON_UINT64_C2(0x8dd01fad, 0x907ffc3c), - RAPIDJSON_UINT64_C2(0xd3515c28, 0x31559a83), RAPIDJSON_UINT64_C2(0x9d71ac8f, 0xada6c9b5), - RAPIDJSON_UINT64_C2(0xea9c2277, 0x23ee8bcb), RAPIDJSON_UINT64_C2(0xaecc4991, 0x4078536d), - RAPIDJSON_UINT64_C2(0x823c1279, 0x5db6ce57), RAPIDJSON_UINT64_C2(0xc2109436, 0x4dfb5637), - RAPIDJSON_UINT64_C2(0x9096ea6f, 0x3848984f), RAPIDJSON_UINT64_C2(0xd77485cb, 0x25823ac7), - RAPIDJSON_UINT64_C2(0xa086cfcd, 0x97bf97f4), RAPIDJSON_UINT64_C2(0xef340a98, 0x172aace5), - RAPIDJSON_UINT64_C2(0xb23867fb, 0x2a35b28e), RAPIDJSON_UINT64_C2(0x84c8d4df, 0xd2c63f3b), - RAPIDJSON_UINT64_C2(0xc5dd4427, 0x1ad3cdba), RAPIDJSON_UINT64_C2(0x936b9fce, 0xbb25c996), - RAPIDJSON_UINT64_C2(0xdbac6c24, 0x7d62a584), RAPIDJSON_UINT64_C2(0xa3ab6658, 0x0d5fdaf6), - RAPIDJSON_UINT64_C2(0xf3e2f893, 0xdec3f126), RAPIDJSON_UINT64_C2(0xb5b5ada8, 0xaaff80b8), - RAPIDJSON_UINT64_C2(0x87625f05, 0x6c7c4a8b), RAPIDJSON_UINT64_C2(0xc9bcff60, 0x34c13053), - RAPIDJSON_UINT64_C2(0x964e858c, 0x91ba2655), RAPIDJSON_UINT64_C2(0xdff97724, 0x70297ebd), - RAPIDJSON_UINT64_C2(0xa6dfbd9f, 0xb8e5b88f), RAPIDJSON_UINT64_C2(0xf8a95fcf, 0x88747d94), - RAPIDJSON_UINT64_C2(0xb9447093, 0x8fa89bcf), RAPIDJSON_UINT64_C2(0x8a08f0f8, 0xbf0f156b), - RAPIDJSON_UINT64_C2(0xcdb02555, 0x653131b6), RAPIDJSON_UINT64_C2(0x993fe2c6, 0xd07b7fac), - RAPIDJSON_UINT64_C2(0xe45c10c4, 0x2a2b3b06), RAPIDJSON_UINT64_C2(0xaa242499, 0x697392d3), - RAPIDJSON_UINT64_C2(0xfd87b5f2, 0x8300ca0e), RAPIDJSON_UINT64_C2(0xbce50864, 0x92111aeb), - RAPIDJSON_UINT64_C2(0x8cbccc09, 0x6f5088cc), RAPIDJSON_UINT64_C2(0xd1b71758, 0xe219652c), - RAPIDJSON_UINT64_C2(0x9c400000, 0x00000000), RAPIDJSON_UINT64_C2(0xe8d4a510, 0x00000000), - RAPIDJSON_UINT64_C2(0xad78ebc5, 0xac620000), RAPIDJSON_UINT64_C2(0x813f3978, 0xf8940984), - RAPIDJSON_UINT64_C2(0xc097ce7b, 0xc90715b3), RAPIDJSON_UINT64_C2(0x8f7e32ce, 0x7bea5c70), - RAPIDJSON_UINT64_C2(0xd5d238a4, 0xabe98068), RAPIDJSON_UINT64_C2(0x9f4f2726, 0x179a2245), - RAPIDJSON_UINT64_C2(0xed63a231, 0xd4c4fb27), RAPIDJSON_UINT64_C2(0xb0de6538, 0x8cc8ada8), - RAPIDJSON_UINT64_C2(0x83c7088e, 0x1aab65db), RAPIDJSON_UINT64_C2(0xc45d1df9, 0x42711d9a), - RAPIDJSON_UINT64_C2(0x924d692c, 0xa61be758), RAPIDJSON_UINT64_C2(0xda01ee64, 0x1a708dea), - RAPIDJSON_UINT64_C2(0xa26da399, 0x9aef774a), RAPIDJSON_UINT64_C2(0xf209787b, 0xb47d6b85), - RAPIDJSON_UINT64_C2(0xb454e4a1, 0x79dd1877), RAPIDJSON_UINT64_C2(0x865b8692, 0x5b9bc5c2), - RAPIDJSON_UINT64_C2(0xc83553c5, 0xc8965d3d), RAPIDJSON_UINT64_C2(0x952ab45c, 0xfa97a0b3), - RAPIDJSON_UINT64_C2(0xde469fbd, 0x99a05fe3), RAPIDJSON_UINT64_C2(0xa59bc234, 0xdb398c25), - RAPIDJSON_UINT64_C2(0xf6c69a72, 0xa3989f5c), RAPIDJSON_UINT64_C2(0xb7dcbf53, 0x54e9bece), - RAPIDJSON_UINT64_C2(0x88fcf317, 0xf22241e2), RAPIDJSON_UINT64_C2(0xcc20ce9b, 0xd35c78a5), - RAPIDJSON_UINT64_C2(0x98165af3, 0x7b2153df), RAPIDJSON_UINT64_C2(0xe2a0b5dc, 0x971f303a), - RAPIDJSON_UINT64_C2(0xa8d9d153, 0x5ce3b396), RAPIDJSON_UINT64_C2(0xfb9b7cd9, 0xa4a7443c), - RAPIDJSON_UINT64_C2(0xbb764c4c, 0xa7a44410), RAPIDJSON_UINT64_C2(0x8bab8eef, 0xb6409c1a), - RAPIDJSON_UINT64_C2(0xd01fef10, 0xa657842c), RAPIDJSON_UINT64_C2(0x9b10a4e5, 0xe9913129), - RAPIDJSON_UINT64_C2(0xe7109bfb, 0xa19c0c9d), RAPIDJSON_UINT64_C2(0xac2820d9, 0x623bf429), - RAPIDJSON_UINT64_C2(0x80444b5e, 0x7aa7cf85), RAPIDJSON_UINT64_C2(0xbf21e440, 0x03acdd2d), - RAPIDJSON_UINT64_C2(0x8e679c2f, 0x5e44ff8f), RAPIDJSON_UINT64_C2(0xd433179d, 0x9c8cb841), - RAPIDJSON_UINT64_C2(0x9e19db92, 0xb4e31ba9), RAPIDJSON_UINT64_C2(0xeb96bf6e, 0xbadf77d9), - RAPIDJSON_UINT64_C2(0xaf87023b, 0x9bf0ee6b) - }; - static const int16_t kCachedPowers_E[] = { - -1220, -1193, -1166, -1140, -1113, -1087, -1060, -1034, -1007, -980, - -954, -927, -901, -874, -847, -821, -794, -768, -741, -715, - -688, -661, -635, -608, -582, -555, -529, -502, -475, -449, - -422, -396, -369, -343, -316, -289, -263, -236, -210, -183, - -157, -130, -103, -77, -50, -24, 3, 30, 56, 83, - 109, 136, 162, 189, 216, 242, 269, 295, 322, 348, - 375, 402, 428, 455, 481, 508, 534, 561, 588, 614, - 641, 667, 694, 720, 747, 774, 800, 827, 853, 880, - 907, 933, 960, 986, 1013, 1039, 1066 - }; - return DiyFp(kCachedPowers_F[index], kCachedPowers_E[index]); -} - -inline DiyFp GetCachedPower(int e, int* K) { - - //int k = static_cast(ceil((-61 - e) * 0.30102999566398114)) + 374; - double dk = (-61 - e) * 0.30102999566398114 + 347; // dk must be positive, so can do ceiling in positive - int k = static_cast(dk); - if (dk - k > 0.0) - k++; - - unsigned index = static_cast((k >> 3) + 1); - *K = -(-348 + static_cast(index << 3)); // decimal exponent no need lookup table - - return GetCachedPowerByIndex(index); -} - -inline DiyFp GetCachedPower10(int exp, int *outExp) { - unsigned index = (static_cast(exp) + 348u) / 8u; - *outExp = -348 + static_cast(index) * 8; - return GetCachedPowerByIndex(index); - } - -#ifdef __GNUC__ -RAPIDJSON_DIAG_POP -#endif - -} // namespace internal -RAPIDJSON_NAMESPACE_END - -#endif // RAPIDJSON_DIYFP_H_ diff --git a/lib/rapidjson/internal/dtoa.h b/lib/rapidjson/internal/dtoa.h deleted file mode 100644 index d04ae21..0000000 --- a/lib/rapidjson/internal/dtoa.h +++ /dev/null @@ -1,217 +0,0 @@ -// 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. - -// This is a C++ header-only implementation of Grisu2 algorithm from the publication: -// Loitsch, Florian. "Printing floating-point numbers quickly and accurately with -// integers." ACM Sigplan Notices 45.6 (2010): 233-243. - -#ifndef RAPIDJSON_DTOA_ -#define RAPIDJSON_DTOA_ - -#include "itoa.h" // GetDigitsLut() -#include "diyfp.h" -#include "ieee754.h" - -RAPIDJSON_NAMESPACE_BEGIN -namespace internal { - -#ifdef __GNUC__ -RAPIDJSON_DIAG_PUSH -RAPIDJSON_DIAG_OFF(effc++) -#endif - -inline void GrisuRound(char* buffer, int len, uint64_t delta, uint64_t rest, uint64_t ten_kappa, uint64_t wp_w) { - while (rest < wp_w && delta - rest >= ten_kappa && - (rest + ten_kappa < wp_w || /// closer - wp_w - rest > rest + ten_kappa - wp_w)) { - buffer[len - 1]--; - rest += ten_kappa; - } -} - -inline unsigned CountDecimalDigit32(uint32_t n) { - // Simple pure C++ implementation was faster than __builtin_clz version in this situation. - if (n < 10) return 1; - if (n < 100) return 2; - if (n < 1000) return 3; - if (n < 10000) return 4; - if (n < 100000) return 5; - if (n < 1000000) return 6; - if (n < 10000000) return 7; - if (n < 100000000) return 8; - // Will not reach 10 digits in DigitGen() - //if (n < 1000000000) return 9; - //return 10; - return 9; -} - -inline void DigitGen(const DiyFp& W, const DiyFp& Mp, uint64_t delta, char* buffer, int* len, int* K) { - static const uint32_t kPow10[] = { 1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000, 1000000000 }; - const DiyFp one(uint64_t(1) << -Mp.e, Mp.e); - const DiyFp wp_w = Mp - W; - uint32_t p1 = static_cast(Mp.f >> -one.e); - uint64_t p2 = Mp.f & (one.f - 1); - unsigned kappa = CountDecimalDigit32(p1); // kappa in [0, 9] - *len = 0; - - while (kappa > 0) { - uint32_t d = 0; - switch (kappa) { - case 9: d = p1 / 100000000; p1 %= 100000000; break; - case 8: d = p1 / 10000000; p1 %= 10000000; break; - case 7: d = p1 / 1000000; p1 %= 1000000; break; - case 6: d = p1 / 100000; p1 %= 100000; break; - case 5: d = p1 / 10000; p1 %= 10000; break; - case 4: d = p1 / 1000; p1 %= 1000; break; - case 3: d = p1 / 100; p1 %= 100; break; - case 2: d = p1 / 10; p1 %= 10; break; - case 1: d = p1; p1 = 0; break; - default:; - } - if (d || *len) - buffer[(*len)++] = static_cast('0' + static_cast(d)); - kappa--; - uint64_t tmp = (static_cast(p1) << -one.e) + p2; - if (tmp <= delta) { - *K += kappa; - GrisuRound(buffer, *len, delta, tmp, static_cast(kPow10[kappa]) << -one.e, wp_w.f); - return; - } - } - - // kappa = 0 - for (;;) { - p2 *= 10; - delta *= 10; - char d = static_cast(p2 >> -one.e); - if (d || *len) - buffer[(*len)++] = static_cast('0' + d); - p2 &= one.f - 1; - kappa--; - if (p2 < delta) { - *K += kappa; - GrisuRound(buffer, *len, delta, p2, one.f, wp_w.f * kPow10[-static_cast(kappa)]); - return; - } - } -} - -inline void Grisu2(double value, char* buffer, int* length, int* K) { - const DiyFp v(value); - DiyFp w_m, w_p; - v.NormalizedBoundaries(&w_m, &w_p); - - const DiyFp c_mk = GetCachedPower(w_p.e, K); - const DiyFp W = v.Normalize() * c_mk; - DiyFp Wp = w_p * c_mk; - DiyFp Wm = w_m * c_mk; - Wm.f++; - Wp.f--; - DigitGen(W, Wp, Wp.f - Wm.f, buffer, length, K); -} - -inline char* WriteExponent(int K, char* buffer) { - if (K < 0) { - *buffer++ = '-'; - K = -K; - } - - if (K >= 100) { - *buffer++ = static_cast('0' + static_cast(K / 100)); - K %= 100; - const char* d = GetDigitsLut() + K * 2; - *buffer++ = d[0]; - *buffer++ = d[1]; - } - else if (K >= 10) { - const char* d = GetDigitsLut() + K * 2; - *buffer++ = d[0]; - *buffer++ = d[1]; - } - else - *buffer++ = static_cast('0' + static_cast(K)); - - return buffer; -} - -inline char* Prettify(char* buffer, int length, int k) { - const int kk = length + k; // 10^(kk-1) <= v < 10^kk - - if (length <= kk && kk <= 21) { - // 1234e7 -> 12340000000 - for (int i = length; i < kk; i++) - buffer[i] = '0'; - buffer[kk] = '.'; - buffer[kk + 1] = '0'; - return &buffer[kk + 2]; - } - else if (0 < kk && kk <= 21) { - // 1234e-2 -> 12.34 - std::memmove(&buffer[kk + 1], &buffer[kk], static_cast(length - kk)); - buffer[kk] = '.'; - return &buffer[length + 1]; - } - else if (-6 < kk && kk <= 0) { - // 1234e-6 -> 0.001234 - const int offset = 2 - kk; - std::memmove(&buffer[offset], &buffer[0], static_cast(length)); - buffer[0] = '0'; - buffer[1] = '.'; - for (int i = 2; i < offset; i++) - buffer[i] = '0'; - return &buffer[length + offset]; - } - else if (length == 1) { - // 1e30 - buffer[1] = 'e'; - return WriteExponent(kk - 1, &buffer[2]); - } - else { - // 1234e30 -> 1.234e33 - std::memmove(&buffer[2], &buffer[1], static_cast(length - 1)); - buffer[1] = '.'; - buffer[length + 1] = 'e'; - return WriteExponent(kk - 1, &buffer[0 + length + 2]); - } -} - -inline char* dtoa(double value, char* buffer) { - Double d(value); - if (d.IsZero()) { - if (d.Sign()) - *buffer++ = '-'; // -0.0, Issue #289 - buffer[0] = '0'; - buffer[1] = '.'; - buffer[2] = '0'; - return &buffer[3]; - } - else { - if (value < 0) { - *buffer++ = '-'; - value = -value; - } - int length, K; - Grisu2(value, buffer, &length, &K); - return Prettify(buffer, length, K); - } -} - -#ifdef __GNUC__ -RAPIDJSON_DIAG_POP -#endif - -} // namespace internal -RAPIDJSON_NAMESPACE_END - -#endif // RAPIDJSON_DTOA_ diff --git a/lib/rapidjson/internal/ieee754.h b/lib/rapidjson/internal/ieee754.h deleted file mode 100644 index 2fdaf54..0000000 --- a/lib/rapidjson/internal/ieee754.h +++ /dev/null @@ -1,77 +0,0 @@ -// 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_IEEE754_ -#define RAPIDJSON_IEEE754_ - -#include "../rapidjson.h" - -RAPIDJSON_NAMESPACE_BEGIN -namespace internal { - -class Double { -public: - Double() {} - Double(double d) : d_(d) {} - Double(uint64_t u) : u_(u) {} - - double Value() const { return d_; } - uint64_t Uint64Value() const { return u_; } - - double NextPositiveDouble() const { - RAPIDJSON_ASSERT(!Sign()); - return Double(u_ + 1).Value(); - } - - bool Sign() const { return (u_ & kSignMask) != 0; } - uint64_t Significand() const { return u_ & kSignificandMask; } - int Exponent() const { return static_cast(((u_ & kExponentMask) >> kSignificandSize) - kExponentBias); } - - bool IsNan() const { return (u_ & kExponentMask) == kExponentMask && Significand() != 0; } - bool IsInf() const { return (u_ & kExponentMask) == kExponentMask && Significand() == 0; } - bool IsNormal() const { return (u_ & kExponentMask) != 0 || Significand() == 0; } - bool IsZero() const { return (u_ & (kExponentMask | kSignificandMask)) == 0; } - - uint64_t IntegerSignificand() const { return IsNormal() ? Significand() | kHiddenBit : Significand(); } - int IntegerExponent() const { return (IsNormal() ? Exponent() : kDenormalExponent) - kSignificandSize; } - uint64_t ToBias() const { return (u_ & kSignMask) ? ~u_ + 1 : u_ | kSignMask; } - - static unsigned EffectiveSignificandSize(int order) { - if (order >= -1021) - return 53; - else if (order <= -1074) - return 0; - else - return (unsigned)order + 1074; - } - -private: - static const int kSignificandSize = 52; - static const int kExponentBias = 0x3FF; - static const int kDenormalExponent = 1 - kExponentBias; - static const uint64_t kSignMask = RAPIDJSON_UINT64_C2(0x80000000, 0x00000000); - static const uint64_t kExponentMask = RAPIDJSON_UINT64_C2(0x7FF00000, 0x00000000); - static const uint64_t kSignificandMask = RAPIDJSON_UINT64_C2(0x000FFFFF, 0xFFFFFFFF); - static const uint64_t kHiddenBit = RAPIDJSON_UINT64_C2(0x00100000, 0x00000000); - - union { - double d_; - uint64_t u_; - }; -}; - -} // namespace internal -RAPIDJSON_NAMESPACE_END - -#endif // RAPIDJSON_IEEE754_ diff --git a/lib/rapidjson/internal/itoa.h b/lib/rapidjson/internal/itoa.h deleted file mode 100644 index 01a4e7e..0000000 --- a/lib/rapidjson/internal/itoa.h +++ /dev/null @@ -1,304 +0,0 @@ -// 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_ITOA_ -#define RAPIDJSON_ITOA_ - -#include "../rapidjson.h" - -RAPIDJSON_NAMESPACE_BEGIN -namespace internal { - -inline const char* GetDigitsLut() { - static const char cDigitsLut[200] = { - '0','0','0','1','0','2','0','3','0','4','0','5','0','6','0','7','0','8','0','9', - '1','0','1','1','1','2','1','3','1','4','1','5','1','6','1','7','1','8','1','9', - '2','0','2','1','2','2','2','3','2','4','2','5','2','6','2','7','2','8','2','9', - '3','0','3','1','3','2','3','3','3','4','3','5','3','6','3','7','3','8','3','9', - '4','0','4','1','4','2','4','3','4','4','4','5','4','6','4','7','4','8','4','9', - '5','0','5','1','5','2','5','3','5','4','5','5','5','6','5','7','5','8','5','9', - '6','0','6','1','6','2','6','3','6','4','6','5','6','6','6','7','6','8','6','9', - '7','0','7','1','7','2','7','3','7','4','7','5','7','6','7','7','7','8','7','9', - '8','0','8','1','8','2','8','3','8','4','8','5','8','6','8','7','8','8','8','9', - '9','0','9','1','9','2','9','3','9','4','9','5','9','6','9','7','9','8','9','9' - }; - return cDigitsLut; -} - -inline char* u32toa(uint32_t value, char* buffer) { - const char* cDigitsLut = GetDigitsLut(); - - if (value < 10000) { - const uint32_t d1 = (value / 100) << 1; - const uint32_t d2 = (value % 100) << 1; - - if (value >= 1000) - *buffer++ = cDigitsLut[d1]; - if (value >= 100) - *buffer++ = cDigitsLut[d1 + 1]; - if (value >= 10) - *buffer++ = cDigitsLut[d2]; - *buffer++ = cDigitsLut[d2 + 1]; - } - else if (value < 100000000) { - // value = bbbbcccc - const uint32_t b = value / 10000; - const uint32_t c = value % 10000; - - const uint32_t d1 = (b / 100) << 1; - const uint32_t d2 = (b % 100) << 1; - - const uint32_t d3 = (c / 100) << 1; - const uint32_t d4 = (c % 100) << 1; - - if (value >= 10000000) - *buffer++ = cDigitsLut[d1]; - if (value >= 1000000) - *buffer++ = cDigitsLut[d1 + 1]; - if (value >= 100000) - *buffer++ = cDigitsLut[d2]; - *buffer++ = cDigitsLut[d2 + 1]; - - *buffer++ = cDigitsLut[d3]; - *buffer++ = cDigitsLut[d3 + 1]; - *buffer++ = cDigitsLut[d4]; - *buffer++ = cDigitsLut[d4 + 1]; - } - else { - // value = aabbbbcccc in decimal - - const uint32_t a = value / 100000000; // 1 to 42 - value %= 100000000; - - if (a >= 10) { - const unsigned i = a << 1; - *buffer++ = cDigitsLut[i]; - *buffer++ = cDigitsLut[i + 1]; - } - else - *buffer++ = static_cast('0' + static_cast(a)); - - const uint32_t b = value / 10000; // 0 to 9999 - const uint32_t c = value % 10000; // 0 to 9999 - - const uint32_t d1 = (b / 100) << 1; - const uint32_t d2 = (b % 100) << 1; - - const uint32_t d3 = (c / 100) << 1; - const uint32_t d4 = (c % 100) << 1; - - *buffer++ = cDigitsLut[d1]; - *buffer++ = cDigitsLut[d1 + 1]; - *buffer++ = cDigitsLut[d2]; - *buffer++ = cDigitsLut[d2 + 1]; - *buffer++ = cDigitsLut[d3]; - *buffer++ = cDigitsLut[d3 + 1]; - *buffer++ = cDigitsLut[d4]; - *buffer++ = cDigitsLut[d4 + 1]; - } - return buffer; -} - -inline char* i32toa(int32_t value, char* buffer) { - uint32_t u = static_cast(value); - if (value < 0) { - *buffer++ = '-'; - u = ~u + 1; - } - - return u32toa(u, buffer); -} - -inline char* u64toa(uint64_t value, char* buffer) { - const char* cDigitsLut = GetDigitsLut(); - const uint64_t kTen8 = 100000000; - const uint64_t kTen9 = kTen8 * 10; - const uint64_t kTen10 = kTen8 * 100; - const uint64_t kTen11 = kTen8 * 1000; - const uint64_t kTen12 = kTen8 * 10000; - const uint64_t kTen13 = kTen8 * 100000; - const uint64_t kTen14 = kTen8 * 1000000; - const uint64_t kTen15 = kTen8 * 10000000; - const uint64_t kTen16 = kTen8 * kTen8; - - if (value < kTen8) { - uint32_t v = static_cast(value); - if (v < 10000) { - const uint32_t d1 = (v / 100) << 1; - const uint32_t d2 = (v % 100) << 1; - - if (v >= 1000) - *buffer++ = cDigitsLut[d1]; - if (v >= 100) - *buffer++ = cDigitsLut[d1 + 1]; - if (v >= 10) - *buffer++ = cDigitsLut[d2]; - *buffer++ = cDigitsLut[d2 + 1]; - } - else { - // value = bbbbcccc - const uint32_t b = v / 10000; - const uint32_t c = v % 10000; - - const uint32_t d1 = (b / 100) << 1; - const uint32_t d2 = (b % 100) << 1; - - const uint32_t d3 = (c / 100) << 1; - const uint32_t d4 = (c % 100) << 1; - - if (value >= 10000000) - *buffer++ = cDigitsLut[d1]; - if (value >= 1000000) - *buffer++ = cDigitsLut[d1 + 1]; - if (value >= 100000) - *buffer++ = cDigitsLut[d2]; - *buffer++ = cDigitsLut[d2 + 1]; - - *buffer++ = cDigitsLut[d3]; - *buffer++ = cDigitsLut[d3 + 1]; - *buffer++ = cDigitsLut[d4]; - *buffer++ = cDigitsLut[d4 + 1]; - } - } - else if (value < kTen16) { - const uint32_t v0 = static_cast(value / kTen8); - const uint32_t v1 = static_cast(value % kTen8); - - const uint32_t b0 = v0 / 10000; - const uint32_t c0 = v0 % 10000; - - const uint32_t d1 = (b0 / 100) << 1; - const uint32_t d2 = (b0 % 100) << 1; - - const uint32_t d3 = (c0 / 100) << 1; - const uint32_t d4 = (c0 % 100) << 1; - - const uint32_t b1 = v1 / 10000; - const uint32_t c1 = v1 % 10000; - - const uint32_t d5 = (b1 / 100) << 1; - const uint32_t d6 = (b1 % 100) << 1; - - const uint32_t d7 = (c1 / 100) << 1; - const uint32_t d8 = (c1 % 100) << 1; - - if (value >= kTen15) - *buffer++ = cDigitsLut[d1]; - if (value >= kTen14) - *buffer++ = cDigitsLut[d1 + 1]; - if (value >= kTen13) - *buffer++ = cDigitsLut[d2]; - if (value >= kTen12) - *buffer++ = cDigitsLut[d2 + 1]; - if (value >= kTen11) - *buffer++ = cDigitsLut[d3]; - if (value >= kTen10) - *buffer++ = cDigitsLut[d3 + 1]; - if (value >= kTen9) - *buffer++ = cDigitsLut[d4]; - if (value >= kTen8) - *buffer++ = cDigitsLut[d4 + 1]; - - *buffer++ = cDigitsLut[d5]; - *buffer++ = cDigitsLut[d5 + 1]; - *buffer++ = cDigitsLut[d6]; - *buffer++ = cDigitsLut[d6 + 1]; - *buffer++ = cDigitsLut[d7]; - *buffer++ = cDigitsLut[d7 + 1]; - *buffer++ = cDigitsLut[d8]; - *buffer++ = cDigitsLut[d8 + 1]; - } - else { - const uint32_t a = static_cast(value / kTen16); // 1 to 1844 - value %= kTen16; - - if (a < 10) - *buffer++ = static_cast('0' + static_cast(a)); - else if (a < 100) { - const uint32_t i = a << 1; - *buffer++ = cDigitsLut[i]; - *buffer++ = cDigitsLut[i + 1]; - } - else if (a < 1000) { - *buffer++ = static_cast('0' + static_cast(a / 100)); - - const uint32_t i = (a % 100) << 1; - *buffer++ = cDigitsLut[i]; - *buffer++ = cDigitsLut[i + 1]; - } - else { - const uint32_t i = (a / 100) << 1; - const uint32_t j = (a % 100) << 1; - *buffer++ = cDigitsLut[i]; - *buffer++ = cDigitsLut[i + 1]; - *buffer++ = cDigitsLut[j]; - *buffer++ = cDigitsLut[j + 1]; - } - - const uint32_t v0 = static_cast(value / kTen8); - const uint32_t v1 = static_cast(value % kTen8); - - const uint32_t b0 = v0 / 10000; - const uint32_t c0 = v0 % 10000; - - const uint32_t d1 = (b0 / 100) << 1; - const uint32_t d2 = (b0 % 100) << 1; - - const uint32_t d3 = (c0 / 100) << 1; - const uint32_t d4 = (c0 % 100) << 1; - - const uint32_t b1 = v1 / 10000; - const uint32_t c1 = v1 % 10000; - - const uint32_t d5 = (b1 / 100) << 1; - const uint32_t d6 = (b1 % 100) << 1; - - const uint32_t d7 = (c1 / 100) << 1; - const uint32_t d8 = (c1 % 100) << 1; - - *buffer++ = cDigitsLut[d1]; - *buffer++ = cDigitsLut[d1 + 1]; - *buffer++ = cDigitsLut[d2]; - *buffer++ = cDigitsLut[d2 + 1]; - *buffer++ = cDigitsLut[d3]; - *buffer++ = cDigitsLut[d3 + 1]; - *buffer++ = cDigitsLut[d4]; - *buffer++ = cDigitsLut[d4 + 1]; - *buffer++ = cDigitsLut[d5]; - *buffer++ = cDigitsLut[d5 + 1]; - *buffer++ = cDigitsLut[d6]; - *buffer++ = cDigitsLut[d6 + 1]; - *buffer++ = cDigitsLut[d7]; - *buffer++ = cDigitsLut[d7 + 1]; - *buffer++ = cDigitsLut[d8]; - *buffer++ = cDigitsLut[d8 + 1]; - } - - return buffer; -} - -inline char* i64toa(int64_t value, char* buffer) { - uint64_t u = static_cast(value); - if (value < 0) { - *buffer++ = '-'; - u = ~u + 1; - } - - return u64toa(u, buffer); -} - -} // namespace internal -RAPIDJSON_NAMESPACE_END - -#endif // RAPIDJSON_ITOA_ diff --git a/lib/rapidjson/internal/meta.h b/lib/rapidjson/internal/meta.h deleted file mode 100644 index 5a9aaa4..0000000 --- a/lib/rapidjson/internal/meta.h +++ /dev/null @@ -1,181 +0,0 @@ -// 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_ - -#include "../rapidjson.h" - -#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 -#endif - -//@cond RAPIDJSON_INTERNAL -RAPIDJSON_NAMESPACE_BEGIN -namespace internal { - -// Helper to wrap/convert arbitrary types to void, useful for arbitrary type matching -template struct Void { typedef void Type; }; - -/////////////////////////////////////////////////////////////////////////////// -// BoolType, TrueType, FalseType -// -template struct BoolType { - static const bool Value = Cond; - typedef BoolType Type; -}; -typedef BoolType TrueType; -typedef BoolType FalseType; - - -/////////////////////////////////////////////////////////////////////////////// -// SelectIf, BoolExpr, NotExpr, AndExpr, OrExpr -// - -template struct SelectIfImpl { template struct Apply { typedef T1 Type; }; }; -template <> struct SelectIfImpl { template struct Apply { typedef T2 Type; }; }; -template struct SelectIfCond : SelectIfImpl::template Apply {}; -template struct SelectIf : SelectIfCond {}; - -template struct AndExprCond : FalseType {}; -template <> struct AndExprCond : TrueType {}; -template struct OrExprCond : TrueType {}; -template <> struct OrExprCond : FalseType {}; - -template struct BoolExpr : SelectIf::Type {}; -template struct NotExpr : SelectIf::Type {}; -template struct AndExpr : AndExprCond::Type {}; -template struct OrExpr : OrExprCond::Type {}; - - -/////////////////////////////////////////////////////////////////////////////// -// AddConst, MaybeAddConst, RemoveConst -template struct AddConst { typedef const T Type; }; -template struct MaybeAddConst : SelectIfCond {}; -template struct RemoveConst { typedef T Type; }; -template struct RemoveConst { typedef T Type; }; - - -/////////////////////////////////////////////////////////////////////////////// -// IsSame, IsConst, IsMoreConst, IsPointer -// -template struct IsSame : FalseType {}; -template struct IsSame : TrueType {}; - -template struct IsConst : FalseType {}; -template struct IsConst : TrueType {}; - -template -struct IsMoreConst - : AndExpr::Type, typename RemoveConst::Type>, - BoolType::Value >= IsConst::Value> >::Type {}; - -template struct IsPointer : FalseType {}; -template struct IsPointer : TrueType {}; - -/////////////////////////////////////////////////////////////////////////////// -// IsBaseOf -// -#if RAPIDJSON_HAS_CXX11_TYPETRAITS - -template struct IsBaseOf - : BoolType< ::std::is_base_of::value> {}; - -#else // simplified version adopted from Boost - -template struct IsBaseOfImpl { - RAPIDJSON_STATIC_ASSERT(sizeof(B) != 0); - RAPIDJSON_STATIC_ASSERT(sizeof(D) != 0); - - typedef char (&Yes)[1]; - typedef char (&No) [2]; - - template - 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 struct IsBaseOf - : OrExpr, BoolExpr > >::Type {}; - -#endif // RAPIDJSON_HAS_CXX11_TYPETRAITS - - -////////////////////////////////////////////////////////////////////////// -// EnableIf / DisableIf -// -template struct EnableIfCond { typedef T Type; }; -template struct EnableIfCond { /* empty */ }; - -template struct DisableIfCond { typedef T Type; }; -template struct DisableIfCond { /* empty */ }; - -template -struct EnableIf : EnableIfCond {}; - -template -struct DisableIf : DisableIfCond {}; - -// SFINAE helpers -struct SfinaeTag {}; -template struct RemoveSfinaeTag; -template struct RemoveSfinaeTag { 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 \ - ::Type * = NULL - -#define RAPIDJSON_DISABLEIF(cond) \ - typename ::RAPIDJSON_NAMESPACE::internal::DisableIf \ - ::Type * = NULL - -#define RAPIDJSON_ENABLEIF_RETURN(cond,returntype) \ - typename ::RAPIDJSON_NAMESPACE::internal::EnableIf \ - ::Type - -#define RAPIDJSON_DISABLEIF_RETURN(cond,returntype) \ - typename ::RAPIDJSON_NAMESPACE::internal::DisableIf \ - ::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/lib/rapidjson/internal/pow10.h b/lib/rapidjson/internal/pow10.h deleted file mode 100644 index 02f475d..0000000 --- a/lib/rapidjson/internal/pow10.h +++ /dev/null @@ -1,55 +0,0 @@ -// 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_ - -#include "../rapidjson.h" - -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/lib/rapidjson/internal/stack.h b/lib/rapidjson/internal/stack.h deleted file mode 100644 index a42388c..0000000 --- a/lib/rapidjson/internal/stack.h +++ /dev/null @@ -1,189 +0,0 @@ -// 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_ - -#include "../rapidjson.h" -#include "swap.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 -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 Swap(Stack& rhs) RAPIDJSON_NOEXCEPT { - internal::Swap(allocator_, rhs.allocator_); - internal::Swap(ownAllocator_, rhs.ownAllocator_); - internal::Swap(stack_, rhs.stack_); - internal::Swap(stackTop_, rhs.stackTop_); - internal::Swap(stackEnd_, rhs.stackEnd_); - internal::Swap(initialCapacity_, rhs.initialCapacity_); - } - - 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 - RAPIDJSON_FORCEINLINE T* Push(size_t count = 1) { - // Expand the stack if needed - if (stackTop_ + sizeof(T) * count >= stackEnd_) - Expand(count); - - T* ret = reinterpret_cast(stackTop_); - stackTop_ += sizeof(T) * count; - return ret; - } - - template - T* Pop(size_t count) { - RAPIDJSON_ASSERT(GetSize() >= count * sizeof(T)); - stackTop_ -= count * sizeof(T); - return reinterpret_cast(stackTop_); - } - - template - T* Top() { - RAPIDJSON_ASSERT(GetSize() >= sizeof(T)); - return reinterpret_cast(stackTop_ - sizeof(T)); - } - - template - T* Bottom() { return (T*)stack_; } - - Allocator& GetAllocator() { return *allocator_; } - bool Empty() const { return stackTop_ == stack_; } - size_t GetSize() const { return static_cast(stackTop_ - stack_); } - size_t GetCapacity() const { return static_cast(stackEnd_ - stack_); } - -private: - template - 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/lib/rapidjson/internal/strfunc.h b/lib/rapidjson/internal/strfunc.h deleted file mode 100644 index 8440506..0000000 --- a/lib/rapidjson/internal/strfunc.h +++ /dev/null @@ -1,39 +0,0 @@ -// 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_ - -#include "../rapidjson.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 -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/lib/rapidjson/internal/strtod.h b/lib/rapidjson/internal/strtod.h deleted file mode 100644 index a1b8211..0000000 --- a/lib/rapidjson/internal/strtod.h +++ /dev/null @@ -1,270 +0,0 @@ -// 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_STRTOD_ -#define RAPIDJSON_STRTOD_ - -#include "../rapidjson.h" -#include "ieee754.h" -#include "biginteger.h" -#include "diyfp.h" -#include "pow10.h" - -RAPIDJSON_NAMESPACE_BEGIN -namespace internal { - -inline double FastPath(double significand, int exp) { - if (exp < -308) - return 0.0; - else if (exp >= 0) - return significand * internal::Pow10(exp); - else - return significand / internal::Pow10(-exp); -} - -inline double StrtodNormalPrecision(double d, int p) { - if (p < -308) { - // Prevent expSum < -308, making Pow10(p) = 0 - d = FastPath(d, -308); - d = FastPath(d, p + 308); - } - else - d = FastPath(d, p); - return d; -} - -template -inline T Min3(T a, T b, T c) { - T m = a; - if (m > b) m = b; - if (m > c) m = c; - return m; -} - -inline int CheckWithinHalfULP(double b, const BigInteger& d, int dExp) { - const Double db(b); - const uint64_t bInt = db.IntegerSignificand(); - const int bExp = db.IntegerExponent(); - const int hExp = bExp - 1; - - int dS_Exp2 = 0, dS_Exp5 = 0, bS_Exp2 = 0, bS_Exp5 = 0, hS_Exp2 = 0, hS_Exp5 = 0; - - // Adjust for decimal exponent - if (dExp >= 0) { - dS_Exp2 += dExp; - dS_Exp5 += dExp; - } - else { - bS_Exp2 -= dExp; - bS_Exp5 -= dExp; - hS_Exp2 -= dExp; - hS_Exp5 -= dExp; - } - - // Adjust for binary exponent - if (bExp >= 0) - bS_Exp2 += bExp; - else { - dS_Exp2 -= bExp; - hS_Exp2 -= bExp; - } - - // Adjust for half ulp exponent - if (hExp >= 0) - hS_Exp2 += hExp; - else { - dS_Exp2 -= hExp; - bS_Exp2 -= hExp; - } - - // Remove common power of two factor from all three scaled values - int common_Exp2 = Min3(dS_Exp2, bS_Exp2, hS_Exp2); - dS_Exp2 -= common_Exp2; - bS_Exp2 -= common_Exp2; - hS_Exp2 -= common_Exp2; - - BigInteger dS = d; - dS.MultiplyPow5(static_cast(dS_Exp5)) <<= static_cast(dS_Exp2); - - BigInteger bS(bInt); - bS.MultiplyPow5(static_cast(bS_Exp5)) <<= static_cast(bS_Exp2); - - BigInteger hS(1); - hS.MultiplyPow5(static_cast(hS_Exp5)) <<= static_cast(hS_Exp2); - - BigInteger delta(0); - dS.Difference(bS, &delta); - - return delta.Compare(hS); -} - -inline bool StrtodFast(double d, int p, double* result) { - // Use fast path for string-to-double conversion if possible - // see http://www.exploringbinary.com/fast-path-decimal-to-floating-point-conversion/ - if (p > 22 && p < 22 + 16) { - // Fast Path Cases In Disguise - d *= internal::Pow10(p - 22); - p = 22; - } - - if (p >= -22 && p <= 22 && d <= 9007199254740991.0) { // 2^53 - 1 - *result = FastPath(d, p); - return true; - } - else - return false; -} - -// Compute an approximation and see if it is within 1/2 ULP -inline bool StrtodDiyFp(const char* decimals, size_t length, size_t decimalPosition, int exp, double* result) { - uint64_t significand = 0; - size_t i = 0; // 2^64 - 1 = 18446744073709551615, 1844674407370955161 = 0x1999999999999999 - for (; i < length; i++) { - if (significand > RAPIDJSON_UINT64_C2(0x19999999, 0x99999999) || - (significand == RAPIDJSON_UINT64_C2(0x19999999, 0x99999999) && decimals[i] > '5')) - break; - significand = significand * 10u + static_cast(decimals[i] - '0'); - } - - if (i < length && decimals[i] >= '5') // Rounding - significand++; - - size_t remaining = length - i; - const unsigned kUlpShift = 3; - const unsigned kUlp = 1 << kUlpShift; - int error = (remaining == 0) ? 0 : kUlp / 2; - - DiyFp v(significand, 0); - v = v.Normalize(); - error <<= -v.e; - - const int dExp = (int)decimalPosition - (int)i + exp; - - int actualExp; - DiyFp cachedPower = GetCachedPower10(dExp, &actualExp); - if (actualExp != dExp) { - static const DiyFp kPow10[] = { - DiyFp(RAPIDJSON_UINT64_C2(0xa0000000, 00000000), -60), // 10^1 - DiyFp(RAPIDJSON_UINT64_C2(0xc8000000, 00000000), -57), // 10^2 - DiyFp(RAPIDJSON_UINT64_C2(0xfa000000, 00000000), -54), // 10^3 - DiyFp(RAPIDJSON_UINT64_C2(0x9c400000, 00000000), -50), // 10^4 - DiyFp(RAPIDJSON_UINT64_C2(0xc3500000, 00000000), -47), // 10^5 - DiyFp(RAPIDJSON_UINT64_C2(0xf4240000, 00000000), -44), // 10^6 - DiyFp(RAPIDJSON_UINT64_C2(0x98968000, 00000000), -40) // 10^7 - }; - int adjustment = dExp - actualExp - 1; - RAPIDJSON_ASSERT(adjustment >= 0 && adjustment < 7); - v = v * kPow10[adjustment]; - if (length + static_cast(adjustment)> 19u) // has more digits than decimal digits in 64-bit - error += kUlp / 2; - } - - v = v * cachedPower; - - error += kUlp + (error == 0 ? 0 : 1); - - const int oldExp = v.e; - v = v.Normalize(); - error <<= oldExp - v.e; - - const unsigned effectiveSignificandSize = Double::EffectiveSignificandSize(64 + v.e); - unsigned precisionSize = 64 - effectiveSignificandSize; - if (precisionSize + kUlpShift >= 64) { - unsigned scaleExp = (precisionSize + kUlpShift) - 63; - v.f >>= scaleExp; - v.e += scaleExp; - error = (error >> scaleExp) + 1 + static_cast(kUlp); - precisionSize -= scaleExp; - } - - DiyFp rounded(v.f >> precisionSize, v.e + static_cast(precisionSize)); - const uint64_t precisionBits = (v.f & ((uint64_t(1) << precisionSize) - 1)) * kUlp; - const uint64_t halfWay = (uint64_t(1) << (precisionSize - 1)) * kUlp; - if (precisionBits >= halfWay + static_cast(error)) { - rounded.f++; - if (rounded.f & (DiyFp::kDpHiddenBit << 1)) { // rounding overflows mantissa (issue #340) - rounded.f >>= 1; - rounded.e++; - } - } - - *result = rounded.ToDouble(); - - return halfWay - static_cast(error) >= precisionBits || precisionBits >= halfWay + static_cast(error); -} - -inline double StrtodBigInteger(double approx, const char* decimals, size_t length, size_t decimalPosition, int exp) { - const BigInteger dInt(decimals, length); - const int dExp = (int)decimalPosition - (int)length + exp; - Double a(approx); - int cmp = CheckWithinHalfULP(a.Value(), dInt, dExp); - if (cmp < 0) - return a.Value(); // within half ULP - else if (cmp == 0) { - // Round towards even - if (a.Significand() & 1) - return a.NextPositiveDouble(); - else - return a.Value(); - } - else // adjustment - return a.NextPositiveDouble(); -} - -inline double StrtodFullPrecision(double d, int p, const char* decimals, size_t length, size_t decimalPosition, int exp) { - RAPIDJSON_ASSERT(d >= 0.0); - RAPIDJSON_ASSERT(length >= 1); - - double result; - if (StrtodFast(d, p, &result)) - return result; - - // Trim leading zeros - while (*decimals == '0' && length > 1) { - length--; - decimals++; - decimalPosition--; - } - - // Trim trailing zeros - while (decimals[length - 1] == '0' && length > 1) { - length--; - decimalPosition--; - exp++; - } - - // Trim right-most digits - const int kMaxDecimalDigit = 780; - if ((int)length > kMaxDecimalDigit) { - int delta = (int(length) - kMaxDecimalDigit); - exp += delta; - decimalPosition -= static_cast(delta); - length = kMaxDecimalDigit; - } - - // If too small, underflow to zero - if (int(length) + exp < -324) - return 0.0; - - if (StrtodDiyFp(decimals, length, decimalPosition, exp, &result)) - return result; - - // Use approximation from StrtodDiyFp and make adjustment with BigInteger comparison - return StrtodBigInteger(result, decimals, length, decimalPosition, exp); -} - -} // namespace internal -RAPIDJSON_NAMESPACE_END - -#endif // RAPIDJSON_STRTOD_ diff --git a/lib/rapidjson/internal/swap.h b/lib/rapidjson/internal/swap.h deleted file mode 100644 index 5b0eca8..0000000 --- a/lib/rapidjson/internal/swap.h +++ /dev/null @@ -1,37 +0,0 @@ -// 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_SWAP_H_ -#define RAPIDJSON_INTERNAL_SWAP_H_ - -#include "../rapidjson.h" - -RAPIDJSON_NAMESPACE_BEGIN -namespace internal { - -//! Custom swap() to avoid dependency on C++ header -/*! \tparam T Type of the arguments to swap, should be instantiated with primitive C++ types only. - \note This has the same semantics as std::swap(). -*/ -template -inline void Swap(T& a, T& b) RAPIDJSON_NOEXCEPT { - T tmp = a; - a = b; - b = tmp; -} - -} // namespace internal -RAPIDJSON_NAMESPACE_END - -#endif // RAPIDJSON_INTERNAL_SWAP_H_ diff --git a/lib/rapidjson/memorybuffer.h b/lib/rapidjson/memorybuffer.h deleted file mode 100644 index 2484b21..0000000 --- a/lib/rapidjson/memorybuffer.h +++ /dev/null @@ -1,70 +0,0 @@ -// 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_MEMORYBUFFER_H_ -#define RAPIDJSON_MEMORYBUFFER_H_ - -#include "rapidjson.h" -#include "internal/stack.h" - -RAPIDJSON_NAMESPACE_BEGIN - -//! Represents an in-memory output byte stream. -/*! - This class is mainly for being wrapped by EncodedOutputStream or AutoUTFOutputStream. - - It is similar to FileWriteBuffer but the destination is an in-memory buffer instead of a file. - - Differences between MemoryBuffer and StringBuffer: - 1. StringBuffer has Encoding but MemoryBuffer is only a byte buffer. - 2. StringBuffer::GetString() returns a null-terminated string. MemoryBuffer::GetBuffer() returns a buffer without terminator. - - \tparam Allocator type for allocating memory buffer. - \note implements Stream concept -*/ -template -struct GenericMemoryBuffer { - typedef char Ch; // byte - - GenericMemoryBuffer(Allocator* allocator = 0, size_t capacity = kDefaultCapacity) : stack_(allocator, capacity) {} - - void Put(Ch c) { *stack_.template Push() = c; } - void Flush() {} - - void Clear() { stack_.Clear(); } - void ShrinkToFit() { stack_.ShrinkToFit(); } - Ch* Push(size_t count) { return stack_.template Push(count); } - void Pop(size_t count) { stack_.template Pop(count); } - - const Ch* GetBuffer() const { - return stack_.template Bottom(); - } - - size_t GetSize() const { return stack_.GetSize(); } - - static const size_t kDefaultCapacity = 256; - mutable internal::Stack stack_; -}; - -typedef GenericMemoryBuffer<> MemoryBuffer; - -//! Implement specialized version of PutN() with memset() for better performance. -template<> -inline void PutN(MemoryBuffer& memoryBuffer, char c, size_t n) { - std::memset(memoryBuffer.stack_.Push(n), c, n * sizeof(c)); -} - -RAPIDJSON_NAMESPACE_END - -#endif // RAPIDJSON_MEMORYBUFFER_H_ diff --git a/lib/rapidjson/memorystream.h b/lib/rapidjson/memorystream.h deleted file mode 100644 index 99feae5..0000000 --- a/lib/rapidjson/memorystream.h +++ /dev/null @@ -1,61 +0,0 @@ -// 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_MEMORYSTREAM_H_ -#define RAPIDJSON_MEMORYSTREAM_H_ - -#include "rapidjson.h" - -RAPIDJSON_NAMESPACE_BEGIN - -//! Represents an in-memory input byte stream. -/*! - This class is mainly for being wrapped by EncodedInputStream or AutoUTFInputStream. - - It is similar to FileReadBuffer but the source is an in-memory buffer instead of a file. - - Differences between MemoryStream and StringStream: - 1. StringStream has encoding but MemoryStream is a byte stream. - 2. MemoryStream needs size of the source buffer and the buffer don't need to be null terminated. StringStream assume null-terminated string as source. - 3. MemoryStream supports Peek4() for encoding detection. StringStream is specified with an encoding so it should not have Peek4(). - \note implements Stream concept -*/ -struct MemoryStream { - typedef char Ch; // byte - - MemoryStream(const Ch *src, size_t size) : src_(src), begin_(src), end_(src + size), size_(size) {} - - Ch Peek() const { return (src_ == end_) ? '\0' : *src_; } - Ch Take() { return (src_ == end_) ? '\0' : *src_++; } - size_t Tell() const { return static_cast(src_ - begin_); } - - Ch* PutBegin() { RAPIDJSON_ASSERT(false); return 0; } - void Put(Ch) { RAPIDJSON_ASSERT(false); } - void Flush() { RAPIDJSON_ASSERT(false); } - size_t PutEnd(Ch*) { RAPIDJSON_ASSERT(false); return 0; } - - // For encoding detection only. - const Ch* Peek4() const { - return Tell() + 4 <= size_ ? src_ : 0; - } - - const Ch* src_; //!< Current read position. - const Ch* begin_; //!< Original head of the string. - const Ch* end_; //!< End of stream. - size_t size_; //!< Size of the stream. -}; - -RAPIDJSON_NAMESPACE_END - -#endif // RAPIDJSON_MEMORYBUFFER_H_ diff --git a/lib/rapidjson/msinttypes/inttypes.h b/lib/rapidjson/msinttypes/inttypes.h deleted file mode 100644 index 1811128..0000000 --- a/lib/rapidjson/msinttypes/inttypes.h +++ /dev/null @@ -1,316 +0,0 @@ -// ISO C9x compliant inttypes.h for Microsoft Visual Studio -// Based on ISO/IEC 9899:TC2 Committee draft (May 6, 2005) WG14/N1124 -// -// Copyright (c) 2006-2013 Alexander Chemeris -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are met: -// -// 1. Redistributions of source code must retain the above copyright notice, -// this list of conditions and the following disclaimer. -// -// 2. Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// -// 3. Neither the name of the product nor the names of its contributors may -// be used to endorse or promote products derived from this software -// without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED -// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO -// EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, -// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; -// OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, -// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR -// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF -// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// -/////////////////////////////////////////////////////////////////////////////// - -// The above software in this distribution may have been modified by -// THL A29 Limited ("Tencent Modifications"). -// All Tencent Modifications are Copyright (C) 2015 THL A29 Limited. - -#ifndef _MSC_VER // [ -#error "Use this header only with Microsoft Visual C++ compilers!" -#endif // _MSC_VER ] - -#ifndef _MSC_INTTYPES_H_ // [ -#define _MSC_INTTYPES_H_ - -#if _MSC_VER > 1000 -#pragma once -#endif - -#include "stdint.h" - -// miloyip: VC supports inttypes.h since VC2013 -#if _MSC_VER >= 1800 -#include -#else - -// 7.8 Format conversion of integer types - -typedef struct { - intmax_t quot; - intmax_t rem; -} imaxdiv_t; - -// 7.8.1 Macros for format specifiers - -#if !defined(__cplusplus) || defined(__STDC_FORMAT_MACROS) // [ See footnote 185 at page 198 - -// The fprintf macros for signed integers are: -#define PRId8 "d" -#define PRIi8 "i" -#define PRIdLEAST8 "d" -#define PRIiLEAST8 "i" -#define PRIdFAST8 "d" -#define PRIiFAST8 "i" - -#define PRId16 "hd" -#define PRIi16 "hi" -#define PRIdLEAST16 "hd" -#define PRIiLEAST16 "hi" -#define PRIdFAST16 "hd" -#define PRIiFAST16 "hi" - -#define PRId32 "I32d" -#define PRIi32 "I32i" -#define PRIdLEAST32 "I32d" -#define PRIiLEAST32 "I32i" -#define PRIdFAST32 "I32d" -#define PRIiFAST32 "I32i" - -#define PRId64 "I64d" -#define PRIi64 "I64i" -#define PRIdLEAST64 "I64d" -#define PRIiLEAST64 "I64i" -#define PRIdFAST64 "I64d" -#define PRIiFAST64 "I64i" - -#define PRIdMAX "I64d" -#define PRIiMAX "I64i" - -#define PRIdPTR "Id" -#define PRIiPTR "Ii" - -// The fprintf macros for unsigned integers are: -#define PRIo8 "o" -#define PRIu8 "u" -#define PRIx8 "x" -#define PRIX8 "X" -#define PRIoLEAST8 "o" -#define PRIuLEAST8 "u" -#define PRIxLEAST8 "x" -#define PRIXLEAST8 "X" -#define PRIoFAST8 "o" -#define PRIuFAST8 "u" -#define PRIxFAST8 "x" -#define PRIXFAST8 "X" - -#define PRIo16 "ho" -#define PRIu16 "hu" -#define PRIx16 "hx" -#define PRIX16 "hX" -#define PRIoLEAST16 "ho" -#define PRIuLEAST16 "hu" -#define PRIxLEAST16 "hx" -#define PRIXLEAST16 "hX" -#define PRIoFAST16 "ho" -#define PRIuFAST16 "hu" -#define PRIxFAST16 "hx" -#define PRIXFAST16 "hX" - -#define PRIo32 "I32o" -#define PRIu32 "I32u" -#define PRIx32 "I32x" -#define PRIX32 "I32X" -#define PRIoLEAST32 "I32o" -#define PRIuLEAST32 "I32u" -#define PRIxLEAST32 "I32x" -#define PRIXLEAST32 "I32X" -#define PRIoFAST32 "I32o" -#define PRIuFAST32 "I32u" -#define PRIxFAST32 "I32x" -#define PRIXFAST32 "I32X" - -#define PRIo64 "I64o" -#define PRIu64 "I64u" -#define PRIx64 "I64x" -#define PRIX64 "I64X" -#define PRIoLEAST64 "I64o" -#define PRIuLEAST64 "I64u" -#define PRIxLEAST64 "I64x" -#define PRIXLEAST64 "I64X" -#define PRIoFAST64 "I64o" -#define PRIuFAST64 "I64u" -#define PRIxFAST64 "I64x" -#define PRIXFAST64 "I64X" - -#define PRIoMAX "I64o" -#define PRIuMAX "I64u" -#define PRIxMAX "I64x" -#define PRIXMAX "I64X" - -#define PRIoPTR "Io" -#define PRIuPTR "Iu" -#define PRIxPTR "Ix" -#define PRIXPTR "IX" - -// The fscanf macros for signed integers are: -#define SCNd8 "d" -#define SCNi8 "i" -#define SCNdLEAST8 "d" -#define SCNiLEAST8 "i" -#define SCNdFAST8 "d" -#define SCNiFAST8 "i" - -#define SCNd16 "hd" -#define SCNi16 "hi" -#define SCNdLEAST16 "hd" -#define SCNiLEAST16 "hi" -#define SCNdFAST16 "hd" -#define SCNiFAST16 "hi" - -#define SCNd32 "ld" -#define SCNi32 "li" -#define SCNdLEAST32 "ld" -#define SCNiLEAST32 "li" -#define SCNdFAST32 "ld" -#define SCNiFAST32 "li" - -#define SCNd64 "I64d" -#define SCNi64 "I64i" -#define SCNdLEAST64 "I64d" -#define SCNiLEAST64 "I64i" -#define SCNdFAST64 "I64d" -#define SCNiFAST64 "I64i" - -#define SCNdMAX "I64d" -#define SCNiMAX "I64i" - -#ifdef _WIN64 // [ -# define SCNdPTR "I64d" -# define SCNiPTR "I64i" -#else // _WIN64 ][ -# define SCNdPTR "ld" -# define SCNiPTR "li" -#endif // _WIN64 ] - -// The fscanf macros for unsigned integers are: -#define SCNo8 "o" -#define SCNu8 "u" -#define SCNx8 "x" -#define SCNX8 "X" -#define SCNoLEAST8 "o" -#define SCNuLEAST8 "u" -#define SCNxLEAST8 "x" -#define SCNXLEAST8 "X" -#define SCNoFAST8 "o" -#define SCNuFAST8 "u" -#define SCNxFAST8 "x" -#define SCNXFAST8 "X" - -#define SCNo16 "ho" -#define SCNu16 "hu" -#define SCNx16 "hx" -#define SCNX16 "hX" -#define SCNoLEAST16 "ho" -#define SCNuLEAST16 "hu" -#define SCNxLEAST16 "hx" -#define SCNXLEAST16 "hX" -#define SCNoFAST16 "ho" -#define SCNuFAST16 "hu" -#define SCNxFAST16 "hx" -#define SCNXFAST16 "hX" - -#define SCNo32 "lo" -#define SCNu32 "lu" -#define SCNx32 "lx" -#define SCNX32 "lX" -#define SCNoLEAST32 "lo" -#define SCNuLEAST32 "lu" -#define SCNxLEAST32 "lx" -#define SCNXLEAST32 "lX" -#define SCNoFAST32 "lo" -#define SCNuFAST32 "lu" -#define SCNxFAST32 "lx" -#define SCNXFAST32 "lX" - -#define SCNo64 "I64o" -#define SCNu64 "I64u" -#define SCNx64 "I64x" -#define SCNX64 "I64X" -#define SCNoLEAST64 "I64o" -#define SCNuLEAST64 "I64u" -#define SCNxLEAST64 "I64x" -#define SCNXLEAST64 "I64X" -#define SCNoFAST64 "I64o" -#define SCNuFAST64 "I64u" -#define SCNxFAST64 "I64x" -#define SCNXFAST64 "I64X" - -#define SCNoMAX "I64o" -#define SCNuMAX "I64u" -#define SCNxMAX "I64x" -#define SCNXMAX "I64X" - -#ifdef _WIN64 // [ -# define SCNoPTR "I64o" -# define SCNuPTR "I64u" -# define SCNxPTR "I64x" -# define SCNXPTR "I64X" -#else // _WIN64 ][ -# define SCNoPTR "lo" -# define SCNuPTR "lu" -# define SCNxPTR "lx" -# define SCNXPTR "lX" -#endif // _WIN64 ] - -#endif // __STDC_FORMAT_MACROS ] - -// 7.8.2 Functions for greatest-width integer types - -// 7.8.2.1 The imaxabs function -#define imaxabs _abs64 - -// 7.8.2.2 The imaxdiv function - -// This is modified version of div() function from Microsoft's div.c found -// in %MSVC.NET%\crt\src\div.c -#ifdef STATIC_IMAXDIV // [ -static -#else // STATIC_IMAXDIV ][ -_inline -#endif // STATIC_IMAXDIV ] -imaxdiv_t __cdecl imaxdiv(intmax_t numer, intmax_t denom) -{ - imaxdiv_t result; - - result.quot = numer / denom; - result.rem = numer % denom; - - if (numer < 0 && result.rem > 0) { - // did division wrong; must fix up - ++result.quot; - result.rem -= denom; - } - - return result; -} - -// 7.8.2.3 The strtoimax and strtoumax functions -#define strtoimax _strtoi64 -#define strtoumax _strtoui64 - -// 7.8.2.4 The wcstoimax and wcstoumax functions -#define wcstoimax _wcstoi64 -#define wcstoumax _wcstoui64 - -#endif // _MSC_VER >= 1800 - -#endif // _MSC_INTTYPES_H_ ] diff --git a/lib/rapidjson/msinttypes/stdint.h b/lib/rapidjson/msinttypes/stdint.h deleted file mode 100644 index a26fff4..0000000 --- a/lib/rapidjson/msinttypes/stdint.h +++ /dev/null @@ -1,300 +0,0 @@ -// ISO C9x compliant stdint.h for Microsoft Visual Studio -// Based on ISO/IEC 9899:TC2 Committee draft (May 6, 2005) WG14/N1124 -// -// Copyright (c) 2006-2013 Alexander Chemeris -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are met: -// -// 1. Redistributions of source code must retain the above copyright notice, -// this list of conditions and the following disclaimer. -// -// 2. Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// -// 3. Neither the name of the product nor the names of its contributors may -// be used to endorse or promote products derived from this software -// without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED -// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO -// EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, -// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; -// OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, -// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR -// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF -// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// -/////////////////////////////////////////////////////////////////////////////// - -// The above software in this distribution may have been modified by -// THL A29 Limited ("Tencent Modifications"). -// All Tencent Modifications are Copyright (C) 2015 THL A29 Limited. - -#ifndef _MSC_VER // [ -#error "Use this header only with Microsoft Visual C++ compilers!" -#endif // _MSC_VER ] - -#ifndef _MSC_STDINT_H_ // [ -#define _MSC_STDINT_H_ - -#if _MSC_VER > 1000 -#pragma once -#endif - -// miloyip: Originally Visual Studio 2010 uses its own stdint.h. However it generates warning with INT64_C(), so change to use this file for vs2010. -#if _MSC_VER >= 1600 // [ -#include - -#if !defined(__cplusplus) || defined(__STDC_CONSTANT_MACROS) // [ See footnote 224 at page 260 - -#undef INT8_C -#undef INT16_C -#undef INT32_C -#undef INT64_C -#undef UINT8_C -#undef UINT16_C -#undef UINT32_C -#undef UINT64_C - -// 7.18.4.1 Macros for minimum-width integer constants - -#define INT8_C(val) val##i8 -#define INT16_C(val) val##i16 -#define INT32_C(val) val##i32 -#define INT64_C(val) val##i64 - -#define UINT8_C(val) val##ui8 -#define UINT16_C(val) val##ui16 -#define UINT32_C(val) val##ui32 -#define UINT64_C(val) val##ui64 - -// 7.18.4.2 Macros for greatest-width integer constants -// These #ifndef's are needed to prevent collisions with . -// Check out Issue 9 for the details. -#ifndef INTMAX_C // [ -# define INTMAX_C INT64_C -#endif // INTMAX_C ] -#ifndef UINTMAX_C // [ -# define UINTMAX_C UINT64_C -#endif // UINTMAX_C ] - -#endif // __STDC_CONSTANT_MACROS ] - -#else // ] _MSC_VER >= 1700 [ - -#include - -// For Visual Studio 6 in C++ mode and for many Visual Studio versions when -// compiling for ARM we should wrap include with 'extern "C++" {}' -// or compiler give many errors like this: -// error C2733: second C linkage of overloaded function 'wmemchr' not allowed -#ifdef __cplusplus -extern "C" { -#endif -# include -#ifdef __cplusplus -} -#endif - -// Define _W64 macros to mark types changing their size, like intptr_t. -#ifndef _W64 -# if !defined(__midl) && (defined(_X86_) || defined(_M_IX86)) && _MSC_VER >= 1300 -# define _W64 __w64 -# else -# define _W64 -# endif -#endif - - -// 7.18.1 Integer types - -// 7.18.1.1 Exact-width integer types - -// Visual Studio 6 and Embedded Visual C++ 4 doesn't -// realize that, e.g. char has the same size as __int8 -// so we give up on __intX for them. -#if (_MSC_VER < 1300) - typedef signed char int8_t; - typedef signed short int16_t; - typedef signed int int32_t; - typedef unsigned char uint8_t; - typedef unsigned short uint16_t; - typedef unsigned int uint32_t; -#else - typedef signed __int8 int8_t; - typedef signed __int16 int16_t; - typedef signed __int32 int32_t; - typedef unsigned __int8 uint8_t; - typedef unsigned __int16 uint16_t; - typedef unsigned __int32 uint32_t; -#endif -typedef signed __int64 int64_t; -typedef unsigned __int64 uint64_t; - - -// 7.18.1.2 Minimum-width integer types -typedef int8_t int_least8_t; -typedef int16_t int_least16_t; -typedef int32_t int_least32_t; -typedef int64_t int_least64_t; -typedef uint8_t uint_least8_t; -typedef uint16_t uint_least16_t; -typedef uint32_t uint_least32_t; -typedef uint64_t uint_least64_t; - -// 7.18.1.3 Fastest minimum-width integer types -typedef int8_t int_fast8_t; -typedef int16_t int_fast16_t; -typedef int32_t int_fast32_t; -typedef int64_t int_fast64_t; -typedef uint8_t uint_fast8_t; -typedef uint16_t uint_fast16_t; -typedef uint32_t uint_fast32_t; -typedef uint64_t uint_fast64_t; - -// 7.18.1.4 Integer types capable of holding object pointers -#ifdef _WIN64 // [ - typedef signed __int64 intptr_t; - typedef unsigned __int64 uintptr_t; -#else // _WIN64 ][ - typedef _W64 signed int intptr_t; - typedef _W64 unsigned int uintptr_t; -#endif // _WIN64 ] - -// 7.18.1.5 Greatest-width integer types -typedef int64_t intmax_t; -typedef uint64_t uintmax_t; - - -// 7.18.2 Limits of specified-width integer types - -#if !defined(__cplusplus) || defined(__STDC_LIMIT_MACROS) // [ See footnote 220 at page 257 and footnote 221 at page 259 - -// 7.18.2.1 Limits of exact-width integer types -#define INT8_MIN ((int8_t)_I8_MIN) -#define INT8_MAX _I8_MAX -#define INT16_MIN ((int16_t)_I16_MIN) -#define INT16_MAX _I16_MAX -#define INT32_MIN ((int32_t)_I32_MIN) -#define INT32_MAX _I32_MAX -#define INT64_MIN ((int64_t)_I64_MIN) -#define INT64_MAX _I64_MAX -#define UINT8_MAX _UI8_MAX -#define UINT16_MAX _UI16_MAX -#define UINT32_MAX _UI32_MAX -#define UINT64_MAX _UI64_MAX - -// 7.18.2.2 Limits of minimum-width integer types -#define INT_LEAST8_MIN INT8_MIN -#define INT_LEAST8_MAX INT8_MAX -#define INT_LEAST16_MIN INT16_MIN -#define INT_LEAST16_MAX INT16_MAX -#define INT_LEAST32_MIN INT32_MIN -#define INT_LEAST32_MAX INT32_MAX -#define INT_LEAST64_MIN INT64_MIN -#define INT_LEAST64_MAX INT64_MAX -#define UINT_LEAST8_MAX UINT8_MAX -#define UINT_LEAST16_MAX UINT16_MAX -#define UINT_LEAST32_MAX UINT32_MAX -#define UINT_LEAST64_MAX UINT64_MAX - -// 7.18.2.3 Limits of fastest minimum-width integer types -#define INT_FAST8_MIN INT8_MIN -#define INT_FAST8_MAX INT8_MAX -#define INT_FAST16_MIN INT16_MIN -#define INT_FAST16_MAX INT16_MAX -#define INT_FAST32_MIN INT32_MIN -#define INT_FAST32_MAX INT32_MAX -#define INT_FAST64_MIN INT64_MIN -#define INT_FAST64_MAX INT64_MAX -#define UINT_FAST8_MAX UINT8_MAX -#define UINT_FAST16_MAX UINT16_MAX -#define UINT_FAST32_MAX UINT32_MAX -#define UINT_FAST64_MAX UINT64_MAX - -// 7.18.2.4 Limits of integer types capable of holding object pointers -#ifdef _WIN64 // [ -# define INTPTR_MIN INT64_MIN -# define INTPTR_MAX INT64_MAX -# define UINTPTR_MAX UINT64_MAX -#else // _WIN64 ][ -# define INTPTR_MIN INT32_MIN -# define INTPTR_MAX INT32_MAX -# define UINTPTR_MAX UINT32_MAX -#endif // _WIN64 ] - -// 7.18.2.5 Limits of greatest-width integer types -#define INTMAX_MIN INT64_MIN -#define INTMAX_MAX INT64_MAX -#define UINTMAX_MAX UINT64_MAX - -// 7.18.3 Limits of other integer types - -#ifdef _WIN64 // [ -# define PTRDIFF_MIN _I64_MIN -# define PTRDIFF_MAX _I64_MAX -#else // _WIN64 ][ -# define PTRDIFF_MIN _I32_MIN -# define PTRDIFF_MAX _I32_MAX -#endif // _WIN64 ] - -#define SIG_ATOMIC_MIN INT_MIN -#define SIG_ATOMIC_MAX INT_MAX - -#ifndef SIZE_MAX // [ -# ifdef _WIN64 // [ -# define SIZE_MAX _UI64_MAX -# else // _WIN64 ][ -# define SIZE_MAX _UI32_MAX -# endif // _WIN64 ] -#endif // SIZE_MAX ] - -// WCHAR_MIN and WCHAR_MAX are also defined in -#ifndef WCHAR_MIN // [ -# define WCHAR_MIN 0 -#endif // WCHAR_MIN ] -#ifndef WCHAR_MAX // [ -# define WCHAR_MAX _UI16_MAX -#endif // WCHAR_MAX ] - -#define WINT_MIN 0 -#define WINT_MAX _UI16_MAX - -#endif // __STDC_LIMIT_MACROS ] - - -// 7.18.4 Limits of other integer types - -#if !defined(__cplusplus) || defined(__STDC_CONSTANT_MACROS) // [ See footnote 224 at page 260 - -// 7.18.4.1 Macros for minimum-width integer constants - -#define INT8_C(val) val##i8 -#define INT16_C(val) val##i16 -#define INT32_C(val) val##i32 -#define INT64_C(val) val##i64 - -#define UINT8_C(val) val##ui8 -#define UINT16_C(val) val##ui16 -#define UINT32_C(val) val##ui32 -#define UINT64_C(val) val##ui64 - -// 7.18.4.2 Macros for greatest-width integer constants -// These #ifndef's are needed to prevent collisions with . -// Check out Issue 9 for the details. -#ifndef INTMAX_C // [ -# define INTMAX_C INT64_C -#endif // INTMAX_C ] -#ifndef UINTMAX_C // [ -# define UINTMAX_C UINT64_C -#endif // UINTMAX_C ] - -#endif // __STDC_CONSTANT_MACROS ] - -#endif // _MSC_VER >= 1600 ] - -#endif // _MSC_STDINT_H_ ] diff --git a/lib/rapidjson/pointer.h b/lib/rapidjson/pointer.h deleted file mode 100644 index 5d2aa8d..0000000 --- a/lib/rapidjson/pointer.h +++ /dev/null @@ -1,1313 +0,0 @@ -// 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_POINTER_H_ -#define RAPIDJSON_POINTER_H_ - -#include "document.h" -#include "internal/itoa.h" - -RAPIDJSON_NAMESPACE_BEGIN - -static const SizeType kPointerInvalidIndex = ~SizeType(0); //!< Represents an invalid index in GenericPointer::Token - -//! Error code of parsing. -/*! \ingroup RAPIDJSON_ERRORS - \see GenericPointer::GenericPointer, GenericPointer::GetParseErrorCode -*/ -enum PointerParseErrorCode { - kPointerParseErrorNone = 0, //!< The parse is successful - - kPointerParseErrorTokenMustBeginWithSolidus, //!< A token must begin with a '/' - kPointerParseErrorInvalidEscape, //!< Invalid escape - kPointerParseErrorInvalidPercentEncoding, //!< Invalid percent encoding in URI fragment - kPointerParseErrorCharacterMustPercentEncode //!< A character must percent encoded in URI fragment -}; - -/////////////////////////////////////////////////////////////////////////////// -// GenericPointer - -//! Represents a JSON Pointer. Use Pointer for UTF8 encoding and default allocator. -/*! - This class implements RFC 6901 "JavaScript Object Notation (JSON) Pointer" - (https://tools.ietf.org/html/rfc6901). - - A JSON pointer is for identifying a specific value in a JSON document - (GenericDocument). It can simplify coding of DOM tree manipulation, because it - can access multiple-level depth of DOM tree with single API call. - - After it parses a string representation (e.g. "/foo/0" or URI fragment - representation (e.g. "#/foo/0") into its internal representation (tokens), - it can be used to resolve a specific value in multiple documents, or sub-tree - of documents. - - Contrary to GenericValue, Pointer can be copy constructed and copy assigned. - Apart from assignment, a Pointer cannot be modified after construction. - - Although Pointer is very convenient, please aware that constructing Pointer - involves parsing and dynamic memory allocation. A special constructor with user- - supplied tokens eliminates these. - - GenericPointer depends on GenericDocument and GenericValue. - - \tparam ValueType The value type of the DOM tree. E.g. GenericValue > - \tparam Allocator The allocator type for allocating memory for internal representation. - - \note GenericPointer uses same encoding of ValueType. - However, Allocator of GenericPointer is independent of Allocator of Value. -*/ -template -class GenericPointer { -public: - typedef typename ValueType::EncodingType EncodingType; //!< Encoding type from Value - typedef typename EncodingType::Ch Ch; //!< Character type from Value - - //! A token is the basic units of internal representation. - /*! - A JSON pointer string representation "/foo/123" is parsed to two tokens: - "foo" and 123. 123 will be represented in both numeric form and string form. - They are resolved according to the actual value type (object or array). - - For token that are not numbers, or the numeric value is out of bound - (greater than limits of SizeType), they are only treated as string form - (i.e. the token's index will be equal to kPointerInvalidIndex). - - This struct is public so that user can create a Pointer without parsing and - allocation, using a special constructor. - */ - struct Token { - const Ch* name; //!< Name of the token. It has null character at the end but it can contain null character. - SizeType length; //!< Length of the name. - SizeType index; //!< A valid array index, if it is not equal to kPointerInvalidIndex. - }; - - //!@name Constructors and destructor. - //@{ - - //! Default constructor. - GenericPointer() : allocator_(), ownAllocator_(), nameBuffer_(), tokens_(), tokenCount_(), parseErrorOffset_(), parseErrorCode_(kPointerParseErrorNone) {} - - //! Constructor that parses a string or URI fragment representation. - /*! - \param source A null-terminated, string or URI fragment representation of JSON pointer. - \param allocator User supplied allocator for this pointer. If no allocator is provided, it creates a self-owned one. - */ - explicit GenericPointer(const Ch* source, Allocator* allocator = 0) : allocator_(allocator), ownAllocator_(), nameBuffer_(), tokens_(), tokenCount_(), parseErrorOffset_(), parseErrorCode_(kPointerParseErrorNone) { - Parse(source, internal::StrLen(source)); - } - -#if RAPIDJSON_HAS_STDSTRING - //! Constructor that parses a string or URI fragment representation. - /*! - \param source A string or URI fragment representation of JSON pointer. - \param allocator User supplied allocator for this pointer. If no allocator is provided, it creates a self-owned one. - \note Requires the definition of the preprocessor symbol \ref RAPIDJSON_HAS_STDSTRING. - */ - explicit GenericPointer(const std::basic_string& source, Allocator* allocator = 0) : allocator_(allocator), ownAllocator_(), nameBuffer_(), tokens_(), tokenCount_(), parseErrorOffset_(), parseErrorCode_(kPointerParseErrorNone) { - Parse(source.c_str(), source.size()); - } -#endif - - //! Constructor that parses a string or URI fragment representation, with length of the source string. - /*! - \param source A string or URI fragment representation of JSON pointer. - \param length Length of source. - \param allocator User supplied allocator for this pointer. If no allocator is provided, it creates a self-owned one. - \note Slightly faster than the overload without length. - */ - GenericPointer(const Ch* source, size_t length, Allocator* allocator = 0) : allocator_(allocator), ownAllocator_(), nameBuffer_(), tokens_(), tokenCount_(), parseErrorOffset_(), parseErrorCode_(kPointerParseErrorNone) { - Parse(source, length); - } - - //! Constructor with user-supplied tokens. - /*! - This constructor let user supplies const array of tokens. - This prevents the parsing process and eliminates allocation. - This is preferred for memory constrained environments. - - \param tokens An constant array of tokens representing the JSON pointer. - \param tokenCount Number of tokens. - - \b Example - \code - #define NAME(s) { s, sizeof(s) / sizeof(s[0]) - 1, kPointerInvalidIndex } - #define INDEX(i) { #i, sizeof(#i) - 1, i } - - static const Pointer::Token kTokens[] = { NAME("foo"), INDEX(123) }; - static const Pointer p(kTokens, sizeof(kTokens) / sizeof(kTokens[0])); - // Equivalent to static const Pointer p("/foo/123"); - - #undef NAME - #undef INDEX - \endcode - */ - GenericPointer(const Token* tokens, size_t tokenCount) : allocator_(), ownAllocator_(), nameBuffer_(), tokens_(const_cast(tokens)), tokenCount_(tokenCount), parseErrorOffset_(), parseErrorCode_(kPointerParseErrorNone) {} - - //! Copy constructor. - GenericPointer(const GenericPointer& rhs) : allocator_(), ownAllocator_(), nameBuffer_(), tokens_(), tokenCount_(), parseErrorOffset_(), parseErrorCode_(kPointerParseErrorNone) { - *this = rhs; - } - - //! Destructor. - ~GenericPointer() { - if (nameBuffer_) // If user-supplied tokens constructor is used, nameBuffer_ is nullptr and tokens_ are not deallocated. - Allocator::Free(tokens_); - RAPIDJSON_DELETE(ownAllocator_); - } - - //! Assignment operator. - GenericPointer& operator=(const GenericPointer& rhs) { - if (this != &rhs) { - // Do not delete ownAllcator - if (nameBuffer_) - Allocator::Free(tokens_); - - tokenCount_ = rhs.tokenCount_; - parseErrorOffset_ = rhs.parseErrorOffset_; - parseErrorCode_ = rhs.parseErrorCode_; - - if (rhs.nameBuffer_) - CopyFromRaw(rhs); // Normally parsed tokens. - else { - tokens_ = rhs.tokens_; // User supplied const tokens. - nameBuffer_ = 0; - } - } - return *this; - } - - //@} - - //!@name Append token - //@{ - - //! Append a token and return a new Pointer - /*! - \param token Token to be appended. - \param allocator Allocator for the newly return Pointer. - \return A new Pointer with appended token. - */ - GenericPointer Append(const Token& token, Allocator* allocator = 0) const { - GenericPointer r; - r.allocator_ = allocator; - Ch *p = r.CopyFromRaw(*this, 1, token.length + 1); - std::memcpy(p, token.name, (token.length + 1) * sizeof(Ch)); - r.tokens_[tokenCount_].name = p; - r.tokens_[tokenCount_].length = token.length; - r.tokens_[tokenCount_].index = token.index; - return r; - } - - //! Append a name token with length, and return a new Pointer - /*! - \param name Name to be appended. - \param length Length of name. - \param allocator Allocator for the newly return Pointer. - \return A new Pointer with appended token. - */ - GenericPointer Append(const Ch* name, SizeType length, Allocator* allocator = 0) const { - Token token = { name, length, kPointerInvalidIndex }; - return Append(token, allocator); - } - - //! Append a name token without length, and return a new Pointer - /*! - \param name Name (const Ch*) to be appended. - \param allocator Allocator for the newly return Pointer. - \return A new Pointer with appended token. - */ - template - RAPIDJSON_DISABLEIF_RETURN((internal::NotExpr::Type, Ch> >), (GenericPointer)) - Append(T* name, Allocator* allocator = 0) const { - return Append(name, StrLen(name), allocator); - } - -#if RAPIDJSON_HAS_STDSTRING - //! Append a name token, and return a new Pointer - /*! - \param name Name to be appended. - \param allocator Allocator for the newly return Pointer. - \return A new Pointer with appended token. - */ - GenericPointer Append(const std::basic_string& name, Allocator* allocator = 0) const { - return Append(name.c_str(), static_cast(name.size()), allocator); - } -#endif - - //! Append a index token, and return a new Pointer - /*! - \param index Index to be appended. - \param allocator Allocator for the newly return Pointer. - \return A new Pointer with appended token. - */ - GenericPointer Append(SizeType index, Allocator* allocator = 0) const { - char buffer[21]; - SizeType length = (sizeof(SizeType) == 4 ? internal::u32toa(index, buffer): internal::u64toa(index, buffer)) - buffer; - buffer[length] = '\0'; - - if (sizeof(Ch) == 1) { - Token token = { (Ch*)buffer, length, index }; - return Append(token, allocator); - } - else { - Ch name[21]; - for (size_t i = 0; i <= length; i++) - name[i] = buffer[i]; - Token token = { name, length, index }; - return Append(token, allocator); - } - } - - //! Append a token by value, and return a new Pointer - /*! - \param value Value (either Uint or String) to be appended. - \param allocator Allocator for the newly return Pointer. - \return A new Pointer with appended token. - */ - GenericPointer Append(const ValueType& token, Allocator* allocator = 0) const { - if (token.IsString()) - return Append(token.GetString(), token.GetStringLength(), allocator); - else { - RAPIDJSON_ASSERT(token.IsUint64()); - RAPIDJSON_ASSERT(token.GetUint64() <= SizeType(~0)); - return Append(static_cast(token.GetUint64()), allocator); - } - } - - //!@name Handling Parse Error - //@{ - - //! Check whether this is a valid pointer. - bool IsValid() const { return parseErrorCode_ == kPointerParseErrorNone; } - - //! Get the parsing error offset in code unit. - size_t GetParseErrorOffset() const { return parseErrorOffset_; } - - //! Get the parsing error code. - PointerParseErrorCode GetParseErrorCode() const { return parseErrorCode_; } - - //@} - - //!@name Tokens - //@{ - - //! Get the token array (const version only). - const Token* GetTokens() const { return tokens_; } - - //! Get the number of tokens. - size_t GetTokenCount() const { return tokenCount_; } - - //@} - - //!@name Equality/inequality operators - //@{ - - //! Equality operator. - /*! - \note When any pointers are invalid, always returns false. - */ - bool operator==(const GenericPointer& rhs) const { - if (!IsValid() || !rhs.IsValid() || tokenCount_ != rhs.tokenCount_) - return false; - - for (size_t i = 0; i < tokenCount_; i++) { - if (tokens_[i].index != rhs.tokens_[i].index || - tokens_[i].length != rhs.tokens_[i].length || - (tokens_[i].length != 0 && std::memcmp(tokens_[i].name, rhs.tokens_[i].name, sizeof(Ch)* tokens_[i].length) != 0)) - { - return false; - } - } - - return true; - } - - //! Inequality operator. - /*! - \note When any pointers are invalid, always returns true. - */ - bool operator!=(const GenericPointer& rhs) const { return !(*this == rhs); } - - //@} - - //!@name Stringify - //@{ - - //! Stringify the pointer into string representation. - /*! - \tparam OutputStream Type of output stream. - \param os The output stream. - */ - template - bool Stringify(OutputStream& os) const { - return Stringify(os); - } - - //! Stringify the pointer into URI fragment representation. - /*! - \tparam OutputStream Type of output stream. - \param os The output stream. - */ - template - bool StringifyUriFragment(OutputStream& os) const { - return Stringify(os); - } - - //@} - - //!@name Create value - //@{ - - //! Create a value in a subtree. - /*! - If the value is not exist, it creates all parent values and a JSON Null value. - So it always succeed and return the newly created or existing value. - - Remind that it may change types of parents according to tokens, so it - potentially removes previously stored values. For example, if a document - was an array, and "/foo" is used to create a value, then the document - will be changed to an object, and all existing array elements are lost. - - \param root Root value of a DOM subtree to be resolved. It can be any value other than document root. - \param allocator Allocator for creating the values if the specified value or its parents are not exist. - \param alreadyExist If non-null, it stores whether the resolved value is already exist. - \return The resolved newly created (a JSON Null value), or already exists value. - */ - ValueType& Create(ValueType& root, typename ValueType::AllocatorType& allocator, bool* alreadyExist = 0) const { - RAPIDJSON_ASSERT(IsValid()); - ValueType* v = &root; - bool exist = true; - for (const Token *t = tokens_; t != tokens_ + tokenCount_; ++t) { - if (v->IsArray() && t->name[0] == '-' && t->length == 1) { - v->PushBack(Value().Move(), allocator); - v = &((*v)[v->Size() - 1]); - exist = false; - } - else { - if (t->index == kPointerInvalidIndex) { // must be object name - if (!v->IsObject()) - v->SetObject(); // Change to Object - } - else { // object name or array index - if (!v->IsArray() && !v->IsObject()) - v->SetArray(); // Change to Array - } - - if (v->IsArray()) { - if (t->index >= v->Size()) { - v->Reserve(t->index + 1, allocator); - while (t->index >= v->Size()) - v->PushBack(Value().Move(), allocator); - exist = false; - } - v = &((*v)[t->index]); - } - else { - typename ValueType::MemberIterator m = v->FindMember(GenericStringRef(t->name, t->length)); - if (m == v->MemberEnd()) { - v->AddMember(Value(t->name, t->length, allocator).Move(), Value().Move(), allocator); - v = &(--v->MemberEnd())->value; // Assumes AddMember() appends at the end - exist = false; - } - else - v = &m->value; - } - } - } - - if (alreadyExist) - *alreadyExist = exist; - - return *v; - } - - //! Creates a value in a document. - /*! - \param document A document to be resolved. - \param allocator Allocator for creating the values if the specified value or its parents are not exist. - \param alreadyExist If non-null, it stores whether the resolved value is already exist. - \return The resolved newly created, or already exists value. - */ - template - ValueType& Create(GenericDocument& document, bool* alreadyExist = 0) const { - return Create(document, document.GetAllocator(), alreadyExist); - } - - //@} - - //!@name Query value - //@{ - - //! Query a value in a subtree. - /*! - \param root Root value of a DOM sub-tree to be resolved. It can be any value other than document root. - \return Pointer to the value if it can be resolved. Otherwise null. - */ - ValueType* Get(ValueType& root) const { - RAPIDJSON_ASSERT(IsValid()); - ValueType* v = &root; - for (const Token *t = tokens_; t != tokens_ + tokenCount_; ++t) { - switch (v->GetType()) { - case kObjectType: - { - typename ValueType::MemberIterator m = v->FindMember(GenericStringRef(t->name, t->length)); - if (m == v->MemberEnd()) - return 0; - v = &m->value; - } - break; - case kArrayType: - if (t->index == kPointerInvalidIndex || t->index >= v->Size()) - return 0; - v = &((*v)[t->index]); - break; - default: - return 0; - } - } - return v; - } - - //! Query a const value in a const subtree. - /*! - \param root Root value of a DOM sub-tree to be resolved. It can be any value other than document root. - \return Pointer to the value if it can be resolved. Otherwise null. - */ - const ValueType* Get(const ValueType& root) const { return Get(const_cast(root)); } - - //@} - - //!@name Query a value with default - //@{ - - //! Query a value in a subtree with default value. - /*! - Similar to Get(), but if the specified value do not exists, it creates all parents and clone the default value. - So that this function always succeed. - - \param root Root value of a DOM sub-tree to be resolved. It can be any value other than document root. - \param defaultValue Default value to be cloned if the value was not exists. - \param allocator Allocator for creating the values if the specified value or its parents are not exist. - \see Create() - */ - ValueType& GetWithDefault(ValueType& root, const ValueType& defaultValue, typename ValueType::AllocatorType& allocator) const { - bool alreadyExist; - Value& v = Create(root, allocator, &alreadyExist); - return alreadyExist ? v : v.CopyFrom(defaultValue, allocator); - } - - //! Query a value in a subtree with default null-terminated string. - ValueType& GetWithDefault(ValueType& root, const Ch* defaultValue, typename ValueType::AllocatorType& allocator) const { - bool alreadyExist; - Value& v = Create(root, allocator, &alreadyExist); - return alreadyExist ? v : v.SetString(defaultValue, allocator); - } - -#if RAPIDJSON_HAS_STDSTRING - //! Query a value in a subtree with default std::basic_string. - ValueType& GetWithDefault(ValueType& root, const std::basic_string& defaultValue, typename ValueType::AllocatorType& allocator) const { - bool alreadyExist; - Value& v = Create(root, allocator, &alreadyExist); - return alreadyExist ? v : v.SetString(defaultValue, allocator); - } -#endif - - //! Query a value in a subtree with default primitive value. - /*! - \tparam T \tparam T Either \ref Type, \c int, \c unsigned, \c int64_t, \c uint64_t, \c bool - */ - template - RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr, internal::IsGenericValue >), (ValueType&)) - GetWithDefault(ValueType& root, T defaultValue, typename ValueType::AllocatorType& allocator) const { - return GetWithDefault(root, ValueType(defaultValue).Move(), allocator); - } - - //! Query a value in a document with default value. - template - ValueType& GetWithDefault(GenericDocument& document, const ValueType& defaultValue) const { - return GetWithDefault(document, defaultValue, document.GetAllocator()); - } - - //! Query a value in a document with default null-terminated string. - template - ValueType& GetWithDefault(GenericDocument& document, const Ch* defaultValue) const { - return GetWithDefault(document, defaultValue, document.GetAllocator()); - } - -#if RAPIDJSON_HAS_STDSTRING - //! Query a value in a document with default std::basic_string. - template - ValueType& GetWithDefault(GenericDocument& document, const std::basic_string& defaultValue) const { - return GetWithDefault(document, defaultValue, document.GetAllocator()); - } -#endif - - //! Query a value in a document with default primitive value. - /*! - \tparam T \tparam T Either \ref Type, \c int, \c unsigned, \c int64_t, \c uint64_t, \c bool - */ - template - RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr, internal::IsGenericValue >), (ValueType&)) - GetWithDefault(GenericDocument& document, T defaultValue) const { - return GetWithDefault(document, defaultValue, document.GetAllocator()); - } - - //@} - - //!@name Set a value - //@{ - - //! Set a value in a subtree, with move semantics. - /*! - It creates all parents if they are not exist or types are different to the tokens. - So this function always succeeds but potentially remove existing values. - - \param root Root value of a DOM sub-tree to be resolved. It can be any value other than document root. - \param value Value to be set. - \param allocator Allocator for creating the values if the specified value or its parents are not exist. - \see Create() - */ - ValueType& Set(ValueType& root, ValueType& value, typename ValueType::AllocatorType& allocator) const { - return Create(root, allocator) = value; - } - - //! Set a value in a subtree, with copy semantics. - ValueType& Set(ValueType& root, const ValueType& value, typename ValueType::AllocatorType& allocator) const { - return Create(root, allocator).CopyFrom(value, allocator); - } - - //! Set a null-terminated string in a subtree. - ValueType& Set(ValueType& root, const Ch* value, typename ValueType::AllocatorType& allocator) const { - return Create(root, allocator) = ValueType(value, allocator).Move(); - } - -#if RAPIDJSON_HAS_STDSTRING - //! Set a std::basic_string in a subtree. - ValueType& Set(ValueType& root, const std::basic_string& value, typename ValueType::AllocatorType& allocator) const { - return Create(root, allocator) = ValueType(value, allocator).Move(); - } -#endif - - //! Set a primitive value in a subtree. - /*! - \tparam T \tparam T Either \ref Type, \c int, \c unsigned, \c int64_t, \c uint64_t, \c bool - */ - template - RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr, internal::IsGenericValue >), (ValueType&)) - Set(ValueType& root, T value, typename ValueType::AllocatorType& allocator) const { - return Create(root, allocator) = ValueType(value).Move(); - } - - //! Set a value in a document, with move semantics. - template - ValueType& Set(GenericDocument& document, ValueType& value) const { - return Create(document) = value; - } - - //! Set a value in a document, with copy semantics. - template - ValueType& Set(GenericDocument& document, const ValueType& value) const { - return Create(document).CopyFrom(value, document.GetAllocator()); - } - - //! Set a null-terminated string in a document. - template - ValueType& Set(GenericDocument& document, const Ch* value) const { - return Create(document) = ValueType(value, document.GetAllocator()).Move(); - } - -#if RAPIDJSON_HAS_STDSTRING - //! Sets a std::basic_string in a document. - template - ValueType& Set(GenericDocument& document, const std::basic_string& value) const { - return Create(document) = ValueType(value, document.GetAllocator()).Move(); - } -#endif - - //! Set a primitive value in a document. - /*! - \tparam T \tparam T Either \ref Type, \c int, \c unsigned, \c int64_t, \c uint64_t, \c bool - */ - template - RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr, internal::IsGenericValue >), (ValueType&)) - Set(GenericDocument& document, T value) const { - return Create(document) = value; - } - - //@} - - //!@name Swap a value - //@{ - - //! Swap a value with a value in a subtree. - /*! - It creates all parents if they are not exist or types are different to the tokens. - So this function always succeeds but potentially remove existing values. - - \param root Root value of a DOM sub-tree to be resolved. It can be any value other than document root. - \param value Value to be swapped. - \param allocator Allocator for creating the values if the specified value or its parents are not exist. - \see Create() - */ - ValueType& Swap(ValueType& root, ValueType& value, typename ValueType::AllocatorType& allocator) const { - return Create(root, allocator).Swap(value); - } - - //! Swap a value with a value in a document. - template - ValueType& Swap(GenericDocument& document, ValueType& value) const { - return Create(document).Swap(value); - } - - //@} - - //! Erase a value in a subtree. - /*! - \param root Root value of a DOM sub-tree to be resolved. It can be any value other than document root. - \return Whether the resolved value is found and erased. - - \note Erasing with an empty pointer \c Pointer(""), i.e. the root, always fail and return false. - */ - bool Erase(ValueType& root) const { - RAPIDJSON_ASSERT(IsValid()); - if (tokenCount_ == 0) // Cannot erase the root - return false; - - ValueType* v = &root; - const Token* last = tokens_ + (tokenCount_ - 1); - for (const Token *t = tokens_; t != last; ++t) { - switch (v->GetType()) { - case kObjectType: - { - typename ValueType::MemberIterator m = v->FindMember(GenericStringRef(t->name, t->length)); - if (m == v->MemberEnd()) - return false; - v = &m->value; - } - break; - case kArrayType: - if (t->index == kPointerInvalidIndex || t->index >= v->Size()) - return false; - v = &((*v)[t->index]); - break; - default: - return false; - } - } - - switch (v->GetType()) { - case kObjectType: - return v->EraseMember(GenericStringRef(last->name, last->length)); - case kArrayType: - if (last->index == kPointerInvalidIndex || last->index >= v->Size()) - return false; - v->Erase(v->Begin() + last->index); - return true; - default: - return false; - } - } - -private: - //! Clone the content from rhs to this. - /*! - \param rhs Source pointer. - \param extraToken Extra tokens to be allocated. - \param extraNameBufferSize Extra name buffer size (in number of Ch) to be allocated. - \return Start of non-occupied name buffer, for storing extra names. - */ - Ch* CopyFromRaw(const GenericPointer& rhs, size_t extraToken = 0, size_t extraNameBufferSize = 0) { - if (!allocator_) // allocator is independently owned. - ownAllocator_ = allocator_ = RAPIDJSON_NEW(Allocator()); - - size_t nameBufferSize = rhs.tokenCount_; // null terminators for tokens - for (Token *t = rhs.tokens_; t != rhs.tokens_ + rhs.tokenCount_; ++t) - nameBufferSize += t->length; - - tokenCount_ = rhs.tokenCount_ + extraToken; - tokens_ = static_cast(allocator_->Malloc(tokenCount_ * sizeof(Token) + (nameBufferSize + extraNameBufferSize) * sizeof(Ch))); - nameBuffer_ = reinterpret_cast(tokens_ + tokenCount_); - std::memcpy(tokens_, rhs.tokens_, rhs.tokenCount_ * sizeof(Token)); - std::memcpy(nameBuffer_, rhs.nameBuffer_, nameBufferSize * sizeof(Ch)); - - // Adjust pointers to name buffer - std::ptrdiff_t diff = nameBuffer_ - rhs.nameBuffer_; - for (Token *t = tokens_; t != tokens_ + rhs.tokenCount_; ++t) - t->name += diff; - - return nameBuffer_ + nameBufferSize; - } - - //! Check whether a character should be percent-encoded. - /*! - According to RFC 3986 2.3 Unreserved Characters. - \param c The character (code unit) to be tested. - */ - bool NeedPercentEncode(Ch c) const { - return !((c >= '0' && c <= '9') || (c >= 'A' && c <='Z') || (c >= 'a' && c <= 'z') || c == '-' || c == '.' || c == '_' || c =='~'); - } - - //! Parse a JSON String or its URI fragment representation into tokens. - /*! - \param source Either a JSON Pointer string, or its URI fragment representation. Not need to be null terminated. - \param length Length of the source string. - \note Source cannot be JSON String Representation of JSON Pointer, e.g. In "/\u0000", \u0000 will not be unescaped. - */ - void Parse(const Ch* source, size_t length) { - RAPIDJSON_ASSERT(source != NULL); - RAPIDJSON_ASSERT(nameBuffer_ == 0); - RAPIDJSON_ASSERT(tokens_ == 0); - - // Create own allocator if user did not supply. - if (!allocator_) - ownAllocator_ = allocator_ = RAPIDJSON_NEW(Allocator()); - - // Count number of '/' as tokenCount - tokenCount_ = 0; - for (const Ch* s = source; s != source + length; s++) - if (*s == '/') - tokenCount_++; - - Token* token = tokens_ = static_cast(allocator_->Malloc(tokenCount_ * sizeof(Token) + length * sizeof(Ch))); - Ch* name = nameBuffer_ = reinterpret_cast(tokens_ + tokenCount_); - size_t i = 0; - - // Detect if it is a URI fragment - bool uriFragment = false; - if (source[i] == '#') { - uriFragment = true; - i++; - } - - if (i != length && source[i] != '/') { - parseErrorCode_ = kPointerParseErrorTokenMustBeginWithSolidus; - goto error; - } - - while (i < length) { - RAPIDJSON_ASSERT(source[i] == '/'); - i++; // consumes '/' - - token->name = name; - bool isNumber = true; - - while (i < length && source[i] != '/') { - Ch c = source[i]; - if (uriFragment) { - // Decoding percent-encoding for URI fragment - if (c == '%') { - PercentDecodeStream is(&source[i], source + length); - GenericInsituStringStream os(name); - Ch* begin = os.PutBegin(); - if (!Transcoder, EncodingType>().Validate(is, os) || !is.IsValid()) { - parseErrorCode_ = kPointerParseErrorInvalidPercentEncoding; - goto error; - } - size_t len = os.PutEnd(begin); - i += is.Tell() - 1; - if (len == 1) - c = *name; - else { - name += len; - isNumber = false; - i++; - continue; - } - } - else if (NeedPercentEncode(c)) { - parseErrorCode_ = kPointerParseErrorCharacterMustPercentEncode; - goto error; - } - } - - i++; - - // Escaping "~0" -> '~', "~1" -> '/' - if (c == '~') { - if (i < length) { - c = source[i]; - if (c == '0') c = '~'; - else if (c == '1') c = '/'; - else { - parseErrorCode_ = kPointerParseErrorInvalidEscape; - goto error; - } - i++; - } - else { - parseErrorCode_ = kPointerParseErrorInvalidEscape; - goto error; - } - } - - // First check for index: all of characters are digit - if (c < '0' || c > '9') - isNumber = false; - - *name++ = c; - } - token->length = name - token->name; - if (token->length == 0) - isNumber = false; - *name++ = '\0'; // Null terminator - - // Second check for index: more than one digit cannot have leading zero - if (isNumber && token->length > 1 && token->name[0] == '0') - isNumber = false; - - // String to SizeType conversion - SizeType n = 0; - if (isNumber) { - for (size_t j = 0; j < token->length; j++) { - SizeType m = n * 10 + static_cast(token->name[j] - '0'); - if (m < n) { // overflow detection - isNumber = false; - break; - } - n = m; - } - } - - token->index = isNumber ? n : kPointerInvalidIndex; - token++; - } - - RAPIDJSON_ASSERT(name <= nameBuffer_ + length); // Should not overflow buffer - parseErrorCode_ = kPointerParseErrorNone; - return; - - error: - Allocator::Free(tokens_); - nameBuffer_ = 0; - tokens_ = 0; - tokenCount_ = 0; - parseErrorOffset_ = i; - return; - } - - //! Stringify to string or URI fragment representation. - /*! - \tparam uriFragment True for stringifying to URI fragment representation. False for string representation. - \tparam OutputStream type of output stream. - \param os The output stream. - */ - template - bool Stringify(OutputStream& os) const { - RAPIDJSON_ASSERT(IsValid()); - - if (uriFragment) - os.Put('#'); - - for (Token *t = tokens_; t != tokens_ + tokenCount_; ++t) { - os.Put('/'); - for (size_t j = 0; j < t->length; j++) { - Ch c = t->name[j]; - if (c == '~') { - os.Put('~'); - os.Put('0'); - } - else if (c == '/') { - os.Put('~'); - os.Put('1'); - } - else if (uriFragment && NeedPercentEncode(c)) { - // Transcode to UTF8 sequence - GenericStringStream source(&t->name[j]); - PercentEncodeStream target(os); - if (!Transcoder >().Validate(source, target)) - return false; - j += source.Tell() - 1; - } - else - os.Put(c); - } - } - return true; - } - - //! A helper stream for decoding a percent-encoded sequence into code unit. - /*! - This stream decodes %XY triplet into code unit (0-255). - If it encounters invalid characters, it sets output code unit as 0 and - mark invalid, and to be checked by IsValid(). - */ - class PercentDecodeStream { - public: - //! Constructor - /*! - \param source Start of the stream - \param end Past-the-end of the stream. - */ - PercentDecodeStream(const Ch* source, const Ch* end) : src_(source), head_(source), end_(end), valid_(true) {} - - Ch Take() { - if (*src_ != '%' || src_ + 3 > end_) { // %XY triplet - valid_ = false; - return 0; - } - src_++; - Ch c = 0; - for (int j = 0; j < 2; j++) { - c <<= 4; - Ch h = *src_; - if (h >= '0' && h <= '9') c += h - '0'; - else if (h >= 'A' && h <= 'F') c += h - 'A' + 10; - else if (h >= 'a' && h <= 'f') c += h - 'a' + 10; - else { - valid_ = false; - return 0; - } - src_++; - } - return c; - } - - size_t Tell() const { return src_ - head_; } - bool IsValid() const { return valid_; } - - private: - const Ch* src_; //!< Current read position. - const Ch* head_; //!< Original head of the string. - const Ch* end_; //!< Past-the-end position. - bool valid_; //!< Whether the parsing is valid. - }; - - //! A helper stream to encode character (UTF-8 code unit) into percent-encoded sequence. - template - class PercentEncodeStream { - public: - PercentEncodeStream(OutputStream& os) : os_(os) {} - void Put(char c) { // UTF-8 must be byte - unsigned char u = static_cast(c); - static const char hexDigits[16] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' }; - os_.Put('%'); - os_.Put(hexDigits[u >> 4]); - os_.Put(hexDigits[u & 15]); - } - private: - OutputStream& os_; - }; - - Allocator* allocator_; //!< The current allocator. It is either user-supplied or equal to ownAllocator_. - Allocator* ownAllocator_; //!< Allocator owned by this Pointer. - Ch* nameBuffer_; //!< A buffer containing all names in tokens. - Token* tokens_; //!< A list of tokens. - size_t tokenCount_; //!< Number of tokens in tokens_. - size_t parseErrorOffset_; //!< Offset in code unit when parsing fail. - PointerParseErrorCode parseErrorCode_; //!< Parsing error code. -}; - -//! GenericPointer for Value (UTF-8, default allocator). -typedef GenericPointer Pointer; - -//!@name Helper functions for GenericPointer -//@{ - -////////////////////////////////////////////////////////////////////////////// - -template -typename T::ValueType& CreateValueByPointer(T& root, const GenericPointer& pointer, typename T::AllocatorType& a) { - return pointer.Create(root, a); -} - -template -typename T::ValueType& CreateValueByPointer(T& root, const CharType(&source)[N], typename T::AllocatorType& a) { - return GenericPointer(source, N - 1).Create(root, a); -} - -// No allocator parameter - -template -typename DocumentType::ValueType& CreateValueByPointer(DocumentType& document, const GenericPointer& pointer) { - return pointer.Create(document); -} - -template -typename DocumentType::ValueType& CreateValueByPointer(DocumentType& document, const CharType(&source)[N]) { - return GenericPointer(source, N - 1).Create(document); -} - -////////////////////////////////////////////////////////////////////////////// - -template -typename T::ValueType* GetValueByPointer(T& root, const GenericPointer& pointer) { - return pointer.Get(root); -} - -template -const typename T::ValueType* GetValueByPointer(const T& root, const GenericPointer& pointer) { - return pointer.Get(root); -} - -template -typename T::ValueType* GetValueByPointer(T& root, const CharType (&source)[N]) { - return GenericPointer(source, N - 1).Get(root); -} - -template -const typename T::ValueType* GetValueByPointer(const T& root, const CharType(&source)[N]) { - return GenericPointer(source, N - 1).Get(root); -} - -////////////////////////////////////////////////////////////////////////////// - -template -typename T::ValueType& GetValueByPointerWithDefault(T& root, const GenericPointer& pointer, const typename T::ValueType& defaultValue, typename T::AllocatorType& a) { - return pointer.GetWithDefault(root, defaultValue, a); -} - -template -typename T::ValueType& GetValueByPointerWithDefault(T& root, const GenericPointer& pointer, const typename T::Ch* defaultValue, typename T::AllocatorType& a) { - return pointer.GetWithDefault(root, defaultValue, a); -} - -#if RAPIDJSON_HAS_STDSTRING -template -typename T::ValueType& GetValueByPointerWithDefault(T& root, const GenericPointer& pointer, const std::basic_string& defaultValue, typename T::AllocatorType& a) { - return pointer.GetWithDefault(root, defaultValue, a); -} -#endif - -template -RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr, internal::IsGenericValue >), (typename T::ValueType&)) -GetValueByPointerWithDefault(T& root, const GenericPointer& pointer, T2 defaultValue, typename T::AllocatorType& a) { - return pointer.GetWithDefault(root, defaultValue, a); -} - -template -typename T::ValueType& GetValueByPointerWithDefault(T& root, const CharType(&source)[N], const typename T::ValueType& defaultValue, typename T::AllocatorType& a) { - return GenericPointer(source, N - 1).GetWithDefault(root, defaultValue, a); -} - -template -typename T::ValueType& GetValueByPointerWithDefault(T& root, const CharType(&source)[N], const typename T::Ch* defaultValue, typename T::AllocatorType& a) { - return GenericPointer(source, N - 1).GetWithDefault(root, defaultValue, a); -} - -#if RAPIDJSON_HAS_STDSTRING -template -typename T::ValueType& GetValueByPointerWithDefault(T& root, const CharType(&source)[N], const std::basic_string& defaultValue, typename T::AllocatorType& a) { - return GenericPointer(source, N - 1).GetWithDefault(root, defaultValue, a); -} -#endif - -template -RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr, internal::IsGenericValue >), (typename T::ValueType&)) -GetValueByPointerWithDefault(T& root, const CharType(&source)[N], T2 defaultValue, typename T::AllocatorType& a) { - return GenericPointer(source, N - 1).GetWithDefault(root, defaultValue, a); -} - -// No allocator parameter - -template -typename DocumentType::ValueType& GetValueByPointerWithDefault(DocumentType& document, const GenericPointer& pointer, const typename DocumentType::ValueType& defaultValue) { - return pointer.GetWithDefault(document, defaultValue); -} - -template -typename DocumentType::ValueType& GetValueByPointerWithDefault(DocumentType& document, const GenericPointer& pointer, const typename DocumentType::Ch* defaultValue) { - return pointer.GetWithDefault(document, defaultValue); -} - -#if RAPIDJSON_HAS_STDSTRING -template -typename DocumentType::ValueType& GetValueByPointerWithDefault(DocumentType& document, const GenericPointer& pointer, const std::basic_string& defaultValue) { - return pointer.GetWithDefault(document, defaultValue); -} -#endif - -template -RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr, internal::IsGenericValue >), (typename DocumentType::ValueType&)) -GetValueByPointerWithDefault(DocumentType& document, const GenericPointer& pointer, T2 defaultValue) { - return pointer.GetWithDefault(document, defaultValue); -} - -template -typename DocumentType::ValueType& GetValueByPointerWithDefault(DocumentType& document, const CharType(&source)[N], const typename DocumentType::ValueType& defaultValue) { - return GenericPointer(source, N - 1).GetWithDefault(document, defaultValue); -} - -template -typename DocumentType::ValueType& GetValueByPointerWithDefault(DocumentType& document, const CharType(&source)[N], const typename DocumentType::Ch* defaultValue) { - return GenericPointer(source, N - 1).GetWithDefault(document, defaultValue); -} - -#if RAPIDJSON_HAS_STDSTRING -template -typename DocumentType::ValueType& GetValueByPointerWithDefault(DocumentType& document, const CharType(&source)[N], const std::basic_string& defaultValue) { - return GenericPointer(source, N - 1).GetWithDefault(document, defaultValue); -} -#endif - -template -RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr, internal::IsGenericValue >), (typename DocumentType::ValueType&)) -GetValueByPointerWithDefault(DocumentType& document, const CharType(&source)[N], T2 defaultValue) { - return GenericPointer(source, N - 1).GetWithDefault(document, defaultValue); -} - -////////////////////////////////////////////////////////////////////////////// - -template -typename T::ValueType& SetValueByPointer(T& root, const GenericPointer& pointer, typename T::ValueType& value, typename T::AllocatorType& a) { - return pointer.Set(root, value, a); -} - -template -typename T::ValueType& SetValueByPointer(T& root, const GenericPointer& pointer, const typename T::ValueType& value, typename T::AllocatorType& a) { - return pointer.Set(root, value, a); -} - -template -typename T::ValueType& SetValueByPointer(T& root, const GenericPointer& pointer, const typename T::Ch* value, typename T::AllocatorType& a) { - return pointer.Set(root, value, a); -} - -#if RAPIDJSON_HAS_STDSTRING -template -typename T::ValueType& SetValueByPointer(T& root, const GenericPointer& pointer, const std::basic_string& value, typename T::AllocatorType& a) { - return pointer.Set(root, value, a); -} -#endif - -template -RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr, internal::IsGenericValue >), (typename T::ValueType&)) -SetValueByPointer(T& root, const GenericPointer& pointer, T2 value, typename T::AllocatorType& a) { - return pointer.Set(root, value, a); -} - -template -typename T::ValueType& SetValueByPointer(T& root, const CharType(&source)[N], typename T::ValueType& value, typename T::AllocatorType& a) { - return GenericPointer(source, N - 1).Set(root, value, a); -} - -template -typename T::ValueType& SetValueByPointer(T& root, const CharType(&source)[N], const typename T::ValueType& value, typename T::AllocatorType& a) { - return GenericPointer(source, N - 1).Set(root, value, a); -} - -template -typename T::ValueType& SetValueByPointer(T& root, const CharType(&source)[N], const typename T::Ch* value, typename T::AllocatorType& a) { - return GenericPointer(source, N - 1).Set(root, value, a); -} - -#if RAPIDJSON_HAS_STDSTRING -template -typename T::ValueType& SetValueByPointer(T& root, const CharType(&source)[N], const std::basic_string& value, typename T::AllocatorType& a) { - return GenericPointer(source, N - 1).Set(root, value, a); -} -#endif - -template -RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr, internal::IsGenericValue >), (typename T::ValueType&)) -SetValueByPointer(T& root, const CharType(&source)[N], T2 value, typename T::AllocatorType& a) { - return GenericPointer(source, N - 1).Set(root, value, a); -} - -// No allocator parameter - -template -typename DocumentType::ValueType& SetValueByPointer(DocumentType& document, const GenericPointer& pointer, typename DocumentType::ValueType& value) { - return pointer.Set(document, value); -} - -template -typename DocumentType::ValueType& SetValueByPointer(DocumentType& document, const GenericPointer& pointer, const typename DocumentType::ValueType& value) { - return pointer.Set(document, value); -} - -template -typename DocumentType::ValueType& SetValueByPointer(DocumentType& document, const GenericPointer& pointer, const typename DocumentType::Ch* value) { - return pointer.Set(document, value); -} - -#if RAPIDJSON_HAS_STDSTRING -template -typename DocumentType::ValueType& SetValueByPointer(DocumentType& document, const GenericPointer& pointer, const std::basic_string& value) { - return pointer.Set(document, value); -} -#endif - -template -RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr, internal::IsGenericValue >), (typename DocumentType::ValueType&)) -SetValueByPointer(DocumentType& document, const GenericPointer& pointer, T2 value) { - return pointer.Set(document, value); -} - -template -typename DocumentType::ValueType& SetValueByPointer(DocumentType& document, const CharType(&source)[N], typename DocumentType::ValueType& value) { - return GenericPointer(source, N - 1).Set(document, value); -} - -template -typename DocumentType::ValueType& SetValueByPointer(DocumentType& document, const CharType(&source)[N], const typename DocumentType::ValueType& value) { - return GenericPointer(source, N - 1).Set(document, value); -} - -template -typename DocumentType::ValueType& SetValueByPointer(DocumentType& document, const CharType(&source)[N], const typename DocumentType::Ch* value) { - return GenericPointer(source, N - 1).Set(document, value); -} - -#if RAPIDJSON_HAS_STDSTRING -template -typename DocumentType::ValueType& SetValueByPointer(DocumentType& document, const CharType(&source)[N], const std::basic_string& value) { - return GenericPointer(source, N - 1).Set(document, value); -} -#endif - -template -RAPIDJSON_DISABLEIF_RETURN((internal::OrExpr, internal::IsGenericValue >), (typename DocumentType::ValueType&)) -SetValueByPointer(DocumentType& document, const CharType(&source)[N], T2 value) { - return GenericPointer(source, N - 1).Set(document, value); -} - -////////////////////////////////////////////////////////////////////////////// - -template -typename T::ValueType& SwapValueByPointer(T& root, const GenericPointer& pointer, typename T::ValueType& value, typename T::AllocatorType& a) { - return pointer.Swap(root, value, a); -} - -template -typename T::ValueType& SwapValueByPointer(T& root, const CharType(&source)[N], typename T::ValueType& value, typename T::AllocatorType& a) { - return GenericPointer(source, N - 1).Swap(root, value, a); -} - -template -typename DocumentType::ValueType& SwapValueByPointer(DocumentType& document, const GenericPointer& pointer, typename DocumentType::ValueType& value) { - return pointer.Swap(document, value); -} - -template -typename DocumentType::ValueType& SwapValueByPointer(DocumentType& document, const CharType(&source)[N], typename DocumentType::ValueType& value) { - return GenericPointer(source, N - 1).Swap(document, value); -} - -////////////////////////////////////////////////////////////////////////////// - -template -bool EraseValueByPointer(T& root, const GenericPointer& pointer) { - return pointer.Erase(root); -} - -template -bool EraseValueByPointer(T& root, const CharType(&source)[N]) { - return GenericPointer(source, N - 1).Erase(root); -} - -//@} - -RAPIDJSON_NAMESPACE_END - -#endif // RAPIDJSON_POINTER_H_ diff --git a/lib/rapidjson/prettywriter.h b/lib/rapidjson/prettywriter.h deleted file mode 100644 index 416dd49..0000000 --- a/lib/rapidjson/prettywriter.h +++ /dev/null @@ -1,207 +0,0 @@ -// 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 TargetEncoding = UTF8<>, typename StackAllocator = CrtAllocator> -class PrettyWriter : public Writer { -public: - typedef Writer 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& str) { - return String(str.data(), SizeType(str.size())); - } -#endif - - bool StartObject() { - PrettyPrefix(kObjectType); - new (Base::level_stack_.template Push()) 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()->inArray); - bool empty = Base::level_stack_.template Pop(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(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()->inArray); - bool empty = Base::level_stack_.template Pop(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(); - - 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/lib/rapidjson/rapidjson.h b/lib/rapidjson/rapidjson.h deleted file mode 100644 index b83f8e2..0000000 --- a/lib/rapidjson/rapidjson.h +++ /dev/null @@ -1,654 +0,0 @@ -// 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 // malloc(), realloc(), free(), size_t -#include // memset(), memcpy(), memmove(), memcmp() - -/////////////////////////////////////////////////////////////////////////////// -// RAPIDJSON_VERSION_STRING -// -// ALWAYS synchronize the following 3 macros with corresponding variables in /CMakeLists.txt. -// - -//!@cond RAPIDJSON_HIDDEN_FROM_DOXYGEN -// token stringification -#define RAPIDJSON_STRINGIFY(x) RAPIDJSON_DO_STRINGIFY(x) -#define RAPIDJSON_DO_STRINGIFY(x) #x -//!@endcond - -/*! \def RAPIDJSON_MAJOR_VERSION - \ingroup RAPIDJSON_CONFIG - \brief Major version of RapidJSON in integer. -*/ -/*! \def RAPIDJSON_MINOR_VERSION - \ingroup RAPIDJSON_CONFIG - \brief Minor version of RapidJSON in integer. -*/ -/*! \def RAPIDJSON_PATCH_VERSION - \ingroup RAPIDJSON_CONFIG - \brief Patch version of RapidJSON in integer. -*/ -/*! \def RAPIDJSON_VERSION_STRING - \ingroup RAPIDJSON_CONFIG - \brief Version of RapidJSON in ".." string format. -*/ -#define RAPIDJSON_MAJOR_VERSION 1 -#define RAPIDJSON_MINOR_VERSION 0 -#define RAPIDJSON_PATCH_VERSION 2 -#define RAPIDJSON_VERSION_STRING \ - RAPIDJSON_STRINGIFY(RAPIDJSON_MAJOR_VERSION.RAPIDJSON_MINOR_VERSION.RAPIDJSON_PATCH_VERSION) - -/////////////////////////////////////////////////////////////////////////////// -// 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 -#include -#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 -# 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) || defined(__EMSCRIPTEN__) -#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 -#if RAPIDJSON_64BIT == 1 -#define RAPIDJSON_ALIGN(x) (((x) + static_cast(7u)) & ~static_cast(7u)) -#else -#define RAPIDJSON_ALIGN(x) (((x) + 3u) & ~3u) -#endif -#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(high32) << 32) | static_cast(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 -#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 struct STATIC_ASSERTION_FAILURE; -template <> struct STATIC_ASSERTION_FAILURE { enum { value = 1 }; }; -template 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)> \ - 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)) - -/////////////////////////////////////////////////////////////////////////////// -// 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 -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. - */ - enum { copyOptimization = 0 }; -}; - -//! Put N copies of a character to a stream. -template -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 -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(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 -struct StreamTraits > { - enum { copyOptimization = 1 }; -}; - -//! String stream with UTF8 encoding. -typedef GenericStringStream > StringStream; - -/////////////////////////////////////////////////////////////////////////////// -// InsituStringStream - -//! A read-write string stream. -/*! This string stream is particularly designed for in-situ parsing. - \note implements Stream concept -*/ -template -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(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(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 -struct StreamTraits > { - enum { copyOptimization = 1 }; -}; - -//! Insitu string stream with UTF8 encoding. -typedef GenericInsituStringStream > 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/lib/rapidjson/reader.h b/lib/rapidjson/reader.h deleted file mode 100644 index 02afc47..0000000 --- a/lib/rapidjson/reader.h +++ /dev/null @@ -1,1452 +0,0 @@ -// 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 -#pragma intrinsic(_BitScanForward) -#endif -#ifdef RAPIDJSON_SSE42 -#include -#elif defined(RAPIDJSON_SSE2) -#include -#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 // 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 Derived = void> -struct BaseReaderHandler { - typedef typename Encoding::Ch Ch; - - typedef typename internal::SelectIf, BaseReaderHandler, Derived>::Type Override; - - bool Default() { return true; } - bool Null() { return static_cast(*this).Default(); } - bool Bool(bool) { return static_cast(*this).Default(); } - bool Int(int) { return static_cast(*this).Default(); } - bool Uint(unsigned) { return static_cast(*this).Default(); } - bool Int64(int64_t) { return static_cast(*this).Default(); } - bool Uint64(uint64_t) { return static_cast(*this).Default(); } - bool Double(double) { return static_cast(*this).Default(); } - bool String(const Ch*, SizeType, bool) { return static_cast(*this).Default(); } - bool StartObject() { return static_cast(*this).Default(); } - bool Key(const Ch* str, SizeType len, bool copy) { return static_cast(*this).String(str, len, copy); } - bool EndObject(SizeType) { return static_cast(*this).Default(); } - bool StartArray() { return static_cast(*this).Default(); } - bool EndArray(SizeType) { return static_cast(*this).Default(); } -}; - -/////////////////////////////////////////////////////////////////////////////// -// StreamLocalCopy - -namespace internal { - -template::copyOptimization> -class StreamLocalCopy; - -//! Do copy optimization. -template -class StreamLocalCopy { -public: - StreamLocalCopy(Stream& original) : s(original), original_(original) {} - ~StreamLocalCopy() { original_ = s; } - - Stream s; - -private: - StreamLocalCopy& operator=(const StreamLocalCopy&) /* = delete */; - - Stream& original_; -}; - -//! Keep reference. -template -class StreamLocalCopy { -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 -void SkipWhitespace(InputStream& is) { - internal::StreamLocalCopy 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((reinterpret_cast(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_loadu_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((reinterpret_cast(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(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 -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 - ParseResult Parse(InputStream& is, Handler& handler) { - if (parseFlags & kParseIterativeFlag) - return IterativeParse(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(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 - ParseResult Parse(InputStream& is, Handler& handler) { - return Parse(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 - 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(is, handler, true); - RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID; - - SkipWhitespace(is); - - if (is.Take() != ':') - RAPIDJSON_PARSE_ERROR(kParseErrorObjectMissColon, is.Tell()); - - SkipWhitespace(is); - - ParseValue(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 - 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(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 - 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 - 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 - 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 - unsigned ParseHex4(InputStream& is) { - unsigned codepoint = 0; - for (int i = 0; i < 4; i++) { - Ch c = is.Take(); - codepoint <<= 4; - codepoint += static_cast(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 - class StackStream { - public: - typedef CharType Ch; - - StackStream(internal::Stack& stack) : stack_(stack), length_(0) {} - RAPIDJSON_FORCEINLINE void Put(Ch c) { - *stack_.template Push() = c; - ++length_; - } - size_t Length() const { return length_; } - Ch* Pop() { - return stack_.template Pop(length_); - } - - private: - StackStream(const StackStream&); - StackStream& operator=(const StackStream&); - - internal::Stack& stack_; - SizeType length_; - }; - - // Parse string and generate String event. Different code paths for kParseInsituFlag. - template - void ParseString(InputStream& is, Handler& handler, bool isKey = false) { - internal::StreamLocalCopy copy(is); - InputStream& s(copy.s); - - bool success = false; - if (parseFlags & kParseInsituFlag) { - typename InputStream::Ch *head = s.PutBegin(); - ParseStringToStream(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 stackStream(stack_); - ParseStringToStream(s, stackStream); - RAPIDJSON_PARSE_ERROR_EARLY_RETURN_VOID; - SizeType length = static_cast(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 - 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::Validate(is, os) : - !Transcoder::Transcode(is, os)) - RAPIDJSON_PARSE_ERROR(kParseErrorStringInvalidEncoding, is.Tell()); - } - } - } - - template - class NumberStream; - - template - class NumberStream { - 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 - class NumberStream : public NumberStream { - typedef NumberStream Base; - public: - NumberStream(GenericReader& reader, InputStream& is) : NumberStream(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 stackStream; - }; - - template - void ParseNumber(InputStream& is, Handler& handler) { - internal::StreamLocalCopy copy(is); - NumberStream 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(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(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(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(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(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(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'; - if (expMinus) { - while (s.Peek() >= '0' && s.Peek() <= '9') { - exp = exp * 10 + (s.Take() - '0'); - if (exp >= 214748364) { // Issue #313: prevent overflow exponent - while (s.Peek() >= '0' && s.Peek() <= '9') // Consume the rest of exponent - s.Take(); - } - } - } - else { // positive exp - int maxExp = 308 - expFrac; - while (s.Peek() >= '0' && s.Peek() <= '9') { - exp = exp * 10 + (s.Take() - '0'); - if (exp > maxExp) - 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(static_cast(~i64 + 1)); - else - cont = handler.Uint64(i64); - } - else { - if (minus) - cont = handler.Int(static_cast(~i + 1)); - else - cont = handler.Uint(i); - } - } - if (!cont) - RAPIDJSON_PARSE_ERROR(kParseErrorTermination, s.Tell()); - } - - // Parse any JSON value - template - void ParseValue(InputStream& is, Handler& handler) { - switch (is.Peek()) { - case 'n': ParseNull (is, handler); break; - case 't': ParseTrue (is, handler); break; - case 'f': ParseFalse (is, handler); break; - case '"': ParseString(is, handler); break; - case '{': ParseObject(is, handler); break; - case '[': ParseArray (is, handler); break; - default : ParseNumber(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 - 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(1) = n; - // Initialize and push the member/element count. - *stack_.template Push(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(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(is, handler); - if (HasParseError()) { - return IterativeParsingErrorState; - } - return dst; - - case IterativeParsingElementState: - // Must be non-compound value. Or it would be ObjectInitial or ArrayInitial state. - ParseValue(is, handler); - if (HasParseError()) { - return IterativeParsingErrorState; - } - return dst; - - case IterativeParsingMemberDelimiterState: - case IterativeParsingElementDelimiterState: - is.Take(); - // Update member/element count. - *stack_.template Top() = *stack_.template Top() + 1; - return dst; - - case IterativeParsingObjectFinishState: - { - // Get member count. - SizeType c = *stack_.template Pop(1); - // If the object is not empty, count the last member. - if (src == IterativeParsingMemberValueState) - ++c; - // Restore the state. - IterativeParsingState n = static_cast(*stack_.template Pop(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(1); - // If the array is not empty, count the last element. - if (src == IterativeParsingElementState) - ++c; - // Restore the state. - IterativeParsingState n = static_cast(*stack_.template Pop(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(is, handler); - if (HasParseError()) { - return IterativeParsingErrorState; - } - return IterativeParsingFinishState; - } - } - - template - void HandleError(IterativeParsingState src, InputStream& is) { - if (HasParseError()) { - // Error flag has been set. - return; - } - - switch (src) { - case IterativeParsingStartState: RAPIDJSON_PARSE_ERROR(kParseErrorDocumentEmpty, is.Tell()); return; - case IterativeParsingFinishState: RAPIDJSON_PARSE_ERROR(kParseErrorDocumentRootNotSingular, is.Tell()); return; - case IterativeParsingObjectInitialState: - case IterativeParsingMemberDelimiterState: RAPIDJSON_PARSE_ERROR(kParseErrorObjectMissName, is.Tell()); return; - case IterativeParsingMemberKeyState: RAPIDJSON_PARSE_ERROR(kParseErrorObjectMissColon, is.Tell()); return; - case IterativeParsingMemberValueState: RAPIDJSON_PARSE_ERROR(kParseErrorObjectMissCommaOrCurlyBracket, is.Tell()); return; - case IterativeParsingElementState: RAPIDJSON_PARSE_ERROR(kParseErrorArrayMissCommaOrSquareBracket, is.Tell()); return; - default: RAPIDJSON_PARSE_ERROR(kParseErrorUnspecificSyntaxError, is.Tell()); - } - } - - template - 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(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 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<> > Reader; - -RAPIDJSON_NAMESPACE_END - -#ifdef __GNUC__ -RAPIDJSON_DIAG_POP -#endif - -#ifdef _MSC_VER -RAPIDJSON_DIAG_POP -#endif - -#endif // RAPIDJSON_READER_H_ diff --git a/lib/rapidjson/stringbuffer.h b/lib/rapidjson/stringbuffer.h deleted file mode 100644 index 1c9c80b..0000000 --- a/lib/rapidjson/stringbuffer.h +++ /dev/null @@ -1,93 +0,0 @@ -// 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 // 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 -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() = c; } - void Flush() {} - - void Clear() { stack_.Clear(); } - void ShrinkToFit() { - // Push and pop a null terminator. This is safe. - *stack_.template Push() = '\0'; - stack_.ShrinkToFit(); - stack_.template Pop(1); - } - Ch* Push(size_t count) { return stack_.template Push(count); } - void Pop(size_t count) { stack_.template Pop(count); } - - const Ch* GetString() const { - // Push and pop a null terminator. This is safe. - *stack_.template Push() = '\0'; - stack_.template Pop(1); - - return stack_.template Bottom(); - } - - size_t GetSize() const { return stack_.GetSize(); } - - static const size_t kDefaultCapacity = 256; - mutable internal::Stack stack_; - -private: - // Prohibit copy constructor & assignment operator. - GenericStringBuffer(const GenericStringBuffer&); - GenericStringBuffer& operator=(const GenericStringBuffer&); -}; - -//! String buffer with UTF8 encoding -typedef GenericStringBuffer > StringBuffer; - -//! Implement specialized version of PutN() with memset() for better performance. -template<> -inline void PutN(GenericStringBuffer >& stream, char c, size_t n) { - std::memset(stream.stack_.Push(n), c, n * sizeof(c)); -} - -RAPIDJSON_NAMESPACE_END - -#endif // RAPIDJSON_STRINGBUFFER_H_ diff --git a/lib/rapidjson/writer.h b/lib/rapidjson/writer.h deleted file mode 100644 index 874faa8..0000000 --- a/lib/rapidjson/writer.h +++ /dev/null @@ -1,395 +0,0 @@ -// 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 // placement new - -#if RAPIDJSON_HAS_STDSTRING -#include -#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 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 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& str) { - return String(str.data(), SizeType(str.size())); - } -#endif - - bool StartObject() { - Prefix(kObjectType); - new (level_stack_.template Push()) 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()->inArray); - level_stack_.template Pop(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(true); - return WriteStartArray(); - } - - bool EndArray(SizeType elementCount = 0) { - (void)elementCount; - RAPIDJSON_ASSERT(level_stack_.GetSize() >= sizeof(Level)); - RAPIDJSON_ASSERT(level_stack_.template Top()->inArray); - level_stack_.template Pop(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 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::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(); - 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 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::WriteInt(int i) { - char *buffer = os_->Push(11); - const char* end = internal::i32toa(i, buffer); - os_->Pop(static_cast(11 - (end - buffer))); - return true; -} - -template<> -inline bool Writer::WriteUint(unsigned u) { - char *buffer = os_->Push(10); - const char* end = internal::u32toa(u, buffer); - os_->Pop(static_cast(10 - (end - buffer))); - return true; -} - -template<> -inline bool Writer::WriteInt64(int64_t i64) { - char *buffer = os_->Push(21); - const char* end = internal::i64toa(i64, buffer); - os_->Pop(static_cast(21 - (end - buffer))); - return true; -} - -template<> -inline bool Writer::WriteUint64(uint64_t u) { - char *buffer = os_->Push(20); - const char* end = internal::u64toa(u, buffer); - os_->Pop(static_cast(20 - (end - buffer))); - return true; -} - -template<> -inline bool Writer::WriteDouble(double d) { - char *buffer = os_->Push(25); - char* end = internal::dtoa(d, buffer); - os_->Pop(static_cast(25 - (end - buffer))); - return true; -} - -RAPIDJSON_NAMESPACE_END - -#ifdef _MSC_VER -RAPIDJSON_DIAG_POP -#endif - -#endif // RAPIDJSON_RAPIDJSON_H_ diff --git a/rapidjson b/rapidjson new file mode 160000 index 0000000..bfdcf49 --- /dev/null +++ b/rapidjson @@ -0,0 +1 @@ +Subproject commit bfdcf4911047688fec49014d575433e2e5eb05be From c4ab7d7773afb9deaac1bd64263a02405144e3c9 Mon Sep 17 00:00:00 2001 From: Pavel Rojtberg Date: Thu, 10 Jan 2019 18:33:48 +0100 Subject: [PATCH 5/5] add screenshot --- README.md | 2 ++ screenshot.jpg | Bin 0 -> 69530 bytes 2 files changed, 2 insertions(+) create mode 100644 screenshot.jpg diff --git a/README.md b/README.md index 91e28a6..660032f 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,8 @@ # PlanetScape Makin' the planets +![](screenshot.jpg) + The general idea will be to implement a bunch o noise functions that you can layer to make the planet the way you want and export a latlon or cubemap. TODO diff --git a/screenshot.jpg b/screenshot.jpg new file mode 100644 index 0000000000000000000000000000000000000000..a33bf7df68b1f03dd4bad4fc9f654edcc3e72486 GIT binary patch literal 69530 zcmeFZcT`hd_dl2rdKIKf=pab%By>~=pj7D~y>|#w0#XG9ArP8M35X!QcM<6XkfIck zDi9z7f*`$5p67kPzwd8mt(i6RTl3F5^PJ?Ybt%qeda#=_0HCEM2p|Oj03ZMz5cC)6?<@f%0NlWrCGpwqIpN>O?&8aT zrAMwl0YOflo}A*Mk`Pg800Dp?pX_fA01;l!zsp|;{>6R0Om^fN5a25>Cgu$nwR7~b zcM^5*@e&KR^A(d26&C|2ss#JmIe0h)aN0Y$xOppa|8DEx=5%vZ;x?7h5!dm(=j7_9 ziST!NgwQo|KzKMn9l2GMITeHDgS~vcoC54PgS|Yx;qt*s+6RNJLITLQG0YPDx2YPC-FMO?QKenwFY^;s)al+MDzY3=EVsOw5e* z%yje&^nVEfg7D`M5|I%Rk3PT2g{9L;w(w8$dt{1knPodjTByg)R~B z@AR*QD!xvD*O8cnl#HAL&(L@SKmY`R2na!cX^p2o#nSnJ3Qb?U{G)fBIa3a-18Ul38`u68JVwMzsV|iS6KAExTLhKuD+qMskx=~ zLw8SaUq5DGaAE(-IPKNf6Vi8Iaid-Q<>xBBj5JdRyB?#v^68%V6*Sm7I}R zdYNzUFKB-w`@aV)`hN-8{{Z&ixMl&AARzwYfoK6LfQzz%1OdQ5`5znn(+B?P1ON1a zfBL}xdLQ^1VD`1bsIF8Ynb)LYd7JIo0uqt1b@BQd(9)41md0_+^rtGX>=ZTXcVKGE zt#(0iYE*){2KYt%M!}}SdU94us!n;5uR^LX{|NT_sb2#WC$3KEKUJ=SaXDYD-+~Py z#-y(SpVZBf%n`WMh#%a^`3t2{-E;C*33Y>MkhI7b# zwb561^TF(J`7jv}*wSUc?WAsy-)=Yk=~XYrqeJ zS2g?84%iPuzfLN=B5<=D=SPC8CX9LeTQryF^r1B3>&m&em~xX0u!LD-1In?rUIExa)=p8#dqe>awCFh3SP0Y5aItlg(*i znd68Z)Q2@|D<$KhzCJMB6lsdLyU8faSQs^67NxxKsWFgEOviBPyCsvs)LT`(jV)N+ zK1E(egX!i0JIBP3+!-Y>`L6xLtKjmZGsagrFDV{f*lebcA6eVM|7a&%h9;{{FarX% z?gB}OiMA&i&6~b>(%UthD*^y>1lNFAF_(3PyyO7WUk*QS*?Zc(pM5f`85NpWWcE^R z9K$j5E$?_aqC44Tok``^&+3_z3zhc~U*spQF2qiZUtFjZT?4+z{#`RX3b%vr*(Y4q zB=?-zT!Oq*es|-=Tl}l$iNEOG5wYMX_#R`zWp{GV2h&T?zYm(}QE%8BP}W}qIs>i& z(5JWvAMvJAudCp7DL#7`!dYe3}26@z@RkJdFH z|M9CUQ1OYu0Fw%_YxQF9?l*kbP;C>tAko_`mpF0J>bwTT8~@E?xJHo|Wn}vMEZ9L4 za}iz9@mEWQHk7WXDtm&pn9ET96N4cpmAoOLGZH<@pVxo`@>;x-j(8z;zCb3>c{fp>4m|8-D`<(=P77;-vq(S@2un$#{pm}*0(pN4LaMCabojT% zQ5S#k`poPuCg!IVnMKN{dFCzS%}2VE!lL@M!kotBT+(l2E(@v=q1a%0ApMEuYkr!_ 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�{yk1e<2x5<^Eyl!=ux!FOk?D+P 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 literal 0 HcmV?d00001