diff --git a/.travis.yml b/.travis.yml index add1910355..226a23fd50 100644 --- a/.travis.yml +++ b/.travis.yml @@ -286,11 +286,11 @@ jobs: script: *script-cpp-unit # GCC 7.3.0 - <<: *test-cpp-unit - name: gcc@7.3.0 -MPI -PY +H5 +ADIOS1 + name: gcc@7.3.0 -MPI -PY +H5 +ADIOS1 -JSON language: python python: "2.7" env: - - CXXSPEC="%gcc@7.3.0" USE_MPI=OFF USE_PYTHON=OFF USE_HDF5=ON USE_ADIOS1=ON USE_ADIOS2=OFF USE_SAMPLES=ON + - CXXSPEC="%gcc@7.3.0" USE_MPI=OFF USE_PYTHON=OFF USE_JSON=OFF USE_HDF5=ON USE_ADIOS1=ON USE_ADIOS2=OFF USE_SAMPLES=ON compiler: gcc addons: apt: diff --git a/CMakeLists.txt b/CMakeLists.txt index 9a1a83ba9e..82b361298f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -46,15 +46,16 @@ function(openpmd_option name description default) endfunction() openpmd_option(MPI "Enable MPI support" AUTO) +openpmd_option(JSON "Enable JSON support" AUTO) openpmd_option(HDF5 "Enable HDF5 support" AUTO) openpmd_option(ADIOS1 "Enable ADIOS1 support" AUTO) openpmd_option(ADIOS2 "Enable ADIOS2 support" OFF) -#openpmd_option(JSON "Enable JSON support" AUTO) openpmd_option(PYTHON "Enable Python bindings" AUTO) option(openPMD_USE_INTERNAL_VARIANT "Use internally shipped MPark.Variant" ON) option(openPMD_USE_INTERNAL_CATCH "Use internally shipped Catch2" ON) option(openPMD_USE_INTERNAL_PYBIND11 "Use internally shipped pybind11" ON) +option(openPMD_USE_INTERNAL_JSON "Use internally shipped nlohmann-json" ON) option(openPMD_USE_INVASIVE_TESTS "Enable unit tests that modify source code" OFF) option(openPMD_USE_VERIFY "Enable internal VERIFY (assert) macro independent of build type" ON) @@ -88,6 +89,43 @@ else() set(openPMD_HAVE_MPI FALSE) endif() +# external library: nlohmann-json (optional) +if(openPMD_USE_JSON STREQUAL AUTO) + if(openPMD_USE_INTERNAL_JSON) + # see https://github.com/nlohmann/json/pull/1330 + set(JSON_BuildTests OFF CACHE INTERNAL "") + add_subdirectory( + "${openPMD_SOURCE_DIR}/share/openPMD/thirdParty/json" + EXCLUDE_FROM_ALL) # does not need to be publicly installed + set(openPMD_HAVE_JSON TRUE) + message(STATUS "nlohmann-json: Using INTERNAL version 3.4.0") + else() + find_package(nlohmann_json 3.4.0 CONFIG) + if(nlohmann_json_FOUND) + set(openPMD_HAVE_JSON TRUE) + message(STATUS "nlohmann-json: Found version ${nlohmann_json_VERSION}") + else() + set(openPMD_HAVE_JSON FALSE) + endif() + endif() +elseif(openPMD_USE_JSON) + if(openPMD_USE_INTERNAL_JSON) + # see https://github.com/nlohmann/json/pull/1330 + set(JSON_BuildTests OFF CACHE INTERNAL "") + add_subdirectory( + "${openPMD_SOURCE_DIR}/share/openPMD/thirdParty/json" + EXCLUDE_FROM_ALL) # does not need to be publicly installed + set(openPMD_HAVE_JSON TRUE) + message(STATUS "nlohmann-json: Using INTERNAL version 3.4.0") + else() + find_package(nlohmann_json 3.4.0 CONFIG REQUIRED) + set(openPMD_HAVE_JSON TRUE) + message(STATUS "nlohmann-json: Found version ${nlohmann_json_VERSION}") + endif() +else() + set(openPMD_HAVE_JSON FALSE) +endif() + # external library: HDF5 (optional) if(openPMD_USE_HDF5 STREQUAL AUTO) set(HDF5_PREFER_PARALLEL ${openPMD_HAVE_MPI}) @@ -326,6 +364,14 @@ else() target_compile_definitions(openPMD PUBLIC "-DopenPMD_HAVE_MPI=0") endif() +# JSON Backend +if(openPMD_HAVE_JSON) + target_link_libraries(openPMD PRIVATE nlohmann_json::nlohmann_json) + target_compile_definitions(openPMD PUBLIC "-DopenPMD_HAVE_JSON=1") +else() + target_compile_definitions(openPMD PUBLIC "-DopenPMD_HAVE_JSON=0") +endif() + # HDF5 Backend if(openPMD_HAVE_HDF5) target_link_libraries(openPMD PUBLIC ${HDF5_LIBRARIES}) @@ -551,6 +597,10 @@ if(BUILD_TESTING) target_compile_definitions(${testname}Tests PUBLIC "-DopenPMD_HAVE_MPI=1") endif() + if(openPMD_HAVE_JSON) + target_compile_definitions(${testname}Tests PUBLIC "-DopenPMD_HAVE_JSON=1") + endif() + if(openPMD_HAVE_HDF5) target_compile_definitions(${testname}Tests PUBLIC "-DopenPMD_HAVE_HDF5=1") endif() diff --git a/README.md b/README.md index 625ef4e3eb..9f86145efa 100644 --- a/README.md +++ b/README.md @@ -97,8 +97,10 @@ Shipped internally in `share/openPMD/thirdParty/`: * [MPark.Variant](https://github.com/mpark/variant) 1.3.0+ ([BSL-1.0](https://github.com/mpark/variant/blob/master/LICENSE.md)) * [Catch2](https://github.com/catchorg/Catch2) 2.3.0+ ([BSL-1.0](https://github.com/catchorg/Catch2/blob/master/LICENSE.txt)) * [pybind11](https://github.com/pybind/pybind11) 2.2.3+ ([new BSD](https://github.com/pybind/pybind11/blob/master/LICENSE)) +* [NLohmann-JSON](https://github.com/nlohmann/json) 3.4.0+ ([MIT](https://github.com/nlohmann/json/blob/develop/LICENSE.MIT)) Optional I/O backends: +* [JSON](https://en.wikipedia.org/wiki/JSON) (*not yet implemented*) * [HDF5](https://support.hdfgroup.org/HDF5) 1.8.13+ * [ADIOS1](https://www.olcf.ornl.gov/center-projects/adios) 1.13.1+ * [ADIOS2](https://github.com/ornladios/ADIOS2) 2.1+ (*not yet implemented*) @@ -173,6 +175,7 @@ CMake controls options with prefixed `-D`, e.g. `-DopenPMD_USE_MPI=OFF`: | CMake Option | Values | Description | |------------------------------|------------------|------------------------------------------------------------------------------| | `openPMD_USE_MPI` | **AUTO**/ON/OFF | Enable MPI support | +| `openPMD_USE_JSON` | **AUTO**/ON/OFF | Enable support for JSON 1 | | `openPMD_USE_HDF5` | **AUTO**/ON/OFF | Enable support for HDF5 | | `openPMD_USE_ADIOS1` | **AUTO**/ON/OFF | Enable support for ADIOS1 | | `openPMD_USE_ADIOS2` | AUTO/ON/**OFF** | Enable support for ADIOS2 1 | @@ -193,6 +196,7 @@ The following options allow to switch to external installs: | `openPMD_USE_INTERNAL_VARIANT` | **ON**/OFF | MPark.Variant | 1.3.0+ | | `openPMD_USE_INTERNAL_CATCH` | **ON**/OFF | Catch2 | 2.3.0+ | | `openPMD_USE_INTERNAL_PYBIND11` | **ON**/OFF | pybind11 | 2.2.3+ | +| `openPMD_USE_INTERNAL_JSON` | **ON**/OFF | NLohmann-JSON | 3.4.0+ | By default, this will build as a static library (`libopenPMD.a`) and installs also its headers. In order to build a static library, append `-DBUILD_SHARED_LIBS=ON` to the `cmake` command. diff --git a/docs/source/dev/buildoptions.rst b/docs/source/dev/buildoptions.rst index edaa5c8568..5023289b1f 100644 --- a/docs/source/dev/buildoptions.rst +++ b/docs/source/dev/buildoptions.rst @@ -15,6 +15,7 @@ CMake controls options with prefixed ``-D``, e.g. ``-DopenPMD_USE_MPI=OFF``: CMake Option Values Description ============================== =============== ======================================================================== ``openPMD_USE_MPI`` **AUTO**/ON/OFF Enable MPI support +``openPMD_USE_JSON`` **AUTO**/ON/OFF Enable support for JSON :sup:`1` ``openPMD_USE_HDF5`` **AUTO**/ON/OFF Enable support for HDF5 ``openPMD_USE_ADIOS1`` **AUTO**/ON/OFF Enable support for ADIOS1 ``openPMD_USE_ADIOS2`` AUTO/ON/**OFF** Enable support for ADIOS2 :sup:`1` @@ -73,6 +74,7 @@ CMake Option Values Installs Library Version ``openPMD_USE_INTERNAL_VARIANT`` **ON**/OFF Yes MPark.Variant 1.3.0+ ``openPMD_USE_INTERNAL_CATCH`` **ON**/OFF No Catch2 2.3.0+ ``openPMD_USE_INTERNAL_PYBIND11`` **ON**/OFF No pybind11 2.2.3+ +``openPMD_USE_INTERNAL_JSON`` **ON**/OFF No NLohmann-JSON 3.4.0+ ================================= =========== ======== ============= ======== diff --git a/docs/source/dev/dependencies.rst b/docs/source/dev/dependencies.rst index fabc0a3fbd..82e2cb91b8 100644 --- a/docs/source/dev/dependencies.rst +++ b/docs/source/dev/dependencies.rst @@ -22,10 +22,12 @@ The following libraries are shipped internally in ``share/openPMD/thirdParty/`` * `MPark.Variant `_ 1.3.0+ (`BSL-1.0 `_) * `Catch2 `_ 2.3.0+ (`BSL-1.0 `_) * `pybind11 `_ 2.2.3+ (`new BSD `_) +* `NLohmann-JSON 3.4.0+ (`MIT `_) Optional: I/O backends ---------------------- +* `JSON `_ * `HDF5 `_ 1.8.13+ * `ADIOS1 `_ 1.13.1+ * `ADIOS2 `_ 2.1+ (*not yet implemented*) diff --git a/openPMDConfig.cmake.in b/openPMDConfig.cmake.in index f01f4f3f59..1245dec9ab 100644 --- a/openPMDConfig.cmake.in +++ b/openPMDConfig.cmake.in @@ -14,6 +14,9 @@ else() endif() set(openPMD_MPI_FOUND ${openPMD_HAVE_MPI}) +set(openPMD_HAVE_JSON @openPMD_HAVE_JSON@) +set(openPMD_JSON_FOUND ${openPMD_HAVE_JSON}) + set(openPMD_HAVE_HDF5 @openPMD_HAVE_HDF5@) if(openPMD_HAVE_HDF5) find_dependency(HDF5) diff --git a/share/openPMD/thirdParty/json/CMakeLists.txt b/share/openPMD/thirdParty/json/CMakeLists.txt new file mode 100644 index 0000000000..cdfce45ac5 --- /dev/null +++ b/share/openPMD/thirdParty/json/CMakeLists.txt @@ -0,0 +1,124 @@ +cmake_minimum_required(VERSION 3.8) + +## +## PROJECT +## name and version +## +project(nlohmann_json VERSION 3.4.0 LANGUAGES CXX) + +## +## INCLUDE +## +## +include(ExternalProject) + +## +## OPTIONS +## +option(JSON_BuildTests "Build the unit tests when BUILD_TESTING is enabled." ON) +option(JSON_MultipleHeaders "Use non-amalgamated version of the library." OFF) + +## +## CONFIGURATION +## +set(NLOHMANN_JSON_TARGET_NAME ${PROJECT_NAME}) +set(NLOHMANN_JSON_CONFIG_INSTALL_DIR "lib/cmake/${PROJECT_NAME}" + CACHE INTERNAL "") +set(NLOHMANN_JSON_INCLUDE_INSTALL_DIR "include") +set(NLOHMANN_JSON_TARGETS_EXPORT_NAME "${PROJECT_NAME}Targets") +set(NLOHMANN_JSON_CMAKE_CONFIG_TEMPLATE "cmake/config.cmake.in") +set(NLOHMANN_JSON_CMAKE_CONFIG_DIR "${CMAKE_CURRENT_BINARY_DIR}") +set(NLOHMANN_JSON_CMAKE_VERSION_CONFIG_FILE "${NLOHMANN_JSON_CMAKE_CONFIG_DIR}/${PROJECT_NAME}ConfigVersion.cmake") +set(NLOHMANN_JSON_CMAKE_PROJECT_CONFIG_FILE "${NLOHMANN_JSON_CMAKE_CONFIG_DIR}/${PROJECT_NAME}Config.cmake") +set(NLOHMANN_JSON_CMAKE_PROJECT_TARGETS_FILE "${NLOHMANN_JSON_CMAKE_CONFIG_DIR}/${PROJECT_NAME}Targets.cmake") + +if (JSON_MultipleHeaders) + set(NLOHMANN_JSON_INCLUDE_BUILD_DIR "${PROJECT_SOURCE_DIR}/include/") + message(STATUS "Using the multi-header code from ${NLOHMANN_JSON_INCLUDE_BUILD_DIR}") +else() + set(NLOHMANN_JSON_INCLUDE_BUILD_DIR "${PROJECT_SOURCE_DIR}/single_include/") + message(STATUS "Using the single-header code from ${NLOHMANN_JSON_INCLUDE_BUILD_DIR}") +endif() + +## +## TARGET +## create target and add include path +## +add_library(${NLOHMANN_JSON_TARGET_NAME} INTERFACE) +add_library(${PROJECT_NAME}::${NLOHMANN_JSON_TARGET_NAME} ALIAS ${NLOHMANN_JSON_TARGET_NAME}) +target_compile_features(${NLOHMANN_JSON_TARGET_NAME} INTERFACE cxx_std_11) + +target_include_directories( + ${NLOHMANN_JSON_TARGET_NAME} + INTERFACE + $ + $ +) + +## add debug view definition file for msvc (natvis) +if (MSVC) + set(NLOHMANN_ADD_NATVIS TRUE) + set(NLOHMANN_NATVIS_FILE "nlohmann_json.natvis") + target_sources( + ${NLOHMANN_JSON_TARGET_NAME} + INTERFACE + $ + $ + ) +endif() + +## +## TESTS +## create and configure the unit test target +## +include(CTest) #adds option BUILD_TESTING (default ON) + +if(BUILD_TESTING AND JSON_BuildTests) + enable_testing() + add_subdirectory(test) +endif() + +## +## INSTALL +## install header files, generate and install cmake config files for find_package() +## +include(CMakePackageConfigHelpers) +write_basic_package_version_file( + ${NLOHMANN_JSON_CMAKE_VERSION_CONFIG_FILE} COMPATIBILITY SameMajorVersion +) +configure_file( + ${NLOHMANN_JSON_CMAKE_CONFIG_TEMPLATE} + ${NLOHMANN_JSON_CMAKE_PROJECT_CONFIG_FILE} + @ONLY +) + +install( + DIRECTORY ${NLOHMANN_JSON_INCLUDE_BUILD_DIR} + DESTINATION ${NLOHMANN_JSON_INCLUDE_INSTALL_DIR} +) +install( + FILES ${NLOHMANN_JSON_CMAKE_PROJECT_CONFIG_FILE} ${NLOHMANN_JSON_CMAKE_VERSION_CONFIG_FILE} + DESTINATION ${NLOHMANN_JSON_CONFIG_INSTALL_DIR} +) +if (NLOHMANN_ADD_NATVIS) + install( + FILES ${NLOHMANN_NATVIS_FILE} + DESTINATION . +) +endif() +export( + TARGETS ${NLOHMANN_JSON_TARGET_NAME} + NAMESPACE ${PROJECT_NAME}:: + FILE ${NLOHMANN_JSON_CMAKE_PROJECT_TARGETS_FILE} +) +install( + TARGETS ${NLOHMANN_JSON_TARGET_NAME} + EXPORT ${NLOHMANN_JSON_TARGETS_EXPORT_NAME} + INCLUDES DESTINATION ${NLOHMANN_JSON_INCLUDE_INSTALL_DIR} +) +install( + EXPORT ${NLOHMANN_JSON_TARGETS_EXPORT_NAME} + NAMESPACE ${PROJECT_NAME}:: + DESTINATION ${NLOHMANN_JSON_CONFIG_INSTALL_DIR} +) + diff --git a/share/openPMD/thirdParty/json/cmake/config.cmake.in b/share/openPMD/thirdParty/json/cmake/config.cmake.in new file mode 100644 index 0000000000..547a2fdad9 --- /dev/null +++ b/share/openPMD/thirdParty/json/cmake/config.cmake.in @@ -0,0 +1,16 @@ +include(FindPackageHandleStandardArgs) +set(${CMAKE_FIND_PACKAGE_NAME}_CONFIG ${CMAKE_CURRENT_LIST_FILE}) +find_package_handle_standard_args(@PROJECT_NAME@ CONFIG_MODE) + +if(NOT TARGET @PROJECT_NAME@::@NLOHMANN_JSON_TARGET_NAME@) + include("${CMAKE_CURRENT_LIST_DIR}/@NLOHMANN_JSON_TARGETS_EXPORT_NAME@.cmake") + if((NOT TARGET @NLOHMANN_JSON_TARGET_NAME@) AND + (NOT @PROJECT_NAME@_FIND_VERSION OR + @PROJECT_NAME@_FIND_VERSION VERSION_LESS 3.2.0)) + add_library(@NLOHMANN_JSON_TARGET_NAME@ INTERFACE IMPORTED) + set_target_properties(@NLOHMANN_JSON_TARGET_NAME@ PROPERTIES + INTERFACE_LINK_LIBRARIES @PROJECT_NAME@::@NLOHMANN_JSON_TARGET_NAME@ + ) + endif() +endif() + diff --git a/share/openPMD/thirdParty/json/nlohmann_json.natvis b/share/openPMD/thirdParty/json/nlohmann_json.natvis new file mode 100644 index 0000000000..557717663b --- /dev/null +++ b/share/openPMD/thirdParty/json/nlohmann_json.natvis @@ -0,0 +1,32 @@ + + + + null + {*(m_value.object)} + {*(m_value.array)} + {*(m_value.string)} + {m_value.boolean} + {m_value.number_integer} + {m_value.number_unsigned} + {m_value.number_float} + discarded + + + *(m_value.object),view(simple) + + + *(m_value.array),view(simple) + + + + + + + {second} + + second + + + + diff --git a/share/openPMD/thirdParty/json/single_include/nlohmann/json.hpp b/share/openPMD/thirdParty/json/single_include/nlohmann/json.hpp new file mode 100644 index 0000000000..1e7cf51e0a --- /dev/null +++ b/share/openPMD/thirdParty/json/single_include/nlohmann/json.hpp @@ -0,0 +1,20274 @@ +/* + __ _____ _____ _____ + __| | __| | | | JSON for Modern C++ +| | |__ | | | | | | version 3.4.0 +|_____|_____|_____|_|___| https://github.com/nlohmann/json + +Licensed under the MIT License . +SPDX-License-Identifier: MIT +Copyright (c) 2013-2018 Niels Lohmann . + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +*/ + +#ifndef NLOHMANN_JSON_HPP +#define NLOHMANN_JSON_HPP + +#define NLOHMANN_JSON_VERSION_MAJOR 3 +#define NLOHMANN_JSON_VERSION_MINOR 4 +#define NLOHMANN_JSON_VERSION_PATCH 0 + +#include // all_of, find, for_each +#include // assert +#include // and, not, or +#include // nullptr_t, ptrdiff_t, size_t +#include // hash, less +#include // initializer_list +#include // istream, ostream +#include // iterator_traits, random_access_iterator_tag +#include // accumulate +#include // string, stoi, to_string +#include // declval, forward, move, pair, swap + +// #include +#ifndef NLOHMANN_JSON_FWD_HPP +#define NLOHMANN_JSON_FWD_HPP + +#include // int64_t, uint64_t +#include // map +#include // allocator +#include // string +#include // vector + +/*! +@brief namespace for Niels Lohmann +@see https://github.com/nlohmann +@since version 1.0.0 +*/ +namespace nlohmann +{ +/*! +@brief default JSONSerializer template argument + +This serializer ignores the template arguments and uses ADL +([argument-dependent lookup](https://en.cppreference.com/w/cpp/language/adl)) +for serialization. +*/ +template +struct adl_serializer; + +template class ObjectType = + std::map, + template class ArrayType = std::vector, + class StringType = std::string, class BooleanType = bool, + class NumberIntegerType = std::int64_t, + class NumberUnsignedType = std::uint64_t, + class NumberFloatType = double, + template class AllocatorType = std::allocator, + template class JSONSerializer = + adl_serializer> +class basic_json; + +/*! +@brief JSON Pointer + +A JSON pointer defines a string syntax for identifying a specific value +within a JSON document. It can be used with functions `at` and +`operator[]`. Furthermore, JSON pointers are the base for JSON patches. + +@sa [RFC 6901](https://tools.ietf.org/html/rfc6901) + +@since version 2.0.0 +*/ +template +class json_pointer; + +/*! +@brief default JSON class + +This type is the default specialization of the @ref basic_json class which +uses the standard template types. + +@since version 1.0.0 +*/ +using json = basic_json<>; +} // namespace nlohmann + +#endif + +// #include + + +// This file contains all internal macro definitions +// You MUST include macro_unscope.hpp at the end of json.hpp to undef all of them + +// exclude unsupported compilers +#if !defined(JSON_SKIP_UNSUPPORTED_COMPILER_CHECK) + #if defined(__clang__) + #if (__clang_major__ * 10000 + __clang_minor__ * 100 + __clang_patchlevel__) < 30400 + #error "unsupported Clang version - see https://github.com/nlohmann/json#supported-compilers" + #endif + #elif defined(__GNUC__) && !(defined(__ICC) || defined(__INTEL_COMPILER)) + #if (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__) < 40800 + #error "unsupported GCC version - see https://github.com/nlohmann/json#supported-compilers" + #endif + #endif +#endif + +// disable float-equal warnings on GCC/clang +#if defined(__clang__) || defined(__GNUC__) || defined(__GNUG__) + #pragma GCC diagnostic push + #pragma GCC diagnostic ignored "-Wfloat-equal" +#endif + +// disable documentation warnings on clang +#if defined(__clang__) + #pragma GCC diagnostic push + #pragma GCC diagnostic ignored "-Wdocumentation" +#endif + +// allow for portable deprecation warnings +#if defined(__clang__) || defined(__GNUC__) || defined(__GNUG__) + #define JSON_DEPRECATED __attribute__((deprecated)) +#elif defined(_MSC_VER) + #define JSON_DEPRECATED __declspec(deprecated) +#else + #define JSON_DEPRECATED +#endif + +// allow to disable exceptions +#if (defined(__cpp_exceptions) || defined(__EXCEPTIONS) || defined(_CPPUNWIND)) && !defined(JSON_NOEXCEPTION) + #define JSON_THROW(exception) throw exception + #define JSON_TRY try + #define JSON_CATCH(exception) catch(exception) + #define JSON_INTERNAL_CATCH(exception) catch(exception) +#else + #define JSON_THROW(exception) std::abort() + #define JSON_TRY if(true) + #define JSON_CATCH(exception) if(false) + #define JSON_INTERNAL_CATCH(exception) if(false) +#endif + +// override exception macros +#if defined(JSON_THROW_USER) + #undef JSON_THROW + #define JSON_THROW JSON_THROW_USER +#endif +#if defined(JSON_TRY_USER) + #undef JSON_TRY + #define JSON_TRY JSON_TRY_USER +#endif +#if defined(JSON_CATCH_USER) + #undef JSON_CATCH + #define JSON_CATCH JSON_CATCH_USER + #undef JSON_INTERNAL_CATCH + #define JSON_INTERNAL_CATCH JSON_CATCH_USER +#endif +#if defined(JSON_INTERNAL_CATCH_USER) + #undef JSON_INTERNAL_CATCH + #define JSON_INTERNAL_CATCH JSON_INTERNAL_CATCH_USER +#endif + +// manual branch prediction +#if defined(__clang__) || defined(__GNUC__) || defined(__GNUG__) + #define JSON_LIKELY(x) __builtin_expect(!!(x), 1) + #define JSON_UNLIKELY(x) __builtin_expect(!!(x), 0) +#else + #define JSON_LIKELY(x) x + #define JSON_UNLIKELY(x) x +#endif + +// C++ language standard detection +#if (defined(__cplusplus) && __cplusplus >= 201703L) || (defined(_HAS_CXX17) && _HAS_CXX17 == 1) // fix for issue #464 + #define JSON_HAS_CPP_17 + #define JSON_HAS_CPP_14 +#elif (defined(__cplusplus) && __cplusplus >= 201402L) || (defined(_HAS_CXX14) && _HAS_CXX14 == 1) + #define JSON_HAS_CPP_14 +#endif + +/*! +@brief macro to briefly define a mapping between an enum and JSON +@def NLOHMANN_JSON_SERIALIZE_ENUM +@since version 3.4.0 +*/ +#define NLOHMANN_JSON_SERIALIZE_ENUM(ENUM_TYPE, ...) \ + template \ + inline void to_json(BasicJsonType& j, const ENUM_TYPE& e) \ + { \ + static_assert(std::is_enum::value, #ENUM_TYPE " must be an enum!"); \ + static const std::pair m[] = __VA_ARGS__; \ + auto it = std::find_if(std::begin(m), std::end(m), \ + [e](const std::pair& ej_pair) -> bool \ + { \ + return ej_pair.first == e; \ + }); \ + j = ((it != std::end(m)) ? it : std::begin(m))->second; \ + } \ + template \ + inline void from_json(const BasicJsonType& j, ENUM_TYPE& e) \ + { \ + static_assert(std::is_enum::value, #ENUM_TYPE " must be an enum!"); \ + static const std::pair m[] = __VA_ARGS__; \ + auto it = std::find_if(std::begin(m), std::end(m), \ + [j](const std::pair& ej_pair) -> bool \ + { \ + return ej_pair.second == j; \ + }); \ + e = ((it != std::end(m)) ? it : std::begin(m))->first; \ + } + +// Ugly macros to avoid uglier copy-paste when specializing basic_json. They +// may be removed in the future once the class is split. + +#define NLOHMANN_BASIC_JSON_TPL_DECLARATION \ + template class ObjectType, \ + template class ArrayType, \ + class StringType, class BooleanType, class NumberIntegerType, \ + class NumberUnsignedType, class NumberFloatType, \ + template class AllocatorType, \ + template class JSONSerializer> + +#define NLOHMANN_BASIC_JSON_TPL \ + basic_json + +// #include + + +#include // not +#include // size_t +#include // conditional, enable_if, false_type, integral_constant, is_constructible, is_integral, is_same, remove_cv, remove_reference, true_type + +namespace nlohmann +{ +namespace detail +{ +// alias templates to reduce boilerplate +template +using enable_if_t = typename std::enable_if::type; + +template +using uncvref_t = typename std::remove_cv::type>::type; + +// implementation of C++14 index_sequence and affiliates +// source: https://stackoverflow.com/a/32223343 +template +struct index_sequence +{ + using type = index_sequence; + using value_type = std::size_t; + static constexpr std::size_t size() noexcept + { + return sizeof...(Ints); + } +}; + +template +struct merge_and_renumber; + +template +struct merge_and_renumber, index_sequence> + : index_sequence < I1..., (sizeof...(I1) + I2)... > {}; + +template +struct make_index_sequence + : merge_and_renumber < typename make_index_sequence < N / 2 >::type, + typename make_index_sequence < N - N / 2 >::type > {}; + +template<> struct make_index_sequence<0> : index_sequence<> {}; +template<> struct make_index_sequence<1> : index_sequence<0> {}; + +template +using index_sequence_for = make_index_sequence; + +// dispatch utility (taken from ranges-v3) +template struct priority_tag : priority_tag < N - 1 > {}; +template<> struct priority_tag<0> {}; + +// taken from ranges-v3 +template +struct static_const +{ + static constexpr T value{}; +}; + +template +constexpr T static_const::value; +} // namespace detail +} // namespace nlohmann + +// #include + + +#include // not +#include // numeric_limits +#include // false_type, is_constructible, is_integral, is_same, true_type +#include // declval + +// #include + +// #include + +// #include + + +#include + +// #include + + +namespace nlohmann +{ +namespace detail +{ +template struct make_void +{ + using type = void; +}; +template using void_t = typename make_void::type; +} // namespace detail +} // namespace nlohmann + + +// http://en.cppreference.com/w/cpp/experimental/is_detected +namespace nlohmann +{ +namespace detail +{ +struct nonesuch +{ + nonesuch() = delete; + ~nonesuch() = delete; + nonesuch(nonesuch const&) = delete; + void operator=(nonesuch const&) = delete; +}; + +template class Op, + class... Args> +struct detector +{ + using value_t = std::false_type; + using type = Default; +}; + +template class Op, class... Args> +struct detector>, Op, Args...> +{ + using value_t = std::true_type; + using type = Op; +}; + +template