diff options
136 files changed, 3526 insertions, 3579 deletions
diff --git a/.gitlab/os-windows.yml b/.gitlab/os-windows.yml index 90ff0a8..8037b33 100644 --- a/.gitlab/os-windows.yml +++ b/.gitlab/os-windows.yml @@ -38,7 +38,7 @@ CMAKE_CONFIGURATION: windows_vs2019_x64_ninja VCVARSALL: "${VS160COMNTOOLS}\\..\\..\\VC\\Auxiliary\\Build\\vcvarsall.bat" VCVARSPLATFORM: "x64" - VCVARSVERSION: "14.29.30037" + VCVARSVERSION: "14.29.30133" ### External testing @@ -49,7 +49,7 @@ CMAKE_CONFIGURATION: windows_vs2019_x64 CMAKE_GENERATOR: "Visual Studio 16 2019" CMAKE_GENERATOR_PLATFORM: "x64" - CMAKE_GENERATOR_TOOLSET: "v142,version=14.29.30037" + CMAKE_GENERATOR_TOOLSET: "v142,version=14.29.30133" CMAKE_CI_NIGHTLY_IGNORE_DEPS: "true" ## Tags @@ -60,7 +60,7 @@ - windows - shell - vs2019 - - msvc-19.29-16.10 + - msvc-19.29-16.11 - nonconcurrent .windows_builder_ext_tags: @@ -69,7 +69,7 @@ - windows - shell - vs2019 - - msvc-19.29-16.10 + - msvc-19.29-16.11 - concurrent ## Windows-specific scripts diff --git a/Help/command/ctest_submit.rst b/Help/command/ctest_submit.rst index e6d277f..d661825 100644 --- a/Help/command/ctest_submit.rst +++ b/Help/command/ctest_submit.rst @@ -30,7 +30,8 @@ The options are: Build = ctest_build results, in Build.xml Test = ctest_test results, in Test.xml Coverage = ctest_coverage results, in Coverage.xml - MemCheck = ctest_memcheck results, in DynamicAnalysis.xml + MemCheck = ctest_memcheck results, in DynamicAnalysis.xml and + DynamicAnalysis-Test.xml Notes = Files listed by CTEST_NOTES_FILES, in Notes.xml ExtraFiles = Files listed by CTEST_EXTRA_SUBMIT_FILES Upload = Files prepared for upload by ctest_upload(), in Upload.xml diff --git a/Help/command/find_package.rst b/Help/command/find_package.rst index 490a5c7..8388709 100644 --- a/Help/command/find_package.rst +++ b/Help/command/find_package.rst @@ -55,12 +55,13 @@ The ``[version]`` argument requests a version with which the package found should be compatible. There are two possible forms in which it may be specified: - * A single version with the format ``major[.minor[.patch[.tweak]]]``. + * A single version with the format ``major[.minor[.patch[.tweak]]]``, where + each component is a numeric value. * A version range with the format ``versionMin...[<]versionMax`` where - ``versionMin`` and ``versionMax`` have the same format as the single - version. By default, both end points are included. By specifying ``<``, - the upper end point will be excluded. Version ranges are only supported - with CMake 3.19 or later. + ``versionMin`` and ``versionMax`` have the same format and constraints + on components being integers as the single version. By default, both end + points are included. By specifying ``<``, the upper end point will be + excluded. Version ranges are only supported with CMake 3.19 or later. The ``EXACT`` option requests that the version be matched exactly. This option is incompatible with the specification of a version range. diff --git a/Help/manual/cmake-policies.7.rst b/Help/manual/cmake-policies.7.rst index b9e3d45..0f0c0ab 100644 --- a/Help/manual/cmake-policies.7.rst +++ b/Help/manual/cmake-policies.7.rst @@ -51,6 +51,14 @@ The :variable:`CMAKE_MINIMUM_REQUIRED_VERSION` variable may also be used to determine whether to report an error on use of deprecated macros or functions. +Policies Introduced by CMake 3.22 +================================= + +.. toctree:: + :maxdepth: 1 + + CMP0127: cmake_dependent_option() supports full Condition Syntax. </policy/CMP0127> + Policies Introduced by CMake 3.21 ================================= diff --git a/Help/policy/CMP0127.rst b/Help/policy/CMP0127.rst new file mode 100644 index 0000000..8560bbf --- /dev/null +++ b/Help/policy/CMP0127.rst @@ -0,0 +1,32 @@ +CMP0127 +------- + +:command:`cmake_dependent_option` supports full :ref:`Condition Syntax`. + +The ``<depends>`` parameter accepts a :ref:`semicolon-separated list <CMake +Language Lists>` of conditions. CMake 3.21 and lower evaluates each +``condition`` as ``if(${condition})``, which does not properly handle +conditions with nested paren groups. CMake 3.22 and above instead prefer +to evaluate each ``condition`` as ``if(<condition>)``, where ``<condition>`` +is re-parsed as if literally written in a call to :command:`if`. This +allows expressions like:: + + "A AND (B OR C)" + +but requires expressions like:: + + "FOO MATCHES (UPPER|lower)" + +to be re-written as:: + + "FOO MATCHES \"(UPPER|lower)\"" + +Policy ``CMP0127`` provides compatibility for projects that have not +been updated to expect the new behavior. + +This policy was introduced in CMake version 3.22. CMake version +|release| warns when the policy is not set and uses ``OLD`` behavior. +Use the :command:`cmake_policy` command to set it to ``OLD`` or ``NEW`` +explicitly. + +.. include:: DEPRECATED.txt diff --git a/Help/prop_sf/VS_SETTINGS.rst b/Help/prop_sf/VS_SETTINGS.rst index 322f5a6..871e36e 100644 --- a/Help/prop_sf/VS_SETTINGS.rst +++ b/Help/prop_sf/VS_SETTINGS.rst @@ -3,7 +3,12 @@ VS_SETTINGS .. versionadded:: 3.18 -Set any item metadata on a non-built file. +Set any item metadata on a file. + +.. versionadded:: 3.22 + + This property is honored for all source file types. + Previously it worked only for non-built files. Takes a list of ``Key=Value`` pairs. Tells the Visual Studio generator to set ``Key`` to ``Value`` as item metadata on the file. diff --git a/Help/release/dev/cmake_dependent_option_policy.rst b/Help/release/dev/cmake_dependent_option_policy.rst new file mode 100644 index 0000000..c131170 --- /dev/null +++ b/Help/release/dev/cmake_dependent_option_policy.rst @@ -0,0 +1,6 @@ +cmake_dependent_option_policy +----------------------------- + +* The :module:`CMakeDependentOption` module :command:`cmake_dependent_option` + macro now supports full :ref:`Condition Syntax`. + See policy :policy:`CMP0127`. diff --git a/Help/release/dev/ctest_memcheck-generate-test.xml.rst b/Help/release/dev/ctest_memcheck-generate-test.xml.rst new file mode 100644 index 0000000..fac02d8 --- /dev/null +++ b/Help/release/dev/ctest_memcheck-generate-test.xml.rst @@ -0,0 +1,6 @@ +ctest_memcheck-generate-test.xml +-------------------------------- + +* The :command:`ctest_memcheck` command now also generates a + `DynamicAnalysis-Test.xml` file which may be used to submit test results to + CDash. diff --git a/Help/release/dev/vs_settings.rst b/Help/release/dev/vs_settings.rst new file mode 100644 index 0000000..64f3ced --- /dev/null +++ b/Help/release/dev/vs_settings.rst @@ -0,0 +1,5 @@ +vs_settings +----------- + +* The :prop_sf:`VS_SETTINGS` source file property is now supported for + all source file types. Previously it worked only for non-built sources. diff --git a/Modules/CMakeDependentOption.cmake b/Modules/CMakeDependentOption.cmake index 96855d2..b7c478f 100644 --- a/Modules/CMakeDependentOption.cmake +++ b/Modules/CMakeDependentOption.cmake @@ -10,44 +10,62 @@ Macro to provide an option dependent on other options. This macro presents an option to the user only if a set of other conditions are true. -Usage: +.. command:: cmake_dependent_option -.. code-block:: cmake + .. code-block:: cmake - cmake_dependent_option(<option> "<help_text>" <value> <depends> <force>) + cmake_dependent_option(<option> "<help_text>" <value> <depends> <force>) -Where ``<option>`` is available to the user if ``<depends>`` is true. When -``<option>`` is available, the given ``<help_text>`` and initial ``<value>`` -are used. If the ``<depends>`` condition is not true, ``<option>`` will not be -presented and will always have the value given by ``<force>``. Any value set by -the user is preserved for when the option is presented again. Each element in -the fourth parameter is evaluated as an if-condition, so -:ref:`Condition Syntax` can be used. + Makes ``<option>`` available to the user if ``<depends>`` is true. When + ``<option>`` is available, the given ``<help_text>`` and initial ``<value>`` + are used. If the ``<depends>`` condition is not true, ``<option>`` will not be + presented and will always have the value given by ``<force>``. Any value set by + the user is preserved for when the option is presented again. In case ``<depends>`` + is a :ref:`semicolon-separated list <CMake Language Lists>`, all elements must + be true in order to initialize ``<option>`` with ``<value>``. Example invocation: .. code-block:: cmake - cmake_dependent_option(USE_FOO "Use Foo" ON - "USE_BAR;NOT USE_ZOT" OFF) + cmake_dependent_option(USE_FOO "Use Foo" ON "USE_BAR;NOT USE_ZOT" OFF) If ``USE_BAR`` is true and ``USE_ZOT`` is false, this provides an option called ``USE_FOO`` that defaults to ON. Otherwise, it sets ``USE_FOO`` to OFF and hides the option from the user. If the status of ``USE_BAR`` or ``USE_ZOT`` ever changes, any value for the ``USE_FOO`` option is saved so that when the option is re-enabled it retains its old value. + +.. versionadded:: 3.22 + + Full :ref:`Condition Syntax` is now supported. See policy :policy:`CMP0127`. + #]=======================================================================] macro(CMAKE_DEPENDENT_OPTION option doc default depends force) + cmake_policy(GET CMP0127 _CDO_CMP0127 + PARENT_SCOPE # undocumented, do not use outside of CMake + ) if(${option}_ISSET MATCHES "^${option}_ISSET$") set(${option}_AVAILABLE 1) - foreach(d ${depends}) - string(REGEX REPLACE " +" ";" CMAKE_DEPENDENT_OPTION_DEP "${d}") - if(${CMAKE_DEPENDENT_OPTION_DEP}) - else() - set(${option}_AVAILABLE 0) - endif() - endforeach() + if("x${_CDO_CMP0127}x" STREQUAL "xNEWx") + foreach(d ${depends}) + cmake_language(EVAL CODE " + if (${d}) + else() + set(${option}_AVAILABLE 0) + endif()" + ) + endforeach() + else() + foreach(d ${depends}) + string(REGEX REPLACE " +" ";" CMAKE_DEPENDENT_OPTION_DEP "${d}") + if(${CMAKE_DEPENDENT_OPTION_DEP}) + else() + set(${option}_AVAILABLE 0) + endif() + endforeach() + endif() if(${option}_AVAILABLE) option(${option} "${doc}" "${default}") set(${option} "${${option}}" CACHE BOOL "${doc}" FORCE) @@ -61,4 +79,9 @@ macro(CMAKE_DEPENDENT_OPTION option doc default depends force) else() set(${option} "${${option}_ISSET}") endif() + if("x${_CDO_CMP0127}x" STREQUAL "xx" AND "x${depends}x" MATCHES "[^A-Za-z0-9_; ]") + cmake_policy(GET_WARNING CMP0127 _CDO_CMP0127_WARNING) + message(AUTHOR_WARNING "${_CDO_CMP0127_WARNING}") + endif() + unset(_CDO_CMP0127) endmacro() diff --git a/Modules/CMakeDetermineASMCompiler.cmake b/Modules/CMakeDetermineASMCompiler.cmake index e8b9db7..a1814b7 100644 --- a/Modules/CMakeDetermineASMCompiler.cmake +++ b/Modules/CMakeDetermineASMCompiler.cmake @@ -125,6 +125,7 @@ if(NOT CMAKE_ASM${ASM_DIALECT}_COMPILER_ID) include(CMakeDetermineCompilerId) set(userflags) CMAKE_DETERMINE_COMPILER_ID_VENDOR(ASM${ASM_DIALECT} "${userflags}") + set(_variant "") if("x${CMAKE_ASM${ASM_DIALECT}_COMPILER_ID}" STREQUAL "xIAR") # primary necessary to detect architecture, so the right archiver and linker can be picked # eg. "IAR Assembler V8.10.1.12857/W32 for ARM" or "IAR Assembler V4.11.1.4666 for Renesas RX" @@ -137,6 +138,19 @@ if(NOT CMAKE_ASM${ASM_DIALECT}_COMPILER_ID) if(_all_compileid_matches) list(GET _all_compileid_matches "-1" CMAKE_ASM${ASM_DIALECT}_COMPILER_ARCHITECTURE_ID) endif() + elseif("x${CMAKE_ASM${ASM_DIALECT}_COMPILER_ID}" STREQUAL "xClang") + # Test whether an MSVC-like command-line option works. + execute_process(COMMAND ${CMAKE_ASM${ASM_DIALECT}_COMPILER} -? + OUTPUT_VARIABLE _clang_output + ERROR_VARIABLE _clang_output + RESULT_VARIABLE _clang_result) + if(_clang_result EQUAL 0) + set(CMAKE_ASM${ASM_DIALECT}_COMPILER_FRONTEND_VARIANT "MSVC") + set(CMAKE_ASM${ASM_DIALECT}_SIMULATE_ID MSVC) + else() + set(CMAKE_ASM${ASM_DIALECT}_COMPILER_FRONTEND_VARIANT "GNU") + endif() + set(_variant " with ${CMAKE_ASM${ASM_DIALECT}_COMPILER_FRONTEND_VARIANT}-like command-line") endif() _cmake_find_compiler_sysroot(ASM${ASM_DIALECT}) @@ -144,6 +158,8 @@ if(NOT CMAKE_ASM${ASM_DIALECT}_COMPILER_ID) unset(CMAKE_ASM${ASM_DIALECT}_COMPILER_ID_OUTPUT) unset(_all_compileid_matches) unset(_compileid) + unset(_clang_result) + unset(_clang_output) endif() if(CMAKE_ASM${ASM_DIALECT}_COMPILER_ID) @@ -157,9 +173,10 @@ if(CMAKE_ASM${ASM_DIALECT}_COMPILER_ID) else() set(_archid "") endif() - message(STATUS "The ASM${ASM_DIALECT} compiler identification is ${CMAKE_ASM${ASM_DIALECT}_COMPILER_ID}${_archid}${_version}") + message(STATUS "The ASM${ASM_DIALECT} compiler identification is ${CMAKE_ASM${ASM_DIALECT}_COMPILER_ID}${_archid}${_version}${_variant}") unset(_archid) unset(_version) + unset(_variant) else() message(STATUS "The ASM${ASM_DIALECT} compiler identification is unknown") endif() diff --git a/Modules/CMakeFindPackageMode.cmake b/Modules/CMakeFindPackageMode.cmake index 815dfc9..726e2a2 100644 --- a/Modules/CMakeFindPackageMode.cmake +++ b/Modules/CMakeFindPackageMode.cmake @@ -78,7 +78,7 @@ if(UNIX) # from the outside if(NOT CMAKE_SIZEOF_VOID_P) set(CMAKE_SIZEOF_VOID_P 4) - if(EXISTS /usr/lib64) + if(EXISTS ${CMAKE_SYSROOT}/usr/lib64) set(CMAKE_SIZEOF_VOID_P 8) else() # use the file utility to check whether itself is 64 bit: diff --git a/Modules/Compiler/Clang-C.cmake b/Modules/Compiler/Clang-C.cmake index cf493d7..1b765ad 100644 --- a/Modules/Compiler/Clang-C.cmake +++ b/Modules/Compiler/Clang-C.cmake @@ -9,6 +9,7 @@ endif() if("x${CMAKE_C_COMPILER_FRONTEND_VARIANT}" STREQUAL "xMSVC") set(CMAKE_C_COMPILE_OPTIONS_EXPLICIT_LANGUAGE -TC) set(CMAKE_C_CLANG_TIDY_DRIVER_MODE "cl") + set(CMAKE_C_INCLUDE_WHAT_YOU_USE_DRIVER_MODE "cl") if((NOT DEFINED CMAKE_DEPENDS_USE_COMPILER OR CMAKE_DEPENDS_USE_COMPILER) AND CMAKE_GENERATOR MATCHES "Makefiles|WMake" AND CMAKE_DEPFILE_FLAGS_C) diff --git a/Modules/Compiler/Clang-CXX.cmake b/Modules/Compiler/Clang-CXX.cmake index 98828e0..84b05d7 100644 --- a/Modules/Compiler/Clang-CXX.cmake +++ b/Modules/Compiler/Clang-CXX.cmake @@ -22,6 +22,7 @@ endif() if("x${CMAKE_CXX_COMPILER_FRONTEND_VARIANT}" STREQUAL "xMSVC") set(CMAKE_CXX_CLANG_TIDY_DRIVER_MODE "cl") + set(CMAKE_CXX_INCLUDE_WHAT_YOU_USE_DRIVER_MODE "cl") if((NOT DEFINED CMAKE_DEPENDS_USE_COMPILER OR CMAKE_DEPENDS_USE_COMPILER) AND CMAKE_GENERATOR MATCHES "Makefiles" AND CMAKE_DEPFILE_FLAGS_CXX) diff --git a/Modules/Compiler/Intel-C.cmake b/Modules/Compiler/Intel-C.cmake index ead9069..9884b58 100644 --- a/Modules/Compiler/Intel-C.cmake +++ b/Modules/Compiler/Intel-C.cmake @@ -17,6 +17,7 @@ if("x${CMAKE_C_SIMULATE_ID}" STREQUAL "xMSVC") set(CMAKE_C_COMPILE_OPTIONS_EXPLICIT_LANGUAGE -TC) set(CMAKE_C_CLANG_TIDY_DRIVER_MODE "cl") + set(CMAKE_C_INCLUDE_WHAT_YOU_USE_DRIVER_MODE "cl") if (NOT CMAKE_C_COMPILER_VERSION VERSION_LESS 16.0.0) set(CMAKE_C11_STANDARD_COMPILE_OPTION "-Qstd=c11") diff --git a/Modules/Compiler/Intel-CXX.cmake b/Modules/Compiler/Intel-CXX.cmake index 37f339a..7c9cca9 100644 --- a/Modules/Compiler/Intel-CXX.cmake +++ b/Modules/Compiler/Intel-CXX.cmake @@ -16,6 +16,7 @@ endif() if("x${CMAKE_CXX_SIMULATE_ID}" STREQUAL "xMSVC") set(CMAKE_CXX_CLANG_TIDY_DRIVER_MODE "cl") + set(CMAKE_CXX_INCLUDE_WHAT_YOU_USE_DRIVER_MODE "cl") if (NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 19.0.0) set(CMAKE_CXX20_STANDARD_COMPILE_OPTION "-Qstd=c++20") diff --git a/Modules/Compiler/IntelLLVM-C.cmake b/Modules/Compiler/IntelLLVM-C.cmake index d69d064..d7346f6 100644 --- a/Modules/Compiler/IntelLLVM-C.cmake +++ b/Modules/Compiler/IntelLLVM-C.cmake @@ -4,6 +4,7 @@ __compiler_intel_llvm(C) if("x${CMAKE_C_COMPILER_FRONTEND_VARIANT}" STREQUAL "xMSVC") set(CMAKE_C_COMPILE_OPTIONS_EXPLICIT_LANGUAGE -TC) set(CMAKE_C_CLANG_TIDY_DRIVER_MODE "cl") + set(CMAKE_C_INCLUDE_WHAT_YOU_USE_DRIVER_MODE "cl") if((NOT DEFINED CMAKE_DEPENDS_USE_COMPILER OR CMAKE_DEPENDS_USE_COMPILER) AND CMAKE_GENERATOR MATCHES "Makefiles|WMake" AND CMAKE_DEPFILE_FLAGS_C) diff --git a/Modules/Compiler/IntelLLVM-CXX.cmake b/Modules/Compiler/IntelLLVM-CXX.cmake index 9799888..cae1f11 100644 --- a/Modules/Compiler/IntelLLVM-CXX.cmake +++ b/Modules/Compiler/IntelLLVM-CXX.cmake @@ -4,6 +4,7 @@ __compiler_intel_llvm(CXX) if("x${CMAKE_CXX_COMPILER_FRONTEND_VARIANT}" STREQUAL "xMSVC") set(CMAKE_CXX_COMPILE_OPTIONS_EXPLICIT_LANGUAGE -TP) set(CMAKE_CXX_CLANG_TIDY_DRIVER_MODE "cl") + set(CMAKE_CXX_INCLUDE_WHAT_YOU_USE_DRIVER_MODE "cl") if((NOT DEFINED CMAKE_DEPENDS_USE_COMPILER OR CMAKE_DEPENDS_USE_COMPILER) AND CMAKE_GENERATOR MATCHES "Makefiles|WMake" AND CMAKE_DEPFILE_FLAGS_CXX) diff --git a/Modules/Compiler/MSVC-C.cmake b/Modules/Compiler/MSVC-C.cmake index 73cca36..4ba1eea 100644 --- a/Modules/Compiler/MSVC-C.cmake +++ b/Modules/Compiler/MSVC-C.cmake @@ -29,6 +29,7 @@ endif() set(CMAKE_C_COMPILE_OPTIONS_EXPLICIT_LANGUAGE -TC) set(CMAKE_C_CLANG_TIDY_DRIVER_MODE "cl") +set(CMAKE_C_INCLUDE_WHAT_YOU_USE_DRIVER_MODE "cl") # There are no C compiler modes so we hard-code the known compiler supported # features. Override the default macro for this special case. Pretend that diff --git a/Modules/Compiler/MSVC-CXX.cmake b/Modules/Compiler/MSVC-CXX.cmake index 09fe851..9bb7722 100644 --- a/Modules/Compiler/MSVC-CXX.cmake +++ b/Modules/Compiler/MSVC-CXX.cmake @@ -4,6 +4,7 @@ include(Compiler/CMakeCommonCompilerMacros) set(CMAKE_CXX_CLANG_TIDY_DRIVER_MODE "cl") +set(CMAKE_CXX_INCLUDE_WHAT_YOU_USE_DRIVER_MODE "cl") if ((CMAKE_CXX_COMPILER_VERSION VERSION_GREATER_EQUAL 19.0.24215.1 AND CMAKE_CXX_COMPILER_VERSION VERSION_LESS 19.10) OR diff --git a/Modules/FindICU.cmake b/Modules/FindICU.cmake index 2bb49ad..1bae825 100644 --- a/Modules/FindICU.cmake +++ b/Modules/FindICU.cmake @@ -172,7 +172,7 @@ function(_ICU_FIND) DOC "ICU ${program} executable" NO_PACKAGE_ROOT_PATH ) - mark_as_advanced(cache_var) + mark_as_advanced("${cache_var}") set("${program_var}" "${${cache_var}}" PARENT_SCOPE) endforeach() @@ -301,7 +301,7 @@ function(_ICU_FIND) HINTS ${icu_roots} PATH_SUFFIXES ${icu_data_suffixes} DOC "ICU ${data} data file") - mark_as_advanced(cache_var) + mark_as_advanced("${cache_var}") set("${data_var}" "${${cache_var}}" PARENT_SCOPE) endforeach() diff --git a/Modules/FindThreads.cmake b/Modules/FindThreads.cmake index c6a3451..e4d6cf3 100644 --- a/Modules/FindThreads.cmake +++ b/Modules/FindThreads.cmake @@ -106,7 +106,7 @@ endmacro() # Do NOT even think about using it outside of this file! macro(_check_pthreads_flag) if(NOT Threads_FOUND) - # If we did not found -lpthread, -lpthread, or -lthread, look for -pthread + # If we did not find -lpthreads, -lpthread, or -lthread, look for -pthread if(NOT DEFINED THREADS_HAVE_PTHREAD_ARG) message(CHECK_START "Check if compiler accepts -pthread") if(CMAKE_C_COMPILER_LOADED) diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index 38639a9..94e36e8 100644 --- a/Source/CMakeVersion.cmake +++ b/Source/CMakeVersion.cmake @@ -1,7 +1,7 @@ # CMake version number components. set(CMake_VERSION_MAJOR 3) set(CMake_VERSION_MINOR 21) -set(CMake_VERSION_PATCH 20210908) +set(CMake_VERSION_PATCH 20210914) #set(CMake_VERSION_RC 0) set(CMake_VERSION_IS_DIRTY 0) diff --git a/Source/CPack/IFW/cmCPackIFWCommon.cxx b/Source/CPack/IFW/cmCPackIFWCommon.cxx index 87ebbfe..177a959 100644 --- a/Source/CPack/IFW/cmCPackIFWCommon.cxx +++ b/Source/CPack/IFW/cmCPackIFWCommon.cxx @@ -21,7 +21,7 @@ cmCPackIFWCommon::cmCPackIFWCommon() { } -const char* cmCPackIFWCommon::GetOption(const std::string& op) const +cmProp cmCPackIFWCommon::GetOption(const std::string& op) const { return this->Generator ? this->Generator->cmCPackGenerator::GetOption(op) : nullptr; diff --git a/Source/CPack/IFW/cmCPackIFWCommon.h b/Source/CPack/IFW/cmCPackIFWCommon.h index 42deda4..cf243dc 100644 --- a/Source/CPack/IFW/cmCPackIFWCommon.h +++ b/Source/CPack/IFW/cmCPackIFWCommon.h @@ -7,6 +7,8 @@ #include <map> #include <string> +#include "cmProperty.h" + class cmCPackIFWGenerator; class cmXMLWriter; @@ -26,7 +28,7 @@ public: public: // Internal implementation - const char* GetOption(const std::string& op) const; + cmProp GetOption(const std::string& op) const; bool IsOn(const std::string& op) const; bool IsSetToOff(const std::string& op) const; bool IsSetToEmpty(const std::string& op) const; diff --git a/Source/CPack/IFW/cmCPackIFWGenerator.cxx b/Source/CPack/IFW/cmCPackIFWGenerator.cxx index 2806c61..4993b40 100644 --- a/Source/CPack/IFW/cmCPackIFWGenerator.cxx +++ b/Source/CPack/IFW/cmCPackIFWGenerator.cxx @@ -14,6 +14,7 @@ #include "cmCPackLog.h" // IWYU pragma: keep #include "cmDuration.h" #include "cmGeneratedFileStream.h" +#include "cmProperty.h" #include "cmStringAlgorithms.h" #include "cmSystemTools.h" @@ -250,7 +251,7 @@ const char* cmCPackIFWGenerator::GetPackagingInstallPrefix() this->SetOption("CPACK_IFW_PACKAGING_INSTALL_PREFIX", tmpPref.c_str()); - return this->GetOption("CPACK_IFW_PACKAGING_INSTALL_PREFIX"); + return this->GetOption("CPACK_IFW_PACKAGING_INSTALL_PREFIX")->c_str(); } const char* cmCPackIFWGenerator::GetOutputExtension() @@ -273,11 +274,11 @@ int cmCPackIFWGenerator::InitializeInternal() // Look 'binarycreator' executable (needs) - const char* BinCreatorStr = this->GetOption(BinCreatorOpt); + cmProp BinCreatorStr = this->GetOption(BinCreatorOpt); if (!BinCreatorStr || cmIsNOTFOUND(BinCreatorStr)) { this->BinCreator.clear(); } else { - this->BinCreator = BinCreatorStr; + this->BinCreator = *BinCreatorStr; } if (this->BinCreator.empty()) { @@ -290,16 +291,16 @@ int cmCPackIFWGenerator::InitializeInternal() // Look 'repogen' executable (optional) - const char* RepoGenStr = this->GetOption(RepoGenOpt); - if (!RepoGenStr || cmIsNOTFOUND(RepoGenStr)) { + cmProp repoGen = this->GetOption(RepoGenOpt); + if (!repoGen || cmIsNOTFOUND(repoGen)) { this->RepoGen.clear(); } else { - this->RepoGen = RepoGenStr; + this->RepoGen = *repoGen; } // Framework version - if (const char* FrameworkVersionSrt = this->GetOption(FrameworkVersionOpt)) { - this->FrameworkVersion = FrameworkVersionSrt; + if (cmProp frameworkVersion = this->GetOption(FrameworkVersionOpt)) { + this->FrameworkVersion = *frameworkVersion; } else { this->FrameworkVersion = "1.9.9"; } @@ -312,14 +313,13 @@ int cmCPackIFWGenerator::InitializeInternal() // Additional packages dirs this->PkgsDirsVector.clear(); - if (const char* dirs = this->GetOption("CPACK_IFW_PACKAGES_DIRECTORIES")) { + if (cmProp dirs = this->GetOption("CPACK_IFW_PACKAGES_DIRECTORIES")) { cmExpandList(dirs, this->PkgsDirsVector); } // Additional repositories dirs this->RepoDirsVector.clear(); - if (const char* dirs = - this->GetOption("CPACK_IFW_REPOSITORIES_DIRECTORIES")) { + if (cmProp dirs = this->GetOption("CPACK_IFW_REPOSITORIES_DIRECTORIES")) { cmExpandList(dirs, this->RepoDirsVector); } @@ -330,23 +330,22 @@ int cmCPackIFWGenerator::InitializeInternal() // Repository this->Repository.Generator = this; this->Repository.Name = "Unspecified"; - if (const char* site = this->GetOption("CPACK_DOWNLOAD_SITE")) { - this->Repository.Url = site; + if (cmProp site = this->GetOption("CPACK_DOWNLOAD_SITE")) { + this->Repository.Url = *site; this->Installer.RemoteRepositories.push_back(&this->Repository); } // Repositories - if (const char* RepoAllStr = this->GetOption("CPACK_IFW_REPOSITORIES_ALL")) { + if (cmProp RepoAllStr = this->GetOption("CPACK_IFW_REPOSITORIES_ALL")) { std::vector<std::string> RepoAllVector = cmExpandedList(RepoAllStr); for (std::string const& r : RepoAllVector) { this->GetRepository(r); } } - if (const char* ifwDownloadAll = this->GetOption("CPACK_IFW_DOWNLOAD_ALL")) { + if (cmProp ifwDownloadAll = this->GetOption("CPACK_IFW_DOWNLOAD_ALL")) { this->OnlineOnly = cmIsOn(ifwDownloadAll); - } else if (const char* cpackDownloadAll = - this->GetOption("CPACK_DOWNLOAD_ALL")) { + } else if (cmProp cpackDownloadAll = this->GetOption("CPACK_DOWNLOAD_ALL")) { this->OnlineOnly = cmIsOn(cpackDownloadAll); } else { this->OnlineOnly = false; @@ -374,9 +373,8 @@ int cmCPackIFWGenerator::InitializeInternal() } // Output extension - if (const char* optOutExt = - this->GetOption("CPACK_IFW_PACKAGE_FILE_EXTENSION")) { - this->OutputExtension = optOutExt; + if (cmProp optOutExt = this->GetOption("CPACK_IFW_PACKAGE_FILE_EXTENSION")) { + this->OutputExtension = *optOutExt; } else if (sysName == "Darwin") { this->OutputExtension = ".dmg"; } else { @@ -508,21 +506,20 @@ std::string cmCPackIFWGenerator::GetRootPackageName() { // Default value std::string name = "root"; - if (const char* optIFW_PACKAGE_GROUP = + if (cmProp optIFW_PACKAGE_GROUP = this->GetOption("CPACK_IFW_PACKAGE_GROUP")) { // Configure from root group cmCPackIFWPackage package; package.Generator = this; package.ConfigureFromGroup(optIFW_PACKAGE_GROUP); name = package.Name; - } else if (const char* optIFW_PACKAGE_NAME = + } else if (cmProp optIFW_PACKAGE_NAME = this->GetOption("CPACK_IFW_PACKAGE_NAME")) { // Configure from root package name - name = optIFW_PACKAGE_NAME; - } else if (const char* optPACKAGE_NAME = - this->GetOption("CPACK_PACKAGE_NAME")) { + name = *optIFW_PACKAGE_NAME; + } else if (cmProp optPACKAGE_NAME = this->GetOption("CPACK_PACKAGE_NAME")) { // Configure from package name - name = optPACKAGE_NAME; + name = *optPACKAGE_NAME; } return name; } @@ -537,10 +534,10 @@ std::string cmCPackIFWGenerator::GetGroupPackageName( if (cmCPackIFWPackage* package = this->GetGroupPackage(group)) { return package->Name; } - const char* option = + cmProp option = this->GetOption("CPACK_IFW_COMPONENT_GROUP_" + cmsys::SystemTools::UpperCase(group->Name) + "_NAME"); - name = option ? option : group->Name; + name = option ? *option : group->Name; if (group->ParentGroup) { cmCPackIFWPackage* package = this->GetGroupPackage(group->ParentGroup); bool dot = !this->ResolveDuplicateNames; @@ -563,8 +560,8 @@ std::string cmCPackIFWGenerator::GetComponentPackageName( } std::string prefix = "CPACK_IFW_COMPONENT_" + cmsys::SystemTools::UpperCase(component->Name) + "_"; - const char* option = this->GetOption(prefix + "NAME"); - name = option ? option : component->Name; + cmProp option = this->GetOption(prefix + "NAME"); + name = option ? *option : component->Name; if (component->Group) { cmCPackIFWPackage* package = this->GetGroupPackage(component->Group); if ((this->componentPackageMethod == diff --git a/Source/CPack/IFW/cmCPackIFWInstaller.cxx b/Source/CPack/IFW/cmCPackIFWInstaller.cxx index bf8b457..23b73ff 100644 --- a/Source/CPack/IFW/cmCPackIFWInstaller.cxx +++ b/Source/CPack/IFW/cmCPackIFWInstaller.cxx @@ -12,6 +12,7 @@ #include "cmCPackIFWRepository.h" #include "cmCPackLog.h" // IWYU pragma: keep #include "cmGeneratedFileStream.h" +#include "cmProperty.h" #include "cmStringAlgorithms.h" #include "cmSystemTools.h" #include "cmXMLParser.h" @@ -33,61 +34,59 @@ void cmCPackIFWInstaller::printSkippedOptionWarning( void cmCPackIFWInstaller::ConfigureFromOptions() { // Name; - if (const char* optIFW_PACKAGE_NAME = - this->GetOption("CPACK_IFW_PACKAGE_NAME")) { - this->Name = optIFW_PACKAGE_NAME; - } else if (const char* optPACKAGE_NAME = - this->GetOption("CPACK_PACKAGE_NAME")) { - this->Name = optPACKAGE_NAME; + if (cmProp optIFW_PACKAGE_NAME = this->GetOption("CPACK_IFW_PACKAGE_NAME")) { + this->Name = *optIFW_PACKAGE_NAME; + } else if (cmProp optPACKAGE_NAME = this->GetOption("CPACK_PACKAGE_NAME")) { + this->Name = *optPACKAGE_NAME; } else { this->Name = "Your package"; } // Title; - if (const char* optIFW_PACKAGE_TITLE = + if (cmProp optIFW_PACKAGE_TITLE = this->GetOption("CPACK_IFW_PACKAGE_TITLE")) { - this->Title = optIFW_PACKAGE_TITLE; - } else if (const char* optPACKAGE_DESCRIPTION_SUMMARY = + this->Title = *optIFW_PACKAGE_TITLE; + } else if (cmProp optPACKAGE_DESCRIPTION_SUMMARY = this->GetOption("CPACK_PACKAGE_DESCRIPTION_SUMMARY")) { - this->Title = optPACKAGE_DESCRIPTION_SUMMARY; + this->Title = *optPACKAGE_DESCRIPTION_SUMMARY; } else { this->Title = "Your package description"; } // Version; - if (const char* option = this->GetOption("CPACK_PACKAGE_VERSION")) { - this->Version = option; + if (cmProp option = this->GetOption("CPACK_PACKAGE_VERSION")) { + this->Version = *option; } else { this->Version = "1.0.0"; } // Publisher - if (const char* optIFW_PACKAGE_PUBLISHER = + if (cmProp optIFW_PACKAGE_PUBLISHER = this->GetOption("CPACK_IFW_PACKAGE_PUBLISHER")) { - this->Publisher = optIFW_PACKAGE_PUBLISHER; - } else if (const char* optPACKAGE_VENDOR = + this->Publisher = *optIFW_PACKAGE_PUBLISHER; + } else if (cmProp optPACKAGE_VENDOR = this->GetOption("CPACK_PACKAGE_VENDOR")) { - this->Publisher = optPACKAGE_VENDOR; + this->Publisher = *optPACKAGE_VENDOR; } // ProductUrl - if (const char* option = this->GetOption("CPACK_IFW_PRODUCT_URL")) { - this->ProductUrl = option; + if (cmProp option = this->GetOption("CPACK_IFW_PRODUCT_URL")) { + this->ProductUrl = *option; } // ApplicationIcon - if (const char* option = this->GetOption("CPACK_IFW_PACKAGE_ICON")) { + if (cmProp option = this->GetOption("CPACK_IFW_PACKAGE_ICON")) { if (cmSystemTools::FileExists(option)) { - this->InstallerApplicationIcon = option; + this->InstallerApplicationIcon = *option; } else { this->printSkippedOptionWarning("CPACK_IFW_PACKAGE_ICON", option); } } // WindowIcon - if (const char* option = this->GetOption("CPACK_IFW_PACKAGE_WINDOW_ICON")) { + if (cmProp option = this->GetOption("CPACK_IFW_PACKAGE_WINDOW_ICON")) { if (cmSystemTools::FileExists(option)) { - this->InstallerWindowIcon = option; + this->InstallerWindowIcon = *option; } else { this->printSkippedOptionWarning("CPACK_IFW_PACKAGE_WINDOW_ICON", option); } @@ -103,45 +102,45 @@ void cmCPackIFWInstaller::ConfigureFromOptions() } // Logo - if (const char* option = this->GetOption("CPACK_IFW_PACKAGE_LOGO")) { + if (cmProp option = this->GetOption("CPACK_IFW_PACKAGE_LOGO")) { if (cmSystemTools::FileExists(option)) { - this->Logo = option; + this->Logo = *option; } else { this->printSkippedOptionWarning("CPACK_IFW_PACKAGE_LOGO", option); } } // Watermark - if (const char* option = this->GetOption("CPACK_IFW_PACKAGE_WATERMARK")) { + if (cmProp option = this->GetOption("CPACK_IFW_PACKAGE_WATERMARK")) { if (cmSystemTools::FileExists(option)) { - this->Watermark = option; + this->Watermark = *option; } else { this->printSkippedOptionWarning("CPACK_IFW_PACKAGE_WATERMARK", option); } } // Banner - if (const char* option = this->GetOption("CPACK_IFW_PACKAGE_BANNER")) { + if (cmProp option = this->GetOption("CPACK_IFW_PACKAGE_BANNER")) { if (cmSystemTools::FileExists(option)) { - this->Banner = option; + this->Banner = *option; } else { this->printSkippedOptionWarning("CPACK_IFW_PACKAGE_BANNER", option); } } // Background - if (const char* option = this->GetOption("CPACK_IFW_PACKAGE_BACKGROUND")) { + if (cmProp option = this->GetOption("CPACK_IFW_PACKAGE_BACKGROUND")) { if (cmSystemTools::FileExists(option)) { - this->Background = option; + this->Background = *option; } else { this->printSkippedOptionWarning("CPACK_IFW_PACKAGE_BACKGROUND", option); } } // WizardStyle - if (const char* option = this->GetOption("CPACK_IFW_PACKAGE_WIZARD_STYLE")) { + if (cmProp option = this->GetOption("CPACK_IFW_PACKAGE_WIZARD_STYLE")) { // Setting the user value in any case - this->WizardStyle = option; + this->WizardStyle = *option; // Check known values if (this->WizardStyle != "Modern" && this->WizardStyle != "Aero" && this->WizardStyle != "Mac" && this->WizardStyle != "Classic") { @@ -154,28 +153,28 @@ void cmCPackIFWInstaller::ConfigureFromOptions() } // StyleSheet - if (const char* option = this->GetOption("CPACK_IFW_PACKAGE_STYLE_SHEET")) { + if (cmProp option = this->GetOption("CPACK_IFW_PACKAGE_STYLE_SHEET")) { if (cmSystemTools::FileExists(option)) { - this->StyleSheet = option; + this->StyleSheet = *option; } else { this->printSkippedOptionWarning("CPACK_IFW_PACKAGE_STYLE_SHEET", option); } } // WizardDefaultWidth - if (const char* option = + if (cmProp option = this->GetOption("CPACK_IFW_PACKAGE_WIZARD_DEFAULT_WIDTH")) { - this->WizardDefaultWidth = option; + this->WizardDefaultWidth = *option; } // WizardDefaultHeight - if (const char* option = + if (cmProp option = this->GetOption("CPACK_IFW_PACKAGE_WIZARD_DEFAULT_HEIGHT")) { - this->WizardDefaultHeight = option; + this->WizardDefaultHeight = *option; } // WizardShowPageList - if (const char* option = + if (cmProp option = this->GetOption("CPACK_IFW_PACKAGE_WIZARD_SHOW_PAGE_LIST")) { if (!this->IsVersionLess("4.0")) { if (this->IsSetToOff("CPACK_IFW_PACKAGE_WIZARD_SHOW_PAGE_LIST")) { @@ -204,23 +203,23 @@ void cmCPackIFWInstaller::ConfigureFromOptions() } // TitleColor - if (const char* option = this->GetOption("CPACK_IFW_PACKAGE_TITLE_COLOR")) { - this->TitleColor = option; + if (cmProp option = this->GetOption("CPACK_IFW_PACKAGE_TITLE_COLOR")) { + this->TitleColor = *option; } // Start menu - if (const char* optIFW_START_MENU_DIR = + if (cmProp optIFW_START_MENU_DIR = this->GetOption("CPACK_IFW_PACKAGE_START_MENU_DIRECTORY")) { - this->StartMenuDir = optIFW_START_MENU_DIR; + this->StartMenuDir = *optIFW_START_MENU_DIR; } else { this->StartMenuDir = this->Name; } // Default target directory for installation - if (const char* optIFW_TARGET_DIRECTORY = + if (cmProp optIFW_TARGET_DIRECTORY = this->GetOption("CPACK_IFW_TARGET_DIRECTORY")) { - this->TargetDir = optIFW_TARGET_DIRECTORY; - } else if (const char* optPACKAGE_INSTALL_DIRECTORY = + this->TargetDir = *optIFW_TARGET_DIRECTORY; + } else if (cmProp optPACKAGE_INSTALL_DIRECTORY = this->GetOption("CPACK_PACKAGE_INSTALL_DIRECTORY")) { this->TargetDir = cmStrCat("@ApplicationsDir@/", optPACKAGE_INSTALL_DIRECTORY); @@ -229,21 +228,20 @@ void cmCPackIFWInstaller::ConfigureFromOptions() } // Default target directory for installation with administrator rights - if (const char* option = - this->GetOption("CPACK_IFW_ADMIN_TARGET_DIRECTORY")) { - this->AdminTargetDir = option; + if (cmProp option = this->GetOption("CPACK_IFW_ADMIN_TARGET_DIRECTORY")) { + this->AdminTargetDir = *option; } // Maintenance tool - if (const char* optIFW_MAINTENANCE_TOOL = + if (cmProp optIFW_MAINTENANCE_TOOL = this->GetOption("CPACK_IFW_PACKAGE_MAINTENANCE_TOOL_NAME")) { - this->MaintenanceToolName = optIFW_MAINTENANCE_TOOL; + this->MaintenanceToolName = *optIFW_MAINTENANCE_TOOL; } // Maintenance tool ini file - if (const char* optIFW_MAINTENANCE_TOOL_INI = + if (cmProp optIFW_MAINTENANCE_TOOL_INI = this->GetOption("CPACK_IFW_PACKAGE_MAINTENANCE_TOOL_INI_FILE")) { - this->MaintenanceToolIniFile = optIFW_MAINTENANCE_TOOL_INI; + this->MaintenanceToolIniFile = *optIFW_MAINTENANCE_TOOL_INI; } // Allow non-ASCII characters @@ -265,13 +263,13 @@ void cmCPackIFWInstaller::ConfigureFromOptions() } // Control script - if (const char* optIFW_CONTROL_SCRIPT = + if (cmProp optIFW_CONTROL_SCRIPT = this->GetOption("CPACK_IFW_PACKAGE_CONTROL_SCRIPT")) { - this->ControlScript = optIFW_CONTROL_SCRIPT; + this->ControlScript = *optIFW_CONTROL_SCRIPT; } // Resources - if (const char* optIFW_PACKAGE_RESOURCES = + if (cmProp optIFW_PACKAGE_RESOURCES = this->GetOption("CPACK_IFW_PACKAGE_RESOURCES")) { this->Resources.clear(); cmExpandList(optIFW_PACKAGE_RESOURCES, this->Resources); @@ -541,7 +539,7 @@ void cmCPackIFWInstaller::GeneratePackageFiles() package.Generator = this->Generator; package.Installer = this; // Check package group - if (const char* option = this->GetOption("CPACK_IFW_PACKAGE_GROUP")) { + if (cmProp option = this->GetOption("CPACK_IFW_PACKAGE_GROUP")) { package.ConfigureFromGroup(option); std::string forcedOption = "CPACK_IFW_COMPONENT_GROUP_" + cmsys::SystemTools::UpperCase(option) + "_FORCED_INSTALLATION"; diff --git a/Source/CPack/IFW/cmCPackIFWPackage.cxx b/Source/CPack/IFW/cmCPackIFWPackage.cxx index 1429c46..c1e11d2 100644 --- a/Source/CPack/IFW/cmCPackIFWPackage.cxx +++ b/Source/CPack/IFW/cmCPackIFWPackage.cxx @@ -15,6 +15,7 @@ #include "cmCPackIFWInstaller.h" #include "cmCPackLog.h" // IWYU pragma: keep #include "cmGeneratedFileStream.h" +#include "cmProperty.h" #include "cmStringAlgorithms.h" #include "cmSystemTools.h" #include "cmTimestamp.h" @@ -124,10 +125,10 @@ std::string cmCPackIFWPackage::GetComponentName(cmCPackComponent* component) if (!component) { return ""; } - const char* option = + cmProp option = this->GetOption("CPACK_IFW_COMPONENT_" + cmsys::SystemTools::UpperCase(component->Name) + "_NAME"); - return option ? option : component->Name; + return option ? *option : component->Name; } void cmCPackIFWPackage::DefaultConfiguration() @@ -159,23 +160,22 @@ int cmCPackIFWPackage::ConfigureFromOptions() this->Name = this->Generator->GetRootPackageName(); // Display name - if (const char* option = this->GetOption("CPACK_PACKAGE_NAME")) { - this->DisplayName[""] = option; + if (cmProp option = this->GetOption("CPACK_PACKAGE_NAME")) { + this->DisplayName[""] = *option; } else { this->DisplayName[""] = "Your package"; } // Description - if (const char* option = - this->GetOption("CPACK_PACKAGE_DESCRIPTION_SUMMARY")) { - this->Description[""] = option; + if (cmProp option = this->GetOption("CPACK_PACKAGE_DESCRIPTION_SUMMARY")) { + this->Description[""] = *option; } else { this->Description[""] = "Your package description"; } // Version - if (const char* option = this->GetOption("CPACK_PACKAGE_VERSION")) { - this->Version = option; + if (cmProp option = this->GetOption("CPACK_PACKAGE_VERSION")) { + this->Version = *option; } else { this->Version = "1.0.0"; } @@ -204,22 +204,22 @@ int cmCPackIFWPackage::ConfigureFromComponent(cmCPackComponent* component) this->Description[""] = component->Description; // Version - if (const char* optVERSION = this->GetOption(prefix + "VERSION")) { - this->Version = optVERSION; - } else if (const char* optPACKAGE_VERSION = + if (cmProp optVERSION = this->GetOption(prefix + "VERSION")) { + this->Version = *optVERSION; + } else if (cmProp optPACKAGE_VERSION = this->GetOption("CPACK_PACKAGE_VERSION")) { - this->Version = optPACKAGE_VERSION; + this->Version = *optPACKAGE_VERSION; } else { this->Version = "1.0.0"; } // Script - if (const char* option = this->GetOption(prefix + "SCRIPT")) { - this->Script = option; + if (cmProp option = this->GetOption(prefix + "SCRIPT")) { + this->Script = *option; } // User interfaces - if (const char* option = this->GetOption(prefix + "USER_INTERFACES")) { + if (cmProp option = this->GetOption(prefix + "USER_INTERFACES")) { this->UserInterfaces.clear(); cmExpandList(option, this->UserInterfaces); } @@ -232,7 +232,7 @@ int cmCPackIFWPackage::ConfigureFromComponent(cmCPackComponent* component) } // Licenses - if (const char* option = this->GetOption(prefix + "LICENSES")) { + if (cmProp option = this->GetOption(prefix + "LICENSES")) { this->Licenses.clear(); cmExpandList(option, this->Licenses); if (this->Licenses.size() % 2 != 0) { @@ -246,8 +246,8 @@ int cmCPackIFWPackage::ConfigureFromComponent(cmCPackComponent* component) } // Priority - if (const char* option = this->GetOption(prefix + "PRIORITY")) { - this->SortingPriority = option; + if (cmProp option = this->GetOption(prefix + "PRIORITY")) { + this->SortingPriority = *option; cmCPackIFWLogger( WARNING, "The \"PRIORITY\" option is set " @@ -289,28 +289,28 @@ int cmCPackIFWPackage::ConfigureFromGroup(cmCPackComponentGroup* group) this->Description[""] = group->Description; // Version - if (const char* optVERSION = this->GetOption(prefix + "VERSION")) { - this->Version = optVERSION; - } else if (const char* optPACKAGE_VERSION = + if (cmProp optVERSION = this->GetOption(prefix + "VERSION")) { + this->Version = *optVERSION; + } else if (cmProp optPACKAGE_VERSION = this->GetOption("CPACK_PACKAGE_VERSION")) { - this->Version = optPACKAGE_VERSION; + this->Version = *optPACKAGE_VERSION; } else { this->Version = "1.0.0"; } // Script - if (const char* option = this->GetOption(prefix + "SCRIPT")) { - this->Script = option; + if (cmProp option = this->GetOption(prefix + "SCRIPT")) { + this->Script = *option; } // User interfaces - if (const char* option = this->GetOption(prefix + "USER_INTERFACES")) { + if (cmProp option = this->GetOption(prefix + "USER_INTERFACES")) { this->UserInterfaces.clear(); cmExpandList(option, this->UserInterfaces); } // Licenses - if (const char* option = this->GetOption(prefix + "LICENSES")) { + if (cmProp option = this->GetOption(prefix + "LICENSES")) { this->Licenses.clear(); cmExpandList(option, this->Licenses); if (this->Licenses.size() % 2 != 0) { @@ -324,8 +324,8 @@ int cmCPackIFWPackage::ConfigureFromGroup(cmCPackComponentGroup* group) } // Priority - if (const char* option = this->GetOption(prefix + "PRIORITY")) { - this->SortingPriority = option; + if (cmProp option = this->GetOption(prefix + "PRIORITY")) { + this->SortingPriority = *option; cmCPackIFWLogger( WARNING, "The \"PRIORITY\" option is set " @@ -346,14 +346,14 @@ int cmCPackIFWPackage::ConfigureFromGroup(const std::string& groupName) std::string prefix = "CPACK_COMPONENT_GROUP_" + cmsys::SystemTools::UpperCase(groupName) + "_"; - if (const char* option = this->GetOption(prefix + "DISPLAY_NAME")) { - group.DisplayName = option; + if (cmProp option = this->GetOption(prefix + "DISPLAY_NAME")) { + group.DisplayName = *option; } else { group.DisplayName = group.Name; } - if (const char* option = this->GetOption(prefix + "DESCRIPTION")) { - group.Description = option; + if (cmProp option = this->GetOption(prefix + "DESCRIPTION")) { + group.Description = *option; } group.IsBold = this->IsOn(prefix + "BOLD_TITLE"); group.IsExpandedByDefault = this->IsOn(prefix + "EXPANDED"); @@ -381,7 +381,7 @@ int cmCPackIFWPackage::ConfigureFromPrefix(const std::string& prefix) option = prefix + "DISPLAY_NAME"; if (this->IsSetToEmpty(option)) { this->DisplayName.clear(); - } else if (const char* value = this->GetOption(option)) { + } else if (cmProp value = this->GetOption(option)) { cmCPackIFWPackage::ExpandListArgument(value, this->DisplayName); } @@ -389,7 +389,7 @@ int cmCPackIFWPackage::ConfigureFromPrefix(const std::string& prefix) option = prefix + "DESCRIPTION"; if (this->IsSetToEmpty(option)) { this->Description.clear(); - } else if (const char* value = this->GetOption(option)) { + } else if (cmProp value = this->GetOption(option)) { cmCPackIFWPackage::ExpandListArgument(value, this->Description); } @@ -397,31 +397,31 @@ int cmCPackIFWPackage::ConfigureFromPrefix(const std::string& prefix) option = prefix + "RELEASE_DATE"; if (this->IsSetToEmpty(option)) { this->ReleaseDate.clear(); - } else if (const char* value = this->GetOption(option)) { - this->ReleaseDate = value; + } else if (cmProp value = this->GetOption(option)) { + this->ReleaseDate = *value; } // Sorting priority option = prefix + "SORTING_PRIORITY"; if (this->IsSetToEmpty(option)) { this->SortingPriority.clear(); - } else if (const char* value = this->GetOption(option)) { - this->SortingPriority = value; + } else if (cmProp value = this->GetOption(option)) { + this->SortingPriority = *value; } // Update text option = prefix + "UPDATE_TEXT"; if (this->IsSetToEmpty(option)) { this->UpdateText.clear(); - } else if (const char* value = this->GetOption(option)) { - this->UpdateText = value; + } else if (cmProp value = this->GetOption(option)) { + this->UpdateText = *value; } // Translations option = prefix + "TRANSLATIONS"; if (this->IsSetToEmpty(option)) { this->Translations.clear(); - } else if (const char* value = this->GetOption(option)) { + } else if (cmProp value = this->GetOption(option)) { this->Translations.clear(); cmExpandList(value, this->Translations); } @@ -429,11 +429,11 @@ int cmCPackIFWPackage::ConfigureFromPrefix(const std::string& prefix) // QtIFW dependencies std::vector<std::string> deps; option = prefix + "DEPENDS"; - if (const char* value = this->GetOption(option)) { + if (cmProp value = this->GetOption(option)) { cmExpandList(value, deps); } option = prefix + "DEPENDENCIES"; - if (const char* value = this->GetOption(option)) { + if (cmProp value = this->GetOption(option)) { cmExpandList(value, deps); } for (std::string const& d : deps) { @@ -454,7 +454,7 @@ int cmCPackIFWPackage::ConfigureFromPrefix(const std::string& prefix) option = prefix + "AUTO_DEPEND_ON"; if (this->IsSetToEmpty(option)) { this->AlienAutoDependOn.clear(); - } else if (const char* value = this->GetOption(option)) { + } else if (cmProp value = this->GetOption(option)) { std::vector<std::string> depsOn = cmExpandedList(value); for (std::string const& d : depsOn) { DependenceStruct dep(d); @@ -483,7 +483,7 @@ int cmCPackIFWPackage::ConfigureFromPrefix(const std::string& prefix) option = prefix + "DEFAULT"; if (this->IsSetToEmpty(option)) { this->Default.clear(); - } else if (const char* value = this->GetOption(option)) { + } else if (cmProp value = this->GetOption(option)) { std::string lowerValue = cmsys::SystemTools::LowerCase(value); if (lowerValue == "true") { this->Default = "true"; @@ -492,7 +492,7 @@ int cmCPackIFWPackage::ConfigureFromPrefix(const std::string& prefix) } else if (lowerValue == "script") { this->Default = "script"; } else { - this->Default = value; + this->Default = *value; } } @@ -510,7 +510,7 @@ int cmCPackIFWPackage::ConfigureFromPrefix(const std::string& prefix) option = prefix + "REPLACES"; if (this->IsSetToEmpty(option)) { this->Replaces.clear(); - } else if (const char* value = this->GetOption(option)) { + } else if (cmProp value = this->GetOption(option)) { this->Replaces.clear(); cmExpandList(value, this->Replaces); } diff --git a/Source/CPack/IFW/cmCPackIFWRepository.cxx b/Source/CPack/IFW/cmCPackIFWRepository.cxx index 7ec2256..cc64e93 100644 --- a/Source/CPack/IFW/cmCPackIFWRepository.cxx +++ b/Source/CPack/IFW/cmCPackIFWRepository.cxx @@ -6,6 +6,7 @@ #include "cmCPackIFWGenerator.h" #include "cmGeneratedFileStream.h" +#include "cmProperty.h" #include "cmSystemTools.h" #include "cmXMLParser.h" #include "cmXMLWriter.h" @@ -55,22 +56,22 @@ bool cmCPackIFWRepository::ConfigureFromOptions() } // Url - if (const char* url = this->GetOption(prefix + "URL")) { - this->Url = url; + if (cmProp url = this->GetOption(prefix + "URL")) { + this->Url = *url; } else { this->Url.clear(); } // Old url - if (const char* oldUrl = this->GetOption(prefix + "OLD_URL")) { - this->OldUrl = oldUrl; + if (cmProp oldUrl = this->GetOption(prefix + "OLD_URL")) { + this->OldUrl = *oldUrl; } else { this->OldUrl.clear(); } // New url - if (const char* newUrl = this->GetOption(prefix + "NEW_URL")) { - this->NewUrl = newUrl; + if (cmProp newUrl = this->GetOption(prefix + "NEW_URL")) { + this->NewUrl = *newUrl; } else { this->NewUrl.clear(); } @@ -83,22 +84,22 @@ bool cmCPackIFWRepository::ConfigureFromOptions() } // Username - if (const char* username = this->GetOption(prefix + "USERNAME")) { - this->Username = username; + if (cmProp username = this->GetOption(prefix + "USERNAME")) { + this->Username = *username; } else { this->Username.clear(); } // Password - if (const char* password = this->GetOption(prefix + "PASSWORD")) { - this->Password = password; + if (cmProp password = this->GetOption(prefix + "PASSWORD")) { + this->Password = *password; } else { this->Password.clear(); } // DisplayName - if (const char* displayName = this->GetOption(prefix + "DISPLAY_NAME")) { - this->DisplayName = displayName; + if (cmProp displayName = this->GetOption(prefix + "DISPLAY_NAME")) { + this->DisplayName = *displayName; } else { this->DisplayName.clear(); } diff --git a/Source/CPack/WiX/cmCPackWIXGenerator.cxx b/Source/CPack/WiX/cmCPackWIXGenerator.cxx index 8b3644f..7ec2c3f 100644 --- a/Source/CPack/WiX/cmCPackWIXGenerator.cxx +++ b/Source/CPack/WiX/cmCPackWIXGenerator.cxx @@ -18,6 +18,7 @@ #include "cmCryptoHash.h" #include "cmGeneratedFileStream.h" #include "cmInstalledFile.h" +#include "cmProperty.h" #include "cmStringAlgorithms.h" #include "cmSystemTools.h" #include "cmUuid.h" @@ -125,7 +126,7 @@ bool cmCPackWIXGenerator::RunLightCommand(std::string const& objectFiles) command << " -ext " << QuotePath(ext); } - const char* const cultures = GetOption("CPACK_WIX_CULTURES"); + cmProp const cultures = GetOption("CPACK_WIX_CULTURES"); if (cultures) { command << " -cultures:" << cultures; } @@ -156,7 +157,7 @@ bool cmCPackWIXGenerator::InitializeWiXConfiguration() return false; } - if (GetOption("CPACK_WIX_PRODUCT_GUID") == 0) { + if (!GetOption("CPACK_WIX_PRODUCT_GUID")) { std::string guid = GenerateGUID(); SetOption("CPACK_WIX_PRODUCT_GUID", guid.c_str()); @@ -165,7 +166,7 @@ bool cmCPackWIXGenerator::InitializeWiXConfiguration() << std::endl); } - if (GetOption("CPACK_WIX_UPGRADE_GUID") == 0) { + if (!GetOption("CPACK_WIX_UPGRADE_GUID")) { std::string guid = GenerateGUID(); SetOption("CPACK_WIX_UPGRADE_GUID", guid.c_str()); @@ -182,7 +183,7 @@ bool cmCPackWIXGenerator::InitializeWiXConfiguration() return false; } - if (GetOption("CPACK_WIX_LICENSE_RTF") == 0) { + if (!GetOption("CPACK_WIX_LICENSE_RTF")) { std::string licenseFilename = this->CPackTopLevel + "/License.rtf"; SetOption("CPACK_WIX_LICENSE_RTF", licenseFilename.c_str()); @@ -191,7 +192,7 @@ bool cmCPackWIXGenerator::InitializeWiXConfiguration() } } - if (GetOption("CPACK_PACKAGE_VENDOR") == 0) { + if (!GetOption("CPACK_PACKAGE_VENDOR")) { std::string defaultVendor = "Humanity"; SetOption("CPACK_PACKAGE_VENDOR", defaultVendor.c_str()); @@ -200,7 +201,7 @@ bool cmCPackWIXGenerator::InitializeWiXConfiguration() << defaultVendor << " . " << std::endl); } - if (GetOption("CPACK_WIX_UI_REF") == 0) { + if (!GetOption("CPACK_WIX_UI_REF")) { std::string defaultRef = "WixUI_InstallDir"; if (!this->Components.empty()) { @@ -210,9 +211,9 @@ bool cmCPackWIXGenerator::InitializeWiXConfiguration() SetOption("CPACK_WIX_UI_REF", defaultRef.c_str()); } - const char* packageContact = GetOption("CPACK_PACKAGE_CONTACT"); - if (packageContact != 0 && GetOption("CPACK_WIX_PROPERTY_ARPCONTACT") == 0) { - SetOption("CPACK_WIX_PROPERTY_ARPCONTACT", packageContact); + cmProp packageContact = GetOption("CPACK_PACKAGE_CONTACT"); + if (packageContact && !GetOption("CPACK_WIX_PROPERTY_ARPCONTACT")) { + SetOption("CPACK_WIX_PROPERTY_ARPCONTACT", packageContact->c_str()); } CollectExtensions("CPACK_WIX_EXTENSIONS", this->CandleExtensions); @@ -223,7 +224,7 @@ bool cmCPackWIXGenerator::InitializeWiXConfiguration() CollectExtensions("CPACK_WIX_LIGHT_EXTENSIONS", this->LightExtensions); CollectXmlNamespaces("CPACK_WIX_CUSTOM_XMLNS", this->CustomXmlNamespaces); - const char* patchFilePath = GetOption("CPACK_WIX_PATCH_FILE"); + cmProp patchFilePath = GetOption("CPACK_WIX_PATCH_FILE"); if (patchFilePath) { std::vector<std::string> patchFilePaths = cmExpandedList(patchFilePath); @@ -295,7 +296,7 @@ bool cmCPackWIXGenerator::PackageFilesImpl() void cmCPackWIXGenerator::AppendUserSuppliedExtraSources() { - const char* cpackWixExtraSources = GetOption("CPACK_WIX_EXTRA_SOURCES"); + cmProp cpackWixExtraSources = GetOption("CPACK_WIX_EXTRA_SOURCES"); if (!cpackWixExtraSources) return; @@ -304,7 +305,7 @@ void cmCPackWIXGenerator::AppendUserSuppliedExtraSources() void cmCPackWIXGenerator::AppendUserSuppliedExtraObjects(std::ostream& stream) { - const char* cpackWixExtraObjects = GetOption("CPACK_WIX_EXTRA_OBJECTS"); + cmProp cpackWixExtraObjects = GetOption("CPACK_WIX_EXTRA_OBJECTS"); if (!cpackWixExtraObjects) return; @@ -335,7 +336,7 @@ void cmCPackWIXGenerator::CreateWiXVariablesIncludeFile() CopyDefinition(includeFile, "CPACK_WIX_UI_BANNER", DefinitionType::PATH); CopyDefinition(includeFile, "CPACK_WIX_UI_DIALOG", DefinitionType::PATH); SetOptionIfNotSet("CPACK_WIX_PROGRAM_MENU_FOLDER", - GetOption("CPACK_PACKAGE_NAME")); + GetOption("CPACK_PACKAGE_NAME").GetCStr()); CopyDefinition(includeFile, "CPACK_WIX_PROGRAM_MENU_FOLDER"); CopyDefinition(includeFile, "CPACK_WIX_UI_REF"); } @@ -355,7 +356,7 @@ void cmCPackWIXGenerator::CreateWiXPropertiesIncludeFile() for (std::string const& name : options) { if (cmHasPrefix(name, prefix)) { std::string id = name.substr(prefix.length()); - std::string value = GetOption(name.c_str()); + std::string value = GetOption(name); includeFile.BeginElement("Property"); includeFile.AddAttribute("Id", id); @@ -364,7 +365,7 @@ void cmCPackWIXGenerator::CreateWiXPropertiesIncludeFile() } } - if (GetOption("CPACK_WIX_PROPERTY_ARPINSTALLLOCATION") == 0) { + if (!GetOption("CPACK_WIX_PROPERTY_ARPINSTALLLOCATION")) { includeFile.BeginElement("Property"); includeFile.AddAttribute("Id", "INSTALL_ROOT"); includeFile.AddAttribute("Secure", "yes"); @@ -405,7 +406,7 @@ void cmCPackWIXGenerator::CopyDefinition(cmWIXSourceWriter& source, std::string const& name, DefinitionType type) { - const char* value = GetOption(name.c_str()); + cmProp value = GetOption(name); if (value) { if (type == DefinitionType::PATH) { AddDefinition(source, name, CMakeToWixPath(value)); @@ -485,17 +486,17 @@ bool cmCPackWIXGenerator::CreateWiXSourceFiles() } std::string featureTitle = cpackPackageName; - if (const char* title = GetOption("CPACK_WIX_ROOT_FEATURE_TITLE")) { - featureTitle = title; + if (cmProp title = GetOption("CPACK_WIX_ROOT_FEATURE_TITLE")) { + featureTitle = *title; } featureDefinitions.AddAttribute("Title", featureTitle); - if (const char* desc = GetOption("CPACK_WIX_ROOT_FEATURE_DESCRIPTION")) { + if (cmProp desc = GetOption("CPACK_WIX_ROOT_FEATURE_DESCRIPTION")) { featureDefinitions.AddAttribute("Description", desc); } featureDefinitions.AddAttribute("Level", "1"); this->Patch->ApplyFragment("#PRODUCTFEATURE", featureDefinitions); - const char* package = GetOption("CPACK_WIX_CMAKE_PACKAGE_REGISTRY"); + cmProp package = GetOption("CPACK_WIX_CMAKE_PACKAGE_REGISTRY"); if (package) { featureDefinitions.CreateCMakePackageRegistryEntry( package, GetOption("CPACK_WIX_UPGRADE_GUID")); @@ -540,10 +541,9 @@ bool cmCPackWIXGenerator::CreateWiXSourceFiles() } bool emitUninstallShortcut = true; - const char* cpackWixProgramMenuFolder = + cmProp cpackWixProgramMenuFolder = GetOption("CPACK_WIX_PROGRAM_MENU_FOLDER"); - if (cpackWixProgramMenuFolder && - cm::string_view(cpackWixProgramMenuFolder) == ".") { + if (cpackWixProgramMenuFolder && cpackWixProgramMenuFolder == ".") { emitUninstallShortcut = false; } else if (emittedShortcutTypes.find(cmWIXShortcuts::START_MENU) == emittedShortcutTypes.end()) { @@ -595,9 +595,9 @@ std::string cmCPackWIXGenerator::GetRootFolderId() const std::string result = "ProgramFiles<64>Folder"; - const char* rootFolderId = GetOption("CPACK_WIX_ROOT_FOLDER_ID"); + cmProp rootFolderId = GetOption("CPACK_WIX_ROOT_FOLDER_ID"); if (rootFolderId) { - result = rootFolderId; + result = *rootFolderId; } if (GetArchitecture() == "x86") { @@ -612,8 +612,8 @@ std::string cmCPackWIXGenerator::GetRootFolderId() const bool cmCPackWIXGenerator::GenerateMainSourceFileFromTemplate() { std::string wixTemplate = FindTemplate("WIX.template.in"); - if (GetOption("CPACK_WIX_TEMPLATE") != 0) { - wixTemplate = GetOption("CPACK_WIX_TEMPLATE"); + if (cmProp wixtpl = GetOption("CPACK_WIX_TEMPLATE")) { + wixTemplate = *wixtpl; } if (wixTemplate.empty()) { @@ -669,7 +669,7 @@ bool cmCPackWIXGenerator::AddComponentsToFeature( featureDefinitions.AddAttribute("Id", featureId); std::vector<std::string> cpackPackageExecutablesList; - const char* cpackPackageExecutables = GetOption("CPACK_PACKAGE_EXECUTABLES"); + cmProp cpackPackageExecutables = GetOption("CPACK_PACKAGE_EXECUTABLES"); if (cpackPackageExecutables) { cmExpandList(cpackPackageExecutables, cpackPackageExecutablesList); if (cpackPackageExecutablesList.size() % 2 != 0) { @@ -683,8 +683,7 @@ bool cmCPackWIXGenerator::AddComponentsToFeature( } std::vector<std::string> cpackPackageDesktopLinksList; - const char* cpackPackageDesktopLinks = - GetOption("CPACK_CREATE_DESKTOP_LINKS"); + cmProp cpackPackageDesktopLinks = GetOption("CPACK_CREATE_DESKTOP_LINKS"); if (cpackPackageDesktopLinks) { cmExpandList(cpackPackageDesktopLinks, cpackPackageDesktopLinksList); } @@ -743,10 +742,9 @@ bool cmCPackWIXGenerator::CreateShortcutsOfSpecificType( std::string directoryId; switch (type) { case cmWIXShortcuts::START_MENU: { - const char* cpackWixProgramMenuFolder = + cmProp cpackWixProgramMenuFolder = GetOption("CPACK_WIX_PROGRAM_MENU_FOLDER"); - if (cpackWixProgramMenuFolder && - cm::string_view(cpackWixProgramMenuFolder) == ".") { + if (cpackWixProgramMenuFolder && cpackWixProgramMenuFolder == ".") { directoryId = "ProgramMenuFolder"; } else { directoryId = "PROGRAM_MENU_FOLDER"; @@ -805,10 +803,9 @@ bool cmCPackWIXGenerator::CreateShortcutsOfSpecificType( fileDefinitions); if (type == cmWIXShortcuts::START_MENU) { - const char* cpackWixProgramMenuFolder = + cmProp cpackWixProgramMenuFolder = GetOption("CPACK_WIX_PROGRAM_MENU_FOLDER"); - if (cpackWixProgramMenuFolder && - cm::string_view(cpackWixProgramMenuFolder) != ".") { + if (cpackWixProgramMenuFolder && cpackWixProgramMenuFolder != ".") { fileDefinitions.EmitRemoveFolder("CM_REMOVE_PROGRAM_MENU_FOLDER" + idSuffix); } @@ -973,9 +970,9 @@ void cmCPackWIXGenerator::AddDirectoryAndFileDefinitions( bool cmCPackWIXGenerator::RequireOption(std::string const& name, std::string& value) const { - const char* tmp = GetOption(name.c_str()); + cmProp tmp = GetOption(name); if (tmp) { - value = tmp; + value = *tmp; return true; } else { @@ -1146,7 +1143,7 @@ bool cmCPackWIXGenerator::IsLegalIdCharacter(char c) void cmCPackWIXGenerator::CollectExtensions(std::string const& variableName, extension_set_t& extensions) { - const char* variableContent = GetOption(variableName.c_str()); + cmProp variableContent = GetOption(variableName); if (!variableContent) return; @@ -1157,7 +1154,7 @@ void cmCPackWIXGenerator::CollectExtensions(std::string const& variableName, void cmCPackWIXGenerator::CollectXmlNamespaces(std::string const& variableName, xmlns_map_t& namespaces) { - const char* variableContent = GetOption(variableName.c_str()); + cmProp variableContent = GetOption(variableName); if (!variableContent) { return; } @@ -1186,7 +1183,7 @@ void cmCPackWIXGenerator::CollectXmlNamespaces(std::string const& variableName, void cmCPackWIXGenerator::AddCustomFlags(std::string const& variableName, std::ostream& stream) { - const char* variableContent = GetOption(variableName.c_str()); + cmProp variableContent = GetOption(variableName); if (!variableContent) return; diff --git a/Source/CPack/cmCPackArchiveGenerator.cxx b/Source/CPack/cmCPackArchiveGenerator.cxx index d9234e6..4f90ba2 100644 --- a/Source/CPack/cmCPackArchiveGenerator.cxx +++ b/Source/CPack/cmCPackArchiveGenerator.cxx @@ -2,7 +2,6 @@ file Copyright.txt or https://cmake.org/licensing for details. */ #include "cmCPackArchiveGenerator.h" -#include <cstdlib> #include <cstring> #include <map> #include <ostream> @@ -13,6 +12,7 @@ #include "cmCPackGenerator.h" #include "cmCPackLog.h" #include "cmGeneratedFileStream.h" +#include "cmProperty.h" #include "cmStringAlgorithms.h" #include "cmSystemTools.h" #include "cmWorkingDirectory.h" @@ -77,7 +77,7 @@ std::string cmCPackArchiveGenerator::GetArchiveComponentFileName( if (this->IsSet("CPACK_ARCHIVE_" + componentUpper + "_FILE_NAME")) { packageFileName += - this->GetOption("CPACK_ARCHIVE_" + componentUpper + "_FILE_NAME"); + *this->GetOption("CPACK_ARCHIVE_" + componentUpper + "_FILE_NAME"); } else if (this->IsSet("CPACK_ARCHIVE_FILE_NAME")) { packageFileName += this->GetComponentPackageFileName( this->GetOption("CPACK_ARCHIVE_FILE_NAME"), component, isGroupName); @@ -118,11 +118,11 @@ int cmCPackArchiveGenerator::addOneComponentToArchive( if (this->IsOn("CPACK_COMPONENT_INCLUDE_TOPLEVEL_DIRECTORY")) { filePrefix = cmStrCat(this->GetOption("CPACK_PACKAGE_FILE_NAME"), '/'); } - const char* installPrefix = - this->GetOption("CPACK_PACKAGING_INSTALL_PREFIX"); - if (installPrefix && installPrefix[0] == '/' && installPrefix[1] != 0) { + cmProp installPrefix = this->GetOption("CPACK_PACKAGING_INSTALL_PREFIX"); + if (installPrefix && installPrefix->size() > 1 && + (*installPrefix)[0] == '/') { // add to file prefix and remove the leading '/' - filePrefix += installPrefix + 1; + filePrefix += installPrefix->substr(1); filePrefix += "/"; } for (std::string const& file : component->Files) { @@ -257,9 +257,9 @@ int cmCPackArchiveGenerator::PackageComponentsAllInOne() this->packageFileNames[0] += "/"; if (this->IsSet("CPACK_ARCHIVE_FILE_NAME")) { - this->packageFileNames[0] += this->GetOption("CPACK_ARCHIVE_FILE_NAME"); + this->packageFileNames[0] += *this->GetOption("CPACK_ARCHIVE_FILE_NAME"); } else { - this->packageFileNames[0] += this->GetOption("CPACK_PACKAGE_FILE_NAME"); + this->packageFileNames[0] += *this->GetOption("CPACK_PACKAGE_FILE_NAME"); } this->packageFileNames[0] += this->GetOutputExtension(); @@ -345,9 +345,9 @@ int cmCPackArchiveGenerator::GetThreadCount() const // CPACK_ARCHIVE_THREADS overrides CPACK_THREADS if (this->IsSet("CPACK_ARCHIVE_THREADS")) { - threads = std::atoi(this->GetOption("CPACK_ARCHIVE_THREADS")); + threads = std::stoi(this->GetOption("CPACK_ARCHIVE_THREADS")); } else if (this->IsSet("CPACK_THREADS")) { - threads = std::atoi(this->GetOption("CPACK_THREADS")); + threads = std::stoi(this->GetOption("CPACK_THREADS")); } return threads; diff --git a/Source/CPack/cmCPackBundleGenerator.cxx b/Source/CPack/cmCPackBundleGenerator.cxx index 4d5f43f..a2e0be4 100644 --- a/Source/CPack/cmCPackBundleGenerator.cxx +++ b/Source/CPack/cmCPackBundleGenerator.cxx @@ -6,6 +6,7 @@ #include <vector> #include "cmCPackLog.h" +#include "cmProperty.h" #include "cmStringAlgorithms.h" #include "cmSystemTools.h" @@ -15,8 +16,8 @@ cmCPackBundleGenerator::~cmCPackBundleGenerator() = default; int cmCPackBundleGenerator::InitializeInternal() { - const char* name = this->GetOption("CPACK_BUNDLE_NAME"); - if (nullptr == name) { + cmProp name = this->GetOption("CPACK_BUNDLE_NAME"); + if (!name) { cmCPackLogger(cmCPackLog::LOG_ERROR, "CPACK_BUNDLE_NAME must be set to use the Bundle generator." << std::endl); @@ -51,30 +52,24 @@ int cmCPackBundleGenerator::ConstructBundle() { // Get required arguments ... - const std::string cpack_bundle_name = this->GetOption("CPACK_BUNDLE_NAME") - ? this->GetOption("CPACK_BUNDLE_NAME") - : ""; - if (cpack_bundle_name.empty()) { + cmProp cpack_bundle_name = this->GetOption("CPACK_BUNDLE_NAME"); + if (cpack_bundle_name->empty()) { cmCPackLogger(cmCPackLog::LOG_ERROR, "CPACK_BUNDLE_NAME must be set." << std::endl); return 0; } - const std::string cpack_bundle_plist = this->GetOption("CPACK_BUNDLE_PLIST") - ? this->GetOption("CPACK_BUNDLE_PLIST") - : ""; - if (cpack_bundle_plist.empty()) { + cmProp cpack_bundle_plist = this->GetOption("CPACK_BUNDLE_PLIST"); + if (cpack_bundle_plist->empty()) { cmCPackLogger(cmCPackLog::LOG_ERROR, "CPACK_BUNDLE_PLIST must be set." << std::endl); return 0; } - const std::string cpack_bundle_icon = this->GetOption("CPACK_BUNDLE_ICON") - ? this->GetOption("CPACK_BUNDLE_ICON") - : ""; - if (cpack_bundle_icon.empty()) { + cmProp cpack_bundle_icon = this->GetOption("CPACK_BUNDLE_ICON"); + if (cpack_bundle_icon->empty()) { cmCPackLogger(cmCPackLog::LOG_ERROR, "CPACK_BUNDLE_ICON must be set." << std::endl); @@ -82,10 +77,8 @@ int cmCPackBundleGenerator::ConstructBundle() } // Get optional arguments ... - const std::string cpack_bundle_startup_command = - this->GetOption("CPACK_BUNDLE_STARTUP_COMMAND") - ? this->GetOption("CPACK_BUNDLE_STARTUP_COMMAND") - : ""; + cmProp cpack_bundle_startup_command = + this->GetOption("CPACK_BUNDLE_STARTUP_COMMAND"); // The staging directory contains everything that will end-up inside the // final disk image ... @@ -138,7 +131,7 @@ int cmCPackBundleGenerator::ConstructBundle() // Optionally a user-provided startup command (could be an // executable or a script) ... - if (!cpack_bundle_startup_command.empty()) { + if (!cpack_bundle_startup_command->empty()) { std::ostringstream command_source; command_source << cpack_bundle_startup_command; @@ -180,13 +173,10 @@ bool cmCPackBundleGenerator::SupportsComponentInstallation() const int cmCPackBundleGenerator::SignBundle(const std::string& src_dir) { - const std::string cpack_apple_cert_app = - this->GetOption("CPACK_BUNDLE_APPLE_CERT_APP") - ? this->GetOption("CPACK_BUNDLE_APPLE_CERT_APP") - : ""; + cmProp cpack_apple_cert_app = this->GetOption("CPACK_BUNDLE_APPLE_CERT_APP"); // codesign the application. - if (!cpack_apple_cert_app.empty()) { + if (!cpack_apple_cert_app->empty()) { std::string output; std::string bundle_path; bundle_path = @@ -195,13 +185,10 @@ int cmCPackBundleGenerator::SignBundle(const std::string& src_dir) // A list of additional files to sign, ie. frameworks and plugins. const std::string sign_parameter = this->GetOption("CPACK_BUNDLE_APPLE_CODESIGN_PARAMETER") - ? this->GetOption("CPACK_BUNDLE_APPLE_CODESIGN_PARAMETER") + ? *this->GetOption("CPACK_BUNDLE_APPLE_CODESIGN_PARAMETER") : "--deep -f"; - const std::string sign_files = - this->GetOption("CPACK_BUNDLE_APPLE_CODESIGN_FILES") - ? this->GetOption("CPACK_BUNDLE_APPLE_CODESIGN_FILES") - : ""; + cmProp sign_files = this->GetOption("CPACK_BUNDLE_APPLE_CODESIGN_FILES"); std::vector<std::string> relFiles = cmExpandedList(sign_files); diff --git a/Source/CPack/cmCPackCygwinBinaryGenerator.cxx b/Source/CPack/cmCPackCygwinBinaryGenerator.cxx index b5abd5a..1de5e1c 100644 --- a/Source/CPack/cmCPackCygwinBinaryGenerator.cxx +++ b/Source/CPack/cmCPackCygwinBinaryGenerator.cxx @@ -8,6 +8,7 @@ #include "cmGeneratedFileStream.h" #include "cmGlobalGenerator.h" #include "cmMakefile.h" +#include "cmProperty.h" #include "cmSystemTools.h" #include "cmake.h" @@ -59,14 +60,15 @@ int cmCPackCygwinBinaryGenerator::PackageFiles() const char* cmCPackCygwinBinaryGenerator::GetOutputExtension() { this->OutputExtension = "-"; - const char* patchNumber = this->GetOption("CPACK_CYGWIN_PATCH_NUMBER"); + cmProp patchNumber = this->GetOption("CPACK_CYGWIN_PATCH_NUMBER"); if (!patchNumber) { - patchNumber = "1"; + this->OutputExtension += "1"; cmCPackLogger(cmCPackLog::LOG_WARNING, "CPACK_CYGWIN_PATCH_NUMBER not specified using 1" << std::endl); + } else { + this->OutputExtension += patchNumber; } - this->OutputExtension += patchNumber; this->OutputExtension += ".tar.bz2"; return this->OutputExtension.c_str(); } diff --git a/Source/CPack/cmCPackCygwinSourceGenerator.cxx b/Source/CPack/cmCPackCygwinSourceGenerator.cxx index 64a88eb..684a988 100644 --- a/Source/CPack/cmCPackCygwinSourceGenerator.cxx +++ b/Source/CPack/cmCPackCygwinSourceGenerator.cxx @@ -8,6 +8,7 @@ #include "cmGeneratedFileStream.h" #include "cmGlobalGenerator.h" #include "cmMakefile.h" +#include "cmProperty.h" #include "cmSystemTools.h" #include "cmake.h" @@ -94,14 +95,15 @@ int cmCPackCygwinSourceGenerator::PackageFiles() } std::string outerTarFile = cmStrCat(this->GetOption("CPACK_TEMPORARY_DIRECTORY"), '-'); - const char* patch = this->GetOption("CPACK_CYGWIN_PATCH_NUMBER"); + cmProp patch = this->GetOption("CPACK_CYGWIN_PATCH_NUMBER"); if (!patch) { cmCPackLogger(cmCPackLog::LOG_WARNING, "CPACK_CYGWIN_PATCH_NUMBER" << " not specified, defaulting to 1\n"); - patch = "1"; + outerTarFile += "1"; + } else { + outerTarFile += patch; } - outerTarFile += patch; outerTarFile += "-src.tar.bz2"; std::string tmpDir = this->GetOption("CPACK_TOPLEVEL_DIRECTORY"); std::string buildScript = @@ -145,14 +147,15 @@ const char* cmCPackCygwinSourceGenerator::GetPackagingInstallPrefix() const char* cmCPackCygwinSourceGenerator::GetOutputExtension() { this->OutputExtension = "-"; - const char* patch = this->GetOption("CPACK_CYGWIN_PATCH_NUMBER"); + cmProp patch = this->GetOption("CPACK_CYGWIN_PATCH_NUMBER"); if (!patch) { cmCPackLogger(cmCPackLog::LOG_WARNING, "CPACK_CYGWIN_PATCH_NUMBER" << " not specified, defaulting to 1\n"); - patch = "1"; + this->OutputExtension += "1"; + } else { + this->OutputExtension += patch; } - this->OutputExtension += patch; this->OutputExtension += "-src.tar.bz2"; return this->OutputExtension.c_str(); } diff --git a/Source/CPack/cmCPackDebGenerator.cxx b/Source/CPack/cmCPackDebGenerator.cxx index 829cef4..52b94c4 100644 --- a/Source/CPack/cmCPackDebGenerator.cxx +++ b/Source/CPack/cmCPackDebGenerator.cxx @@ -20,6 +20,7 @@ #include "cmCPackLog.h" #include "cmCryptoHash.h" #include "cmGeneratedFileStream.h" +#include "cmProperty.h" #include "cmStringAlgorithms.h" #include "cmSystemTools.h" @@ -30,12 +31,12 @@ class DebGenerator public: DebGenerator(cmCPackLog* logger, std::string outputName, std::string workDir, std::string topLevelDir, std::string temporaryDir, - const char* debianCompressionType, const char* numThreads, - const char* debianArchiveType, + cmProp debianCompressionType, cmProp numThreads, + cmProp debianArchiveType, std::map<std::string, std::string> controlValues, bool genShLibs, std::string shLibsFilename, bool genPostInst, std::string postInst, bool genPostRm, std::string postRm, - const char* controlExtra, bool permissionStrctPolicy, + cmProp controlExtra, bool permissionStrctPolicy, std::vector<std::string> packageFiles); bool generate() const; @@ -54,7 +55,7 @@ private: std::string CompressionSuffix; const std::string TopLevelDir; const std::string TemporaryDir; - const char* DebianArchiveType; + const std::string DebianArchiveType; long NumThreads; const std::map<std::string, std::string> ControlValues; const bool GenShLibs; @@ -63,27 +64,28 @@ private: const std::string PostInst; const bool GenPostRm; const std::string PostRm; - const char* ControlExtra; + cmProp ControlExtra; const bool PermissionStrictPolicy; const std::vector<std::string> PackageFiles; cmArchiveWrite::Compress TarCompressionType; }; -DebGenerator::DebGenerator( - cmCPackLog* logger, std::string outputName, std::string workDir, - std::string topLevelDir, std::string temporaryDir, - const char* debianCompressionType, const char* numThreads, - const char* debianArchiveType, - std::map<std::string, std::string> controlValues, bool genShLibs, - std::string shLibsFilename, bool genPostInst, std::string postInst, - bool genPostRm, std::string postRm, const char* controlExtra, - bool permissionStrictPolicy, std::vector<std::string> packageFiles) +DebGenerator::DebGenerator(cmCPackLog* logger, std::string outputName, + std::string workDir, std::string topLevelDir, + std::string temporaryDir, cmProp debCompressionType, + cmProp numThreads, cmProp debianArchiveType, + std::map<std::string, std::string> controlValues, + bool genShLibs, std::string shLibsFilename, + bool genPostInst, std::string postInst, + bool genPostRm, std::string postRm, + cmProp controlExtra, bool permissionStrictPolicy, + std::vector<std::string> packageFiles) : Logger(logger) , OutputName(std::move(outputName)) , WorkDir(std::move(workDir)) , TopLevelDir(std::move(topLevelDir)) , TemporaryDir(std::move(temporaryDir)) - , DebianArchiveType(debianArchiveType ? debianArchiveType : "gnutar") + , DebianArchiveType(debianArchiveType ? *debianArchiveType : "gnutar") , ControlValues(std::move(controlValues)) , GenShLibs(genShLibs) , ShLibsFilename(std::move(shLibsFilename)) @@ -95,26 +97,27 @@ DebGenerator::DebGenerator( , PermissionStrictPolicy(permissionStrictPolicy) , PackageFiles(std::move(packageFiles)) { - if (!debianCompressionType) { - debianCompressionType = "gzip"; + std::string debianCompressionType = "gzip"; + if (debCompressionType) { + debianCompressionType = *debCompressionType; } - if (!std::strcmp(debianCompressionType, "lzma")) { + if (debianCompressionType == "lzma") { this->CompressionSuffix = ".lzma"; this->TarCompressionType = cmArchiveWrite::CompressLZMA; - } else if (!std::strcmp(debianCompressionType, "xz")) { + } else if (debianCompressionType == "xz") { this->CompressionSuffix = ".xz"; this->TarCompressionType = cmArchiveWrite::CompressXZ; - } else if (!std::strcmp(debianCompressionType, "bzip2")) { + } else if (debianCompressionType == "bzip2") { this->CompressionSuffix = ".bz2"; this->TarCompressionType = cmArchiveWrite::CompressBZip2; - } else if (!std::strcmp(debianCompressionType, "gzip")) { + } else if (debianCompressionType == "gzip") { this->CompressionSuffix = ".gz"; this->TarCompressionType = cmArchiveWrite::CompressGZip; - } else if (!std::strcmp(debianCompressionType, "zstd")) { + } else if (debianCompressionType == "zstd") { this->CompressionSuffix = ".zst"; this->TarCompressionType = cmArchiveWrite::CompressZstd; - } else if (!std::strcmp(debianCompressionType, "none")) { + } else if (debianCompressionType == "none") { this->CompressionSuffix.clear(); this->TarCompressionType = cmArchiveWrite::CompressNone; } else { @@ -539,9 +542,8 @@ int cmCPackDebGenerator::PackageOnePack(std::string const& initialTopLevel, std::string localToplevel(initialTopLevel); std::string packageFileName( cmSystemTools::GetParentDirectory(this->toplevel)); - std::string outputFileName( - std::string(this->GetOption("CPACK_PACKAGE_FILE_NAME")) + "-" + - packageName + this->GetOutputExtension()); + std::string outputFileName(*this->GetOption("CPACK_PACKAGE_FILE_NAME") + + "-" + packageName + this->GetOutputExtension()); localToplevel += "/" + packageName; /* replace the TEMP DIRECTORY with the component one */ @@ -627,9 +629,8 @@ int cmCPackDebGenerator::PackageComponentsAllInOne( std::string localToplevel(initialTopLevel); std::string packageFileName( cmSystemTools::GetParentDirectory(this->toplevel)); - std::string outputFileName( - std::string(this->GetOption("CPACK_PACKAGE_FILE_NAME")) + - this->GetOutputExtension()); + std::string outputFileName(*this->GetOption("CPACK_PACKAGE_FILE_NAME") + + this->GetOutputExtension()); // all GROUP in one vs all COMPONENT in one // if must be here otherwise non component paths have a trailing / while // components don't @@ -684,7 +685,7 @@ int cmCPackDebGenerator::PackageFiles() bool cmCPackDebGenerator::createDebPackages() { - auto make_package = [this](const char* const path, + auto make_package = [this](const std::string& path, const char* const output_var, bool (cmCPackDebGenerator::*creator)()) -> bool { try { @@ -706,7 +707,7 @@ bool cmCPackDebGenerator::createDebPackages() bool retval = make_package(this->GetOption("GEN_WDIR"), "GEN_CPACK_OUTPUT_FILE_NAME", &cmCPackDebGenerator::createDeb); - const char* const dbgsymdir_path = this->GetOption("GEN_DBGSYMDIR"); + cmProp dbgsymdir_path = this->GetOption("GEN_DBGSYMDIR"); if (this->IsOn("GEN_CPACK_DEBIAN_DEBUGINFO_PACKAGE") && dbgsymdir_path) { retval = make_package(dbgsymdir_path, "GEN_CPACK_DBGSYM_OUTPUT_FILE_NAME", &cmCPackDebGenerator::createDbgsymDDeb) && @@ -723,78 +724,75 @@ bool cmCPackDebGenerator::createDeb() controlValues["Package"] = cmsys::SystemTools::LowerCase( this->GetOption("GEN_CPACK_DEBIAN_PACKAGE_NAME")); controlValues["Version"] = - this->GetOption("GEN_CPACK_DEBIAN_PACKAGE_VERSION"); + *this->GetOption("GEN_CPACK_DEBIAN_PACKAGE_VERSION"); controlValues["Section"] = - this->GetOption("GEN_CPACK_DEBIAN_PACKAGE_SECTION"); + *this->GetOption("GEN_CPACK_DEBIAN_PACKAGE_SECTION"); controlValues["Priority"] = - this->GetOption("GEN_CPACK_DEBIAN_PACKAGE_PRIORITY"); + *this->GetOption("GEN_CPACK_DEBIAN_PACKAGE_PRIORITY"); controlValues["Architecture"] = - this->GetOption("GEN_CPACK_DEBIAN_PACKAGE_ARCHITECTURE"); + *this->GetOption("GEN_CPACK_DEBIAN_PACKAGE_ARCHITECTURE"); controlValues["Maintainer"] = - this->GetOption("GEN_CPACK_DEBIAN_PACKAGE_MAINTAINER"); + *this->GetOption("GEN_CPACK_DEBIAN_PACKAGE_MAINTAINER"); controlValues["Description"] = - this->GetOption("GEN_CPACK_DEBIAN_PACKAGE_DESCRIPTION"); + *this->GetOption("GEN_CPACK_DEBIAN_PACKAGE_DESCRIPTION"); - const char* debian_pkg_source = + cmProp debian_pkg_source = this->GetOption("GEN_CPACK_DEBIAN_PACKAGE_SOURCE"); if (cmNonempty(debian_pkg_source)) { - controlValues["Source"] = debian_pkg_source; + controlValues["Source"] = *debian_pkg_source; } - const char* debian_pkg_dep = - this->GetOption("GEN_CPACK_DEBIAN_PACKAGE_DEPENDS"); + cmProp debian_pkg_dep = this->GetOption("GEN_CPACK_DEBIAN_PACKAGE_DEPENDS"); if (cmNonempty(debian_pkg_dep)) { - controlValues["Depends"] = debian_pkg_dep; + controlValues["Depends"] = *debian_pkg_dep; } - const char* debian_pkg_rec = + cmProp debian_pkg_rec = this->GetOption("GEN_CPACK_DEBIAN_PACKAGE_RECOMMENDS"); if (cmNonempty(debian_pkg_rec)) { - controlValues["Recommends"] = debian_pkg_rec; + controlValues["Recommends"] = *debian_pkg_rec; } - const char* debian_pkg_sug = - this->GetOption("GEN_CPACK_DEBIAN_PACKAGE_SUGGESTS"); + cmProp debian_pkg_sug = this->GetOption("GEN_CPACK_DEBIAN_PACKAGE_SUGGESTS"); if (cmNonempty(debian_pkg_sug)) { - controlValues["Suggests"] = debian_pkg_sug; + controlValues["Suggests"] = *debian_pkg_sug; } - const char* debian_pkg_url = - this->GetOption("GEN_CPACK_DEBIAN_PACKAGE_HOMEPAGE"); + cmProp debian_pkg_url = this->GetOption("GEN_CPACK_DEBIAN_PACKAGE_HOMEPAGE"); if (cmNonempty(debian_pkg_url)) { - controlValues["Homepage"] = debian_pkg_url; + controlValues["Homepage"] = *debian_pkg_url; } - const char* debian_pkg_predep = + cmProp debian_pkg_predep = this->GetOption("GEN_CPACK_DEBIAN_PACKAGE_PREDEPENDS"); if (cmNonempty(debian_pkg_predep)) { - controlValues["Pre-Depends"] = debian_pkg_predep; + controlValues["Pre-Depends"] = *debian_pkg_predep; } - const char* debian_pkg_enhances = + cmProp debian_pkg_enhances = this->GetOption("GEN_CPACK_DEBIAN_PACKAGE_ENHANCES"); if (cmNonempty(debian_pkg_enhances)) { - controlValues["Enhances"] = debian_pkg_enhances; + controlValues["Enhances"] = *debian_pkg_enhances; } - const char* debian_pkg_breaks = + cmProp debian_pkg_breaks = this->GetOption("GEN_CPACK_DEBIAN_PACKAGE_BREAKS"); if (cmNonempty(debian_pkg_breaks)) { - controlValues["Breaks"] = debian_pkg_breaks; + controlValues["Breaks"] = *debian_pkg_breaks; } - const char* debian_pkg_conflicts = + cmProp debian_pkg_conflicts = this->GetOption("GEN_CPACK_DEBIAN_PACKAGE_CONFLICTS"); if (cmNonempty(debian_pkg_conflicts)) { - controlValues["Conflicts"] = debian_pkg_conflicts; + controlValues["Conflicts"] = *debian_pkg_conflicts; } - const char* debian_pkg_provides = + cmProp debian_pkg_provides = this->GetOption("GEN_CPACK_DEBIAN_PACKAGE_PROVIDES"); if (cmNonempty(debian_pkg_provides)) { - controlValues["Provides"] = debian_pkg_provides; + controlValues["Provides"] = *debian_pkg_provides; } - const char* debian_pkg_replaces = + cmProp debian_pkg_replaces = this->GetOption("GEN_CPACK_DEBIAN_PACKAGE_REPLACES"); if (cmNonempty(debian_pkg_replaces)) { - controlValues["Replaces"] = debian_pkg_replaces; + controlValues["Replaces"] = *debian_pkg_replaces; } const std::string strGenWDIR(this->GetOption("GEN_WDIR")); const std::string shlibsfilename = strGenWDIR + "/shlibs"; - const char* debian_pkg_shlibs = + cmProp debian_pkg_shlibs = this->GetOption("GEN_CPACK_DEBIAN_PACKAGE_SHLIBS"); const bool gen_shibs = this->IsOn("CPACK_DEBIAN_PACKAGE_GENERATE_SHLIBS") && cmNonempty(debian_pkg_shlibs); @@ -851,32 +849,33 @@ bool cmCPackDebGenerator::createDbgsymDDeb() // debian policy enforce lower case for package name std::string packageNameLower = cmsys::SystemTools::LowerCase( this->GetOption("GEN_CPACK_DEBIAN_PACKAGE_NAME")); - const char* debian_pkg_version = + cmProp debian_pkg_version = this->GetOption("GEN_CPACK_DEBIAN_PACKAGE_VERSION"); controlValues["Package"] = packageNameLower + "-dbgsym"; controlValues["Package-Type"] = "ddeb"; - controlValues["Version"] = debian_pkg_version; + controlValues["Version"] = *debian_pkg_version; controlValues["Auto-Built-Package"] = "debug-symbols"; - controlValues["Depends"] = this->GetOption("GEN_CPACK_DEBIAN_PACKAGE_NAME") + - std::string(" (= ") + debian_pkg_version + ")"; + controlValues["Depends"] = + *this->GetOption("GEN_CPACK_DEBIAN_PACKAGE_NAME") + std::string(" (= ") + + *debian_pkg_version + ")"; controlValues["Section"] = "debug"; controlValues["Priority"] = "optional"; controlValues["Architecture"] = - this->GetOption("GEN_CPACK_DEBIAN_PACKAGE_ARCHITECTURE"); + *this->GetOption("GEN_CPACK_DEBIAN_PACKAGE_ARCHITECTURE"); controlValues["Maintainer"] = - this->GetOption("GEN_CPACK_DEBIAN_PACKAGE_MAINTAINER"); + *this->GetOption("GEN_CPACK_DEBIAN_PACKAGE_MAINTAINER"); controlValues["Description"] = std::string("debug symbols for ") + packageNameLower; - const char* debian_pkg_source = + cmProp debian_pkg_source = this->GetOption("GEN_CPACK_DEBIAN_PACKAGE_SOURCE"); if (cmNonempty(debian_pkg_source)) { - controlValues["Source"] = debian_pkg_source; + controlValues["Source"] = *debian_pkg_source; } - const char* debian_build_ids = this->GetOption("GEN_BUILD_IDS"); + cmProp debian_build_ids = this->GetOption("GEN_BUILD_IDS"); if (cmNonempty(debian_build_ids)) { - controlValues["Build-Ids"] = debian_build_ids; + controlValues["Build-Ids"] = *debian_build_ids; } DebGenerator gen( @@ -914,7 +913,7 @@ std::string cmCPackDebGenerator::GetComponentInstallDirNameSuffix( std::string groupVar = "CPACK_COMPONENT_" + cmSystemTools::UpperCase(componentName) + "_GROUP"; if (nullptr != this->GetOption(groupVar)) { - return std::string(this->GetOption(groupVar)); + return *this->GetOption(groupVar); } return componentName; } diff --git a/Source/CPack/cmCPackDragNDropGenerator.cxx b/Source/CPack/cmCPackDragNDropGenerator.cxx index b71c969..a4e4ab3 100644 --- a/Source/CPack/cmCPackDragNDropGenerator.cxx +++ b/Source/CPack/cmCPackDragNDropGenerator.cxx @@ -18,6 +18,7 @@ #include "cmCPackLog.h" #include "cmDuration.h" #include "cmGeneratedFileStream.h" +#include "cmProperty.h" #include "cmStringAlgorithms.h" #include "cmSystemTools.h" #include "cmXMLWriter.h" @@ -260,48 +261,35 @@ int cmCPackDragNDropGenerator::CreateDMG(const std::string& src_dir, const std::string& output_file) { // Get optional arguments ... - const std::string cpack_package_icon = this->GetOption("CPACK_PACKAGE_ICON") - ? this->GetOption("CPACK_PACKAGE_ICON") - : ""; + cmProp cpack_package_icon = this->GetOption("CPACK_PACKAGE_ICON"); const std::string cpack_dmg_volume_name = this->GetOption("CPACK_DMG_VOLUME_NAME") - ? this->GetOption("CPACK_DMG_VOLUME_NAME") - : this->GetOption("CPACK_PACKAGE_FILE_NAME"); + ? *this->GetOption("CPACK_DMG_VOLUME_NAME") + : *this->GetOption("CPACK_PACKAGE_FILE_NAME"); const std::string cpack_dmg_format = this->GetOption("CPACK_DMG_FORMAT") - ? this->GetOption("CPACK_DMG_FORMAT") + ? *this->GetOption("CPACK_DMG_FORMAT") : "UDZO"; const std::string cpack_dmg_filesystem = this->GetOption("CPACK_DMG_FILESYSTEM") - ? this->GetOption("CPACK_DMG_FILESYSTEM") + ? *this->GetOption("CPACK_DMG_FILESYSTEM") : "HFS+"; // Get optional arguments ... std::string cpack_license_file = - this->GetOption("CPACK_RESOURCE_FILE_LICENSE") - ? this->GetOption("CPACK_RESOURCE_FILE_LICENSE") - : ""; + *this->GetOption("CPACK_RESOURCE_FILE_LICENSE"); - const std::string cpack_dmg_background_image = - this->GetOption("CPACK_DMG_BACKGROUND_IMAGE") - ? this->GetOption("CPACK_DMG_BACKGROUND_IMAGE") - : ""; + cmProp cpack_dmg_background_image = + this->GetOption("CPACK_DMG_BACKGROUND_IMAGE"); - const std::string cpack_dmg_ds_store = this->GetOption("CPACK_DMG_DS_STORE") - ? this->GetOption("CPACK_DMG_DS_STORE") - : ""; + cmProp cpack_dmg_ds_store = this->GetOption("CPACK_DMG_DS_STORE"); - const std::string cpack_dmg_languages = - this->GetOption("CPACK_DMG_SLA_LANGUAGES") - ? this->GetOption("CPACK_DMG_SLA_LANGUAGES") - : ""; + cmProp cpack_dmg_languages = this->GetOption("CPACK_DMG_SLA_LANGUAGES"); - const std::string cpack_dmg_ds_store_setup_script = - this->GetOption("CPACK_DMG_DS_STORE_SETUP_SCRIPT") - ? this->GetOption("CPACK_DMG_DS_STORE_SETUP_SCRIPT") - : ""; + cmProp cpack_dmg_ds_store_setup_script = + this->GetOption("CPACK_DMG_DS_STORE_SETUP_SCRIPT"); const bool cpack_dmg_disable_applications_symlink = this->IsOn("CPACK_DMG_DISABLE_APPLICATIONS_SYMLINK"); @@ -332,7 +320,7 @@ int cmCPackDragNDropGenerator::CreateDMG(const std::string& src_dir, } // Optionally add a custom volume icon ... - if (!cpack_package_icon.empty()) { + if (!cpack_package_icon->empty()) { std::ostringstream package_icon_source; package_icon_source << cpack_package_icon; @@ -351,7 +339,7 @@ int cmCPackDragNDropGenerator::CreateDMG(const std::string& src_dir, // Optionally add a custom .DS_Store file // (e.g. for setting background/layout) ... - if (!cpack_dmg_ds_store.empty()) { + if (!cpack_dmg_ds_store->empty()) { std::ostringstream package_settings_source; package_settings_source << cpack_dmg_ds_store; @@ -372,7 +360,7 @@ int cmCPackDragNDropGenerator::CreateDMG(const std::string& src_dir, // Optionally add a custom background image ... // Make sure the background file type is the same as the custom image // and that the file is hidden so it doesn't show up. - if (!cpack_dmg_background_image.empty()) { + if (!cpack_dmg_background_image->empty()) { const std::string extension = cmSystemTools::GetFilenameLastExtension(cpack_dmg_background_image); std::ostringstream package_background_source; @@ -394,7 +382,7 @@ int cmCPackDragNDropGenerator::CreateDMG(const std::string& src_dir, } bool remount_image = - !cpack_package_icon.empty() || !cpack_dmg_ds_store_setup_script.empty(); + !cpack_package_icon->empty() || !cpack_dmg_ds_store_setup_script->empty(); std::string temp_image_format = "UDZO"; @@ -471,7 +459,7 @@ int cmCPackDragNDropGenerator::CreateDMG(const std::string& src_dir, } // Optionally set the custom icon flag for the image ... - if (!had_error && !cpack_package_icon.empty()) { + if (!had_error && !cpack_package_icon->empty()) { std::string error; std::ostringstream setfile_command; setfile_command << this->GetOption("CPACK_COMMAND_SETFILE"); @@ -490,7 +478,7 @@ int cmCPackDragNDropGenerator::CreateDMG(const std::string& src_dir, // Optionally we can execute a custom apple script to generate // the .DS_Store for the volume folder ... - if (!had_error && !cpack_dmg_ds_store_setup_script.empty()) { + if (!had_error && !cpack_dmg_ds_store_setup_script->empty()) { std::ostringstream setup_script_command; setup_script_command << "osascript" << " \"" << cpack_dmg_ds_store_setup_script << "\"" @@ -718,7 +706,7 @@ std::string cmCPackDragNDropGenerator::GetComponentInstallDirNameSuffix( // the current COMPONENT belongs to. std::string groupVar = "CPACK_COMPONENT_" + cmSystemTools::UpperCase(componentName) + "_GROUP"; - const char* _groupName = GetOption(groupVar); + cmProp _groupName = this->GetOption(groupVar); if (_groupName) { std::string groupName = _groupName; diff --git a/Source/CPack/cmCPackExternalGenerator.cxx b/Source/CPack/cmCPackExternalGenerator.cxx index e3521a0..9cdaafe 100644 --- a/Source/CPack/cmCPackExternalGenerator.cxx +++ b/Source/CPack/cmCPackExternalGenerator.cxx @@ -16,6 +16,7 @@ #include "cmCPackComponentGroup.h" #include "cmCPackLog.h" #include "cmMakefile.h" +#include "cmProperty.h" #include "cmStringAlgorithms.h" #include "cmSystemTools.h" @@ -60,7 +61,7 @@ int cmCPackExternalGenerator::PackageFiles() return 0; } - const char* packageScript = this->GetOption("CPACK_EXTERNAL_PACKAGE_SCRIPT"); + cmProp packageScript = this->GetOption("CPACK_EXTERNAL_PACKAGE_SCRIPT"); if (cmNonempty(packageScript)) { if (!cmSystemTools::FileIsFullPath(packageScript)) { cmCPackLogger( @@ -76,10 +77,9 @@ int cmCPackExternalGenerator::PackageFiles() return 0; } - const char* builtPackagesStr = - this->GetOption("CPACK_EXTERNAL_BUILT_PACKAGES"); - if (builtPackagesStr) { - cmExpandList(builtPackagesStr, this->packageFileNames, false); + cmProp builtPackages = this->GetOption("CPACK_EXTERNAL_BUILT_PACKAGES"); + if (builtPackages) { + cmExpandList(builtPackages, this->packageFileNames, false); } } @@ -181,43 +181,42 @@ int cmCPackExternalGenerator::cmCPackExternalVersionGenerator::WriteToJSON( return 0; } - const char* packageName = this->Parent->GetOption("CPACK_PACKAGE_NAME"); + cmProp packageName = this->Parent->GetOption("CPACK_PACKAGE_NAME"); if (packageName) { - root["packageName"] = packageName; + root["packageName"] = *packageName; } - const char* packageVersion = - this->Parent->GetOption("CPACK_PACKAGE_VERSION"); + cmProp packageVersion = this->Parent->GetOption("CPACK_PACKAGE_VERSION"); if (packageVersion) { - root["packageVersion"] = packageVersion; + root["packageVersion"] = *packageVersion; } - const char* packageDescriptionFile = + cmProp packageDescriptionFile = this->Parent->GetOption("CPACK_PACKAGE_DESCRIPTION_FILE"); if (packageDescriptionFile) { - root["packageDescriptionFile"] = packageDescriptionFile; + root["packageDescriptionFile"] = *packageDescriptionFile; } - const char* packageDescriptionSummary = + cmProp packageDescriptionSummary = this->Parent->GetOption("CPACK_PACKAGE_DESCRIPTION_SUMMARY"); if (packageDescriptionSummary) { - root["packageDescriptionSummary"] = packageDescriptionSummary; + root["packageDescriptionSummary"] = *packageDescriptionSummary; } - const char* buildConfigCstr = this->Parent->GetOption("CPACK_BUILD_CONFIG"); + cmProp buildConfigCstr = this->Parent->GetOption("CPACK_BUILD_CONFIG"); if (buildConfigCstr) { - root["buildConfig"] = buildConfigCstr; + root["buildConfig"] = *buildConfigCstr; } - const char* defaultDirectoryPermissions = + cmProp defaultDirectoryPermissions = this->Parent->GetOption("CPACK_INSTALL_DEFAULT_DIRECTORY_PERMISSIONS"); if (cmNonempty(defaultDirectoryPermissions)) { - root["defaultDirectoryPermissions"] = defaultDirectoryPermissions; + root["defaultDirectoryPermissions"] = *defaultDirectoryPermissions; } if (cmIsInternallyOn(this->Parent->GetOption("CPACK_SET_DESTDIR"))) { root["setDestdir"] = true; root["packagingInstallPrefix"] = - this->Parent->GetOption("CPACK_PACKAGING_INSTALL_PREFIX"); + *this->Parent->GetOption("CPACK_PACKAGING_INSTALL_PREFIX"); } else { root["setDestdir"] = false; } diff --git a/Source/CPack/cmCPackFreeBSDGenerator.cxx b/Source/CPack/cmCPackFreeBSDGenerator.cxx index b673006..39ec3c8 100644 --- a/Source/CPack/cmCPackFreeBSDGenerator.cxx +++ b/Source/CPack/cmCPackFreeBSDGenerator.cxx @@ -203,11 +203,11 @@ cmGeneratedFileStream& operator<<(cmGeneratedFileStream& s, // basically a wrapper that handles the NULL-ptr return from GetOption(). std::string cmCPackFreeBSDGenerator::var_lookup(const char* var_name) { - const char* pv = this->GetOption(var_name); + cmProp pv = this->GetOption(var_name); if (!pv) { return std::string(); } - return pv; + return *pv; } // Produce UCL in the given @p manifest file for the common diff --git a/Source/CPack/cmCPackGenerator.cxx b/Source/CPack/cmCPackGenerator.cxx index 00e274d..1527e80 100644 --- a/Source/CPack/cmCPackGenerator.cxx +++ b/Source/CPack/cmCPackGenerator.cxx @@ -78,14 +78,14 @@ int cmCPackGenerator::PrepareNames() std::string tempDirectory = cmStrCat(this->GetOption("CPACK_PACKAGE_DIRECTORY"), "/_CPack_Packages/"); - const char* toplevelTag = this->GetOption("CPACK_TOPLEVEL_TAG"); + cmProp toplevelTag = this->GetOption("CPACK_TOPLEVEL_TAG"); if (toplevelTag) { - tempDirectory += toplevelTag; + tempDirectory += *toplevelTag; tempDirectory += "/"; } - tempDirectory += this->GetOption("CPACK_GENERATOR"); + tempDirectory += *this->GetOption("CPACK_GENERATOR"); std::string topDirectory = tempDirectory; - const char* pfname = this->GetOption("CPACK_PACKAGE_FILE_NAME"); + cmProp pfname = this->GetOption("CPACK_PACKAGE_FILE_NAME"); if (!pfname) { cmCPackLogger(cmCPackLog::LOG_ERROR, "CPACK_PACKAGE_FILE_NAME not specified" << std::endl); @@ -99,7 +99,7 @@ int cmCPackGenerator::PrepareNames() return 0; } outName += this->GetOutputExtension(); - const char* pdir = this->GetOption("CPACK_PACKAGE_DIRECTORY"); + cmProp pdir = this->GetOption("CPACK_PACKAGE_DIRECTORY"); if (!pdir) { cmCPackLogger(cmCPackLog::LOG_ERROR, "CPACK_PACKAGE_DIRECTORY not specified" << std::endl); @@ -125,7 +125,7 @@ int cmCPackGenerator::PrepareNames() cmCPackLogger(cmCPackLog::LOG_DEBUG, "Look for: CPACK_PACKAGE_DESCRIPTION_FILE" << std::endl); - const char* descFileName = this->GetOption("CPACK_PACKAGE_DESCRIPTION_FILE"); + cmProp descFileName = this->GetOption("CPACK_PACKAGE_DESCRIPTION_FILE"); if (descFileName && !this->GetOption("CPACK_PACKAGE_DESCRIPTION")) { cmCPackLogger(cmCPackLog::LOG_DEBUG, "Look for: " << descFileName << std::endl); @@ -135,7 +135,7 @@ int cmCPackGenerator::PrepareNames() << descFileName << "]" << std::endl); return 0; } - cmsys::ifstream ifs(descFileName); + cmsys::ifstream ifs(descFileName->c_str()); if (!ifs) { cmCPackLogger(cmCPackLog::LOG_ERROR, "Cannot open description file name: " << descFileName @@ -151,9 +151,9 @@ int cmCPackGenerator::PrepareNames() ostr << cmXMLSafe(line) << std::endl; } this->SetOption("CPACK_PACKAGE_DESCRIPTION", ostr.str().c_str()); - const char* defFileName = + cmProp defFileName = this->GetOption("CPACK_DEFAULT_PACKAGE_DESCRIPTION_FILE"); - if (defFileName && !strcmp(defFileName, descFileName)) { + if (defFileName && (defFileName == descFileName)) { this->SetOption("CPACK_USED_DEFAULT_PACKAGE_DESCRIPTION_FILE", "ON"); } } @@ -165,7 +165,7 @@ int cmCPackGenerator::PrepareNames() << std::endl); return 0; } - const char* algoSignature = this->GetOption("CPACK_PACKAGE_CHECKSUM"); + cmProp algoSignature = this->GetOption("CPACK_PACKAGE_CHECKSUM"); if (algoSignature) { if (!cmCryptoHash::New(algoSignature)) { cmCPackLogger(cmCPackLog::LOG_ERROR, @@ -215,7 +215,7 @@ int cmCPackGenerator::InstallProject() // prepare default created directory permissions mode_t default_dir_mode_v = 0; mode_t* default_dir_mode = nullptr; - const char* default_dir_install_permissions = + cmProp default_dir_install_permissions = this->GetOption("CPACK_INSTALL_DEFAULT_DIRECTORY_PERMISSIONS"); if (cmNonempty(default_dir_install_permissions)) { std::vector<std::string> items = @@ -266,7 +266,7 @@ int cmCPackGenerator::InstallProject() } // Run pre-build actions - const char* preBuildScripts = this->GetOption("CPACK_PRE_BUILD_SCRIPTS"); + cmProp preBuildScripts = this->GetOption("CPACK_PRE_BUILD_SCRIPTS"); if (preBuildScripts) { const auto scripts = cmExpandedList(preBuildScripts, false); for (const auto& script : scripts) { @@ -293,7 +293,7 @@ int cmCPackGenerator::InstallProjectViaInstallCommands( bool setDestDir, const std::string& tempInstallDirectory) { (void)setDestDir; - const char* installCommands = this->GetOption("CPACK_INSTALL_COMMANDS"); + cmProp installCommands = this->GetOption("CPACK_INSTALL_COMMANDS"); if (cmNonempty(installCommands)) { std::string tempInstallDirectoryEnv = cmStrCat("CMAKE_INSTALL_PREFIX=", tempInstallDirectory); @@ -333,7 +333,7 @@ int cmCPackGenerator::InstallProjectViaInstalledDirectories( (void)setDestDir; (void)tempInstallDirectory; std::vector<cmsys::RegularExpression> ignoreFilesRegex; - const char* cpackIgnoreFiles = this->GetOption("CPACK_IGNORE_FILES"); + cmProp cpackIgnoreFiles = this->GetOption("CPACK_IGNORE_FILES"); if (cpackIgnoreFiles) { std::vector<std::string> ignoreFilesRegexString = cmExpandedList(cpackIgnoreFiles); @@ -343,8 +343,7 @@ int cmCPackGenerator::InstallProjectViaInstalledDirectories( ignoreFilesRegex.emplace_back(ifr); } } - const char* installDirectories = - this->GetOption("CPACK_INSTALLED_DIRECTORIES"); + cmProp installDirectories = this->GetOption("CPACK_INSTALLED_DIRECTORIES"); if (cmNonempty(installDirectories)) { std::vector<std::string> installDirectoriesVector = cmExpandedList(installDirectories); @@ -472,9 +471,9 @@ int cmCPackGenerator::InstallProjectViaInstalledDirectories( int cmCPackGenerator::InstallProjectViaInstallScript( bool setDestDir, const std::string& tempInstallDirectory) { - const char* cmakeScripts = this->GetOption("CPACK_INSTALL_SCRIPTS"); + cmProp cmakeScripts = this->GetOption("CPACK_INSTALL_SCRIPTS"); { - const char* const cmakeScript = this->GetOption("CPACK_INSTALL_SCRIPT"); + cmProp const cmakeScript = this->GetOption("CPACK_INSTALL_SCRIPT"); if (cmakeScript && cmakeScripts) { cmCPackLogger( cmCPackLog::LOG_WARNING, @@ -485,7 +484,7 @@ int cmCPackGenerator::InstallProjectViaInstallScript( cmakeScripts = cmakeScript; } } - if (cmakeScripts && *cmakeScripts) { + if (cmakeScripts && !cmakeScripts->empty()) { cmCPackLogger(cmCPackLog::LOG_OUTPUT, "- Install scripts: " << cmakeScripts << std::endl); std::vector<std::string> cmakeScriptsVector = cmExpandedList(cmakeScripts); @@ -502,7 +501,7 @@ int cmCPackGenerator::InstallProjectViaInstallScript( std::string dir; if (this->GetOption("CPACK_INSTALL_PREFIX")) { - dir += this->GetOption("CPACK_INSTALL_PREFIX"); + dir += *this->GetOption("CPACK_INSTALL_PREFIX"); } this->SetOption("CMAKE_INSTALL_PREFIX", dir.c_str()); cmCPackLogger( @@ -540,8 +539,8 @@ int cmCPackGenerator::InstallProjectViaInstallCMakeProjects( bool setDestDir, const std::string& baseTempInstallDirectory, const mode_t* default_dir_mode) { - const char* cmakeProjects = this->GetOption("CPACK_INSTALL_CMAKE_PROJECTS"); - const char* cmakeGenerator = this->GetOption("CPACK_CMAKE_GENERATOR"); + cmProp cmakeProjects = this->GetOption("CPACK_INSTALL_CMAKE_PROJECTS"); + cmProp cmakeGenerator = this->GetOption("CPACK_CMAKE_GENERATOR"); std::string absoluteDestFiles; if (cmNonempty(cmakeProjects)) { if (!cmakeGenerator) { @@ -595,7 +594,7 @@ int cmCPackGenerator::InstallProjectViaInstallCMakeProjects( // Determine the installation types for this project (if provided). std::string installTypesVar = "CPACK_" + cmSystemTools::UpperCase(project.Component) + "_INSTALL_TYPES"; - const char* installTypes = this->GetOption(installTypesVar); + cmProp installTypes = this->GetOption(installTypesVar); if (cmNonempty(installTypes)) { std::vector<std::string> installTypesVector = cmExpandedList(installTypes); @@ -608,7 +607,7 @@ int cmCPackGenerator::InstallProjectViaInstallCMakeProjects( // Determine the set of components that will be used in this project std::string componentsVar = "CPACK_COMPONENTS_" + cmSystemTools::UpperCase(project.Component); - const char* components = this->GetOption(componentsVar); + cmProp components = this->GetOption(componentsVar); if (cmNonempty(components)) { cmExpandList(components, componentsVector); for (std::string const& comp : componentsVector) { @@ -625,12 +624,7 @@ int cmCPackGenerator::InstallProjectViaInstallCMakeProjects( std::vector<std::string> buildConfigs; // Try get configuration names given via `-C` CLI option - { - const char* const buildConfigCstr = - this->GetOption("CPACK_BUILD_CONFIG"); - auto buildConfig = buildConfigCstr ? buildConfigCstr : std::string{}; - cmExpandList(buildConfig, buildConfigs); - } + cmExpandList(this->GetOption("CPACK_BUILD_CONFIG"), buildConfigs); // Remove duplicates std::sort(buildConfigs.begin(), buildConfigs.end()); @@ -767,11 +761,11 @@ int cmCPackGenerator::InstallCMakeProject( tempInstallDirectory += this->GetComponentInstallDirNameSuffix(component); if (this->IsOn("CPACK_COMPONENT_INCLUDE_TOPLEVEL_DIRECTORY")) { tempInstallDirectory += "/"; - tempInstallDirectory += this->GetOption("CPACK_PACKAGE_FILE_NAME"); + tempInstallDirectory += *this->GetOption("CPACK_PACKAGE_FILE_NAME"); } } - const char* default_dir_inst_permissions = + cmProp default_dir_inst_permissions = this->GetOption("CPACK_INSTALL_DEFAULT_DIRECTORY_PERMISSIONS"); if (cmNonempty(default_dir_inst_permissions)) { mf.AddDefinition("CMAKE_INSTALL_DEFAULT_DIRECTORY_PERMISSIONS", @@ -795,12 +789,13 @@ int cmCPackGenerator::InstallCMakeProject( // I know this is tricky and awkward but it's the price for // CPACK_SET_DESTDIR backward compatibility. if (cmIsInternallyOn(this->GetOption("CPACK_SET_DESTDIR"))) { - this->SetOption("CPACK_INSTALL_PREFIX", - this->GetOption("CPACK_PACKAGING_INSTALL_PREFIX")); + this->SetOption( + "CPACK_INSTALL_PREFIX", + this->GetOption("CPACK_PACKAGING_INSTALL_PREFIX").GetCStr()); } std::string dir; if (this->GetOption("CPACK_INSTALL_PREFIX")) { - dir += this->GetOption("CPACK_INSTALL_PREFIX"); + dir += *this->GetOption("CPACK_INSTALL_PREFIX"); } mf.AddDefinition("CMAKE_INSTALL_PREFIX", dir); @@ -979,7 +974,7 @@ int cmCPackGenerator::InstallCMakeProject( } else { this->SetOption( absoluteDestFileComponent, - cmToCStr(mf.GetDefinition("CPACK_ABSOLUTE_DESTINATION_FILES"))); + mf.GetDefinition("CPACK_ABSOLUTE_DESTINATION_FILES").GetCStr()); } } } @@ -1038,8 +1033,7 @@ int cmCPackGenerator::DoPackage() } if (cmIsOn(this->GetOption("CPACK_REMOVE_TOPLEVEL_DIRECTORY"))) { - const char* toplevelDirectory = - this->GetOption("CPACK_TOPLEVEL_DIRECTORY"); + cmProp toplevelDirectory = this->GetOption("CPACK_TOPLEVEL_DIRECTORY"); if (cmSystemTools::FileExists(toplevelDirectory)) { cmCPackLogger(cmCPackLog::LOG_VERBOSE, "Remove toplevel directory: " << toplevelDirectory @@ -1060,9 +1054,9 @@ int cmCPackGenerator::DoPackage() } cmCPackLogger(cmCPackLog::LOG_DEBUG, "Done install project " << std::endl); - const char* tempPackageFileName = + cmProp tempPackageFileName = this->GetOption("CPACK_TEMPORARY_PACKAGE_FILE_NAME"); - const char* tempDirectory = this->GetOption("CPACK_TEMPORARY_DIRECTORY"); + cmProp tempDirectory = this->GetOption("CPACK_TEMPORARY_DIRECTORY"); cmCPackLogger(cmCPackLog::LOG_DEBUG, "Find files" << std::endl); cmsys::Glob gl; @@ -1079,7 +1073,7 @@ int cmCPackGenerator::DoPackage() cmCPackLogger(cmCPackLog::LOG_OUTPUT, "Create package" << std::endl); cmCPackLogger(cmCPackLog::LOG_VERBOSE, "Package files to: " - << (tempPackageFileName ? tempPackageFileName : "(NULL)") + << (tempPackageFileName ? *tempPackageFileName : "(NULL)") << std::endl); if (cmSystemTools::FileExists(tempPackageFileName)) { cmCPackLogger(cmCPackLog::LOG_VERBOSE, @@ -1099,9 +1093,8 @@ int cmCPackGenerator::DoPackage() * may update this during PackageFiles. * (either putting several names or updating the provided one) */ - this->packageFileNames.emplace_back(tempPackageFileName ? tempPackageFileName - : ""); - this->toplevel = tempDirectory; + this->packageFileNames.emplace_back(tempPackageFileName); + this->toplevel = *tempDirectory; { // scope that enables package generators to run internal scripts with // latest CMake policies enabled cmMakefile::ScopePushPop pp{ this->MakefileMap }; @@ -1115,7 +1108,7 @@ int cmCPackGenerator::DoPackage() } } // Run post-build actions - const char* postBuildScripts = this->GetOption("CPACK_POST_BUILD_SCRIPTS"); + cmProp postBuildScripts = this->GetOption("CPACK_POST_BUILD_SCRIPTS"); if (postBuildScripts) { this->MakefileMap->AddDefinition("CPACK_PACKAGE_FILES", cmJoin(this->packageFileNames, ";")); @@ -1135,8 +1128,8 @@ int cmCPackGenerator::DoPackage() } /* Prepare checksum algorithm*/ - const char* algo = this->GetOption("CPACK_PACKAGE_CHECKSUM"); - std::unique_ptr<cmCryptoHash> crypto = cmCryptoHash::New(algo ? algo : ""); + cmProp algo = this->GetOption("CPACK_PACKAGE_CHECKSUM"); + std::unique_ptr<cmCryptoHash> crypto = cmCryptoHash::New(algo); /* * Copy the generated packages to final destination @@ -1151,19 +1144,19 @@ int cmCPackGenerator::DoPackage() for (std::string const& pkgFileName : this->packageFileNames) { std::string tmpPF(this->GetOption("CPACK_OUTPUT_FILE_PREFIX")); std::string filename(cmSystemTools::GetFilenameName(pkgFileName)); - tempPackageFileName = pkgFileName.c_str(); + tempPackageFileName = cmProp(pkgFileName); tmpPF += "/" + filename; const char* packageFileName = tmpPF.c_str(); cmCPackLogger(cmCPackLog::LOG_DEBUG, "Copy final package(s): " - << (tempPackageFileName ? tempPackageFileName : "(NULL)") + << (tempPackageFileName ? *tempPackageFileName : "(NULL)") << " to " << (packageFileName ? packageFileName : "(NULL)") << std::endl); if (!cmSystemTools::CopyFileIfDifferent(pkgFileName, tmpPF)) { cmCPackLogger( cmCPackLog::LOG_ERROR, "Problem copying the package: " - << (tempPackageFileName ? tempPackageFileName : "(NULL)") << " to " + << (tempPackageFileName ? *tempPackageFileName : "(NULL)") << " to " << (packageFileName ? packageFileName : "(NULL)") << std::endl); return 0; } @@ -1200,7 +1193,7 @@ int cmCPackGenerator::Initialize(const std::string& name, cmMakefile* mf) // set the running generator name this->SetOption("CPACK_GENERATOR", this->Name.c_str()); // Load the project specific config file - const char* config = this->GetOption("CPACK_PROJECT_CONFIG_FILE"); + cmProp config = this->GetOption("CPACK_PROJECT_CONFIG_FILE"); if (config) { mf->ReadListFile(config); } @@ -1250,15 +1243,14 @@ bool cmCPackGenerator::IsSetToEmpty(const std::string& op) const return false; } -const char* cmCPackGenerator::GetOption(const std::string& op) const +cmProp cmCPackGenerator::GetOption(const std::string& op) const { cmProp ret = this->MakefileMap->GetDefinition(op); if (!ret) { cmCPackLogger(cmCPackLog::LOG_DEBUG, "Warning, GetOption return NULL for: " << op << std::endl); - return nullptr; } - return ret->c_str(); + return ret; } std::vector<std::string> cmCPackGenerator::GetOptions() const @@ -1311,7 +1303,7 @@ const char* cmCPackGenerator::GetPackagingInstallPrefix() << this->GetOption("CPACK_PACKAGING_INSTALL_PREFIX") << "'" << std::endl); - return this->GetOption("CPACK_PACKAGING_INSTALL_PREFIX"); + return this->GetOption("CPACK_PACKAGING_INSTALL_PREFIX")->c_str(); } std::string cmCPackGenerator::FindTemplate(const char* name) @@ -1391,12 +1383,8 @@ int cmCPackGenerator::PrepareGroupingKind() method = ONE_PACKAGE_PER_GROUP; } - std::string groupingType; - // Second way to specify grouping - if (nullptr != this->GetOption("CPACK_COMPONENTS_GROUPING")) { - groupingType = this->GetOption("CPACK_COMPONENTS_GROUPING"); - } + std::string groupingType = *this->GetOption("CPACK_COMPONENTS_GROUPING"); if (!groupingType.empty()) { cmCPackLogger(cmCPackLog::LOG_VERBOSE, @@ -1477,18 +1465,18 @@ std::string cmCPackGenerator::GetComponentPackageFileName( if (isGroupName) { std::string groupDispVar = "CPACK_COMPONENT_GROUP_" + cmSystemTools::UpperCase(groupOrComponentName) + "_DISPLAY_NAME"; - const char* groupDispName = this->GetOption(groupDispVar); + cmProp groupDispName = this->GetOption(groupDispVar); if (groupDispName) { - suffix = "-" + std::string(groupDispName); + suffix = "-" + *groupDispName; } } /* the [single] component case */ else { std::string dispVar = "CPACK_COMPONENT_" + cmSystemTools::UpperCase(groupOrComponentName) + "_DISPLAY_NAME"; - const char* dispName = this->GetOption(dispVar); + cmProp dispName = this->GetOption(dispVar); if (dispName) { - suffix = "-" + std::string(dispName); + suffix = "-" + *dispName; } } } @@ -1531,9 +1519,9 @@ cmCPackInstallationType* cmCPackGenerator::GetInstallationType( "CPACK_INSTALL_TYPE_" + cmsys::SystemTools::UpperCase(name); installType->Name = name; - const char* displayName = this->GetOption(macroPrefix + "_DISPLAY_NAME"); + cmProp displayName = this->GetOption(macroPrefix + "_DISPLAY_NAME"); if (cmNonempty(displayName)) { - installType->DisplayName = displayName; + installType->DisplayName = *displayName; } else { installType->DisplayName = installType->Name; } @@ -1553,9 +1541,9 @@ cmCPackComponent* cmCPackGenerator::GetComponent( std::string macroPrefix = "CPACK_COMPONENT_" + cmsys::SystemTools::UpperCase(name); component->Name = name; - const char* displayName = this->GetOption(macroPrefix + "_DISPLAY_NAME"); + cmProp displayName = this->GetOption(macroPrefix + "_DISPLAY_NAME"); if (cmNonempty(displayName)) { - component->DisplayName = displayName; + component->DisplayName = *displayName; } else { component->DisplayName = component->Name; } @@ -1565,17 +1553,17 @@ cmCPackComponent* cmCPackGenerator::GetComponent( component->IsDownloaded = this->IsOn(macroPrefix + "_DOWNLOADED") || cmIsOn(this->GetOption("CPACK_DOWNLOAD_ALL")); - const char* archiveFile = this->GetOption(macroPrefix + "_ARCHIVE_FILE"); + cmProp archiveFile = this->GetOption(macroPrefix + "_ARCHIVE_FILE"); if (cmNonempty(archiveFile)) { - component->ArchiveFile = archiveFile; + component->ArchiveFile = *archiveFile; } - const char* plist = this->GetOption(macroPrefix + "_PLIST"); + cmProp plist = this->GetOption(macroPrefix + "_PLIST"); if (cmNonempty(plist)) { - component->Plist = plist; + component->Plist = *plist; } - const char* groupName = this->GetOption(macroPrefix + "_GROUP"); + cmProp groupName = this->GetOption(macroPrefix + "_GROUP"); if (cmNonempty(groupName)) { component->Group = this->GetComponentGroup(projectName, groupName); component->Group->Components.push_back(component); @@ -1583,13 +1571,13 @@ cmCPackComponent* cmCPackGenerator::GetComponent( component->Group = nullptr; } - const char* description = this->GetOption(macroPrefix + "_DESCRIPTION"); + cmProp description = this->GetOption(macroPrefix + "_DESCRIPTION"); if (cmNonempty(description)) { - component->Description = description; + component->Description = *description; } // Determine the installation types. - const char* installTypes = this->GetOption(macroPrefix + "_INSTALL_TYPES"); + cmProp installTypes = this->GetOption(macroPrefix + "_INSTALL_TYPES"); if (cmNonempty(installTypes)) { std::vector<std::string> installTypesVector = cmExpandedList(installTypes); @@ -1600,7 +1588,7 @@ cmCPackComponent* cmCPackGenerator::GetComponent( } // Determine the component dependencies. - const char* depends = this->GetOption(macroPrefix + "_DEPENDS"); + cmProp depends = this->GetOption(macroPrefix + "_DEPENDS"); if (cmNonempty(depends)) { std::vector<std::string> dependsVector = cmExpandedList(depends); for (std::string const& depend : dependsVector) { @@ -1624,21 +1612,20 @@ cmCPackComponentGroup* cmCPackGenerator::GetComponentGroup( if (!hasGroup) { // Define the group group->Name = name; - const char* displayName = this->GetOption(macroPrefix + "_DISPLAY_NAME"); + cmProp displayName = this->GetOption(macroPrefix + "_DISPLAY_NAME"); if (cmNonempty(displayName)) { - group->DisplayName = displayName; + group->DisplayName = *displayName; } else { group->DisplayName = group->Name; } - const char* description = this->GetOption(macroPrefix + "_DESCRIPTION"); + cmProp description = this->GetOption(macroPrefix + "_DESCRIPTION"); if (cmNonempty(description)) { - group->Description = description; + group->Description = *description; } group->IsBold = this->IsOn(macroPrefix + "_BOLD_TITLE"); group->IsExpandedByDefault = this->IsOn(macroPrefix + "_EXPANDED"); - const char* parentGroupName = - this->GetOption(macroPrefix + "_PARENT_GROUP"); + cmProp parentGroupName = this->GetOption(macroPrefix + "_PARENT_GROUP"); if (cmNonempty(parentGroupName)) { group->ParentGroup = this->GetComponentGroup(projectName, parentGroupName); diff --git a/Source/CPack/cmCPackGenerator.h b/Source/CPack/cmCPackGenerator.h index 2512d42..1968c35 100644 --- a/Source/CPack/cmCPackGenerator.h +++ b/Source/CPack/cmCPackGenerator.h @@ -12,6 +12,7 @@ #include "cm_sys_stat.h" #include "cmCPackComponentGroup.h" +#include "cmProperty.h" #include "cmSystemTools.h" class cmCPackLog; @@ -85,7 +86,7 @@ public: //! Set and get the options void SetOption(const std::string& op, const char* value); void SetOptionIfNotSet(const std::string& op, const char* value); - const char* GetOption(const std::string& op) const; + cmProp GetOption(const std::string& op) const; std::vector<std::string> GetOptions() const; bool IsSet(const std::string& name) const; bool IsOn(const std::string& name) const; diff --git a/Source/CPack/cmCPackNSISGenerator.cxx b/Source/CPack/cmCPackNSISGenerator.cxx index 395b1df..a3b59ca 100644 --- a/Source/CPack/cmCPackNSISGenerator.cxx +++ b/Source/CPack/cmCPackNSISGenerator.cxx @@ -19,6 +19,7 @@ #include "cmCPackLog.h" #include "cmDuration.h" #include "cmGeneratedFileStream.h" +#include "cmProperty.h" #include "cmStringAlgorithms.h" #include "cmSystemTools.h" @@ -142,9 +143,9 @@ int cmCPackNSISGenerator::PackageFiles() } std::string installerHeaderImage; if (this->IsSet("CPACK_NSIS_MUI_HEADERIMAGE")) { - installerHeaderImage = this->GetOption("CPACK_NSIS_MUI_HEADERIMAGE"); + installerHeaderImage = *this->GetOption("CPACK_NSIS_MUI_HEADERIMAGE"); } else if (this->IsSet("CPACK_PACKAGE_ICON")) { - installerHeaderImage = this->GetOption("CPACK_PACKAGE_ICON"); + installerHeaderImage = *this->GetOption("CPACK_PACKAGE_ICON"); } if (!installerHeaderImage.empty()) { std::string installerIconCode = cmStrCat( @@ -479,8 +480,8 @@ int cmCPackNSISGenerator::InitializeInternal() cmsys::RegularExpression versionRexCVS("v(.*)\\.cvs"); if (!resS || retVal || (!versionRex.find(output) && !versionRexCVS.find(output))) { - const char* topDir = this->GetOption("CPACK_TOPLEVEL_DIRECTORY"); - std::string tmpFile = cmStrCat(topDir ? topDir : ".", "/NSISOutput.log"); + cmProp topDir = this->GetOption("CPACK_TOPLEVEL_DIRECTORY"); + std::string tmpFile = cmStrCat(topDir ? *topDir : ".", "/NSISOutput.log"); cmGeneratedFileStream ofs(tmpFile); ofs << "# Run command: " << nsisCmd << std::endl << "# Output:" << std::endl @@ -512,11 +513,11 @@ int cmCPackNSISGenerator::InitializeInternal() } this->SetOptionIfNotSet("CPACK_INSTALLER_PROGRAM", nsisPath.c_str()); this->SetOptionIfNotSet("CPACK_NSIS_EXECUTABLES_DIRECTORY", "bin"); - const char* cpackPackageExecutables = + cmProp cpackPackageExecutables = this->GetOption("CPACK_PACKAGE_EXECUTABLES"); - const char* cpackPackageDeskTopLinks = + cmProp cpackPackageDeskTopLinks = this->GetOption("CPACK_CREATE_DESKTOP_LINKS"); - const char* cpackNsisExecutablesDirectory = + cmProp cpackNsisExecutablesDirectory = this->GetOption("CPACK_NSIS_EXECUTABLES_DIRECTORY"); std::vector<std::string> cpackPackageDesktopLinksVector; if (cpackPackageDeskTopLinks) { @@ -589,7 +590,7 @@ int cmCPackNSISGenerator::InitializeInternal() void cmCPackNSISGenerator::CreateMenuLinks(std::ostream& str, std::ostream& deleteStr) { - const char* cpackMenuLinks = this->GetOption("CPACK_NSIS_MENU_LINKS"); + cmProp cpackMenuLinks = this->GetOption("CPACK_NSIS_MENU_LINKS"); if (!cpackMenuLinks) { return; } @@ -728,11 +729,10 @@ std::string cmCPackNSISGenerator::CreateComponentDescription( } // Create the directory for the upload area - const char* userUploadDirectory = - this->GetOption("CPACK_UPLOAD_DIRECTORY"); + cmProp userUploadDirectory = this->GetOption("CPACK_UPLOAD_DIRECTORY"); std::string uploadDirectory; if (cmNonempty(userUploadDirectory)) { - uploadDirectory = userUploadDirectory; + uploadDirectory = *userUploadDirectory; } else { uploadDirectory = cmStrCat(this->GetOption("CPACK_PACKAGE_DIRECTORY"), "/CPackUploads"); @@ -968,9 +968,9 @@ std::string cmCPackNSISGenerator::CreateComponentGroupDescription( std::string cmCPackNSISGenerator::CustomComponentInstallDirectory( cm::string_view componentName) { - const char* outputDir = this->GetOption( + cmProp outputDir = this->GetOption( cmStrCat("CPACK_NSIS_", componentName, "_INSTALL_DIRECTORY")); - return outputDir ? outputDir : "$INSTDIR"; + return outputDir ? *outputDir : "$INSTDIR"; } std::string cmCPackNSISGenerator::TranslateNewlines(std::string str) diff --git a/Source/CPack/cmCPackNuGetGenerator.cxx b/Source/CPack/cmCPackNuGetGenerator.cxx index 98dc890..9e7f92a 100644 --- a/Source/CPack/cmCPackNuGetGenerator.cxx +++ b/Source/CPack/cmCPackNuGetGenerator.cxx @@ -12,6 +12,7 @@ #include "cmCPackComponentGroup.h" #include "cmCPackLog.h" +#include "cmProperty.h" #include "cmStringAlgorithms.h" #include "cmSystemTools.h" @@ -120,7 +121,7 @@ void cmCPackNuGetGenerator::SetupGroupComponentVariables(bool ignoreGroup) void cmCPackNuGetGenerator::AddGeneratedPackageNames() { - const char* const files_list = this->GetOption("GEN_CPACK_OUTPUT_FILES"); + cmProp const files_list = this->GetOption("GEN_CPACK_OUTPUT_FILES"); if (!files_list) { cmCPackLogger( cmCPackLog::LOG_ERROR, @@ -129,7 +130,7 @@ void cmCPackNuGetGenerator::AddGeneratedPackageNames() return; } // add the generated packages to package file names list - std::string fileNames{ files_list }; + const std::string& fileNames = *files_list; const char sep = ';'; std::string::size_type pos1 = 0; std::string::size_type pos2 = fileNames.find(sep, pos1 + 1); diff --git a/Source/CPack/cmCPackOSXX11Generator.cxx b/Source/CPack/cmCPackOSXX11Generator.cxx index 5de4a6f..262cc6e 100644 --- a/Source/CPack/cmCPackOSXX11Generator.cxx +++ b/Source/CPack/cmCPackOSXX11Generator.cxx @@ -10,6 +10,7 @@ #include "cmCPackLog.h" #include "cmDuration.h" #include "cmGeneratedFileStream.h" +#include "cmProperty.h" #include "cmStringAlgorithms.h" #include "cmSystemTools.h" @@ -22,7 +23,7 @@ int cmCPackOSXX11Generator::PackageFiles() // TODO: Use toplevel ? // It is used! Is this an obsolete comment? - const char* cpackPackageExecutables = + cmProp cpackPackageExecutables = this->GetOption("CPACK_PACKAGE_EXECUTABLES"); if (cpackPackageExecutables) { cmCPackLogger(cmCPackLog::LOG_DEBUG, @@ -70,7 +71,7 @@ int cmCPackOSXX11Generator::PackageFiles() const char* scrDir = scriptDirectory.c_str(); const char* contDir = contentsDirectory.c_str(); const char* rsrcFile = resourceFileName.c_str(); - const char* iconFile = this->GetOption("CPACK_PACKAGE_ICON"); + cmProp iconFile = this->GetOption("CPACK_PACKAGE_ICON"); if (iconFile) { std::string iconFileName = cmsys::SystemTools::GetFilenameName(iconFile); if (!cmSystemTools::FileExists(iconFile)) { @@ -103,9 +104,9 @@ int cmCPackOSXX11Generator::PackageFiles() true) || !this->CopyResourcePlistFile("OSXScriptLauncher.rsrc", dir, rsrcFile, true) || - !this->CopyResourcePlistFile("OSXScriptLauncher", appdir, - this->GetOption("CPACK_PACKAGE_FILE_NAME"), - true)) { + !this->CopyResourcePlistFile( + "OSXScriptLauncher", appdir, + this->GetOption("CPACK_PACKAGE_FILE_NAME").GetCStr(), true)) { cmCPackLogger(cmCPackLog::LOG_ERROR, "Problem copying the resource files" << std::endl); return 0; diff --git a/Source/CPack/cmCPackPKGGenerator.cxx b/Source/CPack/cmCPackPKGGenerator.cxx index ac3d64d..a1eba56 100644 --- a/Source/CPack/cmCPackPKGGenerator.cxx +++ b/Source/CPack/cmCPackPKGGenerator.cxx @@ -7,6 +7,7 @@ #include "cmCPackComponentGroup.h" #include "cmCPackGenerator.h" #include "cmCPackLog.h" +#include "cmProperty.h" #include "cmStringAlgorithms.h" #include "cmSystemTools.h" #include "cmXMLWriter.h" @@ -56,7 +57,7 @@ void cmCPackPKGGenerator::CreateBackground(const char* themeName, std::string opt = (themeName == nullptr) ? cmStrCat("CPACK_", genName, "_BACKGROUND") : cmStrCat("CPACK_", genName, "_BACKGROUND_", paramSuffix); - const char* bgFileName = this->GetOption(opt); + cmProp bgFileName = this->GetOption(opt); if (bgFileName == nullptr) { return; } @@ -78,7 +79,7 @@ void cmCPackPKGGenerator::CreateBackground(const char* themeName, xout.Attribute("file", bgFileName); - const char* param = this->GetOption(cmStrCat(opt, "_ALIGNMENT")); + cmProp param = this->GetOption(cmStrCat(opt, "_ALIGNMENT")); if (param != nullptr) { xout.Attribute("alignment", param); } @@ -315,7 +316,7 @@ bool cmCPackPKGGenerator::CopyCreateResourceFile(const std::string& name, { std::string uname = cmSystemTools::UpperCase(name); std::string cpackVar = "CPACK_RESOURCE_FILE_" + uname; - const char* inFileName = this->GetOption(cpackVar); + cmProp inFileName = this->GetOption(cpackVar); if (!inFileName) { cmCPackLogger(cmCPackLog::LOG_ERROR, "CPack option: " << cpackVar.c_str() @@ -351,7 +352,7 @@ bool cmCPackPKGGenerator::CopyCreateResourceFile(const std::string& name, (name + ext).c_str()); cmCPackLogger(cmCPackLog::LOG_VERBOSE, - "Configure file: " << (inFileName ? inFileName : "(NULL)") + "Configure file: " << (inFileName ? *inFileName : "(NULL)") << " to " << destFileName << std::endl); this->ConfigureFile(inFileName, destFileName); return true; diff --git a/Source/CPack/cmCPackPackageMakerGenerator.cxx b/Source/CPack/cmCPackPackageMakerGenerator.cxx index f51ea42..33b601c 100644 --- a/Source/CPack/cmCPackPackageMakerGenerator.cxx +++ b/Source/CPack/cmCPackPackageMakerGenerator.cxx @@ -16,6 +16,7 @@ #include "cmCPackLog.h" #include "cmDuration.h" #include "cmGeneratedFileStream.h" +#include "cmProperty.h" #include "cmStringAlgorithms.h" #include "cmSystemTools.h" #include "cmXMLWriter.h" @@ -79,9 +80,9 @@ int cmCPackPackageMakerGenerator::PackageFiles() resDir += "/en.lproj"; } - const char* preflight = this->GetOption("CPACK_PREFLIGHT_SCRIPT"); - const char* postflight = this->GetOption("CPACK_POSTFLIGHT_SCRIPT"); - const char* postupgrade = this->GetOption("CPACK_POSTUPGRADE_SCRIPT"); + cmProp preflight = this->GetOption("CPACK_PREFLIGHT_SCRIPT"); + cmProp postflight = this->GetOption("CPACK_POSTFLIGHT_SCRIPT"); + cmProp postupgrade = this->GetOption("CPACK_POSTUPGRADE_SCRIPT"); if (this->Components.empty()) { // Create directory structure @@ -167,10 +168,9 @@ int cmCPackPackageMakerGenerator::PackageFiles() // Create the directory where downloaded component packages will // be placed. - const char* userUploadDirectory = - this->GetOption("CPACK_UPLOAD_DIRECTORY"); + cmProp userUploadDirectory = this->GetOption("CPACK_UPLOAD_DIRECTORY"); std::string uploadDirectory; - if (userUploadDirectory && *userUploadDirectory) { + if (userUploadDirectory && !userUploadDirectory->empty()) { uploadDirectory = userUploadDirectory; } else { uploadDirectory = @@ -352,8 +352,8 @@ int cmCPackPackageMakerGenerator::InitializeInternal() "/PackageMaker.app/Contents/MacOS"); std::string pkgPath; - const char* inst_program = this->GetOption("CPACK_INSTALLER_PROGRAM"); - if (inst_program && *inst_program) { + cmProp inst_program = this->GetOption("CPACK_INSTALLER_PROGRAM"); + if (inst_program && !inst_program->empty()) { pkgPath = inst_program; } else { pkgPath = cmSystemTools::FindProgram("PackageMaker", paths, false); @@ -427,11 +427,12 @@ int cmCPackPackageMakerGenerator::InitializeInternal() // Determine the package compatibility version. If it wasn't // specified by the user, we define it based on which features the // user requested. - const char* packageCompat = this->GetOption("CPACK_OSX_PACKAGE_VERSION"); - if (packageCompat && *packageCompat) { + cmProp packageCompat = this->GetOption("CPACK_OSX_PACKAGE_VERSION"); + if (packageCompat && !packageCompat->empty()) { unsigned int majorVersion = 10; unsigned int minorVersion = 5; - int res = sscanf(packageCompat, "%u.%u", &majorVersion, &minorVersion); + int res = + sscanf(packageCompat->c_str(), "%u.%u", &majorVersion, &minorVersion); if (res == 2) { this->PackageCompatibilityVersion = getVersion(majorVersion, minorVersion); diff --git a/Source/CPack/cmCPackProductBuildGenerator.cxx b/Source/CPack/cmCPackProductBuildGenerator.cxx index a3e55de..99c55a0 100644 --- a/Source/CPack/cmCPackProductBuildGenerator.cxx +++ b/Source/CPack/cmCPackProductBuildGenerator.cxx @@ -10,6 +10,7 @@ #include "cmCPackLog.h" #include "cmDuration.h" #include "cmGeneratedFileStream.h" +#include "cmProperty.h" #include "cmStringAlgorithms.h" #include "cmSystemTools.h" @@ -87,11 +88,11 @@ int cmCPackProductBuildGenerator::PackageFiles() std::string version = this->GetOption("CPACK_PACKAGE_VERSION"); std::string productbuild = this->GetOption("CPACK_COMMAND_PRODUCTBUILD"); std::string identityName; - if (const char* n = this->GetOption("CPACK_PRODUCTBUILD_IDENTITY_NAME")) { + if (cmProp n = this->GetOption("CPACK_PRODUCTBUILD_IDENTITY_NAME")) { identityName = n; } std::string keychainPath; - if (const char* p = this->GetOption("CPACK_PRODUCTBUILD_KEYCHAIN_PATH")) { + if (cmProp p = this->GetOption("CPACK_PRODUCTBUILD_KEYCHAIN_PATH")) { keychainPath = p; } @@ -173,8 +174,8 @@ bool cmCPackProductBuildGenerator::GenerateComponentPackage( const char* comp_name = component ? component->Name.c_str() : nullptr; - const char* preflight = this->GetComponentScript("PREFLIGHT", comp_name); - const char* postflight = this->GetComponentScript("POSTFLIGHT", comp_name); + cmProp preflight = this->GetComponentScript("PREFLIGHT", comp_name); + cmProp postflight = this->GetComponentScript("POSTFLIGHT", comp_name); std::string resDir = packageFileDir; if (component) { @@ -213,11 +214,11 @@ bool cmCPackProductBuildGenerator::GenerateComponentPackage( std::string version = this->GetOption("CPACK_PACKAGE_VERSION"); std::string pkgbuild = this->GetOption("CPACK_COMMAND_PKGBUILD"); std::string identityName; - if (const char* n = this->GetOption("CPACK_PKGBUILD_IDENTITY_NAME")) { + if (cmProp n = this->GetOption("CPACK_PKGBUILD_IDENTITY_NAME")) { identityName = n; } std::string keychainPath; - if (const char* p = this->GetOption("CPACK_PKGBUILD_KEYCHAIN_PATH")) { + if (cmProp p = this->GetOption("CPACK_PKGBUILD_KEYCHAIN_PATH")) { keychainPath = p; } @@ -239,7 +240,7 @@ bool cmCPackProductBuildGenerator::GenerateComponentPackage( return RunProductBuild(pkgCmd.str()); } -const char* cmCPackProductBuildGenerator::GetComponentScript( +cmProp cmCPackProductBuildGenerator::GetComponentScript( const char* script, const char* component_name) { std::string scriptname = std::string("CPACK_") + script + "_"; diff --git a/Source/CPack/cmCPackProductBuildGenerator.h b/Source/CPack/cmCPackProductBuildGenerator.h index 462e2fc..8f169b0 100644 --- a/Source/CPack/cmCPackProductBuildGenerator.h +++ b/Source/CPack/cmCPackProductBuildGenerator.h @@ -8,6 +8,7 @@ #include "cmCPackGenerator.h" #include "cmCPackPKGGenerator.h" +#include "cmProperty.h" class cmCPackComponent; @@ -45,6 +46,5 @@ protected: const std::string& packageDir, const cmCPackComponent* component); - const char* GetComponentScript(const char* script, - const char* script_component); + cmProp GetComponentScript(const char* script, const char* script_component); }; diff --git a/Source/CPack/cmCPackRPMGenerator.cxx b/Source/CPack/cmCPackRPMGenerator.cxx index c3f6d59..2765c58 100644 --- a/Source/CPack/cmCPackRPMGenerator.cxx +++ b/Source/CPack/cmCPackRPMGenerator.cxx @@ -12,6 +12,7 @@ #include "cmCPackComponentGroup.h" #include "cmCPackGenerator.h" #include "cmCPackLog.h" +#include "cmProperty.h" #include "cmStringAlgorithms.h" #include "cmSystemTools.h" @@ -103,7 +104,7 @@ int cmCPackRPMGenerator::PackageComponents(bool ignoreGroup) this->packageFileNames.clear(); std::string initialTopLevel(this->GetOption("CPACK_TEMPORARY_DIRECTORY")); - const char* mainComponent = this->GetOption("CPACK_RPM_MAIN_COMPONENT"); + cmProp mainComponent = this->GetOption("CPACK_RPM_MAIN_COMPONENT"); if (this->IsOn("CPACK_RPM_DEBUGINFO_SINGLE_PACKAGE") && !this->IsOn("CPACK_RPM_DEBUGINFO_PACKAGE")) { diff --git a/Source/CPack/cmCPackSTGZGenerator.cxx b/Source/CPack/cmCPackSTGZGenerator.cxx index ad0a3e2..7eb8cc3 100644 --- a/Source/CPack/cmCPackSTGZGenerator.cxx +++ b/Source/CPack/cmCPackSTGZGenerator.cxx @@ -14,6 +14,7 @@ #include "cmArchiveWrite.h" #include "cmCPackGenerator.h" #include "cmCPackLog.h" +#include "cmProperty.h" #include "cmSystemTools.h" cmCPackSTGZGenerator::cmCPackSTGZGenerator() diff --git a/Source/CTest/cmCTestGenericHandler.cxx b/Source/CTest/cmCTestGenericHandler.cxx index 48cc0e4..bd33055 100644 --- a/Source/CTest/cmCTestGenericHandler.cxx +++ b/Source/CTest/cmCTestGenericHandler.cxx @@ -72,13 +72,13 @@ void cmCTestGenericHandler::Initialize() this->MultiOptions = this->PersistentMultiOptions; } -const char* cmCTestGenericHandler::GetOption(const std::string& op) +cmProp cmCTestGenericHandler::GetOption(const std::string& op) { auto remit = this->Options.find(op); if (remit == this->Options.end()) { return nullptr; } - return remit->second.c_str(); + return cmProp(remit->second); } std::vector<std::string> cmCTestGenericHandler::GetMultiOption( diff --git a/Source/CTest/cmCTestGenericHandler.h b/Source/CTest/cmCTestGenericHandler.h index e846fd9..0b8b224 100644 --- a/Source/CTest/cmCTestGenericHandler.h +++ b/Source/CTest/cmCTestGenericHandler.h @@ -11,6 +11,7 @@ #include <stddef.h> #include "cmCTest.h" +#include "cmProperty.h" #include "cmSystemTools.h" class cmGeneratedFileStream; @@ -87,7 +88,7 @@ public: */ void SetPersistentOption(const std::string& op, const char* value); void SetOption(const std::string& op, const char* value); - const char* GetOption(const std::string& op); + cmProp GetOption(const std::string& op); /** * Multi-Options collect one or more values from flags; passing diff --git a/Source/CTest/cmCTestSubmitHandler.cxx b/Source/CTest/cmCTestSubmitHandler.cxx index 5b54573..9322bd5 100644 --- a/Source/CTest/cmCTestSubmitHandler.cxx +++ b/Source/CTest/cmCTestSubmitHandler.cxx @@ -357,12 +357,8 @@ bool cmCTestSubmitHandler::SubmitUsingHTTP( // If curl failed for any reason, or checksum fails, wait and retry // if (res != CURLE_OK || this->HasErrors) { - std::string retryDelay = this->GetOption("RetryDelay") == nullptr - ? "" - : this->GetOption("RetryDelay"); - std::string retryCount = this->GetOption("RetryCount") == nullptr - ? "" - : this->GetOption("RetryCount"); + std::string retryDelay = *this->GetOption("RetryDelay"); + std::string retryCount = *this->GetOption("RetryCount"); auto delay = cmDuration( retryDelay.empty() @@ -522,12 +518,8 @@ int cmCTestSubmitHandler::HandleCDashUploadFile(std::string const& file, bool internalTest = cmIsOn(this->GetOption("InternalTest")); // Get RETRY_COUNT and RETRY_DELAY values if they were set. - std::string retryDelayString = this->GetOption("RetryDelay") == nullptr - ? "" - : this->GetOption("RetryDelay"); - std::string retryCountString = this->GetOption("RetryCount") == nullptr - ? "" - : this->GetOption("RetryCount"); + std::string retryDelayString = *this->GetOption("RetryDelay"); + std::string retryCountString = *this->GetOption("RetryCount"); auto retryDelay = std::chrono::seconds(0); if (!retryDelayString.empty()) { unsigned long retryDelayValue = 0; @@ -716,8 +708,8 @@ int cmCTestSubmitHandler::HandleCDashUploadFile(std::string const& file, int cmCTestSubmitHandler::ProcessHandler() { - const char* cdashUploadFile = this->GetOption("CDashUploadFile"); - const char* cdashUploadType = this->GetOption("CDashUploadType"); + cmProp cdashUploadFile = this->GetOption("CDashUploadFile"); + cmProp cdashUploadType = this->GetOption("CDashUploadType"); if (cdashUploadFile && cdashUploadType) { return this->HandleCDashUploadFile(cdashUploadFile, cdashUploadType); } @@ -804,6 +796,7 @@ int cmCTestSubmitHandler::ProcessHandler() } } this->CTest->AddIfExists(cmCTest::PartMemCheck, "DynamicAnalysis.xml"); + this->CTest->AddIfExists(cmCTest::PartMemCheck, "DynamicAnalysis-Test.xml"); this->CTest->AddIfExists(cmCTest::PartMemCheck, "Purify.xml"); this->CTest->AddIfExists(cmCTest::PartNotes, "Notes.xml"); this->CTest->AddIfExists(cmCTest::PartUpload, "Upload.xml"); diff --git a/Source/CTest/cmCTestTestHandler.cxx b/Source/CTest/cmCTestTestHandler.cxx index 1157d10..c41b661 100644 --- a/Source/CTest/cmCTestTestHandler.cxx +++ b/Source/CTest/cmCTestTestHandler.cxx @@ -521,7 +521,7 @@ bool cmCTestTestHandler::ProcessOptions() if (cmIsOn(this->GetOption("ScheduleRandom"))) { this->CTest->SetScheduleType("Random"); } - if (const char* repeat = this->GetOption("Repeat")) { + if (cmProp repeat = this->GetOption("Repeat")) { cmsys::RegularExpression repeatRegex( "^(UNTIL_FAIL|UNTIL_PASS|AFTER_TIMEOUT):([0-9]+)$"); if (repeatRegex.find(repeat)) { @@ -546,7 +546,7 @@ bool cmCTestTestHandler::ProcessOptions() } } if (this->GetOption("ParallelLevel")) { - this->CTest->SetParallelLevel(atoi(this->GetOption("ParallelLevel"))); + this->CTest->SetParallelLevel(std::stoi(this->GetOption("ParallelLevel"))); } if (this->GetOption("StopOnFailure")) { @@ -557,7 +557,7 @@ bool cmCTestTestHandler::ProcessOptions() this->IncludeLabelRegularExpressions); BuildLabelRE(this->GetMultiOption("ExcludeLabelRegularExpression"), this->ExcludeLabelRegularExpressions); - const char* val = this->GetOption("IncludeRegularExpression"); + cmProp val = this->GetOption("IncludeRegularExpression"); if (val) { this->UseIncludeRegExp(); this->SetIncludeRegExp(val); @@ -569,19 +569,19 @@ bool cmCTestTestHandler::ProcessOptions() } val = this->GetOption("ExcludeFixtureRegularExpression"); if (val) { - this->ExcludeFixtureRegExp = val; + this->ExcludeFixtureRegExp = *val; } val = this->GetOption("ExcludeFixtureSetupRegularExpression"); if (val) { - this->ExcludeFixtureSetupRegExp = val; + this->ExcludeFixtureSetupRegExp = *val; } val = this->GetOption("ExcludeFixtureCleanupRegularExpression"); if (val) { - this->ExcludeFixtureCleanupRegExp = val; + this->ExcludeFixtureCleanupRegExp = *val; } val = this->GetOption("ResourceSpecFile"); if (val) { - this->ResourceSpecFile = val; + this->ResourceSpecFile = *val; } this->SetRerunFailed(cmIsOn(this->GetOption("RerunFailed"))); @@ -705,6 +705,21 @@ bool cmCTestTestHandler::GenerateXML() this->GenerateCTestXML(xml); } + if (this->MemCheck) { + cmGeneratedFileStream xmlfile; + if (!this->StartResultingXML(cmCTest::PartTest, "DynamicAnalysis-Test", + xmlfile)) { + cmCTestLog(this->CTest, ERROR_MESSAGE, + "Cannot create testing XML file" << std::endl); + this->LogFile = nullptr; + return false; + } + cmXMLWriter xml(xmlfile); + // Explicitly call this class' `GenerateCTestXML` method to make `Test.xml` + // as well. + this->cmCTestTestHandler::GenerateCTestXML(xml); + } + return true; } @@ -2066,26 +2081,26 @@ void cmCTestTestHandler::RecordCustomTestMeasurements(cmXMLWriter& xml, } } -void cmCTestTestHandler::SetIncludeRegExp(const char* arg) +void cmCTestTestHandler::SetIncludeRegExp(const std::string& arg) { this->IncludeRegExp = arg; } -void cmCTestTestHandler::SetExcludeRegExp(const char* arg) +void cmCTestTestHandler::SetExcludeRegExp(const std::string& arg) { this->ExcludeRegExp = arg; } -void cmCTestTestHandler::SetTestsToRunInformation(const char* in) +void cmCTestTestHandler::SetTestsToRunInformation(cmProp in) { if (!in) { return; } - this->TestsToRunString = in; + this->TestsToRunString = *in; // if the argument is a file, then read it and use the contents as the // string if (cmSystemTools::FileExists(in)) { - cmsys::ifstream fin(in); + cmsys::ifstream fin(in->c_str()); unsigned long filelen = cmSystemTools::FileLength(in); auto buff = cm::make_unique<char[]>(filelen + 1); fin.getline(buff.get(), filelen); diff --git a/Source/CTest/cmCTestTestHandler.h b/Source/CTest/cmCTestTestHandler.h index f2da320..585a336 100644 --- a/Source/CTest/cmCTestTestHandler.h +++ b/Source/CTest/cmCTestTestHandler.h @@ -22,6 +22,7 @@ #include "cmCTestResourceSpec.h" #include "cmDuration.h" #include "cmListFileCache.h" +#include "cmProperty.h" class cmMakefile; class cmXMLWriter; @@ -65,8 +66,8 @@ public: /// them on void UseIncludeRegExp(); void UseExcludeRegExp(); - void SetIncludeRegExp(const char*); - void SetExcludeRegExp(const char*); + void SetIncludeRegExp(const std::string&); + void SetExcludeRegExp(const std::string&); void SetMaxIndex(int n) { this->MaxIndex = n; } int GetMaxIndex() { return this->MaxIndex; } @@ -81,7 +82,7 @@ public: } //! pass the -I argument down - void SetTestsToRunInformation(const char*); + void SetTestsToRunInformation(cmProp); cmCTestTestHandler(); diff --git a/Source/CTest/cmCTestUpdateHandler.cxx b/Source/CTest/cmCTestUpdateHandler.cxx index 57cc024..7c7c380 100644 --- a/Source/CTest/cmCTestUpdateHandler.cxx +++ b/Source/CTest/cmCTestUpdateHandler.cxx @@ -17,6 +17,7 @@ #include "cmCTestSVN.h" #include "cmCTestVC.h" #include "cmGeneratedFileStream.h" +#include "cmProperty.h" #include "cmStringAlgorithms.h" #include "cmSystemTools.h" #include "cmVersion.h" @@ -108,7 +109,7 @@ int cmCTestUpdateHandler::ProcessHandler() static_cast<void>(fixLocale); // Get source dir - const char* sourceDirectory = this->GetOption("SourceDirectory"); + cmProp sourceDirectory = this->GetOption("SourceDirectory"); if (!sourceDirectory) { cmCTestLog(this->CTest, ERROR_MESSAGE, "Cannot find SourceDirectory key in the DartConfiguration.tcl" @@ -257,7 +258,7 @@ int cmCTestUpdateHandler::ProcessHandler() return updated && loadedMods ? numUpdated : -1; } -int cmCTestUpdateHandler::DetectVCS(const char* dir) +int cmCTestUpdateHandler::DetectVCS(const std::string& dir) { std::string sourceDirectory = dir; cmCTestOptionalLog(this->CTest, DEBUG, diff --git a/Source/CTest/cmCTestUpdateHandler.h b/Source/CTest/cmCTestUpdateHandler.h index 25bbb2f..70269ea 100644 --- a/Source/CTest/cmCTestUpdateHandler.h +++ b/Source/CTest/cmCTestUpdateHandler.h @@ -59,6 +59,6 @@ private: std::string UpdateCommand; int UpdateType; - int DetectVCS(const char* dir); + int DetectVCS(const std::string& dir); bool SelectVCS(); }; diff --git a/Source/cmAlgorithms.h b/Source/cmAlgorithms.h index c192e2a..a1830f9 100644 --- a/Source/cmAlgorithms.h +++ b/Source/cmAlgorithms.h @@ -60,6 +60,10 @@ class cmListFileBacktrace; using cmBacktraceRange = cmRange<std::vector<cmListFileBacktrace>::const_iterator>; +template <typename T> +class BT; +using cmBTStringRange = cmRange<std::vector<BT<std::string>>::const_iterator>; + template <typename Range> typename Range::const_iterator cmRemoveN(Range& r, size_t n) { @@ -133,7 +137,13 @@ ForwardIterator cmRemoveDuplicates(ForwardIterator first, ForwardIterator last) } template <typename Range> -typename Range::const_iterator cmRemoveDuplicates(Range& r) +typename Range::iterator cmRemoveDuplicates(Range& r) +{ + return cmRemoveDuplicates(r.begin(), r.end()); +} + +template <typename Range> +typename Range::const_iterator cmRemoveDuplicates(Range const& r) { return cmRemoveDuplicates(r.begin(), r.end()); } diff --git a/Source/cmCPluginAPI.cxx b/Source/cmCPluginAPI.cxx index ace7382..e922ee5 100644 --- a/Source/cmCPluginAPI.cxx +++ b/Source/cmCPluginAPI.cxx @@ -173,7 +173,7 @@ void CCONV cmAddLinkDirectoryForTarget(void* arg, const char* tgt, std::string(tgt) + " for directory " + std::string(d)); return; } - t->InsertLinkDirectory(d, mf->GetBacktrace()); + t->InsertLinkDirectory(BT<std::string>(d, mf->GetBacktrace())); } void CCONV cmAddExecutable(void* arg, const char* exename, int numSrcs, diff --git a/Source/cmCacheManager.cxx b/Source/cmCacheManager.cxx index 8fefaa6..17369c8 100644 --- a/Source/cmCacheManager.cxx +++ b/Source/cmCacheManager.cxx @@ -232,17 +232,17 @@ bool cmCacheManager::SaveCache(const std::string& path, cmMessenger* messenger) // before writing the cache, update the version numbers // to the this->AddCacheEntry("CMAKE_CACHE_MAJOR_VERSION", - std::to_string(cmVersion::GetMajorVersion()).c_str(), + std::to_string(cmVersion::GetMajorVersion()), "Major version of cmake used to create the " "current loaded cache", cmStateEnums::INTERNAL); this->AddCacheEntry("CMAKE_CACHE_MINOR_VERSION", - std::to_string(cmVersion::GetMinorVersion()).c_str(), + std::to_string(cmVersion::GetMinorVersion()), "Minor version of cmake used to create the " "current loaded cache", cmStateEnums::INTERNAL); this->AddCacheEntry("CMAKE_CACHE_PATCH_VERSION", - std::to_string(cmVersion::GetPatchVersion()).c_str(), + std::to_string(cmVersion::GetPatchVersion()), "Patch version of cmake used to create the " "current loaded cache", cmStateEnums::INTERNAL); @@ -256,7 +256,7 @@ bool cmCacheManager::SaveCache(const std::string& path, cmMessenger* messenger) currentcwd[0] = static_cast<char>(currentcwd[0] - 'A' + 'a'); } cmSystemTools::ConvertToUnixSlashes(currentcwd); - this->AddCacheEntry("CMAKE_CACHEFILE_DIR", currentcwd.c_str(), + this->AddCacheEntry("CMAKE_CACHEFILE_DIR", currentcwd, "This is the directory where this CMakeCache.txt" " was created", cmStateEnums::INTERNAL); @@ -521,7 +521,7 @@ void cmCacheManager::PrintCache(std::ostream& out) const "=================================================\n"; } -void cmCacheManager::AddCacheEntry(const std::string& key, const char* value, +void cmCacheManager::AddCacheEntry(const std::string& key, cmProp value, const char* helpString, cmStateEnums::CacheEntryType type) { @@ -550,10 +550,10 @@ void cmCacheManager::AddCacheEntry(const std::string& key, const char* value, : "(This variable does not exist and should not be used)"); } -void cmCacheManager::CacheEntry::SetValue(const char* value) +void cmCacheManager::CacheEntry::SetValue(cmProp value) { if (value) { - this->Value = value; + this->Value = *value; this->Initialized = true; } else { this->Value.clear(); diff --git a/Source/cmCacheManager.h b/Source/cmCacheManager.h index 0238fb8..eca7150 100644 --- a/Source/cmCacheManager.h +++ b/Source/cmCacheManager.h @@ -31,7 +31,7 @@ class cmCacheManager public: const std::string& GetValue() const { return this->Value; } - void SetValue(const char*); + void SetValue(cmProp); cmStateEnums::CacheEntryType GetType() const { return this->Type; } void SetType(cmStateEnums::CacheEntryType ty) { this->Type = ty; } @@ -83,7 +83,7 @@ public: void SetCacheEntryValue(std::string const& key, std::string const& value) { if (auto* entry = this->GetCacheEntry(key)) { - entry->SetValue(value.c_str()); + entry->SetValue(cmProp(value)); } } @@ -173,6 +173,18 @@ public: //! Add an entry into the cache void AddCacheEntry(const std::string& key, const char* value, + const char* helpString, cmStateEnums::CacheEntryType type) + { + this->AddCacheEntry(key, + value ? cmProp(std::string(value)) : cmProp(nullptr), + helpString, type); + } + void AddCacheEntry(const std::string& key, const std::string& value, + const char* helpString, cmStateEnums::CacheEntryType type) + { + this->AddCacheEntry(key, cmProp(value), helpString, type); + } + void AddCacheEntry(const std::string& key, cmProp value, const char* helpString, cmStateEnums::CacheEntryType type); diff --git a/Source/cmComputeLinkDepends.cxx b/Source/cmComputeLinkDepends.cxx index 0b27e34..15a12ba 100644 --- a/Source/cmComputeLinkDepends.cxx +++ b/Source/cmComputeLinkDepends.cxx @@ -607,7 +607,7 @@ cmLinkItem cmComputeLinkDepends::ResolveLinkItem(int depender_index, from = depender; } } - return from->ResolveLinkItem(name, cmListFileBacktrace()); + return from->ResolveLinkItem(BT<std::string>(name)); } void cmComputeLinkDepends::InferDependencies() diff --git a/Source/cmComputeTargetDepends.cxx b/Source/cmComputeTargetDepends.cxx index 76712f4..5d3e04f 100644 --- a/Source/cmComputeTargetDepends.cxx +++ b/Source/cmComputeTargetDepends.cxx @@ -323,7 +323,7 @@ void cmComputeTargetDepends::AddObjectDepends(int depender_index, } cmGeneratorTarget const* depender = this->Targets[depender_index]; cmLinkItem const& objItem = - depender->ResolveLinkItem(objLib, cmListFileBacktrace()); + depender->ResolveLinkItem(BT<std::string>(objLib)); if (emitted.insert(objItem).second) { if (depender->GetType() != cmStateEnums::EXECUTABLE && depender->GetType() != cmStateEnums::STATIC_LIBRARY && diff --git a/Source/cmFindBase.cxx b/Source/cmFindBase.cxx index f4e1763..37f9572 100644 --- a/Source/cmFindBase.cxx +++ b/Source/cmFindBase.cxx @@ -358,8 +358,8 @@ void cmFindBase::NormalizeFindResult() // value. if (value != *existingValue || this->AlreadyInCacheWithoutMetaInfo) { this->Makefile->GetCMakeInstance()->AddCacheEntry( - this->VariableName, value.c_str(), - this->VariableDocumentation.c_str(), this->VariableType); + this->VariableName, value, this->VariableDocumentation.c_str(), + this->VariableType); if (this->Makefile->GetPolicyStatus(cmPolicies::CMP0126) == cmPolicies::NEW) { if (this->Makefile->IsNormalDefinitionSet(this->VariableName)) { diff --git a/Source/cmGeneratorTarget.cxx b/Source/cmGeneratorTarget.cxx index 3201ae3..648708a 100644 --- a/Source/cmGeneratorTarget.cxx +++ b/Source/cmGeneratorTarget.cxx @@ -145,12 +145,10 @@ private: class TargetPropertyEntryString : public cmGeneratorTarget::TargetPropertyEntry { public: - TargetPropertyEntryString(std::string propertyValue, - cmListFileBacktrace backtrace, + TargetPropertyEntryString(BT<std::string> propertyValue, cmLinkImplItem const& item = NoLinkImplItem) : cmGeneratorTarget::TargetPropertyEntry(item) , PropertyValue(std::move(propertyValue)) - , Backtrace(std::move(backtrace)) { } @@ -159,46 +157,46 @@ public: cmGeneratorExpressionDAGChecker*, std::string const&) const override { - return this->PropertyValue; + return this->PropertyValue.Value; } - cmListFileBacktrace GetBacktrace() const override { return this->Backtrace; } - std::string const& GetInput() const override { return this->PropertyValue; } + cmListFileBacktrace GetBacktrace() const override + { + return this->PropertyValue.Backtrace; + } + std::string const& GetInput() const override + { + return this->PropertyValue.Value; + } private: - std::string PropertyValue; - cmListFileBacktrace Backtrace; + BT<std::string> PropertyValue; }; std::unique_ptr<cmGeneratorTarget::TargetPropertyEntry> -CreateTargetPropertyEntry( - const std::string& propertyValue, - cmListFileBacktrace backtrace = cmListFileBacktrace(), - bool evaluateForBuildsystem = false) +CreateTargetPropertyEntry(const BT<std::string>& propertyValue, + bool evaluateForBuildsystem = false) { - if (cmGeneratorExpression::Find(propertyValue) != std::string::npos) { - cmGeneratorExpression ge(std::move(backtrace)); + if (cmGeneratorExpression::Find(propertyValue.Value) != std::string::npos) { + cmGeneratorExpression ge(propertyValue.Backtrace); std::unique_ptr<cmCompiledGeneratorExpression> cge = - ge.Parse(propertyValue); + ge.Parse(propertyValue.Value); cge->SetEvaluateForBuildsystem(evaluateForBuildsystem); return std::unique_ptr<cmGeneratorTarget::TargetPropertyEntry>( cm::make_unique<TargetPropertyEntryGenex>(std::move(cge))); } return std::unique_ptr<cmGeneratorTarget::TargetPropertyEntry>( - cm::make_unique<TargetPropertyEntryString>(propertyValue, - std::move(backtrace))); + cm::make_unique<TargetPropertyEntryString>(propertyValue)); } void CreatePropertyGeneratorExpressions( - cmStringRange entries, cmBacktraceRange backtraces, + cmBTStringRange entries, std::vector<std::unique_ptr<cmGeneratorTarget::TargetPropertyEntry>>& items, bool evaluateForBuildsystem = false) { - auto btIt = backtraces.begin(); - for (auto it = entries.begin(); it != entries.end(); ++it, ++btIt) { - items.push_back( - CreateTargetPropertyEntry(*it, *btIt, evaluateForBuildsystem)); + for (auto const& entry : entries) { + items.push_back(CreateTargetPropertyEntry(entry, evaluateForBuildsystem)); } } @@ -289,35 +287,27 @@ cmGeneratorTarget::cmGeneratorTarget(cmTarget* t, cmLocalGenerator* lg) this->GlobalGenerator->ComputeTargetObjectDirectory(this); CreatePropertyGeneratorExpressions(t->GetIncludeDirectoriesEntries(), - t->GetIncludeDirectoriesBacktraces(), this->IncludeDirectoriesEntries); CreatePropertyGeneratorExpressions(t->GetCompileOptionsEntries(), - t->GetCompileOptionsBacktraces(), this->CompileOptionsEntries); CreatePropertyGeneratorExpressions(t->GetCompileFeaturesEntries(), - t->GetCompileFeaturesBacktraces(), this->CompileFeaturesEntries); CreatePropertyGeneratorExpressions(t->GetCompileDefinitionsEntries(), - t->GetCompileDefinitionsBacktraces(), this->CompileDefinitionsEntries); CreatePropertyGeneratorExpressions(t->GetLinkOptionsEntries(), - t->GetLinkOptionsBacktraces(), this->LinkOptionsEntries); CreatePropertyGeneratorExpressions(t->GetLinkDirectoriesEntries(), - t->GetLinkDirectoriesBacktraces(), this->LinkDirectoriesEntries); CreatePropertyGeneratorExpressions(t->GetPrecompileHeadersEntries(), - t->GetPrecompileHeadersBacktraces(), this->PrecompileHeadersEntries); CreatePropertyGeneratorExpressions(t->GetSourceEntries(), - t->GetSourceBacktraces(), this->SourceEntries, true); this->PolicyMap = t->GetPolicyMap(); @@ -698,7 +688,8 @@ void cmGeneratorTarget::AddSourceCommon(const std::string& src, bool before) { this->SourceEntries.insert( before ? this->SourceEntries.begin() : this->SourceEntries.end(), - CreateTargetPropertyEntry(src, this->Makefile->GetBacktrace(), true)); + CreateTargetPropertyEntry( + BT<std::string>(src, this->Makefile->GetBacktrace()), true)); this->ClearSourcesCache(); } @@ -719,11 +710,13 @@ void cmGeneratorTarget::AddTracedSources(std::vector<std::string> const& srcs) void cmGeneratorTarget::AddIncludeDirectory(const std::string& src, bool before) { - this->Target->InsertInclude(src, this->Makefile->GetBacktrace(), before); + this->Target->InsertInclude( + BT<std::string>(src, this->Makefile->GetBacktrace()), before); this->IncludeDirectoriesEntries.insert( before ? this->IncludeDirectoriesEntries.begin() : this->IncludeDirectoriesEntries.end(), - CreateTargetPropertyEntry(src, this->Makefile->GetBacktrace(), true)); + CreateTargetPropertyEntry( + BT<std::string>(src, this->Makefile->GetBacktrace()), true)); } std::vector<cmSourceFile*> const* cmGeneratorTarget::GetSourceDepends( @@ -1675,9 +1668,9 @@ std::vector<BT<std::string>> cmGeneratorTarget::GetSourceFilePaths( // for TARGET_OBJECTS instead for backwards compatibility with OLD // behavior of CMP0024 and CMP0026 only. - cmStringRange sourceEntries = this->Target->GetSourceEntries(); - for (std::string const& entry : sourceEntries) { - std::vector<std::string> items = cmExpandedList(entry); + cmBTStringRange sourceEntries = this->Target->GetSourceEntries(); + for (auto const& entry : sourceEntries) { + std::vector<std::string> items = cmExpandedList(entry.Value); for (std::string const& item : items) { if (cmHasLiteralPrefix(item, "$<TARGET_OBJECTS:") && item.back() == '>') { @@ -6364,7 +6357,7 @@ cm::optional<cmLinkItem> cmGeneratorTarget::LookupLinkItem( if (name == this->GetName() || name.empty()) { return maybeItem; } - maybeItem = this->ResolveLinkItem(name, bt, scope->LG); + maybeItem = this->ResolveLinkItem(BT<std::string>(name, bt), scope->LG); return maybeItem; } @@ -7377,9 +7370,9 @@ void cmGeneratorTarget::GetObjectLibrariesCMP0026( // there is no cmGeneratorTarget at configure-time, so search the SOURCES // for TARGET_OBJECTS instead for backwards compatibility with OLD // behavior of CMP0024 and CMP0026 only. - cmStringRange rng = this->Target->GetSourceEntries(); - for (std::string const& entry : rng) { - std::vector<std::string> files = cmExpandedList(entry); + cmBTStringRange rng = this->Target->GetSourceEntries(); + for (auto const& entry : rng) { + std::vector<std::string> files = cmExpandedList(entry.Value); for (std::string const& li : files) { if (cmHasLiteralPrefix(li, "$<TARGET_OBJECTS:") && li.back() == '>') { std::string objLibName = li.substr(17, li.size() - 18); @@ -7607,24 +7600,21 @@ void cmGeneratorTarget::ComputeLinkImplementationLibraries( { cmLocalGenerator const* lg = this->LocalGenerator; cmMakefile const* mf = lg->GetMakefile(); - cmStringRange entryRange = this->Target->GetLinkImplementationEntries(); - cmBacktraceRange btRange = this->Target->GetLinkImplementationBacktraces(); - cmBacktraceRange::const_iterator btIt = btRange.begin(); + cmBTStringRange entryRange = this->Target->GetLinkImplementationEntries(); // Collect libraries directly linked in this configuration. - for (cmStringRange::const_iterator le = entryRange.begin(), - end = entryRange.end(); - le != end; ++le, ++btIt) { + for (auto const& entry : entryRange) { std::vector<std::string> llibs; // Keep this logic in sync with ExpandLinkItems. cmGeneratorExpressionDAGChecker dagChecker(this, "LINK_LIBRARIES", nullptr, nullptr); - cmGeneratorExpression ge(*btIt); - std::unique_ptr<cmCompiledGeneratorExpression> const cge = ge.Parse(*le); + cmGeneratorExpression ge(entry.Backtrace); + std::unique_ptr<cmCompiledGeneratorExpression> const cge = + ge.Parse(entry.Value); cge->SetEvaluateForBuildsystem(true); std::string const& evaluated = cge->Evaluate(this->LocalGenerator, config, head, &dagChecker, nullptr, this->LinkerLanguage); - bool const fromGenex = evaluated != *le; + bool const fromGenex = evaluated != entry.Value; cmExpandList(evaluated, llibs); if (cge->GetHadHeadSensitiveCondition()) { impl.HadHeadSensitiveCondition = true; @@ -7682,7 +7672,8 @@ void cmGeneratorTarget::ComputeLinkImplementationLibraries( } // The entry is meant for this configuration. - cmLinkItem item = this->ResolveLinkItem(name, *btIt, lg); + cmLinkItem item = + this->ResolveLinkItem(BT<std::string>(name, entry.Backtrace), lg); if (!item.Target) { // Report explicitly linked object files separately. std::string const& maybeObj = item.AsStr(); @@ -7724,7 +7715,7 @@ void cmGeneratorTarget::ComputeLinkImplementationLibraries( } // Support OLD behavior for CMP0003. impl.WrongConfigLibraries.push_back( - this->ResolveLinkItem(name, cmListFileBacktrace())); + this->ResolveLinkItem(BT<std::string>(name))); } } } @@ -7750,16 +7741,16 @@ cmGeneratorTarget::TargetOrString cmGeneratorTarget::ResolveTargetReference( } cmLinkItem cmGeneratorTarget::ResolveLinkItem( - std::string const& name, cmListFileBacktrace const& bt) const + BT<std::string> const& name) const { - return this->ResolveLinkItem(name, bt, this->LocalGenerator); + return this->ResolveLinkItem(name, this->LocalGenerator); } -cmLinkItem cmGeneratorTarget::ResolveLinkItem(std::string const& name, - cmListFileBacktrace const& bt, +cmLinkItem cmGeneratorTarget::ResolveLinkItem(BT<std::string> const& name, cmLocalGenerator const* lg) const { - TargetOrString resolved = this->ResolveTargetReference(name, lg); + auto bt = name.Backtrace; + TargetOrString resolved = this->ResolveTargetReference(name.Value, lg); if (!resolved.Target) { return cmLinkItem(resolved.String, false, bt); diff --git a/Source/cmGeneratorTarget.h b/Source/cmGeneratorTarget.h index bb46211..0076085 100644 --- a/Source/cmGeneratorTarget.h +++ b/Source/cmGeneratorTarget.h @@ -409,10 +409,8 @@ public: TargetOrString ResolveTargetReference(std::string const& name, cmLocalGenerator const* lg) const; - cmLinkItem ResolveLinkItem(std::string const& name, - cmListFileBacktrace const& bt) const; - cmLinkItem ResolveLinkItem(std::string const& name, - cmListFileBacktrace const& bt, + cmLinkItem ResolveLinkItem(BT<std::string> const& name) const; + cmLinkItem ResolveLinkItem(BT<std::string> const& name, cmLocalGenerator const* lg) const; // Compute the set of languages compiled by the target. This is diff --git a/Source/cmGlobalCommonGenerator.cxx b/Source/cmGlobalCommonGenerator.cxx index a8e0f23..24c8944 100644 --- a/Source/cmGlobalCommonGenerator.cxx +++ b/Source/cmGlobalCommonGenerator.cxx @@ -117,7 +117,7 @@ std::string cmGlobalCommonGenerator::GetEditCacheCommand() const editCacheCommand = cmSystemTools::GetCMakeGUICommand(); } if (!editCacheCommand.empty()) { - cm->AddCacheEntry("CMAKE_EDIT_COMMAND", editCacheCommand.c_str(), + cm->AddCacheEntry("CMAKE_EDIT_COMMAND", editCacheCommand, "Path to cache edit program executable.", cmStateEnums::INTERNAL); } diff --git a/Source/cmGlobalGenerator.cxx b/Source/cmGlobalGenerator.cxx index 3561deb..fd1a197 100644 --- a/Source/cmGlobalGenerator.cxx +++ b/Source/cmGlobalGenerator.cxx @@ -1718,10 +1718,8 @@ void cmGlobalGenerator::FinalizeTargetCompileInfo() // Construct per-target generator information. for (const auto& mf : this->Makefiles) { - const cmStringRange noconfig_compile_definitions = + const cmBTStringRange noconfig_compile_definitions = mf->GetCompileDefinitionsEntries(); - const cmBacktraceRange noconfig_compile_definitions_bts = - mf->GetCompileDefinitionsBacktraces(); for (auto& target : mf->GetTargets()) { cmTarget* t = &target.second; @@ -1735,12 +1733,8 @@ void cmGlobalGenerator::FinalizeTargetCompileInfo() continue; } - { - auto btIt = noconfig_compile_definitions_bts.begin(); - auto it = noconfig_compile_definitions.begin(); - for (; it != noconfig_compile_definitions.end(); ++it, ++btIt) { - t->InsertCompileDefinition(*it, *btIt); - } + for (auto const& def : noconfig_compile_definitions) { + t->InsertCompileDefinition(def); } cmPolicies::PolicyStatus polSt = @@ -2191,9 +2185,8 @@ void cmGlobalGenerator::EnableLanguagesFromGenerator(cmGlobalGenerator* gen, this->TryCompileOuterMakefile = mf; cmProp make = gen->GetCMakeInstance()->GetCacheDefinition("CMAKE_MAKE_PROGRAM"); - this->GetCMakeInstance()->AddCacheEntry("CMAKE_MAKE_PROGRAM", cmToCStr(make), - "make program", - cmStateEnums::FILEPATH); + this->GetCMakeInstance()->AddCacheEntry( + "CMAKE_MAKE_PROGRAM", make, "make program", cmStateEnums::FILEPATH); // copy the enabled languages this->GetCMakeInstance()->GetState()->SetEnabledLanguages( gen->GetCMakeInstance()->GetState()->GetEnabledLanguages()); diff --git a/Source/cmGlobalVisualStudioVersionedGenerator.cxx b/Source/cmGlobalVisualStudioVersionedGenerator.cxx index d0ad53e..3ecf32e 100644 --- a/Source/cmGlobalVisualStudioVersionedGenerator.cxx +++ b/Source/cmGlobalVisualStudioVersionedGenerator.cxx @@ -467,9 +467,9 @@ bool cmGlobalVisualStudioVersionedGenerator::SetGeneratorInstance( // Save the selected instance persistently. std::string genInstance = mf->GetSafeDefinition("CMAKE_GENERATOR_INSTANCE"); if (vsInstance != genInstance) { - this->CMakeInstance->AddCacheEntry( - "CMAKE_GENERATOR_INSTANCE", vsInstance.c_str(), - "Generator instance identifier.", cmStateEnums::INTERNAL); + this->CMakeInstance->AddCacheEntry("CMAKE_GENERATOR_INSTANCE", vsInstance, + "Generator instance identifier.", + cmStateEnums::INTERNAL); } return true; diff --git a/Source/cmGlobalXCodeGenerator.cxx b/Source/cmGlobalXCodeGenerator.cxx index 763f12a..fa76b01 100644 --- a/Source/cmGlobalXCodeGenerator.cxx +++ b/Source/cmGlobalXCodeGenerator.cxx @@ -3241,9 +3241,8 @@ std::string cmGlobalXCodeGenerator::GetOrCreateId(const std::string& name, return *storedGUID; } - this->CMakeInstance->AddCacheEntry(guidStoreName, id.c_str(), - "Stored Xcode object GUID", - cmStateEnums::INTERNAL); + this->CMakeInstance->AddCacheEntry( + guidStoreName, id, "Stored Xcode object GUID", cmStateEnums::INTERNAL); return id; } diff --git a/Source/cmIncludeExternalMSProjectCommand.cxx b/Source/cmIncludeExternalMSProjectCommand.cxx index 5b532ce..c8b4a39 100644 --- a/Source/cmIncludeExternalMSProjectCommand.cxx +++ b/Source/cmIncludeExternalMSProjectCommand.cxx @@ -77,9 +77,8 @@ bool cmIncludeExternalMSProjectCommand(std::vector<std::string> const& args, if (!customGuid.empty()) { std::string guidVariable = utility_name + "_GUID_CMAKE"; - mf.GetCMakeInstance()->AddCacheEntry(guidVariable, customGuid.c_str(), - "Stored GUID", - cmStateEnums::INTERNAL); + mf.GetCMakeInstance()->AddCacheEntry( + guidVariable, customGuid, "Stored GUID", cmStateEnums::INTERNAL); } // Create a target instance for this utility. diff --git a/Source/cmLocalVisualStudio7Generator.cxx b/Source/cmLocalVisualStudio7Generator.cxx index 151470b..7b5fed6 100644 --- a/Source/cmLocalVisualStudio7Generator.cxx +++ b/Source/cmLocalVisualStudio7Generator.cxx @@ -566,7 +566,7 @@ public: } else { this->Stream << this->LG->EscapeForXML("\n"); } - std::string script = this->LG->ConstructScript(ccg); + std::string script = this->LG->ConstructScript(ccg, unmanaged); this->Stream << this->LG->EscapeForXML(script); } @@ -1779,7 +1779,7 @@ void cmLocalVisualStudio7Generator::WriteCustomRule( } std::string comment = this->ConstructComment(ccg); - std::string script = this->ConstructScript(ccg); + std::string script = this->ConstructScript(ccg, unmanaged); if (this->FortranProject) { cmSystemTools::ReplaceString(script, "$(Configuration)", config); } @@ -2142,7 +2142,7 @@ void cmLocalVisualStudio7Generator::ReadAndStoreExternalGUID( std::string guidStoreName = cmStrCat(name, "_GUID_CMAKE"); // save the GUID in the cache this->GlobalGenerator->GetCMakeInstance()->AddCacheEntry( - guidStoreName, parser.GUID.c_str(), "Stored GUID", cmStateEnums::INTERNAL); + guidStoreName, parser.GUID, "Stored GUID", cmStateEnums::INTERNAL); } std::string cmLocalVisualStudio7Generator::GetTargetDirectory( diff --git a/Source/cmLocalVisualStudioGenerator.cxx b/Source/cmLocalVisualStudioGenerator.cxx index 46f9d31..acddfe1 100644 --- a/Source/cmLocalVisualStudioGenerator.cxx +++ b/Source/cmLocalVisualStudioGenerator.cxx @@ -124,7 +124,8 @@ const char* cmLocalVisualStudioGenerator::GetReportErrorLabel() const } std::string cmLocalVisualStudioGenerator::ConstructScript( - cmCustomCommandGenerator const& ccg, const std::string& newline_text) + cmCustomCommandGenerator const& ccg, IsManaged isManaged, + const std::string& newline_text) { bool useLocal = this->CustomCommandUseLocal(); std::string workingDirectory = ccg.GetWorkingDirectory(); @@ -236,6 +237,14 @@ std::string cmLocalVisualStudioGenerator::ConstructScript( script += newline; script += "if %errorlevel% neq 0 goto "; script += this->GetReportErrorLabel(); + if (isManaged == managed) { + // These aren't generated by default for C# projects. + script += newline; + script += this->GetReportErrorLabel(); + script += newline; + script += "exit /b 0"; + script += newline; + } } return script; diff --git a/Source/cmLocalVisualStudioGenerator.h b/Source/cmLocalVisualStudioGenerator.h index 91fb6b0..0e7f63f 100644 --- a/Source/cmLocalVisualStudioGenerator.h +++ b/Source/cmLocalVisualStudioGenerator.h @@ -31,7 +31,13 @@ public: virtual ~cmLocalVisualStudioGenerator(); /** Construct a script from the given list of command lines. */ + enum IsManaged + { + unmanaged, + managed + }; std::string ConstructScript(cmCustomCommandGenerator const& ccg, + IsManaged isManaged, const std::string& newline = "\n"); /** Label to which to jump in a batch file after a failed step in a diff --git a/Source/cmMakefile.cxx b/Source/cmMakefile.cxx index 7abbd31..ef31d76 100644 --- a/Source/cmMakefile.cxx +++ b/Source/cmMakefile.cxx @@ -212,59 +212,31 @@ void cmMakefile::MaybeWarnCMP0074(std::string const& pkg) } } -cmStringRange cmMakefile::GetIncludeDirectoriesEntries() const +cmBTStringRange cmMakefile::GetIncludeDirectoriesEntries() const { return this->StateSnapshot.GetDirectory().GetIncludeDirectoriesEntries(); } -cmBacktraceRange cmMakefile::GetIncludeDirectoriesBacktraces() const -{ - return this->StateSnapshot.GetDirectory() - .GetIncludeDirectoriesEntryBacktraces(); -} - -cmStringRange cmMakefile::GetCompileOptionsEntries() const +cmBTStringRange cmMakefile::GetCompileOptionsEntries() const { return this->StateSnapshot.GetDirectory().GetCompileOptionsEntries(); } -cmBacktraceRange cmMakefile::GetCompileOptionsBacktraces() const -{ - return this->StateSnapshot.GetDirectory().GetCompileOptionsEntryBacktraces(); -} - -cmStringRange cmMakefile::GetCompileDefinitionsEntries() const +cmBTStringRange cmMakefile::GetCompileDefinitionsEntries() const { return this->StateSnapshot.GetDirectory().GetCompileDefinitionsEntries(); } -cmBacktraceRange cmMakefile::GetCompileDefinitionsBacktraces() const -{ - return this->StateSnapshot.GetDirectory() - .GetCompileDefinitionsEntryBacktraces(); -} - -cmStringRange cmMakefile::GetLinkOptionsEntries() const +cmBTStringRange cmMakefile::GetLinkOptionsEntries() const { return this->StateSnapshot.GetDirectory().GetLinkOptionsEntries(); } -cmBacktraceRange cmMakefile::GetLinkOptionsBacktraces() const -{ - return this->StateSnapshot.GetDirectory().GetLinkOptionsEntryBacktraces(); -} - -cmStringRange cmMakefile::GetLinkDirectoriesEntries() const +cmBTStringRange cmMakefile::GetLinkDirectoriesEntries() const { return this->StateSnapshot.GetDirectory().GetLinkDirectoriesEntries(); } -cmBacktraceRange cmMakefile::GetLinkDirectoriesBacktraces() const -{ - return this->StateSnapshot.GetDirectory() - .GetLinkDirectoriesEntryBacktraces(); -} - cmListFileBacktrace cmMakefile::GetBacktrace() const { return this->Backtrace; @@ -1386,10 +1358,10 @@ void cmMakefile::AddLinkDirectory(std::string const& directory, bool before) { if (before) { this->StateSnapshot.GetDirectory().PrependLinkDirectoriesEntry( - directory, this->Backtrace); + BT<std::string>(directory, this->Backtrace)); } else { this->StateSnapshot.GetDirectory().AppendLinkDirectoriesEntry( - directory, this->Backtrace); + BT<std::string>(directory, this->Backtrace)); } } @@ -1876,16 +1848,16 @@ void cmMakefile::AddIncludeDirectories(const std::vector<std::string>& incs, std::string entryString = cmJoin(incs, ";"); if (before) { this->StateSnapshot.GetDirectory().PrependIncludeDirectoriesEntry( - entryString, this->Backtrace); + BT<std::string>(entryString, this->Backtrace)); } else { this->StateSnapshot.GetDirectory().AppendIncludeDirectoriesEntry( - entryString, this->Backtrace); + BT<std::string>(entryString, this->Backtrace)); } // Property on each target: for (auto& target : this->Targets) { cmTarget& t = target.second; - t.InsertInclude(entryString, this->Backtrace, before); + t.InsertInclude(BT<std::string>(entryString, this->Backtrace), before); } } @@ -1955,7 +1927,7 @@ void cmMakefile::AddCacheDefinition(const std::string& name, const char* value, nvalue += files[cc]; } - this->GetCMakeInstance()->AddCacheEntry(name, nvalue.c_str(), doc, type); + this->GetCMakeInstance()->AddCacheEntry(name, nvalue, doc, type); nvalue = *this->GetState()->GetInitializedCacheValue(name); value = nvalue.c_str(); } @@ -3589,13 +3561,13 @@ int cmMakefile::TryCompile(const std::string& srcdir, // Tell the single-configuration generator which one to use. // Add this before the user-provided CMake arguments in case // one of the arguments is -DCMAKE_BUILD_TYPE=... - cm.AddCacheEntry("CMAKE_BUILD_TYPE", config->c_str(), - "Build configuration", cmStateEnums::STRING); + cm.AddCacheEntry("CMAKE_BUILD_TYPE", config, "Build configuration", + cmStateEnums::STRING); } } cmProp recursionDepth = this->GetDefinition("CMAKE_MAXIMUM_RECURSION_DEPTH"); if (recursionDepth) { - cm.AddCacheEntry("CMAKE_MAXIMUM_RECURSION_DEPTH", recursionDepth->c_str(), + cm.AddCacheEntry("CMAKE_MAXIMUM_RECURSION_DEPTH", recursionDepth, "Maximum recursion depth", cmStateEnums::STRING); } // if cmake args were provided then pass them in diff --git a/Source/cmMakefile.h b/Source/cmMakefile.h index fd9a679..bdcab3b 100644 --- a/Source/cmMakefile.h +++ b/Source/cmMakefile.h @@ -33,7 +33,6 @@ #include "cmSourceFileLocationKind.h" #include "cmStateSnapshot.h" #include "cmStateTypes.h" -#include "cmStringAlgorithms.h" // IWYU does not see that 'std::unordered_map<std::string, cmTarget>' // will not compile without the complete type. @@ -879,16 +878,11 @@ public: bool CheckCMP0037(std::string const& targetName, cmStateEnums::TargetType targetType) const; - cmStringRange GetIncludeDirectoriesEntries() const; - cmBacktraceRange GetIncludeDirectoriesBacktraces() const; - cmStringRange GetCompileOptionsEntries() const; - cmBacktraceRange GetCompileOptionsBacktraces() const; - cmStringRange GetCompileDefinitionsEntries() const; - cmBacktraceRange GetCompileDefinitionsBacktraces() const; - cmStringRange GetLinkOptionsEntries() const; - cmBacktraceRange GetLinkOptionsBacktraces() const; - cmStringRange GetLinkDirectoriesEntries() const; - cmBacktraceRange GetLinkDirectoriesBacktraces() const; + cmBTStringRange GetIncludeDirectoriesEntries() const; + cmBTStringRange GetCompileOptionsEntries() const; + cmBTStringRange GetCompileDefinitionsEntries() const; + cmBTStringRange GetLinkOptionsEntries() const; + cmBTStringRange GetLinkDirectoriesEntries() const; std::set<std::string> const& GetSystemIncludeDirectories() const { diff --git a/Source/cmMakefileTargetGenerator.cxx b/Source/cmMakefileTargetGenerator.cxx index c83a7ab..70b6d27 100644 --- a/Source/cmMakefileTargetGenerator.cxx +++ b/Source/cmMakefileTargetGenerator.cxx @@ -999,7 +999,25 @@ void cmMakefileTargetGenerator::WriteObjectRuleFiles( } if (cmNonempty(iwyu)) { run_iwyu += " --iwyu="; - run_iwyu += this->LocalGenerator->EscapeForShell(*iwyu); + + // Only add --driver-mode if it is not already specified, as adding + // it unconditionally might override a user-specified driver-mode + if (iwyu.Get()->find("--driver-mode=") == std::string::npos) { + cmProp p = this->Makefile->GetDefinition( + cmStrCat("CMAKE_", lang, "_INCLUDE_WHAT_YOU_USE_DRIVER_MODE")); + std::string driverMode; + + if (cmNonempty(p)) { + driverMode = *p; + } else { + driverMode = lang == "C" ? "gcc" : "g++"; + } + + run_iwyu += this->LocalGenerator->EscapeForShell( + cmStrCat(*iwyu, ";--driver-mode=", driverMode)); + } else { + run_iwyu += this->LocalGenerator->EscapeForShell(*iwyu); + } } if (cmNonempty(tidy)) { run_iwyu += " --tidy="; diff --git a/Source/cmNinjaTargetGenerator.cxx b/Source/cmNinjaTargetGenerator.cxx index 1b6b834..7cc1581 100644 --- a/Source/cmNinjaTargetGenerator.cxx +++ b/Source/cmNinjaTargetGenerator.cxx @@ -774,8 +774,11 @@ void cmNinjaTargetGenerator::WriteCompileRule(const std::string& lang, cmProp d = mf->GetDefinition("CMAKE_C_COMPILER"); const std::string cl = d ? *d : mf->GetSafeDefinition("CMAKE_CXX_COMPILER"); - cldeps = cmStrCat('"', cmSystemTools::GetCMClDepsCommand(), "\" ", lang, - ' ', vars.Source, " $DEP_FILE $out \"", + std::string cmcldepsPath; + cmSystemTools::GetShortPath(cmSystemTools::GetCMClDepsCommand(), + cmcldepsPath); + cldeps = cmStrCat(cmcldepsPath, ' ', lang, ' ', vars.Source, + " $DEP_FILE $out \"", mf->GetSafeDefinition("CMAKE_CL_SHOWINCLUDES_PREFIX"), "\" \"", cl, "\" "); } @@ -874,8 +877,26 @@ void cmNinjaTargetGenerator::WriteCompileRule(const std::string& lang, compilerLauncher.clear(); } if (cmNonempty(iwyu)) { - run_iwyu += cmStrCat(" --iwyu=", - this->GetLocalGenerator()->EscapeForShell(*iwyu)); + run_iwyu += " --iwyu="; + + // Only add --driver-mode if it is not already specified, as adding + // it unconditionally might override a user-specified driver-mode + if (iwyu.Get()->find("--driver-mode=") == std::string::npos) { + cmProp p = this->Makefile->GetDefinition( + cmStrCat("CMAKE_", lang, "_INCLUDE_WHAT_YOU_USE_DRIVER_MODE")); + std::string driverMode; + + if (cmNonempty(p)) { + driverMode = *p; + } else { + driverMode = lang == "C" ? "gcc" : "g++"; + } + + run_iwyu += this->LocalGenerator->EscapeForShell( + cmStrCat(*iwyu, ";--driver-mode=", driverMode)); + } else { + run_iwyu += this->LocalGenerator->EscapeForShell(*iwyu); + } } if (cmNonempty(tidy)) { run_iwyu += " --tidy="; diff --git a/Source/cmPolicies.h b/Source/cmPolicies.h index f7c0d25..a98e6c6 100644 --- a/Source/cmPolicies.h +++ b/Source/cmPolicies.h @@ -379,7 +379,10 @@ class cmMakefile; 3, 21, 0, cmPolicies::WARN) \ SELECT(POLICY, CMP0126, \ "set(CACHE) does not remove a normal variable of the same name.", 3, \ - 21, 0, cmPolicies::WARN) + 21, 0, cmPolicies::WARN) \ + SELECT(POLICY, CMP0127, \ + "cmake_dependent_option() supports full Condition Syntax.", 3, 22, \ + 0, cmPolicies::WARN) #define CM_SELECT_ID(F, A1, A2, A3, A4, A5, A6) F(A1) #define CM_FOR_EACH_POLICY_ID(POLICY) \ diff --git a/Source/cmQtAutoGenInitializer.cxx b/Source/cmQtAutoGenInitializer.cxx index 4dd78e5..fe038c7 100644 --- a/Source/cmQtAutoGenInitializer.cxx +++ b/Source/cmQtAutoGenInitializer.cxx @@ -24,6 +24,7 @@ #include "cmsys/SystemInformation.hxx" +#include "cmAlgorithms.h" #include "cmCustomCommand.h" #include "cmCustomCommandLines.h" #include "cmGeneratedFileStream.h" @@ -522,6 +523,8 @@ bool cmQtAutoGenInitializer::InitCustomTargets() // Filters cmExpandList(this->GenTarget->GetSafeProperty("AUTOMOC_MACRO_NAMES"), this->Moc.MacroNames); + this->Moc.MacroNames.erase(cmRemoveDuplicates(this->Moc.MacroNames), + this->Moc.MacroNames.end()); { auto filterList = cmExpandedList( this->GenTarget->GetSafeProperty("AUTOMOC_DEPEND_FILTERS")); diff --git a/Source/cmState.cxx b/Source/cmState.cxx index a045545..16718e8 100644 --- a/Source/cmState.cxx +++ b/Source/cmState.cxx @@ -206,7 +206,7 @@ bool cmState::GetCacheEntryPropertyAsBool(std::string const& key, return this->CacheManager->GetCacheEntryPropertyAsBool(key, propertyName); } -void cmState::AddCacheEntry(const std::string& key, const char* value, +void cmState::AddCacheEntry(const std::string& key, cmProp value, const char* helpString, cmStateEnums::CacheEntryType type) { @@ -277,15 +277,10 @@ cmStateSnapshot cmState::Reset() cmLinkedTree<cmStateDetail::BuildsystemDirectoryStateType>::iterator it = this->BuildsystemDirectory.Truncate(); it->IncludeDirectories.clear(); - it->IncludeDirectoryBacktraces.clear(); it->CompileDefinitions.clear(); - it->CompileDefinitionsBacktraces.clear(); it->CompileOptions.clear(); - it->CompileOptionsBacktraces.clear(); it->LinkOptions.clear(); - it->LinkOptionsBacktraces.clear(); it->LinkDirectories.clear(); - it->LinkDirectoriesBacktraces.clear(); it->DirectoryEnd = pos; it->NormalTargetNames.clear(); it->ImportedTargetNames.clear(); diff --git a/Source/cmState.h b/Source/cmState.h index 0fd28d0..390f6d6 100644 --- a/Source/cmState.h +++ b/Source/cmState.h @@ -219,6 +219,18 @@ public: private: friend class cmake; void AddCacheEntry(const std::string& key, const char* value, + const char* helpString, cmStateEnums::CacheEntryType type) + { + this->AddCacheEntry(key, + value ? cmProp(std::string(value)) : cmProp(nullptr), + helpString, type); + } + void AddCacheEntry(const std::string& key, const std::string& value, + const char* helpString, cmStateEnums::CacheEntryType type) + { + this->AddCacheEntry(key, cmProp(value), helpString, type); + } + void AddCacheEntry(const std::string& key, cmProp value, const char* helpString, cmStateEnums::CacheEntryType type); diff --git a/Source/cmStateDirectory.cxx b/Source/cmStateDirectory.cxx index ed5b5d8..8f83b02 100644 --- a/Source/cmStateDirectory.cxx +++ b/Source/cmStateDirectory.cxx @@ -19,6 +19,7 @@ #include "cmState.h" #include "cmStatePrivate.h" #include "cmStateTypes.h" +#include "cmStringAlgorithms.h" #include "cmSystemTools.h" static std::string const kBINARY_DIR = "BINARY_DIR"; @@ -63,7 +64,7 @@ cmStateDirectory::cmStateDirectory( } template <typename T, typename U> -cmStringRange GetPropertyContent(T const& content, U contentEndPosition) +cmBTStringRange GetPropertyContent(T const& content, U contentEndPosition) { auto end = content.begin() + contentEndPosition; @@ -73,88 +74,59 @@ cmStringRange GetPropertyContent(T const& content, U contentEndPosition) return cmMakeRange(rbegin.base(), end); } -template <typename T, typename U, typename V> -cmBacktraceRange GetPropertyBacktraces(T const& content, U const& backtraces, - V contentEndPosition) -{ - auto entryEnd = content.begin() + contentEndPosition; - - auto rbegin = cm::make_reverse_iterator(entryEnd); - rbegin = std::find(rbegin, content.rend(), cmPropertySentinal); - - auto it = backtraces.begin() + std::distance(content.begin(), rbegin.base()); - - auto end = backtraces.end(); - return cmMakeRange(it, end); -} - -template <typename T, typename U, typename V> -void AppendEntry(T& content, U& backtraces, V& endContentPosition, - const std::string& value, const cmListFileBacktrace& lfbt) +template <typename T, typename U> +void AppendEntry(T& content, U& endContentPosition, + const BT<std::string>& value) { - if (value.empty()) { + if (value.Value.empty()) { return; } assert(endContentPosition == content.size()); content.push_back(value); - backtraces.push_back(lfbt); endContentPosition = content.size(); } -template <typename T, typename U, typename V> -void SetContent(T& content, U& backtraces, V& endContentPosition, - const std::string& vec, const cmListFileBacktrace& lfbt) +template <typename T, typename U> +void SetContent(T& content, U& endContentPosition, const BT<std::string>& vec) { assert(endContentPosition == content.size()); content.resize(content.size() + 2); - backtraces.resize(backtraces.size() + 2); content.back() = vec; - backtraces.back() = lfbt; endContentPosition = content.size(); } -template <typename T, typename U, typename V> -void ClearContent(T& content, U& backtraces, V& endContentPosition) +template <typename T, typename U> +void ClearContent(T& content, U& endContentPosition) { assert(endContentPosition == content.size()); content.resize(content.size() + 1); - backtraces.resize(backtraces.size() + 1); endContentPosition = content.size(); } -cmStringRange cmStateDirectory::GetIncludeDirectoriesEntries() const +cmBTStringRange cmStateDirectory::GetIncludeDirectoriesEntries() const { return GetPropertyContent( this->DirectoryState->IncludeDirectories, this->Snapshot_.Position->IncludeDirectoryPosition); } -cmBacktraceRange cmStateDirectory::GetIncludeDirectoriesEntryBacktraces() const -{ - return GetPropertyBacktraces( - this->DirectoryState->IncludeDirectories, - this->DirectoryState->IncludeDirectoryBacktraces, - this->Snapshot_.Position->IncludeDirectoryPosition); -} - void cmStateDirectory::AppendIncludeDirectoriesEntry( - const std::string& vec, const cmListFileBacktrace& lfbt) + const BT<std::string>& vec) { AppendEntry(this->DirectoryState->IncludeDirectories, - this->DirectoryState->IncludeDirectoryBacktraces, - this->Snapshot_.Position->IncludeDirectoryPosition, vec, lfbt); + this->Snapshot_.Position->IncludeDirectoryPosition, vec); } void cmStateDirectory::PrependIncludeDirectoriesEntry( - const std::string& vec, const cmListFileBacktrace& lfbt) + const BT<std::string>& vec) { auto entryEnd = this->DirectoryState->IncludeDirectories.begin() + this->Snapshot_.Position->IncludeDirectoryPosition; @@ -164,167 +136,111 @@ void cmStateDirectory::PrependIncludeDirectoriesEntry( rbegin = std::find(rbegin, rend, cmPropertySentinal); auto entryIt = rbegin.base(); - auto entryBegin = this->DirectoryState->IncludeDirectories.begin(); - - auto btIt = this->DirectoryState->IncludeDirectoryBacktraces.begin() + - std::distance(entryBegin, entryIt); this->DirectoryState->IncludeDirectories.insert(entryIt, vec); - this->DirectoryState->IncludeDirectoryBacktraces.insert(btIt, lfbt); this->Snapshot_.Position->IncludeDirectoryPosition = this->DirectoryState->IncludeDirectories.size(); } -void cmStateDirectory::SetIncludeDirectories(const std::string& vec, - const cmListFileBacktrace& lfbt) +void cmStateDirectory::SetIncludeDirectories(const BT<std::string>& vec) { SetContent(this->DirectoryState->IncludeDirectories, - this->DirectoryState->IncludeDirectoryBacktraces, - this->Snapshot_.Position->IncludeDirectoryPosition, vec, lfbt); + this->Snapshot_.Position->IncludeDirectoryPosition, vec); } void cmStateDirectory::ClearIncludeDirectories() { ClearContent(this->DirectoryState->IncludeDirectories, - this->DirectoryState->IncludeDirectoryBacktraces, this->Snapshot_.Position->IncludeDirectoryPosition); } -cmStringRange cmStateDirectory::GetCompileDefinitionsEntries() const +cmBTStringRange cmStateDirectory::GetCompileDefinitionsEntries() const { return GetPropertyContent( this->DirectoryState->CompileDefinitions, this->Snapshot_.Position->CompileDefinitionsPosition); } -cmBacktraceRange cmStateDirectory::GetCompileDefinitionsEntryBacktraces() const -{ - return GetPropertyBacktraces( - this->DirectoryState->CompileDefinitions, - this->DirectoryState->CompileDefinitionsBacktraces, - this->Snapshot_.Position->CompileDefinitionsPosition); -} - void cmStateDirectory::AppendCompileDefinitionsEntry( - const std::string& vec, const cmListFileBacktrace& lfbt) + const BT<std::string>& vec) { AppendEntry(this->DirectoryState->CompileDefinitions, - this->DirectoryState->CompileDefinitionsBacktraces, - this->Snapshot_.Position->CompileDefinitionsPosition, vec, lfbt); + this->Snapshot_.Position->CompileDefinitionsPosition, vec); } -void cmStateDirectory::SetCompileDefinitions(const std::string& vec, - const cmListFileBacktrace& lfbt) +void cmStateDirectory::SetCompileDefinitions(const BT<std::string>& vec) { SetContent(this->DirectoryState->CompileDefinitions, - this->DirectoryState->CompileDefinitionsBacktraces, - this->Snapshot_.Position->CompileDefinitionsPosition, vec, lfbt); + this->Snapshot_.Position->CompileDefinitionsPosition, vec); } void cmStateDirectory::ClearCompileDefinitions() { ClearContent(this->DirectoryState->CompileDefinitions, - this->DirectoryState->CompileDefinitionsBacktraces, this->Snapshot_.Position->CompileDefinitionsPosition); } -cmStringRange cmStateDirectory::GetCompileOptionsEntries() const +cmBTStringRange cmStateDirectory::GetCompileOptionsEntries() const { return GetPropertyContent(this->DirectoryState->CompileOptions, this->Snapshot_.Position->CompileOptionsPosition); } -cmBacktraceRange cmStateDirectory::GetCompileOptionsEntryBacktraces() const -{ - return GetPropertyBacktraces( - this->DirectoryState->CompileOptions, - this->DirectoryState->CompileOptionsBacktraces, - this->Snapshot_.Position->CompileOptionsPosition); -} - -void cmStateDirectory::AppendCompileOptionsEntry( - const std::string& vec, const cmListFileBacktrace& lfbt) +void cmStateDirectory::AppendCompileOptionsEntry(const BT<std::string>& vec) { AppendEntry(this->DirectoryState->CompileOptions, - this->DirectoryState->CompileOptionsBacktraces, - this->Snapshot_.Position->CompileOptionsPosition, vec, lfbt); + this->Snapshot_.Position->CompileOptionsPosition, vec); } -void cmStateDirectory::SetCompileOptions(const std::string& vec, - const cmListFileBacktrace& lfbt) +void cmStateDirectory::SetCompileOptions(const BT<std::string>& vec) { SetContent(this->DirectoryState->CompileOptions, - this->DirectoryState->CompileOptionsBacktraces, - this->Snapshot_.Position->CompileOptionsPosition, vec, lfbt); + this->Snapshot_.Position->CompileOptionsPosition, vec); } void cmStateDirectory::ClearCompileOptions() { ClearContent(this->DirectoryState->CompileOptions, - this->DirectoryState->CompileOptionsBacktraces, this->Snapshot_.Position->CompileOptionsPosition); } -cmStringRange cmStateDirectory::GetLinkOptionsEntries() const +cmBTStringRange cmStateDirectory::GetLinkOptionsEntries() const { return GetPropertyContent(this->DirectoryState->LinkOptions, this->Snapshot_.Position->LinkOptionsPosition); } -cmBacktraceRange cmStateDirectory::GetLinkOptionsEntryBacktraces() const -{ - return GetPropertyBacktraces(this->DirectoryState->LinkOptions, - this->DirectoryState->LinkOptionsBacktraces, - this->Snapshot_.Position->LinkOptionsPosition); -} - -void cmStateDirectory::AppendLinkOptionsEntry(const std::string& vec, - const cmListFileBacktrace& lfbt) +void cmStateDirectory::AppendLinkOptionsEntry(const BT<std::string>& vec) { AppendEntry(this->DirectoryState->LinkOptions, - this->DirectoryState->LinkOptionsBacktraces, - this->Snapshot_.Position->LinkOptionsPosition, vec, lfbt); + this->Snapshot_.Position->LinkOptionsPosition, vec); } -void cmStateDirectory::SetLinkOptions(const std::string& vec, - const cmListFileBacktrace& lfbt) +void cmStateDirectory::SetLinkOptions(const BT<std::string>& vec) { SetContent(this->DirectoryState->LinkOptions, - this->DirectoryState->LinkOptionsBacktraces, - this->Snapshot_.Position->LinkOptionsPosition, vec, lfbt); + this->Snapshot_.Position->LinkOptionsPosition, vec); } void cmStateDirectory::ClearLinkOptions() { ClearContent(this->DirectoryState->LinkOptions, - this->DirectoryState->LinkOptionsBacktraces, this->Snapshot_.Position->LinkOptionsPosition); } -cmStringRange cmStateDirectory::GetLinkDirectoriesEntries() const +cmBTStringRange cmStateDirectory::GetLinkDirectoriesEntries() const { return GetPropertyContent(this->DirectoryState->LinkDirectories, this->Snapshot_.Position->LinkDirectoriesPosition); } -cmBacktraceRange cmStateDirectory::GetLinkDirectoriesEntryBacktraces() const -{ - return GetPropertyBacktraces( - this->DirectoryState->LinkDirectories, - this->DirectoryState->LinkDirectoriesBacktraces, - this->Snapshot_.Position->LinkDirectoriesPosition); -} - -void cmStateDirectory::AppendLinkDirectoriesEntry( - const std::string& vec, const cmListFileBacktrace& lfbt) +void cmStateDirectory::AppendLinkDirectoriesEntry(const BT<std::string>& vec) { AppendEntry(this->DirectoryState->LinkDirectories, - this->DirectoryState->LinkDirectoriesBacktraces, - this->Snapshot_.Position->LinkDirectoriesPosition, vec, lfbt); + this->Snapshot_.Position->LinkDirectoriesPosition, vec); } -void cmStateDirectory::PrependLinkDirectoriesEntry( - const std::string& vec, const cmListFileBacktrace& lfbt) +void cmStateDirectory::PrependLinkDirectoriesEntry(const BT<std::string>& vec) { auto entryEnd = this->DirectoryState->LinkDirectories.begin() + this->Snapshot_.Position->LinkDirectoriesPosition; @@ -334,30 +250,22 @@ void cmStateDirectory::PrependLinkDirectoriesEntry( rbegin = std::find(rbegin, rend, cmPropertySentinal); auto entryIt = rbegin.base(); - auto entryBegin = this->DirectoryState->LinkDirectories.begin(); - - auto btIt = this->DirectoryState->LinkDirectoriesBacktraces.begin() + - std::distance(entryBegin, entryIt); this->DirectoryState->LinkDirectories.insert(entryIt, vec); - this->DirectoryState->LinkDirectoriesBacktraces.insert(btIt, lfbt); this->Snapshot_.Position->LinkDirectoriesPosition = this->DirectoryState->LinkDirectories.size(); } -void cmStateDirectory::SetLinkDirectories(const std::string& vec, - const cmListFileBacktrace& lfbt) +void cmStateDirectory::SetLinkDirectories(const BT<std::string>& vec) { SetContent(this->DirectoryState->LinkDirectories, - this->DirectoryState->LinkDirectoriesBacktraces, - this->Snapshot_.Position->LinkDirectoriesPosition, vec, lfbt); + this->Snapshot_.Position->LinkDirectoriesPosition, vec); } void cmStateDirectory::ClearLinkDirectories() { ClearContent(this->DirectoryState->LinkDirectories, - this->DirectoryState->LinkDirectoriesBacktraces, this->Snapshot_.Position->LinkDirectoriesPosition); } @@ -370,7 +278,7 @@ void cmStateDirectory::StoreProperty(const std::string& prop, ValueType value, this->ClearIncludeDirectories(); return; } - this->SetIncludeDirectories(value, lfbt); + this->SetIncludeDirectories(BT<std::string>(value, lfbt)); return; } if (prop == "COMPILE_OPTIONS") { @@ -378,7 +286,7 @@ void cmStateDirectory::StoreProperty(const std::string& prop, ValueType value, this->ClearCompileOptions(); return; } - this->SetCompileOptions(value, lfbt); + this->SetCompileOptions(BT<std::string>(value, lfbt)); return; } if (prop == "COMPILE_DEFINITIONS") { @@ -386,7 +294,7 @@ void cmStateDirectory::StoreProperty(const std::string& prop, ValueType value, this->ClearCompileDefinitions(); return; } - this->SetCompileDefinitions(value, lfbt); + this->SetCompileDefinitions(BT<std::string>(value, lfbt)); return; } if (prop == "LINK_OPTIONS") { @@ -394,7 +302,7 @@ void cmStateDirectory::StoreProperty(const std::string& prop, ValueType value, this->ClearLinkOptions(); return; } - this->SetLinkOptions(value, lfbt); + this->SetLinkOptions(BT<std::string>(value, lfbt)); return; } if (prop == "LINK_DIRECTORIES") { @@ -402,7 +310,7 @@ void cmStateDirectory::StoreProperty(const std::string& prop, ValueType value, this->ClearLinkDirectories(); return; } - this->SetLinkDirectories(value, lfbt); + this->SetLinkDirectories(BT<std::string>(value, lfbt)); return; } @@ -425,23 +333,23 @@ void cmStateDirectory::AppendProperty(const std::string& prop, cmListFileBacktrace const& lfbt) { if (prop == "INCLUDE_DIRECTORIES") { - this->AppendIncludeDirectoriesEntry(value, lfbt); + this->AppendIncludeDirectoriesEntry(BT<std::string>(value, lfbt)); return; } if (prop == "COMPILE_OPTIONS") { - this->AppendCompileOptionsEntry(value, lfbt); + this->AppendCompileOptionsEntry(BT<std::string>(value, lfbt)); return; } if (prop == "COMPILE_DEFINITIONS") { - this->AppendCompileDefinitionsEntry(value, lfbt); + this->AppendCompileDefinitionsEntry(BT<std::string>(value, lfbt)); return; } if (prop == "LINK_OPTIONS") { - this->AppendLinkOptionsEntry(value, lfbt); + this->AppendLinkOptionsEntry(BT<std::string>(value, lfbt)); return; } if (prop == "LINK_DIRECTORIES") { - this->AppendLinkDirectoriesEntry(value, lfbt); + this->AppendLinkDirectoriesEntry(BT<std::string>(value, lfbt)); return; } diff --git a/Source/cmStateDirectory.h b/Source/cmStateDirectory.h index 65e2f30..fac5d58c 100644 --- a/Source/cmStateDirectory.h +++ b/Source/cmStateDirectory.h @@ -14,7 +14,6 @@ #include "cmProperty.h" #include "cmStatePrivate.h" #include "cmStateSnapshot.h" -#include "cmStringAlgorithms.h" class cmStateDirectory { @@ -28,47 +27,31 @@ public: std::string const& GetCurrentBinary() const; void SetCurrentBinary(std::string const& dir); - cmStringRange GetIncludeDirectoriesEntries() const; - cmBacktraceRange GetIncludeDirectoriesEntryBacktraces() const; - void AppendIncludeDirectoriesEntry(std::string const& vec, - cmListFileBacktrace const& lfbt); - void PrependIncludeDirectoriesEntry(std::string const& vec, - cmListFileBacktrace const& lfbt); - void SetIncludeDirectories(std::string const& vec, - cmListFileBacktrace const& lfbt); + cmBTStringRange GetIncludeDirectoriesEntries() const; + void AppendIncludeDirectoriesEntry(BT<std::string> const& vec); + void PrependIncludeDirectoriesEntry(BT<std::string> const& vec); + void SetIncludeDirectories(BT<std::string> const& vec); void ClearIncludeDirectories(); - cmStringRange GetCompileDefinitionsEntries() const; - cmBacktraceRange GetCompileDefinitionsEntryBacktraces() const; - void AppendCompileDefinitionsEntry(std::string const& vec, - cmListFileBacktrace const& lfbt); - void SetCompileDefinitions(std::string const& vec, - cmListFileBacktrace const& lfbt); + cmBTStringRange GetCompileDefinitionsEntries() const; + void AppendCompileDefinitionsEntry(BT<std::string> const& vec); + void SetCompileDefinitions(BT<std::string> const& vec); void ClearCompileDefinitions(); - cmStringRange GetCompileOptionsEntries() const; - cmBacktraceRange GetCompileOptionsEntryBacktraces() const; - void AppendCompileOptionsEntry(std::string const& vec, - cmListFileBacktrace const& lfbt); - void SetCompileOptions(std::string const& vec, - cmListFileBacktrace const& lfbt); + cmBTStringRange GetCompileOptionsEntries() const; + void AppendCompileOptionsEntry(BT<std::string> const& vec); + void SetCompileOptions(BT<std::string> const& vec); void ClearCompileOptions(); - cmStringRange GetLinkOptionsEntries() const; - cmBacktraceRange GetLinkOptionsEntryBacktraces() const; - void AppendLinkOptionsEntry(std::string const& vec, - cmListFileBacktrace const& lfbt); - void PrependLinkDirectoriesEntry(std::string const& vec, - cmListFileBacktrace const& lfbt); - void SetLinkOptions(std::string const& vec, cmListFileBacktrace const& lfbt); + cmBTStringRange GetLinkOptionsEntries() const; + void AppendLinkOptionsEntry(BT<std::string> const& vec); + void PrependLinkDirectoriesEntry(BT<std::string> const& vec); + void SetLinkOptions(BT<std::string> const& vec); void ClearLinkOptions(); - cmStringRange GetLinkDirectoriesEntries() const; - cmBacktraceRange GetLinkDirectoriesEntryBacktraces() const; - void AppendLinkDirectoriesEntry(std::string const& vec, - cmListFileBacktrace const& lfbt); - void SetLinkDirectories(std::string const& vec, - cmListFileBacktrace const& lfbt); + cmBTStringRange GetLinkDirectoriesEntries() const; + void AppendLinkDirectoriesEntry(BT<std::string> const& vec); + void SetLinkDirectories(BT<std::string> const& vecs); void ClearLinkDirectories(); void SetProperty(const std::string& prop, const char* value, diff --git a/Source/cmStatePrivate.h b/Source/cmStatePrivate.h index 6f475f2..fd46eed 100644 --- a/Source/cmStatePrivate.h +++ b/Source/cmStatePrivate.h @@ -67,20 +67,15 @@ struct cmStateDetail::BuildsystemDirectoryStateType std::string Location; std::string OutputLocation; - std::vector<std::string> IncludeDirectories; - std::vector<cmListFileBacktrace> IncludeDirectoryBacktraces; + std::vector<BT<std::string>> IncludeDirectories; - std::vector<std::string> CompileDefinitions; - std::vector<cmListFileBacktrace> CompileDefinitionsBacktraces; + std::vector<BT<std::string>> CompileDefinitions; - std::vector<std::string> CompileOptions; - std::vector<cmListFileBacktrace> CompileOptionsBacktraces; + std::vector<BT<std::string>> CompileOptions; - std::vector<std::string> LinkOptions; - std::vector<cmListFileBacktrace> LinkOptionsBacktraces; + std::vector<BT<std::string>> LinkOptions; - std::vector<std::string> LinkDirectories; - std::vector<cmListFileBacktrace> LinkDirectoriesBacktraces; + std::vector<BT<std::string>> LinkDirectories; std::vector<std::string> NormalTargetNames; std::vector<std::string> ImportedTargetNames; diff --git a/Source/cmStateSnapshot.cxx b/Source/cmStateSnapshot.cxx index 66cbcca..bd7db85 100644 --- a/Source/cmStateSnapshot.cxx +++ b/Source/cmStateSnapshot.cxx @@ -19,6 +19,10 @@ #include "cmSystemTools.h" #include "cmVersion.h" +#if defined(__CYGWIN__) +# include "cmStringAlgorithms.h" +#endif + cmStateSnapshot::cmStateSnapshot(cmState* state) : State(state) { @@ -259,12 +263,10 @@ bool cmStateSnapshot::RaiseScope(std::string const& var, const char* varDef) return true; } -template <typename T, typename U, typename V> +template <typename T, typename U> void InitializeContentFromParent(T& parentContent, T& thisContent, - U& parentBacktraces, U& thisBacktraces, - V& contentEndPosition) + U& contentEndPosition) { - auto parentBegin = parentContent.begin(); auto parentEnd = parentContent.end(); auto parentRbegin = cm::make_reverse_iterator(parentEnd); @@ -272,12 +274,7 @@ void InitializeContentFromParent(T& parentContent, T& thisContent, parentRbegin = std::find(parentRbegin, parentRend, cmPropertySentinal); auto parentIt = parentRbegin.base(); - thisContent = std::vector<std::string>(parentIt, parentEnd); - - auto btIt = parentBacktraces.begin() + std::distance(parentBegin, parentIt); - auto btEnd = parentBacktraces.end(); - - thisBacktraces = std::vector<cmListFileBacktrace>(btIt, btEnd); + thisContent = std::vector<BT<std::string>>(parentIt, parentEnd); contentEndPosition = thisContent.size(); } @@ -359,36 +356,26 @@ void cmStateSnapshot::InitializeFromParent() InitializeContentFromParent( parent->BuildSystemDirectory->IncludeDirectories, this->Position->BuildSystemDirectory->IncludeDirectories, - parent->BuildSystemDirectory->IncludeDirectoryBacktraces, - this->Position->BuildSystemDirectory->IncludeDirectoryBacktraces, this->Position->IncludeDirectoryPosition); InitializeContentFromParent( parent->BuildSystemDirectory->CompileDefinitions, this->Position->BuildSystemDirectory->CompileDefinitions, - parent->BuildSystemDirectory->CompileDefinitionsBacktraces, - this->Position->BuildSystemDirectory->CompileDefinitionsBacktraces, this->Position->CompileDefinitionsPosition); InitializeContentFromParent( parent->BuildSystemDirectory->CompileOptions, this->Position->BuildSystemDirectory->CompileOptions, - parent->BuildSystemDirectory->CompileOptionsBacktraces, - this->Position->BuildSystemDirectory->CompileOptionsBacktraces, this->Position->CompileOptionsPosition); InitializeContentFromParent( parent->BuildSystemDirectory->LinkOptions, this->Position->BuildSystemDirectory->LinkOptions, - parent->BuildSystemDirectory->LinkOptionsBacktraces, - this->Position->BuildSystemDirectory->LinkOptionsBacktraces, this->Position->LinkOptionsPosition); InitializeContentFromParent( parent->BuildSystemDirectory->LinkDirectories, this->Position->BuildSystemDirectory->LinkDirectories, - parent->BuildSystemDirectory->LinkDirectoriesBacktraces, - this->Position->BuildSystemDirectory->LinkDirectoriesBacktraces, this->Position->LinkDirectoriesPosition); cmProp include_regex = diff --git a/Source/cmTarget.cxx b/Source/cmTarget.cxx index 4f446d8..af64dce 100644 --- a/Source/cmTarget.cxx +++ b/Source/cmTarget.cxx @@ -83,15 +83,15 @@ cmProp cmTargetPropertyComputer::GetSources<cmTarget>( cmTarget const* tgt, cmMessenger* messenger, cmListFileBacktrace const& context) { - cmStringRange entries = tgt->GetSourceEntries(); + cmBTStringRange entries = tgt->GetSourceEntries(); if (entries.empty()) { return nullptr; } std::ostringstream ss; const char* sep = ""; - for (std::string const& entry : entries) { - std::vector<std::string> files = cmExpandedList(entry); + for (auto const& entry : entries) { + std::vector<std::string> files = cmExpandedList(entry.Value); for (std::string const& file : files) { if (cmHasLiteralPrefix(file, "$<TARGET_OBJECTS:") && file.back() == '>') { @@ -187,25 +187,16 @@ public: std::set<std::string> SystemIncludeDirectories; cmTarget::LinkLibraryVectorType OriginalLinkLibraries; std::map<std::string, BTs<std::string>> LanguageStandardProperties; - std::vector<std::string> IncludeDirectoriesEntries; - std::vector<cmListFileBacktrace> IncludeDirectoriesBacktraces; + std::vector<BT<std::string>> IncludeDirectoriesEntries; std::vector<std::string> InstallIncludeDirectoriesEntries; - std::vector<std::string> CompileOptionsEntries; - std::vector<cmListFileBacktrace> CompileOptionsBacktraces; - std::vector<std::string> CompileFeaturesEntries; - std::vector<cmListFileBacktrace> CompileFeaturesBacktraces; - std::vector<std::string> CompileDefinitionsEntries; - std::vector<cmListFileBacktrace> CompileDefinitionsBacktraces; - std::vector<std::string> PrecompileHeadersEntries; - std::vector<cmListFileBacktrace> PrecompileHeadersBacktraces; - std::vector<std::string> SourceEntries; - std::vector<cmListFileBacktrace> SourceBacktraces; - std::vector<std::string> LinkOptionsEntries; - std::vector<cmListFileBacktrace> LinkOptionsBacktraces; - std::vector<std::string> LinkDirectoriesEntries; - std::vector<cmListFileBacktrace> LinkDirectoriesBacktraces; - std::vector<std::string> LinkImplementationPropertyEntries; - std::vector<cmListFileBacktrace> LinkImplementationPropertyBacktraces; + std::vector<BT<std::string>> CompileOptionsEntries; + std::vector<BT<std::string>> CompileFeaturesEntries; + std::vector<BT<std::string>> CompileDefinitionsEntries; + std::vector<BT<std::string>> PrecompileHeadersEntries; + std::vector<BT<std::string>> SourceEntries; + std::vector<BT<std::string>> LinkOptionsEntries; + std::vector<BT<std::string>> LinkDirectoriesEntries; + std::vector<BT<std::string>> LinkImplementationPropertyEntries; std::vector<std::pair<cmTarget::TLLSignature, cmListFileContext>> TLLCommands; cmListFileBacktrace Backtrace; @@ -482,8 +473,6 @@ cmTarget::cmTarget(std::string const& name, cmStateEnums::TargetType type, // of the same directory property: cm::append(this->impl->IncludeDirectoriesEntries, this->impl->Makefile->GetIncludeDirectoriesEntries()); - cm::append(this->impl->IncludeDirectoriesBacktraces, - this->impl->Makefile->GetIncludeDirectoriesBacktraces()); { auto const& sysInc = this->impl->Makefile->GetSystemIncludeDirectories(); @@ -493,18 +482,12 @@ cmTarget::cmTarget(std::string const& name, cmStateEnums::TargetType type, cm::append(this->impl->CompileOptionsEntries, this->impl->Makefile->GetCompileOptionsEntries()); - cm::append(this->impl->CompileOptionsBacktraces, - this->impl->Makefile->GetCompileOptionsBacktraces()); cm::append(this->impl->LinkOptionsEntries, this->impl->Makefile->GetLinkOptionsEntries()); - cm::append(this->impl->LinkOptionsBacktraces, - this->impl->Makefile->GetLinkOptionsBacktraces()); cm::append(this->impl->LinkDirectoriesEntries, this->impl->Makefile->GetLinkDirectoriesEntries()); - cm::append(this->impl->LinkDirectoriesBacktraces, - this->impl->Makefile->GetLinkDirectoriesBacktraces()); } if (this->impl->TargetType == cmStateEnums::EXECUTABLE) { @@ -613,11 +596,9 @@ void cmTarget::SetLanguageStandardProperty(std::string const& lang, const std::string& feature) { cmListFileBacktrace featureBacktrace; - for (size_t i = 0; i < this->impl->CompileFeaturesEntries.size(); i++) { - if (this->impl->CompileFeaturesEntries[i] == feature) { - if (i < this->impl->CompileFeaturesBacktraces.size()) { - featureBacktrace = this->impl->CompileFeaturesBacktraces[i]; - } + for (auto const& entry : this->impl->CompileFeaturesEntries) { + if (entry.Value == feature) { + featureBacktrace = entry.Backtrace; break; } } @@ -729,8 +710,7 @@ void cmTarget::AddTracedSources(std::vector<std::string> const& srcs) { if (!srcs.empty()) { cmListFileBacktrace lfbt = this->impl->Makefile->GetBacktrace(); - this->impl->SourceEntries.push_back(cmJoin(srcs, ";")); - this->impl->SourceBacktraces.push_back(lfbt); + this->impl->SourceEntries.emplace_back(cmJoin(srcs, ";"), lfbt); } } @@ -754,8 +734,7 @@ void cmTarget::AddSources(std::vector<std::string> const& srcs) } if (!srcFiles.empty()) { cmListFileBacktrace lfbt = this->impl->Makefile->GetBacktrace(); - this->impl->SourceEntries.push_back(std::move(srcFiles)); - this->impl->SourceBacktraces.push_back(lfbt); + this->impl->SourceEntries.emplace_back(std::move(srcFiles), lfbt); } } @@ -843,9 +822,9 @@ public: { } - bool operator()(std::string const& entry) + bool operator()(BT<std::string> const& entry) { - std::vector<std::string> files = cmExpandedList(entry); + std::vector<std::string> files = cmExpandedList(entry.Value); std::vector<cmSourceFileLocation> locations; locations.reserve(files.size()); std::transform(files.begin(), files.end(), std::back_inserter(locations), @@ -866,11 +845,7 @@ cmSourceFile* cmTarget::AddSource(const std::string& src, bool before) cmListFileBacktrace lfbt = this->impl->Makefile->GetBacktrace(); this->impl->SourceEntries.insert(before ? this->impl->SourceEntries.begin() : this->impl->SourceEntries.end(), - src); - this->impl->SourceBacktraces.insert( - before ? this->impl->SourceBacktraces.begin() - : this->impl->SourceBacktraces.end(), - lfbt); + BT<std::string>(src, lfbt)); } if (cmGeneratorExpression::Find(src) != std::string::npos) { return nullptr; @@ -1087,96 +1062,51 @@ cmStringRange cmTarget::GetInstallIncludeDirectoriesEntries() const return cmMakeRange(this->impl->InstallIncludeDirectoriesEntries); } -cmStringRange cmTarget::GetIncludeDirectoriesEntries() const +cmBTStringRange cmTarget::GetIncludeDirectoriesEntries() const { return cmMakeRange(this->impl->IncludeDirectoriesEntries); } -cmBacktraceRange cmTarget::GetIncludeDirectoriesBacktraces() const -{ - return cmMakeRange(this->impl->IncludeDirectoriesBacktraces); -} - -cmStringRange cmTarget::GetCompileOptionsEntries() const +cmBTStringRange cmTarget::GetCompileOptionsEntries() const { return cmMakeRange(this->impl->CompileOptionsEntries); } -cmBacktraceRange cmTarget::GetCompileOptionsBacktraces() const -{ - return cmMakeRange(this->impl->CompileOptionsBacktraces); -} - -cmStringRange cmTarget::GetCompileFeaturesEntries() const +cmBTStringRange cmTarget::GetCompileFeaturesEntries() const { return cmMakeRange(this->impl->CompileFeaturesEntries); } -cmBacktraceRange cmTarget::GetCompileFeaturesBacktraces() const -{ - return cmMakeRange(this->impl->CompileFeaturesBacktraces); -} - -cmStringRange cmTarget::GetCompileDefinitionsEntries() const +cmBTStringRange cmTarget::GetCompileDefinitionsEntries() const { return cmMakeRange(this->impl->CompileDefinitionsEntries); } -cmBacktraceRange cmTarget::GetCompileDefinitionsBacktraces() const -{ - return cmMakeRange(this->impl->CompileDefinitionsBacktraces); -} - -cmStringRange cmTarget::GetPrecompileHeadersEntries() const +cmBTStringRange cmTarget::GetPrecompileHeadersEntries() const { return cmMakeRange(this->impl->PrecompileHeadersEntries); } -cmBacktraceRange cmTarget::GetPrecompileHeadersBacktraces() const -{ - return cmMakeRange(this->impl->PrecompileHeadersBacktraces); -} - -cmStringRange cmTarget::GetSourceEntries() const +cmBTStringRange cmTarget::GetSourceEntries() const { return cmMakeRange(this->impl->SourceEntries); } -cmBacktraceRange cmTarget::GetSourceBacktraces() const -{ - return cmMakeRange(this->impl->SourceBacktraces); -} - -cmStringRange cmTarget::GetLinkOptionsEntries() const +cmBTStringRange cmTarget::GetLinkOptionsEntries() const { return cmMakeRange(this->impl->LinkOptionsEntries); } -cmBacktraceRange cmTarget::GetLinkOptionsBacktraces() const -{ - return cmMakeRange(this->impl->LinkOptionsBacktraces); -} - -cmStringRange cmTarget::GetLinkDirectoriesEntries() const +cmBTStringRange cmTarget::GetLinkDirectoriesEntries() const { return cmMakeRange(this->impl->LinkDirectoriesEntries); } -cmBacktraceRange cmTarget::GetLinkDirectoriesBacktraces() const -{ - return cmMakeRange(this->impl->LinkDirectoriesBacktraces); -} - -cmStringRange cmTarget::GetLinkImplementationEntries() const +cmBTStringRange cmTarget::GetLinkImplementationEntries() const { return cmMakeRange(this->impl->LinkImplementationPropertyEntries); } -cmBacktraceRange cmTarget::GetLinkImplementationBacktraces() const -{ - return cmMakeRange(this->impl->LinkImplementationPropertyBacktraces); -} - namespace { #define MAKE_PROP(PROP) const std::string prop##PROP = #PROP MAKE_PROP(C_STANDARD); @@ -1270,75 +1200,57 @@ void cmTarget::StoreProperty(const std::string& prop, ValueType value) if (prop == propINCLUDE_DIRECTORIES) { this->impl->IncludeDirectoriesEntries.clear(); - this->impl->IncludeDirectoriesBacktraces.clear(); if (value) { - this->impl->IncludeDirectoriesEntries.emplace_back(value); cmListFileBacktrace lfbt = this->impl->Makefile->GetBacktrace(); - this->impl->IncludeDirectoriesBacktraces.push_back(lfbt); + this->impl->IncludeDirectoriesEntries.emplace_back(value, lfbt); } } else if (prop == propCOMPILE_OPTIONS) { this->impl->CompileOptionsEntries.clear(); - this->impl->CompileOptionsBacktraces.clear(); if (value) { - this->impl->CompileOptionsEntries.emplace_back(value); cmListFileBacktrace lfbt = this->impl->Makefile->GetBacktrace(); - this->impl->CompileOptionsBacktraces.push_back(lfbt); + this->impl->CompileOptionsEntries.emplace_back(value, lfbt); } } else if (prop == propCOMPILE_FEATURES) { this->impl->CompileFeaturesEntries.clear(); - this->impl->CompileFeaturesBacktraces.clear(); if (value) { - this->impl->CompileFeaturesEntries.emplace_back(value); cmListFileBacktrace lfbt = this->impl->Makefile->GetBacktrace(); - this->impl->CompileFeaturesBacktraces.push_back(lfbt); + this->impl->CompileFeaturesEntries.emplace_back(value, lfbt); } } else if (prop == propCOMPILE_DEFINITIONS) { this->impl->CompileDefinitionsEntries.clear(); - this->impl->CompileDefinitionsBacktraces.clear(); if (value) { - this->impl->CompileDefinitionsEntries.emplace_back(value); cmListFileBacktrace lfbt = this->impl->Makefile->GetBacktrace(); - this->impl->CompileDefinitionsBacktraces.push_back(lfbt); + this->impl->CompileDefinitionsEntries.emplace_back(value, lfbt); } } else if (prop == propLINK_OPTIONS) { this->impl->LinkOptionsEntries.clear(); - this->impl->LinkOptionsBacktraces.clear(); if (value) { - this->impl->LinkOptionsEntries.emplace_back(value); cmListFileBacktrace lfbt = this->impl->Makefile->GetBacktrace(); - this->impl->LinkOptionsBacktraces.push_back(lfbt); + this->impl->LinkOptionsEntries.emplace_back(value, lfbt); } } else if (prop == propLINK_DIRECTORIES) { this->impl->LinkDirectoriesEntries.clear(); - this->impl->LinkDirectoriesBacktraces.clear(); if (value) { - this->impl->LinkDirectoriesEntries.emplace_back(value); cmListFileBacktrace lfbt = this->impl->Makefile->GetBacktrace(); - this->impl->LinkDirectoriesBacktraces.push_back(lfbt); + this->impl->LinkDirectoriesEntries.emplace_back(value, lfbt); } } else if (prop == propPRECOMPILE_HEADERS) { this->impl->PrecompileHeadersEntries.clear(); - this->impl->PrecompileHeadersBacktraces.clear(); if (value) { - this->impl->PrecompileHeadersEntries.emplace_back(value); cmListFileBacktrace lfbt = this->impl->Makefile->GetBacktrace(); - this->impl->PrecompileHeadersBacktraces.push_back(lfbt); + this->impl->PrecompileHeadersEntries.emplace_back(value, lfbt); } } else if (prop == propLINK_LIBRARIES) { this->impl->LinkImplementationPropertyEntries.clear(); - this->impl->LinkImplementationPropertyBacktraces.clear(); if (value) { cmListFileBacktrace lfbt = this->impl->Makefile->GetBacktrace(); - this->impl->LinkImplementationPropertyEntries.emplace_back(value); - this->impl->LinkImplementationPropertyBacktraces.push_back(lfbt); + this->impl->LinkImplementationPropertyEntries.emplace_back(value, lfbt); } } else if (prop == propSOURCES) { this->impl->SourceEntries.clear(); - this->impl->SourceBacktraces.clear(); if (value) { cmListFileBacktrace lfbt = this->impl->Makefile->GetBacktrace(); - this->impl->SourceEntries.emplace_back(value); - this->impl->SourceBacktraces.push_back(lfbt); + this->impl->SourceEntries.emplace_back(value, lfbt); } } else if (prop == propIMPORTED_GLOBAL) { if (!cmIsOn(value)) { @@ -1443,39 +1355,33 @@ void cmTarget::AppendProperty(const std::string& prop, } if (prop == "INCLUDE_DIRECTORIES") { if (!value.empty()) { - this->impl->IncludeDirectoriesEntries.emplace_back(value); cmListFileBacktrace lfbt = this->impl->Makefile->GetBacktrace(); - this->impl->IncludeDirectoriesBacktraces.push_back(lfbt); + this->impl->IncludeDirectoriesEntries.emplace_back(value, lfbt); } } else if (prop == "COMPILE_OPTIONS") { if (!value.empty()) { - this->impl->CompileOptionsEntries.emplace_back(value); cmListFileBacktrace lfbt = this->impl->Makefile->GetBacktrace(); - this->impl->CompileOptionsBacktraces.push_back(lfbt); + this->impl->CompileOptionsEntries.emplace_back(value, lfbt); } } else if (prop == "COMPILE_FEATURES") { if (!value.empty()) { - this->impl->CompileFeaturesEntries.emplace_back(value); cmListFileBacktrace lfbt = this->impl->Makefile->GetBacktrace(); - this->impl->CompileFeaturesBacktraces.push_back(lfbt); + this->impl->CompileFeaturesEntries.emplace_back(value, lfbt); } } else if (prop == "COMPILE_DEFINITIONS") { if (!value.empty()) { - this->impl->CompileDefinitionsEntries.emplace_back(value); cmListFileBacktrace lfbt = this->impl->Makefile->GetBacktrace(); - this->impl->CompileDefinitionsBacktraces.push_back(lfbt); + this->impl->CompileDefinitionsEntries.emplace_back(value, lfbt); } } else if (prop == "LINK_OPTIONS") { if (!value.empty()) { - this->impl->LinkOptionsEntries.emplace_back(value); cmListFileBacktrace lfbt = this->impl->Makefile->GetBacktrace(); - this->impl->LinkOptionsBacktraces.push_back(lfbt); + this->impl->LinkOptionsEntries.emplace_back(value, lfbt); } } else if (prop == "LINK_DIRECTORIES") { if (!value.empty()) { - this->impl->LinkDirectoriesEntries.emplace_back(value); cmListFileBacktrace lfbt = this->impl->Makefile->GetBacktrace(); - this->impl->LinkDirectoriesBacktraces.push_back(lfbt); + this->impl->LinkDirectoriesEntries.emplace_back(value, lfbt); } } else if (prop == "PRECOMPILE_HEADERS") { if (this->GetProperty("PRECOMPILE_HEADERS_REUSE_FROM")) { @@ -1487,20 +1393,17 @@ void cmTarget::AppendProperty(const std::string& prop, return; } if (!value.empty()) { - this->impl->PrecompileHeadersEntries.emplace_back(value); cmListFileBacktrace lfbt = this->impl->Makefile->GetBacktrace(); - this->impl->PrecompileHeadersBacktraces.push_back(lfbt); + this->impl->PrecompileHeadersEntries.emplace_back(value, lfbt); } } else if (prop == "LINK_LIBRARIES") { if (!value.empty()) { cmListFileBacktrace lfbt = this->impl->Makefile->GetBacktrace(); - this->impl->LinkImplementationPropertyEntries.emplace_back(value); - this->impl->LinkImplementationPropertyBacktraces.push_back(lfbt); + this->impl->LinkImplementationPropertyEntries.emplace_back(value, lfbt); } } else if (prop == "SOURCES") { cmListFileBacktrace lfbt = this->impl->Makefile->GetBacktrace(); - this->impl->SourceEntries.emplace_back(value); - this->impl->SourceBacktraces.push_back(lfbt); + this->impl->SourceEntries.emplace_back(value, lfbt); } else if (cmHasLiteralPrefix(prop, "IMPORTED_LIBNAME")) { this->impl->Makefile->IssueMessage( MessageType::FATAL_ERROR, prop + " property may not be APPENDed."); @@ -1550,70 +1453,46 @@ void cmTarget::AppendBuildInterfaceIncludes() } } -void cmTarget::InsertInclude(std::string const& entry, - cmListFileBacktrace const& bt, bool before) +void cmTarget::InsertInclude(BT<std::string> const& entry, bool before) { auto position = before ? this->impl->IncludeDirectoriesEntries.begin() : this->impl->IncludeDirectoriesEntries.end(); - auto btPosition = before ? this->impl->IncludeDirectoriesBacktraces.begin() - : this->impl->IncludeDirectoriesBacktraces.end(); - this->impl->IncludeDirectoriesEntries.insert(position, entry); - this->impl->IncludeDirectoriesBacktraces.insert(btPosition, bt); } -void cmTarget::InsertCompileOption(std::string const& entry, - cmListFileBacktrace const& bt, bool before) +void cmTarget::InsertCompileOption(BT<std::string> const& entry, bool before) { auto position = before ? this->impl->CompileOptionsEntries.begin() : this->impl->CompileOptionsEntries.end(); - auto btPosition = before ? this->impl->CompileOptionsBacktraces.begin() - : this->impl->CompileOptionsBacktraces.end(); - this->impl->CompileOptionsEntries.insert(position, entry); - this->impl->CompileOptionsBacktraces.insert(btPosition, bt); } -void cmTarget::InsertCompileDefinition(std::string const& entry, - cmListFileBacktrace const& bt) +void cmTarget::InsertCompileDefinition(BT<std::string> const& entry) { this->impl->CompileDefinitionsEntries.push_back(entry); - this->impl->CompileDefinitionsBacktraces.push_back(bt); } -void cmTarget::InsertLinkOption(std::string const& entry, - cmListFileBacktrace const& bt, bool before) +void cmTarget::InsertLinkOption(BT<std::string> const& entry, bool before) { auto position = before ? this->impl->LinkOptionsEntries.begin() : this->impl->LinkOptionsEntries.end(); - auto btPosition = before ? this->impl->LinkOptionsBacktraces.begin() - : this->impl->LinkOptionsBacktraces.end(); - this->impl->LinkOptionsEntries.insert(position, entry); - this->impl->LinkOptionsBacktraces.insert(btPosition, bt); } -void cmTarget::InsertLinkDirectory(std::string const& entry, - cmListFileBacktrace const& bt, bool before) +void cmTarget::InsertLinkDirectory(BT<std::string> const& entry, bool before) { auto position = before ? this->impl->LinkDirectoriesEntries.begin() : this->impl->LinkDirectoriesEntries.end(); - auto btPosition = before ? this->impl->LinkDirectoriesBacktraces.begin() - : this->impl->LinkDirectoriesBacktraces.end(); - this->impl->LinkDirectoriesEntries.insert(position, entry); - this->impl->LinkDirectoriesBacktraces.insert(btPosition, bt); } -void cmTarget::InsertPrecompileHeader(std::string const& entry, - cmListFileBacktrace const& bt) +void cmTarget::InsertPrecompileHeader(BT<std::string> const& entry) { this->impl->PrecompileHeadersEntries.push_back(entry); - this->impl->PrecompileHeadersBacktraces.push_back(bt); } static void cmTargetCheckLINK_INTERFACE_LIBRARIES(const std::string& prop, diff --git a/Source/cmTarget.h b/Source/cmTarget.h index de0c4e3..eced1ae 100644 --- a/Source/cmTarget.h +++ b/Source/cmTarget.h @@ -217,18 +217,12 @@ public: //! Get a backtrace from the creation of the target. cmListFileBacktrace const& GetBacktrace() const; - void InsertInclude(std::string const& entry, cmListFileBacktrace const& bt, - bool before = false); - void InsertCompileOption(std::string const& entry, - cmListFileBacktrace const& bt, bool before = false); - void InsertCompileDefinition(std::string const& entry, - cmListFileBacktrace const& bt); - void InsertLinkOption(std::string const& entry, - cmListFileBacktrace const& bt, bool before = false); - void InsertLinkDirectory(std::string const& entry, - cmListFileBacktrace const& bt, bool before = false); - void InsertPrecompileHeader(std::string const& entry, - cmListFileBacktrace const& bt); + void InsertInclude(BT<std::string> const& entry, bool before = false); + void InsertCompileOption(BT<std::string> const& entry, bool before = false); + void InsertCompileDefinition(BT<std::string> const& entry); + void InsertLinkOption(BT<std::string> const& entry, bool before = false); + void InsertLinkDirectory(BT<std::string> const& entry, bool before = false); + void InsertPrecompileHeader(BT<std::string> const& entry); void AppendBuildInterfaceIncludes(); @@ -248,32 +242,23 @@ public: std::string const& value, const std::string& feature); - cmStringRange GetIncludeDirectoriesEntries() const; - cmBacktraceRange GetIncludeDirectoriesBacktraces() const; + cmBTStringRange GetIncludeDirectoriesEntries() const; - cmStringRange GetCompileOptionsEntries() const; - cmBacktraceRange GetCompileOptionsBacktraces() const; + cmBTStringRange GetCompileOptionsEntries() const; - cmStringRange GetCompileFeaturesEntries() const; - cmBacktraceRange GetCompileFeaturesBacktraces() const; + cmBTStringRange GetCompileFeaturesEntries() const; - cmStringRange GetCompileDefinitionsEntries() const; - cmBacktraceRange GetCompileDefinitionsBacktraces() const; + cmBTStringRange GetCompileDefinitionsEntries() const; - cmStringRange GetPrecompileHeadersEntries() const; - cmBacktraceRange GetPrecompileHeadersBacktraces() const; + cmBTStringRange GetPrecompileHeadersEntries() const; - cmStringRange GetSourceEntries() const; - cmBacktraceRange GetSourceBacktraces() const; + cmBTStringRange GetSourceEntries() const; - cmStringRange GetLinkOptionsEntries() const; - cmBacktraceRange GetLinkOptionsBacktraces() const; + cmBTStringRange GetLinkOptionsEntries() const; - cmStringRange GetLinkDirectoriesEntries() const; - cmBacktraceRange GetLinkDirectoriesBacktraces() const; + cmBTStringRange GetLinkDirectoriesEntries() const; - cmStringRange GetLinkImplementationEntries() const; - cmBacktraceRange GetLinkImplementationBacktraces() const; + cmBTStringRange GetLinkImplementationEntries() const; std::string ImportedGetFullPath(const std::string& config, cmStateEnums::ArtifactType artifact) const; diff --git a/Source/cmTargetCompileOptionsCommand.cxx b/Source/cmTargetCompileOptionsCommand.cxx index dee2c10..8ca3842 100644 --- a/Source/cmTargetCompileOptionsCommand.cxx +++ b/Source/cmTargetCompileOptionsCommand.cxx @@ -37,7 +37,8 @@ private: } cmListFileBacktrace lfbt = this->Makefile->GetBacktrace(); - tgt->InsertCompileOption(this->Join(content), lfbt, prepend); + tgt->InsertCompileOption(BT<std::string>(this->Join(content), lfbt), + prepend); return true; // Successfully handled. } diff --git a/Source/cmTargetIncludeDirectoriesCommand.cxx b/Source/cmTargetIncludeDirectoriesCommand.cxx index 3897499..f31501e 100644 --- a/Source/cmTargetIncludeDirectoriesCommand.cxx +++ b/Source/cmTargetIncludeDirectoriesCommand.cxx @@ -63,7 +63,7 @@ bool TargetIncludeDirectoriesImpl::HandleDirectContent( bool system) { cmListFileBacktrace lfbt = this->Makefile->GetBacktrace(); - tgt->InsertInclude(this->Join(content), lfbt, prepend); + tgt->InsertInclude(BT<std::string>(this->Join(content), lfbt), prepend); if (system) { std::string prefix = this->Makefile->GetCurrentSourceDirectory() + "/"; std::set<std::string> sdirs; diff --git a/Source/cmTargetLinkDirectoriesCommand.cxx b/Source/cmTargetLinkDirectoriesCommand.cxx index 0c68d60..3ba27a8 100644 --- a/Source/cmTargetLinkDirectoriesCommand.cxx +++ b/Source/cmTargetLinkDirectoriesCommand.cxx @@ -34,7 +34,8 @@ private: bool prepend, bool /*system*/) override { cmListFileBacktrace lfbt = this->Makefile->GetBacktrace(); - tgt->InsertLinkDirectory(this->Join(content), lfbt, prepend); + tgt->InsertLinkDirectory(BT<std::string>(this->Join(content), lfbt), + prepend); return true; // Successfully handled. } }; diff --git a/Source/cmTargetLinkOptionsCommand.cxx b/Source/cmTargetLinkOptionsCommand.cxx index df9416f..3ea2d71 100644 --- a/Source/cmTargetLinkOptionsCommand.cxx +++ b/Source/cmTargetLinkOptionsCommand.cxx @@ -30,7 +30,7 @@ private: bool prepend, bool /*system*/) override { cmListFileBacktrace lfbt = this->Makefile->GetBacktrace(); - tgt->InsertLinkOption(this->Join(content), lfbt, prepend); + tgt->InsertLinkOption(BT<std::string>(this->Join(content), lfbt), prepend); return true; // Successfully handled. } diff --git a/Source/cmVisualStudio10TargetGenerator.cxx b/Source/cmVisualStudio10TargetGenerator.cxx index 9407228..75fb05f 100644 --- a/Source/cmVisualStudio10TargetGenerator.cxx +++ b/Source/cmVisualStudio10TargetGenerator.cxx @@ -1465,7 +1465,10 @@ void cmVisualStudio10TargetGenerator::WriteCustomRule( cmCustomCommandGenerator ccg(command, c, lg, true); std::string comment = lg->ConstructComment(ccg); comment = cmVS10EscapeComment(comment); - std::string script = lg->ConstructScript(ccg); + cmLocalVisualStudioGenerator::IsManaged isManaged = (this->Managed) + ? cmLocalVisualStudioGenerator::managed + : cmLocalVisualStudioGenerator::unmanaged; + std::string script = lg->ConstructScript(ccg, isManaged); bool symbolic = false; // input files for custom command std::stringstream additional_inputs; @@ -1796,8 +1799,8 @@ void cmVisualStudio10TargetGenerator::WriteGroupSources( } } -void cmVisualStudio10TargetGenerator::WriteHeaderSource(Elem& e1, - cmSourceFile const* sf) +void cmVisualStudio10TargetGenerator::WriteHeaderSource( + Elem& e1, cmSourceFile const* sf, ConfigToSettings const& toolSettings) { std::string const& fileName = sf->GetFullPath(); Elem e2(e1, "ClInclude"); @@ -1808,6 +1811,7 @@ void cmVisualStudio10TargetGenerator::WriteHeaderSource(Elem& e1, e2.Element("DependentUpon", fileName.substr(0, fileName.find_last_of("."))); } + this->FinishWritingSource(e2, toolSettings); } void cmVisualStudio10TargetGenerator::ParseSettingsProperty( @@ -1864,8 +1868,8 @@ bool cmVisualStudio10TargetGenerator::PropertyIsSameInAllConfigs( return true; } -void cmVisualStudio10TargetGenerator::WriteExtraSource(Elem& e1, - cmSourceFile const* sf) +void cmVisualStudio10TargetGenerator::WriteExtraSource( + Elem& e1, cmSourceFile const* sf, ConfigToSettings& toolSettings) { bool toolHasSettings = false; const char* tool = "None"; @@ -1876,10 +1880,6 @@ void cmVisualStudio10TargetGenerator::WriteExtraSource(Elem& e1, std::string copyToOutDir; std::string includeInVsix; std::string ext = cmSystemTools::LowerCase(sf->GetExtension()); - ConfigToSettings toolSettings; - for (const auto& config : this->Configurations) { - toolSettings[config]; - } if (this->ProjectType == csproj && !this->InSourceBuild) { toolHasSettings = true; @@ -2047,10 +2047,6 @@ void cmVisualStudio10TargetGenerator::WriteExtraSource(Elem& e1, } } - if (cmProp p = sf->GetProperty("VS_SETTINGS")) { - ParseSettingsProperty(*p, toolSettings); - } - if (!toolSettings.empty()) { toolHasSettings = true; } @@ -2060,27 +2056,7 @@ void cmVisualStudio10TargetGenerator::WriteExtraSource(Elem& e1, if (toolHasSettings) { e2.SetHasElements(); - std::vector<std::string> writtenSettings; - for (const auto& configSettings : toolSettings) { - for (const auto& setting : configSettings.second) { - - if (std::find(writtenSettings.begin(), writtenSettings.end(), - setting.first) != writtenSettings.end()) { - continue; - } - - if (PropertyIsSameInAllConfigs(toolSettings, setting.first)) { - e2.Element(setting.first, setting.second); - writtenSettings.push_back(setting.first); - } else { - e2.WritePlatformConfigTag(setting.first, - "'$(Configuration)|$(Platform)'=='" + - configSettings.first + "|" + - this->Platform + "'", - setting.second); - } - } - } + this->FinishWritingSource(e2, toolSettings); if (!deployContent.empty()) { cmGeneratorExpression ge; @@ -2217,6 +2193,15 @@ void cmVisualStudio10TargetGenerator::WriteAllSources(Elem& e0) // Skip explicit reference to CMakeLists.txt source. continue; } + + ConfigToSettings toolSettings; + for (const auto& config : this->Configurations) { + toolSettings[config]; + } + if (cmProp p = si.Source->GetProperty("VS_SETTINGS")) { + ParseSettingsProperty(*p, toolSettings); + } + const char* tool = nullptr; switch (si.Kind) { case cmGeneratorTarget::SourceKindAppManifest: @@ -2244,10 +2229,10 @@ void cmVisualStudio10TargetGenerator::WriteAllSources(Elem& e0) } break; case cmGeneratorTarget::SourceKindExtra: - this->WriteExtraSource(e1, si.Source); + this->WriteExtraSource(e1, si.Source, toolSettings); break; case cmGeneratorTarget::SourceKindHeader: - this->WriteHeaderSource(e1, si.Source); + this->WriteHeaderSource(e1, si.Source, toolSettings); break; case cmGeneratorTarget::SourceKindIDL: tool = "Midl"; @@ -2357,6 +2342,8 @@ void cmVisualStudio10TargetGenerator::WriteAllSources(Elem& e0) if (!isCSharp && !exclude_configs.empty()) { this->WriteExcludeFromBuild(e2, exclude_configs); } + + this->FinishWritingSource(e2, toolSettings); } } @@ -2365,6 +2352,32 @@ void cmVisualStudio10TargetGenerator::WriteAllSources(Elem& e0) } } +void cmVisualStudio10TargetGenerator::FinishWritingSource( + Elem& e2, ConfigToSettings const& toolSettings) +{ + std::vector<std::string> writtenSettings; + for (const auto& configSettings : toolSettings) { + for (const auto& setting : configSettings.second) { + + if (std::find(writtenSettings.begin(), writtenSettings.end(), + setting.first) != writtenSettings.end()) { + continue; + } + + if (PropertyIsSameInAllConfigs(toolSettings, setting.first)) { + e2.Element(setting.first, setting.second); + writtenSettings.push_back(setting.first); + } else { + e2.WritePlatformConfigTag(setting.first, + "'$(Configuration)|$(Platform)'=='" + + configSettings.first + "|" + + this->Platform + "'", + setting.second); + } + } + } +} + void cmVisualStudio10TargetGenerator::OutputSourceSpecificFlags( Elem& e2, cmSourceFile const* source) { @@ -4205,7 +4218,10 @@ void cmVisualStudio10TargetGenerator::WriteEvent( comment += lg->ConstructComment(ccg); script += pre; pre = "\n"; - script += lg->ConstructScript(ccg); + cmLocalVisualStudioGenerator::IsManaged isManaged = (this->Managed) + ? cmLocalVisualStudioGenerator::managed + : cmLocalVisualStudioGenerator::unmanaged; + script += lg->ConstructScript(ccg, isManaged); stdPipesUTF8 = stdPipesUTF8 || cc.GetStdPipesUTF8(); } diff --git a/Source/cmVisualStudio10TargetGenerator.h b/Source/cmVisualStudio10TargetGenerator.h index 55c5444..a5ce5e5 100644 --- a/Source/cmVisualStudio10TargetGenerator.h +++ b/Source/cmVisualStudio10TargetGenerator.h @@ -58,6 +58,10 @@ private: struct Elem; struct OptionsHelper; + using ConfigToSettings = + std::unordered_map<std::string, + std::unordered_map<std::string, std::string>>; + std::string ConvertPath(std::string const& path, bool forceRelative); std::string CalcCondition(const std::string& config) const; void WriteProjectConfigurations(Elem& e0); @@ -66,12 +70,15 @@ private: void WriteCEDebugProjectConfigurationValues(Elem& e0); void WriteMSToolConfigurationValuesManaged(Elem& e1, std::string const& config); - void WriteHeaderSource(Elem& e1, cmSourceFile const* sf); - void WriteExtraSource(Elem& e1, cmSourceFile const* sf); + void WriteHeaderSource(Elem& e1, cmSourceFile const* sf, + ConfigToSettings const& toolSettings); + void WriteExtraSource(Elem& e1, cmSourceFile const* sf, + ConfigToSettings& toolSettings); void WriteNsightTegraConfigurationValues(Elem& e1, std::string const& config); void WriteAndroidConfigurationValues(Elem& e1, std::string const& config); void WriteSource(Elem& e2, cmSourceFile const* sf); + void FinishWritingSource(Elem& e2, ConfigToSettings const& toolSettings); void WriteExcludeFromBuild(Elem& e2, std::vector<size_t> const& exclude_configs); void WriteAllSources(Elem& e0); @@ -252,9 +259,6 @@ private: void ClassifyAllConfigSources(); void ClassifyAllConfigSource(cmGeneratorTarget::AllConfigSource const& acs); - using ConfigToSettings = - std::unordered_map<std::string, - std::unordered_map<std::string, std::string>>; std::unordered_map<std::string, ConfigToSettings> ParsedToolTargetSettings; bool PropertyIsSameInAllConfigs(const ConfigToSettings& toolSettings, const std::string& propName); diff --git a/Source/cmake.cxx b/Source/cmake.cxx index beb5d16..7cafaee 100644 --- a/Source/cmake.cxx +++ b/Source/cmake.cxx @@ -605,9 +605,8 @@ void cmake::ProcessCacheArg(const std::string& var, const std::string& value, } } - this->AddCacheEntry(var, value.c_str(), - "No help, variable specified on the command line.", - type); + this->AddCacheEntry( + var, value, "No help, variable specified on the command line.", type); if (this->WarnUnusedCli) { if (!haveValue || @@ -1517,16 +1516,15 @@ void cmake::SetDirectoriesFromFile(const std::string& arg) int cmake::AddCMakePaths() { // Save the value in the cache - this->AddCacheEntry("CMAKE_COMMAND", - cmSystemTools::GetCMakeCommand().c_str(), + this->AddCacheEntry("CMAKE_COMMAND", cmSystemTools::GetCMakeCommand(), "Path to CMake executable.", cmStateEnums::INTERNAL); #ifndef CMAKE_BOOTSTRAP - this->AddCacheEntry( - "CMAKE_CTEST_COMMAND", cmSystemTools::GetCTestCommand().c_str(), - "Path to ctest program executable.", cmStateEnums::INTERNAL); - this->AddCacheEntry( - "CMAKE_CPACK_COMMAND", cmSystemTools::GetCPackCommand().c_str(), - "Path to cpack program executable.", cmStateEnums::INTERNAL); + this->AddCacheEntry("CMAKE_CTEST_COMMAND", cmSystemTools::GetCTestCommand(), + "Path to ctest program executable.", + cmStateEnums::INTERNAL); + this->AddCacheEntry("CMAKE_CPACK_COMMAND", cmSystemTools::GetCPackCommand(), + "Path to cpack program executable.", + cmStateEnums::INTERNAL); #endif if (!cmSystemTools::FileExists( (cmSystemTools::GetCMakeRoot() + "/Modules/CMake.cmake"))) { @@ -1538,7 +1536,7 @@ int cmake::AddCMakePaths() cmSystemTools::GetCMakeRoot()); return 0; } - this->AddCacheEntry("CMAKE_ROOT", cmSystemTools::GetCMakeRoot().c_str(), + this->AddCacheEntry("CMAKE_ROOT", cmSystemTools::GetCMakeRoot(), "Path to CMake installation.", cmStateEnums::INTERNAL); return 1; @@ -1886,7 +1884,7 @@ int cmake::HandleDeleteCacheVariables(const std::string& var) this->LoadCache(); // restore the changed compilers for (SaveCacheEntry const& i : saved) { - this->AddCacheEntry(i.key, i.value.c_str(), i.help.c_str(), i.type); + this->AddCacheEntry(i.key, i.value, i.help.c_str(), i.type); } cmSystemTools::Message(warning.str()); // avoid reconfigure if there were errors @@ -1993,7 +1991,7 @@ int cmake::ActualConfigure() } if (!res) { this->AddCacheEntry( - "CMAKE_HOME_DIRECTORY", this->GetHomeDirectory().c_str(), + "CMAKE_HOME_DIRECTORY", this->GetHomeDirectory(), "Source directory with the top level CMakeLists.txt file for this " "project", cmStateEnums::INTERNAL); @@ -2038,19 +2036,17 @@ int cmake::ActualConfigure() } } if (!this->State->GetInitializedCacheValue("CMAKE_GENERATOR")) { - this->AddCacheEntry("CMAKE_GENERATOR", - this->GlobalGenerator->GetName().c_str(), + this->AddCacheEntry("CMAKE_GENERATOR", this->GlobalGenerator->GetName(), "Name of generator.", cmStateEnums::INTERNAL); - this->AddCacheEntry("CMAKE_EXTRA_GENERATOR", - this->GlobalGenerator->GetExtraGeneratorName().c_str(), - "Name of external makefile project generator.", - cmStateEnums::INTERNAL); + this->AddCacheEntry( + "CMAKE_EXTRA_GENERATOR", this->GlobalGenerator->GetExtraGeneratorName(), + "Name of external makefile project generator.", cmStateEnums::INTERNAL); if (!this->State->GetInitializedCacheValue("CMAKE_TOOLCHAIN_FILE")) { std::string envToolchain; if (cmSystemTools::GetEnv("CMAKE_TOOLCHAIN_FILE", envToolchain) && !envToolchain.empty()) { - this->AddCacheEntry("CMAKE_TOOLCHAIN_FILE", envToolchain.c_str(), + this->AddCacheEntry("CMAKE_TOOLCHAIN_FILE", envToolchain, "The CMake toolchain file", cmStateEnums::FILEPATH); } @@ -2069,9 +2065,9 @@ int cmake::ActualConfigure() return -2; } } else { - this->AddCacheEntry( - "CMAKE_GENERATOR_INSTANCE", this->GeneratorInstance.c_str(), - "Generator instance identifier.", cmStateEnums::INTERNAL); + this->AddCacheEntry("CMAKE_GENERATOR_INSTANCE", this->GeneratorInstance, + "Generator instance identifier.", + cmStateEnums::INTERNAL); } if (cmProp platformName = @@ -2087,8 +2083,7 @@ int cmake::ActualConfigure() return -2; } } else { - this->AddCacheEntry("CMAKE_GENERATOR_PLATFORM", - this->GeneratorPlatform.c_str(), + this->AddCacheEntry("CMAKE_GENERATOR_PLATFORM", this->GeneratorPlatform, "Name of generator platform.", cmStateEnums::INTERNAL); } @@ -2104,8 +2099,7 @@ int cmake::ActualConfigure() return -2; } } else { - this->AddCacheEntry("CMAKE_GENERATOR_TOOLSET", - this->GeneratorToolset.c_str(), + this->AddCacheEntry("CMAKE_GENERATOR_TOOLSET", this->GeneratorToolset, "Name of generator toolset.", cmStateEnums::INTERNAL); } @@ -2416,7 +2410,7 @@ int cmake::Generate() return 0; } -void cmake::AddCacheEntry(const std::string& key, const char* value, +void cmake::AddCacheEntry(const std::string& key, cmProp value, const char* helpString, int type) { this->State->AddCacheEntry(key, value, helpString, @@ -3540,7 +3534,7 @@ void cmake::SetSuppressDevWarnings(bool b) value = "FALSE"; } - this->AddCacheEntry("CMAKE_SUPPRESS_DEVELOPER_WARNINGS", value.c_str(), + this->AddCacheEntry("CMAKE_SUPPRESS_DEVELOPER_WARNINGS", value, "Suppress Warnings that are meant for" " the author of the CMakeLists.txt files.", cmStateEnums::INTERNAL); @@ -3564,7 +3558,7 @@ void cmake::SetSuppressDeprecatedWarnings(bool b) value = "TRUE"; } - this->AddCacheEntry("CMAKE_WARN_DEPRECATED", value.c_str(), + this->AddCacheEntry("CMAKE_WARN_DEPRECATED", value, "Whether to issue warnings for deprecated " "functionality.", cmStateEnums::INTERNAL); @@ -3588,7 +3582,7 @@ void cmake::SetDevWarningsAsErrors(bool b) value = "TRUE"; } - this->AddCacheEntry("CMAKE_SUPPRESS_DEVELOPER_ERRORS", value.c_str(), + this->AddCacheEntry("CMAKE_SUPPRESS_DEVELOPER_ERRORS", value, "Suppress errors that are meant for" " the author of the CMakeLists.txt files.", cmStateEnums::INTERNAL); @@ -3612,7 +3606,7 @@ void cmake::SetDeprecatedWarningsAsErrors(bool b) value = "FALSE"; } - this->AddCacheEntry("CMAKE_ERROR_DEPRECATED", value.c_str(), + this->AddCacheEntry("CMAKE_ERROR_DEPRECATED", value, "Whether to issue deprecation errors for macros" " and functions.", cmStateEnums::INTERNAL); diff --git a/Source/cmake.h b/Source/cmake.h index 32c7582..7408044 100644 --- a/Source/cmake.h +++ b/Source/cmake.h @@ -332,6 +332,18 @@ public: cmProp GetCacheDefinition(const std::string&) const; //! Add an entry into the cache void AddCacheEntry(const std::string& key, const char* value, + const char* helpString, int type) + { + this->AddCacheEntry(key, + value ? cmProp(std::string(value)) : cmProp(nullptr), + helpString, type); + } + void AddCacheEntry(const std::string& key, const std::string& value, + const char* helpString, int type) + { + this->AddCacheEntry(key, cmProp(value), helpString, type); + } + void AddCacheEntry(const std::string& key, cmProp value, const char* helpString, int type); bool DoWriteGlobVerifyTarget() const; diff --git a/Source/kwsys/Status.hxx.in b/Source/kwsys/Status.hxx.in index ed46d5c..16efaef 100644 --- a/Source/kwsys/Status.hxx.in +++ b/Source/kwsys/Status.hxx.in @@ -55,7 +55,10 @@ public: #endif /** Return true on "Success", false otherwise. */ - explicit operator bool() const { return this->Kind_ == Kind::Success; } + bool IsSuccess() const { return this->Kind_ == Kind::Success; } + + /** Return true on "Success", false otherwise. */ + explicit operator bool() const { return this->IsSuccess(); } /** Return the kind of status. */ Kind GetKind() const { return this->Kind_; } diff --git a/Source/kwsys/SystemInformation.cxx b/Source/kwsys/SystemInformation.cxx index 12f9139..f2bf85f 100644 --- a/Source/kwsys/SystemInformation.cxx +++ b/Source/kwsys/SystemInformation.cxx @@ -1356,14 +1356,12 @@ std::string SymbolProperties::Demangle(const char* symbol) const std::string result = safes(symbol); # if defined(KWSYS_SYSTEMINFORMATION_HAS_CPP_DEMANGLE) int status = 0; - size_t bufferLen = 1024; - char* buffer = (char*)malloc(1024); char* demangledSymbol = - abi::__cxa_demangle(symbol, buffer, &bufferLen, &status); + abi::__cxa_demangle(symbol, nullptr, nullptr, &status); if (!status) { result = demangledSymbol; } - free(buffer); + free(demangledSymbol); # else (void)symbol; # endif diff --git a/Source/kwsys/SystemTools.cxx b/Source/kwsys/SystemTools.cxx index 7c26974..930d84c 100644 --- a/Source/kwsys/SystemTools.cxx +++ b/Source/kwsys/SystemTools.cxx @@ -14,6 +14,10 @@ # endif #endif +#if defined(_WIN32) && !defined(_WIN32_WINNT) +# define _WIN32_WINNT _WIN32_WINNT_VISTA +#endif + #include "kwsysPrivate.h" #include KWSYS_HEADER(RegularExpression.hxx) #include KWSYS_HEADER(SystemTools.hxx) @@ -2419,7 +2423,7 @@ Status SystemTools::CopyFileAlways(std::string const& source, if (SystemTools::FileIsDirectory(source)) { status = SystemTools::MakeDirectory(destination); - if (!status) { + if (!status.IsSuccess()) { return status; } } else { @@ -2444,17 +2448,17 @@ Status SystemTools::CopyFileAlways(std::string const& source, // Create destination directory if (!destination_dir.empty()) { status = SystemTools::MakeDirectory(destination_dir); - if (!status) { + if (!status.IsSuccess()) { return status; } } status = SystemTools::CloneFileContent(source, real_destination); // if cloning did not succeed, fall back to blockwise copy - if (!status) { + if (!status.IsSuccess()) { status = SystemTools::CopyFileContentBlockwise(source, real_destination); } - if (!status) { + if (!status.IsSuccess()) { return status; } } @@ -2484,11 +2488,11 @@ Status SystemTools::CopyADirectory(std::string const& source, Status status; Directory dir; status = dir.Load(source); - if (!status) { + if (!status.IsSuccess()) { return status; } status = SystemTools::MakeDirectory(destination); - if (!status) { + if (!status.IsSuccess()) { return status; } @@ -2503,12 +2507,12 @@ Status SystemTools::CopyADirectory(std::string const& source, fullDestPath += "/"; fullDestPath += dir.GetFile(static_cast<unsigned long>(fileNum)); status = SystemTools::CopyADirectory(fullPath, fullDestPath, always); - if (!status) { + if (!status.IsSuccess()) { return status; } } else { status = SystemTools::CopyAFile(fullPath, destination, always); - if (!status) { + if (!status.IsSuccess()) { return status; } } @@ -2660,7 +2664,7 @@ Status SystemTools::RemoveADirectory(std::string const& source) Status status; Directory dir; status = dir.Load(source); - if (!status) { + if (!status.IsSuccess()) { return status; } @@ -2674,12 +2678,12 @@ Status SystemTools::RemoveADirectory(std::string const& source) if (SystemTools::FileIsDirectory(fullPath) && !SystemTools::FileIsSymlink(fullPath)) { status = SystemTools::RemoveADirectory(fullPath); - if (!status) { + if (!status.IsSuccess()) { return status; } } else { status = SystemTools::RemoveFile(fullPath); - if (!status) { + if (!status.IsSuccess()) { return status; } } @@ -3143,7 +3147,7 @@ Status SystemTools::ReadSymlink(std::string const& newName, status = Status::Windows_GetLastError(); } CloseHandle(hFile); - if (!status) { + if (!status.IsSuccess()) { return status; } PREPARSE_DATA_BUFFER data = diff --git a/Source/kwsys/testDirectory.cxx b/Source/kwsys/testDirectory.cxx index 06a22dc..a847462 100644 --- a/Source/kwsys/testDirectory.cxx +++ b/Source/kwsys/testDirectory.cxx @@ -122,7 +122,7 @@ int _copyDirectoryTest() } const Status copysuccess = SystemTools::CopyADirectory(source, destination); const bool destinationexists = SystemTools::PathExists(destination); - if (copysuccess) { + if (copysuccess.IsSuccess()) { std::cerr << "CopyADirectory should have returned false" << std::endl; SystemTools::RemoveADirectory(destination); return 3; diff --git a/Source/kwsys/testStatus.cxx b/Source/kwsys/testStatus.cxx index f85ef42..0a767a8 100644 --- a/Source/kwsys/testStatus.cxx +++ b/Source/kwsys/testStatus.cxx @@ -31,6 +31,10 @@ int testStatus(int, char* []) std::cerr << "Status Success constructor does not produce Success\n"; res = false; } + if (!status.IsSuccess()) { + std::cerr << "Status Success gives false IsSuccess\n"; + res = false; + } if (!status) { std::cerr << "Status Success kind is not true\n"; res = false; @@ -55,6 +59,10 @@ int testStatus(int, char* []) std::cerr << "Status POSIX constructor does not produce POSIX\n"; res = false; } + if (status.IsSuccess()) { + std::cerr << "Status POSIX gives true IsSuccess\n"; + res = false; + } if (status) { std::cerr << "Status POSIX kind is not false\n"; res = false; @@ -87,6 +95,10 @@ int testStatus(int, char* []) std::cerr << "Status Windows constructor does not produce Windows\n"; res = false; } + if (status.IsSuccess()) { + std::cerr << "Status Windows gives true IsSuccess\n"; + res = false; + } if (status) { std::cerr << "Status Windows kind is not false\n"; res = false; diff --git a/Source/kwsys/testSystemTools.cxx b/Source/kwsys/testSystemTools.cxx index 39a19cb..6ccc7a7 100644 --- a/Source/kwsys/testSystemTools.cxx +++ b/Source/kwsys/testSystemTools.cxx @@ -436,7 +436,7 @@ static bool CheckFileOperations() if (symlinkStatus.GetWindows() != ERROR_PRIVILEGE_NOT_HELD) #endif { - if (!symlinkStatus) { + if (!symlinkStatus.IsSuccess()) { std::cerr << "CreateSymlink for: " << testBadSymlink << " -> " << testBadSymlinkTgt << " failed: " << symlinkStatus.GetString() << std::endl; diff --git a/Tests/RunCMake/CMakeDependentOption/Regex-stdout.txt b/Tests/RunCMake/CMakeDependentOption/Parentheses-CMP0127-NEW-stdout.txt index 15b56a1..15b56a1 100644 --- a/Tests/RunCMake/CMakeDependentOption/Regex-stdout.txt +++ b/Tests/RunCMake/CMakeDependentOption/Parentheses-CMP0127-NEW-stdout.txt diff --git a/Tests/RunCMake/CMakeDependentOption/Parentheses-CMP0127-NEW.cmake b/Tests/RunCMake/CMakeDependentOption/Parentheses-CMP0127-NEW.cmake new file mode 100644 index 0000000..5a2b018 --- /dev/null +++ b/Tests/RunCMake/CMakeDependentOption/Parentheses-CMP0127-NEW.cmake @@ -0,0 +1,9 @@ +include(CMakeDependentOption) + +cmake_policy(SET CMP0127 NEW) + +set(A 1) +set(B 1) +set(C 0) +cmake_dependent_option(USE_FOO "Use Foo" ON "A AND (B OR C)" OFF) +message(STATUS "USE_FOO='${USE_FOO}'") diff --git a/Tests/RunCMake/CMakeDependentOption/Parentheses-CMP0127-WARN-stderr.txt b/Tests/RunCMake/CMakeDependentOption/Parentheses-CMP0127-WARN-stderr.txt new file mode 100644 index 0000000..b16e84b --- /dev/null +++ b/Tests/RunCMake/CMakeDependentOption/Parentheses-CMP0127-WARN-stderr.txt @@ -0,0 +1,9 @@ +^CMake Warning \(dev\) at [^ +]*/Modules/CMakeDependentOption.cmake:[0-9]+ \(message\): + Policy CMP0127 is not set: cmake_dependent_option\(\) supports full Condition + Syntax. Run "cmake --help-policy CMP0127" for policy details. Use the + cmake_policy command to set the policy and suppress this warning. +Call Stack \(most recent call first\): + [^ +]*/Tests/RunCMake/CMakeDependentOption/Parentheses-CMP0127-WARN.cmake:[0-9]+ \(cmake_dependent_option\) +This warning is for project developers. Use -Wno-dev to suppress it.$ diff --git a/Tests/RunCMake/CMakeDependentOption/Parentheses-CMP0127-WARN-stdout.txt b/Tests/RunCMake/CMakeDependentOption/Parentheses-CMP0127-WARN-stdout.txt new file mode 100644 index 0000000..d89dbd3 --- /dev/null +++ b/Tests/RunCMake/CMakeDependentOption/Parentheses-CMP0127-WARN-stdout.txt @@ -0,0 +1,2 @@ +-- USE_FOO='OFF' +-- USE_BAR='ON' diff --git a/Tests/RunCMake/CMakeDependentOption/Parentheses-CMP0127-WARN.cmake b/Tests/RunCMake/CMakeDependentOption/Parentheses-CMP0127-WARN.cmake new file mode 100644 index 0000000..00d440d --- /dev/null +++ b/Tests/RunCMake/CMakeDependentOption/Parentheses-CMP0127-WARN.cmake @@ -0,0 +1,9 @@ +include(CMakeDependentOption) + +set(A 1) +set(B 1) +set(C 0) +cmake_dependent_option(USE_FOO "Use Foo" ON "A AND (B OR C)" OFF) +message(STATUS "USE_FOO='${USE_FOO}'") +cmake_dependent_option(USE_BAR "Use Bar" ON "A;B" OFF) +message(STATUS "USE_BAR='${USE_BAR}'") diff --git a/Tests/RunCMake/CMakeDependentOption/Regex-CMP0127-NEW-stdout.txt b/Tests/RunCMake/CMakeDependentOption/Regex-CMP0127-NEW-stdout.txt new file mode 100644 index 0000000..15b56a1 --- /dev/null +++ b/Tests/RunCMake/CMakeDependentOption/Regex-CMP0127-NEW-stdout.txt @@ -0,0 +1 @@ +-- USE_FOO='ON' diff --git a/Tests/RunCMake/CMakeDependentOption/Regex-CMP0127-NEW.cmake b/Tests/RunCMake/CMakeDependentOption/Regex-CMP0127-NEW.cmake new file mode 100644 index 0000000..e92c1e6 --- /dev/null +++ b/Tests/RunCMake/CMakeDependentOption/Regex-CMP0127-NEW.cmake @@ -0,0 +1,7 @@ +include(CMakeDependentOption) + +cmake_policy(SET CMP0127 NEW) + +set(FOO "lower") +cmake_dependent_option(USE_FOO "Use Foo" ON "FOO MATCHES \"(UPPER|lower)\"" OFF) +message(STATUS "USE_FOO='${USE_FOO}'") diff --git a/Tests/RunCMake/CMakeDependentOption/Regex-CMP0127-OLD-stdout.txt b/Tests/RunCMake/CMakeDependentOption/Regex-CMP0127-OLD-stdout.txt new file mode 100644 index 0000000..15b56a1 --- /dev/null +++ b/Tests/RunCMake/CMakeDependentOption/Regex-CMP0127-OLD-stdout.txt @@ -0,0 +1 @@ +-- USE_FOO='ON' diff --git a/Tests/RunCMake/CMakeDependentOption/Regex.cmake b/Tests/RunCMake/CMakeDependentOption/Regex-CMP0127-OLD.cmake index 8342a01..81df003 100644 --- a/Tests/RunCMake/CMakeDependentOption/Regex.cmake +++ b/Tests/RunCMake/CMakeDependentOption/Regex-CMP0127-OLD.cmake @@ -1,5 +1,7 @@ include(CMakeDependentOption) +cmake_policy(SET CMP0127 OLD) + set(FOO "lower") cmake_dependent_option(USE_FOO "Use Foo" ON "FOO MATCHES (UPPER|lower)" OFF) message(STATUS "USE_FOO='${USE_FOO}'") diff --git a/Tests/RunCMake/CMakeDependentOption/RunCMakeTest.cmake b/Tests/RunCMake/CMakeDependentOption/RunCMakeTest.cmake index e1045f2..61e046f 100644 --- a/Tests/RunCMake/CMakeDependentOption/RunCMakeTest.cmake +++ b/Tests/RunCMake/CMakeDependentOption/RunCMakeTest.cmake @@ -1,3 +1,6 @@ include(RunCMake) -run_cmake_script(Regex) +run_cmake_script(Regex-CMP0127-NEW) +run_cmake_script(Regex-CMP0127-OLD) +run_cmake_script(Parentheses-CMP0127-NEW) +run_cmake_script(Parentheses-CMP0127-WARN) diff --git a/Tests/RunCMake/CMakeDependentOption/Simple-CMP0127-OLD-stdout.txt b/Tests/RunCMake/CMakeDependentOption/Simple-CMP0127-OLD-stdout.txt new file mode 100644 index 0000000..15b56a1 --- /dev/null +++ b/Tests/RunCMake/CMakeDependentOption/Simple-CMP0127-OLD-stdout.txt @@ -0,0 +1 @@ +-- USE_FOO='ON' diff --git a/Tests/RunCMake/CMakeDependentOption/Simple-CMP0127-OLD.cmake b/Tests/RunCMake/CMakeDependentOption/Simple-CMP0127-OLD.cmake new file mode 100644 index 0000000..6db2128 --- /dev/null +++ b/Tests/RunCMake/CMakeDependentOption/Simple-CMP0127-OLD.cmake @@ -0,0 +1,6 @@ +include(CMakeDependentOption) + +set(A1 1) +set(bb 1) +cmake_dependent_option(USE_FOO "Use Foo" ON "A1;bb" OFF) +message(STATUS "USE_FOO='${USE_FOO}'") diff --git a/Tests/RunCMake/VS10Project/VsSettings-check.cmake b/Tests/RunCMake/VS10Project/VsSettings-check.cmake index 0f8b26c..13cc8e2 100644 --- a/Tests/RunCMake/VS10Project/VsSettings-check.cmake +++ b/Tests/RunCMake/VS10Project/VsSettings-check.cmake @@ -4,20 +4,29 @@ macro(ensure_props_set projectFile) return() endif() - set(SettingFound FALSE) + set(Setting1Found FALSE) + set(Setting2Found FALSE) file(STRINGS "${projectFile}" lines) foreach(line IN LISTS lines) if(line MATCHES "<SourceProperty1.*Debug.*>SourceProperty1Value</SourceProperty1>") message("SourceProperty1 setting found") - set(SettingFound TRUE) + set(Setting1Found TRUE) + endif() + if(line MATCHES "<SourceProperty2.*Debug.*>SourceProperty2Value</SourceProperty2>") + message("SourceProperty2 setting found") + set(Setting2Found TRUE) endif() endforeach() - if (NOT SettingFound) + if (NOT Setting1Found) set(RunCMake_TEST_FAILED "SourceProperty1 setting was not found") return() endif() + if (NOT Setting2Found) + set(RunCMake_TEST_FAILED "SourceProperty2 setting was not found") + return() + endif() endmacro() ensure_props_set("${RunCMake_TEST_BINARY_DIR}/foo.vcxproj") diff --git a/Tests/RunCMake/VS10Project/VsSettings.cmake b/Tests/RunCMake/VS10Project/VsSettings.cmake index a4b321b..3a046f1 100644 --- a/Tests/RunCMake/VS10Project/VsSettings.cmake +++ b/Tests/RunCMake/VS10Project/VsSettings.cmake @@ -3,3 +3,5 @@ enable_language(CXX) add_library(foo foo.cpp shader.hlsl) set_property(SOURCE shader.hlsl PROPERTY VS_SETTINGS "$<$<CONFIG:DEBUG>:SourceProperty1=SourceProperty1Value>") +set_property(SOURCE foo.cpp PROPERTY VS_SETTINGS + "$<$<CONFIG:DEBUG>:SourceProperty2=SourceProperty2Value>") diff --git a/Tests/RunCMake/ctest_memcheck/ExpectedOutputs-check.cmake b/Tests/RunCMake/ctest_memcheck/ExpectedOutputs-check.cmake new file mode 100644 index 0000000..9d2a059 --- /dev/null +++ b/Tests/RunCMake/ctest_memcheck/ExpectedOutputs-check.cmake @@ -0,0 +1,10 @@ +function (find_xml_file name) + file(GLOB test_xml_file "${RunCMake_TEST_BINARY_DIR}/Testing/*/${name}.xml") + if (NOT test_xml_file) + message(FATAL_ERROR + "${name}.xml not created.") + endif () +endfunction () + +find_xml_file(DynamicAnalysis) +find_xml_file(DynamicAnalysis-Test) diff --git a/Tests/RunCMake/ctest_memcheck/ExpectedOutputs-stderr.txt b/Tests/RunCMake/ctest_memcheck/ExpectedOutputs-stderr.txt new file mode 100644 index 0000000..e1fc77a --- /dev/null +++ b/Tests/RunCMake/ctest_memcheck/ExpectedOutputs-stderr.txt @@ -0,0 +1 @@ +Cannot find memory tester output file: .*/Tests/RunCMake/ctest_memcheck/ExpectedOutputs-build/Testing/Temporary/MemoryChecker.1.log\.\* diff --git a/Tests/RunCMake/ctest_memcheck/ExpectedOutputs-stdout.txt b/Tests/RunCMake/ctest_memcheck/ExpectedOutputs-stdout.txt new file mode 100644 index 0000000..b3473bf --- /dev/null +++ b/Tests/RunCMake/ctest_memcheck/ExpectedOutputs-stdout.txt @@ -0,0 +1,2 @@ +Memory checking results: +left shift of negative value -256 - 1 diff --git a/Tests/RunCMake/ctest_memcheck/RunCMakeTest.cmake b/Tests/RunCMake/ctest_memcheck/RunCMakeTest.cmake index 6e0a91c..cb8f696 100644 --- a/Tests/RunCMake/ctest_memcheck/RunCMakeTest.cmake +++ b/Tests/RunCMake/ctest_memcheck/RunCMakeTest.cmake @@ -95,6 +95,19 @@ unset(CMAKELISTS_EXTRA_CODE) unset(CTEST_EXTRA_CODE) #----------------------------------------------------------------------------- +# add output test +set(CTEST_EXTRA_CODE +"set(CTEST_MEMORYCHECK_SANITIZER_OPTIONS \"simulate_sanitizer=1\") +") +set(CMAKELISTS_EXTRA_CODE +"add_test(NAME TestSan COMMAND \"\${CMAKE_COMMAND}\" +-P \"${RunCMake_SOURCE_DIR}/testUndefinedBehaviorSanitizer.cmake\") +") +run_mc_test(ExpectedOutputs "" -DMEMCHECK_TYPE=UndefinedBehaviorSanitizer) +unset(CMAKELISTS_EXTRA_CODE) +unset(CTEST_EXTRA_CODE) + +#----------------------------------------------------------------------------- set(CTEST_EXTRA_CODE "string(REPLACE \" \" \"\\\\ \" PRE_POST_COMMAND \"\${CTEST_MEMORYCHECK_COMMAND}\") set(CTEST_CUSTOM_PRE_MEMCHECK \"\${PRE_POST_COMMAND} pre command\") diff --git a/Utilities/IWYU/mapping.imp b/Utilities/IWYU/mapping.imp index f1bdcc4..8c55c85 100644 --- a/Utilities/IWYU/mapping.imp +++ b/Utilities/IWYU/mapping.imp @@ -101,6 +101,7 @@ # Wrappers for 3rd-party libraries { include: [ "@<.*curl/curlver.h>", private, "<cm3p/curl/curl.h>", public ] }, + { include: [ "@<.*json/config.h>", private, "<cm3p/json/value.h>", public ] }, { include: [ "@<.*json/forwards.h>", private, "<cm3p/json/value.h>", public ] }, { include: [ "@<.*uv/.+\\.h>", private, "<cm3p/uv.h>", public ] }, { include: [ "@<.*expat_external.h>", private, "<cm3p/expat.h>", public ] }, diff --git a/Utilities/Scripts/update-jsoncpp.bash b/Utilities/Scripts/update-jsoncpp.bash index f8fe544..5ed00e7 100755 --- a/Utilities/Scripts/update-jsoncpp.bash +++ b/Utilities/Scripts/update-jsoncpp.bash @@ -8,7 +8,7 @@ readonly name="jsoncpp" readonly ownership="JsonCpp Upstream <kwrobot@kitware.com>" readonly subtree="Utilities/cmjsoncpp" readonly repo="https://github.com/open-source-parsers/jsoncpp.git" -readonly tag="1.8.2" +readonly tag="1.9.4" readonly shortlog=false readonly paths=" LICENSE diff --git a/Utilities/cmjsoncpp/include/json/allocator.h b/Utilities/cmjsoncpp/include/json/allocator.h index 9562436..a685da1 100644 --- a/Utilities/cmjsoncpp/include/json/allocator.h +++ b/Utilities/cmjsoncpp/include/json/allocator.h @@ -3,8 +3,8 @@ // recognized in your jurisdiction. // See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE -#ifndef CPPTL_JSON_ALLOCATOR_H_INCLUDED -#define CPPTL_JSON_ALLOCATOR_H_INCLUDED +#ifndef JSON_ALLOCATOR_H_INCLUDED +#define JSON_ALLOCATOR_H_INCLUDED #include <cstring> #include <memory> @@ -14,89 +14,80 @@ #endif namespace Json { -template<typename T> -class SecureAllocator { - public: - // Type definitions - using value_type = T; - using pointer = T*; - using const_pointer = const T*; - using reference = T&; - using const_reference = const T&; - using size_type = std::size_t; - using difference_type = std::ptrdiff_t; - - /** - * Allocate memory for N items using the standard allocator. - */ - pointer allocate(size_type n) { - // allocate using "global operator new" - return static_cast<pointer>(::operator new(n * sizeof(T))); - } - - /** - * Release memory which was allocated for N items at pointer P. - * - * The memory block is filled with zeroes before being released. - * The pointer argument is tagged as "volatile" to prevent the - * compiler optimizing out this critical step. - */ - void deallocate(volatile pointer p, size_type n) { - std::memset(p, 0, n * sizeof(T)); - // free using "global operator delete" - ::operator delete(p); - } - - /** - * Construct an item in-place at pointer P. - */ - template<typename... Args> - void construct(pointer p, Args&&... args) { - // construct using "placement new" and "perfect forwarding" - ::new (static_cast<void*>(p)) T(std::forward<Args>(args)...); - } - - size_type max_size() const { - return size_t(-1) / sizeof(T); - } - - pointer address( reference x ) const { - return std::addressof(x); - } - - const_pointer address( const_reference x ) const { - return std::addressof(x); - } - - /** - * Destroy an item in-place at pointer P. - */ - void destroy(pointer p) { - // destroy using "explicit destructor" - p->~T(); - } - - // Boilerplate - SecureAllocator() {} - template<typename U> SecureAllocator(const SecureAllocator<U>&) {} - template<typename U> struct rebind { using other = SecureAllocator<U>; }; +template <typename T> class SecureAllocator { +public: + // Type definitions + using value_type = T; + using pointer = T*; + using const_pointer = const T*; + using reference = T&; + using const_reference = const T&; + using size_type = std::size_t; + using difference_type = std::ptrdiff_t; + + /** + * Allocate memory for N items using the standard allocator. + */ + pointer allocate(size_type n) { + // allocate using "global operator new" + return static_cast<pointer>(::operator new(n * sizeof(T))); + } + + /** + * Release memory which was allocated for N items at pointer P. + * + * The memory block is filled with zeroes before being released. + * The pointer argument is tagged as "volatile" to prevent the + * compiler optimizing out this critical step. + */ + void deallocate(volatile pointer p, size_type n) { + std::memset(p, 0, n * sizeof(T)); + // free using "global operator delete" + ::operator delete(p); + } + + /** + * Construct an item in-place at pointer P. + */ + template <typename... Args> void construct(pointer p, Args&&... args) { + // construct using "placement new" and "perfect forwarding" + ::new (static_cast<void*>(p)) T(std::forward<Args>(args)...); + } + + size_type max_size() const { return size_t(-1) / sizeof(T); } + + pointer address(reference x) const { return std::addressof(x); } + + const_pointer address(const_reference x) const { return std::addressof(x); } + + /** + * Destroy an item in-place at pointer P. + */ + void destroy(pointer p) { + // destroy using "explicit destructor" + p->~T(); + } + + // Boilerplate + SecureAllocator() {} + template <typename U> SecureAllocator(const SecureAllocator<U>&) {} + template <typename U> struct rebind { using other = SecureAllocator<U>; }; }; - -template<typename T, typename U> +template <typename T, typename U> bool operator==(const SecureAllocator<T>&, const SecureAllocator<U>&) { - return true; + return true; } -template<typename T, typename U> +template <typename T, typename U> bool operator!=(const SecureAllocator<T>&, const SecureAllocator<U>&) { - return false; + return false; } -} //namespace Json +} // namespace Json #if !defined(__SUNPRO_CC) #pragma pack(pop) #endif -#endif // CPPTL_JSON_ALLOCATOR_H_INCLUDED +#endif // JSON_ALLOCATOR_H_INCLUDED diff --git a/Utilities/cmjsoncpp/include/json/assertions.h b/Utilities/cmjsoncpp/include/json/assertions.h index f64913f..415c463 100644 --- a/Utilities/cmjsoncpp/include/json/assertions.h +++ b/Utilities/cmjsoncpp/include/json/assertions.h @@ -3,14 +3,14 @@ // recognized in your jurisdiction. // See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE -#ifndef CPPTL_JSON_ASSERTIONS_H_INCLUDED -#define CPPTL_JSON_ASSERTIONS_H_INCLUDED +#ifndef JSON_ASSERTIONS_H_INCLUDED +#define JSON_ASSERTIONS_H_INCLUDED #if !defined(JSON_IS_AMALGAMATION) #include "config.h" #endif // if !defined(JSON_IS_AMALGAMATION) -#include <stdlib.h> +#include <cstdlib> #include <sstream> /** It should not be possible for a maliciously designed file to @@ -20,35 +20,42 @@ #if JSON_USE_EXCEPTION // @todo <= add detail about condition in exception -# define JSON_ASSERT(condition) \ - {if (!(condition)) {Json::throwLogicError( "assert json failed" );}} - -# define JSON_FAIL_MESSAGE(message) \ - { \ - JSONCPP_OSTRINGSTREAM oss; oss << message; \ +#define JSON_ASSERT(condition) \ + do { \ + if (!(condition)) { \ + Json::throwLogicError("assert json failed"); \ + } \ + } while (0) + +#define JSON_FAIL_MESSAGE(message) \ + do { \ + OStringStream oss; \ + oss << message; \ Json::throwLogicError(oss.str()); \ abort(); \ - } + } while (0) #else // JSON_USE_EXCEPTION -# define JSON_ASSERT(condition) assert(condition) +#define JSON_ASSERT(condition) assert(condition) // The call to assert() will show the failure message in debug builds. In // release builds we abort, for a core-dump or debugger. -# define JSON_FAIL_MESSAGE(message) \ +#define JSON_FAIL_MESSAGE(message) \ { \ - JSONCPP_OSTRINGSTREAM oss; oss << message; \ + OStringStream oss; \ + oss << message; \ assert(false && oss.str().c_str()); \ abort(); \ } - #endif #define JSON_ASSERT_MESSAGE(condition, message) \ - if (!(condition)) { \ - JSON_FAIL_MESSAGE(message); \ - } + do { \ + if (!(condition)) { \ + JSON_FAIL_MESSAGE(message); \ + } \ + } while (0) -#endif // CPPTL_JSON_ASSERTIONS_H_INCLUDED +#endif // JSON_ASSERTIONS_H_INCLUDED diff --git a/Utilities/cmjsoncpp/include/json/config.h b/Utilities/cmjsoncpp/include/json/config.h index 2cc8462..f03b746 100644 --- a/Utilities/cmjsoncpp/include/json/config.h +++ b/Utilities/cmjsoncpp/include/json/config.h @@ -6,26 +6,18 @@ #ifndef JSON_CONFIG_H_INCLUDED #define JSON_CONFIG_H_INCLUDED -// Include KWSys Large File Support configuration. -#include <cmsys/Configure.h> - -#include <stddef.h> -#include <string> //typedef String -#include <stdint.h> //typedef int64_t, uint64_t - #if defined(_MSC_VER) # pragma warning(push,1) #endif -/// If defined, indicates that json library is embedded in CppTL library. -//# define JSON_IN_CPPTL 1 - -/// If defined, indicates that json may leverage CppTL library -//# define JSON_USE_CPPTL 1 -/// If defined, indicates that cpptl vector based map should be used instead of -/// std::map -/// as Value container. -//# define JSON_USE_CPPTL_SMALLMAP 1 +#include <cstddef> +#include <cstdint> +#include <istream> +#include <memory> +#include <ostream> +#include <sstream> +#include <string> +#include <type_traits> // If non-zero, the library uses exceptions to report bad input instead of C // assertion macros. The default is to use exceptions. @@ -33,108 +25,73 @@ #define JSON_USE_EXCEPTION 1 #endif -/// If defined, indicates that the source file is amalgated +// Temporary, tracked for removal with issue #982. +#ifndef JSON_USE_NULLREF +#define JSON_USE_NULLREF 1 +#endif + +/// If defined, indicates that the source file is amalgamated /// to prevent private header inclusion. -/// Remarks: it is automatically defined in the generated amalgated header. +/// Remarks: it is automatically defined in the generated amalgamated header. // #define JSON_IS_AMALGAMATION -#ifdef JSON_IN_CPPTL -#include <cpptl/config.h> -#ifndef JSON_USE_CPPTL -#define JSON_USE_CPPTL 1 -#endif -#endif - -#ifdef JSON_IN_CPPTL -#define JSON_API CPPTL_API -#elif defined(JSON_DLL_BUILD) +// Export macros for DLL visibility +#if defined(JSON_DLL_BUILD) #if defined(_MSC_VER) || defined(__MINGW32__) #define JSON_API __declspec(dllexport) #define JSONCPP_DISABLE_DLL_INTERFACE_WARNING +#elif defined(__GNUC__) || defined(__clang__) +#define JSON_API __attribute__((visibility("default"))) #endif // if defined(_MSC_VER) + #elif defined(JSON_DLL) #if defined(_MSC_VER) || defined(__MINGW32__) #define JSON_API __declspec(dllimport) #define JSONCPP_DISABLE_DLL_INTERFACE_WARNING #endif // if defined(_MSC_VER) -#endif // ifdef JSON_IN_CPPTL +#endif // ifdef JSON_DLL_BUILD + #if !defined(JSON_API) #define JSON_API #endif -// If JSON_NO_INT64 is defined, then Json only support C++ "int" type for -// integer -// Storages, and 64 bits integer support is disabled. -// #define JSON_NO_INT64 1 +#if defined(_MSC_VER) && _MSC_VER < 1800 +#error \ + "ERROR: Visual Studio 12 (2013) with _MSC_VER=1800 is the oldest supported compiler with sufficient C++11 capabilities" +#endif -#if defined(_MSC_VER) // MSVC -# if _MSC_VER <= 1200 // MSVC 6 - // Microsoft Visual Studio 6 only support conversion from __int64 to double - // (no conversion from unsigned __int64). -# define JSON_USE_INT64_DOUBLE_CONVERSION 1 - // Disable warning 4786 for VS6 caused by STL (identifier was truncated to '255' - // characters in the debug information) - // All projects I've ever seen with VS6 were using this globally (not bothering - // with pragma push/pop). -# pragma warning(disable : 4786) -# endif // MSVC 6 - -#endif // defined(_MSC_VER) - -// In c++11 the override keyword allows you to explicity define that a function -// is intended to override the base-class version. This makes the code more -// managable and fixes a set of common hard-to-find bugs. -#if __cplusplus >= 201103L -# define JSONCPP_OVERRIDE override -# define JSONCPP_NOEXCEPT noexcept -#elif defined(_MSC_VER) && _MSC_VER > 1600 && _MSC_VER < 1900 -# define JSONCPP_OVERRIDE override -# define JSONCPP_NOEXCEPT throw() -#elif defined(_MSC_VER) && _MSC_VER >= 1900 -# define JSONCPP_OVERRIDE override -# define JSONCPP_NOEXCEPT noexcept +#if defined(_MSC_VER) && _MSC_VER < 1900 +// As recommended at +// https://stackoverflow.com/questions/2915672/snprintf-and-visual-studio-2010 +extern JSON_API int msvc_pre1900_c99_snprintf(char* outBuf, size_t size, + const char* format, ...); +#define jsoncpp_snprintf msvc_pre1900_c99_snprintf #else -# define JSONCPP_OVERRIDE -# define JSONCPP_NOEXCEPT throw() +#define jsoncpp_snprintf std::snprintf #endif -#ifndef JSON_HAS_RVALUE_REFERENCES +// If JSON_NO_INT64 is defined, then Json only support C++ "int" type for +// integer +// Storages, and 64 bits integer support is disabled. +// #define JSON_NO_INT64 1 -#if defined(_MSC_VER) && _MSC_VER >= 1600 // MSVC >= 2010 -#define JSON_HAS_RVALUE_REFERENCES 1 -#endif // MSVC >= 2010 +// JSONCPP_OVERRIDE is maintained for backwards compatibility of external tools. +// C++11 should be used directly in JSONCPP. +#define JSONCPP_OVERRIDE override #ifdef __clang__ -#if __has_feature(cxx_rvalue_references) -#define JSON_HAS_RVALUE_REFERENCES 1 -#endif // has_feature - -#elif defined __GNUC__ // not clang (gcc comes later since clang emulates gcc) -#if defined(__GXX_EXPERIMENTAL_CXX0X__) || (__cplusplus >= 201103L) -#define JSON_HAS_RVALUE_REFERENCES 1 -#endif // GXX_EXPERIMENTAL - -#endif // __clang__ || __GNUC__ - -#endif // not defined JSON_HAS_RVALUE_REFERENCES - -#ifndef JSON_HAS_RVALUE_REFERENCES -#define JSON_HAS_RVALUE_REFERENCES 0 +#if __has_extension(attribute_deprecated_with_message) +#define JSONCPP_DEPRECATED(message) __attribute__((deprecated(message))) #endif - -#ifdef __clang__ -# if __has_extension(attribute_deprecated_with_message) -# define JSONCPP_DEPRECATED(message) __attribute__ ((deprecated(message))) -# endif -#elif defined __GNUC__ // not clang (gcc comes later since clang emulates gcc) -# if (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 5)) -# define JSONCPP_DEPRECATED(message) __attribute__ ((deprecated(message))) -# elif (__GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 1)) -# define JSONCPP_DEPRECATED(message) __attribute__((__deprecated__)) -# endif // GNUC version -#elif defined(_MSC_VER) && _MSC_VER >= 1500 // MSVC 2008 - /// Indicates that the following function is deprecated. -# define JSONCPP_DEPRECATED(message) __declspec(deprecated(message)) +#elif defined(__GNUC__) // not clang (gcc comes later since clang emulates gcc) +#if (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 5)) +#define JSONCPP_DEPRECATED(message) __attribute__((deprecated(message))) +#elif (__GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 1)) +#define JSONCPP_DEPRECATED(message) __attribute__((__deprecated__)) +#endif // GNUC version +#elif defined(_MSC_VER) // MSVC (after clang because clang on Windows emulates + // MSVC) +#define JSONCPP_DEPRECATED(message) __declspec(deprecated(message)) #endif // __clang__ || __GNUC__ || _MSC_VER #undef JSONCPP_DEPRECATED // no deprecations in CMake copy @@ -142,53 +99,58 @@ #define JSONCPP_DEPRECATED(message) #endif // if !defined(JSONCPP_DEPRECATED) -#if __GNUC__ >= 6 -# define JSON_USE_INT64_DOUBLE_CONVERSION 1 +#if defined(__clang__) || (defined(__GNUC__) && (__GNUC__ >= 6)) +#define JSON_USE_INT64_DOUBLE_CONVERSION 1 #endif #if !defined(JSON_IS_AMALGAMATION) -# include "version.h" - -# if JSONCPP_USING_SECURE_MEMORY -# include "allocator.h" //typedef Allocator -# endif +#include "allocator.h" +#include "version.h" #endif // if !defined(JSON_IS_AMALGAMATION) namespace Json { -typedef int Int; -typedef unsigned int UInt; +using Int = int; +using UInt = unsigned int; #if defined(JSON_NO_INT64) -typedef int LargestInt; -typedef unsigned int LargestUInt; +using LargestInt = int; +using LargestUInt = unsigned int; #undef JSON_HAS_INT64 #else // if defined(JSON_NO_INT64) // For Microsoft Visual use specific types as long long is not supported #if defined(_MSC_VER) // Microsoft Visual Studio -typedef __int64 Int64; -typedef unsigned __int64 UInt64; +using Int64 = __int64; +using UInt64 = unsigned __int64; #else // if defined(_MSC_VER) // Other platforms, use long long -typedef int64_t Int64; -typedef uint64_t UInt64; -#endif // if defined(_MSC_VER) -typedef Int64 LargestInt; -typedef UInt64 LargestUInt; +using Int64 = int64_t; +using UInt64 = uint64_t; +#endif // if defined(_MSC_VER) +using LargestInt = Int64; +using LargestUInt = UInt64; #define JSON_HAS_INT64 #endif // if defined(JSON_NO_INT64) -#if JSONCPP_USING_SECURE_MEMORY -#define JSONCPP_STRING std::basic_string<char, std::char_traits<char>, Json::SecureAllocator<char> > -#define JSONCPP_OSTRINGSTREAM std::basic_ostringstream<char, std::char_traits<char>, Json::SecureAllocator<char> > -#define JSONCPP_OSTREAM std::basic_ostream<char, std::char_traits<char>> -#define JSONCPP_ISTRINGSTREAM std::basic_istringstream<char, std::char_traits<char>, Json::SecureAllocator<char> > -#define JSONCPP_ISTREAM std::istream -#else -#define JSONCPP_STRING std::string -#define JSONCPP_OSTRINGSTREAM std::ostringstream -#define JSONCPP_OSTREAM std::ostream -#define JSONCPP_ISTRINGSTREAM std::istringstream -#define JSONCPP_ISTREAM std::istream -#endif // if JSONCPP_USING_SECURE_MEMORY -} // end namespace Json + +template <typename T> +using Allocator = + typename std::conditional<JSONCPP_USING_SECURE_MEMORY, SecureAllocator<T>, + std::allocator<T>>::type; +using String = std::basic_string<char, std::char_traits<char>, Allocator<char>>; +using IStringStream = + std::basic_istringstream<String::value_type, String::traits_type, + String::allocator_type>; +using OStringStream = + std::basic_ostringstream<String::value_type, String::traits_type, + String::allocator_type>; +using IStream = std::istream; +using OStream = std::ostream; +} // namespace Json + +// Legacy names (formerly macros). +using JSONCPP_STRING = Json::String; +using JSONCPP_ISTRINGSTREAM = Json::IStringStream; +using JSONCPP_OSTRINGSTREAM = Json::OStringStream; +using JSONCPP_ISTREAM = Json::IStream; +using JSONCPP_OSTREAM = Json::OStream; #endif // JSON_CONFIG_H_INCLUDED diff --git a/Utilities/cmjsoncpp/include/json/forwards.h b/Utilities/cmjsoncpp/include/json/forwards.h index 70bbe19..affe33a 100644 --- a/Utilities/cmjsoncpp/include/json/forwards.h +++ b/Utilities/cmjsoncpp/include/json/forwards.h @@ -13,17 +13,23 @@ namespace Json { // writer.h +class StreamWriter; +class StreamWriterBuilder; +class Writer; class FastWriter; class StyledWriter; +class StyledStreamWriter; // reader.h class Reader; +class CharReader; +class CharReaderBuilder; -// features.h +// json_features.h class Features; // value.h -typedef unsigned int ArrayIndex; +using ArrayIndex = unsigned int; class StaticString; class Path; class PathArgument; diff --git a/Utilities/cmjsoncpp/include/json/json.h b/Utilities/cmjsoncpp/include/json/json.h index 5964672..5c776a1 100644 --- a/Utilities/cmjsoncpp/include/json/json.h +++ b/Utilities/cmjsoncpp/include/json/json.h @@ -6,9 +6,10 @@ #ifndef JSON_JSON_H_INCLUDED #define JSON_JSON_H_INCLUDED -#include "value.h" +#include "config.h" +#include "json_features.h" #include "reader.h" +#include "value.h" #include "writer.h" -#include "features.h" #endif // JSON_JSON_H_INCLUDED diff --git a/Utilities/cmjsoncpp/include/json/features.h b/Utilities/cmjsoncpp/include/json/json_features.h index 365abb3..6b99b4d 100644 --- a/Utilities/cmjsoncpp/include/json/features.h +++ b/Utilities/cmjsoncpp/include/json/json_features.h @@ -3,8 +3,8 @@ // recognized in your jurisdiction. // See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE -#ifndef CPPTL_JSON_FEATURES_H_INCLUDED -#define CPPTL_JSON_FEATURES_H_INCLUDED +#ifndef JSON_FEATURES_H_INCLUDED +#define JSON_FEATURES_H_INCLUDED #if !defined(JSON_IS_AMALGAMATION) #include "forwards.h" @@ -43,17 +43,17 @@ public: Features(); /// \c true if comments are allowed. Default: \c true. - bool allowComments_; + bool allowComments_{true}; /// \c true if root must be either an array or an object value. Default: \c /// false. - bool strictRoot_; + bool strictRoot_{false}; /// \c true if dropped null placeholders are allowed. Default: \c false. - bool allowDroppedNullPlaceholders_; + bool allowDroppedNullPlaceholders_{false}; /// \c true if numeric object key are allowed. Default: \c false. - bool allowNumericKeys_; + bool allowNumericKeys_{false}; }; } // namespace Json @@ -62,4 +62,4 @@ public: #pragma pack(pop) #endif -#endif // CPPTL_JSON_FEATURES_H_INCLUDED +#endif // JSON_FEATURES_H_INCLUDED diff --git a/Utilities/cmjsoncpp/include/json/reader.h b/Utilities/cmjsoncpp/include/json/reader.h index 667246a..7ad0be6 100644 --- a/Utilities/cmjsoncpp/include/json/reader.h +++ b/Utilities/cmjsoncpp/include/json/reader.h @@ -3,18 +3,18 @@ // recognized in your jurisdiction. // See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE -#ifndef CPPTL_JSON_READER_H_INCLUDED -#define CPPTL_JSON_READER_H_INCLUDED +#ifndef JSON_READER_H_INCLUDED +#define JSON_READER_H_INCLUDED #if !defined(JSON_IS_AMALGAMATION) -#include "features.h" +#include "json_features.h" #include "value.h" #endif // if !defined(JSON_IS_AMALGAMATION) #include <deque> #include <iosfwd> +#include <istream> #include <stack> #include <string> -#include <istream> // Disable warning C4251: <data member>: <type> needs to have dll-interface to // be used by... @@ -30,132 +30,130 @@ namespace Json { /** \brief Unserialize a <a HREF="http://www.json.org">JSON</a> document into a - *Value. + * Value. * * deprecated Use CharReader and CharReaderBuilder. */ -class JSONCPP_DEPRECATED("Use CharReader and CharReaderBuilder instead") JSON_API Reader { + +class JSONCPP_DEPRECATED( + "Use CharReader and CharReaderBuilder instead.") JSON_API Reader { public: - typedef char Char; - typedef const Char* Location; + using Char = char; + using Location = const Char*; /** \brief An error tagged with where in the JSON text it was encountered. * * The offsets give the [start, limit) range of bytes within the text. Note * that this is bytes, not codepoints. - * */ struct StructuredError { ptrdiff_t offset_start; ptrdiff_t offset_limit; - JSONCPP_STRING message; + String message; }; - /** \brief Constructs a Reader allowing all features - * for parsing. + /** \brief Constructs a Reader allowing all features for parsing. */ + JSONCPP_DEPRECATED("Use CharReader and CharReaderBuilder instead") Reader(); - /** \brief Constructs a Reader allowing the specified feature set - * for parsing. + /** \brief Constructs a Reader allowing the specified feature set for parsing. */ + JSONCPP_DEPRECATED("Use CharReader and CharReaderBuilder instead") Reader(const Features& features); /** \brief Read a Value from a <a HREF="http://www.json.org">JSON</a> * document. - * \param document UTF-8 encoded string containing the document to read. - * \param root [out] Contains the root value of the document if it was - * successfully parsed. - * \param collectComments \c true to collect comment and allow writing them - * back during - * serialization, \c false to discard comments. - * This parameter is ignored if - * Features::allowComments_ - * is \c false. + * + * \param document UTF-8 encoded string containing the document + * to read. + * \param[out] root Contains the root value of the document if it + * was successfully parsed. + * \param collectComments \c true to collect comment and allow writing + * them back during serialization, \c false to + * discard comments. This parameter is ignored + * if Features::allowComments_ is \c false. * \return \c true if the document was successfully parsed, \c false if an * error occurred. */ - bool - parse(const std::string& document, Value& root, bool collectComments = true); + bool parse(const std::string& document, Value& root, + bool collectComments = true); /** \brief Read a Value from a <a HREF="http://www.json.org">JSON</a> - document. - * \param beginDoc Pointer on the beginning of the UTF-8 encoded string of the - document to read. - * \param endDoc Pointer on the end of the UTF-8 encoded string of the - document to read. - * Must be >= beginDoc. - * \param root [out] Contains the root value of the document if it was - * successfully parsed. - * \param collectComments \c true to collect comment and allow writing them - back during - * serialization, \c false to discard comments. - * This parameter is ignored if - Features::allowComments_ - * is \c false. + * document. + * + * \param beginDoc Pointer on the beginning of the UTF-8 encoded + * string of the document to read. + * \param endDoc Pointer on the end of the UTF-8 encoded string + * of the document to read. Must be >= beginDoc. + * \param[out] root Contains the root value of the document if it + * was successfully parsed. + * \param collectComments \c true to collect comment and allow writing + * them back during serialization, \c false to + * discard comments. This parameter is ignored + * if Features::allowComments_ is \c false. * \return \c true if the document was successfully parsed, \c false if an - error occurred. + * error occurred. */ - bool parse(const char* beginDoc, - const char* endDoc, - Value& root, + bool parse(const char* beginDoc, const char* endDoc, Value& root, bool collectComments = true); /// \brief Parse from input stream. /// \see Json::operator>>(std::istream&, Json::Value&). - bool parse(JSONCPP_ISTREAM& is, Value& root, bool collectComments = true); + bool parse(IStream& is, Value& root, bool collectComments = true); /** \brief Returns a user friendly string that list errors in the parsed * document. - * \return Formatted error message with the list of errors with their location - * in - * the parsed document. An empty string is returned if no error - * occurred - * during parsing. + * + * \return Formatted error message with the list of errors with their + * location in the parsed document. An empty string is returned if no error + * occurred during parsing. * deprecated Use getFormattedErrorMessages() instead (typo fix). */ JSONCPP_DEPRECATED("Use getFormattedErrorMessages() instead.") - JSONCPP_STRING getFormatedErrorMessages() const; + String getFormatedErrorMessages() const; /** \brief Returns a user friendly string that list errors in the parsed * document. - * \return Formatted error message with the list of errors with their location - * in - * the parsed document. An empty string is returned if no error - * occurred - * during parsing. + * + * \return Formatted error message with the list of errors with their + * location in the parsed document. An empty string is returned if no error + * occurred during parsing. */ - JSONCPP_STRING getFormattedErrorMessages() const; + String getFormattedErrorMessages() const; - /** \brief Returns a vector of structured erros encounted while parsing. + /** \brief Returns a vector of structured errors encountered while parsing. + * * \return A (possibly empty) vector of StructuredError objects. Currently - * only one error can be returned, but the caller should tolerate - * multiple - * errors. This can occur if the parser recovers from a non-fatal - * parse error and then encounters additional errors. + * only one error can be returned, but the caller should tolerate multiple + * errors. This can occur if the parser recovers from a non-fatal parse + * error and then encounters additional errors. */ std::vector<StructuredError> getStructuredErrors() const; /** \brief Add a semantic error message. - * \param value JSON Value location associated with the error + * + * \param value JSON Value location associated with the error * \param message The error message. - * \return \c true if the error was successfully added, \c false if the - * Value offset exceeds the document size. + * \return \c true if the error was successfully added, \c false if the Value + * offset exceeds the document size. */ - bool pushError(const Value& value, const JSONCPP_STRING& message); + bool pushError(const Value& value, const String& message); /** \brief Add a semantic error message with extra context. - * \param value JSON Value location associated with the error + * + * \param value JSON Value location associated with the error * \param message The error message. - * \param extra Additional JSON Value location to contextualize the error + * \param extra Additional JSON Value location to contextualize the error * \return \c true if the error was successfully added, \c false if either * Value offset exceeds the document size. */ - bool pushError(const Value& value, const JSONCPP_STRING& message, const Value& extra); + bool pushError(const Value& value, const String& message, const Value& extra); /** \brief Return whether there are any errors. - * \return \c true if there are no errors to report \c false if - * errors have occurred. + * + * \return \c true if there are no errors to report \c false if errors have + * occurred. */ bool good() const; @@ -187,15 +185,15 @@ private: class ErrorInfo { public: Token token_; - JSONCPP_STRING message_; + String message_; Location extra_; }; - typedef std::deque<ErrorInfo> Errors; + using Errors = std::deque<ErrorInfo>; bool readToken(Token& token); void skipSpaces(); - bool match(Location pattern, int patternLength); + bool match(const Char* pattern, int patternLength); bool readComment(); bool readCStyleComment(); bool readCppStyleComment(); @@ -207,142 +205,138 @@ private: bool decodeNumber(Token& token); bool decodeNumber(Token& token, Value& decoded); bool decodeString(Token& token); - bool decodeString(Token& token, JSONCPP_STRING& decoded); + bool decodeString(Token& token, String& decoded); bool decodeDouble(Token& token); bool decodeDouble(Token& token, Value& decoded); - bool decodeUnicodeCodePoint(Token& token, - Location& current, - Location end, + bool decodeUnicodeCodePoint(Token& token, Location& current, Location end, unsigned int& unicode); - bool decodeUnicodeEscapeSequence(Token& token, - Location& current, - Location end, - unsigned int& unicode); - bool addError(const JSONCPP_STRING& message, Token& token, Location extra = 0); + bool decodeUnicodeEscapeSequence(Token& token, Location& current, + Location end, unsigned int& unicode); + bool addError(const String& message, Token& token, Location extra = nullptr); bool recoverFromError(TokenType skipUntilToken); - bool addErrorAndRecover(const JSONCPP_STRING& message, - Token& token, + bool addErrorAndRecover(const String& message, Token& token, TokenType skipUntilToken); void skipUntilSpace(); Value& currentValue(); Char getNextChar(); - void - getLocationLineAndColumn(Location location, int& line, int& column) const; - JSONCPP_STRING getLocationLineAndColumn(Location location) const; + void getLocationLineAndColumn(Location location, int& line, + int& column) const; + String getLocationLineAndColumn(Location location) const; void addComment(Location begin, Location end, CommentPlacement placement); void skipCommentTokens(Token& token); static bool containsNewLine(Location begin, Location end); - static JSONCPP_STRING normalizeEOL(Location begin, Location end); + static String normalizeEOL(Location begin, Location end); - typedef std::stack<Value*> Nodes; + using Nodes = std::stack<Value*>; Nodes nodes_; Errors errors_; - JSONCPP_STRING document_; - Location begin_; - Location end_; - Location current_; - Location lastValueEnd_; - Value* lastValue_; - JSONCPP_STRING commentsBefore_; + String document_; + Location begin_{}; + Location end_{}; + Location current_{}; + Location lastValueEnd_{}; + Value* lastValue_{}; + String commentsBefore_; Features features_; - bool collectComments_; -}; // Reader + bool collectComments_{}; +}; // Reader /** Interface for reading JSON from a char array. */ class JSON_API CharReader { public: - virtual ~CharReader() {} + virtual ~CharReader() = default; /** \brief Read a Value from a <a HREF="http://www.json.org">JSON</a> - document. - * The document must be a UTF-8 encoded string containing the document to read. + * document. The document must be a UTF-8 encoded string containing the + * document to read. * - * \param beginDoc Pointer on the beginning of the UTF-8 encoded string of the - document to read. - * \param endDoc Pointer on the end of the UTF-8 encoded string of the - document to read. - * Must be >= beginDoc. - * \param root [out] Contains the root value of the document if it was - * successfully parsed. - * \param errs [out] Formatted error messages (if not NULL) - * a user friendly string that lists errors in the parsed - * document. + * \param beginDoc Pointer on the beginning of the UTF-8 encoded string + * of the document to read. + * \param endDoc Pointer on the end of the UTF-8 encoded string of the + * document to read. Must be >= beginDoc. + * \param[out] root Contains the root value of the document if it was + * successfully parsed. + * \param[out] errs Formatted error messages (if not NULL) a user + * friendly string that lists errors in the parsed + * document. * \return \c true if the document was successfully parsed, \c false if an - error occurred. + * error occurred. */ - virtual bool parse( - char const* beginDoc, char const* endDoc, - Value* root, JSONCPP_STRING* errs) = 0; + virtual bool parse(char const* beginDoc, char const* endDoc, Value* root, + String* errs) = 0; class JSON_API Factory { public: - virtual ~Factory() {} + virtual ~Factory() = default; /** \brief Allocate a CharReader via operator new(). * \throw std::exception if something goes wrong (e.g. invalid settings) */ virtual CharReader* newCharReader() const = 0; - }; // Factory -}; // CharReader + }; // Factory +}; // CharReader /** \brief Build a CharReader implementation. - -Usage: -\code - using namespace Json; - CharReaderBuilder builder; - builder["collectComments"] = false; - Value value; - JSONCPP_STRING errs; - bool ok = parseFromStream(builder, std::cin, &value, &errs); -\endcode -*/ + * + * Usage: + * \code + * using namespace Json; + * CharReaderBuilder builder; + * builder["collectComments"] = false; + * Value value; + * String errs; + * bool ok = parseFromStream(builder, std::cin, &value, &errs); + * \endcode + */ class JSON_API CharReaderBuilder : public CharReader::Factory { public: // Note: We use a Json::Value so that we can add data-members to this class // without a major version bump. /** Configuration of this builder. - These are case-sensitive. - Available settings (case-sensitive): - - `"collectComments": false or true` - - true to collect comment and allow writing them - back during serialization, false to discard comments. - This parameter is ignored if allowComments is false. - - `"allowComments": false or true` - - true if comments are allowed. - - `"strictRoot": false or true` - - true if root must be either an array or an object value - - `"allowDroppedNullPlaceholders": false or true` - - true if dropped null placeholders are allowed. (See StreamWriterBuilder.) - - `"allowNumericKeys": false or true` - - true if numeric object keys are allowed. - - `"allowSingleQuotes": false or true` - - true if '' are allowed for strings (both keys and values) - - `"stackLimit": integer` - - Exceeding stackLimit (recursive depth of `readValue()`) will - cause an exception. - - This is a security issue (seg-faults caused by deeply nested JSON), - so the default is low. - - `"failIfExtra": false or true` - - If true, `parse()` returns false when extra non-whitespace trails - the JSON value in the input string. - - `"rejectDupKeys": false or true` - - If true, `parse()` returns false when a key is duplicated within an object. - - `"allowSpecialFloats": false or true` - - If true, special float values (NaNs and infinities) are allowed - and their values are lossfree restorable. - - You can examine 'settings_` yourself - to see the defaults. You can also write and read them just like any - JSON Value. - \sa setDefaults() - */ + * These are case-sensitive. + * Available settings (case-sensitive): + * - `"collectComments": false or true` + * - true to collect comment and allow writing them back during + * serialization, false to discard comments. This parameter is ignored + * if allowComments is false. + * - `"allowComments": false or true` + * - true if comments are allowed. + * - `"allowTrailingCommas": false or true` + * - true if trailing commas in objects and arrays are allowed. + * - `"strictRoot": false or true` + * - true if root must be either an array or an object value + * - `"allowDroppedNullPlaceholders": false or true` + * - true if dropped null placeholders are allowed. (See + * StreamWriterBuilder.) + * - `"allowNumericKeys": false or true` + * - true if numeric object keys are allowed. + * - `"allowSingleQuotes": false or true` + * - true if '' are allowed for strings (both keys and values) + * - `"stackLimit": integer` + * - Exceeding stackLimit (recursive depth of `readValue()`) will cause an + * exception. + * - This is a security issue (seg-faults caused by deeply nested JSON), so + * the default is low. + * - `"failIfExtra": false or true` + * - If true, `parse()` returns false when extra non-whitespace trails the + * JSON value in the input string. + * - `"rejectDupKeys": false or true` + * - If true, `parse()` returns false when a key is duplicated within an + * object. + * - `"allowSpecialFloats": false or true` + * - If true, special float values (NaNs and infinities) are allowed and + * their values are lossfree restorable. + * + * You can examine 'settings_` yourself to see the defaults. You can also + * write and read them just like any JSON Value. + * \sa setDefaults() + */ Json::Value settings_; CharReaderBuilder(); - ~CharReaderBuilder() JSONCPP_OVERRIDE; + ~CharReaderBuilder() override; - CharReader* newCharReader() const JSONCPP_OVERRIDE; + CharReader* newCharReader() const override; /** \return true if 'settings' are legal and consistent; * otherwise, indicate bad settings via 'invalid'. @@ -351,7 +345,7 @@ public: /** A simple way to update a specific setting. */ - Value& operator[](JSONCPP_STRING key); + Value& operator[](const String& key); /** Called by ctor, but you can use this to reset settings_. * \pre 'settings' != NULL (but Json::null is fine) @@ -368,39 +362,37 @@ public: }; /** Consume entire stream and use its begin/end. - * Someday we might have a real StreamReader, but for now this - * is convenient. - */ -bool JSON_API parseFromStream( - CharReader::Factory const&, - JSONCPP_ISTREAM&, - Value* root, std::string* errs); + * Someday we might have a real StreamReader, but for now this + * is convenient. + */ +bool JSON_API parseFromStream(CharReader::Factory const&, IStream&, Value* root, + String* errs); /** \brief Read from 'sin' into 'root'. - - Always keep comments from the input JSON. - - This can be used to read a file into a particular sub-object. - For example: - \code - Json::Value root; - cin >> root["dir"]["file"]; - cout << root; - \endcode - Result: - \verbatim - { - "dir": { - "file": { - // The input stream JSON would be nested here. - } - } - } - \endverbatim - \throw std::exception on parse error. - \see Json::operator<<() -*/ -JSON_API JSONCPP_ISTREAM& operator>>(JSONCPP_ISTREAM&, Value&); + * + * Always keep comments from the input JSON. + * + * This can be used to read a file into a particular sub-object. + * For example: + * \code + * Json::Value root; + * cin >> root["dir"]["file"]; + * cout << root; + * \endcode + * Result: + * \verbatim + * { + * "dir": { + * "file": { + * // The input stream JSON would be nested here. + * } + * } + * } + * \endverbatim + * \throw std::exception on parse error. + * \see Json::operator<<() + */ +JSON_API IStream& operator>>(IStream&, Value&); } // namespace Json @@ -412,4 +404,4 @@ JSON_API JSONCPP_ISTREAM& operator>>(JSONCPP_ISTREAM&, Value&); #pragma warning(pop) #endif // if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING) -#endif // CPPTL_JSON_READER_H_INCLUDED +#endif // JSON_READER_H_INCLUDED diff --git a/Utilities/cmjsoncpp/include/json/value.h b/Utilities/cmjsoncpp/include/json/value.h index 7b90c5a..952d423 100644 --- a/Utilities/cmjsoncpp/include/json/value.h +++ b/Utilities/cmjsoncpp/include/json/value.h @@ -3,38 +3,49 @@ // recognized in your jurisdiction. // See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE -#ifndef CPPTL_JSON_H_INCLUDED -#define CPPTL_JSON_H_INCLUDED +#ifndef JSON_H_INCLUDED +#define JSON_H_INCLUDED #if !defined(JSON_IS_AMALGAMATION) #include "forwards.h" #endif // if !defined(JSON_IS_AMALGAMATION) -#include <string> -#include <vector> -#include <exception> -#ifndef JSON_USE_CPPTL_SMALLMAP -#include <map> +// Conditional NORETURN attribute on the throw functions would: +// a) suppress false positives from static code analysis +// b) possibly improve optimization opportunities. +#if !defined(JSONCPP_NORETURN) +#if defined(_MSC_VER) && _MSC_VER == 1800 +#define JSONCPP_NORETURN __declspec(noreturn) #else -#include <cpptl/smallmap.h> +#define JSONCPP_NORETURN [[noreturn]] #endif -#ifdef JSON_USE_CPPTL -#include <cpptl/forwards.h> #endif -//Conditional NORETURN attribute on the throw functions would: -// a) suppress false positives from static code analysis -// b) possibly improve optimization opportunities. -#if !defined(JSONCPP_NORETURN) -# if defined(_MSC_VER) -# define JSONCPP_NORETURN __declspec(noreturn) -# elif defined(__GNUC__) -# define JSONCPP_NORETURN __attribute__ ((__noreturn__)) -# else -# define JSONCPP_NORETURN -# endif +// Support for '= delete' with template declarations was a late addition +// to the c++11 standard and is rejected by clang 3.8 and Apple clang 8.2 +// even though these declare themselves to be c++11 compilers. +#if !defined(JSONCPP_TEMPLATE_DELETE) +#if defined(__clang__) && defined(__apple_build_version__) +#if __apple_build_version__ <= 8000042 +#define JSONCPP_TEMPLATE_DELETE +#endif +#elif defined(__clang__) +#if __clang_major__ == 3 && __clang_minor__ <= 8 +#define JSONCPP_TEMPLATE_DELETE +#endif +#endif +#if !defined(JSONCPP_TEMPLATE_DELETE) +#define JSONCPP_TEMPLATE_DELETE = delete +#endif #endif +#include <array> +#include <exception> +#include <map> +#include <memory> +#include <string> +#include <vector> + // Disable warning C4251: <data member>: <type> needs to have dll-interface to // be used by... #if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING) @@ -50,17 +61,19 @@ */ namespace Json { +#if JSON_USE_EXCEPTION /** Base class for all exceptions we throw. * * We use nothing but these internally. Of course, STL can throw others. */ class JSON_API Exception : public std::exception { public: - Exception(JSONCPP_STRING const& msg); - ~Exception() JSONCPP_NOEXCEPT JSONCPP_OVERRIDE; - char const* what() const JSONCPP_NOEXCEPT JSONCPP_OVERRIDE; + Exception(String msg); + ~Exception() noexcept override; + char const* what() const noexcept override; + protected: - JSONCPP_STRING msg_; + String msg_; }; /** Exceptions which the user cannot easily avoid. @@ -71,7 +84,7 @@ protected: */ class JSON_API RuntimeError : public Exception { public: - RuntimeError(JSONCPP_STRING const& msg); + RuntimeError(String const& msg); }; /** Exceptions thrown by JSON_ASSERT/JSON_FAIL macros. @@ -82,13 +95,14 @@ public: */ class JSON_API LogicError : public Exception { public: - LogicError(JSONCPP_STRING const& msg); + LogicError(String const& msg); }; +#endif /// used internally -JSONCPP_NORETURN void throwRuntimeError(JSONCPP_STRING const& msg); +JSONCPP_NORETURN void throwRuntimeError(String const& msg); /// used internally -JSONCPP_NORETURN void throwLogicError(JSONCPP_STRING const& msg); +JSONCPP_NORETURN void throwLogicError(String const& msg); /** \brief Type of the value held by a Value object. */ @@ -111,14 +125,16 @@ enum CommentPlacement { numberOfCommentPlacement }; -//# ifdef JSON_USE_CPPTL -// typedef CppTL::AnyEnumerator<const char *> EnumMemberNames; -// typedef CppTL::AnyEnumerator<const Value &> EnumValues; -//# endif +/** \brief Type of precision for formatting of real values. + */ +enum PrecisionType { + significantDigits = 0, ///< we set max number of significant digits in string + decimalPlaces ///< we set max number of digits after "." in string +}; /** \brief Lightweight wrapper to tag static string. * - * Value constructor and objectValue member assignement takes advantage of the + * Value constructor and objectValue member assignment takes advantage of the * StaticString and avoid the cost of string duplication when storing the * string or the member name. * @@ -167,7 +183,7 @@ private: * The get() methods can be used to obtain default value in the case the * required element does not exist. * - * It is possible to iterate over the list of a #objectValue values using + * It is possible to iterate over the list of member keys of an object using * the getMemberNames() method. * * \note #Value string-length fit in size_t, but keys must be < 2^30. @@ -178,73 +194,86 @@ private: */ class JSON_API Value { friend class ValueIteratorBase; + public: - typedef std::vector<JSONCPP_STRING> Members; - typedef ValueIterator iterator; - typedef ValueConstIterator const_iterator; - typedef Json::UInt UInt; - typedef Json::Int Int; + using Members = std::vector<String>; + using iterator = ValueIterator; + using const_iterator = ValueConstIterator; + using UInt = Json::UInt; + using Int = Json::Int; #if defined(JSON_HAS_INT64) - typedef Json::UInt64 UInt64; - typedef Json::Int64 Int64; + using UInt64 = Json::UInt64; + using Int64 = Json::Int64; #endif // defined(JSON_HAS_INT64) - typedef Json::LargestInt LargestInt; - typedef Json::LargestUInt LargestUInt; - typedef Json::ArrayIndex ArrayIndex; + using LargestInt = Json::LargestInt; + using LargestUInt = Json::LargestUInt; + using ArrayIndex = Json::ArrayIndex; - static const Value& null; ///< We regret this reference to a global instance; prefer the simpler Value(). - static const Value& nullRef; ///< just a kludge for binary-compatibility; same as null - static Value const& nullSingleton(); ///< Prefer this to null or nullRef. + // Required for boost integration, e. g. BOOST_TEST + using value_type = std::string; + +#if JSON_USE_NULLREF + // Binary compatibility kludges, do not use. + static const Value& null; + static const Value& nullRef; +#endif + + // null and nullRef are deprecated, use this instead. + static Value const& nullSingleton(); /// Minimum signed integer value that can be stored in a Json::Value. - static const LargestInt minLargestInt; + static constexpr LargestInt minLargestInt = + LargestInt(~(LargestUInt(-1) / 2)); /// Maximum signed integer value that can be stored in a Json::Value. - static const LargestInt maxLargestInt; + static constexpr LargestInt maxLargestInt = LargestInt(LargestUInt(-1) / 2); /// Maximum unsigned integer value that can be stored in a Json::Value. - static const LargestUInt maxLargestUInt; + static constexpr LargestUInt maxLargestUInt = LargestUInt(-1); /// Minimum signed int value that can be stored in a Json::Value. - static const Int minInt; + static constexpr Int minInt = Int(~(UInt(-1) / 2)); /// Maximum signed int value that can be stored in a Json::Value. - static const Int maxInt; + static constexpr Int maxInt = Int(UInt(-1) / 2); /// Maximum unsigned int value that can be stored in a Json::Value. - static const UInt maxUInt; + static constexpr UInt maxUInt = UInt(-1); #if defined(JSON_HAS_INT64) /// Minimum signed 64 bits int value that can be stored in a Json::Value. - static const Int64 minInt64; + static constexpr Int64 minInt64 = Int64(~(UInt64(-1) / 2)); /// Maximum signed 64 bits int value that can be stored in a Json::Value. - static const Int64 maxInt64; + static constexpr Int64 maxInt64 = Int64(UInt64(-1) / 2); /// Maximum unsigned 64 bits int value that can be stored in a Json::Value. - static const UInt64 maxUInt64; + static constexpr UInt64 maxUInt64 = UInt64(-1); #endif // defined(JSON_HAS_INT64) - + /// Default precision for real value for string representation. + static constexpr UInt defaultRealPrecision = 17; + // The constant is hard-coded because some compiler have trouble + // converting Value::maxUInt64 to a double correctly (AIX/xlC). + // Assumes that UInt64 is a 64 bits integer. + static constexpr double maxUInt64AsDouble = 18446744073709551615.0; +// Workaround for bug in the NVIDIAs CUDA 9.1 nvcc compiler +// when using gcc and clang backend compilers. CZString +// cannot be defined as private. See issue #486 +#ifdef __NVCC__ +public: +#else private: +#endif #ifndef JSONCPP_DOC_EXCLUDE_IMPLEMENTATION class CZString { public: - enum DuplicationPolicy { - noDuplication = 0, - duplicate, - duplicateOnCopy - }; + enum DuplicationPolicy { noDuplication = 0, duplicate, duplicateOnCopy }; CZString(ArrayIndex index); CZString(char const* str, unsigned length, DuplicationPolicy allocate); CZString(CZString const& other); -#if JSON_HAS_RVALUE_REFERENCES CZString(CZString&& other); -#endif ~CZString(); CZString& operator=(const CZString& other); - -#if JSON_HAS_RVALUE_REFERENCES CZString& operator=(CZString&& other); -#endif bool operator<(CZString const& other) const; bool operator==(CZString const& other) const; ArrayIndex index() const; - //const char* c_str() const; ///< deprecated + // const char* c_str() const; ///< deprecated char const* data() const; unsigned length() const; bool isStaticString() const; @@ -253,11 +282,11 @@ private: void swap(CZString& other); struct StringStorage { - unsigned policy_: 2; - unsigned length_: 30; // 1GB max + unsigned policy_ : 2; + unsigned length_ : 30; // 1GB max }; - char const* cstr_; // actually, a prefixed string, unless policy is noDup + char const* cstr_; // actually, a prefixed string, unless policy is noDup union { ArrayIndex index_; StringStorage storage_; @@ -265,29 +294,26 @@ private: }; public: -#ifndef JSON_USE_CPPTL_SMALLMAP typedef std::map<CZString, Value> ObjectValues; -#else - typedef CppTL::SmallMap<CZString, Value> ObjectValues; -#endif // ifndef JSON_USE_CPPTL_SMALLMAP #endif // ifndef JSONCPP_DOC_EXCLUDE_IMPLEMENTATION public: - /** \brief Create a default Value of the given type. - - This is a very useful constructor. - To create an empty array, pass arrayValue. - To create an empty object, pass objectValue. - Another Value can then be set to this one by assignment. -This is useful since clear() and resize() will not alter types. - - Examples: -\code -Json::Value null_value; // null -Json::Value arr_value(Json::arrayValue); // [] -Json::Value obj_value(Json::objectValue); // {} -\endcode - */ + /** + * \brief Create a default Value of the given type. + * + * This is a very useful constructor. + * To create an empty array, pass arrayValue. + * To create an empty object, pass objectValue. + * Another Value can then be set to this one by assignment. + * This is useful since clear() and resize() will not alter types. + * + * Examples: + * \code + * Json::Value null_value; // null + * Json::Value arr_value(Json::arrayValue); // [] + * Json::Value obj_value(Json::objectValue); // {} + * \endcode + */ Value(ValueType type = nullValue); Value(Int value); Value(UInt value); @@ -298,38 +324,35 @@ Json::Value obj_value(Json::objectValue); // {} Value(double value); Value(const char* value); ///< Copy til first 0. (NULL causes to seg-fault.) Value(const char* begin, const char* end); ///< Copy all, incl zeroes. - /** \brief Constructs a value from a static string. - + /** + * \brief Constructs a value from a static string. + * * Like other value string constructor but do not duplicate the string for - * internal storage. The given string must remain alive after the call to this - * constructor. + * internal storage. The given string must remain alive after the call to + * this constructor. + * * \note This works only for null-terminated strings. (We cannot change the - * size of this class, so we have nowhere to store the length, - * which might be computed later for various operations.) + * size of this class, so we have nowhere to store the length, which might be + * computed later for various operations.) * * Example of usage: - * \code - * static StaticString foo("some text"); - * Json::Value aValue(foo); - * \endcode + * \code + * static StaticString foo("some text"); + * Json::Value aValue(foo); + * \endcode */ Value(const StaticString& value); - Value(const JSONCPP_STRING& value); ///< Copy data() til size(). Embedded zeroes too. -#ifdef JSON_USE_CPPTL - Value(const CppTL::ConstString& value); -#endif + Value(const String& value); Value(bool value); - /// Deep copy. + Value(std::nullptr_t ptr) = delete; Value(const Value& other); -#if JSON_HAS_RVALUE_REFERENCES - /// Move constructor Value(Value&& other); -#endif ~Value(); - /// Deep copy, then swap(other). - /// \note Over-write existing comments. To preserve comments, use #swapPayload(). - Value& operator=(Value other); + /// \note Overwrite existing comments. To preserve comments, use + /// #swapPayload(). + Value& operator=(const Value& other); + Value& operator=(Value&& other); /// Swap everything. void swap(Value& other); @@ -354,17 +377,14 @@ Json::Value obj_value(Json::objectValue); // {} const char* asCString() const; ///< Embedded zeroes could cause you trouble! #if JSONCPP_USING_SECURE_MEMORY - unsigned getCStringLength() const; //Allows you to understand the length of the CString + unsigned getCStringLength() const; // Allows you to understand the length of + // the CString #endif - JSONCPP_STRING asString() const; ///< Embedded zeroes are possible. + String asString() const; ///< Embedded zeroes are possible. /** Get raw char* of string-value. * \return false if !string. (Seg-fault if str or end are NULL.) */ - bool getString( - char const** begin, char const** end) const; -#ifdef JSON_USE_CPPTL - CppTL::ConstString asConstString() const; -#endif + bool getString(char const** begin, char const** end) const; Int asInt() const; UInt asUInt() const; #if defined(JSON_HAS_INT64) @@ -390,6 +410,10 @@ Json::Value obj_value(Json::objectValue); // {} bool isArray() const; bool isObject() const; + /// The `as<T>` and `is<T>` member function templates and specializations. + template <typename T> T as() const JSONCPP_TEMPLATE_DELETE; + template <typename T> bool is() const JSONCPP_TEMPLATE_DELETE; + bool isConvertibleTo(ValueType other) const; /// Number of values in array or object @@ -399,50 +423,41 @@ Json::Value obj_value(Json::objectValue); // {} /// otherwise, false. bool empty() const; - /// Return isNull() - bool operator!() const; + /// Return !isNull() + explicit operator bool() const; /// Remove all object members and array elements. /// \pre type() is arrayValue, objectValue, or nullValue /// \post type() is unchanged void clear(); - /// Resize the array to size elements. + /// Resize the array to newSize elements. /// New elements are initialized to null. /// May only be called on nullValue or arrayValue. /// \pre type() is arrayValue or nullValue /// \post type() is arrayValue - void resize(ArrayIndex size); + void resize(ArrayIndex newSize); - /// Access an array element (zero based index ). - /// If the array contains less than index element, then null value are - /// inserted - /// in the array so that its size is index+1. + //@{ + /// Access an array element (zero based index). If the array contains less + /// than index element, then null value are inserted in the array so that + /// its size is index+1. /// (You may need to say 'value[0u]' to get your compiler to distinguish - /// this from the operator[] which takes a string.) + /// this from the operator[] which takes a string.) Value& operator[](ArrayIndex index); - - /// Access an array element (zero based index ). - /// If the array contains less than index element, then null value are - /// inserted - /// in the array so that its size is index+1. - /// (You may need to say 'value[0u]' to get your compiler to distinguish - /// this from the operator[] which takes a string.) Value& operator[](int index); + //@} - /// Access an array element (zero based index ) + //@{ + /// Access an array element (zero based index). /// (You may need to say 'value[0u]' to get your compiler to distinguish - /// this from the operator[] which takes a string.) + /// this from the operator[] which takes a string.) const Value& operator[](ArrayIndex index) const; - - /// Access an array element (zero based index ) - /// (You may need to say 'value[0u]' to get your compiler to distinguish - /// this from the operator[] which takes a string.) const Value& operator[](int index) const; + //@} /// If the array contains at least index+1 elements, returns the element - /// value, - /// otherwise returns defaultValue. + /// value, otherwise returns defaultValue. Value get(ArrayIndex index, const Value& defaultValue) const; /// Return true if index < size(). bool isValidIndex(ArrayIndex index) const; @@ -450,61 +465,51 @@ Json::Value obj_value(Json::objectValue); // {} /// /// Equivalent to jsonvalue[jsonvalue.size()] = value; Value& append(const Value& value); - -#if JSON_HAS_RVALUE_REFERENCES Value& append(Value&& value); -#endif + + /// \brief Insert value in array at specific index + bool insert(ArrayIndex index, const Value& newValue); + bool insert(ArrayIndex index, Value&& newValue); /// Access an object value by name, create a null member if it does not exist. /// \note Because of our implementation, keys are limited to 2^30 -1 chars. - /// Exceeding that will cause an exception. + /// Exceeding that will cause an exception. Value& operator[](const char* key); /// Access an object value by name, returns null if there is no member with /// that name. const Value& operator[](const char* key) const; /// Access an object value by name, create a null member if it does not exist. /// \param key may contain embedded nulls. - Value& operator[](const JSONCPP_STRING& key); + Value& operator[](const String& key); /// Access an object value by name, returns null if there is no member with /// that name. /// \param key may contain embedded nulls. - const Value& operator[](const JSONCPP_STRING& key) const; + const Value& operator[](const String& key) const; /** \brief Access an object value by name, create a null member if it does not - exist. - - * If the object has no entry for that name, then the member name used to store - * the new entry is not duplicated. + * exist. + * + * If the object has no entry for that name, then the member name used to + * store the new entry is not duplicated. * Example of use: - * \code - * Json::Value object; - * static const StaticString code("code"); - * object[code] = 1234; - * \endcode + * \code + * Json::Value object; + * static const StaticString code("code"); + * object[code] = 1234; + * \endcode */ Value& operator[](const StaticString& key); -#ifdef JSON_USE_CPPTL - /// Access an object value by name, create a null member if it does not exist. - Value& operator[](const CppTL::ConstString& key); - /// Access an object value by name, returns null if there is no member with - /// that name. - const Value& operator[](const CppTL::ConstString& key) const; -#endif /// Return the member named key if it exist, defaultValue otherwise. /// \note deep copy Value get(const char* key, const Value& defaultValue) const; /// Return the member named key if it exist, defaultValue otherwise. /// \note deep copy /// \note key may contain embedded nulls. - Value get(const char* begin, const char* end, const Value& defaultValue) const; + Value get(const char* begin, const char* end, + const Value& defaultValue) const; /// Return the member named key if it exist, defaultValue otherwise. /// \note deep copy /// \param key may contain embedded nulls. - Value get(const JSONCPP_STRING& key, const Value& defaultValue) const; -#ifdef JSON_USE_CPPTL - /// Return the member named key if it exist, defaultValue otherwise. - /// \note deep copy - Value get(const CppTL::ConstString& key, const Value& defaultValue) const; -#endif + Value get(const String& key, const Value& defaultValue) const; /// Most general and efficient version of isMember()const, get()const, /// and operator[]const /// \note As stated elsewhere, behavior is undefined if (end-begin) >= 2^30 @@ -512,53 +517,44 @@ Json::Value obj_value(Json::objectValue); // {} /// Most general and efficient version of object-mutators. /// \note As stated elsewhere, behavior is undefined if (end-begin) >= 2^30 /// \return non-zero, but JSON_ASSERT if this is neither object nor nullValue. - Value const* demand(char const* begin, char const* end); + Value* demand(char const* begin, char const* end); /// \brief Remove and return the named member. /// /// Do nothing if it did not exist. - /// \return the removed Value, or null. /// \pre type() is objectValue or nullValue /// \post type() is unchanged - /// deprecated - JSONCPP_DEPRECATED("") - Value removeMember(const char* key); + void removeMember(const char* key); /// Same as removeMember(const char*) /// \param key may contain embedded nulls. - /// deprecated - JSONCPP_DEPRECATED("") - Value removeMember(const JSONCPP_STRING& key); + void removeMember(const String& key); /// Same as removeMember(const char* begin, const char* end, Value* removed), /// but 'key' is null-terminated. bool removeMember(const char* key, Value* removed); /** \brief Remove the named map member. - - Update 'removed' iff removed. - \param key may contain embedded nulls. - \return true iff removed (no exceptions) - */ - bool removeMember(JSONCPP_STRING const& key, Value* removed); - /// Same as removeMember(JSONCPP_STRING const& key, Value* removed) + * + * Update 'removed' iff removed. + * \param key may contain embedded nulls. + * \return true iff removed (no exceptions) + */ + bool removeMember(String const& key, Value* removed); + /// Same as removeMember(String const& key, Value* removed) bool removeMember(const char* begin, const char* end, Value* removed); /** \brief Remove the indexed array element. - - O(n) expensive operations. - Update 'removed' iff removed. - \return true iff removed (no exceptions) - */ - bool removeIndex(ArrayIndex i, Value* removed); + * + * O(n) expensive operations. + * Update 'removed' iff removed. + * \return true if removed (no exceptions) + */ + bool removeIndex(ArrayIndex index, Value* removed); /// Return true if the object has a member named key. /// \note 'key' must be null-terminated. bool isMember(const char* key) const; /// Return true if the object has a member named key. /// \param key may contain embedded nulls. - bool isMember(const JSONCPP_STRING& key) const; - /// Same as isMember(JSONCPP_STRING const& key)const + bool isMember(const String& key) const; + /// Same as isMember(String const& key)const bool isMember(const char* begin, const char* end) const; -#ifdef JSON_USE_CPPTL - /// Return true if the object has a member named key. - bool isMember(const CppTL::ConstString& key) const; -#endif /// \brief Return a list of the member names. /// @@ -567,23 +563,22 @@ Json::Value obj_value(Json::objectValue); // {} /// \post if type() was nullValue, it remains nullValue Members getMemberNames() const; - //# ifdef JSON_USE_CPPTL - // EnumMemberNames enumMemberNames() const; - // EnumValues enumValues() const; - //# endif - /// deprecated Always pass len. - JSONCPP_DEPRECATED("Use setComment(JSONCPP_STRING const&) instead.") - void setComment(const char* comment, CommentPlacement placement); + JSONCPP_DEPRECATED("Use setComment(String const&) instead.") + void setComment(const char* comment, CommentPlacement placement) { + setComment(String(comment, strlen(comment)), placement); + } /// Comments must be //... or /* ... */ - void setComment(const char* comment, size_t len, CommentPlacement placement); + void setComment(const char* comment, size_t len, CommentPlacement placement) { + setComment(String(comment, len), placement); + } /// Comments must be //... or /* ... */ - void setComment(const JSONCPP_STRING& comment, CommentPlacement placement); + void setComment(String comment, CommentPlacement placement); bool hasComment(CommentPlacement placement) const; /// Include delimiters and embedded newlines. - JSONCPP_STRING getComment(CommentPlacement placement) const; + String getComment(CommentPlacement placement) const; - JSONCPP_STRING toStyledString() const; + String toStyledString() const; const_iterator begin() const; const_iterator end() const; @@ -599,20 +594,20 @@ Json::Value obj_value(Json::objectValue); // {} ptrdiff_t getOffsetLimit() const; private: + void setType(ValueType v) { + bits_.value_type_ = static_cast<unsigned char>(v); + } + bool isAllocated() const { return bits_.allocated_; } + void setIsAllocated(bool v) { bits_.allocated_ = v; } + void initBasic(ValueType type, bool allocated = false); + void dupPayload(const Value& other); + void releasePayload(); + void dupMeta(const Value& other); Value& resolveReference(const char* key); Value& resolveReference(const char* key, const char* end); - struct CommentInfo { - CommentInfo(); - ~CommentInfo(); - - void setComment(const char* text, size_t len); - - char* comment_; - }; - // struct MemberNamesTransform //{ // typedef const char *result_type; @@ -627,13 +622,33 @@ private: LargestUInt uint_; double real_; bool bool_; - char* string_; // actually ptr to unsigned, followed by str, unless !allocated_ + char* string_; // if allocated_, ptr to { unsigned, char[] }. ObjectValues* map_; } value_; - ValueType type_ : 8; - unsigned int allocated_ : 1; // Notes: if declared as bool, bitfield is useless. - // If not allocated_, string_ must be null-terminated. - CommentInfo* comments_; + + struct { + // Really a ValueType, but types should agree for bitfield packing. + unsigned int value_type_ : 8; + // Unless allocated_, string_ must be null-terminated. + unsigned int allocated_ : 1; + } bits_; + + class Comments { + public: + Comments() = default; + Comments(const Comments& that); + Comments(Comments&& that); + Comments& operator=(const Comments& that); + Comments& operator=(Comments&& that); + bool has(CommentPlacement slot) const; + String get(CommentPlacement slot) const; + void set(CommentPlacement slot, String comment); + + private: + using Array = std::array<String, numberOfCommentPlacement>; + std::unique_ptr<Array> ptr_; + }; + Comments comments_; // [start, limit) byte offsets in the source JSON text from which this Value // was extracted. @@ -641,6 +656,36 @@ private: ptrdiff_t limit_; }; +template <> inline bool Value::as<bool>() const { return asBool(); } +template <> inline bool Value::is<bool>() const { return isBool(); } + +template <> inline Int Value::as<Int>() const { return asInt(); } +template <> inline bool Value::is<Int>() const { return isInt(); } + +template <> inline UInt Value::as<UInt>() const { return asUInt(); } +template <> inline bool Value::is<UInt>() const { return isUInt(); } + +#if defined(JSON_HAS_INT64) +template <> inline Int64 Value::as<Int64>() const { return asInt64(); } +template <> inline bool Value::is<Int64>() const { return isInt64(); } + +template <> inline UInt64 Value::as<UInt64>() const { return asUInt64(); } +template <> inline bool Value::is<UInt64>() const { return isUInt64(); } +#endif + +template <> inline double Value::as<double>() const { return asDouble(); } +template <> inline bool Value::is<double>() const { return isDouble(); } + +template <> inline String Value::as<String>() const { return asString(); } +template <> inline bool Value::is<String>() const { return isString(); } + +/// These `as` specializations are type conversions, and do not have a +/// corresponding `is`. +template <> inline float Value::as<float>() const { return asFloat(); } +template <> inline const char* Value::as<const char*>() const { + return asCString(); +} + /** \brief Experimental and untested: represents an element of the "path" to * access a node. */ @@ -651,17 +696,13 @@ public: PathArgument(); PathArgument(ArrayIndex index); PathArgument(const char* key); - PathArgument(const JSONCPP_STRING& key); + PathArgument(String key); private: - enum Kind { - kindNone = 0, - kindIndex, - kindKey - }; - JSONCPP_STRING key_; - ArrayIndex index_; - Kind kind_; + enum Kind { kindNone = 0, kindIndex, kindKey }; + String key_; + ArrayIndex index_{}; + Kind kind_{kindNone}; }; /** \brief Experimental and untested: represents a "path" to access a node. @@ -673,12 +714,11 @@ private: * - ".name1.name2.name3" * - ".[0][1][2].name1[3]" * - ".%" => member name is provided as parameter - * - ".[%]" => index is provied as parameter + * - ".[%]" => index is provided as parameter */ class JSON_API Path { public: - Path(const JSONCPP_STRING& path, - const PathArgument& a1 = PathArgument(), + Path(const String& path, const PathArgument& a1 = PathArgument(), const PathArgument& a2 = PathArgument(), const PathArgument& a3 = PathArgument(), const PathArgument& a4 = PathArgument(), @@ -691,15 +731,13 @@ public: Value& make(Value& root) const; private: - typedef std::vector<const PathArgument*> InArgs; - typedef std::vector<PathArgument> Args; + using InArgs = std::vector<const PathArgument*>; + using Args = std::vector<PathArgument>; - void makePath(const JSONCPP_STRING& path, const InArgs& in); - void addPathInArg(const JSONCPP_STRING& path, - const InArgs& in, - InArgs::const_iterator& itInArg, - PathArgument::Kind kind); - void invalidPath(const JSONCPP_STRING& path, int location); + void makePath(const String& path, const InArgs& in); + void addPathInArg(const String& path, const InArgs& in, + InArgs::const_iterator& itInArg, PathArgument::Kind kind); + static void invalidPath(const String& path, int location); Args args_; }; @@ -709,10 +747,10 @@ private: */ class JSON_API ValueIteratorBase { public: - typedef std::bidirectional_iterator_tag iterator_category; - typedef unsigned int size_t; - typedef int difference_type; - typedef ValueIteratorBase SelfType; + using iterator_category = std::bidirectional_iterator_tag; + using size_t = unsigned int; + using difference_type = int; + using SelfType = ValueIteratorBase; bool operator==(const SelfType& other) const { return isEqual(other); } @@ -726,17 +764,19 @@ public: /// Value. Value key() const; - /// Return the index of the referenced Value, or -1 if it is not an arrayValue. + /// Return the index of the referenced Value, or -1 if it is not an + /// arrayValue. UInt index() const; /// Return the member name of the referenced Value, or "" if it is not an /// objectValue. /// \note Avoid `c_str()` on result, as embedded zeroes are possible. - JSONCPP_STRING name() const; + String name() const; /// Return the member name of the referenced Value. "" if it is not an /// objectValue. - /// deprecated This cannot be used for UTF-8 strings, since there can be embedded nulls. + /// deprecated This cannot be used for UTF-8 strings, since there can be + /// embedded nulls. JSONCPP_DEPRECATED("Use `key = name();` instead.") char const* memberName() const; /// Return the member name of the referenced Value, or NULL if it is not an @@ -745,7 +785,14 @@ public: char const* memberName(char const** end) const; protected: - Value& deref() const; + /*! Internal utility functions to assist with implementing + * other iterator functions. The const and non-const versions + * of the "deref" protected methods expose the protected + * current_ member variable in a way that can often be + * optimized away by the compiler. + */ + const Value& deref() const; + Value& deref(); void increment(); @@ -760,7 +807,7 @@ protected: private: Value::ObjectValues::iterator current_; // Indicates that iterator is for a null value. - bool isNull_; + bool isNull_{true}; public: // For some reason, BORLAND needs these at the end, rather @@ -776,20 +823,21 @@ class JSON_API ValueConstIterator : public ValueIteratorBase { friend class Value; public: - typedef const Value value_type; - //typedef unsigned int size_t; - //typedef int difference_type; - typedef const Value& reference; - typedef const Value* pointer; - typedef ValueConstIterator SelfType; + using value_type = const Value; + // typedef unsigned int size_t; + // typedef int difference_type; + using reference = const Value&; + using pointer = const Value*; + using SelfType = ValueConstIterator; ValueConstIterator(); ValueConstIterator(ValueIterator const& other); private: -/*! internal Use by Value to create an iterator. - */ + /*! internal Use by Value to create an iterator. + */ explicit ValueConstIterator(const Value::ObjectValues::iterator& current); + public: SelfType& operator=(const ValueIteratorBase& other); @@ -826,21 +874,22 @@ class JSON_API ValueIterator : public ValueIteratorBase { friend class Value; public: - typedef Value value_type; - typedef unsigned int size_t; - typedef int difference_type; - typedef Value& reference; - typedef Value* pointer; - typedef ValueIterator SelfType; + using value_type = Value; + using size_t = unsigned int; + using difference_type = int; + using reference = Value&; + using pointer = Value*; + using SelfType = ValueIterator; ValueIterator(); explicit ValueIterator(const ValueConstIterator& other); ValueIterator(const ValueIterator& other); private: -/*! internal Use by Value to create an iterator. - */ + /*! internal Use by Value to create an iterator. + */ explicit ValueIterator(const Value::ObjectValues::iterator& current); + public: SelfType& operator=(const SelfType& other); @@ -866,19 +915,18 @@ public: return *this; } - reference operator*() const { return deref(); } - - pointer operator->() const { return &deref(); } + /*! The return value of non-const iterators can be + * changed, so the these functions are not const + * because the returned references/pointers can be used + * to change state of the base class. + */ + reference operator*() { return deref(); } + pointer operator->() { return &deref(); } }; -} // namespace Json +inline void swap(Value& a, Value& b) { a.swap(b); } - -namespace std { -/// Specialize std::swap() for Json::Value. -template<> -inline void swap(Json::Value& a, Json::Value& b) { a.swap(b); } -} +} // namespace Json #if !defined(__SUNPRO_CC) #pragma pack(pop) @@ -888,4 +936,4 @@ inline void swap(Json::Value& a, Json::Value& b) { a.swap(b); } #pragma warning(pop) #endif // if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING) -#endif // CPPTL_JSON_H_INCLUDED +#endif // JSON_H_INCLUDED diff --git a/Utilities/cmjsoncpp/include/json/version.h b/Utilities/cmjsoncpp/include/json/version.h index d953961..5b9783d 100644 --- a/Utilities/cmjsoncpp/include/json/version.h +++ b/Utilities/cmjsoncpp/include/json/version.h @@ -1,14 +1,22 @@ -// DO NOT EDIT. This file (and "version") is generated by CMake. -// Run CMake configure step to update it. #ifndef JSON_VERSION_H_INCLUDED -# define JSON_VERSION_H_INCLUDED +#define JSON_VERSION_H_INCLUDED -# define JSONCPP_VERSION_STRING "1.8.2" -# define JSONCPP_VERSION_MAJOR 1 -# define JSONCPP_VERSION_MINOR 8 -# define JSONCPP_VERSION_PATCH 2 -# define JSONCPP_VERSION_QUALIFIER -# define JSONCPP_VERSION_HEXA ((JSONCPP_VERSION_MAJOR << 24) | (JSONCPP_VERSION_MINOR << 16) | (JSONCPP_VERSION_PATCH << 8)) +// Note: version must be updated in three places when doing a release. This +// annoying process ensures that amalgamate, CMake, and meson all report the +// correct version. +// 1. /meson.build +// 2. /include/json/version.h +// 3. /CMakeLists.txt +// IMPORTANT: also update the SOVERSION!! + +#define JSONCPP_VERSION_STRING "1.9.4" +#define JSONCPP_VERSION_MAJOR 1 +#define JSONCPP_VERSION_MINOR 9 +#define JSONCPP_VERSION_PATCH 3 +#define JSONCPP_VERSION_QUALIFIER +#define JSONCPP_VERSION_HEXA \ + ((JSONCPP_VERSION_MAJOR << 24) | (JSONCPP_VERSION_MINOR << 16) | \ + (JSONCPP_VERSION_PATCH << 8)) #ifdef JSONCPP_USING_SECURE_MEMORY #undef JSONCPP_USING_SECURE_MEMORY diff --git a/Utilities/cmjsoncpp/include/json/writer.h b/Utilities/cmjsoncpp/include/json/writer.h index d3ae62b..cc6b78c 100644 --- a/Utilities/cmjsoncpp/include/json/writer.h +++ b/Utilities/cmjsoncpp/include/json/writer.h @@ -9,14 +9,13 @@ #if !defined(JSON_IS_AMALGAMATION) #include "value.h" #endif // if !defined(JSON_IS_AMALGAMATION) -#include <iosfwd> -#include <vector> -#include <string> #include <ostream> +#include <string> +#include <vector> // Disable warning C4251: <data member>: <type> needs to have dll-interface to // be used by... -#if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING) +#if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING) && defined(_MSC_VER) #pragma warning(push) #pragma warning(disable : 4251) #endif // if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING) @@ -30,31 +29,31 @@ namespace Json { class Value; /** - -Usage: -\code - using namespace Json; - void writeToStdout(StreamWriter::Factory const& factory, Value const& value) { - std::unique_ptr<StreamWriter> const writer( - factory.newStreamWriter()); - writer->write(value, &std::cout); - std::cout << std::endl; // add lf and flush - } -\endcode -*/ + * + * Usage: + * \code + * using namespace Json; + * void writeToStdout(StreamWriter::Factory const& factory, Value const& value) + * { std::unique_ptr<StreamWriter> const writer( factory.newStreamWriter()); + * writer->write(value, &std::cout); + * std::cout << std::endl; // add lf and flush + * } + * \endcode + */ class JSON_API StreamWriter { protected: - JSONCPP_OSTREAM* sout_; // not owned; will not delete + OStream* sout_; // not owned; will not delete public: StreamWriter(); virtual ~StreamWriter(); /** Write Value into document as configured in sub-class. - Do not take ownership of sout, but maintain a reference during function. - \pre sout != NULL - \return zero on success (For now, we always return zero, so check the stream instead.) - \throw std::exception possibly, depending on configuration + * Do not take ownership of sout, but maintain a reference during function. + * \pre sout != NULL + * \return zero on success (For now, we always return zero, so check the + * stream instead.) \throw std::exception possibly, depending on + * configuration */ - virtual int write(Value const& root, JSONCPP_OSTREAM* sout) = 0; + virtual int write(Value const& root, OStream* sout) = 0; /** \brief A simple abstract factory. */ @@ -65,64 +64,69 @@ public: * \throw std::exception if something goes wrong (e.g. invalid settings) */ virtual StreamWriter* newStreamWriter() const = 0; - }; // Factory -}; // StreamWriter + }; // Factory +}; // StreamWriter /** \brief Write into stringstream, then return string, for convenience. * A StreamWriter will be created from the factory, used, and then deleted. */ -JSONCPP_STRING JSON_API writeString(StreamWriter::Factory const& factory, Value const& root); - +String JSON_API writeString(StreamWriter::Factory const& factory, + Value const& root); /** \brief Build a StreamWriter implementation. -Usage: -\code - using namespace Json; - Value value = ...; - StreamWriterBuilder builder; - builder["commentStyle"] = "None"; - builder["indentation"] = " "; // or whatever you like - std::unique_ptr<Json::StreamWriter> writer( - builder.newStreamWriter()); - writer->write(value, &std::cout); - std::cout << std::endl; // add lf and flush -\endcode +* Usage: +* \code +* using namespace Json; +* Value value = ...; +* StreamWriterBuilder builder; +* builder["commentStyle"] = "None"; +* builder["indentation"] = " "; // or whatever you like +* std::unique_ptr<Json::StreamWriter> writer( +* builder.newStreamWriter()); +* writer->write(value, &std::cout); +* std::cout << std::endl; // add lf and flush +* \endcode */ class JSON_API StreamWriterBuilder : public StreamWriter::Factory { public: // Note: We use a Json::Value so that we can add data-members to this class // without a major version bump. /** Configuration of this builder. - Available settings (case-sensitive): - - "commentStyle": "None" or "All" - - "indentation": "<anything>" - - "enableYAMLCompatibility": false or true - - slightly change the whitespace around colons - - "dropNullPlaceholders": false or true - - Drop the "null" string from the writer's output for nullValues. - Strictly speaking, this is not valid JSON. But when the output is being - fed to a browser's Javascript, it makes for smaller output and the - browser can handle the output just fine. - - "useSpecialFloats": false or true - - If true, outputs non-finite floating point values in the following way: - NaN values as "NaN", positive infinity as "Infinity", and negative infinity - as "-Infinity". - - You can examine 'settings_` yourself - to see the defaults. You can also write and read them just like any - JSON Value. - \sa setDefaults() - */ + * Available settings (case-sensitive): + * - "commentStyle": "None" or "All" + * - "indentation": "<anything>". + * - Setting this to an empty string also omits newline characters. + * - "enableYAMLCompatibility": false or true + * - slightly change the whitespace around colons + * - "dropNullPlaceholders": false or true + * - Drop the "null" string from the writer's output for nullValues. + * Strictly speaking, this is not valid JSON. But when the output is being + * fed to a browser's JavaScript, it makes for smaller output and the + * browser can handle the output just fine. + * - "useSpecialFloats": false or true + * - If true, outputs non-finite floating point values in the following way: + * NaN values as "NaN", positive infinity as "Infinity", and negative + * infinity as "-Infinity". + * - "precision": int + * - Number of precision digits for formatting of real values. + * - "precisionType": "significant"(default) or "decimal" + * - Type of precision for formatting of real values. + + * You can examine 'settings_` yourself + * to see the defaults. You can also write and read them just like any + * JSON Value. + * \sa setDefaults() + */ Json::Value settings_; StreamWriterBuilder(); - ~StreamWriterBuilder() JSONCPP_OVERRIDE; + ~StreamWriterBuilder() override; /** * \throw std::exception if something goes wrong (e.g. invalid settings) */ - StreamWriter* newStreamWriter() const JSONCPP_OVERRIDE; + StreamWriter* newStreamWriter() const override; /** \return true if 'settings' are legal and consistent; * otherwise, indicate bad settings via 'invalid'. @@ -130,7 +134,7 @@ public: bool validate(Json::Value* invalid) const; /** A simple way to update a specific setting. */ - Value& operator[](JSONCPP_STRING key); + Value& operator[](const String& key); /** Called by ctor, but you can use this to reset settings_. * \pre 'settings' != NULL (but Json::null is fine) @@ -147,7 +151,7 @@ class JSONCPP_DEPRECATED("Use StreamWriter instead") JSON_API Writer { public: virtual ~Writer(); - virtual JSONCPP_STRING write(const Value& root) = 0; + virtual String write(const Value& root) = 0; }; /** \brief Outputs a Value in <a HREF="http://www.json.org">JSON</a> format @@ -155,21 +159,25 @@ public: * * The JSON document is written in a single line. It is not intended for 'human' *consumption, - * but may be usefull to support feature such as RPC where bandwith is limited. + * but may be useful to support feature such as RPC where bandwidth is limited. * \sa Reader, Value * deprecated Use StreamWriterBuilder. */ -class JSONCPP_DEPRECATED("Use StreamWriterBuilder instead") JSON_API FastWriter : public Writer { - +#if defined(_MSC_VER) +#pragma warning(push) +#pragma warning(disable : 4996) // Deriving from deprecated class +#endif +class JSONCPP_DEPRECATED("Use StreamWriterBuilder instead") JSON_API FastWriter + : public Writer { public: FastWriter(); - ~FastWriter() JSONCPP_OVERRIDE {} + ~FastWriter() override = default; void enableYAMLCompatibility(); /** \brief Drop the "null" string from the writer's output for nullValues. * Strictly speaking, this is not valid JSON. But when the output is being - * fed to a browser's Javascript, it makes for smaller output and the + * fed to a browser's JavaScript, it makes for smaller output and the * browser can handle the output just fine. */ void dropNullPlaceholders(); @@ -177,16 +185,19 @@ public: void omitEndingLineFeed(); public: // overridden from Writer - JSONCPP_STRING write(const Value& root) JSONCPP_OVERRIDE; + String write(const Value& root) override; private: void writeValue(const Value& value); - JSONCPP_STRING document_; - bool yamlCompatiblityEnabled_; - bool dropNullPlaceholders_; - bool omitEndingLineFeed_; + String document_; + bool yamlCompatibilityEnabled_{false}; + bool dropNullPlaceholders_{false}; + bool omitEndingLineFeed_{false}; }; +#if defined(_MSC_VER) +#pragma warning(pop) +#endif /** \brief Writes a Value in <a HREF="http://www.json.org">JSON</a> format in a *human friendly way. @@ -212,41 +223,49 @@ private: * \sa Reader, Value, Value::setComment() * deprecated Use StreamWriterBuilder. */ -class JSONCPP_DEPRECATED("Use StreamWriterBuilder instead") JSON_API StyledWriter : public Writer { +#if defined(_MSC_VER) +#pragma warning(push) +#pragma warning(disable : 4996) // Deriving from deprecated class +#endif +class JSONCPP_DEPRECATED("Use StreamWriterBuilder instead") JSON_API + StyledWriter : public Writer { public: StyledWriter(); - ~StyledWriter() JSONCPP_OVERRIDE {} + ~StyledWriter() override = default; public: // overridden from Writer /** \brief Serialize a Value in <a HREF="http://www.json.org">JSON</a> format. * \param root Value to serialize. * \return String containing the JSON document that represents the root value. */ - JSONCPP_STRING write(const Value& root) JSONCPP_OVERRIDE; + String write(const Value& root) override; private: void writeValue(const Value& value); void writeArrayValue(const Value& value); - bool isMultineArray(const Value& value); - void pushValue(const JSONCPP_STRING& value); + bool isMultilineArray(const Value& value); + void pushValue(const String& value); void writeIndent(); - void writeWithIndent(const JSONCPP_STRING& value); + void writeWithIndent(const String& value); void indent(); void unindent(); void writeCommentBeforeValue(const Value& root); void writeCommentAfterValueOnSameLine(const Value& root); - bool hasCommentForValue(const Value& value); - static JSONCPP_STRING normalizeEOL(const JSONCPP_STRING& text); + static bool hasCommentForValue(const Value& value); + static String normalizeEOL(const String& text); - typedef std::vector<JSONCPP_STRING> ChildValues; + using ChildValues = std::vector<String>; ChildValues childValues_; - JSONCPP_STRING document_; - JSONCPP_STRING indentString_; - unsigned int rightMargin_; - unsigned int indentSize_; - bool addChildValues_; + String document_; + String indentString_; + unsigned int rightMargin_{74}; + unsigned int indentSize_{3}; + bool addChildValues_{false}; }; +#if defined(_MSC_VER) +#pragma warning(pop) +#endif /** \brief Writes a Value in <a HREF="http://www.json.org">JSON</a> format in a human friendly way, @@ -273,13 +292,18 @@ private: * \sa Reader, Value, Value::setComment() * deprecated Use StreamWriterBuilder. */ -class JSONCPP_DEPRECATED("Use StreamWriterBuilder instead") JSON_API StyledStreamWriter { +#if defined(_MSC_VER) +#pragma warning(push) +#pragma warning(disable : 4996) // Deriving from deprecated class +#endif +class JSONCPP_DEPRECATED("Use StreamWriterBuilder instead") JSON_API + StyledStreamWriter { public: -/** - * \param indentation Each level will be indented by this amount extra. - */ - StyledStreamWriter(JSONCPP_STRING indentation = "\t"); - ~StyledStreamWriter() {} + /** + * \param indentation Each level will be indented by this amount extra. + */ + StyledStreamWriter(String indentation = "\t"); + ~StyledStreamWriter() = default; public: /** \brief Serialize a Value in <a HREF="http://www.json.org">JSON</a> format. @@ -288,46 +312,51 @@ public: * \note There is no point in deriving from Writer, since write() should not * return a value. */ - void write(JSONCPP_OSTREAM& out, const Value& root); + void write(OStream& out, const Value& root); private: void writeValue(const Value& value); void writeArrayValue(const Value& value); - bool isMultineArray(const Value& value); - void pushValue(const JSONCPP_STRING& value); + bool isMultilineArray(const Value& value); + void pushValue(const String& value); void writeIndent(); - void writeWithIndent(const JSONCPP_STRING& value); + void writeWithIndent(const String& value); void indent(); void unindent(); void writeCommentBeforeValue(const Value& root); void writeCommentAfterValueOnSameLine(const Value& root); - bool hasCommentForValue(const Value& value); - static JSONCPP_STRING normalizeEOL(const JSONCPP_STRING& text); + static bool hasCommentForValue(const Value& value); + static String normalizeEOL(const String& text); - typedef std::vector<JSONCPP_STRING> ChildValues; + using ChildValues = std::vector<String>; ChildValues childValues_; - JSONCPP_OSTREAM* document_; - JSONCPP_STRING indentString_; - unsigned int rightMargin_; - JSONCPP_STRING indentation_; + OStream* document_; + String indentString_; + unsigned int rightMargin_{74}; + String indentation_; bool addChildValues_ : 1; bool indented_ : 1; }; +#if defined(_MSC_VER) +#pragma warning(pop) +#endif #if defined(JSON_HAS_INT64) -JSONCPP_STRING JSON_API valueToString(Int value); -JSONCPP_STRING JSON_API valueToString(UInt value); +String JSON_API valueToString(Int value); +String JSON_API valueToString(UInt value); #endif // if defined(JSON_HAS_INT64) -JSONCPP_STRING JSON_API valueToString(LargestInt value); -JSONCPP_STRING JSON_API valueToString(LargestUInt value); -JSONCPP_STRING JSON_API valueToString(double value); -JSONCPP_STRING JSON_API valueToString(bool value); -JSONCPP_STRING JSON_API valueToQuotedString(const char* value); +String JSON_API valueToString(LargestInt value); +String JSON_API valueToString(LargestUInt value); +String JSON_API valueToString( + double value, unsigned int precision = Value::defaultRealPrecision, + PrecisionType precisionType = PrecisionType::significantDigits); +String JSON_API valueToString(bool value); +String JSON_API valueToQuotedString(const char* value); /// \brief Output using the StyledStreamWriter. /// \see Json::operator>>() -JSON_API JSONCPP_OSTREAM& operator<<(JSONCPP_OSTREAM&, const Value& root); +JSON_API OStream& operator<<(OStream&, const Value& root); } // namespace Json diff --git a/Utilities/cmjsoncpp/src/lib_json/json_reader.cpp b/Utilities/cmjsoncpp/src/lib_json/json_reader.cpp index 8291cc6..e6caf40 100644 --- a/Utilities/cmjsoncpp/src/lib_json/json_reader.cpp +++ b/Utilities/cmjsoncpp/src/lib_json/json_reader.cpp @@ -5,69 +5,65 @@ // See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE #if !defined(JSON_IS_AMALGAMATION) +#include "json_tool.h" #include <json/assertions.h> #include <json/reader.h> #include <json/value.h> -#include "json_tool.h" #endif // if !defined(JSON_IS_AMALGAMATION) -#include <utility> -#include <stdio.h> -#include <assert.h> -#include <string.h> +#include <algorithm> +#include <cassert> +#include <cstring> +#include <iostream> #include <istream> -#include <sstream> +#include <limits> #include <memory> #include <set> -#include <limits> +#include <sstream> +#include <utility> -#if defined(_MSC_VER) -#if !defined(WINCE) && defined(__STDC_SECURE_LIB__) && _MSC_VER >= 1500 // VC++ 9.0 and above -#define snprintf sprintf_s -#elif _MSC_VER >= 1900 // VC++ 14.0 and above -#define snprintf std::snprintf -#else -#define snprintf _snprintf -#endif -#elif defined(__ANDROID__) || defined(__QNXNTO__) -#define snprintf snprintf -#elif __cplusplus >= 201103L -#if !defined(__MINGW32__) && !defined(__CYGWIN__) -#define snprintf std::snprintf -#endif -#endif +#include <cstdio> +#if __cplusplus >= 201103L -#if defined(__QNXNTO__) +#if !defined(sscanf) #define sscanf std::sscanf #endif -#if defined(_MSC_VER) && _MSC_VER >= 1400 // VC++ 8.0 +#endif //__cplusplus + +#if defined(_MSC_VER) +#if !defined(_CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES) +#define _CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES 1 +#endif //_CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES +#endif //_MSC_VER + +#if defined(_MSC_VER) // Disable warning about strdup being deprecated. #pragma warning(disable : 4996) #endif -// Define JSONCPP_DEPRECATED_STACK_LIMIT as an appropriate integer at compile time to change the stack limit +// Define JSONCPP_DEPRECATED_STACK_LIMIT as an appropriate integer at compile +// time to change the stack limit #if !defined(JSONCPP_DEPRECATED_STACK_LIMIT) #define JSONCPP_DEPRECATED_STACK_LIMIT 1000 #endif -static size_t const stackLimit_g = JSONCPP_DEPRECATED_STACK_LIMIT; // see readValue() +static size_t const stackLimit_g = + JSONCPP_DEPRECATED_STACK_LIMIT; // see readValue() namespace Json { #if __cplusplus >= 201103L || (defined(_CPPLIB_VER) && _CPPLIB_VER >= 520) -typedef std::unique_ptr<CharReader> CharReaderPtr; +using CharReaderPtr = std::unique_ptr<CharReader>; #else -typedef std::auto_ptr<CharReader> CharReaderPtr; +using CharReaderPtr = std::auto_ptr<CharReader>; #endif // Implementation of class Features // //////////////////////////////// -Features::Features() - : allowComments_(true), strictRoot_(false), - allowDroppedNullPlaceholders_(false), allowNumericKeys_(false) {} +Features::Features() = default; -Features Features::all() { return Features(); } +Features Features::all() { return {}; } Features Features::strictMode() { Features features; @@ -82,49 +78,38 @@ Features Features::strictMode() { // //////////////////////////////// bool Reader::containsNewLine(Reader::Location begin, Reader::Location end) { - for (; begin < end; ++begin) - if (*begin == '\n' || *begin == '\r') - return true; - return false; + return std::any_of(begin, end, [](char b) { return b == '\n' || b == '\r'; }); } // Class Reader // ////////////////////////////////////////////////////////////////// -Reader::Reader() - : errors_(), document_(), begin_(), end_(), current_(), lastValueEnd_(), - lastValue_(), commentsBefore_(), features_(Features::all()), - collectComments_() {} +Reader::Reader() : features_(Features::all()) {} -Reader::Reader(const Features& features) - : errors_(), document_(), begin_(), end_(), current_(), lastValueEnd_(), - lastValue_(), commentsBefore_(), features_(features), collectComments_() { -} +Reader::Reader(const Features& features) : features_(features) {} -bool -Reader::parse(const std::string& document, Value& root, bool collectComments) { +bool Reader::parse(const std::string& document, Value& root, + bool collectComments) { document_.assign(document.begin(), document.end()); const char* begin = document_.c_str(); const char* end = begin + document_.length(); return parse(begin, end, root, collectComments); } -bool Reader::parse(std::istream& sin, Value& root, bool collectComments) { - // std::istream_iterator<char> begin(sin); +bool Reader::parse(std::istream& is, Value& root, bool collectComments) { + // std::istream_iterator<char> begin(is); // std::istream_iterator<char> end; // Those would allow streamed input from a file, if parse() were a // template function. - // Since JSONCPP_STRING is reference-counted, this at least does not + // Since String is reference-counted, this at least does not // create an extra copy. - JSONCPP_STRING doc; - std::getline(sin, doc, (char)EOF); + String doc; + std::getline(is, doc, static_cast<char> EOF); return parse(doc.data(), doc.data() + doc.size(), root, collectComments); } -bool Reader::parse(const char* beginDoc, - const char* endDoc, - Value& root, +bool Reader::parse(const char* beginDoc, const char* endDoc, Value& root, bool collectComments) { if (!features_.allowComments_) { collectComments = false; @@ -134,8 +119,8 @@ bool Reader::parse(const char* beginDoc, end_ = endDoc; collectComments_ = collectComments; current_ = begin_; - lastValueEnd_ = 0; - lastValue_ = 0; + lastValueEnd_ = nullptr; + lastValue_ = nullptr; commentsBefore_.clear(); errors_.clear(); while (!nodes_.empty()) @@ -165,9 +150,11 @@ bool Reader::parse(const char* beginDoc, bool Reader::readValue() { // readValue() may call itself only if it calls readObject() or ReadArray(). - // These methods execute nodes_.push() just before and nodes_.pop)() just after calling readValue(). - // parse() executes one nodes_.push(), so > instead of >=. - if (nodes_.size() > stackLimit_g) throwRuntimeError("Exceeded stackLimit in readValue()."); + // These methods execute nodes_.push() just before and nodes_.pop)() just + // after calling readValue(). parse() executes one nodes_.push(), so > instead + // of >=. + if (nodes_.size() > stackLimit_g) + throwRuntimeError("Exceeded stackLimit in readValue()."); Token token; skipCommentTokens(token); @@ -193,30 +180,24 @@ bool Reader::readValue() { case tokenString: successful = decodeString(token); break; - case tokenTrue: - { + case tokenTrue: { Value v(true); currentValue().swapPayload(v); currentValue().setOffsetStart(token.start_ - begin_); currentValue().setOffsetLimit(token.end_ - begin_); - } - break; - case tokenFalse: - { + } break; + case tokenFalse: { Value v(false); currentValue().swapPayload(v); currentValue().setOffsetStart(token.start_ - begin_); currentValue().setOffsetLimit(token.end_ - begin_); - } - break; - case tokenNull: - { + } break; + case tokenNull: { Value v; currentValue().swapPayload(v); currentValue().setOffsetStart(token.start_ - begin_); currentValue().setOffsetLimit(token.end_ - begin_); - } - break; + } break; case tokenArraySeparator: case tokenObjectEnd: case tokenArrayEnd: @@ -322,7 +303,7 @@ bool Reader::readToken(Token& token) { if (!ok) token.type_ = tokenError; token.end_ = current_; - return true; + return ok; } void Reader::skipSpaces() { @@ -335,7 +316,7 @@ void Reader::skipSpaces() { } } -bool Reader::match(Location pattern, int patternLength) { +bool Reader::match(const Char* pattern, int patternLength) { if (end_ - current_ < patternLength) return false; int index = patternLength; @@ -369,16 +350,16 @@ bool Reader::readComment() { return true; } -JSONCPP_STRING Reader::normalizeEOL(Reader::Location begin, Reader::Location end) { - JSONCPP_STRING normalized; +String Reader::normalizeEOL(Reader::Location begin, Reader::Location end) { + String normalized; normalized.reserve(static_cast<size_t>(end - begin)); Reader::Location current = begin; while (current != end) { char c = *current++; if (c == '\r') { if (current != end && *current == '\n') - // convert dos EOL - ++current; + // convert dos EOL + ++current; // convert Mac EOL normalized += '\n'; } else { @@ -388,12 +369,12 @@ JSONCPP_STRING Reader::normalizeEOL(Reader::Location begin, Reader::Location end return normalized; } -void -Reader::addComment(Location begin, Location end, CommentPlacement placement) { +void Reader::addComment(Location begin, Location end, + CommentPlacement placement) { assert(collectComments_); - const JSONCPP_STRING& normalized = normalizeEOL(begin, end); + const String& normalized = normalizeEOL(begin, end); if (placement == commentAfterOnSameLine) { - assert(lastValue_ != 0); + assert(lastValue_ != nullptr); lastValue_->setComment(normalized, placement); } else { commentsBefore_ += normalized; @@ -426,7 +407,7 @@ bool Reader::readCppStyleComment() { } void Reader::readNumber() { - const char *p = current_; + Location p = current_; char c = '0'; // stopgap for already consumed character // integral part while (c >= '0' && c <= '9') @@ -459,12 +440,12 @@ bool Reader::readString() { return c == '"'; } -bool Reader::readObject(Token& tokenStart) { +bool Reader::readObject(Token& token) { Token tokenName; - JSONCPP_STRING name; + String name; Value init(objectValue); currentValue().swapPayload(init); - currentValue().setOffsetStart(tokenStart.start_ - begin_); + currentValue().setOffsetStart(token.start_ - begin_); while (readToken(tokenName)) { bool initialTokenOk = true; while (tokenName.type_ == tokenComment && initialTokenOk) @@ -481,15 +462,15 @@ bool Reader::readObject(Token& tokenStart) { Value numberName; if (!decodeNumber(tokenName, numberName)) return recoverFromError(tokenObjectEnd); - name = JSONCPP_STRING(numberName.asCString()); + name = numberName.asString(); } else { break; } Token colon; if (!readToken(colon) || colon.type_ != tokenMemberSeparator) { - return addErrorAndRecover( - "Missing ':' after object member name", colon, tokenObjectEnd); + return addErrorAndRecover("Missing ':' after object member name", colon, + tokenObjectEnd); } Value& value = currentValue()[name]; nodes_.push(&value); @@ -502,8 +483,8 @@ bool Reader::readObject(Token& tokenStart) { if (!readToken(comma) || (comma.type_ != tokenObjectEnd && comma.type_ != tokenArraySeparator && comma.type_ != tokenComment)) { - return addErrorAndRecover( - "Missing ',' or '}' in object declaration", comma, tokenObjectEnd); + return addErrorAndRecover("Missing ',' or '}' in object declaration", + comma, tokenObjectEnd); } bool finalizeTokenOk = true; while (comma.type_ == tokenComment && finalizeTokenOk) @@ -511,14 +492,14 @@ bool Reader::readObject(Token& tokenStart) { if (comma.type_ == tokenObjectEnd) return true; } - return addErrorAndRecover( - "Missing '}' or object member name", tokenName, tokenObjectEnd); + return addErrorAndRecover("Missing '}' or object member name", tokenName, + tokenObjectEnd); } -bool Reader::readArray(Token& tokenStart) { +bool Reader::readArray(Token& token) { Value init(arrayValue); currentValue().swapPayload(init); - currentValue().setOffsetStart(tokenStart.start_ - begin_); + currentValue().setOffsetStart(token.start_ - begin_); skipSpaces(); if (current_ != end_ && *current_ == ']') // empty array { @@ -535,19 +516,19 @@ bool Reader::readArray(Token& tokenStart) { if (!ok) // error already set return recoverFromError(tokenArrayEnd); - Token token; + Token currentToken; // Accept Comment after last item in the array. - ok = readToken(token); - while (token.type_ == tokenComment && ok) { - ok = readToken(token); + ok = readToken(currentToken); + while (currentToken.type_ == tokenComment && ok) { + ok = readToken(currentToken); } - bool badTokenType = - (token.type_ != tokenArraySeparator && token.type_ != tokenArrayEnd); + bool badTokenType = (currentToken.type_ != tokenArraySeparator && + currentToken.type_ != tokenArrayEnd); if (!ok || badTokenType) { - return addErrorAndRecover( - "Missing ',' or ']' in array declaration", token, tokenArrayEnd); + return addErrorAndRecover("Missing ',' or ']' in array declaration", + currentToken, tokenArrayEnd); } - if (token.type_ == tokenArrayEnd) + if (currentToken.type_ == tokenArrayEnd) break; } return true; @@ -571,7 +552,8 @@ bool Reader::decodeNumber(Token& token, Value& decoded) { bool isNegative = *current == '-'; if (isNegative) ++current; - // TODO: Help the compiler do the div and mod at compile time or get rid of them. + // TODO: Help the compiler do the div and mod at compile time or get rid of + // them. Value::LargestUInt maxIntegerValue = isNegative ? Value::LargestUInt(Value::maxLargestInt) + 1 : Value::maxLargestUInt; @@ -581,7 +563,7 @@ bool Reader::decodeNumber(Token& token, Value& decoded) { Char c = *current++; if (c < '0' || c > '9') return decodeDouble(token, decoded); - Value::UInt digit(static_cast<Value::UInt>(c - '0')); + auto digit(static_cast<Value::UInt>(c - '0')); if (value >= threshold) { // We've hit or exceeded the max value divided by 10 (rounded down). If // a) we've only just touched the limit, b) this is the last digit, and @@ -617,18 +599,17 @@ bool Reader::decodeDouble(Token& token) { bool Reader::decodeDouble(Token& token, Value& decoded) { double value = 0; - JSONCPP_STRING buffer(token.start_, token.end_); - JSONCPP_ISTRINGSTREAM is(buffer); + String buffer(token.start_, token.end_); + IStringStream is(buffer); if (!(is >> value)) - return addError("'" + JSONCPP_STRING(token.start_, token.end_) + - "' is not a number.", - token); + return addError( + "'" + String(token.start_, token.end_) + "' is not a number.", token); decoded = value; return true; } bool Reader::decodeString(Token& token) { - JSONCPP_STRING decoded_string; + String decoded_string; if (!decodeString(token, decoded_string)) return false; Value decoded(decoded_string); @@ -638,7 +619,7 @@ bool Reader::decodeString(Token& token) { return true; } -bool Reader::decodeString(Token& token, JSONCPP_STRING& decoded) { +bool Reader::decodeString(Token& token, String& decoded) { decoded.reserve(static_cast<size_t>(token.end_ - token.start_ - 2)); Location current = token.start_ + 1; // skip '"' Location end = token.end_ - 1; // do not include '"' @@ -646,7 +627,7 @@ bool Reader::decodeString(Token& token, JSONCPP_STRING& decoded) { Char c = *current++; if (c == '"') break; - else if (c == '\\') { + if (c == '\\') { if (current == end) return addError("Empty escape sequence in string", token, current); Char escape = *current++; @@ -691,10 +672,8 @@ bool Reader::decodeString(Token& token, JSONCPP_STRING& decoded) { return true; } -bool Reader::decodeUnicodeCodePoint(Token& token, - Location& current, - Location end, - unsigned int& unicode) { +bool Reader::decodeUnicodeCodePoint(Token& token, Location& current, + Location end, unsigned int& unicode) { if (!decodeUnicodeEscapeSequence(token, current, end, unicode)) return false; @@ -703,10 +682,9 @@ bool Reader::decodeUnicodeCodePoint(Token& token, if (end - current < 6) return addError( "additional six characters expected to parse unicode surrogate pair.", - token, - current); - unsigned int surrogatePair; + token, current); if (*(current++) == '\\' && *(current++) == 'u') { + unsigned int surrogatePair; if (decodeUnicodeEscapeSequence(token, current, end, surrogatePair)) { unicode = 0x10000 + ((unicode & 0x3FF) << 10) + (surrogatePair & 0x3FF); } else @@ -714,20 +692,17 @@ bool Reader::decodeUnicodeCodePoint(Token& token, } else return addError("expecting another \\u token to begin the second half of " "a unicode surrogate pair", - token, - current); + token, current); } return true; } -bool Reader::decodeUnicodeEscapeSequence(Token& token, - Location& current, +bool Reader::decodeUnicodeEscapeSequence(Token& token, Location& current, Location end, unsigned int& ret_unicode) { if (end - current < 4) return addError( - "Bad unicode escape sequence in string: four digits expected.", - token, + "Bad unicode escape sequence in string: four digits expected.", token, current); int unicode = 0; for (int index = 0; index < 4; ++index) { @@ -742,15 +717,13 @@ bool Reader::decodeUnicodeEscapeSequence(Token& token, else return addError( "Bad unicode escape sequence in string: hexadecimal digit expected.", - token, - current); + token, current); } ret_unicode = static_cast<unsigned int>(unicode); return true; } -bool -Reader::addError(const JSONCPP_STRING& message, Token& token, Location extra) { +bool Reader::addError(const String& message, Token& token, Location extra) { ErrorInfo info; info.token_ = token; info.message_ = message; @@ -772,8 +745,7 @@ bool Reader::recoverFromError(TokenType skipUntilToken) { return false; } -bool Reader::addErrorAndRecover(const JSONCPP_STRING& message, - Token& token, +bool Reader::addErrorAndRecover(const String& message, Token& token, TokenType skipUntilToken) { addError(message, token); return recoverFromError(skipUntilToken); @@ -787,8 +759,7 @@ Reader::Char Reader::getNextChar() { return *current_++; } -void Reader::getLocationLineAndColumn(Location location, - int& line, +void Reader::getLocationLineAndColumn(Location location, int& line, int& column) const { Location current = begin_; Location lastLineStart = current; @@ -810,25 +781,22 @@ void Reader::getLocationLineAndColumn(Location location, ++line; } -JSONCPP_STRING Reader::getLocationLineAndColumn(Location location) const { +String Reader::getLocationLineAndColumn(Location location) const { int line, column; getLocationLineAndColumn(location, line, column); char buffer[18 + 16 + 16 + 1]; - snprintf(buffer, sizeof(buffer), "Line %d, Column %d", line, column); + jsoncpp_snprintf(buffer, sizeof(buffer), "Line %d, Column %d", line, column); return buffer; } // Deprecated. Preserved for backward compatibility -JSONCPP_STRING Reader::getFormatedErrorMessages() const { +String Reader::getFormatedErrorMessages() const { return getFormattedErrorMessages(); } -JSONCPP_STRING Reader::getFormattedErrorMessages() const { - JSONCPP_STRING formattedMessage; - for (Errors::const_iterator itError = errors_.begin(); - itError != errors_.end(); - ++itError) { - const ErrorInfo& error = *itError; +String Reader::getFormattedErrorMessages() const { + String formattedMessage; + for (const auto& error : errors_) { formattedMessage += "* " + getLocationLineAndColumn(error.token_.start_) + "\n"; formattedMessage += " " + error.message_ + "\n"; @@ -841,10 +809,7 @@ JSONCPP_STRING Reader::getFormattedErrorMessages() const { std::vector<Reader::StructuredError> Reader::getStructuredErrors() const { std::vector<Reader::StructuredError> allErrors; - for (Errors::const_iterator itError = errors_.begin(); - itError != errors_.end(); - ++itError) { - const ErrorInfo& error = *itError; + for (const auto& error : errors_) { Reader::StructuredError structured; structured.offset_start = error.token_.start_ - begin_; structured.offset_limit = error.token_.end_ - begin_; @@ -854,28 +819,27 @@ std::vector<Reader::StructuredError> Reader::getStructuredErrors() const { return allErrors; } -bool Reader::pushError(const Value& value, const JSONCPP_STRING& message) { +bool Reader::pushError(const Value& value, const String& message) { ptrdiff_t const length = end_ - begin_; - if(value.getOffsetStart() > length - || value.getOffsetLimit() > length) + if (value.getOffsetStart() > length || value.getOffsetLimit() > length) return false; Token token; token.type_ = tokenError; token.start_ = begin_ + value.getOffsetStart(); - token.end_ = end_ + value.getOffsetLimit(); + token.end_ = begin_ + value.getOffsetLimit(); ErrorInfo info; info.token_ = token; info.message_ = message; - info.extra_ = 0; + info.extra_ = nullptr; errors_.push_back(info); return true; } -bool Reader::pushError(const Value& value, const JSONCPP_STRING& message, const Value& extra) { +bool Reader::pushError(const Value& value, const String& message, + const Value& extra) { ptrdiff_t const length = end_ - begin_; - if(value.getOffsetStart() > length - || value.getOffsetLimit() > length - || extra.getOffsetLimit() > length) + if (value.getOffsetStart() > length || value.getOffsetLimit() > length || + extra.getOffsetLimit() > length) return false; Token token; token.type_ = tokenError; @@ -889,15 +853,15 @@ bool Reader::pushError(const Value& value, const JSONCPP_STRING& message, const return true; } -bool Reader::good() const { - return !errors_.size(); -} +bool Reader::good() const { return errors_.empty(); } -// exact copy of Features +// Originally copied from the Features class (now deprecated), used internally +// for features implementation. class OurFeatures { public: static OurFeatures all(); bool allowComments_; + bool allowTrailingCommas_; bool strictRoot_; bool allowDroppedNullPlaceholders_; bool allowNumericKeys_; @@ -905,42 +869,36 @@ public: bool failIfExtra_; bool rejectDupKeys_; bool allowSpecialFloats_; - int stackLimit_; -}; // OurFeatures - -// exact copy of Implementation of class Features -// //////////////////////////////// + bool skipBom_; + size_t stackLimit_; +}; // OurFeatures -OurFeatures OurFeatures::all() { return OurFeatures(); } +OurFeatures OurFeatures::all() { return {}; } // Implementation of class Reader // //////////////////////////////// -// exact copy of Reader, renamed to OurReader +// Originally copied from the Reader class (now deprecated), used internally +// for implementing JSON reading. class OurReader { public: - typedef char Char; - typedef const Char* Location; + using Char = char; + using Location = const Char*; struct StructuredError { ptrdiff_t offset_start; ptrdiff_t offset_limit; - JSONCPP_STRING message; + String message; }; - OurReader(OurFeatures const& features); - bool parse(const char* beginDoc, - const char* endDoc, - Value& root, + explicit OurReader(OurFeatures const& features); + bool parse(const char* beginDoc, const char* endDoc, Value& root, bool collectComments = true); - JSONCPP_STRING getFormattedErrorMessages() const; + String getFormattedErrorMessages() const; std::vector<StructuredError> getStructuredErrors() const; - bool pushError(const Value& value, const JSONCPP_STRING& message); - bool pushError(const Value& value, const JSONCPP_STRING& message, const Value& extra); - bool good() const; private: - OurReader(OurReader const&); // no impl - void operator=(OurReader const&); // no impl + OurReader(OurReader const&); // no impl + void operator=(OurReader const&); // no impl enum TokenType { tokenEndOfStream = 0, @@ -972,17 +930,18 @@ private: class ErrorInfo { public: Token token_; - JSONCPP_STRING message_; + String message_; Location extra_; }; - typedef std::deque<ErrorInfo> Errors; + using Errors = std::deque<ErrorInfo>; bool readToken(Token& token); void skipSpaces(); - bool match(Location pattern, int patternLength); + void skipBom(bool skipBom); + bool match(const Char* pattern, int patternLength); bool readComment(); - bool readCStyleComment(); + bool readCStyleComment(bool* containsNewLineResult); bool readCppStyleComment(); bool readString(); bool readStringSingleQuote(); @@ -993,68 +952,57 @@ private: bool decodeNumber(Token& token); bool decodeNumber(Token& token, Value& decoded); bool decodeString(Token& token); - bool decodeString(Token& token, JSONCPP_STRING& decoded); + bool decodeString(Token& token, String& decoded); bool decodeDouble(Token& token); bool decodeDouble(Token& token, Value& decoded); - bool decodeUnicodeCodePoint(Token& token, - Location& current, - Location end, + bool decodeUnicodeCodePoint(Token& token, Location& current, Location end, unsigned int& unicode); - bool decodeUnicodeEscapeSequence(Token& token, - Location& current, - Location end, - unsigned int& unicode); - bool addError(const JSONCPP_STRING& message, Token& token, Location extra = 0); + bool decodeUnicodeEscapeSequence(Token& token, Location& current, + Location end, unsigned int& unicode); + bool addError(const String& message, Token& token, Location extra = nullptr); bool recoverFromError(TokenType skipUntilToken); - bool addErrorAndRecover(const JSONCPP_STRING& message, - Token& token, + bool addErrorAndRecover(const String& message, Token& token, TokenType skipUntilToken); void skipUntilSpace(); Value& currentValue(); Char getNextChar(); - void - getLocationLineAndColumn(Location location, int& line, int& column) const; - JSONCPP_STRING getLocationLineAndColumn(Location location) const; + void getLocationLineAndColumn(Location location, int& line, + int& column) const; + String getLocationLineAndColumn(Location location) const; void addComment(Location begin, Location end, CommentPlacement placement); void skipCommentTokens(Token& token); - static JSONCPP_STRING normalizeEOL(Location begin, Location end); + static String normalizeEOL(Location begin, Location end); static bool containsNewLine(Location begin, Location end); - typedef std::stack<Value*> Nodes; - Nodes nodes_; - Errors errors_; - JSONCPP_STRING document_; - Location begin_; - Location end_; - Location current_; - Location lastValueEnd_; - Value* lastValue_; - JSONCPP_STRING commentsBefore_; + using Nodes = std::stack<Value*>; + + Nodes nodes_{}; + Errors errors_{}; + String document_{}; + Location begin_ = nullptr; + Location end_ = nullptr; + Location current_ = nullptr; + Location lastValueEnd_ = nullptr; + Value* lastValue_ = nullptr; + bool lastValueHasAComment_ = false; + String commentsBefore_{}; OurFeatures const features_; - bool collectComments_; -}; // OurReader + bool collectComments_ = false; +}; // OurReader // complete copy of Read impl, for OurReader -bool OurReader::containsNewLine(OurReader::Location begin, OurReader::Location end) { - for (; begin < end; ++begin) - if (*begin == '\n' || *begin == '\r') - return true; - return false; +bool OurReader::containsNewLine(OurReader::Location begin, + OurReader::Location end) { + return std::any_of(begin, end, [](char b) { return b == '\n' || b == '\r'; }); } -OurReader::OurReader(OurFeatures const& features) - : errors_(), document_(), begin_(), end_(), current_(), lastValueEnd_(), - lastValue_(), commentsBefore_(), - features_(features), collectComments_() { -} +OurReader::OurReader(OurFeatures const& features) : features_(features) {} -bool OurReader::parse(const char* beginDoc, - const char* endDoc, - Value& root, - bool collectComments) { +bool OurReader::parse(const char* beginDoc, const char* endDoc, Value& root, + bool collectComments) { if (!features_.allowComments_) { collectComments = false; } @@ -1063,22 +1011,23 @@ bool OurReader::parse(const char* beginDoc, end_ = endDoc; collectComments_ = collectComments; current_ = begin_; - lastValueEnd_ = 0; - lastValue_ = 0; + lastValueEnd_ = nullptr; + lastValue_ = nullptr; commentsBefore_.clear(); errors_.clear(); while (!nodes_.empty()) nodes_.pop(); nodes_.push(&root); + // skip byte order mark if it exists at the beginning of the UTF-8 text. + skipBom(features_.skipBom_); bool successful = readValue(); + nodes_.pop(); Token token; skipCommentTokens(token); - if (features_.failIfExtra_) { - if ((features_.strictRoot_ || token.type_ != tokenError) && token.type_ != tokenEndOfStream) { - addError("Extra non-whitespace after JSON value.", token); - return false; - } + if (features_.failIfExtra_ && (token.type_ != tokenEndOfStream)) { + addError("Extra non-whitespace after JSON value.", token); + return false; } if (collectComments_ && !commentsBefore_.empty()) root.setComment(commentsBefore_, commentAfter); @@ -1100,7 +1049,8 @@ bool OurReader::parse(const char* beginDoc, bool OurReader::readValue() { // To preserve the old behaviour we cast size_t to int. - if (static_cast<int>(nodes_.size()) > features_.stackLimit_) throwRuntimeError("Exceeded stackLimit in readValue()."); + if (nodes_.size() > features_.stackLimit_) + throwRuntimeError("Exceeded stackLimit in readValue()."); Token token; skipCommentTokens(token); bool successful = true; @@ -1125,54 +1075,42 @@ bool OurReader::readValue() { case tokenString: successful = decodeString(token); break; - case tokenTrue: - { + case tokenTrue: { Value v(true); currentValue().swapPayload(v); currentValue().setOffsetStart(token.start_ - begin_); currentValue().setOffsetLimit(token.end_ - begin_); - } - break; - case tokenFalse: - { + } break; + case tokenFalse: { Value v(false); currentValue().swapPayload(v); currentValue().setOffsetStart(token.start_ - begin_); currentValue().setOffsetLimit(token.end_ - begin_); - } - break; - case tokenNull: - { + } break; + case tokenNull: { Value v; currentValue().swapPayload(v); currentValue().setOffsetStart(token.start_ - begin_); currentValue().setOffsetLimit(token.end_ - begin_); - } - break; - case tokenNaN: - { + } break; + case tokenNaN: { Value v(std::numeric_limits<double>::quiet_NaN()); currentValue().swapPayload(v); currentValue().setOffsetStart(token.start_ - begin_); currentValue().setOffsetLimit(token.end_ - begin_); - } - break; - case tokenPosInf: - { + } break; + case tokenPosInf: { Value v(std::numeric_limits<double>::infinity()); currentValue().swapPayload(v); currentValue().setOffsetStart(token.start_ - begin_); currentValue().setOffsetLimit(token.end_ - begin_); - } - break; - case tokenNegInf: - { + } break; + case tokenNegInf: { Value v(-std::numeric_limits<double>::infinity()); currentValue().swapPayload(v); currentValue().setOffsetStart(token.start_ - begin_); currentValue().setOffsetLimit(token.end_ - begin_); - } - break; + } break; case tokenArraySeparator: case tokenObjectEnd: case tokenArrayEnd: @@ -1194,6 +1132,7 @@ bool OurReader::readValue() { if (collectComments_) { lastValueEnd_ = current_; + lastValueHasAComment_ = false; lastValue_ = ¤tValue(); } @@ -1234,10 +1173,13 @@ bool OurReader::readToken(Token& token) { break; case '\'': if (features_.allowSingleQuotes_) { - token.type_ = tokenString; - ok = readStringSingleQuote(); + token.type_ = tokenString; + ok = readStringSingleQuote(); + } else { + // If we don't allow single quotes, this is a failure case. + ok = false; + } break; - } // else continue case '/': token.type_ = tokenComment; ok = readComment(); @@ -1263,6 +1205,14 @@ bool OurReader::readToken(Token& token) { ok = features_.allowSpecialFloats_ && match("nfinity", 7); } break; + case '+': + if (readNumber(true)) { + token.type_ = tokenNumber; + } else { + token.type_ = tokenPosInf; + ok = features_.allowSpecialFloats_ && match("nfinity", 7); + } + break; case 't': token.type_ = tokenTrue; ok = match("rue", 3); @@ -1307,7 +1257,7 @@ bool OurReader::readToken(Token& token) { if (!ok) token.type_ = tokenError; token.end_ = current_; - return true; + return ok; } void OurReader::skipSpaces() { @@ -1320,7 +1270,17 @@ void OurReader::skipSpaces() { } } -bool OurReader::match(Location pattern, int patternLength) { +void OurReader::skipBom(bool skipBom) { + // The default behavior is to skip BOM. + if (skipBom) { + if ((end_ - begin_) >= 3 && strncmp(begin_, "\xEF\xBB\xBF", 3) == 0) { + begin_ += 3; + current_ = begin_; + } + } +} + +bool OurReader::match(const Char* pattern, int patternLength) { if (end_ - current_ < patternLength) return false; int index = patternLength; @@ -1332,21 +1292,32 @@ bool OurReader::match(Location pattern, int patternLength) { } bool OurReader::readComment() { - Location commentBegin = current_ - 1; - Char c = getNextChar(); + const Location commentBegin = current_ - 1; + const Char c = getNextChar(); bool successful = false; - if (c == '*') - successful = readCStyleComment(); - else if (c == '/') + bool cStyleWithEmbeddedNewline = false; + + const bool isCStyleComment = (c == '*'); + const bool isCppStyleComment = (c == '/'); + if (isCStyleComment) { + successful = readCStyleComment(&cStyleWithEmbeddedNewline); + } else if (isCppStyleComment) { successful = readCppStyleComment(); + } + if (!successful) return false; if (collectComments_) { CommentPlacement placement = commentBefore; - if (lastValueEnd_ && !containsNewLine(lastValueEnd_, commentBegin)) { - if (c != '*' || !containsNewLine(commentBegin, current_)) - placement = commentAfterOnSameLine; + + if (!lastValueHasAComment_) { + if (lastValueEnd_ && !containsNewLine(lastValueEnd_, commentBegin)) { + if (isCppStyleComment || !cStyleWithEmbeddedNewline) { + placement = commentAfterOnSameLine; + lastValueHasAComment_ = true; + } + } } addComment(commentBegin, current_, placement); @@ -1354,16 +1325,17 @@ bool OurReader::readComment() { return true; } -JSONCPP_STRING OurReader::normalizeEOL(OurReader::Location begin, OurReader::Location end) { - JSONCPP_STRING normalized; +String OurReader::normalizeEOL(OurReader::Location begin, + OurReader::Location end) { + String normalized; normalized.reserve(static_cast<size_t>(end - begin)); OurReader::Location current = begin; while (current != end) { char c = *current++; if (c == '\r') { if (current != end && *current == '\n') - // convert dos EOL - ++current; + // convert dos EOL + ++current; // convert Mac EOL normalized += '\n'; } else { @@ -1373,24 +1345,29 @@ JSONCPP_STRING OurReader::normalizeEOL(OurReader::Location begin, OurReader::Loc return normalized; } -void -OurReader::addComment(Location begin, Location end, CommentPlacement placement) { +void OurReader::addComment(Location begin, Location end, + CommentPlacement placement) { assert(collectComments_); - const JSONCPP_STRING& normalized = normalizeEOL(begin, end); + const String& normalized = normalizeEOL(begin, end); if (placement == commentAfterOnSameLine) { - assert(lastValue_ != 0); + assert(lastValue_ != nullptr); lastValue_->setComment(normalized, placement); } else { commentsBefore_ += normalized; } } -bool OurReader::readCStyleComment() { +bool OurReader::readCStyleComment(bool* containsNewLineResult) { + *containsNewLineResult = false; + while ((current_ + 1) < end_) { Char c = getNextChar(); if (c == '*' && *current_ == '/') break; + if (c == '\n') + *containsNewLineResult = true; } + return getNextChar() == '/'; } @@ -1411,7 +1388,7 @@ bool OurReader::readCppStyleComment() { } bool OurReader::readNumber(bool checkInf) { - const char *p = current_; + Location p = current_; if (checkInf && p != end_ && *p == 'I') { current_ = ++p; return false; @@ -1448,7 +1425,6 @@ bool OurReader::readString() { return c == '"'; } - bool OurReader::readStringSingleQuote() { Char c = 0; while (current_ != end_) { @@ -1461,19 +1437,21 @@ bool OurReader::readStringSingleQuote() { return c == '\''; } -bool OurReader::readObject(Token& tokenStart) { +bool OurReader::readObject(Token& token) { Token tokenName; - JSONCPP_STRING name; + String name; Value init(objectValue); currentValue().swapPayload(init); - currentValue().setOffsetStart(tokenStart.start_ - begin_); + currentValue().setOffsetStart(token.start_ - begin_); while (readToken(tokenName)) { bool initialTokenOk = true; while (tokenName.type_ == tokenComment && initialTokenOk) initialTokenOk = readToken(tokenName); if (!initialTokenOk) break; - if (tokenName.type_ == tokenObjectEnd && name.empty()) // empty object + if (tokenName.type_ == tokenObjectEnd && + (name.empty() || + features_.allowTrailingCommas_)) // empty object or trailing comma return true; name.clear(); if (tokenName.type_ == tokenString) { @@ -1487,17 +1465,17 @@ bool OurReader::readObject(Token& tokenStart) { } else { break; } + if (name.length() >= (1U << 30)) + throwRuntimeError("keylength >= 2^30"); + if (features_.rejectDupKeys_ && currentValue().isMember(name)) { + String msg = "Duplicate key: '" + name + "'"; + return addErrorAndRecover(msg, tokenName, tokenObjectEnd); + } Token colon; if (!readToken(colon) || colon.type_ != tokenMemberSeparator) { - return addErrorAndRecover( - "Missing ':' after object member name", colon, tokenObjectEnd); - } - if (name.length() >= (1U<<30)) throwRuntimeError("keylength >= 2^30"); - if (features_.rejectDupKeys_ && currentValue().isMember(name)) { - JSONCPP_STRING msg = "Duplicate key: '" + name + "'"; - return addErrorAndRecover( - msg, tokenName, tokenObjectEnd); + return addErrorAndRecover("Missing ':' after object member name", colon, + tokenObjectEnd); } Value& value = currentValue()[name]; nodes_.push(&value); @@ -1510,8 +1488,8 @@ bool OurReader::readObject(Token& tokenStart) { if (!readToken(comma) || (comma.type_ != tokenObjectEnd && comma.type_ != tokenArraySeparator && comma.type_ != tokenComment)) { - return addErrorAndRecover( - "Missing ',' or '}' in object declaration", comma, tokenObjectEnd); + return addErrorAndRecover("Missing ',' or '}' in object declaration", + comma, tokenObjectEnd); } bool finalizeTokenOk = true; while (comma.type_ == tokenComment && finalizeTokenOk) @@ -1519,23 +1497,27 @@ bool OurReader::readObject(Token& tokenStart) { if (comma.type_ == tokenObjectEnd) return true; } - return addErrorAndRecover( - "Missing '}' or object member name", tokenName, tokenObjectEnd); + return addErrorAndRecover("Missing '}' or object member name", tokenName, + tokenObjectEnd); } -bool OurReader::readArray(Token& tokenStart) { +bool OurReader::readArray(Token& token) { Value init(arrayValue); currentValue().swapPayload(init); - currentValue().setOffsetStart(tokenStart.start_ - begin_); - skipSpaces(); - if (current_ != end_ && *current_ == ']') // empty array - { - Token endArray; - readToken(endArray); - return true; - } + currentValue().setOffsetStart(token.start_ - begin_); int index = 0; for (;;) { + skipSpaces(); + if (current_ != end_ && *current_ == ']' && + (index == 0 || + (features_.allowTrailingCommas_ && + !features_.allowDroppedNullPlaceholders_))) // empty array or trailing + // comma + { + Token endArray; + readToken(endArray); + return true; + } Value& value = currentValue()[index++]; nodes_.push(&value); bool ok = readValue(); @@ -1543,19 +1525,19 @@ bool OurReader::readArray(Token& tokenStart) { if (!ok) // error already set return recoverFromError(tokenArrayEnd); - Token token; + Token currentToken; // Accept Comment after last item in the array. - ok = readToken(token); - while (token.type_ == tokenComment && ok) { - ok = readToken(token); + ok = readToken(currentToken); + while (currentToken.type_ == tokenComment && ok) { + ok = readToken(currentToken); } - bool badTokenType = - (token.type_ != tokenArraySeparator && token.type_ != tokenArrayEnd); + bool badTokenType = (currentToken.type_ != tokenArraySeparator && + currentToken.type_ != tokenArrayEnd); if (!ok || badTokenType) { - return addErrorAndRecover( - "Missing ',' or ']' in array declaration", token, tokenArrayEnd); + return addErrorAndRecover("Missing ',' or ']' in array declaration", + currentToken, tokenArrayEnd); } - if (token.type_ == tokenArrayEnd) + if (currentToken.type_ == tokenArrayEnd) break; } return true; @@ -1576,38 +1558,78 @@ bool OurReader::decodeNumber(Token& token, Value& decoded) { // larger than the maximum supported value of an integer then // we decode the number as a double. Location current = token.start_; - bool isNegative = *current == '-'; - if (isNegative) + const bool isNegative = *current == '-'; + if (isNegative) { ++current; - // TODO: Help the compiler do the div and mod at compile time or get rid of them. - Value::LargestUInt maxIntegerValue = - isNegative ? Value::LargestUInt(Value::minLargestInt) - : Value::maxLargestUInt; - Value::LargestUInt threshold = maxIntegerValue / 10; + } + + // We assume we can represent the largest and smallest integer types as + // unsigned integers with separate sign. This is only true if they can fit + // into an unsigned integer. + static_assert(Value::maxLargestInt <= Value::maxLargestUInt, + "Int must be smaller than UInt"); + + // We need to convert minLargestInt into a positive number. The easiest way + // to do this conversion is to assume our "threshold" value of minLargestInt + // divided by 10 can fit in maxLargestInt when absolute valued. This should + // be a safe assumption. + static_assert(Value::minLargestInt <= -Value::maxLargestInt, + "The absolute value of minLargestInt must be greater than or " + "equal to maxLargestInt"); + static_assert(Value::minLargestInt / 10 >= -Value::maxLargestInt, + "The absolute value of minLargestInt must be only 1 magnitude " + "larger than maxLargest Int"); + + static constexpr Value::LargestUInt positive_threshold = + Value::maxLargestUInt / 10; + static constexpr Value::UInt positive_last_digit = Value::maxLargestUInt % 10; + + // For the negative values, we have to be more careful. Since typically + // -Value::minLargestInt will cause an overflow, we first divide by 10 and + // then take the inverse. This assumes that minLargestInt is only a single + // power of 10 different in magnitude, which we check above. For the last + // digit, we take the modulus before negating for the same reason. + static constexpr auto negative_threshold = + Value::LargestUInt(-(Value::minLargestInt / 10)); + static constexpr auto negative_last_digit = + Value::UInt(-(Value::minLargestInt % 10)); + + const Value::LargestUInt threshold = + isNegative ? negative_threshold : positive_threshold; + const Value::UInt max_last_digit = + isNegative ? negative_last_digit : positive_last_digit; + Value::LargestUInt value = 0; while (current < token.end_) { Char c = *current++; if (c < '0' || c > '9') return decodeDouble(token, decoded); - Value::UInt digit(static_cast<Value::UInt>(c - '0')); + + const auto digit(static_cast<Value::UInt>(c - '0')); if (value >= threshold) { // We've hit or exceeded the max value divided by 10 (rounded down). If - // a) we've only just touched the limit, b) this is the last digit, and + // a) we've only just touched the limit, meaing value == threshold, + // b) this is the last digit, or // c) it's small enough to fit in that rounding delta, we're okay. // Otherwise treat this number as a double to avoid overflow. if (value > threshold || current != token.end_ || - digit > maxIntegerValue % 10) { + digit > max_last_digit) { return decodeDouble(token, decoded); } } value = value * 10 + digit; } - if (isNegative) - decoded = -Value::LargestInt(value); - else if (value <= Value::LargestUInt(Value::maxInt)) + + if (isNegative) { + // We use the same magnitude assumption here, just in case. + const auto last_digit = static_cast<Value::UInt>(value % 10); + decoded = -Value::LargestInt(value / 10) * 10 - last_digit; + } else if (value <= Value::LargestUInt(Value::maxLargestInt)) { decoded = Value::LargestInt(value); - else + } else { decoded = value; + } + return true; } @@ -1623,44 +1645,18 @@ bool OurReader::decodeDouble(Token& token) { bool OurReader::decodeDouble(Token& token, Value& decoded) { double value = 0; - const int bufferSize = 32; - int count; - ptrdiff_t const length = token.end_ - token.start_; - - // Sanity check to avoid buffer overflow exploits. - if (length < 0) { - return addError("Unable to parse token length", token); - } - size_t const ulength = static_cast<size_t>(length); - - // Avoid using a string constant for the format control string given to - // sscanf, as this can cause hard to debug crashes on OS X. See here for more - // info: - // - // http://developer.apple.com/library/mac/#DOCUMENTATION/DeveloperTools/gcc-4.0.1/gcc/Incompatibilities.html - char format[] = "%lf"; - - if (length <= bufferSize) { - Char buffer[bufferSize + 1]; - memcpy(buffer, token.start_, ulength); - buffer[length] = 0; - fixNumericLocaleInput(buffer, buffer + length); - count = sscanf(buffer, format, &value); - } else { - JSONCPP_STRING buffer(token.start_, token.end_); - count = sscanf(buffer.c_str(), format, &value); + const String buffer(token.start_, token.end_); + IStringStream is(buffer); + if (!(is >> value)) { + return addError( + "'" + String(token.start_, token.end_) + "' is not a number.", token); } - - if (count != 1) - return addError("'" + JSONCPP_STRING(token.start_, token.end_) + - "' is not a number.", - token); decoded = value; return true; } bool OurReader::decodeString(Token& token) { - JSONCPP_STRING decoded_string; + String decoded_string; if (!decodeString(token, decoded_string)) return false; Value decoded(decoded_string); @@ -1670,7 +1666,7 @@ bool OurReader::decodeString(Token& token) { return true; } -bool OurReader::decodeString(Token& token, JSONCPP_STRING& decoded) { +bool OurReader::decodeString(Token& token, String& decoded) { decoded.reserve(static_cast<size_t>(token.end_ - token.start_ - 2)); Location current = token.start_ + 1; // skip '"' Location end = token.end_ - 1; // do not include '"' @@ -1678,7 +1674,7 @@ bool OurReader::decodeString(Token& token, JSONCPP_STRING& decoded) { Char c = *current++; if (c == '"') break; - else if (c == '\\') { + if (c == '\\') { if (current == end) return addError("Empty escape sequence in string", token, current); Char escape = *current++; @@ -1723,10 +1719,8 @@ bool OurReader::decodeString(Token& token, JSONCPP_STRING& decoded) { return true; } -bool OurReader::decodeUnicodeCodePoint(Token& token, - Location& current, - Location end, - unsigned int& unicode) { +bool OurReader::decodeUnicodeCodePoint(Token& token, Location& current, + Location end, unsigned int& unicode) { unicode = 0; // Convince clang-analyzer that this is initialized before use. if (!decodeUnicodeEscapeSequence(token, current, end, unicode)) @@ -1736,10 +1730,9 @@ bool OurReader::decodeUnicodeCodePoint(Token& token, if (end - current < 6) return addError( "additional six characters expected to parse unicode surrogate pair.", - token, - current); - unsigned int surrogatePair; + token, current); if (*(current++) == '\\' && *(current++) == 'u') { + unsigned int surrogatePair; if (decodeUnicodeEscapeSequence(token, current, end, surrogatePair)) { unicode = 0x10000 + ((unicode & 0x3FF) << 10) + (surrogatePair & 0x3FF); } else @@ -1747,20 +1740,17 @@ bool OurReader::decodeUnicodeCodePoint(Token& token, } else return addError("expecting another \\u token to begin the second half of " "a unicode surrogate pair", - token, - current); + token, current); } return true; } -bool OurReader::decodeUnicodeEscapeSequence(Token& token, - Location& current, - Location end, - unsigned int& ret_unicode) { +bool OurReader::decodeUnicodeEscapeSequence(Token& token, Location& current, + Location end, + unsigned int& ret_unicode) { if (end - current < 4) return addError( - "Bad unicode escape sequence in string: four digits expected.", - token, + "Bad unicode escape sequence in string: four digits expected.", token, current); int unicode = 0; for (int index = 0; index < 4; ++index) { @@ -1775,15 +1765,13 @@ bool OurReader::decodeUnicodeEscapeSequence(Token& token, else return addError( "Bad unicode escape sequence in string: hexadecimal digit expected.", - token, - current); + token, current); } ret_unicode = static_cast<unsigned int>(unicode); return true; } -bool -OurReader::addError(const JSONCPP_STRING& message, Token& token, Location extra) { +bool OurReader::addError(const String& message, Token& token, Location extra) { ErrorInfo info; info.token_ = token; info.message_ = message; @@ -1805,9 +1793,8 @@ bool OurReader::recoverFromError(TokenType skipUntilToken) { return false; } -bool OurReader::addErrorAndRecover(const JSONCPP_STRING& message, - Token& token, - TokenType skipUntilToken) { +bool OurReader::addErrorAndRecover(const String& message, Token& token, + TokenType skipUntilToken) { addError(message, token); return recoverFromError(skipUntilToken); } @@ -1820,9 +1807,8 @@ OurReader::Char OurReader::getNextChar() { return *current_++; } -void OurReader::getLocationLineAndColumn(Location location, - int& line, - int& column) const { +void OurReader::getLocationLineAndColumn(Location location, int& line, + int& column) const { Location current = begin_; Location lastLineStart = current; line = 0; @@ -1843,20 +1829,17 @@ void OurReader::getLocationLineAndColumn(Location location, ++line; } -JSONCPP_STRING OurReader::getLocationLineAndColumn(Location location) const { +String OurReader::getLocationLineAndColumn(Location location) const { int line, column; getLocationLineAndColumn(location, line, column); char buffer[18 + 16 + 16 + 1]; - snprintf(buffer, sizeof(buffer), "Line %d, Column %d", line, column); + jsoncpp_snprintf(buffer, sizeof(buffer), "Line %d, Column %d", line, column); return buffer; } -JSONCPP_STRING OurReader::getFormattedErrorMessages() const { - JSONCPP_STRING formattedMessage; - for (Errors::const_iterator itError = errors_.begin(); - itError != errors_.end(); - ++itError) { - const ErrorInfo& error = *itError; +String OurReader::getFormattedErrorMessages() const { + String formattedMessage; + for (const auto& error : errors_) { formattedMessage += "* " + getLocationLineAndColumn(error.token_.start_) + "\n"; formattedMessage += " " + error.message_ + "\n"; @@ -1869,10 +1852,7 @@ JSONCPP_STRING OurReader::getFormattedErrorMessages() const { std::vector<OurReader::StructuredError> OurReader::getStructuredErrors() const { std::vector<OurReader::StructuredError> allErrors; - for (Errors::const_iterator itError = errors_.begin(); - itError != errors_.end(); - ++itError) { - const ErrorInfo& error = *itError; + for (const auto& error : errors_) { OurReader::StructuredError structured; structured.offset_start = error.token_.start_ - begin_; structured.offset_limit = error.token_.end_ - begin_; @@ -1882,59 +1862,15 @@ std::vector<OurReader::StructuredError> OurReader::getStructuredErrors() const { return allErrors; } -bool OurReader::pushError(const Value& value, const JSONCPP_STRING& message) { - ptrdiff_t length = end_ - begin_; - if(value.getOffsetStart() > length - || value.getOffsetLimit() > length) - return false; - Token token; - token.type_ = tokenError; - token.start_ = begin_ + value.getOffsetStart(); - token.end_ = end_ + value.getOffsetLimit(); - ErrorInfo info; - info.token_ = token; - info.message_ = message; - info.extra_ = 0; - errors_.push_back(info); - return true; -} - -bool OurReader::pushError(const Value& value, const JSONCPP_STRING& message, const Value& extra) { - ptrdiff_t length = end_ - begin_; - if(value.getOffsetStart() > length - || value.getOffsetLimit() > length - || extra.getOffsetLimit() > length) - return false; - Token token; - token.type_ = tokenError; - token.start_ = begin_ + value.getOffsetStart(); - token.end_ = begin_ + value.getOffsetLimit(); - ErrorInfo info; - info.token_ = token; - info.message_ = message; - info.extra_ = begin_ + extra.getOffsetStart(); - errors_.push_back(info); - return true; -} - -bool OurReader::good() const { - return !errors_.size(); -} - - class OurCharReader : public CharReader { bool const collectComments_; OurReader reader_; + public: - OurCharReader( - bool collectComments, - OurFeatures const& features) - : collectComments_(collectComments) - , reader_(features) - {} - bool parse( - char const* beginDoc, char const* endDoc, - Value* root, JSONCPP_STRING* errs) JSONCPP_OVERRIDE { + OurCharReader(bool collectComments, OurFeatures const& features) + : collectComments_(collectComments), reader_(features) {} + bool parse(char const* beginDoc, char const* endDoc, Value* root, + String* errs) override { bool ok = reader_.parse(beginDoc, endDoc, *root, collectComments_); if (errs) { *errs = reader_.getFormattedErrorMessages(); @@ -1943,67 +1879,64 @@ public: } }; -CharReaderBuilder::CharReaderBuilder() -{ - setDefaults(&settings_); -} -CharReaderBuilder::~CharReaderBuilder() -{} -CharReader* CharReaderBuilder::newCharReader() const -{ +CharReaderBuilder::CharReaderBuilder() { setDefaults(&settings_); } +CharReaderBuilder::~CharReaderBuilder() = default; +CharReader* CharReaderBuilder::newCharReader() const { bool collectComments = settings_["collectComments"].asBool(); OurFeatures features = OurFeatures::all(); features.allowComments_ = settings_["allowComments"].asBool(); + features.allowTrailingCommas_ = settings_["allowTrailingCommas"].asBool(); features.strictRoot_ = settings_["strictRoot"].asBool(); - features.allowDroppedNullPlaceholders_ = settings_["allowDroppedNullPlaceholders"].asBool(); + features.allowDroppedNullPlaceholders_ = + settings_["allowDroppedNullPlaceholders"].asBool(); features.allowNumericKeys_ = settings_["allowNumericKeys"].asBool(); features.allowSingleQuotes_ = settings_["allowSingleQuotes"].asBool(); - features.stackLimit_ = settings_["stackLimit"].asInt(); + + // Stack limit is always a size_t, so we get this as an unsigned int + // regardless of it we have 64-bit integer support enabled. + features.stackLimit_ = static_cast<size_t>(settings_["stackLimit"].asUInt()); features.failIfExtra_ = settings_["failIfExtra"].asBool(); features.rejectDupKeys_ = settings_["rejectDupKeys"].asBool(); features.allowSpecialFloats_ = settings_["allowSpecialFloats"].asBool(); + features.skipBom_ = settings_["skipBom"].asBool(); return new OurCharReader(collectComments, features); } -static void getValidReaderKeys(std::set<JSONCPP_STRING>* valid_keys) -{ - valid_keys->clear(); - valid_keys->insert("collectComments"); - valid_keys->insert("allowComments"); - valid_keys->insert("strictRoot"); - valid_keys->insert("allowDroppedNullPlaceholders"); - valid_keys->insert("allowNumericKeys"); - valid_keys->insert("allowSingleQuotes"); - valid_keys->insert("stackLimit"); - valid_keys->insert("failIfExtra"); - valid_keys->insert("rejectDupKeys"); - valid_keys->insert("allowSpecialFloats"); -} -bool CharReaderBuilder::validate(Json::Value* invalid) const -{ - Json::Value my_invalid; - if (!invalid) invalid = &my_invalid; // so we do not need to test for NULL - Json::Value& inv = *invalid; - std::set<JSONCPP_STRING> valid_keys; - getValidReaderKeys(&valid_keys); - Value::Members keys = settings_.getMemberNames(); - size_t n = keys.size(); - for (size_t i = 0; i < n; ++i) { - JSONCPP_STRING const& key = keys[i]; - if (valid_keys.find(key) == valid_keys.end()) { - inv[key] = settings_[key]; - } + +bool CharReaderBuilder::validate(Json::Value* invalid) const { + static const auto& valid_keys = *new std::set<String>{ + "collectComments", + "allowComments", + "allowTrailingCommas", + "strictRoot", + "allowDroppedNullPlaceholders", + "allowNumericKeys", + "allowSingleQuotes", + "stackLimit", + "failIfExtra", + "rejectDupKeys", + "allowSpecialFloats", + "skipBom", + }; + for (auto si = settings_.begin(); si != settings_.end(); ++si) { + auto key = si.name(); + if (valid_keys.count(key)) + continue; + if (invalid) + (*invalid)[std::move(key)] = *si; + else + return false; } - return 0u == inv.size(); + return invalid ? invalid->empty() : true; } -Value& CharReaderBuilder::operator[](JSONCPP_STRING key) -{ + +Value& CharReaderBuilder::operator[](const String& key) { return settings_[key]; } // static -void CharReaderBuilder::strictMode(Json::Value* settings) -{ -//! [CharReaderBuilderStrictMode] +void CharReaderBuilder::strictMode(Json::Value* settings) { + //! [CharReaderBuilderStrictMode] (*settings)["allowComments"] = false; + (*settings)["allowTrailingCommas"] = false; (*settings)["strictRoot"] = true; (*settings)["allowDroppedNullPlaceholders"] = false; (*settings)["allowNumericKeys"] = false; @@ -2012,14 +1945,15 @@ void CharReaderBuilder::strictMode(Json::Value* settings) (*settings)["failIfExtra"] = true; (*settings)["rejectDupKeys"] = true; (*settings)["allowSpecialFloats"] = false; -//! [CharReaderBuilderStrictMode] + (*settings)["skipBom"] = true; + //! [CharReaderBuilderStrictMode] } // static -void CharReaderBuilder::setDefaults(Json::Value* settings) -{ -//! [CharReaderBuilderDefaults] +void CharReaderBuilder::setDefaults(Json::Value* settings) { + //! [CharReaderBuilderDefaults] (*settings)["collectComments"] = true; (*settings)["allowComments"] = true; + (*settings)["allowTrailingCommas"] = true; (*settings)["strictRoot"] = false; (*settings)["allowDroppedNullPlaceholders"] = false; (*settings)["allowNumericKeys"] = false; @@ -2028,19 +1962,18 @@ void CharReaderBuilder::setDefaults(Json::Value* settings) (*settings)["failIfExtra"] = false; (*settings)["rejectDupKeys"] = false; (*settings)["allowSpecialFloats"] = false; -//! [CharReaderBuilderDefaults] + (*settings)["skipBom"] = true; + //! [CharReaderBuilderDefaults] } ////////////////////////////////// // global functions -bool parseFromStream( - CharReader::Factory const& fact, JSONCPP_ISTREAM& sin, - Value* root, JSONCPP_STRING* errs) -{ - JSONCPP_OSTRINGSTREAM ssin; +bool parseFromStream(CharReader::Factory const& fact, IStream& sin, Value* root, + String* errs) { + OStringStream ssin; ssin << sin.rdbuf(); - JSONCPP_STRING doc = ssin.str(); + String doc = ssin.str(); char const* begin = doc.data(); char const* end = begin + doc.size(); // Note that we do not actually need a null-terminator. @@ -2048,15 +1981,11 @@ bool parseFromStream( return reader->parse(begin, end, root, errs); } -JSONCPP_ISTREAM& operator>>(JSONCPP_ISTREAM& sin, Value& root) { +IStream& operator>>(IStream& sin, Value& root) { CharReaderBuilder b; - JSONCPP_STRING errs; + String errs; bool ok = parseFromStream(b, sin, &root, &errs); if (!ok) { - fprintf(stderr, - "Error from reader: %s", - errs.c_str()); - throwRuntimeError(errs); } return sin; diff --git a/Utilities/cmjsoncpp/src/lib_json/json_tool.h b/Utilities/cmjsoncpp/src/lib_json/json_tool.h index 4316178..2d7b7d9 100644 --- a/Utilities/cmjsoncpp/src/lib_json/json_tool.h +++ b/Utilities/cmjsoncpp/src/lib_json/json_tool.h @@ -6,6 +6,9 @@ #ifndef LIB_JSONCPP_JSON_TOOL_H_INCLUDED #define LIB_JSONCPP_JSON_TOOL_H_INCLUDED +#if !defined(JSON_IS_AMALGAMATION) +#include <json/config.h> +#endif // Also support old flag NO_LOCALE_SUPPORT #ifdef NO_LOCALE_SUPPORT @@ -23,7 +26,7 @@ */ namespace Json { -static char getDecimalPoint() { +static inline char getDecimalPoint() { #ifdef JSONCPP_NO_LOCALE_SUPPORT return '\0'; #else @@ -33,8 +36,8 @@ static char getDecimalPoint() { } /// Converts a unicode code-point to UTF-8. -static inline JSONCPP_STRING codePointToUTF8(unsigned int cp) { - JSONCPP_STRING result; +static inline String codePointToUTF8(unsigned int cp) { + String result; // based on description from http://en.wikipedia.org/wiki/UTF-8 @@ -61,9 +64,6 @@ static inline JSONCPP_STRING codePointToUTF8(unsigned int cp) { return result; } -/// Returns true if ch is a control character (in range [1,31]). -static inline bool isControlCharacter(char ch) { return ch > 0 && ch <= 0x1F; } - enum { /// Constant that specify the size of the buffer that must be passed to /// uintToString. @@ -71,10 +71,10 @@ enum { }; // Defines a char buffer for use with uintToString(). -typedef char UIntToStringBuffer[uintToStringBufferSize]; +using UIntToStringBuffer = char[uintToStringBufferSize]; /** Converts an unsigned integer to string. - * @param value Unsigned interger to convert to string + * @param value Unsigned integer to convert to string * @param current Input/Output string buffer. * Must have at least uintToStringBufferSize chars free. */ @@ -91,27 +91,44 @@ static inline void uintToString(LargestUInt value, char*& current) { * We had a sophisticated way, but it did not work in WinCE. * @see https://github.com/open-source-parsers/jsoncpp/pull/9 */ -static inline void fixNumericLocale(char* begin, char* end) { - while (begin < end) { +template <typename Iter> Iter fixNumericLocale(Iter begin, Iter end) { + for (; begin != end; ++begin) { if (*begin == ',') { *begin = '.'; } - ++begin; } + return begin; } -static inline void fixNumericLocaleInput(char* begin, char* end) { +template <typename Iter> void fixNumericLocaleInput(Iter begin, Iter end) { char decimalPoint = getDecimalPoint(); - if (decimalPoint != '\0' && decimalPoint != '.') { - while (begin < end) { - if (*begin == '.') { - *begin = decimalPoint; - } - ++begin; + if (decimalPoint == '\0' || decimalPoint == '.') { + return; + } + for (; begin != end; ++begin) { + if (*begin == '.') { + *begin = decimalPoint; + } + } +} + +/** + * Return iterator that would be the new end of the range [begin,end), if we + * were to delete zeros in the end of string, but not the last zero before '.'. + */ +template <typename Iter> Iter fixZerosInTheEnd(Iter begin, Iter end) { + for (; begin != end; --end) { + if (*(end - 1) != '0') { + return end; + } + // Don't delete the last zero before the decimal point. + if (begin != (end - 1) && *(end - 2) == '.') { + return end; } } + return end; } -} // namespace Json { +} // namespace Json #endif // LIB_JSONCPP_JSON_TOOL_H_INCLUDED diff --git a/Utilities/cmjsoncpp/src/lib_json/json_value.cpp b/Utilities/cmjsoncpp/src/lib_json/json_value.cpp index f271e57..d59b7d9 100644 --- a/Utilities/cmjsoncpp/src/lib_json/json_value.cpp +++ b/Utilities/cmjsoncpp/src/lib_json/json_value.cpp @@ -8,20 +8,54 @@ #include <json/value.h> #include <json/writer.h> #endif // if !defined(JSON_IS_AMALGAMATION) -#include <math.h> +#include <algorithm> +#include <cassert> +#include <cmath> +#include <cstddef> +#include <cstring> +#include <iostream> #include <sstream> #include <utility> -#include <string.h> -#include <assert.h> -#ifdef JSON_USE_CPPTL -#include <cpptl/conststring.h> + +// Provide implementation equivalent of std::snprintf for older _MSC compilers +#if defined(_MSC_VER) && _MSC_VER < 1900 +#include <stdarg.h> +static int msvc_pre1900_c99_vsnprintf(char* outBuf, size_t size, + const char* format, va_list ap) { + int count = -1; + if (size != 0) + count = _vsnprintf_s(outBuf, size, _TRUNCATE, format, ap); + if (count == -1) + count = _vscprintf(format, ap); + return count; +} + +int JSON_API msvc_pre1900_c99_snprintf(char* outBuf, size_t size, + const char* format, ...) { + va_list ap; + va_start(ap, format); + const int count = msvc_pre1900_c99_vsnprintf(outBuf, size, format, ap); + va_end(ap); + return count; +} +#endif + +// Disable warning C4702 : unreachable code +#if defined(_MSC_VER) +#pragma warning(disable : 4702) #endif -#include <cstddef> // size_t -#include <algorithm> // min() #define JSON_ASSERT_UNREACHABLE assert(false) namespace Json { +template <typename T> +static std::unique_ptr<T> cloneUnique(const std::unique_ptr<T>& p) { + std::unique_ptr<T> r; + if (p) { + r = std::unique_ptr<T>(new T(*p)); + } + return r; +} // This is a walkaround to avoid the static initialization of Value::null. // kNull must be word-aligned to avoid crashing on ARM. We use an alignment of @@ -31,50 +65,34 @@ namespace Json { #else #define ALIGNAS(byte_alignment) #endif -//static const unsigned char ALIGNAS(8) kNull[sizeof(Value)] = { 0 }; -//const unsigned char& kNullRef = kNull[0]; -//const Value& Value::null = reinterpret_cast<const Value&>(kNullRef); -//const Value& Value::nullRef = null; // static -Value const& Value::nullSingleton() -{ - static Value const nullStatic; - return nullStatic; +Value const& Value::nullSingleton() { + static Value const nullStatic; + return nullStatic; } -// for backwards compatibility, we'll leave these global references around, but DO NOT -// use them in JSONCPP library code any more! +#if JSON_USE_NULLREF +// for backwards compatibility, we'll leave these global references around, but +// DO NOT use them in JSONCPP library code any more! +// static Value const& Value::null = Value::nullSingleton(); -Value const& Value::nullRef = Value::nullSingleton(); -const Int Value::minInt = Int(~(UInt(-1) / 2)); -const Int Value::maxInt = Int(UInt(-1) / 2); -const UInt Value::maxUInt = UInt(-1); -#if defined(JSON_HAS_INT64) -const Int64 Value::minInt64 = Int64(~(UInt64(-1) / 2)); -const Int64 Value::maxInt64 = Int64(UInt64(-1) / 2); -const UInt64 Value::maxUInt64 = UInt64(-1); -// The constant is hard-coded because some compiler have trouble -// converting Value::maxUInt64 to a double correctly (AIX/xlC). -// Assumes that UInt64 is a 64 bits integer. -static const double maxUInt64AsDouble = 18446744073709551615.0; -#endif // defined(JSON_HAS_INT64) -const LargestInt Value::minLargestInt = LargestInt(~(LargestUInt(-1) / 2)); -const LargestInt Value::maxLargestInt = LargestInt(LargestUInt(-1) / 2); -const LargestUInt Value::maxLargestUInt = LargestUInt(-1); +// static +Value const& Value::nullRef = Value::nullSingleton(); +#endif #if !defined(JSON_USE_INT64_DOUBLE_CONVERSION) template <typename T, typename U> static inline bool InRange(double d, T min, U max) { // The casts can lose precision, but we are looking only for // an approximate range. Might fail on edge cases though. ~cdunn - //return d >= static_cast<double>(min) && d <= static_cast<double>(max); - return d >= min && d <= max; + return d >= static_cast<double>(min) && d <= static_cast<double>(max); } #else // if !defined(JSON_USE_INT64_DOUBLE_CONVERSION) static inline double integerToDouble(Json::UInt64 value) { - return static_cast<double>(Int64(value / 2)) * 2.0 + static_cast<double>(Int64(value & 1)); + return static_cast<double>(Int64(value / 2)) * 2.0 + + static_cast<double>(Int64(value & 1)); } template <typename T> static inline double integerToDouble(T value) { @@ -94,19 +112,16 @@ static inline bool InRange(double d, T min, U max) { * computed using strlen(value). * @return Pointer on the duplicate instance of string. */ -static inline char* duplicateStringValue(const char* value, - size_t length) -{ +static inline char* duplicateStringValue(const char* value, size_t length) { // Avoid an integer overflow in the call to malloc below by limiting length // to a sane value. if (length >= static_cast<size_t>(Value::maxInt)) length = Value::maxInt - 1; - char* newString = static_cast<char*>(malloc(length + 1)); - if (newString == NULL) { - throwRuntimeError( - "in Json::Value::duplicateStringValue(): " - "Failed to allocate string value buffer"); + auto newString = static_cast<char*>(malloc(length + 1)); + if (newString == nullptr) { + throwRuntimeError("in Json::Value::duplicateStringValue(): " + "Failed to allocate string value buffer"); } memcpy(newString, value, length); newString[length] = 0; @@ -115,31 +130,28 @@ static inline char* duplicateStringValue(const char* value, /* Record the length as a prefix. */ -static inline char* duplicateAndPrefixStringValue( - const char* value, - unsigned int length) -{ +static inline char* duplicateAndPrefixStringValue(const char* value, + unsigned int length) { // Avoid an integer overflow in the call to malloc below by limiting length // to a sane value. - JSON_ASSERT_MESSAGE(length <= static_cast<unsigned>(Value::maxInt) - sizeof(unsigned) - 1U, + JSON_ASSERT_MESSAGE(length <= static_cast<unsigned>(Value::maxInt) - + sizeof(unsigned) - 1U, "in Json::Value::duplicateAndPrefixStringValue(): " "length too big for prefixing"); - unsigned actualLength = length + static_cast<unsigned>(sizeof(unsigned)) + 1U; - char* newString = static_cast<char*>(malloc(actualLength)); - if (newString == 0) { - throwRuntimeError( - "in Json::Value::duplicateAndPrefixStringValue(): " - "Failed to allocate string value buffer"); + size_t actualLength = sizeof(length) + length + 1; + auto newString = static_cast<char*>(malloc(actualLength)); + if (newString == nullptr) { + throwRuntimeError("in Json::Value::duplicateAndPrefixStringValue(): " + "Failed to allocate string value buffer"); } *reinterpret_cast<unsigned*>(newString) = length; memcpy(newString + sizeof(unsigned), value, length); - newString[actualLength - 1U] = 0; // to avoid buffer over-run accidents by users later + newString[actualLength - 1U] = + 0; // to avoid buffer over-run accidents by users later return newString; } -inline static void decodePrefixedString( - bool isPrefixed, char const* prefixed, - unsigned* length, char const** value) -{ +inline static void decodePrefixedString(bool isPrefixed, char const* prefixed, + unsigned* length, char const** value) { if (!isPrefixed) { *length = static_cast<unsigned>(strlen(prefixed)); *value = prefixed; @@ -148,7 +160,8 @@ inline static void decodePrefixedString( *value = prefixed + sizeof(unsigned); } } -/** Free the string duplicated by duplicateStringValue()/duplicateAndPrefixStringValue(). +/** Free the string duplicated by + * duplicateStringValue()/duplicateAndPrefixStringValue(). */ #if JSONCPP_USING_SECURE_MEMORY static inline void releasePrefixedStringValue(char* value) { @@ -161,17 +174,13 @@ static inline void releasePrefixedStringValue(char* value) { } static inline void releaseStringValue(char* value, unsigned length) { // length==0 => we allocated the strings memory - size_t size = (length==0) ? strlen(value) : length; + size_t size = (length == 0) ? strlen(value) : length; memset(value, 0, size); free(value); } -#else // !JSONCPP_USING_SECURE_MEMORY -static inline void releasePrefixedStringValue(char* value) { - free(value); -} -static inline void releaseStringValue(char* value, unsigned) { - free(value); -} +#else // !JSONCPP_USING_SECURE_MEMORY +static inline void releasePrefixedStringValue(char* value) { free(value); } +static inline void releaseStringValue(char* value, unsigned) { free(value); } #endif // JSONCPP_USING_SECURE_MEMORY } // namespace Json @@ -190,58 +199,28 @@ static inline void releaseStringValue(char* value, unsigned) { namespace Json { -Exception::Exception(JSONCPP_STRING const& msg) - : msg_(msg) -{} -Exception::~Exception() JSONCPP_NOEXCEPT -{} -char const* Exception::what() const JSONCPP_NOEXCEPT -{ - return msg_.c_str(); -} -RuntimeError::RuntimeError(JSONCPP_STRING const& msg) - : Exception(msg) -{} -LogicError::LogicError(JSONCPP_STRING const& msg) - : Exception(msg) -{} -JSONCPP_NORETURN void throwRuntimeError(JSONCPP_STRING const& msg) -{ +#if JSON_USE_EXCEPTION +Exception::Exception(String msg) : msg_(std::move(msg)) {} +Exception::~Exception() noexcept = default; +char const* Exception::what() const noexcept { return msg_.c_str(); } +RuntimeError::RuntimeError(String const& msg) : Exception(msg) {} +LogicError::LogicError(String const& msg) : Exception(msg) {} +JSONCPP_NORETURN void throwRuntimeError(String const& msg) { throw RuntimeError(msg); } -JSONCPP_NORETURN void throwLogicError(JSONCPP_STRING const& msg) -{ +JSONCPP_NORETURN void throwLogicError(String const& msg) { throw LogicError(msg); } - -// ////////////////////////////////////////////////////////////////// -// ////////////////////////////////////////////////////////////////// -// ////////////////////////////////////////////////////////////////// -// class Value::CommentInfo -// ////////////////////////////////////////////////////////////////// -// ////////////////////////////////////////////////////////////////// -// ////////////////////////////////////////////////////////////////// - -Value::CommentInfo::CommentInfo() : comment_(0) -{} - -Value::CommentInfo::~CommentInfo() { - if (comment_) - releaseStringValue(comment_, 0u); +#else // !JSON_USE_EXCEPTION +JSONCPP_NORETURN void throwRuntimeError(String const& msg) { + std::cerr << msg << std::endl; + abort(); } - -void Value::CommentInfo::setComment(const char* text, size_t len) { - if (comment_) { - releaseStringValue(comment_, 0u); - comment_ = 0; - } - JSON_ASSERT(text != 0); - JSON_ASSERT_MESSAGE( - text[0] == '\0' || text[0] == '/', - "in Json::Value::setComment(): Comments must start with /"); - // It seems that /**/ style comments are acceptable as well. - comment_ = duplicateStringValue(text, len); +JSONCPP_NORETURN void throwLogicError(String const& msg) { + std::cerr << msg << std::endl; + abort(); } +#endif // ////////////////////////////////////////////////////////////////// // ////////////////////////////////////////////////////////////////// @@ -254,36 +233,44 @@ void Value::CommentInfo::setComment(const char* text, size_t len) { // Notes: policy_ indicates if the string was allocated when // a string is stored. -Value::CZString::CZString(ArrayIndex aindex) : cstr_(0), index_(aindex) {} +Value::CZString::CZString(ArrayIndex index) : cstr_(nullptr), index_(index) {} -Value::CZString::CZString(char const* str, unsigned ulength, DuplicationPolicy allocate) +Value::CZString::CZString(char const* str, unsigned length, + DuplicationPolicy allocate) : cstr_(str) { // allocate != duplicate storage_.policy_ = allocate & 0x3; - storage_.length_ = ulength & 0x3FFFFFFF; + storage_.length_ = length & 0x3FFFFFFF; } Value::CZString::CZString(const CZString& other) { - cstr_ = (other.storage_.policy_ != noDuplication && other.cstr_ != 0 - ? duplicateStringValue(other.cstr_, other.storage_.length_) - : other.cstr_); - storage_.policy_ = static_cast<unsigned>(other.cstr_ - ? (static_cast<DuplicationPolicy>(other.storage_.policy_) == noDuplication - ? noDuplication : duplicate) - : static_cast<DuplicationPolicy>(other.storage_.policy_)) & 3U; + cstr_ = (other.storage_.policy_ != noDuplication && other.cstr_ != nullptr + ? duplicateStringValue(other.cstr_, other.storage_.length_) + : other.cstr_); + storage_.policy_ = + static_cast<unsigned>( + other.cstr_ + ? (static_cast<DuplicationPolicy>(other.storage_.policy_) == + noDuplication + ? noDuplication + : duplicate) + : static_cast<DuplicationPolicy>(other.storage_.policy_)) & + 3U; storage_.length_ = other.storage_.length_; } -#if JSON_HAS_RVALUE_REFERENCES Value::CZString::CZString(CZString&& other) - : cstr_(other.cstr_), index_(other.index_) { + : cstr_(other.cstr_), index_(other.index_) { other.cstr_ = nullptr; } -#endif Value::CZString::~CZString() { if (cstr_ && storage_.policy_ == duplicate) { - releaseStringValue(const_cast<char*>(cstr_), storage_.length_ + 1u); //+1 for null terminating character for sake of completeness but not actually necessary + releaseStringValue(const_cast<char*>(cstr_), + storage_.length_ + 1U); // +1 for null terminating + // character for sake of + // completeness but not actually + // necessary } } @@ -298,36 +285,39 @@ Value::CZString& Value::CZString::operator=(const CZString& other) { return *this; } -#if JSON_HAS_RVALUE_REFERENCES Value::CZString& Value::CZString::operator=(CZString&& other) { cstr_ = other.cstr_; index_ = other.index_; other.cstr_ = nullptr; return *this; } -#endif bool Value::CZString::operator<(const CZString& other) const { - if (!cstr_) return index_ < other.index_; - //return strcmp(cstr_, other.cstr_) < 0; + if (!cstr_) + return index_ < other.index_; + // return strcmp(cstr_, other.cstr_) < 0; // Assume both are strings. unsigned this_len = this->storage_.length_; unsigned other_len = other.storage_.length_; unsigned min_len = std::min<unsigned>(this_len, other_len); JSON_ASSERT(this->cstr_ && other.cstr_); int comp = memcmp(this->cstr_, other.cstr_, min_len); - if (comp < 0) return true; - if (comp > 0) return false; + if (comp < 0) + return true; + if (comp > 0) + return false; return (this_len < other_len); } bool Value::CZString::operator==(const CZString& other) const { - if (!cstr_) return index_ == other.index_; - //return strcmp(cstr_, other.cstr_) == 0; + if (!cstr_) + return index_ == other.index_; + // return strcmp(cstr_, other.cstr_) == 0; // Assume both are strings. unsigned this_len = this->storage_.length_; unsigned other_len = other.storage_.length_; - if (this_len != other_len) return false; + if (this_len != other_len) + return false; JSON_ASSERT(this->cstr_ && other.cstr_); int comp = memcmp(this->cstr_, other.cstr_, this_len); return comp == 0; @@ -335,10 +325,12 @@ bool Value::CZString::operator==(const CZString& other) const { ArrayIndex Value::CZString::index() const { return index_; } -//const char* Value::CZString::c_str() const { return cstr_; } +// const char* Value::CZString::c_str() const { return cstr_; } const char* Value::CZString::data() const { return cstr_; } unsigned Value::CZString::length() const { return storage_.length_; } -bool Value::CZString::isStaticString() const { return storage_.policy_ == noDuplication; } +bool Value::CZString::isStaticString() const { + return storage_.policy_ == noDuplication; +} // ////////////////////////////////////////////////////////////////// // ////////////////////////////////////////////////////////////////// @@ -352,10 +344,10 @@ bool Value::CZString::isStaticString() const { return storage_.policy_ == noDupl * memset( this, 0, sizeof(Value) ) * This optimization is used in ValueInternalMap fast allocator. */ -Value::Value(ValueType vtype) { +Value::Value(ValueType type) { static char const emptyString[] = ""; - initBasic(vtype); - switch (vtype) { + initBasic(type); + switch (type) { case nullValue: break; case intValue: @@ -408,20 +400,22 @@ Value::Value(double value) { Value::Value(const char* value) { initBasic(stringValue, true); - JSON_ASSERT_MESSAGE(value != NULL, "Null Value Passed to Value Constructor"); - value_.string_ = duplicateAndPrefixStringValue(value, static_cast<unsigned>(strlen(value))); + JSON_ASSERT_MESSAGE(value != nullptr, + "Null Value Passed to Value Constructor"); + value_.string_ = duplicateAndPrefixStringValue( + value, static_cast<unsigned>(strlen(value))); } -Value::Value(const char* beginValue, const char* endValue) { +Value::Value(const char* begin, const char* end) { initBasic(stringValue, true); value_.string_ = - duplicateAndPrefixStringValue(beginValue, static_cast<unsigned>(endValue - beginValue)); + duplicateAndPrefixStringValue(begin, static_cast<unsigned>(end - begin)); } -Value::Value(const JSONCPP_STRING& value) { +Value::Value(const String& value) { initBasic(stringValue, true); - value_.string_ = - duplicateAndPrefixStringValue(value.data(), static_cast<unsigned>(value.length())); + value_.string_ = duplicateAndPrefixStringValue( + value.data(), static_cast<unsigned>(value.length())); } Value::Value(const StaticString& value) { @@ -429,114 +423,44 @@ Value::Value(const StaticString& value) { value_.string_ = const_cast<char*>(value.c_str()); } -#ifdef JSON_USE_CPPTL -Value::Value(const CppTL::ConstString& value) { - initBasic(stringValue, true); - value_.string_ = duplicateAndPrefixStringValue(value, static_cast<unsigned>(value.length())); -} -#endif - Value::Value(bool value) { initBasic(booleanValue); value_.bool_ = value; } -Value::Value(Value const& other) - : type_(other.type_), allocated_(false) - , - comments_(0), start_(other.start_), limit_(other.limit_) -{ - switch (type_) { - case nullValue: - case intValue: - case uintValue: - case realValue: - case booleanValue: - value_ = other.value_; - break; - case stringValue: - if (other.value_.string_ && other.allocated_) { - unsigned len; - char const* str; - decodePrefixedString(other.allocated_, other.value_.string_, - &len, &str); - value_.string_ = duplicateAndPrefixStringValue(str, len); - allocated_ = true; - } else { - value_.string_ = other.value_.string_; - allocated_ = false; - } - break; - case arrayValue: - case objectValue: - value_.map_ = new ObjectValues(*other.value_.map_); - break; - default: - JSON_ASSERT_UNREACHABLE; - } - if (other.comments_) { - comments_ = new CommentInfo[numberOfCommentPlacement]; - for (int comment = 0; comment < numberOfCommentPlacement; ++comment) { - const CommentInfo& otherComment = other.comments_[comment]; - if (otherComment.comment_) - comments_[comment].setComment( - otherComment.comment_, strlen(otherComment.comment_)); - } - } +Value::Value(const Value& other) { + dupPayload(other); + dupMeta(other); } -#if JSON_HAS_RVALUE_REFERENCES -// Move constructor Value::Value(Value&& other) { initBasic(nullValue); swap(other); } -#endif Value::~Value() { - switch (type_) { - case nullValue: - case intValue: - case uintValue: - case realValue: - case booleanValue: - break; - case stringValue: - if (allocated_) - releasePrefixedStringValue(value_.string_); - break; - case arrayValue: - case objectValue: - delete value_.map_; - break; - default: - JSON_ASSERT_UNREACHABLE; - } - - delete[] comments_; - + releasePayload(); value_.uint_ = 0; } -Value& Value::operator=(Value other) { - swap(other); +Value& Value::operator=(const Value& other) { + Value(other).swap(*this); + return *this; +} + +Value& Value::operator=(Value&& other) { + other.swap(*this); return *this; } void Value::swapPayload(Value& other) { - ValueType temp = type_; - type_ = other.type_; - other.type_ = temp; + std::swap(bits_, other.bits_); std::swap(value_, other.value_); - int temp2 = allocated_; - allocated_ = other.allocated_; - other.allocated_ = temp2 & 0x1; } void Value::copyPayload(const Value& other) { - type_ = other.type_; - value_ = other.value_; - allocated_ = other.allocated_; + releasePayload(); + dupPayload(other); } void Value::swap(Value& other) { @@ -548,12 +472,12 @@ void Value::swap(Value& other) { void Value::copy(const Value& other) { copyPayload(other); - comments_ = other.comments_; - start_ = other.start_; - limit_ = other.limit_; + dupMeta(other); } -ValueType Value::type() const { return type_; } +ValueType Value::type() const { + return static_cast<ValueType>(bits_.value_type_); +} int Value::compare(const Value& other) const { if (*this < other) @@ -564,10 +488,10 @@ int Value::compare(const Value& other) const { } bool Value::operator<(const Value& other) const { - int typeDelta = type_ - other.type_; + int typeDelta = type() - other.type(); if (typeDelta) - return typeDelta < 0 ? true : false; - switch (type_) { + return typeDelta < 0; + switch (type()) { case nullValue: return false; case intValue: @@ -578,30 +502,33 @@ bool Value::operator<(const Value& other) const { return value_.real_ < other.value_.real_; case booleanValue: return value_.bool_ < other.value_.bool_; - case stringValue: - { - if ((value_.string_ == 0) || (other.value_.string_ == 0)) { - if (other.value_.string_) return true; - else return false; + case stringValue: { + if ((value_.string_ == nullptr) || (other.value_.string_ == nullptr)) { + return other.value_.string_ != nullptr; } unsigned this_len; unsigned other_len; char const* this_str; char const* other_str; - decodePrefixedString(this->allocated_, this->value_.string_, &this_len, &this_str); - decodePrefixedString(other.allocated_, other.value_.string_, &other_len, &other_str); + decodePrefixedString(this->isAllocated(), this->value_.string_, &this_len, + &this_str); + decodePrefixedString(other.isAllocated(), other.value_.string_, &other_len, + &other_str); unsigned min_len = std::min<unsigned>(this_len, other_len); JSON_ASSERT(this_str && other_str); int comp = memcmp(this_str, other_str, min_len); - if (comp < 0) return true; - if (comp > 0) return false; + if (comp < 0) + return true; + if (comp > 0) + return false; return (this_len < other_len); } case arrayValue: case objectValue: { - int delta = int(value_.map_->size() - other.value_.map_->size()); - if (delta) - return delta < 0; + auto thisSize = value_.map_->size(); + auto otherSize = other.value_.map_->size(); + if (thisSize != otherSize) + return thisSize < otherSize; return (*value_.map_) < (*other.value_.map_); } default: @@ -617,14 +544,9 @@ bool Value::operator>=(const Value& other) const { return !(*this < other); } bool Value::operator>(const Value& other) const { return other < *this; } bool Value::operator==(const Value& other) const { - // if ( type_ != other.type_ ) - // GCC 2.95.3 says: - // attempt to take address of bit-field structure member `Json::Value::type_' - // Beats me, but a temp solves the problem. - int temp = other.type_; - if (type_ != temp) + if (type() != other.type()) return false; - switch (type_) { + switch (type()) { case nullValue: return true; case intValue: @@ -635,18 +557,20 @@ bool Value::operator==(const Value& other) const { return value_.real_ == other.value_.real_; case booleanValue: return value_.bool_ == other.value_.bool_; - case stringValue: - { - if ((value_.string_ == 0) || (other.value_.string_ == 0)) { + case stringValue: { + if ((value_.string_ == nullptr) || (other.value_.string_ == nullptr)) { return (value_.string_ == other.value_.string_); } unsigned this_len; unsigned other_len; char const* this_str; char const* other_str; - decodePrefixedString(this->allocated_, this->value_.string_, &this_len, &this_str); - decodePrefixedString(other.allocated_, other.value_.string_, &other_len, &other_str); - if (this_len != other_len) return false; + decodePrefixedString(this->isAllocated(), this->value_.string_, &this_len, + &this_str); + decodePrefixedString(other.isAllocated(), other.value_.string_, &other_len, + &other_str); + if (this_len != other_len) + return false; JSON_ASSERT(this_str && other_str); int comp = memcmp(this_str, other_str, this_len); return comp == 0; @@ -664,47 +588,55 @@ bool Value::operator==(const Value& other) const { bool Value::operator!=(const Value& other) const { return !(*this == other); } const char* Value::asCString() const { - JSON_ASSERT_MESSAGE(type_ == stringValue, + JSON_ASSERT_MESSAGE(type() == stringValue, "in Json::Value::asCString(): requires stringValue"); - if (value_.string_ == 0) return 0; + if (value_.string_ == nullptr) + return nullptr; unsigned this_len; char const* this_str; - decodePrefixedString(this->allocated_, this->value_.string_, &this_len, &this_str); + decodePrefixedString(this->isAllocated(), this->value_.string_, &this_len, + &this_str); return this_str; } #if JSONCPP_USING_SECURE_MEMORY unsigned Value::getCStringLength() const { - JSON_ASSERT_MESSAGE(type_ == stringValue, - "in Json::Value::asCString(): requires stringValue"); - if (value_.string_ == 0) return 0; + JSON_ASSERT_MESSAGE(type() == stringValue, + "in Json::Value::asCString(): requires stringValue"); + if (value_.string_ == 0) + return 0; unsigned this_len; char const* this_str; - decodePrefixedString(this->allocated_, this->value_.string_, &this_len, &this_str); + decodePrefixedString(this->isAllocated(), this->value_.string_, &this_len, + &this_str); return this_len; } #endif -bool Value::getString(char const** str, char const** cend) const { - if (type_ != stringValue) return false; - if (value_.string_ == 0) return false; +bool Value::getString(char const** begin, char const** end) const { + if (type() != stringValue) + return false; + if (value_.string_ == nullptr) + return false; unsigned length; - decodePrefixedString(this->allocated_, this->value_.string_, &length, str); - *cend = *str + length; + decodePrefixedString(this->isAllocated(), this->value_.string_, &length, + begin); + *end = *begin + length; return true; } -JSONCPP_STRING Value::asString() const { - switch (type_) { +String Value::asString() const { + switch (type()) { case nullValue: return ""; - case stringValue: - { - if (value_.string_ == 0) return ""; + case stringValue: { + if (value_.string_ == nullptr) + return ""; unsigned this_len; char const* this_str; - decodePrefixedString(this->allocated_, this->value_.string_, &this_len, &this_str); - return JSONCPP_STRING(this_str, this_len); + decodePrefixedString(this->isAllocated(), this->value_.string_, &this_len, + &this_str); + return String(this_str, this_len); } case booleanValue: return value_.bool_ ? "true" : "false"; @@ -719,18 +651,8 @@ JSONCPP_STRING Value::asString() const { } } -#ifdef JSON_USE_CPPTL -CppTL::ConstString Value::asConstString() const { - unsigned len; - char const* str; - decodePrefixedString(allocated_, value_.string_, - &len, &str); - return CppTL::ConstString(str, len); -} -#endif - Value::Int Value::asInt() const { - switch (type_) { + switch (type()) { case intValue: JSON_ASSERT_MESSAGE(isInt(), "LargestInt out of Int range"); return Int(value_.int_); @@ -752,7 +674,7 @@ Value::Int Value::asInt() const { } Value::UInt Value::asUInt() const { - switch (type_) { + switch (type()) { case intValue: JSON_ASSERT_MESSAGE(isUInt(), "LargestInt out of UInt range"); return UInt(value_.int_); @@ -776,7 +698,7 @@ Value::UInt Value::asUInt() const { #if defined(JSON_HAS_INT64) Value::Int64 Value::asInt64() const { - switch (type_) { + switch (type()) { case intValue: return Int64(value_.int_); case uintValue: @@ -797,7 +719,7 @@ Value::Int64 Value::asInt64() const { } Value::UInt64 Value::asUInt64() const { - switch (type_) { + switch (type()) { case intValue: JSON_ASSERT_MESSAGE(isUInt64(), "LargestInt out of UInt64 range"); return UInt64(value_.int_); @@ -835,7 +757,7 @@ LargestUInt Value::asLargestUInt() const { } double Value::asDouble() const { - switch (type_) { + switch (type()) { case intValue: return static_cast<double>(value_.int_); case uintValue: @@ -857,7 +779,7 @@ double Value::asDouble() const { } float Value::asFloat() const { - switch (type_) { + switch (type()) { case intValue: return static_cast<float>(value_.int_); case uintValue: @@ -872,7 +794,7 @@ float Value::asFloat() const { case nullValue: return 0.0; case booleanValue: - return value_.bool_ ? 1.0f : 0.0f; + return value_.bool_ ? 1.0F : 0.0F; default: break; } @@ -880,18 +802,20 @@ float Value::asFloat() const { } bool Value::asBool() const { - switch (type_) { + switch (type()) { case booleanValue: return value_.bool_; case nullValue: return false; case intValue: - return value_.int_ ? true : false; + return value_.int_ != 0; case uintValue: - return value_.uint_ ? true : false; - case realValue: - // This is kind of strange. Not recommended. - return (value_.real_ != 0.0) ? true : false; + return value_.uint_ != 0; + case realValue: { + // According to JavaScript language zero or NaN is regarded as false + const auto value_classification = std::fpclassify(value_.real_); + return value_classification != FP_ZERO && value_classification != FP_NAN; + } default: break; } @@ -902,30 +826,30 @@ bool Value::isConvertibleTo(ValueType other) const { switch (other) { case nullValue: return (isNumeric() && asDouble() == 0.0) || - (type_ == booleanValue && value_.bool_ == false) || - (type_ == stringValue && asString().empty()) || - (type_ == arrayValue && value_.map_->size() == 0) || - (type_ == objectValue && value_.map_->size() == 0) || - type_ == nullValue; + (type() == booleanValue && !value_.bool_) || + (type() == stringValue && asString().empty()) || + (type() == arrayValue && value_.map_->empty()) || + (type() == objectValue && value_.map_->empty()) || + type() == nullValue; case intValue: return isInt() || - (type_ == realValue && InRange(value_.real_, minInt, maxInt)) || - type_ == booleanValue || type_ == nullValue; + (type() == realValue && InRange(value_.real_, minInt, maxInt)) || + type() == booleanValue || type() == nullValue; case uintValue: return isUInt() || - (type_ == realValue && InRange(value_.real_, 0, maxUInt)) || - type_ == booleanValue || type_ == nullValue; + (type() == realValue && InRange(value_.real_, 0, maxUInt)) || + type() == booleanValue || type() == nullValue; case realValue: - return isNumeric() || type_ == booleanValue || type_ == nullValue; + return isNumeric() || type() == booleanValue || type() == nullValue; case booleanValue: - return isNumeric() || type_ == booleanValue || type_ == nullValue; + return isNumeric() || type() == booleanValue || type() == nullValue; case stringValue: - return isNumeric() || type_ == booleanValue || type_ == stringValue || - type_ == nullValue; + return isNumeric() || type() == booleanValue || type() == stringValue || + type() == nullValue; case arrayValue: - return type_ == arrayValue || type_ == nullValue; + return type() == arrayValue || type() == nullValue; case objectValue: - return type_ == objectValue || type_ == nullValue; + return type() == objectValue || type() == nullValue; } JSON_ASSERT_UNREACHABLE; return false; @@ -933,7 +857,7 @@ bool Value::isConvertibleTo(ValueType other) const { /// Number of values in array or object ArrayIndex Value::size() const { - switch (type_) { + switch (type()) { case nullValue: case intValue: case uintValue: @@ -957,20 +881,19 @@ ArrayIndex Value::size() const { bool Value::empty() const { if (isNull() || isArray() || isObject()) - return size() == 0u; - else - return false; + return size() == 0U; + return false; } -bool Value::operator!() const { return isNull(); } +Value::operator bool() const { return !isNull(); } void Value::clear() { - JSON_ASSERT_MESSAGE(type_ == nullValue || type_ == arrayValue || - type_ == objectValue, + JSON_ASSERT_MESSAGE(type() == nullValue || type() == arrayValue || + type() == objectValue, "in Json::Value::clear(): requires complex value"); start_ = 0; limit_ = 0; - switch (type_) { + switch (type()) { case arrayValue: case objectValue: value_.map_->clear(); @@ -981,15 +904,15 @@ void Value::clear() { } void Value::resize(ArrayIndex newSize) { - JSON_ASSERT_MESSAGE(type_ == nullValue || type_ == arrayValue, + JSON_ASSERT_MESSAGE(type() == nullValue || type() == arrayValue, "in Json::Value::resize(): requires arrayValue"); - if (type_ == nullValue) + if (type() == nullValue) *this = Value(arrayValue); ArrayIndex oldSize = size(); if (newSize == 0) clear(); else if (newSize > oldSize) - (*this)[newSize - 1]; + this->operator[](newSize - 1); else { for (ArrayIndex index = newSize; index < oldSize; ++index) { value_.map_->erase(index); @@ -1000,12 +923,12 @@ void Value::resize(ArrayIndex newSize) { Value& Value::operator[](ArrayIndex index) { JSON_ASSERT_MESSAGE( - type_ == nullValue || type_ == arrayValue, + type() == nullValue || type() == arrayValue, "in Json::Value::operator[](ArrayIndex): requires arrayValue"); - if (type_ == nullValue) + if (type() == nullValue) *this = Value(arrayValue); CZString key(index); - ObjectValues::iterator it = value_.map_->lower_bound(key); + auto it = value_.map_->lower_bound(key); if (it != value_.map_->end() && (*it).first == key) return (*it).second; @@ -1023,9 +946,9 @@ Value& Value::operator[](int index) { const Value& Value::operator[](ArrayIndex index) const { JSON_ASSERT_MESSAGE( - type_ == nullValue || type_ == arrayValue, + type() == nullValue || type() == arrayValue, "in Json::Value::operator[](ArrayIndex)const: requires arrayValue"); - if (type_ == nullValue) + if (type() == nullValue) return nullSingleton(); CZString key(index); ObjectValues::const_iterator it = value_.map_->find(key); @@ -1041,26 +964,85 @@ const Value& Value::operator[](int index) const { return (*this)[ArrayIndex(index)]; } -void Value::initBasic(ValueType vtype, bool allocated) { - type_ = vtype; - allocated_ = allocated; - comments_ = 0; +void Value::initBasic(ValueType type, bool allocated) { + setType(type); + setIsAllocated(allocated); + comments_ = Comments{}; start_ = 0; limit_ = 0; } +void Value::dupPayload(const Value& other) { + setType(other.type()); + setIsAllocated(false); + switch (type()) { + case nullValue: + case intValue: + case uintValue: + case realValue: + case booleanValue: + value_ = other.value_; + break; + case stringValue: + if (other.value_.string_ && other.isAllocated()) { + unsigned len; + char const* str; + decodePrefixedString(other.isAllocated(), other.value_.string_, &len, + &str); + value_.string_ = duplicateAndPrefixStringValue(str, len); + setIsAllocated(true); + } else { + value_.string_ = other.value_.string_; + } + break; + case arrayValue: + case objectValue: + value_.map_ = new ObjectValues(*other.value_.map_); + break; + default: + JSON_ASSERT_UNREACHABLE; + } +} + +void Value::releasePayload() { + switch (type()) { + case nullValue: + case intValue: + case uintValue: + case realValue: + case booleanValue: + break; + case stringValue: + if (isAllocated()) + releasePrefixedStringValue(value_.string_); + break; + case arrayValue: + case objectValue: + delete value_.map_; + break; + default: + JSON_ASSERT_UNREACHABLE; + } +} + +void Value::dupMeta(const Value& other) { + comments_ = other.comments_; + start_ = other.start_; + limit_ = other.limit_; +} + // Access an object value by name, create a null member if it does not exist. // @pre Type of '*this' is object or null. // @param key is null-terminated. Value& Value::resolveReference(const char* key) { JSON_ASSERT_MESSAGE( - type_ == nullValue || type_ == objectValue, + type() == nullValue || type() == objectValue, "in Json::Value::resolveReference(): requires objectValue"); - if (type_ == nullValue) + if (type() == nullValue) *this = Value(objectValue); - CZString actualKey( - key, static_cast<unsigned>(strlen(key)), CZString::noDuplication); // NOTE! - ObjectValues::iterator it = value_.map_->lower_bound(actualKey); + CZString actualKey(key, static_cast<unsigned>(strlen(key)), + CZString::noDuplication); // NOTE! + auto it = value_.map_->lower_bound(actualKey); if (it != value_.map_->end() && (*it).first == actualKey) return (*it).second; @@ -1071,16 +1053,15 @@ Value& Value::resolveReference(const char* key) { } // @param key is not null-terminated. -Value& Value::resolveReference(char const* key, char const* cend) -{ +Value& Value::resolveReference(char const* key, char const* end) { JSON_ASSERT_MESSAGE( - type_ == nullValue || type_ == objectValue, + type() == nullValue || type() == objectValue, "in Json::Value::resolveReference(key, end): requires objectValue"); - if (type_ == nullValue) + if (type() == nullValue) *this = Value(objectValue); - CZString actualKey( - key, static_cast<unsigned>(cend-key), CZString::duplicateOnCopy); - ObjectValues::iterator it = value_.map_->lower_bound(actualKey); + CZString actualKey(key, static_cast<unsigned>(end - key), + CZString::duplicateOnCopy); + auto it = value_.map_->lower_bound(actualKey); if (it != value_.map_->end() && (*it).first == actualKey) return (*it).second; @@ -1097,27 +1078,35 @@ Value Value::get(ArrayIndex index, const Value& defaultValue) const { bool Value::isValidIndex(ArrayIndex index) const { return index < size(); } -Value const* Value::find(char const* key, char const* cend) const -{ - JSON_ASSERT_MESSAGE( - type_ == nullValue || type_ == objectValue, - "in Json::Value::find(key, end, found): requires objectValue or nullValue"); - if (type_ == nullValue) return NULL; - CZString actualKey(key, static_cast<unsigned>(cend-key), CZString::noDuplication); +Value const* Value::find(char const* begin, char const* end) const { + JSON_ASSERT_MESSAGE(type() == nullValue || type() == objectValue, + "in Json::Value::find(begin, end): requires " + "objectValue or nullValue"); + if (type() == nullValue) + return nullptr; + CZString actualKey(begin, static_cast<unsigned>(end - begin), + CZString::noDuplication); ObjectValues::const_iterator it = value_.map_->find(actualKey); - if (it == value_.map_->end()) return NULL; + if (it == value_.map_->end()) + return nullptr; return &(*it).second; } -const Value& Value::operator[](const char* key) const -{ +Value* Value::demand(char const* begin, char const* end) { + JSON_ASSERT_MESSAGE(type() == nullValue || type() == objectValue, + "in Json::Value::demand(begin, end): requires " + "objectValue or nullValue"); + return &resolveReference(begin, end); +} +const Value& Value::operator[](const char* key) const { Value const* found = find(key, key + strlen(key)); - if (!found) return nullSingleton(); + if (!found) + return nullSingleton(); return *found; } -Value const& Value::operator[](JSONCPP_STRING const& key) const -{ +Value const& Value::operator[](const String& key) const { Value const* found = find(key.data(), key.data() + key.length()); - if (!found) return nullSingleton(); + if (!found) + return nullSingleton(); return *found; } @@ -1125,7 +1114,7 @@ Value& Value::operator[](const char* key) { return resolveReference(key, key + strlen(key)); } -Value& Value::operator[](const JSONCPP_STRING& key) { +Value& Value::operator[](const String& key) { return resolveReference(key.data(), key.data() + key.length()); } @@ -1133,179 +1122,140 @@ Value& Value::operator[](const StaticString& key) { return resolveReference(key.c_str()); } -#ifdef JSON_USE_CPPTL -Value& Value::operator[](const CppTL::ConstString& key) { - return resolveReference(key.c_str(), key.end_c_str()); -} -Value const& Value::operator[](CppTL::ConstString const& key) const -{ - Value const* found = find(key.c_str(), key.end_c_str()); - if (!found) return nullSingleton(); - return *found; +Value& Value::append(const Value& value) { return append(Value(value)); } + +Value& Value::append(Value&& value) { + JSON_ASSERT_MESSAGE(type() == nullValue || type() == arrayValue, + "in Json::Value::append: requires arrayValue"); + if (type() == nullValue) { + *this = Value(arrayValue); + } + return this->value_.map_->emplace(size(), std::move(value)).first->second; } -#endif -Value& Value::append(const Value& value) { return (*this)[size()] = value; } +bool Value::insert(ArrayIndex index, const Value& newValue) { + return insert(index, Value(newValue)); +} -#if JSON_HAS_RVALUE_REFERENCES - Value& Value::append(Value&& value) { return (*this)[size()] = value; } -#endif +bool Value::insert(ArrayIndex index, Value&& newValue) { + JSON_ASSERT_MESSAGE(type() == nullValue || type() == arrayValue, + "in Json::Value::insert: requires arrayValue"); + ArrayIndex length = size(); + if (index > length) { + return false; + } + for (ArrayIndex i = length; i > index; i--) { + (*this)[i] = std::move((*this)[i - 1]); + } + (*this)[index] = std::move(newValue); + return true; +} -Value Value::get(char const* key, char const* cend, Value const& defaultValue) const -{ - Value const* found = find(key, cend); +Value Value::get(char const* begin, char const* end, + Value const& defaultValue) const { + Value const* found = find(begin, end); return !found ? defaultValue : *found; } -Value Value::get(char const* key, Value const& defaultValue) const -{ +Value Value::get(char const* key, Value const& defaultValue) const { return get(key, key + strlen(key), defaultValue); } -Value Value::get(JSONCPP_STRING const& key, Value const& defaultValue) const -{ +Value Value::get(String const& key, Value const& defaultValue) const { return get(key.data(), key.data() + key.length(), defaultValue); } - -bool Value::removeMember(const char* key, const char* cend, Value* removed) -{ - if (type_ != objectValue) { +bool Value::removeMember(const char* begin, const char* end, Value* removed) { + if (type() != objectValue) { return false; } - CZString actualKey(key, static_cast<unsigned>(cend-key), CZString::noDuplication); - ObjectValues::iterator it = value_.map_->find(actualKey); + CZString actualKey(begin, static_cast<unsigned>(end - begin), + CZString::noDuplication); + auto it = value_.map_->find(actualKey); if (it == value_.map_->end()) return false; - *removed = it->second; + if (removed) + *removed = std::move(it->second); value_.map_->erase(it); return true; } -bool Value::removeMember(const char* key, Value* removed) -{ +bool Value::removeMember(const char* key, Value* removed) { return removeMember(key, key + strlen(key), removed); } -bool Value::removeMember(JSONCPP_STRING const& key, Value* removed) -{ +bool Value::removeMember(String const& key, Value* removed) { return removeMember(key.data(), key.data() + key.length(), removed); } -Value Value::removeMember(const char* key) -{ - JSON_ASSERT_MESSAGE(type_ == nullValue || type_ == objectValue, +void Value::removeMember(const char* key) { + JSON_ASSERT_MESSAGE(type() == nullValue || type() == objectValue, "in Json::Value::removeMember(): requires objectValue"); - if (type_ == nullValue) - return nullSingleton(); + if (type() == nullValue) + return; - Value removed; // null - removeMember(key, key + strlen(key), &removed); - return removed; // still null if removeMember() did nothing -} -Value Value::removeMember(const JSONCPP_STRING& key) -{ - return removeMember(key.c_str()); + CZString actualKey(key, unsigned(strlen(key)), CZString::noDuplication); + value_.map_->erase(actualKey); } +void Value::removeMember(const String& key) { removeMember(key.c_str()); } bool Value::removeIndex(ArrayIndex index, Value* removed) { - if (type_ != arrayValue) { + if (type() != arrayValue) { return false; } CZString key(index); - ObjectValues::iterator it = value_.map_->find(key); + auto it = value_.map_->find(key); if (it == value_.map_->end()) { return false; } - *removed = it->second; + if (removed) + *removed = it->second; ArrayIndex oldSize = size(); // shift left all items left, into the place of the "removed" - for (ArrayIndex i = index; i < (oldSize - 1); ++i){ + for (ArrayIndex i = index; i < (oldSize - 1); ++i) { CZString keey(i); (*value_.map_)[keey] = (*this)[i + 1]; } // erase the last one ("leftover") CZString keyLast(oldSize - 1); - ObjectValues::iterator itLast = value_.map_->find(keyLast); + auto itLast = value_.map_->find(keyLast); value_.map_->erase(itLast); return true; } -#ifdef JSON_USE_CPPTL -Value Value::get(const CppTL::ConstString& key, - const Value& defaultValue) const { - return get(key.c_str(), key.end_c_str(), defaultValue); +bool Value::isMember(char const* begin, char const* end) const { + Value const* value = find(begin, end); + return nullptr != value; } -#endif - -bool Value::isMember(char const* key, char const* cend) const -{ - Value const* value = find(key, cend); - return NULL != value; -} -bool Value::isMember(char const* key) const -{ +bool Value::isMember(char const* key) const { return isMember(key, key + strlen(key)); } -bool Value::isMember(JSONCPP_STRING const& key) const -{ +bool Value::isMember(String const& key) const { return isMember(key.data(), key.data() + key.length()); } -#ifdef JSON_USE_CPPTL -bool Value::isMember(const CppTL::ConstString& key) const { - return isMember(key.c_str(), key.end_c_str()); -} -#endif - Value::Members Value::getMemberNames() const { JSON_ASSERT_MESSAGE( - type_ == nullValue || type_ == objectValue, + type() == nullValue || type() == objectValue, "in Json::Value::getMemberNames(), value must be objectValue"); - if (type_ == nullValue) + if (type() == nullValue) return Value::Members(); Members members; members.reserve(value_.map_->size()); ObjectValues::const_iterator it = value_.map_->begin(); ObjectValues::const_iterator itEnd = value_.map_->end(); for (; it != itEnd; ++it) { - members.push_back(JSONCPP_STRING((*it).first.data(), - (*it).first.length())); + members.push_back(String((*it).first.data(), (*it).first.length())); } return members; } -// -//# ifdef JSON_USE_CPPTL -// EnumMemberNames -// Value::enumMemberNames() const -//{ -// if ( type_ == objectValue ) -// { -// return CppTL::Enum::any( CppTL::Enum::transform( -// CppTL::Enum::keys( *(value_.map_), CppTL::Type<const CZString &>() ), -// MemberNamesTransform() ) ); -// } -// return EnumMemberNames(); -//} -// -// -// EnumValues -// Value::enumValues() const -//{ -// if ( type_ == objectValue || type_ == arrayValue ) -// return CppTL::Enum::anyValues( *(value_.map_), -// CppTL::Type<const Value &>() ); -// return EnumValues(); -//} -// -//# endif static bool IsIntegral(double d) { double integral_part; return modf(d, &integral_part) == 0.0; } -bool Value::isNull() const { return type_ == nullValue; } +bool Value::isNull() const { return type() == nullValue; } -bool Value::isBool() const { return type_ == booleanValue; } +bool Value::isBool() const { return type() == booleanValue; } bool Value::isInt() const { - switch (type_) { + switch (type()) { case intValue: #if defined(JSON_HAS_INT64) return value_.int_ >= minInt && value_.int_ <= maxInt; @@ -1324,7 +1274,7 @@ bool Value::isInt() const { } bool Value::isUInt() const { - switch (type_) { + switch (type()) { case intValue: #if defined(JSON_HAS_INT64) return value_.int_ >= 0 && LargestUInt(value_.int_) <= LargestUInt(maxUInt); @@ -1348,7 +1298,7 @@ bool Value::isUInt() const { bool Value::isInt64() const { #if defined(JSON_HAS_INT64) - switch (type_) { + switch (type()) { case intValue: return true; case uintValue: @@ -1368,7 +1318,7 @@ bool Value::isInt64() const { bool Value::isUInt64() const { #if defined(JSON_HAS_INT64) - switch (type_) { + switch (type()) { case intValue: return value_.int_ >= 0; case uintValue: @@ -1387,61 +1337,92 @@ bool Value::isUInt64() const { } bool Value::isIntegral() const { - switch (type_) { - case intValue: - case uintValue: - return true; - case realValue: + switch (type()) { + case intValue: + case uintValue: + return true; + case realValue: #if defined(JSON_HAS_INT64) - // Note that maxUInt64 (= 2^64 - 1) is not exactly representable as a - // double, so double(maxUInt64) will be rounded up to 2^64. Therefore we - // require the value to be strictly less than the limit. - return value_.real_ >= double(minInt64) && value_.real_ < maxUInt64AsDouble && IsIntegral(value_.real_); + // Note that maxUInt64 (= 2^64 - 1) is not exactly representable as a + // double, so double(maxUInt64) will be rounded up to 2^64. Therefore we + // require the value to be strictly less than the limit. + return value_.real_ >= double(minInt64) && + value_.real_ < maxUInt64AsDouble && IsIntegral(value_.real_); #else - return value_.real_ >= minInt && value_.real_ <= maxUInt && IsIntegral(value_.real_); + return value_.real_ >= minInt && value_.real_ <= maxUInt && + IsIntegral(value_.real_); #endif // JSON_HAS_INT64 - default: - break; + default: + break; } return false; } -bool Value::isDouble() const { return type_ == intValue || type_ == uintValue || type_ == realValue; } +bool Value::isDouble() const { + return type() == intValue || type() == uintValue || type() == realValue; +} bool Value::isNumeric() const { return isDouble(); } -bool Value::isString() const { return type_ == stringValue; } +bool Value::isString() const { return type() == stringValue; } -bool Value::isArray() const { return type_ == arrayValue; } +bool Value::isArray() const { return type() == arrayValue; } -bool Value::isObject() const { return type_ == objectValue; } +bool Value::isObject() const { return type() == objectValue; } -void Value::setComment(const char* comment, size_t len, CommentPlacement placement) { - if (!comments_) - comments_ = new CommentInfo[numberOfCommentPlacement]; - if ((len > 0) && (comment[len-1] == '\n')) { - // Always discard trailing newline, to aid indentation. - len -= 1; - } - comments_[placement].setComment(comment, len); +Value::Comments::Comments(const Comments& that) + : ptr_{cloneUnique(that.ptr_)} {} + +Value::Comments::Comments(Comments&& that) : ptr_{std::move(that.ptr_)} {} + +Value::Comments& Value::Comments::operator=(const Comments& that) { + ptr_ = cloneUnique(that.ptr_); + return *this; } -void Value::setComment(const char* comment, CommentPlacement placement) { - setComment(comment, strlen(comment), placement); +Value::Comments& Value::Comments::operator=(Comments&& that) { + ptr_ = std::move(that.ptr_); + return *this; +} + +bool Value::Comments::has(CommentPlacement slot) const { + return ptr_ && !(*ptr_)[slot].empty(); } -void Value::setComment(const JSONCPP_STRING& comment, CommentPlacement placement) { - setComment(comment.c_str(), comment.length(), placement); +String Value::Comments::get(CommentPlacement slot) const { + if (!ptr_) + return {}; + return (*ptr_)[slot]; +} + +void Value::Comments::set(CommentPlacement slot, String comment) { + if (!ptr_) { + ptr_ = std::unique_ptr<Array>(new Array()); + } + // check comments array boundry. + if (slot < CommentPlacement::numberOfCommentPlacement) { + (*ptr_)[slot] = std::move(comment); + } +} + +void Value::setComment(String comment, CommentPlacement placement) { + if (!comment.empty() && (comment.back() == '\n')) { + // Always discard trailing newline, to aid indentation. + comment.pop_back(); + } + JSON_ASSERT(!comment.empty()); + JSON_ASSERT_MESSAGE( + comment[0] == '\0' || comment[0] == '/', + "in Json::Value::setComment(): Comments must start with /"); + comments_.set(placement, std::move(comment)); } bool Value::hasComment(CommentPlacement placement) const { - return comments_ != 0 && comments_[placement].comment_ != 0; + return comments_.has(placement); } -JSONCPP_STRING Value::getComment(CommentPlacement placement) const { - if (hasComment(placement)) - return comments_[placement].comment_; - return ""; +String Value::getComment(CommentPlacement placement) const { + return comments_.get(placement); } void Value::setOffsetStart(ptrdiff_t start) { start_ = start; } @@ -1452,18 +1433,18 @@ ptrdiff_t Value::getOffsetStart() const { return start_; } ptrdiff_t Value::getOffsetLimit() const { return limit_; } -JSONCPP_STRING Value::toStyledString() const { +String Value::toStyledString() const { StreamWriterBuilder builder; - JSONCPP_STRING out = this->hasComment(commentBefore) ? "\n" : ""; + String out = this->hasComment(commentBefore) ? "\n" : ""; out += Json::writeString(builder, *this); - out += "\n"; + out += '\n'; return out; } Value::const_iterator Value::begin() const { - switch (type_) { + switch (type()) { case arrayValue: case objectValue: if (value_.map_) @@ -1472,11 +1453,11 @@ Value::const_iterator Value::begin() const { default: break; } - return const_iterator(); + return {}; } Value::const_iterator Value::end() const { - switch (type_) { + switch (type()) { case arrayValue: case objectValue: if (value_.map_) @@ -1485,11 +1466,11 @@ Value::const_iterator Value::end() const { default: break; } - return const_iterator(); + return {}; } Value::iterator Value::begin() { - switch (type_) { + switch (type()) { case arrayValue: case objectValue: if (value_.map_) @@ -1502,7 +1483,7 @@ Value::iterator Value::begin() { } Value::iterator Value::end() { - switch (type_) { + switch (type()) { case arrayValue: case objectValue: if (value_.map_) @@ -1517,25 +1498,20 @@ Value::iterator Value::end() { // class PathArgument // ////////////////////////////////////////////////////////////////// -PathArgument::PathArgument() : key_(), index_(), kind_(kindNone) {} +PathArgument::PathArgument() = default; PathArgument::PathArgument(ArrayIndex index) - : key_(), index_(index), kind_(kindIndex) {} + : index_(index), kind_(kindIndex) {} -PathArgument::PathArgument(const char* key) - : key_(key), index_(), kind_(kindKey) {} +PathArgument::PathArgument(const char* key) : key_(key), kind_(kindKey) {} -PathArgument::PathArgument(const JSONCPP_STRING& key) - : key_(key.c_str()), index_(), kind_(kindKey) {} +PathArgument::PathArgument(String key) : key_(std::move(key)), kind_(kindKey) {} // class Path // ////////////////////////////////////////////////////////////////// -Path::Path(const JSONCPP_STRING& path, - const PathArgument& a1, - const PathArgument& a2, - const PathArgument& a3, - const PathArgument& a4, +Path::Path(const String& path, const PathArgument& a1, const PathArgument& a2, + const PathArgument& a3, const PathArgument& a4, const PathArgument& a5) { InArgs in; in.reserve(5); @@ -1547,10 +1523,10 @@ Path::Path(const JSONCPP_STRING& path, makePath(path, in); } -void Path::makePath(const JSONCPP_STRING& path, const InArgs& in) { +void Path::makePath(const String& path, const InArgs& in) { const char* current = path.c_str(); const char* end = current + path.length(); - InArgs::const_iterator itInArg = in.begin(); + auto itInArg = in.begin(); while (current != end) { if (*current == '[') { ++current; @@ -1573,13 +1549,12 @@ void Path::makePath(const JSONCPP_STRING& path, const InArgs& in) { const char* beginName = current; while (current != end && !strchr("[.", *current)) ++current; - args_.push_back(JSONCPP_STRING(beginName, current)); + args_.push_back(String(beginName, current)); } } } -void Path::addPathInArg(const JSONCPP_STRING& /*path*/, - const InArgs& in, +void Path::addPathInArg(const String& /*path*/, const InArgs& in, InArgs::const_iterator& itInArg, PathArgument::Kind kind) { if (itInArg == in.end()) { @@ -1591,30 +1566,29 @@ void Path::addPathInArg(const JSONCPP_STRING& /*path*/, } } -void Path::invalidPath(const JSONCPP_STRING& /*path*/, int /*location*/) { +void Path::invalidPath(const String& /*path*/, int /*location*/) { // Error: invalid path. } const Value& Path::resolve(const Value& root) const { const Value* node = &root; - for (Args::const_iterator it = args_.begin(); it != args_.end(); ++it) { - const PathArgument& arg = *it; + for (const auto& arg : args_) { if (arg.kind_ == PathArgument::kindIndex) { if (!node->isArray() || !node->isValidIndex(arg.index_)) { - // Error: unable to resolve path (array value expected at position... - return Value::null; + // Error: unable to resolve path (array value expected at position... ) + return Value::nullSingleton(); } node = &((*node)[arg.index_]); } else if (arg.kind_ == PathArgument::kindKey) { if (!node->isObject()) { // Error: unable to resolve path (object value expected at position...) - return Value::null; + return Value::nullSingleton(); } node = &((*node)[arg.key_]); if (node == &Value::nullSingleton()) { // Error: unable to resolve path (object has no member named '' at // position...) - return Value::null; + return Value::nullSingleton(); } } } @@ -1623,8 +1597,7 @@ const Value& Path::resolve(const Value& root) const { Value Path::resolve(const Value& root, const Value& defaultValue) const { const Value* node = &root; - for (Args::const_iterator it = args_.begin(); it != args_.end(); ++it) { - const PathArgument& arg = *it; + for (const auto& arg : args_) { if (arg.kind_ == PathArgument::kindIndex) { if (!node->isArray() || !node->isValidIndex(arg.index_)) return defaultValue; @@ -1642,8 +1615,7 @@ Value Path::resolve(const Value& root, const Value& defaultValue) const { Value& Path::make(Value& root) const { Value* node = &root; - for (Args::const_iterator it = args_.begin(); it != args_.end(); ++it) { - const PathArgument& arg = *it; + for (const auto& arg : args_) { if (arg.kind_ == PathArgument::kindIndex) { if (!node->isArray()) { // Error: node is not an array at position ... diff --git a/Utilities/cmjsoncpp/src/lib_json/json_valueiterator.inl b/Utilities/cmjsoncpp/src/lib_json/json_valueiterator.inl index 5243bfe..d6128b8 100644 --- a/Utilities/cmjsoncpp/src/lib_json/json_valueiterator.inl +++ b/Utilities/cmjsoncpp/src/lib_json/json_valueiterator.inl @@ -15,31 +15,21 @@ namespace Json { // ////////////////////////////////////////////////////////////////// // ////////////////////////////////////////////////////////////////// -ValueIteratorBase::ValueIteratorBase() - : current_(), isNull_(true) { -} +ValueIteratorBase::ValueIteratorBase() : current_() {} ValueIteratorBase::ValueIteratorBase( const Value::ObjectValues::iterator& current) : current_(current), isNull_(false) {} -Value& ValueIteratorBase::deref() const { - return current_->second; -} +Value& ValueIteratorBase::deref() { return current_->second; } +const Value& ValueIteratorBase::deref() const { return current_->second; } -void ValueIteratorBase::increment() { - ++current_; -} +void ValueIteratorBase::increment() { ++current_; } -void ValueIteratorBase::decrement() { - --current_; -} +void ValueIteratorBase::decrement() { --current_; } ValueIteratorBase::difference_type ValueIteratorBase::computeDistance(const SelfType& other) const { -#ifdef JSON_USE_CPPTL_SMALLMAP - return other.current_ - current_; -#else // Iterator for null value are initialized using the default // constructor, which initialize current_ to the default // std::map::iterator. As begin() and end() are two instance @@ -60,7 +50,6 @@ ValueIteratorBase::computeDistance(const SelfType& other) const { ++myDistance; } return myDistance; -#endif } bool ValueIteratorBase::isEqual(const SelfType& other) const { @@ -92,12 +81,13 @@ UInt ValueIteratorBase::index() const { return Value::UInt(-1); } -JSONCPP_STRING ValueIteratorBase::name() const { +String ValueIteratorBase::name() const { char const* keey; char const* end; keey = memberName(&end); - if (!keey) return JSONCPP_STRING(); - return JSONCPP_STRING(keey, end); + if (!keey) + return String(); + return String(keey, end); } char const* ValueIteratorBase::memberName() const { @@ -108,8 +98,8 @@ char const* ValueIteratorBase::memberName() const { char const* ValueIteratorBase::memberName(char const** end) const { const char* cname = (*current_).first.data(); if (!cname) { - *end = NULL; - return NULL; + *end = nullptr; + return nullptr; } *end = cname + (*current_).first.length(); return cname; @@ -123,7 +113,7 @@ char const* ValueIteratorBase::memberName(char const** end) const { // ////////////////////////////////////////////////////////////////// // ////////////////////////////////////////////////////////////////// -ValueConstIterator::ValueConstIterator() {} +ValueConstIterator::ValueConstIterator() = default; ValueConstIterator::ValueConstIterator( const Value::ObjectValues::iterator& current) @@ -146,7 +136,7 @@ operator=(const ValueIteratorBase& other) { // ////////////////////////////////////////////////////////////////// // ////////////////////////////////////////////////////////////////// -ValueIterator::ValueIterator() {} +ValueIterator::ValueIterator() = default; ValueIterator::ValueIterator(const Value::ObjectValues::iterator& current) : ValueIteratorBase(current) {} @@ -156,8 +146,7 @@ ValueIterator::ValueIterator(const ValueConstIterator& other) throwRuntimeError("ConstIterator to Iterator should never be allowed."); } -ValueIterator::ValueIterator(const ValueIterator& other) - : ValueIteratorBase(other) {} +ValueIterator::ValueIterator(const ValueIterator& other) = default; ValueIterator& ValueIterator::operator=(const SelfType& other) { copy(other); diff --git a/Utilities/cmjsoncpp/src/lib_json/json_writer.cpp b/Utilities/cmjsoncpp/src/lib_json/json_writer.cpp index fc86505..8bf02db 100644 --- a/Utilities/cmjsoncpp/src/lib_json/json_writer.cpp +++ b/Utilities/cmjsoncpp/src/lib_json/json_writer.cpp @@ -4,106 +4,81 @@ // See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE #if !defined(JSON_IS_AMALGAMATION) -#include <json/writer.h> #include "json_tool.h" +#include <json/writer.h> #endif // if !defined(JSON_IS_AMALGAMATION) +#include <algorithm> +#include <cassert> +#include <cctype> +#include <cstring> #include <iomanip> #include <memory> +#include <set> #include <sstream> #include <utility> -#include <set> -#include <cassert> -#include <cstring> + +#if __cplusplus >= 201103L +#include <cmath> #include <cstdio> -#if defined(_MSC_VER) && _MSC_VER >= 1200 && _MSC_VER < 1800 // Between VC++ 6.0 and VC++ 11.0 -#include <float.h> -#define isfinite _finite -#elif defined(__sun) && defined(__SVR4) //Solaris -#if !defined(isfinite) -#include <ieeefp.h> -#define isfinite finite +#if !defined(isnan) +#define isnan std::isnan #endif -#elif defined(_AIX) + #if !defined(isfinite) -#include <math.h> -#define isfinite finite -#endif -#elif defined(__hpux) -#if !defined(isfinite) && !defined(__GNUC__) -#if defined(__ia64) && !defined(finite) -#define isfinite(x) ((sizeof(x) == sizeof(float) ? \ - _Isfinitef(x) : _IsFinite(x))) -#else -#include <math.h> -#define isfinite finite -#endif +#define isfinite std::isfinite #endif + #else #include <cmath> -#if !(defined(__QNXNTO__)) // QNX already defines isfinite -#define isfinite std::isfinite -#endif -#endif +#include <cstdio> #if defined(_MSC_VER) -#if !defined(WINCE) && defined(__STDC_SECURE_LIB__) && _MSC_VER >= 1500 // VC++ 9.0 and above -#define snprintf sprintf_s -#elif _MSC_VER >= 1900 // VC++ 14.0 and above -#define snprintf std::snprintf -#else -#define snprintf _snprintf -#endif -#elif defined(__ANDROID__) || defined(__QNXNTO__) -#define snprintf snprintf -#elif __cplusplus >= 201103L -#if !defined(__MINGW32__) && !defined(__CYGWIN__) -#define snprintf std::snprintf -#endif +#if !defined(isnan) +#include <float.h> +#define isnan _isnan #endif -#if defined(__BORLANDC__) +#if !defined(isfinite) #include <float.h> #define isfinite _finite -#define snprintf _snprintf #endif -// Solaris -#if defined(__sun) -# include <ieeefp.h> -# if !defined(isfinite) -# define isfinite finite -# endif -#endif +#if !defined(_CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES) +#define _CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES 1 +#endif //_CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES + +#endif //_MSC_VER -// AIX -#if defined(_AIX) -# if !defined(isfinite) -# define isfinite finite -# endif +#if defined(__sun) && defined(__SVR4) // Solaris +#if !defined(isfinite) +#include <ieeefp.h> +#define isfinite finite +#endif #endif -// HP-UX #if defined(__hpux) -# if !defined(isfinite) -# if defined(__ia64) && !defined(finite) && !defined(__GNUC__) -# define isfinite(x) ((sizeof(x) == sizeof(float) ? \ - _Isfinitef(x) : _Isfinite(x))) -# else -# include <math.h> -# define isfinite finite -# endif -# endif +#if !defined(isfinite) +#if defined(__ia64) && !defined(finite) +#define isfinite(x) \ + ((sizeof(x) == sizeof(float) ? _Isfinitef(x) : _IsFinite(x))) +#endif +#endif +#endif + +#if !defined(isnan) +// IEEE standard states that NaN values will not compare to themselves +#define isnan(x) (x != x) #endif -// Ancient glibc -#if defined(__GLIBC__) && __GLIBC__ == 2 && __GLIBC_MINOR__ < 2 -# if !defined(isfinite) -# define isfinite __finite -# endif +#if !defined(__APPLE__) +#if !defined(isfinite) +#define isfinite finite +#endif +#endif #endif -#if defined(_MSC_VER) && _MSC_VER >= 1400 // VC++ 8.0 +#if defined(_MSC_VER) // Disable warning about strdup being deprecated. #pragma warning(disable : 4996) #endif @@ -111,30 +86,12 @@ namespace Json { #if __cplusplus >= 201103L || (defined(_CPPLIB_VER) && _CPPLIB_VER >= 520) -typedef std::unique_ptr<StreamWriter> StreamWriterPtr; +using StreamWriterPtr = std::unique_ptr<StreamWriter>; #else -typedef std::auto_ptr<StreamWriter> StreamWriterPtr; +using StreamWriterPtr = std::auto_ptr<StreamWriter>; #endif -static bool containsControlCharacter(const char* str) { - while (*str) { - if (isControlCharacter(*(str++))) - return true; - } - return false; -} - -static bool containsControlCharacter0(const char* str, unsigned len) { - char const* end = str + len; - while (end != str) { - if (isControlCharacter(*str) || 0==*str) - return true; - ++str; - } - return false; -} - -JSONCPP_STRING valueToString(LargestInt value) { +String valueToString(LargestInt value) { UIntToStringBuffer buffer; char* current = buffer + sizeof(buffer); if (value == Value::minLargestInt) { @@ -150,7 +107,7 @@ JSONCPP_STRING valueToString(LargestInt value) { return current; } -JSONCPP_STRING valueToString(LargestUInt value) { +String valueToString(LargestUInt value) { UIntToStringBuffer buffer; char* current = buffer + sizeof(buffer); uintToString(value, current); @@ -160,147 +117,171 @@ JSONCPP_STRING valueToString(LargestUInt value) { #if defined(JSON_HAS_INT64) -JSONCPP_STRING valueToString(Int value) { - return valueToString(LargestInt(value)); -} +String valueToString(Int value) { return valueToString(LargestInt(value)); } -JSONCPP_STRING valueToString(UInt value) { - return valueToString(LargestUInt(value)); -} +String valueToString(UInt value) { return valueToString(LargestUInt(value)); } #endif // # if defined(JSON_HAS_INT64) namespace { -JSONCPP_STRING valueToString(double value, bool useSpecialFloats, unsigned int precision) { - // Allocate a buffer that is more than large enough to store the 16 digits of - // precision requested below. - char buffer[36]; - int len = -1; - - char formatString[15]; - snprintf(formatString, sizeof(formatString), "%%.%dg", precision); - +String valueToString(double value, bool useSpecialFloats, + unsigned int precision, PrecisionType precisionType) { // Print into the buffer. We need not request the alternative representation - // that always has a decimal point because JSON doesn't distingish the + // that always has a decimal point because JSON doesn't distinguish the // concepts of reals and integers. - if (isfinite(value)) { - len = snprintf(buffer, sizeof(buffer), formatString, value); - fixNumericLocale(buffer, buffer + len); + if (!isfinite(value)) { + static const char* const reps[2][3] = {{"NaN", "-Infinity", "Infinity"}, + {"null", "-1e+9999", "1e+9999"}}; + return reps[useSpecialFloats ? 0 : 1] + [isnan(value) ? 0 : (value < 0) ? 1 : 2]; + } - // try to ensure we preserve the fact that this was given to us as a double on input - if (!strchr(buffer, '.') && !strchr(buffer, 'e')) { - strcat(buffer, ".0"); + String buffer(size_t(36), '\0'); + while (true) { + int len = jsoncpp_snprintf( + &*buffer.begin(), buffer.size(), + (precisionType == PrecisionType::significantDigits) ? "%.*g" : "%.*f", + precision, value); + assert(len >= 0); + auto wouldPrint = static_cast<size_t>(len); + if (wouldPrint >= buffer.size()) { + buffer.resize(wouldPrint + 1); + continue; } + buffer.resize(wouldPrint); + break; + } - } else { - // IEEE standard states that NaN values will not compare to themselves - if (value != value) { - len = snprintf(buffer, sizeof(buffer), useSpecialFloats ? "NaN" : "null"); - } else if (value < 0) { - len = snprintf(buffer, sizeof(buffer), useSpecialFloats ? "-Infinity" : "-1e+9999"); - } else { - len = snprintf(buffer, sizeof(buffer), useSpecialFloats ? "Infinity" : "1e+9999"); - } + buffer.erase(fixNumericLocale(buffer.begin(), buffer.end()), buffer.end()); + + // strip the zero padding from the right + if (precisionType == PrecisionType::decimalPlaces) { + buffer.erase(fixZerosInTheEnd(buffer.begin(), buffer.end()), buffer.end()); + } + + // try to ensure we preserve the fact that this was given to us as a double on + // input + if (buffer.find('.') == buffer.npos && buffer.find('e') == buffer.npos) { + buffer += ".0"; } - assert(len >= 0); return buffer; } +} // namespace + +String valueToString(double value, unsigned int precision, + PrecisionType precisionType) { + return valueToString(value, false, precision, precisionType); } -JSONCPP_STRING valueToString(double value) { return valueToString(value, false, 17); } +String valueToString(bool value) { return value ? "true" : "false"; } -JSONCPP_STRING valueToString(bool value) { return value ? "true" : "false"; } +static bool doesAnyCharRequireEscaping(char const* s, size_t n) { + assert(s || !n); -JSONCPP_STRING valueToQuotedString(const char* value) { - if (value == NULL) - return ""; - // Not sure how to handle unicode... - if (strpbrk(value, "\"\\\b\f\n\r\t") == NULL && - !containsControlCharacter(value)) - return JSONCPP_STRING("\"") + value + "\""; - // We have to walk value and escape any special characters. - // Appending to JSONCPP_STRING is not efficient, but this should be rare. - // (Note: forward slashes are *not* rare, but I am not escaping them.) - JSONCPP_STRING::size_type maxsize = - strlen(value) * 2 + 3; // allescaped+quotes+NULL - JSONCPP_STRING result; - result.reserve(maxsize); // to avoid lots of mallocs - result += "\""; - for (const char* c = value; *c != 0; ++c) { - switch (*c) { - case '\"': - result += "\\\""; - break; - case '\\': - result += "\\\\"; - break; - case '\b': - result += "\\b"; - break; - case '\f': - result += "\\f"; - break; - case '\n': - result += "\\n"; - break; - case '\r': - result += "\\r"; - break; - case '\t': - result += "\\t"; - break; - // case '/': - // Even though \/ is considered a legal escape in JSON, a bare - // slash is also legal, so I see no reason to escape it. - // (I hope I am not misunderstanding something. - // blep notes: actually escaping \/ may be useful in javascript to avoid </ - // sequence. - // Should add a flag to allow this compatibility mode and prevent this - // sequence from occurring. - default: - if (isControlCharacter(*c)) { - JSONCPP_OSTRINGSTREAM oss; - oss << "\\u" << std::hex << std::uppercase << std::setfill('0') - << std::setw(4) << static_cast<int>(*c); - result += oss.str(); - } else { - result += *c; - } - break; - } + return std::any_of(s, s + n, [](unsigned char c) { + return c == '\\' || c == '"' || c < 0x20 || c > 0x7F; + }); +} + +static unsigned int utf8ToCodepoint(const char*& s, const char* e) { + const unsigned int REPLACEMENT_CHARACTER = 0xFFFD; + + unsigned int firstByte = static_cast<unsigned char>(*s); + + if (firstByte < 0x80) + return firstByte; + + if (firstByte < 0xE0) { + if (e - s < 2) + return REPLACEMENT_CHARACTER; + + unsigned int calculated = + ((firstByte & 0x1F) << 6) | (static_cast<unsigned int>(s[1]) & 0x3F); + s += 1; + // oversized encoded characters are invalid + return calculated < 0x80 ? REPLACEMENT_CHARACTER : calculated; } - result += "\""; + + if (firstByte < 0xF0) { + if (e - s < 3) + return REPLACEMENT_CHARACTER; + + unsigned int calculated = ((firstByte & 0x0F) << 12) | + ((static_cast<unsigned int>(s[1]) & 0x3F) << 6) | + (static_cast<unsigned int>(s[2]) & 0x3F); + s += 2; + // surrogates aren't valid codepoints itself + // shouldn't be UTF-8 encoded + if (calculated >= 0xD800 && calculated <= 0xDFFF) + return REPLACEMENT_CHARACTER; + // oversized encoded characters are invalid + return calculated < 0x800 ? REPLACEMENT_CHARACTER : calculated; + } + + if (firstByte < 0xF8) { + if (e - s < 4) + return REPLACEMENT_CHARACTER; + + unsigned int calculated = ((firstByte & 0x07) << 18) | + ((static_cast<unsigned int>(s[1]) & 0x3F) << 12) | + ((static_cast<unsigned int>(s[2]) & 0x3F) << 6) | + (static_cast<unsigned int>(s[3]) & 0x3F); + s += 3; + // oversized encoded characters are invalid + return calculated < 0x10000 ? REPLACEMENT_CHARACTER : calculated; + } + + return REPLACEMENT_CHARACTER; +} + +static const char hex2[] = "000102030405060708090a0b0c0d0e0f" + "101112131415161718191a1b1c1d1e1f" + "202122232425262728292a2b2c2d2e2f" + "303132333435363738393a3b3c3d3e3f" + "404142434445464748494a4b4c4d4e4f" + "505152535455565758595a5b5c5d5e5f" + "606162636465666768696a6b6c6d6e6f" + "707172737475767778797a7b7c7d7e7f" + "808182838485868788898a8b8c8d8e8f" + "909192939495969798999a9b9c9d9e9f" + "a0a1a2a3a4a5a6a7a8a9aaabacadaeaf" + "b0b1b2b3b4b5b6b7b8b9babbbcbdbebf" + "c0c1c2c3c4c5c6c7c8c9cacbcccdcecf" + "d0d1d2d3d4d5d6d7d8d9dadbdcdddedf" + "e0e1e2e3e4e5e6e7e8e9eaebecedeeef" + "f0f1f2f3f4f5f6f7f8f9fafbfcfdfeff"; + +static String toHex16Bit(unsigned int x) { + const unsigned int hi = (x >> 8) & 0xff; + const unsigned int lo = x & 0xff; + String result(4, ' '); + result[0] = hex2[2 * hi]; + result[1] = hex2[2 * hi + 1]; + result[2] = hex2[2 * lo]; + result[3] = hex2[2 * lo + 1]; return result; } -// https://github.com/upcaste/upcaste/blob/master/src/upcore/src/cstring/strnpbrk.cpp -static char const* strnpbrk(char const* s, char const* accept, size_t n) { - assert((s || !n) && accept); +static void appendRaw(String& result, unsigned ch) { + result += static_cast<char>(ch); +} - char const* const end = s + n; - for (char const* cur = s; cur < end; ++cur) { - int const c = *cur; - for (char const* a = accept; *a; ++a) { - if (*a == c) { - return cur; - } - } - } - return NULL; +static void appendHex(String& result, unsigned ch) { + result.append("\\u").append(toHex16Bit(ch)); } -static JSONCPP_STRING valueToQuotedStringN(const char* value, unsigned length) { - if (value == NULL) + +static String valueToQuotedStringN(const char* value, unsigned length, + bool emitUTF8 = false) { + if (value == nullptr) return ""; - // Not sure how to handle unicode... - if (strnpbrk(value, "\"\\\b\f\n\r\t", length) == NULL && - !containsControlCharacter0(value, length)) - return JSONCPP_STRING("\"") + value + "\""; + + if (!doesAnyCharRequireEscaping(value, length)) + return String("\"") + value + "\""; // We have to walk value and escape any special characters. - // Appending to JSONCPP_STRING is not efficient, but this should be rare. + // Appending to String is not efficient, but this should be rare. // (Note: forward slashes are *not* rare, but I am not escaping them.) - JSONCPP_STRING::size_type maxsize = - length * 2 + 3; // allescaped+quotes+NULL - JSONCPP_STRING result; + String::size_type maxsize = length * 2 + 3; // allescaped+quotes+NULL + String result; result.reserve(maxsize); // to avoid lots of mallocs result += "\""; char const* end = value + length; @@ -335,44 +316,63 @@ static JSONCPP_STRING valueToQuotedStringN(const char* value, unsigned length) { // sequence. // Should add a flag to allow this compatibility mode and prevent this // sequence from occurring. - default: - if ((isControlCharacter(*c)) || (*c == 0)) { - JSONCPP_OSTRINGSTREAM oss; - oss << "\\u" << std::hex << std::uppercase << std::setfill('0') - << std::setw(4) << static_cast<int>(*c); - result += oss.str(); + default: { + if (emitUTF8) { + unsigned codepoint = static_cast<unsigned char>(*c); + if (codepoint < 0x20) { + appendHex(result, codepoint); + } else { + appendRaw(result, codepoint); + } } else { - result += *c; + unsigned codepoint = utf8ToCodepoint(c, end); // modifies `c` + if (codepoint < 0x20) { + appendHex(result, codepoint); + } else if (codepoint < 0x80) { + appendRaw(result, codepoint); + } else if (codepoint < 0x10000) { + // Basic Multilingual Plane + appendHex(result, codepoint); + } else { + // Extended Unicode. Encode 20 bits as a surrogate pair. + codepoint -= 0x10000; + appendHex(result, 0xd800 + ((codepoint >> 10) & 0x3ff)); + appendHex(result, 0xdc00 + (codepoint & 0x3ff)); + } } - break; + } break; } } result += "\""; return result; } +String valueToQuotedString(const char* value) { + return valueToQuotedStringN(value, static_cast<unsigned int>(strlen(value))); +} + // Class Writer // ////////////////////////////////////////////////////////////////// -Writer::~Writer() {} +Writer::~Writer() = default; // Class FastWriter // ////////////////////////////////////////////////////////////////// FastWriter::FastWriter() - : yamlCompatiblityEnabled_(false), dropNullPlaceholders_(false), - omitEndingLineFeed_(false) {} -void FastWriter::enableYAMLCompatibility() { yamlCompatiblityEnabled_ = true; } + = default; + +void FastWriter::enableYAMLCompatibility() { yamlCompatibilityEnabled_ = true; } void FastWriter::dropNullPlaceholders() { dropNullPlaceholders_ = true; } void FastWriter::omitEndingLineFeed() { omitEndingLineFeed_ = true; } -JSONCPP_STRING FastWriter::write(const Value& root) { +String FastWriter::write(const Value& root) { document_.clear(); writeValue(root); if (!omitEndingLineFeed_) - document_ += "\n"; + document_ += '\n'; return document_; } @@ -391,13 +391,13 @@ void FastWriter::writeValue(const Value& value) { case realValue: document_ += valueToString(value.asDouble()); break; - case stringValue: - { + case stringValue: { // Is NULL possible for value.string_? No. char const* str; char const* end; bool ok = value.getString(&str, &end); - if (ok) document_ += valueToQuotedStringN(str, static_cast<unsigned>(end-str)); + if (ok) + document_ += valueToQuotedStringN(str, static_cast<unsigned>(end - str)); break; } case booleanValue: @@ -416,13 +416,13 @@ void FastWriter::writeValue(const Value& value) { case objectValue: { Value::Members members(value.getMemberNames()); document_ += '{'; - for (Value::Members::iterator it = members.begin(); it != members.end(); - ++it) { - const JSONCPP_STRING& name = *it; + for (auto it = members.begin(); it != members.end(); ++it) { + const String& name = *it; if (it != members.begin()) document_ += ','; - document_ += valueToQuotedStringN(name.data(), static_cast<unsigned>(name.length())); - document_ += yamlCompatiblityEnabled_ ? ": " : ":"; + document_ += valueToQuotedStringN(name.data(), + static_cast<unsigned>(name.length())); + document_ += yamlCompatibilityEnabled_ ? ": " : ":"; writeValue(value[name]); } document_ += '}'; @@ -433,17 +433,16 @@ void FastWriter::writeValue(const Value& value) { // Class StyledWriter // ////////////////////////////////////////////////////////////////// -StyledWriter::StyledWriter() - : rightMargin_(74), indentSize_(3), addChildValues_() {} +StyledWriter::StyledWriter() = default; -JSONCPP_STRING StyledWriter::write(const Value& root) { +String StyledWriter::write(const Value& root) { document_.clear(); addChildValues_ = false; indentString_.clear(); writeCommentBeforeValue(root); writeValue(root); writeCommentAfterValueOnSameLine(root); - document_ += "\n"; + document_ += '\n'; return document_; } @@ -461,14 +460,15 @@ void StyledWriter::writeValue(const Value& value) { case realValue: pushValue(valueToString(value.asDouble())); break; - case stringValue: - { + case stringValue: { // Is NULL possible for value.string_? No. char const* str; char const* end; bool ok = value.getString(&str, &end); - if (ok) pushValue(valueToQuotedStringN(str, static_cast<unsigned>(end-str))); - else pushValue(""); + if (ok) + pushValue(valueToQuotedStringN(str, static_cast<unsigned>(end - str))); + else + pushValue(""); break; } case booleanValue: @@ -484,9 +484,9 @@ void StyledWriter::writeValue(const Value& value) { else { writeWithIndent("{"); indent(); - Value::Members::iterator it = members.begin(); + auto it = members.begin(); for (;;) { - const JSONCPP_STRING& name = *it; + const String& name = *it; const Value& childValue = value[name]; writeCommentBeforeValue(childValue); writeWithIndent(valueToQuotedString(name.c_str())); @@ -511,7 +511,7 @@ void StyledWriter::writeArrayValue(const Value& value) { if (size == 0) pushValue("[]"); else { - bool isArrayMultiLine = isMultineArray(value); + bool isArrayMultiLine = isMultilineArray(value); if (isArrayMultiLine) { writeWithIndent("["); indent(); @@ -549,14 +549,14 @@ void StyledWriter::writeArrayValue(const Value& value) { } } -bool StyledWriter::isMultineArray(const Value& value) { +bool StyledWriter::isMultilineArray(const Value& value) { ArrayIndex const size = value.size(); bool isMultiLine = size * 3 >= rightMargin_; childValues_.clear(); for (ArrayIndex index = 0; index < size && !isMultiLine; ++index) { const Value& childValue = value[index]; isMultiLine = ((childValue.isArray() || childValue.isObject()) && - childValue.size() > 0); + !childValue.empty()); } if (!isMultiLine) // check if line length > max line length { @@ -576,7 +576,7 @@ bool StyledWriter::isMultineArray(const Value& value) { return isMultiLine; } -void StyledWriter::pushValue(const JSONCPP_STRING& value) { +void StyledWriter::pushValue(const String& value) { if (addChildValues_) childValues_.push_back(value); else @@ -594,12 +594,12 @@ void StyledWriter::writeIndent() { document_ += indentString_; } -void StyledWriter::writeWithIndent(const JSONCPP_STRING& value) { +void StyledWriter::writeWithIndent(const String& value) { writeIndent(); document_ += value; } -void StyledWriter::indent() { indentString_ += JSONCPP_STRING(indentSize_, ' '); } +void StyledWriter::indent() { indentString_ += String(indentSize_, ' '); } void StyledWriter::unindent() { assert(indentString_.size() >= indentSize_); @@ -610,20 +610,19 @@ void StyledWriter::writeCommentBeforeValue(const Value& root) { if (!root.hasComment(commentBefore)) return; - document_ += "\n"; + document_ += '\n'; writeIndent(); - const JSONCPP_STRING& comment = root.getComment(commentBefore); - JSONCPP_STRING::const_iterator iter = comment.begin(); + const String& comment = root.getComment(commentBefore); + String::const_iterator iter = comment.begin(); while (iter != comment.end()) { document_ += *iter; - if (*iter == '\n' && - (iter != comment.end() && *(iter + 1) == '/')) + if (*iter == '\n' && ((iter + 1) != comment.end() && *(iter + 1) == '/')) writeIndent(); ++iter; } // Comments are stripped of trailing newlines, so add one here - document_ += "\n"; + document_ += '\n'; } void StyledWriter::writeCommentAfterValueOnSameLine(const Value& root) { @@ -631,9 +630,9 @@ void StyledWriter::writeCommentAfterValueOnSameLine(const Value& root) { document_ += " " + root.getComment(commentAfterOnSameLine); if (root.hasComment(commentAfter)) { - document_ += "\n"; + document_ += '\n'; document_ += root.getComment(commentAfter); - document_ += "\n"; + document_ += '\n'; } } @@ -646,22 +645,23 @@ bool StyledWriter::hasCommentForValue(const Value& value) { // Class StyledStreamWriter // ////////////////////////////////////////////////////////////////// -StyledStreamWriter::StyledStreamWriter(JSONCPP_STRING indentation) - : document_(NULL), rightMargin_(74), indentation_(indentation), - addChildValues_() {} +StyledStreamWriter::StyledStreamWriter(String indentation) + : document_(nullptr), indentation_(std::move(indentation)), + addChildValues_(), indented_(false) {} -void StyledStreamWriter::write(JSONCPP_OSTREAM& out, const Value& root) { +void StyledStreamWriter::write(OStream& out, const Value& root) { document_ = &out; addChildValues_ = false; indentString_.clear(); indented_ = true; writeCommentBeforeValue(root); - if (!indented_) writeIndent(); + if (!indented_) + writeIndent(); indented_ = true; writeValue(root); writeCommentAfterValueOnSameLine(root); *document_ << "\n"; - document_ = NULL; // Forget the stream, for safety. + document_ = nullptr; // Forget the stream, for safety. } void StyledStreamWriter::writeValue(const Value& value) { @@ -678,14 +678,15 @@ void StyledStreamWriter::writeValue(const Value& value) { case realValue: pushValue(valueToString(value.asDouble())); break; - case stringValue: - { + case stringValue: { // Is NULL possible for value.string_? No. char const* str; char const* end; bool ok = value.getString(&str, &end); - if (ok) pushValue(valueToQuotedStringN(str, static_cast<unsigned>(end-str))); - else pushValue(""); + if (ok) + pushValue(valueToQuotedStringN(str, static_cast<unsigned>(end - str))); + else + pushValue(""); break; } case booleanValue: @@ -701,9 +702,9 @@ void StyledStreamWriter::writeValue(const Value& value) { else { writeWithIndent("{"); indent(); - Value::Members::iterator it = members.begin(); + auto it = members.begin(); for (;;) { - const JSONCPP_STRING& name = *it; + const String& name = *it; const Value& childValue = value[name]; writeCommentBeforeValue(childValue); writeWithIndent(valueToQuotedString(name.c_str())); @@ -728,7 +729,7 @@ void StyledStreamWriter::writeArrayValue(const Value& value) { if (size == 0) pushValue("[]"); else { - bool isArrayMultiLine = isMultineArray(value); + bool isArrayMultiLine = isMultilineArray(value); if (isArrayMultiLine) { writeWithIndent("["); indent(); @@ -740,7 +741,8 @@ void StyledStreamWriter::writeArrayValue(const Value& value) { if (hasChildValue) writeWithIndent(childValues_[index]); else { - if (!indented_) writeIndent(); + if (!indented_) + writeIndent(); indented_ = true; writeValue(childValue); indented_ = false; @@ -768,14 +770,14 @@ void StyledStreamWriter::writeArrayValue(const Value& value) { } } -bool StyledStreamWriter::isMultineArray(const Value& value) { +bool StyledStreamWriter::isMultilineArray(const Value& value) { ArrayIndex const size = value.size(); bool isMultiLine = size * 3 >= rightMargin_; childValues_.clear(); for (ArrayIndex index = 0; index < size && !isMultiLine; ++index) { const Value& childValue = value[index]; isMultiLine = ((childValue.isArray() || childValue.isObject()) && - childValue.size() > 0); + !childValue.empty()); } if (!isMultiLine) // check if line length > max line length { @@ -795,7 +797,7 @@ bool StyledStreamWriter::isMultineArray(const Value& value) { return isMultiLine; } -void StyledStreamWriter::pushValue(const JSONCPP_STRING& value) { +void StyledStreamWriter::pushValue(const String& value) { if (addChildValues_) childValues_.push_back(value); else @@ -810,8 +812,9 @@ void StyledStreamWriter::writeIndent() { *document_ << '\n' << indentString_; } -void StyledStreamWriter::writeWithIndent(const JSONCPP_STRING& value) { - if (!indented_) writeIndent(); +void StyledStreamWriter::writeWithIndent(const String& value) { + if (!indented_) + writeIndent(); *document_ << value; indented_ = false; } @@ -827,13 +830,13 @@ void StyledStreamWriter::writeCommentBeforeValue(const Value& root) { if (!root.hasComment(commentBefore)) return; - if (!indented_) writeIndent(); - const JSONCPP_STRING& comment = root.getComment(commentBefore); - JSONCPP_STRING::const_iterator iter = comment.begin(); + if (!indented_) + writeIndent(); + const String& comment = root.getComment(commentBefore); + String::const_iterator iter = comment.begin(); while (iter != comment.end()) { *document_ << *iter; - if (*iter == '\n' && - (iter != comment.end() && *(iter + 1) == '/')) + if (*iter == '\n' && ((iter + 1) != comment.end() && *(iter + 1) == '/')) // writeIndent(); // would include newline *document_ << indentString_; ++iter; @@ -865,84 +868,73 @@ bool StyledStreamWriter::hasCommentForValue(const Value& value) { struct CommentStyle { /// Decide whether to write comments. enum Enum { - None, ///< Drop all comments. - Most, ///< Recover odd behavior of previous versions (not implemented yet). - All ///< Keep all comments. + None, ///< Drop all comments. + Most, ///< Recover odd behavior of previous versions (not implemented yet). + All ///< Keep all comments. }; }; -struct BuiltStyledStreamWriter : public StreamWriter -{ - BuiltStyledStreamWriter( - JSONCPP_STRING const& indentation, - CommentStyle::Enum cs, - JSONCPP_STRING const& colonSymbol, - JSONCPP_STRING const& nullSymbol, - JSONCPP_STRING const& endingLineFeedSymbol, - bool useSpecialFloats, - unsigned int precision); - int write(Value const& root, JSONCPP_OSTREAM* sout) JSONCPP_OVERRIDE; +struct BuiltStyledStreamWriter : public StreamWriter { + BuiltStyledStreamWriter(String indentation, CommentStyle::Enum cs, + String colonSymbol, String nullSymbol, + String endingLineFeedSymbol, bool useSpecialFloats, + bool emitUTF8, unsigned int precision, + PrecisionType precisionType); + int write(Value const& root, OStream* sout) override; + private: void writeValue(Value const& value); void writeArrayValue(Value const& value); - bool isMultineArray(Value const& value); - void pushValue(JSONCPP_STRING const& value); + bool isMultilineArray(Value const& value); + void pushValue(String const& value); void writeIndent(); - void writeWithIndent(JSONCPP_STRING const& value); + void writeWithIndent(String const& value); void indent(); void unindent(); void writeCommentBeforeValue(Value const& root); void writeCommentAfterValueOnSameLine(Value const& root); static bool hasCommentForValue(const Value& value); - typedef std::vector<JSONCPP_STRING> ChildValues; + using ChildValues = std::vector<String>; ChildValues childValues_; - JSONCPP_STRING indentString_; + String indentString_; unsigned int rightMargin_; - JSONCPP_STRING indentation_; + String indentation_; CommentStyle::Enum cs_; - JSONCPP_STRING colonSymbol_; - JSONCPP_STRING nullSymbol_; - JSONCPP_STRING endingLineFeedSymbol_; + String colonSymbol_; + String nullSymbol_; + String endingLineFeedSymbol_; bool addChildValues_ : 1; bool indented_ : 1; bool useSpecialFloats_ : 1; + bool emitUTF8_ : 1; unsigned int precision_; + PrecisionType precisionType_; }; BuiltStyledStreamWriter::BuiltStyledStreamWriter( - JSONCPP_STRING const& indentation, - CommentStyle::Enum cs, - JSONCPP_STRING const& colonSymbol, - JSONCPP_STRING const& nullSymbol, - JSONCPP_STRING const& endingLineFeedSymbol, - bool useSpecialFloats, - unsigned int precision) - : rightMargin_(74) - , indentation_(indentation) - , cs_(cs) - , colonSymbol_(colonSymbol) - , nullSymbol_(nullSymbol) - , endingLineFeedSymbol_(endingLineFeedSymbol) - , addChildValues_(false) - , indented_(false) - , useSpecialFloats_(useSpecialFloats) - , precision_(precision) -{ -} -int BuiltStyledStreamWriter::write(Value const& root, JSONCPP_OSTREAM* sout) -{ + String indentation, CommentStyle::Enum cs, String colonSymbol, + String nullSymbol, String endingLineFeedSymbol, bool useSpecialFloats, + bool emitUTF8, unsigned int precision, PrecisionType precisionType) + : rightMargin_(74), indentation_(std::move(indentation)), cs_(cs), + colonSymbol_(std::move(colonSymbol)), nullSymbol_(std::move(nullSymbol)), + endingLineFeedSymbol_(std::move(endingLineFeedSymbol)), + addChildValues_(false), indented_(false), + useSpecialFloats_(useSpecialFloats), emitUTF8_(emitUTF8), + precision_(precision), precisionType_(precisionType) {} +int BuiltStyledStreamWriter::write(Value const& root, OStream* sout) { sout_ = sout; addChildValues_ = false; indented_ = true; indentString_.clear(); writeCommentBeforeValue(root); - if (!indented_) writeIndent(); + if (!indented_) + writeIndent(); indented_ = true; writeValue(root); writeCommentAfterValueOnSameLine(root); *sout_ << endingLineFeedSymbol_; - sout_ = NULL; + sout_ = nullptr; return 0; } void BuiltStyledStreamWriter::writeValue(Value const& value) { @@ -957,16 +949,19 @@ void BuiltStyledStreamWriter::writeValue(Value const& value) { pushValue(valueToString(value.asLargestUInt())); break; case realValue: - pushValue(valueToString(value.asDouble(), useSpecialFloats_, precision_)); + pushValue(valueToString(value.asDouble(), useSpecialFloats_, precision_, + precisionType_)); break; - case stringValue: - { + case stringValue: { // Is NULL is possible for value.string_? No. char const* str; char const* end; bool ok = value.getString(&str, &end); - if (ok) pushValue(valueToQuotedStringN(str, static_cast<unsigned>(end-str))); - else pushValue(""); + if (ok) + pushValue(valueToQuotedStringN(str, static_cast<unsigned>(end - str), + emitUTF8_)); + else + pushValue(""); break; } case booleanValue: @@ -982,12 +977,13 @@ void BuiltStyledStreamWriter::writeValue(Value const& value) { else { writeWithIndent("{"); indent(); - Value::Members::iterator it = members.begin(); + auto it = members.begin(); for (;;) { - JSONCPP_STRING const& name = *it; + String const& name = *it; Value const& childValue = value[name]; writeCommentBeforeValue(childValue); - writeWithIndent(valueToQuotedStringN(name.data(), static_cast<unsigned>(name.length()))); + writeWithIndent(valueToQuotedStringN( + name.data(), static_cast<unsigned>(name.length()), emitUTF8_)); *sout_ << colonSymbol_; writeValue(childValue); if (++it == members.end()) { @@ -1009,7 +1005,7 @@ void BuiltStyledStreamWriter::writeArrayValue(Value const& value) { if (size == 0) pushValue("[]"); else { - bool isMultiLine = (cs_ == CommentStyle::All) || isMultineArray(value); + bool isMultiLine = (cs_ == CommentStyle::All) || isMultilineArray(value); if (isMultiLine) { writeWithIndent("["); indent(); @@ -1021,7 +1017,8 @@ void BuiltStyledStreamWriter::writeArrayValue(Value const& value) { if (hasChildValue) writeWithIndent(childValues_[index]); else { - if (!indented_) writeIndent(); + if (!indented_) + writeIndent(); indented_ = true; writeValue(childValue); indented_ = false; @@ -1039,26 +1036,28 @@ void BuiltStyledStreamWriter::writeArrayValue(Value const& value) { { assert(childValues_.size() == size); *sout_ << "["; - if (!indentation_.empty()) *sout_ << " "; + if (!indentation_.empty()) + *sout_ << " "; for (unsigned index = 0; index < size; ++index) { if (index > 0) *sout_ << ((!indentation_.empty()) ? ", " : ","); *sout_ << childValues_[index]; } - if (!indentation_.empty()) *sout_ << " "; + if (!indentation_.empty()) + *sout_ << " "; *sout_ << "]"; } } } -bool BuiltStyledStreamWriter::isMultineArray(Value const& value) { +bool BuiltStyledStreamWriter::isMultilineArray(Value const& value) { ArrayIndex const size = value.size(); bool isMultiLine = size * 3 >= rightMargin_; childValues_.clear(); for (ArrayIndex index = 0; index < size && !isMultiLine; ++index) { Value const& childValue = value[index]; isMultiLine = ((childValue.isArray() || childValue.isObject()) && - childValue.size() > 0); + !childValue.empty()); } if (!isMultiLine) // check if line length > max line length { @@ -1078,7 +1077,7 @@ bool BuiltStyledStreamWriter::isMultineArray(Value const& value) { return isMultiLine; } -void BuiltStyledStreamWriter::pushValue(JSONCPP_STRING const& value) { +void BuiltStyledStreamWriter::pushValue(String const& value) { if (addChildValues_) childValues_.push_back(value); else @@ -1097,8 +1096,9 @@ void BuiltStyledStreamWriter::writeIndent() { } } -void BuiltStyledStreamWriter::writeWithIndent(JSONCPP_STRING const& value) { - if (!indented_) writeIndent(); +void BuiltStyledStreamWriter::writeWithIndent(String const& value) { + if (!indented_) + writeIndent(); *sout_ << value; indented_ = false; } @@ -1111,17 +1111,18 @@ void BuiltStyledStreamWriter::unindent() { } void BuiltStyledStreamWriter::writeCommentBeforeValue(Value const& root) { - if (cs_ == CommentStyle::None) return; + if (cs_ == CommentStyle::None) + return; if (!root.hasComment(commentBefore)) return; - if (!indented_) writeIndent(); - const JSONCPP_STRING& comment = root.getComment(commentBefore); - JSONCPP_STRING::const_iterator iter = comment.begin(); + if (!indented_) + writeIndent(); + const String& comment = root.getComment(commentBefore); + String::const_iterator iter = comment.begin(); while (iter != comment.end()) { *sout_ << *iter; - if (*iter == '\n' && - (iter != comment.end() && *(iter + 1) == '/')) + if (*iter == '\n' && ((iter + 1) != comment.end() && *(iter + 1) == '/')) // writeIndent(); // would write extra newline *sout_ << indentString_; ++iter; @@ -1129,8 +1130,10 @@ void BuiltStyledStreamWriter::writeCommentBeforeValue(Value const& root) { indented_ = false; } -void BuiltStyledStreamWriter::writeCommentAfterValueOnSameLine(Value const& root) { - if (cs_ == CommentStyle::None) return; +void BuiltStyledStreamWriter::writeCommentAfterValueOnSameLine( + Value const& root) { + if (cs_ == CommentStyle::None) + return; if (root.hasComment(commentAfterOnSameLine)) *sout_ << " " + root.getComment(commentAfterOnSameLine); @@ -1150,28 +1153,19 @@ bool BuiltStyledStreamWriter::hasCommentForValue(const Value& value) { /////////////// // StreamWriter -StreamWriter::StreamWriter() - : sout_(NULL) -{ -} -StreamWriter::~StreamWriter() -{ -} -StreamWriter::Factory::~Factory() -{} -StreamWriterBuilder::StreamWriterBuilder() -{ - setDefaults(&settings_); -} -StreamWriterBuilder::~StreamWriterBuilder() -{} -StreamWriter* StreamWriterBuilder::newStreamWriter() const -{ - JSONCPP_STRING indentation = settings_["indentation"].asString(); - JSONCPP_STRING cs_str = settings_["commentStyle"].asString(); - bool eyc = settings_["enableYAMLCompatibility"].asBool(); - bool dnp = settings_["dropNullPlaceholders"].asBool(); - bool usf = settings_["useSpecialFloats"].asBool(); +StreamWriter::StreamWriter() : sout_(nullptr) {} +StreamWriter::~StreamWriter() = default; +StreamWriter::Factory::~Factory() = default; +StreamWriterBuilder::StreamWriterBuilder() { setDefaults(&settings_); } +StreamWriterBuilder::~StreamWriterBuilder() = default; +StreamWriter* StreamWriterBuilder::newStreamWriter() const { + const String indentation = settings_["indentation"].asString(); + const String cs_str = settings_["commentStyle"].asString(); + const String pt_str = settings_["precisionType"].asString(); + const bool eyc = settings_["enableYAMLCompatibility"].asBool(); + const bool dnp = settings_["dropNullPlaceholders"].asBool(); + const bool usf = settings_["useSpecialFloats"].asBool(); + const bool emitUTF8 = settings_["emitUTF8"].asBool(); unsigned int pre = settings_["precision"].asUInt(); CommentStyle::Enum cs = CommentStyle::All; if (cs_str == "All") { @@ -1181,74 +1175,80 @@ StreamWriter* StreamWriterBuilder::newStreamWriter() const } else { throwRuntimeError("commentStyle must be 'All' or 'None'"); } - JSONCPP_STRING colonSymbol = " : "; + PrecisionType precisionType(significantDigits); + if (pt_str == "significant") { + precisionType = PrecisionType::significantDigits; + } else if (pt_str == "decimal") { + precisionType = PrecisionType::decimalPlaces; + } else { + throwRuntimeError("precisionType must be 'significant' or 'decimal'"); + } + String colonSymbol = " : "; if (eyc) { colonSymbol = ": "; } else if (indentation.empty()) { colonSymbol = ":"; } - JSONCPP_STRING nullSymbol = "null"; + String nullSymbol = "null"; if (dnp) { nullSymbol.clear(); } - if (pre > 17) pre = 17; - JSONCPP_STRING endingLineFeedSymbol; - return new BuiltStyledStreamWriter( - indentation, cs, - colonSymbol, nullSymbol, endingLineFeedSymbol, usf, pre); + if (pre > 17) + pre = 17; + String endingLineFeedSymbol; + return new BuiltStyledStreamWriter(indentation, cs, colonSymbol, nullSymbol, + endingLineFeedSymbol, usf, emitUTF8, pre, + precisionType); } -static void getValidWriterKeys(std::set<JSONCPP_STRING>* valid_keys) -{ - valid_keys->clear(); - valid_keys->insert("indentation"); - valid_keys->insert("commentStyle"); - valid_keys->insert("enableYAMLCompatibility"); - valid_keys->insert("dropNullPlaceholders"); - valid_keys->insert("useSpecialFloats"); - valid_keys->insert("precision"); -} -bool StreamWriterBuilder::validate(Json::Value* invalid) const -{ - Json::Value my_invalid; - if (!invalid) invalid = &my_invalid; // so we do not need to test for NULL - Json::Value& inv = *invalid; - std::set<JSONCPP_STRING> valid_keys; - getValidWriterKeys(&valid_keys); - Value::Members keys = settings_.getMemberNames(); - size_t n = keys.size(); - for (size_t i = 0; i < n; ++i) { - JSONCPP_STRING const& key = keys[i]; - if (valid_keys.find(key) == valid_keys.end()) { - inv[key] = settings_[key]; - } + +bool StreamWriterBuilder::validate(Json::Value* invalid) const { + static const auto& valid_keys = *new std::set<String>{ + "indentation", + "commentStyle", + "enableYAMLCompatibility", + "dropNullPlaceholders", + "useSpecialFloats", + "emitUTF8", + "precision", + "precisionType", + }; + for (auto si = settings_.begin(); si != settings_.end(); ++si) { + auto key = si.name(); + if (valid_keys.count(key)) + continue; + if (invalid) + (*invalid)[std::move(key)] = *si; + else + return false; } - return 0u == inv.size(); + return invalid ? invalid->empty() : true; } -Value& StreamWriterBuilder::operator[](JSONCPP_STRING key) -{ + +Value& StreamWriterBuilder::operator[](const String& key) { return settings_[key]; } // static -void StreamWriterBuilder::setDefaults(Json::Value* settings) -{ +void StreamWriterBuilder::setDefaults(Json::Value* settings) { //! [StreamWriterBuilderDefaults] (*settings)["commentStyle"] = "All"; (*settings)["indentation"] = "\t"; (*settings)["enableYAMLCompatibility"] = false; (*settings)["dropNullPlaceholders"] = false; (*settings)["useSpecialFloats"] = false; + (*settings)["emitUTF8"] = false; (*settings)["precision"] = 17; + (*settings)["precisionType"] = "significant"; //! [StreamWriterBuilderDefaults] } -JSONCPP_STRING writeString(StreamWriter::Factory const& builder, Value const& root) { - JSONCPP_OSTRINGSTREAM sout; - StreamWriterPtr const writer(builder.newStreamWriter()); +String writeString(StreamWriter::Factory const& factory, Value const& root) { + OStringStream sout; + StreamWriterPtr const writer(factory.newStreamWriter()); writer->write(root, &sout); return sout.str(); } -JSONCPP_OSTREAM& operator<<(JSONCPP_OSTREAM& sout, Value const& root) { +OStream& operator<<(OStream& sout, Value const& root) { StreamWriterBuilder builder; StreamWriterPtr const writer(builder.newStreamWriter()); writer->write(root, &sout); |