From 858033cd627b5217778cf795e9956d9eec866965 Mon Sep 17 00:00:00 2001 From: Alex McCaskey Date: Thu, 25 Jul 2024 14:25:29 +0000 Subject: [PATCH 1/6] Add JW to python, add http server for pyscf Signed-off-by: Alex McCaskey --- cudaqlib/gse/utils/operator_pool.h | 1 + cudaqlib/operators.h | 3 +- cudaqlib/operators/CMakeLists.txt | 9 +- .../chemistry/MoleculePackageDriver.h | 1 + .../drivers/pyscf/ExternalPySCFDriver.cpp | 61 +- .../drivers/pyscf/RESTPySCFDriver.cpp | 124 + cudaqlib/operators/chemistry/molecule.cpp | 21 +- cudaqlib/operators/chemistry/molecule.h | 8 +- cudaqlib/operators/fermion/fermion_op.cpp | 14 + cudaqlib/operators/fermion/fermion_op.h | 2 + cudaqlib/operators/fermion/fermion_to_spin.h | 6 +- cudaqlib/optim/observe_gradient.h | 2 + python/bindings/operators/py_operators.cpp | 58 +- .../pyscf/generators/gas_phase_generator.py | 135 +- .../polarizable_embedded_generator.py | 354 +-- python/tests/test_operators.py | 13 + python/tests/test_pyscf_tool.py | 2 +- tests/CMakeLists.txt | 6 +- tests/kernels/UCCSDTester.cpp | 2 +- tests/operators/OperatorsTester.cpp | 6 +- tools/chemistry/cudaq-pyscf.py | 126 +- tpls/json/LICENSE | 21 + tpls/json/{ => include/nlohmann}/json.hpp | 2177 +++++++---------- 23 files changed, 1568 insertions(+), 1584 deletions(-) create mode 100644 cudaqlib/operators/chemistry/drivers/pyscf/RESTPySCFDriver.cpp create mode 100644 tpls/json/LICENSE rename tpls/json/{ => include/nlohmann}/json.hpp (92%) diff --git a/cudaqlib/gse/utils/operator_pool.h b/cudaqlib/gse/utils/operator_pool.h index 212b068..df3af0a 100644 --- a/cudaqlib/gse/utils/operator_pool.h +++ b/cudaqlib/gse/utils/operator_pool.h @@ -39,6 +39,7 @@ inline std::size_t getIntLike(const std::any &any) { class operator_pool : public extension_point { public: operator_pool() = default; + virtual ~operator_pool() {} virtual std::vector generate(const std::unordered_map &config) const = 0; }; diff --git a/cudaqlib/operators.h b/cudaqlib/operators.h index 772eaeb..29f328b 100644 --- a/cudaqlib/operators.h +++ b/cudaqlib/operators.h @@ -8,4 +8,5 @@ #pragma once #include "operators/chemistry/MoleculePackageDriver.h" -#include "operators/fermion/fermion_to_spin.h" \ No newline at end of file +#include "operators/fermion/fermion_to_spin.h" +#include "operators/fermion/transformations/jordan_wigner.h" \ No newline at end of file diff --git a/cudaqlib/operators/CMakeLists.txt b/cudaqlib/operators/CMakeLists.txt index 66f4d97..3e098ef 100644 --- a/cudaqlib/operators/CMakeLists.txt +++ b/cudaqlib/operators/CMakeLists.txt @@ -16,15 +16,14 @@ add_library(${LIBRARY_NAME} SHARED fermion/transformations/jordan_wigner.cpp # chemistry package drivers chemistry/drivers/pyscf/ExternalPySCFDriver.cpp + chemistry/drivers/pyscf/RESTPySCFDriver.cpp ) - -target_link_libraries(${LIBRARY_NAME} PUBLIC cudaq::cudaq) target_include_directories(${LIBRARY_NAME} PRIVATE $ $ - $ + $ $ $ $ @@ -32,6 +31,8 @@ target_include_directories(${LIBRARY_NAME} $ $) +target_link_libraries(${LIBRARY_NAME} PUBLIC cudaq::cudaq cudaq::cudaq-common) + install( TARGETS ${LIBRARY_NAME} EXPORT ${LIBRARY_NAME}Targets @@ -44,4 +45,4 @@ install( DESTINATION lib/cmake/operators) install(FILES "${CMAKE_SOURCE_DIR}/cmake/${LIBRARY_NAME}Config.cmake" - DESTINATION lib/cmake/operators) \ No newline at end of file + DESTINATION lib/cmake/operators) diff --git a/cudaqlib/operators/chemistry/MoleculePackageDriver.h b/cudaqlib/operators/chemistry/MoleculePackageDriver.h index 8190ce7..181d176 100644 --- a/cudaqlib/operators/chemistry/MoleculePackageDriver.h +++ b/cudaqlib/operators/chemistry/MoleculePackageDriver.h @@ -25,6 +25,7 @@ class MoleculePackageDriver : public extension_point { int spin, int charge, molecule_options options = molecule_options()) = 0; + virtual bool is_available() const { return true; } /// Virtual destructor needed when deleting an instance of a derived class /// via a pointer to the base class. virtual ~MoleculePackageDriver(){}; diff --git a/cudaqlib/operators/chemistry/drivers/pyscf/ExternalPySCFDriver.cpp b/cudaqlib/operators/chemistry/drivers/pyscf/ExternalPySCFDriver.cpp index d2c8cc1..939e89e 100644 --- a/cudaqlib/operators/chemistry/drivers/pyscf/ExternalPySCFDriver.cpp +++ b/cudaqlib/operators/chemistry/drivers/pyscf/ExternalPySCFDriver.cpp @@ -6,7 +6,7 @@ * the terms of the Apache License 2.0 which accompanies this distribution. * ******************************************************************************/ -#include "json.hpp" +#include "nlohmann/json.hpp" #include "cudaqlib/operators/chemistry/MoleculePackageDriver.h" #include "cudaqlib/operators/fermion/fermion_to_spin.h" @@ -45,10 +45,10 @@ class external_pyscf std::string oneBodyFile = outFileName + "_one_body.dat"; std::string twoBodyFile = outFileName + "_two_body.dat"; std::string metadataFile = outFileName + "_metadata.json"; - std::filesystem::path libPath{cudaqlib::__internal__::getCUDAQLibraryPath()}; + std::filesystem::path libPath{ + cudaqlib::__internal__::getCUDAQLibraryPath()}; auto cudaqLibPath = libPath.parent_path(); - auto cudaqPySCFTool = - cudaqLibPath.parent_path() / "bin" / "cudaq-pyscf.py"; + auto cudaqPySCFTool = cudaqLibPath.parent_path() / "bin" / "cudaq-pyscf.py"; // Convert the geometry to an XYZ string for (auto &atom : geometry) @@ -58,11 +58,12 @@ class external_pyscf xyzFileStr = "\"" + xyzFileStr + "\""; std::string argString = fmt::format( - "{} --type {} --xyz {} --charge {} --spin {} --basis {} --out-file-name {} " + "{} --type {} --xyz {} --charge {} --spin {} --basis {} " + "--out-file-name {} " "{} --memory {} {} --cycles {} --initguess {} {} {} {} {} {} {} {} {} " "{} {} {}", - cudaqPySCFTool.string(), options.type, xyzFileStr, charge, spin, basis, outFileName, - options.verbose ? "--verbose" : "", options.memory, + cudaqPySCFTool.string(), options.type, xyzFileStr, charge, spin, basis, + outFileName, options.verbose ? "--verbose" : "", options.memory, options.symmetry ? "--symmetry" : "", options.cycles, options.initguess, options.UR ? "--UR" : "", options.nele_cas.has_value() @@ -87,22 +88,40 @@ class external_pyscf // Import all the data we need from the execution. std::ifstream f(metadataFile); auto metadata = nlohmann::json::parse(f); - metadata.dump(); - auto oneVec = readInData(oneBodyFile); - auto twoVec = readInData(twoBodyFile); - std::remove(metadataFile.c_str()); - std::remove(oneBodyFile.c_str()); - std::remove(twoBodyFile.c_str()); // Get the energy, num orbitals, and num qubits - auto energy = metadata["nuclear_energy"].get(); + std::unordered_map energies; + for (auto &[energyName, E] : metadata["energies"].items()) + energies.insert({energyName, E}); + + double energy = 0.0; + if (energies.contains("nuclear_energy")) + energy = energies["nuclear_energy"]; + else if (energies.contains("core_energy")) + energy = energies["core_energy"]; + auto numOrb = metadata["num_orbitals"].get(); auto numQubits = 2 * numOrb; + auto num_electrons = metadata["num_electrons"].get(); - // Create the fermion operator + // Get the operators fermion_op fermionOp(numQubits, energy); - fermionOp.hpq.set_data(oneVec); - fermionOp.hpqrs.set_data(twoVec); + std::unordered_map operators; + for (auto &[opFileName, opType] : metadata["operators"].items()) { + auto type = opType.get(); + if (type == "obi") + fermionOp.hpq.add(readInData(opFileName)); + else if (type == "tbi") + fermionOp.hpqrs.add(readInData(opFileName)); + + auto res = operators.insert({type, fermion_op(numQubits, energy)}); + if (type.find("obi") != std::string::npos) + res.first->second.hpq.set_data(readInData(opFileName)); + else + res.first->second.hpqrs.set_data(readInData(opFileName)); + + std::remove(opFileName.c_str()); + } // Transform to a spin operator auto transform = fermion_to_spin::get(options.fermion_to_string); @@ -110,12 +129,8 @@ class external_pyscf // Return the molecular hamiltonian return operators::molecular_hamiltonian{ - spinHamiltonian, - std::move(fermionOp), - metadata["num_electrons"].get(), - numOrb, - energy, - metadata["hf_energy"].get()}; + spinHamiltonian, std::move(fermionOp), num_electrons, numOrb, energy, + energies, std::move(operators)}; } CUDAQ_REGISTER_MOLECULEPACKAGEDRIVER(external_pyscf) diff --git a/cudaqlib/operators/chemistry/drivers/pyscf/RESTPySCFDriver.cpp b/cudaqlib/operators/chemistry/drivers/pyscf/RESTPySCFDriver.cpp new file mode 100644 index 0000000..175a563 --- /dev/null +++ b/cudaqlib/operators/chemistry/drivers/pyscf/RESTPySCFDriver.cpp @@ -0,0 +1,124 @@ +/******************************************************************************* + * Copyright (c) 2022 - 2023 NVIDIA Corporation & Affiliates. * + * All rights reserved. * + * * + * This source code and the accompanying materials are made available under * + * the terms of the Apache License 2.0 which accompanies this distribution. * + ******************************************************************************/ + +#include "nlohmann/json.hpp" + +#include "cudaqlib/operators/chemistry/MoleculePackageDriver.h" +#include "cudaqlib/operators/fermion/fermion_to_spin.h" +#include "cudaqlib/utils/library_utils.h" + +#include "common/RestClient.h" + +#include +#include +#include + +namespace cudaq::operators { + +class RESTPySCFDriver + : public details::MoleculePackageDriver_impl { + +public: + bool is_available() const override { + RestClient client; + std::map headers; + try { + auto res = client.get("localhost:8000/", "status", headers); + if (res.contains("status") && + res["status"].get() == "available") + return true; + } catch (std::exception& e) { + return false; + } + return true; + } + + /// @brief Create the molecular hamiltonian + operators::molecular_hamiltonian + createMolecule(const molecular_geometry &geometry, const std::string &basis, + int spin, int charge, molecule_options options) override { + std::string xyzFileStr = ""; + // Convert the geometry to an XYZ string + for (auto &atom : geometry) + xyzFileStr += + fmt::format("{} {:f} {:f} {:f}; ", atom.name, atom.coordinates[0], + atom.coordinates[1], atom.coordinates[2]); + + RestClient client; + nlohmann::json payload = {{"xyz", xyzFileStr}, + {"basis", basis}, + {"spin", spin}, + {"charge", charge}, + {"type", "gas_phase"}, + {"symmetry", false}, + {"cycles", options.cycles}, + {"initguess", options.initguess}, + {"UR", options.UR}, + {"MP2", options.MP2}, + {"natorb", options.natorb}, + {"casci", options.casci}, + {"ccsd", options.ccsd}, + {"casscf", options.casscf}, + {"integrals_natorb", options.integrals_natorb}, + {"integrals_casscf", options.integrals_casscf}, + {"verbose", options.verbose}}; + if (options.nele_cas.has_value()) + payload["nele_cas"] = options.nele_cas.value(); + if (options.norb_cas.has_value()) + payload["norb_cas"] = options.norb_cas.value(); + if (options.potfile.has_value()) + payload["potfile"] = options.potfile.value(); + + std::map headers{ + {"Content-Type", "application/json"}}; + auto metadata = client.post("localhost:8000/", "create_molecule", payload, + headers, true); + + // Get the energy, num orbitals, and num qubits + std::unordered_map energies; + for (auto &[energyName, E] : metadata["energies"].items()) + energies.insert({energyName, E}); + + double energy = 0.0; + if (energies.contains("nuclear_energy")) + energy = energies["nuclear_energy"]; + else if (energies.contains("core_energy")) + energy = energies["core_energy"]; + + auto numOrb = metadata["num_orbitals"].get(); + auto numQubits = 2 * numOrb; + auto num_electrons = metadata["num_electrons"].get(); + + // Get the operators + fermion_op fermionOp(numQubits, energy); + std::unordered_map operators; + auto hpqElements = metadata["hpq"]["data"]; + auto hpqrsElements = metadata["hpqrs"]["data"]; + std::vector> hpqValues, hpqrsValues; + for (auto &element : hpqElements) + hpqValues.push_back({element[0].get(), element[1].get()}); + for (auto &element : hpqrsElements) + hpqrsValues.push_back( + {element[0].get(), element[1].get()}); + fermionOp.hpq.set_data(hpqValues); + fermionOp.hpqrs.set_data(hpqrsValues); + + // Transform to a spin operator + auto transform = fermion_to_spin::get(options.fermion_to_string); + auto spinHamiltonian = transform->generate(fermionOp); + + // Return the molecular hamiltonian + return operators::molecular_hamiltonian{ + spinHamiltonian, std::move(fermionOp), num_electrons, numOrb, energy, + energies, std::move(operators)}; + } + + CUDAQ_REGISTER_MOLECULEPACKAGEDRIVER(RESTPySCFDriver) +}; + +} // namespace cudaq::operators \ No newline at end of file diff --git a/cudaqlib/operators/chemistry/molecule.cpp b/cudaqlib/operators/chemistry/molecule.cpp index 3e2a7e2..d7e0585 100644 --- a/cudaqlib/operators/chemistry/molecule.cpp +++ b/cudaqlib/operators/chemistry/molecule.cpp @@ -73,8 +73,14 @@ molecular_hamiltonian create_molecule(const molecular_geometry &geometry, if (!MoleculePackageDriver::is_registered(options.driver)) throw std::runtime_error("invalid molecule package driver (" + options.driver + ")"); - return MoleculePackageDriver::get(options.driver) - ->createMolecule(geometry, basis, spin, charge, options); + auto driver = MoleculePackageDriver::get(options.driver); + + if (!driver->is_available()) { + if (options.driver.find("REST") != std::string::npos) { + driver = MoleculePackageDriver::get("external_pyscf"); + } + } + return driver->createMolecule(geometry, basis, spin, charge, options); } void molecule_options::dump() { @@ -84,10 +90,10 @@ void molecule_options::dump() { std::cout << "\tsymmetry: " << symmetry << "\n"; std::cout << "\tcycles: " << cycles << "\n"; std::cout << "\tinitguess: " << initguess << "\n"; - std::cout << "\tnele_cas: " << (nele_cas.has_value() ? nele_cas.value() - : -1) << "\n"; - std::cout << "\tnorb_cas: " << (norb_cas.has_value() ? norb_cas.value() - : -1) << "\n"; + std::cout << "\tnele_cas: " << (nele_cas.has_value() ? nele_cas.value() : -1) + << "\n"; + std::cout << "\tnorb_cas: " << (norb_cas.has_value() ? norb_cas.value() : -1) + << "\n"; std::cout << "\tUR: " << std::boolalpha << UR << "\n"; std::cout << "\tMP2: " << std::boolalpha << MP2 << "\n"; std::cout << "\tnatorb: " << std::boolalpha << natorb << "\n"; @@ -101,4 +107,7 @@ void molecule_options::dump() { std::cout << "\tintegrals_natorb: " << std::boolalpha << integrals_natorb << "\n]\n"; } + +spin_op one_particle_op(std::size_t p, std::size_t q) { return spin_op(); } + } // namespace cudaq::operators diff --git a/cudaqlib/operators/chemistry/molecule.h b/cudaqlib/operators/chemistry/molecule.h index 382f6e7..0810fce 100644 --- a/cudaqlib/operators/chemistry/molecule.h +++ b/cudaqlib/operators/chemistry/molecule.h @@ -51,12 +51,12 @@ struct molecular_hamiltonian { std::size_t n_electrons; std::size_t n_orbitals; double nuclear_repulsion; - double hf_energy; - double fci_energy; + std::unordered_map energies; + std::unordered_map operators; }; struct molecule_options { - std::string driver = "external_pyscf"; + std::string driver = "RESTPySCFDriver"; std::string fermion_to_string = "jordan_wigner"; std::string type = "gas_phase"; bool symmetry = false; @@ -85,4 +85,6 @@ create_molecule(const molecular_geometry &geometry, const std::string &basis, int spin, int charge, molecule_options options = molecule_options()); +spin_op one_particle_op(std::size_t p, std::size_t q); + } // namespace cudaq::operators diff --git a/cudaqlib/operators/fermion/fermion_op.cpp b/cudaqlib/operators/fermion/fermion_op.cpp index 4e23ded..c36bd2a 100644 --- a/cudaqlib/operators/fermion/fermion_op.cpp +++ b/cudaqlib/operators/fermion/fermion_op.cpp @@ -19,6 +19,12 @@ one_body_integrals::one_body_integrals(const std::vector &shape) new std::complex[shape[0] * shape[1]]); } +void one_body_integrals::add(const std::vector> &data) { + auto *local = unOwnedData == nullptr ? ownedData.get() : unOwnedData; + xt::adapt(local, shape[0] * shape[1], xt::no_ownership(), shape) += + xt::adapt(data.data(), shape[0] * shape[1], xt::no_ownership(), shape); +} + void one_body_integrals::set_data( const std::vector> &data) { std::complex *ptr = nullptr; @@ -41,6 +47,14 @@ void one_body_integrals::dump() { << '\n'; } +void two_body_integrals::add(const std::vector> &data) { + auto *local = unOwnedData == nullptr ? ownedData.get() : unOwnedData; + xt::adapt(local, shape[0] * shape[1] * shape[2] * shape[3], + xt::no_ownership(), shape) += + xt::adapt(data.data(), shape[0] * shape[1] * shape[2] * shape[3], + xt::no_ownership(), shape); +} + two_body_integrals::two_body_integrals(const std::vector &shape) : shape(shape) { assert(shape.size() == 4); diff --git a/cudaqlib/operators/fermion/fermion_op.h b/cudaqlib/operators/fermion/fermion_op.h index 2e1c62e..98d7e23 100644 --- a/cudaqlib/operators/fermion/fermion_op.h +++ b/cudaqlib/operators/fermion/fermion_op.h @@ -28,6 +28,7 @@ class one_body_integrals { one_body_integrals(const std::vector &shape); std::complex &operator()(std::size_t i, std::size_t j) const; void dump(); + void add(const std::vector> &data); void set_data(const std::vector> &data); std::complex *raw_data() { if (ownedData) @@ -53,6 +54,7 @@ class two_body_integrals { std::complex &operator()(std::size_t p, std::size_t q, std::size_t r, std::size_t s) const; void dump(); + void add(const std::vector> &data); void set_data(const std::vector> &data); std::complex *raw_data() { if (ownedData) diff --git a/cudaqlib/operators/fermion/fermion_to_spin.h b/cudaqlib/operators/fermion/fermion_to_spin.h index e720aa4..dd90262 100644 --- a/cudaqlib/operators/fermion/fermion_to_spin.h +++ b/cudaqlib/operators/fermion/fermion_to_spin.h @@ -8,8 +8,8 @@ #pragma once -#include "cudaqlib/utils/extension_point.h" #include "cudaq/spin_op.h" +#include "cudaqlib/utils/extension_point.h" #include "fermion_op.h" namespace cudaq::operators { @@ -22,11 +22,13 @@ class fermion_to_spin : public extension_point { /// @brief Given a fermionic representation of an operator /// generate an equivalent operator on spins. virtual spin_op generate(const fermion_op &fermionOp) = 0; + virtual ~fermion_to_spin() {} + }; CUDAQ_DEFINE_EXTENSION_IMPL(fermion_to_spin) -#define CUDAQ_REGISTER_FERMION_TO_SPIN(TYPE) \ +#define CUDAQ_REGISTER_FERMION_TO_SPIN(TYPE) \ static inline const std::string class_identifier = #TYPE; \ static std::unique_ptr create() { \ return std::make_unique(); \ diff --git a/cudaqlib/optim/observe_gradient.h b/cudaqlib/optim/observe_gradient.h index 3a6d145..a6a5bdd 100644 --- a/cudaqlib/optim/observe_gradient.h +++ b/cudaqlib/optim/observe_gradient.h @@ -105,6 +105,8 @@ class observe_gradient : public extension_point { numRequiredExpectations = 0; batchIdx = 0; } + + virtual ~observe_gradient() {} }; CUDAQ_DEFINE_EXTENSION_IMPL(observe_gradient) diff --git a/python/bindings/operators/py_operators.cpp b/python/bindings/operators/py_operators.cpp index 5640160..cb88b09 100644 --- a/python/bindings/operators/py_operators.cpp +++ b/python/bindings/operators/py_operators.cpp @@ -21,14 +21,66 @@ namespace cudaq::operators { void bindOperators(py::module &mod) { auto operators = mod.def_submodule("operators"); + + operators.def("jordan_wigner", [](fermion_op& op) { + return fermion_to_spin::get("jordan_wigner")->generate(op); + }); + + py::class_(operators, "fermion_to_spin") + .def_static("get", + [](const std::string &name) { return fermion_to_spin::get(name); }) + .def("generate", &fermion_to_spin::generate, ""); + + py::class_(operators, "OneBodyIntegrals", + py::buffer_protocol()) + .def_buffer([](one_body_integrals &m) -> py::buffer_info { + return py::buffer_info( + m.raw_data(), /* Pointer to buffer */ + sizeof(std::complex), /* Size of one scalar */ + py::format_descriptor>::format(), /* Python + struct-style format + descriptor */ + 2, /* Number of dimensions */ + m.shape, /* Buffer dimensions */ + {sizeof(std::complex) * + m.shape[1], /* Strides (in bytes) for each index */ + sizeof(std::complex)}); + }); + + py::class_(operators, "TwoBodyIntegrals", + py::buffer_protocol()) + .def_buffer([](two_body_integrals &m) -> py::buffer_info { + auto calculateStrides = [](std::vector &shape_) { + std::vector strides(4); + strides[3] = sizeof(std::complex); + strides[2] = strides[3] * shape_[3]; + strides[1] = strides[2] * shape_[2]; + strides[0] = strides[1] * shape_[1]; + return strides; + }; + return py::buffer_info( + m.raw_data(), /* Pointer to buffer */ + sizeof(std::complex), /* Size of one scalar */ + py::format_descriptor>::format(), /* Python + struct-style format + descriptor */ + 4, /* Number of dimensions */ + m.shape, /* Buffer dimensions */ + calculateStrides(m.shape)); + }); + + py::class_(operators, "FermionOperator", "") + .def_readonly("hpq", &fermion_op::hpq, "") + .def_readonly("hpqrs", &fermion_op::hpqrs, ""); + py::class_(operators, "MolecularHamiltonian") + .def_readonly("energies", &molecular_hamiltonian::energies) + .def_readonly("operators", &molecular_hamiltonian::operators) .def_readonly("hamiltonian", &molecular_hamiltonian::hamiltonian) .def_readonly("n_electrons", &molecular_hamiltonian::n_electrons) .def_readonly("n_orbitals", &molecular_hamiltonian::n_orbitals) .def_readonly("nuclear_repulsion", - &molecular_hamiltonian::nuclear_repulsion) - .def_readonly("hf_energy", &molecular_hamiltonian::hf_energy) - .def_readonly("fci_energy", &molecular_hamiltonian::fci_energy); + &molecular_hamiltonian::nuclear_repulsion); operators.def( "create_molecule", diff --git a/python/cudaqlib/tools/chemistry/pyscf/generators/gas_phase_generator.py b/python/cudaqlib/tools/chemistry/pyscf/generators/gas_phase_generator.py index 0298846..979f8f0 100644 --- a/python/cudaqlib/tools/chemistry/pyscf/generators/gas_phase_generator.py +++ b/python/cudaqlib/tools/chemistry/pyscf/generators/gas_phase_generator.py @@ -11,7 +11,7 @@ from functools import reduce try: from pyscf import gto, scf, cc, ao2mo, mp, mcscf, solvent, fci -except ValueError: +except RuntimeError: print( 'PySCF should be installed to use cudaq-pyscf tool. Use pip install pyscf' ) @@ -120,14 +120,15 @@ def get_spin_hamiltonian(self, xyz:str, spin:int, charge: int, basis:str, symmet # Initialize the molecule ################################ filename = xyz.split('.')[0] if outFileName == None else outFileName + energies = {} if (nele_cas is None) and (norb_cas is not None): - raise ValueError( + raise RuntimeError( "WARN: nele_cas is None and norb_cas is not None. nele_cas and norb_cas should be either both None\ or have values") if (nele_cas is not None) and (norb_cas is None): - raise ValueError( + raise RuntimeError( "WARN: nele_cas is not None and norb_cas is None. nele_cas and norb_cas should be either both None\ or have values") @@ -135,7 +136,7 @@ def get_spin_hamiltonian(self, xyz:str, spin:int, charge: int, basis:str, symmet # To add (coming soon) if UR and nele_cas is None: - raise ValueError( + raise RuntimeError( "WARN: Unrestricted spin calculation for the full space is not supported yet on Cudaq.\ Only active space is currently supported for the unrestricted spin calculations." ) @@ -181,9 +182,9 @@ def get_spin_hamiltonian(self, xyz:str, spin:int, charge: int, basis:str, symmet print('[pyscf] Total number of orbitals = ', norb) nelec = mol.nelectron + energies['hf_energy'] = myhf.e_tot if verbose: print('[pyscf] Total number of electrons = ', nelec) - if verbose: print('[pyscf] HF energy = ', myhf.e_tot) ########################## @@ -209,13 +210,10 @@ def get_spin_hamiltonian(self, xyz:str, spin:int, charge: int, basis:str, symmet print( '[pyscf] Natural orbital (alpha orbitals) occupation number from UR-MP2: ' ) - if verbose: print(noon_a) - if verbose: print( '[pyscf] Natural orbital (beta orbitals) occupation number from UR-MP2: ' ) - if verbose: print(noon_b) natorbs = np.zeros(np.shape(myhf.mo_coeff)) @@ -226,7 +224,7 @@ def get_spin_hamiltonian(self, xyz:str, spin:int, charge: int, basis:str, symmet else: if spin != 0: - raise ValueError("WARN: ROMP2 is unvailable in pyscf.") + raise RuntimeError("WARN: ROMP2 is unvailable in pyscf.") else: mymp = mp.MP2(myhf) mp_ecorr, mp_t2 = mymp.kernel() @@ -241,7 +239,6 @@ def get_spin_hamiltonian(self, xyz:str, spin:int, charge: int, basis:str, symmet print( '[pyscf] Natural orbital occupation number from R-MP2: ' ) - if verbose: print(noons) ####################################### @@ -258,6 +255,7 @@ def get_spin_hamiltonian(self, xyz:str, spin:int, charge: int, basis:str, symmet print( '[pyscf] UR-CASCI energy using natural orbitals= ', mycasci.e_tot) + energies['UR-CASCI'] = mycasci.e_tot else: mycasci_mo = mcscf.UCASCI(myhf, norb_cas, nele_cas) mycasci_mo.kernel() @@ -265,6 +263,7 @@ def get_spin_hamiltonian(self, xyz:str, spin:int, charge: int, basis:str, symmet print( '[pyscf] UR-CASCI energy using molecular orbitals= ', mycasci_mo.e_tot) + energies['UR-CASCI'] = mycasci_mo.e_tot else: if nele_cas is None: @@ -272,6 +271,7 @@ def get_spin_hamiltonian(self, xyz:str, spin:int, charge: int, basis:str, symmet result = myfci.kernel() if verbose: print('[pyscf] FCI energy = ', result[0]) + energies['fci_energy'] = result[0] else: if natorb and (spin == 0): @@ -282,8 +282,10 @@ def get_spin_hamiltonian(self, xyz:str, spin:int, charge: int, basis:str, symmet '[pyscf] R-CASCI energy using natural orbitals= ', mycasci.e_tot) + energies['R-CASCI'] = mycasci.e_tot + elif natorb and (spin != 0): - raise ValueError( + raise RuntimeError( "WARN: Natural orbitals cannot be computed. ROMP2 is unvailable in pyscf." ) @@ -295,6 +297,9 @@ def get_spin_hamiltonian(self, xyz:str, spin:int, charge: int, basis:str, symmet '[pyscf] R-CASCI energy using molecular orbitals= ', mycasci_mo.e_tot) + energies['R-CASCI'] = mycasci_mo.e_tot + + ######################## # CCSD ######################## @@ -328,6 +333,9 @@ def get_spin_hamiltonian(self, xyz:str, spin:int, charge: int, basis:str, symmet '[pyscf] UR-CCSD energy of the active space using molecular orbitals= ', mycc.e_tot) + energies['UR-CCSD'] = mycc.e_tot + + else: if nele_cas is None: mycc = cc.CCSD(myhf) @@ -341,8 +349,8 @@ def get_spin_hamiltonian(self, xyz:str, spin:int, charge: int, basis:str, symmet frozen = [] frozen += [y for y in range(0, mc.ncore)] frozen += [ - y for y in range(mc.ncore + - norb_cas, len(myhf.mo_coeff)) + y + for y in range(mc.ncore + norb_cas, len(myhf.mo_coeff)) ] if natorb and (spin == 0): mycc = cc.CCSD(myhf, frozen=frozen, mo_coeff=natorbs) @@ -354,7 +362,7 @@ def get_spin_hamiltonian(self, xyz:str, spin:int, charge: int, basis:str, symmet mycc.e_tot) elif natorb and (spin != 0): - raise ValueError( + raise RuntimeError( "WARN: Natural orbitals cannot be computed. ROMP2 is unvailable in pyscf." ) @@ -367,12 +375,15 @@ def get_spin_hamiltonian(self, xyz:str, spin:int, charge: int, basis:str, symmet '[pyscf] R-CCSD energy of the active space using molecular orbitals= ', mycc.e_tot) + energies['R-CCSD'] = mycc.e_tot + + ######################### # CASSCF ######################### if casscf: if nele_cas is None: - raise ValueError("WARN: You should define the active space.") + raise RuntimeError("WARN: You should define the active space.") if UR: if natorb: @@ -404,7 +415,7 @@ def get_spin_hamiltonian(self, xyz:str, spin:int, charge: int, basis:str, symmet mycas.e_tot) elif natorb and (spin != 0): - raise ValueError( + raise RuntimeError( "WARN: Natural orbitals cannot be computed. ROMP2 is unvailable in pyscf." ) @@ -417,6 +428,9 @@ def get_spin_hamiltonian(self, xyz:str, spin:int, charge: int, basis:str, symmet '[pyscf] R-CASSCF energy using molecular orbitals= ', mycas.e_tot) + energies['R-CASSCF'] = mycas.e_tot + + ################################### # CASCI: FCI of the active space ################################## @@ -432,27 +446,30 @@ def get_spin_hamiltonian(self, xyz:str, spin:int, charge: int, basis:str, symmet nele_cas, ecore=ecore) if verbose: - print('[pyscf] UR-CASCI energy using the casscf orbitals= ', - e_fci) + print( + '[pyscf] UR-CASCI energy using the casscf orbitals= ', + e_fci) else: if natorb and (spin != 0): - raise ValueError( + raise RuntimeError( "WARN: Natural orbitals cannot be computed. ROMP2 is unavailable in pyscf." ) - else: - h1e_cas, ecore = mycas.get_h1eff() - h2e_cas = mycas.get_h2eff() - - e_fci, fcivec = fci.direct_spin1.kernel(h1e_cas, - h2e_cas, - norb_cas, - nele_cas, - ecore=ecore) - if verbose: - print( - '[pyscf] R-CASCI energy using the casscf orbitals= ', - e_fci) + + h1e_cas, ecore = mycas.get_h1eff() + h2e_cas = mycas.get_h2eff() + + e_fci, fcivec = fci.direct_spin1.kernel(h1e_cas, + h2e_cas, + norb_cas, + nele_cas, + ecore=ecore) + if verbose: + print( + '[pyscf] R-CASCI energy using the casscf orbitals= ', + e_fci) + energies['UR-CASCI'] = e_fci + ################################################################################### # Computation of one- and two- electron integrals for the active space Hamiltonian @@ -486,10 +503,11 @@ def get_spin_hamiltonian(self, xyz:str, spin:int, charge: int, basis:str, symmet order='C') h2e_cas[2] = np.asarray(h2e_cas[2].transpose(0, 2, 3, 1), order='C') - h2e_cas_prime = np.asarray(h2e_cas[1].transpose(2, 0, 1, 3), + h2e_cas_prime = np.asarray(h2e_cas[1].transpose( + 2, 0, 1, 3), order='C') else: - raise ValueError( + raise RuntimeError( "WARN: You need to run casscf. Use casscf=True.") else: @@ -536,12 +554,14 @@ def get_spin_hamiltonian(self, xyz:str, spin:int, charge: int, basis:str, symmet # molecular electron integrals obi, tbi, e_nn = self.generate_molecular_spin_ham_restricted( h1e, h2e, nuclear_repulsion) + energies['nuclear_energy'] = e_nn else: if integrals_natorb: if spin != 0: - raise ValueError("WARN: ROMP2 is unvailable in pyscf.") + raise RuntimeError( + "WARN: ROMP2 is unvailable in pyscf.") else: mc = mcscf.CASCI(myhf, norb_cas, nele_cas) h1e_cas, ecore = mc.get_h1eff(natorbs) @@ -558,7 +578,7 @@ def get_spin_hamiltonian(self, xyz:str, spin:int, charge: int, basis:str, symmet h2e_cas = np.asarray(h2e_cas.transpose(0, 2, 3, 1), order='C') else: - raise ValueError( + raise RuntimeError( "WARN: You need to run casscf. Use casscf=True.") else: @@ -573,6 +593,7 @@ def get_spin_hamiltonian(self, xyz:str, spin:int, charge: int, basis:str, symmet # molecular electron integrals obi, tbi, core_energy = self.generate_molecular_spin_ham_restricted( h1e_cas, h2e_cas, ecore) + energies['core_energy'] = ecore # Dump obi and tbi to binary file. if cache_data: @@ -581,30 +602,26 @@ def get_spin_hamiltonian(self, xyz:str, spin:int, charge: int, basis:str, symmet ###################################################### # Dump energies / etc to a metadata file - if nele_cas is None: - if cache_data: - metadata = { - 'num_electrons': nelec, - 'num_orbitals': norb, - 'nuclear_energy': e_nn, - 'hf_energy': myhf.e_tot + metadata = {} + if cache_data: + metadata = { + 'num_electrons': nelec if nele_cas == None else nele_cas, + 'num_orbitals': norb if nele_cas == None else norb_cas, + 'hf_energy': myhf.e_tot, + 'energies': energies, + 'operators': { + f'{filename}_one_body.dat': 'obi', + f'{filename}_two_body.dat': 'tbi' } - with open(f'{filename}_metadata.json', 'w') as f: - json.dump(metadata, f) + } - return (obi, tbi, e_nn, nelec, norb) + with open(f'{filename}_metadata.json', 'w') as f: + json.dump(metadata, f) + + if nele_cas is None: + return (obi, tbi, e_nn, nelec, norb, metadata) - else: - if cache_data: - metadata = { - 'num_electrons': nele_cas, - 'num_orbitals': norb_cas, - 'nuclear_energy': ecore, - 'hf_energy': myhf.e_tot - } - with open(f'{filename}_metadata.json', 'w') as f: - json.dump(metadata, f) - return (obi, tbi, ecore, nele_cas, norb_cas) + return (obi, tbi, ecore, nele_cas, norb_cas, metadata) def generate(self, xyz, basis, **kwargs): if xyz == None: @@ -644,8 +661,8 @@ def generate(self, xyz, basis, **kwargs): 'out_file_name'] if 'out_file_name' in kwargs else None return self.get_spin_hamiltonian(xyz, spin, charge, basis, symmetry, memory, cycles, initguess, UR, - nele_cas, norb_cas, MP2, natorb, casci, - ccsd, casscf, integrals_natorb, + nele_cas, norb_cas, MP2, natorb, + casci, ccsd, casscf, integrals_natorb, integrals_casscf, verbose, cache_data, outfilename) diff --git a/python/cudaqlib/tools/chemistry/pyscf/generators/polarizable_embedded_generator.py b/python/cudaqlib/tools/chemistry/pyscf/generators/polarizable_embedded_generator.py index 269bb89..c3f0167 100644 --- a/python/cudaqlib/tools/chemistry/pyscf/generators/polarizable_embedded_generator.py +++ b/python/cudaqlib/tools/chemistry/pyscf/generators/polarizable_embedded_generator.py @@ -92,6 +92,8 @@ def get_spin_hamiltonian(self,xyz:str, potfile:str, spin:int, charge: int, basis print( 'WARN: UHF is not implemented yet for PE model in Cudaq. RHF & ROHF are only supported.' ) + + energies = {} ################################ # Initialize the molecule @@ -122,11 +124,11 @@ def get_spin_hamiltonian(self,xyz:str, potfile:str, spin:int, charge: int, basis norb = mf_pe.mo_coeff.shape[1] if verbose: print('[Pyscf] Total number of orbitals = ', norb) - if verbose: print('[Pyscf] Total HF energy with solvent:', mf_pe.e_tot) - if verbose: print('[Pyscf] Polarizable embedding energy from HF: ', mf_pe.with_solvent.e) + + energies['hf_energy'] = mf_pe.e_tot dm = mf_pe.make_rdm1() @@ -136,26 +138,27 @@ def get_spin_hamiltonian(self,xyz:str, potfile:str, spin:int, charge: int, basis if MP2: if spin != 0: - raise ValueError("WARN: ROMP2 is unvailable in pyscf.") - else: - mymp = mp.MP2(mf_pe) - mymp = solvent.PE(mymp, potfile) - mymp.run() + raise RuntimeError("WARN: ROMP2 is unvailable in pyscf.") + + mymp = mp.MP2(mf_pe) + mymp = solvent.PE(mymp, potfile) + mymp.run() + if verbose: + print('[pyscf] R-MP2 energy with solvent= ', mymp.e_tot) + print('[Pyscf] Polarizable embedding energy from MP: ', + mymp.with_solvent.e) + energies['r-mp2'] = mymp.e_tot + energies['pe-mp2-energy'] = mymp.with_solvent.e + + if integrals_natorb or natorb: + # Compute natural orbitals + noons, natorbs = mcscf.addons.make_natural_orbitals(mymp) if verbose: - print('[pyscf] R-MP2 energy with solvent= ', mymp.e_tot) + print( + '[Pyscf] Natural orbital occupation number from R-MP2: ' + ) if verbose: - print('[Pyscf] Polarizable embedding energy from MP: ', - mymp.with_solvent.e) - - if integrals_natorb or natorb: - # Compute natural orbitals - noons, natorbs = mcscf.addons.make_natural_orbitals(mymp) - if verbose: - print( - '[Pyscf] Natural orbital occupation number from R-MP2: ' - ) - if verbose: - print(noons) + print(noons) ################# # CASCI @@ -163,36 +166,30 @@ def get_spin_hamiltonian(self,xyz:str, potfile:str, spin:int, charge: int, basis if casci: if nele_cas is None: + raise RuntimeError('[Pyscf] FCI with PE is not supported.') - #myfci=fci.FCI(mf_pe) - #myfci=solvent.PE(myfci, args.potfile,dm) - #myfci.run() - #if verbose: print('[pyscf] FCI energy with solvent= ', myfci.e_tot) - #if verbose: print('[Pyscf] Polarizable embedding energy from FCI: ', myfci.with_solvent.e) - print('[Pyscf] FCI with PE is not supported.') + if natorb and (spin == 0): + mycasci = mcscf.CASCI(mf_pe, norb_cas, nele_cas) + mycasci = solvent.PE(mycasci, potfile) + mycasci.run(natorbs) + if verbose: + print( + '[pyscf] CASCI energy (using natural orbitals) with solvent= ', + mycasci.e_tot) + energies['casci-natorb'] = mycasci.e_tot else: - if natorb and (spin == 0): - mycasci = mcscf.CASCI(mf_pe, norb_cas, nele_cas) - mycasci = solvent.PE(mycasci, potfile) - mycasci.run(natorbs) - if verbose: - print( - '[pyscf] CASCI energy (using natural orbitals) with solvent= ', - mycasci.e_tot) - - else: - mycasci = mcscf.CASCI(mf_pe, norb_cas, nele_cas) - mycasci = solvent.PE(mycasci, potfile) - mycasci.run() - if verbose: - print( - '[pyscf] CASCI energy (using molecular orbitals) with solvent= ', - mycasci.e_tot) - if verbose: - print( - '[Pyscf] Polarizable embedding energy from CASCI: ', - mycasci.with_solvent.e) + mycasci = mcscf.CASCI(mf_pe, norb_cas, nele_cas) + mycasci = solvent.PE(mycasci, potfile) + mycasci.run() + if verbose: + print( + '[pyscf] CASCI energy (using molecular orbitals) with solvent= ', + mycasci.e_tot) + print('[Pyscf] Polarizable embedding energy from CASCI: ', + mycasci.with_solvent.e) + energies['casci-mo'] = mycasci.e_tot + energies['pe-casci-energy'] = mycasci.with_solvent.e ################# ## CCSD @@ -206,9 +203,11 @@ def get_spin_hamiltonian(self,xyz:str, potfile:str, spin:int, charge: int, basis if verbose: print('[Pyscf] Total CCSD energy with solvent: ', mycc.e_tot) - if verbose: print('[Pyscf] Polarizable embedding energy from CCSD: ', mycc.with_solvent.e) + + energies['ccsd-mo'] = mycc.e_tot + energies['pe-ccsd-energy'] = mycc.with_solvent.e else: mc = mcscf.CASCI(mf_pe, norb_cas, nele_cas) @@ -226,6 +225,7 @@ def get_spin_hamiltonian(self,xyz:str, potfile:str, spin:int, charge: int, basis print( '[pyscf] R-CCSD energy of the active space (using natural orbitals) with solvent= ', mycc.e_tot) + energies['r-ccsd-natorb'] = mycc.e_tot else: mycc = cc.CCSD(mf_pe, frozen=frozen) mycc = solvent.PE(mycc, potfile) @@ -234,10 +234,12 @@ def get_spin_hamiltonian(self,xyz:str, potfile:str, spin:int, charge: int, basis print( '[pyscf] CCSD energy of the active space (using molecular orbitals) with solvent= ', mycc.e_tot) - if verbose: print( '[Pyscf] Polarizable embedding energy from CCSD: ', mycc.with_solvent.e) + energies['ccsd-mo'] = mycc.e_tot + energies['pe-ccsd-energy'] = mycc.with_solvent.e + ############################ # CASSCF ############################ @@ -251,6 +253,7 @@ def get_spin_hamiltonian(self,xyz:str, potfile:str, spin:int, charge: int, basis print( '[pyscf] CASSCF energy (using natural orbitals) with solvent= ', mycas.e_tot) + energies['casscf-natorb'] = mycas.e_tot else: mycas = mcscf.CASSCF(mf_pe, norb_cas, nele_cas) @@ -261,6 +264,7 @@ def get_spin_hamiltonian(self,xyz:str, potfile:str, spin:int, charge: int, basis print( '[pyscf] CASSCF energy (using molecular orbitals) with solvent= ', mycas.e_tot) + energies['casscf-mo'] = mycas.e_tot ########################################################################### # Computation of one and two electron integrals for the QC+PE @@ -298,6 +302,7 @@ def get_spin_hamiltonian(self,xyz:str, potfile:str, spin:int, charge: int, basis mype = PolEmbed(mol, potfile) E_pe, V_pe, V_es, V_ind = mype.get_pe_contribution(dm) + energies['pe-energy'] = E_pe # convert V_pe from atomic orbital to molecular orbital representation V_pe_mo = reduce(np.dot, (mf_pe.mo_coeff.T, V_pe, mf_pe.mo_coeff)) @@ -305,13 +310,19 @@ def get_spin_hamiltonian(self,xyz:str, potfile:str, spin:int, charge: int, basis obi_pe = self.generate_pe_spin_ham_restricted(V_pe_mo) if cache: obi_pe.astype(complex).tofile(f'{filename}_pe_one_body.dat') + # V_pe_mo.asttype(complex).tofile(f'{filename}_v_pe_mo.dat') metadata = { 'num_electrons': nelec, 'num_orbitals': norb, 'nuclear_energy': e_nn, - 'PE_energy': E_pe, - 'HF_energy': mf_pe.e_tot + 'hf_energy': mf_pe.e_tot, + 'energies': energies, + 'operators': { + f'{filename}_pe_one_body.dat': 'pe_obi', + f'{filename}_one_body.dat': 'obi', + f'{filename}_two_body.dat': 'tbi' + } } if cache: with open(f'{filename}_metadata.json', 'w') as f: @@ -319,96 +330,54 @@ def get_spin_hamiltonian(self,xyz:str, potfile:str, spin:int, charge: int, basis return (obi, tbi, nuclear_repulsion, obi_pe, nelec, norb) - else: - if integrals_natorb: - mc = mcscf.CASCI(mf_pe, norb_cas, nele_cas) - h1e_cas, ecore = mc.get_h1eff(natorbs) - h2e_cas = mc.get_h2eff(natorbs) - h2e_cas = ao2mo.restore('1', h2e_cas, norb_cas) - h2e_cas = np.asarray(h2e_cas.transpose(0, 2, 3, 1), order='C') - - obi, tbi, core_energy = self.generate_molecular_spin_ham_restricted( - h1e_cas, h2e_cas, ecore) + if integrals_natorb: + mc = mcscf.CASCI(mf_pe, norb_cas, nele_cas) + h1e_cas, ecore = mc.get_h1eff(natorbs) + h2e_cas = mc.get_h2eff(natorbs) + h2e_cas = ao2mo.restore('1', h2e_cas, norb_cas) + h2e_cas = np.asarray(h2e_cas.transpose(0, 2, 3, 1), order='C') - # Dump obi and tbi to binary file. - if cache: - obi.astype(complex).tofile(f'{filename}_one_body.dat') - tbi.astype(complex).tofile(f'{filename}_two_body.dat') - - if casci: - - dm = mcscf.make_rdm1(mycasci) - mype = PolEmbed(mol, potfile) - E_pe, V_pe, V_es, V_ind = mype.get_pe_contribution(dm) - #convert from ao to mo - - #V_pe_mo=reduce(np.dot, (mf_pe.mo_coeff.T, V_pe, mf_pe.mo_coeff)) - V_pe_mo = reduce(np.dot, (natorbs.T, V_pe, natorbs)) - - V_pe_cas = V_pe_mo[mycasci.ncore:mycasci.ncore + - mycasci.ncas, - mycasci.ncore:mycasci.ncore + - mycasci.ncas] - - obi_pe = self.generate_pe_spin_ham_restricted(V_pe_cas) - if cache: - obi_pe.astype(complex).tofile( - f'{filename}_pe_one_body.dat') - - metadata = { - 'num_electrons': nele_cas, - 'num_orbitals': norb_cas, - 'core_energy': ecore, - 'PE_energy': E_pe, - 'HF_energy': mf_pe.e_tot - } - if cache: - with open(f'{filename}_metadata.json', 'w') as f: - json.dump(metadata, f) + obi, tbi, core_energy = self.generate_molecular_spin_ham_restricted( + h1e_cas, h2e_cas, ecore) - return (obi, tbi, ecore, obi_pe, nele_cas, norb_cas) - - else: - raise ValueError('You should use casci=True.') - - elif integrals_casscf: - if casscf: - h1e_cas, ecore = mycas.get_h1eff() - h2e_cas = mycas.get_h2eff() - h2e_cas = ao2mo.restore('1', h2e_cas, norb_cas) - h2e_cas = np.asarray(h2e_cas.transpose(0, 2, 3, 1), - order='C') - else: - raise ValueError( - "WARN: You need to run casscf. Use casscf=True.") - obi, tbi, core_energy = self.generate_molecular_spin_ham_restricted( - h1e_cas, h2e_cas, ecore) + # Dump obi and tbi to binary file. + if cache: + obi.astype(complex).tofile(f'{filename}_one_body.dat') + tbi.astype(complex).tofile(f'{filename}_two_body.dat') - # Dump obi and tbi to binary file. - if cache: - obi.astype(complex).tofile(f'{filename}_one_body.dat') - tbi.astype(complex).tofile(f'{filename}_two_body.dat') + if casci: - dm = mcscf.make_rdm1(mycas) - # Compute the PE contribution to the Hamiltonian + dm = mcscf.make_rdm1(mycasci) mype = PolEmbed(mol, potfile) E_pe, V_pe, V_es, V_ind = mype.get_pe_contribution(dm) + #convert from ao to mo - V_pe_mo = reduce(np.dot, - (mycas.mo_coeff.T, V_pe, mycas.mo_coeff)) - V_pe_cas = V_pe_mo[mycas.ncore:mycas.ncore + mycas.ncas, - mycas.ncore:mycas.ncore + mycas.ncas] + #V_pe_mo=reduce(np.dot, (mf_pe.mo_coeff.T, V_pe, mf_pe.mo_coeff)) + V_pe_mo = reduce(np.dot, (natorbs.T, V_pe, natorbs)) + + V_pe_cas = V_pe_mo[mycasci.ncore:mycasci.ncore + mycasci.ncas, + mycasci.ncore:mycasci.ncore + mycasci.ncas] + obi_pe = self.generate_pe_spin_ham_restricted(V_pe_cas) if cache: - obi_pe.astype(complex).tofile(f'{filename}_pe_one_body.dat') + obi_pe.astype(complex).tofile( + f'{filename}_pe_one_body.dat') + energies['core-energy'] = ecore + energies['pe-energy'] = E_pe metadata = { 'num_electrons': nele_cas, 'num_orbitals': norb_cas, 'core_energy': ecore, - 'PE_energy': E_pe, - 'HF_energy': mf_pe.e_tot + 'pe_energy': E_pe, + 'hf_energy': mf_pe.e_tot, + 'energies': energies, + 'operators': { + f'{filename}_pe_one_body.dat': 'pe_obi', + f'{filename}_one_body.dat': 'obi', + f'{filename}_two_body.dat': 'tbi' + } } if cache: with open(f'{filename}_metadata.json', 'w') as f: @@ -416,46 +385,105 @@ def get_spin_hamiltonian(self,xyz:str, potfile:str, spin:int, charge: int, basis return (obi, tbi, ecore, obi_pe, nele_cas, norb_cas) - else: - mc = mcscf.CASCI(mf_pe, norb_cas, nele_cas) - h1e_cas, ecore = mc.get_h1eff(mf_pe.mo_coeff) - h2e_cas = mc.get_h2eff(mf_pe.mo_coeff) - h2e_cas = ao2mo.restore('1', h2e_cas, norb_cas) - h2e_cas = np.asarray(h2e_cas.transpose(0, 2, 3, 1), order='C') - obi, tbi, core_energy = self.generate_molecular_spin_ham_restricted( - h1e_cas, h2e_cas, ecore) - - # Dump obi and tbi to binary file. - if cache: - obi.astype(complex).tofile(f'{filename}_one_body.dat') - tbi.astype(complex).tofile(f'{filename}_two_body.dat') + raise ValueError('You should use casci=True.') - dm = mf_pe.make_rdm1() - # Compute the PE contribution to the Hamiltonian - mype = PolEmbed(mol, potfile) - E_pe, V_pe, V_es, V_ind = mype.get_pe_contribution(dm) - #convert from ao to mo - V_pe_mo = reduce(np.dot, - (mf_pe.mo_coeff.T, V_pe, mf_pe.mo_coeff)) + if integrals_casscf: + if not casscf: + raise RuntimeError( + "WARN: You need to run casscf. Use casscf=True.") - V_pe_cas = V_pe_mo[mc.ncore:mc.ncore + mc.ncas, - mc.ncore:mc.ncore + mc.ncas] - obi_pe = self.generate_pe_spin_ham_restricted(V_pe_cas) - if cache: - obi_pe.astype(complex).tofile(f'{filename}_pe_one_body.dat') + h1e_cas, ecore = mycas.get_h1eff() + h2e_cas = mycas.get_h2eff() + h2e_cas = ao2mo.restore('1', h2e_cas, norb_cas) + h2e_cas = np.asarray(h2e_cas.transpose(0, 2, 3, 1), order='C') - metadata = { - 'num_electrons': nele_cas, - 'num_orbitals': norb_cas, - 'core_energy': ecore, - 'PE_energy': E_pe, - 'HF_energy': mf_pe.e_tot + obi, tbi, core_energy = self.generate_molecular_spin_ham_restricted( + h1e_cas, h2e_cas, ecore) + + dm = mcscf.make_rdm1(mycas) + # Compute the PE contribution to the Hamiltonian + mype = PolEmbed(mol, potfile) + E_pe, V_pe, V_es, V_ind = mype.get_pe_contribution(dm) + #convert from ao to mo + V_pe_mo = reduce(np.dot, (mycas.mo_coeff.T, V_pe, mycas.mo_coeff)) + + V_pe_cas = V_pe_mo[mycas.ncore:mycas.ncore + mycas.ncas, + mycas.ncore:mycas.ncore + mycas.ncas] + obi_pe = self.generate_pe_spin_ham_restricted(V_pe_cas) + if cache: + obi_pe.astype(complex).tofile(f'{filename}_pe_one_body.dat') + obi.astype(complex).tofile(f'{filename}_one_body.dat') + tbi.astype(complex).tofile(f'{filename}_two_body.dat') + energies ['pe-energy'] = E_pe + energies['core-energy'] = ecore + metadata = { + 'num_electrons': nele_cas, + 'num_orbitals': norb_cas, + 'core_energy': ecore, + 'pe_energy': E_pe, + 'hf_energy': mf_pe.e_tot, + 'energies': energies, + 'operators': { + f'{filename}_pe_one_body.dat': 'pe_obi', + f'{filename}_one_body.dat': 'obi', + f'{filename}_two_body.dat': 'tbi' } - if cache: - with open(f'{filename}_metadata.json', 'w') as f: - json.dump(metadata, f) + } + if cache: + with open(f'{filename}_metadata.json', 'w') as f: + json.dump(metadata, f) - return (obi, tbi, ecore, obi_pe, nele_cas, norb_cas) + return (obi, tbi, ecore, obi_pe, nele_cas, norb_cas) + + mc = mcscf.CASCI(mf_pe, norb_cas, nele_cas) + h1e_cas, ecore = mc.get_h1eff(mf_pe.mo_coeff) + h2e_cas = mc.get_h2eff(mf_pe.mo_coeff) + h2e_cas = ao2mo.restore('1', h2e_cas, norb_cas) + h2e_cas = np.asarray(h2e_cas.transpose(0, 2, 3, 1), order='C') + obi, tbi, core_energy = self.generate_molecular_spin_ham_restricted( + h1e_cas, h2e_cas, ecore) + + dm = mf_pe.make_rdm1() + # Compute the PE contribution to the Hamiltonian + mype = PolEmbed(mol, potfile) + E_pe, V_pe, V_es, V_ind = mype.get_pe_contribution(dm) + print('TESTING HERE, ', V_pe) + + #convert from ao to mo + V_pe_mo = reduce(np.dot, (mf_pe.mo_coeff.T, V_pe, mf_pe.mo_coeff)) + + V_pe_cas = V_pe_mo[mc.ncore:mc.ncore + mc.ncas, + mc.ncore:mc.ncore + mc.ncas] + obi_pe = self.generate_pe_spin_ham_restricted(V_pe_cas) + if cache: + obi.astype(complex).tofile(f'{filename}_one_body.dat') + tbi.astype(complex).tofile(f'{filename}_two_body.dat') + obi_pe.astype(complex).tofile(f'{filename}_pe_one_body.dat') + V_pe.astype(complex).tofile(f'{filename}_vpe.dat') + mf_pe.mo_coeff.astype(complex).tofile(f'{filename}_mo_coeff.dat') + + energies['pe-energy'] = E_pe + energies['core-energy'] = ecore + metadata = { + 'num_electrons': nele_cas, + 'num_orbitals': norb_cas, + 'core_energy': ecore, + 'pe_energy': E_pe, + 'hf_energy': mf_pe.e_tot, + 'energies': energies, + 'operators': { + f'{filename}_pe_one_body.dat': 'pe_obi', + f'{filename}_one_body.dat': 'obi', + f'{filename}_two_body.dat': 'tbi', + f'{filename}_mo_coeff.dat': 'pe_mo_coeff_obi', + f'{filename}_vpe.dat': 'pe_vpe_obi' + } + } + if cache: + with open(f'{filename}_metadata.json', 'w') as f: + json.dump(metadata, f) + + return (obi, tbi, ecore, obi_pe, nele_cas, norb_cas) def generate(self, xyz, basis, **kwargs): requiredOptions = ['potfile', 'spin', 'charge'] @@ -489,8 +517,8 @@ def generate(self, xyz, basis, **kwargs): 'out_file_name'] if 'out_file_name' in kwargs else None return self.get_spin_hamiltonian(xyz, potfile, spin, charge, basis, symmetry, memory, cycles, initguess, - nele_cas, norb_cas, MP2, natorb, casci, - ccsd, casscf, integrals_natorb, + nele_cas, norb_cas, MP2, natorb, + casci, ccsd, casscf, integrals_natorb, integrals_casscf, verbose, cache_data, outfilename) diff --git a/python/tests/test_operators.py b/python/tests/test_operators.py index d839def..1585e26 100644 --- a/python/tests/test_operators.py +++ b/python/tests/test_operators.py @@ -14,6 +14,19 @@ import cudaq, cudaqlib from cudaq import spin +def test_operators(): + geometry = [('H', (0., 0., 0.)), ('H', (0., 0., .7474))] + molecule = cudaqlib.operators.create_molecule( + geometry, 'sto-3g', 0, 0, verbose=True, casci=True) + print(molecule.hamiltonian.to_string()) + print(molecule.energies) + assert np.isclose(-1.11, molecule.energies['hf_energy'], atol=1e-2) + assert np.isclose(-1.13, molecule.energies['fci_energy'], atol=1e-2) + minE = molecule.hamiltonian.to_matrix().minimal_eigenvalue() + assert np.isclose(-1.13, minE, atol=1e-2) + + + def test_chemistry_operators(): diff --git a/python/tests/test_pyscf_tool.py b/python/tests/test_pyscf_tool.py index 0613d28..12a192f 100644 --- a/python/tests/test_pyscf_tool.py +++ b/python/tests/test_pyscf_tool.py @@ -63,7 +63,7 @@ def test_gas_phase_active_space_cudaq(): print(molecule) assert molecule.n_electrons == 6 assert molecule.n_orbitals == 6 - assert np.isclose(-107.49999, molecule.hf_energy, atol=1e-3) + assert np.isclose(-107.49999, molecule.energies['hf_energy'], atol=1e-3) def test_pyscf_pe(): diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 0a017b2..bf4b212 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -44,9 +44,13 @@ endif() target_include_directories(test_kernels PRIVATE ${CMAKE_SOURCE_DIR}) target_link_libraries(test_kernels PRIVATE + cudaq::cudaq-common + /home/.cudaq/lib/libcpr.a + cudaq::cudaq cudaq::cudaq-builder - cudaq-operators cudaq-operator-pools cudaq-optim + cudaq-operators + gtest_main) gtest_discover_tests(test_kernels) diff --git a/tests/kernels/UCCSDTester.cpp b/tests/kernels/UCCSDTester.cpp index 256d765..a4ff72d 100644 --- a/tests/kernels/UCCSDTester.cpp +++ b/tests/kernels/UCCSDTester.cpp @@ -287,7 +287,7 @@ TEST(UCCSDTester, checkUCCSDAnsatz) { auto numQubits = molecule.n_orbitals * 2; // EXPECT_NEAR(molecule.fci_energy, -1.137, 1e-3); - EXPECT_NEAR(molecule.hf_energy, -1.1163255644, 1e-3); + EXPECT_NEAR(molecule.energies["hf_energy"], -1.1163255644, 1e-3); EXPECT_EQ(numElectrons, 2); EXPECT_EQ(numQubits, 4); diff --git a/tests/operators/OperatorsTester.cpp b/tests/operators/OperatorsTester.cpp index c37ed67..d72d8b8 100644 --- a/tests/operators/OperatorsTester.cpp +++ b/tests/operators/OperatorsTester.cpp @@ -394,11 +394,11 @@ TEST(OperatorsTester, checkMolecule) { cudaq::operators::molecular_geometry geometry{{"H", {0., 0., 0.}}, {"H", {0., 0., .7474}}}; auto molecule = cudaq::operators::create_molecule(geometry, "sto-3g", 0, 0, - {.verbose = true}); + {.driver="RESTPySCFDriver",.verbose = true}); molecule.hamiltonian.dump(); // EXPECT_NEAR(molecule.fci_energy, -1.137, 1e-3); - EXPECT_NEAR(molecule.hf_energy, -1.1163255644, 1e-3); + EXPECT_NEAR(molecule.energies["hf_energy"], -1.1163255644, 1e-3); EXPECT_EQ(molecule.n_electrons, 2); EXPECT_EQ(molecule.n_orbitals, 2); @@ -499,7 +499,7 @@ H -0.4691 -0.7570 0.0 geometry, "631g", 0, 0, {.nele_cas = 6, .norb_cas = 6, .ccsd = true, .verbose = true}); - molecule.hamiltonian.dump(); + // molecule.hamiltonian.dump(); EXPECT_EQ(molecule.n_electrons, 6); EXPECT_EQ(molecule.n_orbitals, 6); } \ No newline at end of file diff --git a/tools/chemistry/cudaq-pyscf.py b/tools/chemistry/cudaq-pyscf.py index f46866f..6f9bfba 100755 --- a/tools/chemistry/cudaq-pyscf.py +++ b/tools/chemistry/cudaq-pyscf.py @@ -1,16 +1,23 @@ #!/usr/bin/env python3 -import argparse, json +import argparse import importlib, pkgutil import cudaqlib.tools.chemistry.pyscf.generators +from fastapi import FastAPI, Response +from pydantic import BaseModel, PlainValidator, PlainSerializer +import uvicorn, os, signal, importlib, pkgutil +from typing import List, Annotated +import numpy as np + def iter_namespace(ns_pkg): return pkgutil.iter_modules(ns_pkg.__path__, ns_pkg.__name__ + ".") discovered_plugins = {} -for finder, name, ispkg in iter_namespace(cudaqlib.tools.chemistry.pyscf.generators): +for finder, name, ispkg in iter_namespace( + cudaqlib.tools.chemistry.pyscf.generators): try: discovered_plugins[name] = importlib.import_module(name) except ModuleNotFoundError: @@ -27,6 +34,8 @@ def iter_namespace(ns_pkg): parser = argparse.ArgumentParser() +parser.add_argument('--server-mode', action='store_true', default=False) + # Add arguments parser.add_argument( '--type', @@ -40,7 +49,9 @@ def iter_namespace(ns_pkg): parser.add_argument('--out-file-name', help='base file name for output data.', type=str) -parser.add_argument('--spin', help="no. of unpaired electrons (2 *s)", type=int) +parser.add_argument('--spin', + help="no. of unpaired electrons (2 *s)", + type=int) parser.add_argument('--symmetry', help="", action='store_true', default=False) parser.add_argument('--memory', help="", type=float, default=4000) parser.add_argument('--cycles', help="", type=int, default=100) @@ -69,11 +80,104 @@ def iter_namespace(ns_pkg): # Parse the arguments args = parser.parse_args() -if args.type not in hamiltonianGenerators: - raise RuntimeError(f'invalid hamiltonian generator type - {args.type}') -hamiltonianGenerator = hamiltonianGenerators[ - args.type].get_hamiltonian_generator() - -filterArgs = ['xyz', 'basis'] -filteredArgs = {k: v for (k, v) in vars(args).items() if k not in filterArgs} -hamiltonianGenerator.generate(args.xyz, args.basis, **filteredArgs) + +if not args.server_mode: + + if args.type not in hamiltonianGenerators: + raise RuntimeError(f'invalid hamiltonian generator type - {args.type}') + hamiltonianGenerator = hamiltonianGenerators[ + args.type].get_hamiltonian_generator() + + filterArgs = ['xyz', 'basis'] + filteredArgs = { + k: v + for (k, v) in vars(args).items() if k not in filterArgs + } + hamiltonianGenerator.generate(args.xyz, args.basis, **filteredArgs) + + exit(0) + +app = FastAPI() + + +@app.get("/shutdown") +async def shutdown(): + os.kill(os.getpid(), signal.SIGTERM) + return Response(status_code=200, content='Server shutting down...') + + +Complex = Annotated[ + complex, + PlainValidator(lambda x: x if isinstance(x, complex) else complex( + x.real, x.imag)), + PlainSerializer(lambda x: (x.real, x.imag), return_type=tuple)] + + +class IntegralsData(BaseModel): + data: List[Complex] + + @classmethod + def from_numpy(cls, array: np.ndarray): + return cls(data=array.flatten().tolist()) + + + +class MoleculeInput(BaseModel): + basis: str + xyz: str + spin: int + charge: int + type: str = 'gas_phase' + symmetry: bool = False + cycles: int = 100 + memory: float = 4000. + initguess: str = 'minao' + UR: bool = False + MP2: bool = False + natorb: bool = False + casci: bool = False + ccsd: bool = False + casscf: bool = False + integrals_natorb: bool = False + integrals_casscf: bool = False + verbose: bool = False + nele_cas: int = None + norb_cas: int = None + potfile: str = None + + + +class Molecule(BaseModel): + energies: dict + num_orbitals: int + num_electrons: int + hpq: IntegralsData + hpqrs: IntegralsData + + +@app.get("/status") +async def get_status(): + return {"status" : "available"} + +@app.post("/create_molecule") +async def create_molecule(molecule: MoleculeInput): + hamiltonianGenerator = hamiltonianGenerators[ + molecule.type].get_hamiltonian_generator() + + filterArgs = ['xyz', 'basis'] + filteredArgs = { + k: v + for (k, v) in vars(molecule).items() if k not in filterArgs + } + filteredArgs['cache_data'] = False + res = hamiltonianGenerator.generate(molecule.xyz, molecule.basis, + **filteredArgs) + return Molecule(energies=res[-1]['energies'], + num_orbitals=res[-1]['num_orbitals'], + num_electrons=res[-1]['num_electrons'], + hpq=IntegralsData.from_numpy(res[0]), + hpqrs=IntegralsData.from_numpy(res[1])) + + +if __name__ == "__main__": + uvicorn.run(app, host="0.0.0.0", port=8000) diff --git a/tpls/json/LICENSE b/tpls/json/LICENSE new file mode 100644 index 0000000..2fd5ad7 --- /dev/null +++ b/tpls/json/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2013-2022 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. \ No newline at end of file diff --git a/tpls/json/json.hpp b/tpls/json/include/nlohmann/json.hpp similarity index 92% rename from tpls/json/json.hpp rename to tpls/json/include/nlohmann/json.hpp index 8b72ea6..e9bf475 100644 --- a/tpls/json/json.hpp +++ b/tpls/json/include/nlohmann/json.hpp @@ -1,9 +1,9 @@ // __ _____ _____ _____ // __| | __| | | | JSON for Modern C++ -// | | |__ | | | | | | version 3.11.3 +// | | |__ | | | | | | version 3.11.1 // |_____|_____|_____|_|___| https://github.com/nlohmann/json // -// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann +// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann // SPDX-License-Identifier: MIT /****************************************************************************\ @@ -27,6 +27,7 @@ #endif // JSON_NO_IO #include // random_access_iterator_tag #include // unique_ptr +#include // accumulate #include // string, stoi, to_string #include // declval, forward, move, pair, swap #include // vector @@ -34,10 +35,10 @@ // #include // __ _____ _____ _____ // __| | __| | | | JSON for Modern C++ -// | | |__ | | | | | | version 3.11.3 +// | | |__ | | | | | | version 3.11.1 // |_____|_____|_____|_|___| https://github.com/nlohmann/json // -// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann +// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann // SPDX-License-Identifier: MIT @@ -47,10 +48,10 @@ // #include // __ _____ _____ _____ // __| | __| | | | JSON for Modern C++ -// | | |__ | | | | | | version 3.11.3 +// | | |__ | | | | | | version 3.11.1 // |_____|_____|_____|_|___| https://github.com/nlohmann/json // -// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann +// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann // SPDX-License-Identifier: MIT @@ -59,7 +60,7 @@ #ifndef JSON_SKIP_LIBRARY_VERSION_CHECK #if defined(NLOHMANN_JSON_VERSION_MAJOR) && defined(NLOHMANN_JSON_VERSION_MINOR) && defined(NLOHMANN_JSON_VERSION_PATCH) - #if NLOHMANN_JSON_VERSION_MAJOR != 3 || NLOHMANN_JSON_VERSION_MINOR != 11 || NLOHMANN_JSON_VERSION_PATCH != 3 + #if NLOHMANN_JSON_VERSION_MAJOR != 3 || NLOHMANN_JSON_VERSION_MINOR != 11 || NLOHMANN_JSON_VERSION_PATCH != 1 #warning "Already included a different version of the library!" #endif #endif @@ -67,7 +68,7 @@ #define NLOHMANN_JSON_VERSION_MAJOR 3 // NOLINT(modernize-macro-to-enum) #define NLOHMANN_JSON_VERSION_MINOR 11 // NOLINT(modernize-macro-to-enum) -#define NLOHMANN_JSON_VERSION_PATCH 3 // NOLINT(modernize-macro-to-enum) +#define NLOHMANN_JSON_VERSION_PATCH 1 // NOLINT(modernize-macro-to-enum) #ifndef JSON_DIAGNOSTICS #define JSON_DIAGNOSTICS 0 @@ -89,70 +90,49 @@ #define NLOHMANN_JSON_ABI_TAG_LEGACY_DISCARDED_VALUE_COMPARISON #endif -#ifndef NLOHMANN_JSON_NAMESPACE_NO_VERSION - #define NLOHMANN_JSON_NAMESPACE_NO_VERSION 0 -#endif +#define NLOHMANN_JSON_ABI_PREFIX_EX(major, minor, patch) \ + json_v ## major ## _ ## minor ## _ ## patch +#define NLOHMANN_JSON_ABI_PREFIX(major, minor, patch) \ + NLOHMANN_JSON_ABI_PREFIX_EX(major, minor, patch) -// Construct the namespace ABI tags component -#define NLOHMANN_JSON_ABI_TAGS_CONCAT_EX(a, b) json_abi ## a ## b -#define NLOHMANN_JSON_ABI_TAGS_CONCAT(a, b) \ - NLOHMANN_JSON_ABI_TAGS_CONCAT_EX(a, b) +#define NLOHMANN_JSON_ABI_CONCAT_EX(a, b, c) a ## b ## c +#define NLOHMANN_JSON_ABI_CONCAT(a, b, c) \ + NLOHMANN_JSON_ABI_CONCAT_EX(a, b, c) -#define NLOHMANN_JSON_ABI_TAGS \ - NLOHMANN_JSON_ABI_TAGS_CONCAT( \ - NLOHMANN_JSON_ABI_TAG_DIAGNOSTICS, \ +#define NLOHMANN_JSON_ABI_STRING \ + NLOHMANN_JSON_ABI_CONCAT( \ + NLOHMANN_JSON_ABI_PREFIX( \ + NLOHMANN_JSON_VERSION_MAJOR, \ + NLOHMANN_JSON_VERSION_MINOR, \ + NLOHMANN_JSON_VERSION_PATCH), \ + NLOHMANN_JSON_ABI_TAG_DIAGNOSTICS, \ NLOHMANN_JSON_ABI_TAG_LEGACY_DISCARDED_VALUE_COMPARISON) -// Construct the namespace version component -#define NLOHMANN_JSON_NAMESPACE_VERSION_CONCAT_EX(major, minor, patch) \ - _v ## major ## _ ## minor ## _ ## patch -#define NLOHMANN_JSON_NAMESPACE_VERSION_CONCAT(major, minor, patch) \ - NLOHMANN_JSON_NAMESPACE_VERSION_CONCAT_EX(major, minor, patch) - -#if NLOHMANN_JSON_NAMESPACE_NO_VERSION -#define NLOHMANN_JSON_NAMESPACE_VERSION -#else -#define NLOHMANN_JSON_NAMESPACE_VERSION \ - NLOHMANN_JSON_NAMESPACE_VERSION_CONCAT(NLOHMANN_JSON_VERSION_MAJOR, \ - NLOHMANN_JSON_VERSION_MINOR, \ - NLOHMANN_JSON_VERSION_PATCH) -#endif - -// Combine namespace components -#define NLOHMANN_JSON_NAMESPACE_CONCAT_EX(a, b) a ## b -#define NLOHMANN_JSON_NAMESPACE_CONCAT(a, b) \ - NLOHMANN_JSON_NAMESPACE_CONCAT_EX(a, b) - #ifndef NLOHMANN_JSON_NAMESPACE -#define NLOHMANN_JSON_NAMESPACE \ - nlohmann::NLOHMANN_JSON_NAMESPACE_CONCAT( \ - NLOHMANN_JSON_ABI_TAGS, \ - NLOHMANN_JSON_NAMESPACE_VERSION) + #define NLOHMANN_JSON_NAMESPACE nlohmann::NLOHMANN_JSON_ABI_STRING #endif #ifndef NLOHMANN_JSON_NAMESPACE_BEGIN -#define NLOHMANN_JSON_NAMESPACE_BEGIN \ - namespace nlohmann \ - { \ - inline namespace NLOHMANN_JSON_NAMESPACE_CONCAT( \ - NLOHMANN_JSON_ABI_TAGS, \ - NLOHMANN_JSON_NAMESPACE_VERSION) \ +#define NLOHMANN_JSON_NAMESPACE_BEGIN \ + namespace nlohmann \ + { \ + inline namespace NLOHMANN_JSON_ABI_STRING \ { #endif #ifndef NLOHMANN_JSON_NAMESPACE_END -#define NLOHMANN_JSON_NAMESPACE_END \ - } /* namespace (inline namespace) NOLINT(readability/namespace) */ \ - } // namespace nlohmann +#define NLOHMANN_JSON_NAMESPACE_END \ + } /* namespace (abi_string) */ \ + } /* namespace nlohmann */ #endif // #include // __ _____ _____ _____ // __| | __| | | | JSON for Modern C++ -// | | |__ | | | | | | version 3.11.3 +// | | |__ | | | | | | version 3.11.1 // |_____|_____|_____|_|___| https://github.com/nlohmann/json // -// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann +// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann // SPDX-License-Identifier: MIT @@ -172,19 +152,16 @@ // #include // __ _____ _____ _____ // __| | __| | | | JSON for Modern C++ -// | | |__ | | | | | | version 3.11.3 +// | | |__ | | | | | | version 3.11.1 // |_____|_____|_____|_|___| https://github.com/nlohmann/json // -// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann +// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann // SPDX-License-Identifier: MIT #include // nullptr_t #include // exception -#if JSON_DIAGNOSTICS - #include // accumulate -#endif #include // runtime_error #include // to_string #include // vector @@ -192,10 +169,10 @@ // #include // __ _____ _____ _____ // __| | __| | | | JSON for Modern C++ -// | | |__ | | | | | | version 3.11.3 +// | | |__ | | | | | | version 3.11.1 // |_____|_____|_____|_|___| https://github.com/nlohmann/json // -// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann +// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann // SPDX-License-Identifier: MIT @@ -208,10 +185,10 @@ // #include // __ _____ _____ _____ // __| | __| | | | JSON for Modern C++ -// | | |__ | | | | | | version 3.11.3 +// | | |__ | | | | | | version 3.11.1 // |_____|_____|_____|_|___| https://github.com/nlohmann/json // -// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann +// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann // SPDX-License-Identifier: MIT @@ -220,10 +197,10 @@ // #include // __ _____ _____ _____ // __| | __| | | | JSON for Modern C++ -// | | |__ | | | | | | version 3.11.3 +// | | |__ | | | | | | version 3.11.1 // |_____|_____|_____|_|___| https://github.com/nlohmann/json // -// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann +// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann // SPDX-License-Identifier: MIT @@ -233,10 +210,10 @@ // #include // __ _____ _____ _____ // __| | __| | | | JSON for Modern C++ -// | | |__ | | | | | | version 3.11.3 +// | | |__ | | | | | | version 3.11.1 // |_____|_____|_____|_|___| https://github.com/nlohmann/json // -// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann +// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann // SPDX-License-Identifier: MIT @@ -320,10 +297,10 @@ NLOHMANN_JSON_NAMESPACE_END // __ _____ _____ _____ // __| | __| | | | JSON for Modern C++ -// | | |__ | | | | | | version 3.11.3 +// | | |__ | | | | | | version 3.11.1 // |_____|_____|_____|_|___| https://github.com/nlohmann/json // -// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann +// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann // SPDX-FileCopyrightText: 2016-2021 Evan Nemerson // SPDX-License-Identifier: MIT @@ -2485,14 +2462,6 @@ JSON_HEDLEY_DIAGNOSTIC_POP #endif #endif -#ifndef JSON_HAS_STATIC_RTTI - #if !defined(_HAS_STATIC_RTTI) || _HAS_STATIC_RTTI != 0 - #define JSON_HAS_STATIC_RTTI 1 - #else - #define JSON_HAS_STATIC_RTTI 0 - #endif -#endif - #ifdef JSON_HAS_CPP_17 #define JSON_INLINE_VARIABLE inline #else @@ -2600,13 +2569,12 @@ JSON_HEDLEY_DIAGNOSTIC_POP class NumberUnsignedType, class NumberFloatType, \ template class AllocatorType, \ template class JSONSerializer, \ - class BinaryType, \ - class CustomBaseClass> + class BinaryType> #define NLOHMANN_BASIC_JSON_TPL \ basic_json + AllocatorType, JSONSerializer, BinaryType> // Macros to simplify conversion from/to types @@ -2756,10 +2724,7 @@ JSON_HEDLEY_DIAGNOSTIC_POP #define NLOHMANN_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT(Type, ...) \ friend void to_json(nlohmann::json& nlohmann_json_j, const Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) } \ - friend void from_json(const nlohmann::json& nlohmann_json_j, Type& nlohmann_json_t) { const Type nlohmann_json_default_obj{}; NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_FROM_WITH_DEFAULT, __VA_ARGS__)) } - -#define NLOHMANN_DEFINE_TYPE_INTRUSIVE_ONLY_SERIALIZE(Type, ...) \ - friend void to_json(nlohmann::json& nlohmann_json_j, const Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) } + friend void from_json(const nlohmann::json& nlohmann_json_j, Type& nlohmann_json_t) { Type nlohmann_json_default_obj; NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_FROM_WITH_DEFAULT, __VA_ARGS__)) } /*! @brief macro @@ -2770,12 +2735,10 @@ JSON_HEDLEY_DIAGNOSTIC_POP inline void to_json(nlohmann::json& nlohmann_json_j, const Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) } \ inline void from_json(const nlohmann::json& nlohmann_json_j, Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_FROM, __VA_ARGS__)) } -#define NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE_ONLY_SERIALIZE(Type, ...) \ - inline void to_json(nlohmann::json& nlohmann_json_j, const Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) } - #define NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE_WITH_DEFAULT(Type, ...) \ inline void to_json(nlohmann::json& nlohmann_json_j, const Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) } \ - inline void from_json(const nlohmann::json& nlohmann_json_j, Type& nlohmann_json_t) { const Type nlohmann_json_default_obj{}; NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_FROM_WITH_DEFAULT, __VA_ARGS__)) } + inline void from_json(const nlohmann::json& nlohmann_json_j, Type& nlohmann_json_t) { Type nlohmann_json_default_obj; NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_FROM_WITH_DEFAULT, __VA_ARGS__)) } + // inspired from https://stackoverflow.com/a/26745591 // allows to call any std function as if (e.g. with begin): @@ -2939,10 +2902,10 @@ NLOHMANN_JSON_NAMESPACE_END // #include // __ _____ _____ _____ // __| | __| | | | JSON for Modern C++ -// | | |__ | | | | | | version 3.11.3 +// | | |__ | | | | | | version 3.11.1 // |_____|_____|_____|_|___| https://github.com/nlohmann/json // -// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann +// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann // SPDX-License-Identifier: MIT @@ -3014,10 +2977,10 @@ NLOHMANN_JSON_NAMESPACE_END // #include // __ _____ _____ _____ // __| | __| | | | JSON for Modern C++ -// | | |__ | | | | | | version 3.11.3 +// | | |__ | | | | | | version 3.11.1 // |_____|_____|_____|_|___| https://github.com/nlohmann/json // -// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann +// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann // SPDX-License-Identifier: MIT @@ -3056,16 +3019,15 @@ NLOHMANN_JSON_NAMESPACE_END // #include // __ _____ _____ _____ // __| | __| | | | JSON for Modern C++ -// | | |__ | | | | | | version 3.11.3 +// | | |__ | | | | | | version 3.11.1 // |_____|_____|_____|_|___| https://github.com/nlohmann/json // -// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann +// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann // SPDX-FileCopyrightText: 2018 The Abseil Authors // SPDX-License-Identifier: MIT -#include // array #include // size_t #include // conditional, enable_if, false_type, integral_constant, is_constructible, is_integral, is_same, remove_cv, remove_reference, true_type #include // index_sequence, make_index_sequence, index_sequence_for @@ -3210,19 +3172,15 @@ template<> struct priority_tag<0> {}; template struct static_const { - static JSON_INLINE_VARIABLE constexpr T value{}; + static constexpr T value{}; }; #ifndef JSON_HAS_CPP_17 + template - constexpr T static_const::value; -#endif + constexpr T static_const::value; // NOLINT(readability-redundant-declaration) -template -inline constexpr std::array make_array(Args&& ... args) -{ - return std::array {{static_cast(std::forward(args))...}}; -} +#endif } // namespace detail NLOHMANN_JSON_NAMESPACE_END @@ -3230,10 +3188,10 @@ NLOHMANN_JSON_NAMESPACE_END // #include // __ _____ _____ _____ // __| | __| | | | JSON for Modern C++ -// | | |__ | | | | | | version 3.11.3 +// | | |__ | | | | | | version 3.11.1 // |_____|_____|_____|_|___| https://github.com/nlohmann/json // -// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann +// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann // SPDX-License-Identifier: MIT @@ -3242,15 +3200,14 @@ NLOHMANN_JSON_NAMESPACE_END #include // false_type, is_constructible, is_integral, is_same, true_type #include // declval #include // tuple -#include // char_traits // #include // __ _____ _____ _____ // __| | __| | | | JSON for Modern C++ -// | | |__ | | | | | | version 3.11.3 +// | | |__ | | | | | | version 3.11.1 // |_____|_____|_____|_|___| https://github.com/nlohmann/json // -// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann +// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann // SPDX-License-Identifier: MIT @@ -3315,10 +3272,10 @@ NLOHMANN_JSON_NAMESPACE_END // #include // __ _____ _____ _____ // __| | __| | | | JSON for Modern C++ -// | | |__ | | | | | | version 3.11.3 +// | | |__ | | | | | | version 3.11.1 // |_____|_____|_____|_|___| https://github.com/nlohmann/json // -// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann +// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann // SPDX-License-Identifier: MIT @@ -3335,10 +3292,10 @@ NLOHMANN_JSON_NAMESPACE_END // #include // __ _____ _____ _____ // __| | __| | | | JSON for Modern C++ -// | | |__ | | | | | | version 3.11.3 +// | | |__ | | | | | | version 3.11.1 // |_____|_____|_____|_|___| https://github.com/nlohmann/json // -// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann +// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann // SPDX-License-Identifier: MIT @@ -3359,10 +3316,10 @@ NLOHMANN_JSON_NAMESPACE_END // #include // __ _____ _____ _____ // __| | __| | | | JSON for Modern C++ -// | | |__ | | | | | | version 3.11.3 +// | | |__ | | | | | | version 3.11.1 // |_____|_____|_____|_|___| https://github.com/nlohmann/json // -// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann +// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann // SPDX-License-Identifier: MIT #ifndef INCLUDE_NLOHMANN_JSON_FWD_HPP_ @@ -3406,13 +3363,12 @@ NLOHMANN_JSON_NAMESPACE_END template class AllocatorType = std::allocator, template class JSONSerializer = adl_serializer, - class BinaryType = std::vector, // cppcheck-suppress syntaxError - class CustomBaseClass = void> + class BinaryType = std::vector> class basic_json; /// @brief JSON Pointer defines a string syntax for identifying a specific value within a JSON document /// @sa https://json.nlohmann.me/api/json_pointer/ - template + template class json_pointer; /*! @@ -3595,63 +3551,6 @@ struct actual_object_comparator template using actual_object_comparator_t = typename actual_object_comparator::type; -///////////////// -// char_traits // -///////////////// - -// Primary template of char_traits calls std char_traits -template -struct char_traits : std::char_traits -{}; - -// Explicitly define char traits for unsigned char since it is not standard -template<> -struct char_traits : std::char_traits -{ - using char_type = unsigned char; - using int_type = uint64_t; - - // Redefine to_int_type function - static int_type to_int_type(char_type c) noexcept - { - return static_cast(c); - } - - static char_type to_char_type(int_type i) noexcept - { - return static_cast(i); - } - - static constexpr int_type eof() noexcept - { - return static_cast(EOF); - } -}; - -// Explicitly define char traits for signed char since it is not standard -template<> -struct char_traits : std::char_traits -{ - using char_type = signed char; - using int_type = uint64_t; - - // Redefine to_int_type function - static int_type to_int_type(char_type c) noexcept - { - return static_cast(c); - } - - static char_type to_char_type(int_type i) noexcept - { - return static_cast(i); - } - - static constexpr int_type eof() noexcept - { - return static_cast(EOF); - } -}; - /////////////////// // is_ functions // /////////////////// @@ -3688,6 +3587,7 @@ template struct is_default_constructible> : conjunction...> {}; + template struct is_constructible : std::is_constructible {}; @@ -3703,6 +3603,7 @@ struct is_constructible> : is_default_constructible struct is_constructible> : is_default_constructible> {}; + template struct is_iterator_traits : std::false_type {}; @@ -4112,6 +4013,7 @@ struct value_in_range_of_impl2 } }; + template struct value_in_range_of_impl2 { @@ -4152,68 +4054,16 @@ inline constexpr bool value_in_range_of(T val) return value_in_range_of_impl1::test(val); } -template -using bool_constant = std::integral_constant; - -/////////////////////////////////////////////////////////////////////////////// -// is_c_string -/////////////////////////////////////////////////////////////////////////////// - -namespace impl -{ - -template -inline constexpr bool is_c_string() -{ - using TUnExt = typename std::remove_extent::type; - using TUnCVExt = typename std::remove_cv::type; - using TUnPtr = typename std::remove_pointer::type; - using TUnCVPtr = typename std::remove_cv::type; - return - (std::is_array::value && std::is_same::value) - || (std::is_pointer::value && std::is_same::value); -} - -} // namespace impl - -// checks whether T is a [cv] char */[cv] char[] C string -template -struct is_c_string : bool_constant()> {}; - -template -using is_c_string_uncvref = is_c_string>; - -/////////////////////////////////////////////////////////////////////////////// -// is_transparent -/////////////////////////////////////////////////////////////////////////////// - -namespace impl -{ - -template -inline constexpr bool is_transparent() -{ - return is_detected::value; -} - -} // namespace impl - -// checks whether T has a member named is_transparent -template -struct is_transparent : bool_constant()> {}; - -/////////////////////////////////////////////////////////////////////////////// - } // namespace detail NLOHMANN_JSON_NAMESPACE_END // #include // __ _____ _____ _____ // __| | __| | | | JSON for Modern C++ -// | | |__ | | | | | | version 3.11.3 +// | | |__ | | | | | | version 3.11.1 // |_____|_____|_____|_|___| https://github.com/nlohmann/json // -// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann +// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann // SPDX-License-Identifier: MIT @@ -4237,28 +4087,28 @@ inline std::size_t concat_length() } template -inline std::size_t concat_length(const char* cstr, const Args& ... rest); +inline std::size_t concat_length(const char* cstr, Args&& ... rest); template -inline std::size_t concat_length(const StringType& str, const Args& ... rest); +inline std::size_t concat_length(const StringType& str, Args&& ... rest); template -inline std::size_t concat_length(const char /*c*/, const Args& ... rest) +inline std::size_t concat_length(const char /*c*/, Args&& ... rest) { - return 1 + concat_length(rest...); + return 1 + concat_length(std::forward(rest)...); } template -inline std::size_t concat_length(const char* cstr, const Args& ... rest) +inline std::size_t concat_length(const char* cstr, Args&& ... rest) { // cppcheck-suppress ignoredReturnValue - return ::strlen(cstr) + concat_length(rest...); + return ::strlen(cstr) + concat_length(std::forward(rest)...); } template -inline std::size_t concat_length(const StringType& str, const Args& ... rest) +inline std::size_t concat_length(const StringType& str, Args&& ... rest) { - return str.size() + concat_length(rest...); + return str.size() + concat_length(std::forward(rest)...); } template @@ -4349,7 +4199,7 @@ template inline OutStringType concat(Args && ... args) { OutStringType str; - str.reserve(concat_length(args...)); + str.reserve(concat_length(std::forward(args)...)); concat_into(str, std::forward(args)...); return str; } @@ -4358,6 +4208,7 @@ inline OutStringType concat(Args && ... args) NLOHMANN_JSON_NAMESPACE_END + NLOHMANN_JSON_NAMESPACE_BEGIN namespace detail { @@ -4405,9 +4256,9 @@ class exception : public std::exception { case value_t::array: { - for (std::size_t i = 0; i < current->m_parent->m_data.m_value.array->size(); ++i) + for (std::size_t i = 0; i < current->m_parent->m_value.array->size(); ++i) { - if (¤t->m_parent->m_data.m_value.array->operator[](i) == current) + if (¤t->m_parent->m_value.array->operator[](i) == current) { tokens.emplace_back(std::to_string(i)); break; @@ -4418,7 +4269,7 @@ class exception : public std::exception case value_t::object: { - for (const auto& element : *current->m_parent->m_data.m_value.object) + for (const auto& element : *current->m_parent->m_value.object) { if (&element.second == current) { @@ -4481,17 +4332,17 @@ class parse_error : public exception template::value, int> = 0> static parse_error create(int id_, const position_t& pos, const std::string& what_arg, BasicJsonContext context) { - const std::string w = concat(exception::name("parse_error", id_), "parse error", - position_string(pos), ": ", exception::diagnostics(context), what_arg); + std::string w = concat(exception::name("parse_error", id_), "parse error", + position_string(pos), ": ", exception::diagnostics(context), what_arg); return {id_, pos.chars_read_total, w.c_str()}; } template::value, int> = 0> static parse_error create(int id_, std::size_t byte_, const std::string& what_arg, BasicJsonContext context) { - const std::string w = concat(exception::name("parse_error", id_), "parse error", - (byte_ != 0 ? (concat(" at byte ", std::to_string(byte_))) : ""), - ": ", exception::diagnostics(context), what_arg); + std::string w = concat(exception::name("parse_error", id_), "parse error", + (byte_ != 0 ? (concat(" at byte ", std::to_string(byte_))) : ""), + ": ", exception::diagnostics(context), what_arg); return {id_, byte_, w.c_str()}; } @@ -4525,7 +4376,7 @@ class invalid_iterator : public exception template::value, int> = 0> static invalid_iterator create(int id_, const std::string& what_arg, BasicJsonContext context) { - const std::string w = concat(exception::name("invalid_iterator", id_), exception::diagnostics(context), what_arg); + std::string w = concat(exception::name("invalid_iterator", id_), exception::diagnostics(context), what_arg); return {id_, w.c_str()}; } @@ -4543,7 +4394,7 @@ class type_error : public exception template::value, int> = 0> static type_error create(int id_, const std::string& what_arg, BasicJsonContext context) { - const std::string w = concat(exception::name("type_error", id_), exception::diagnostics(context), what_arg); + std::string w = concat(exception::name("type_error", id_), exception::diagnostics(context), what_arg); return {id_, w.c_str()}; } @@ -4560,7 +4411,7 @@ class out_of_range : public exception template::value, int> = 0> static out_of_range create(int id_, const std::string& what_arg, BasicJsonContext context) { - const std::string w = concat(exception::name("out_of_range", id_), exception::diagnostics(context), what_arg); + std::string w = concat(exception::name("out_of_range", id_), exception::diagnostics(context), what_arg); return {id_, w.c_str()}; } @@ -4577,7 +4428,7 @@ class other_error : public exception template::value, int> = 0> static other_error create(int id_, const std::string& what_arg, BasicJsonContext context) { - const std::string w = concat(exception::name("other_error", id_), exception::diagnostics(context), what_arg); + std::string w = concat(exception::name("other_error", id_), exception::diagnostics(context), what_arg); return {id_, w.c_str()}; } @@ -4596,10 +4447,10 @@ NLOHMANN_JSON_NAMESPACE_END // #include // __ _____ _____ _____ // __| | __| | | | JSON for Modern C++ -// | | |__ | | | | | | version 3.11.3 +// | | |__ | | | | | | version 3.11.1 // |_____|_____|_____|_|___| https://github.com/nlohmann/json // -// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann +// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann // SPDX-License-Identifier: MIT @@ -4620,10 +4471,10 @@ NLOHMANN_JSON_NAMESPACE_END // #include // __ _____ _____ _____ // __| | __| | | | JSON for Modern C++ -// | | |__ | | | | | | version 3.11.3 +// | | |__ | | | | | | version 3.11.1 // |_____|_____|_____|_|___| https://github.com/nlohmann/json // -// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann +// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann // SPDX-License-Identifier: MIT @@ -5126,10 +4977,10 @@ NLOHMANN_JSON_NAMESPACE_END // #include // __ _____ _____ _____ // __| | __| | | | JSON for Modern C++ -// | | |__ | | | | | | version 3.11.3 +// | | |__ | | | | | | version 3.11.1 // |_____|_____|_____|_|___| https://github.com/nlohmann/json // -// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann +// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann // SPDX-License-Identifier: MIT @@ -5146,10 +4997,10 @@ NLOHMANN_JSON_NAMESPACE_END // #include // __ _____ _____ _____ // __| | __| | | | JSON for Modern C++ -// | | |__ | | | | | | version 3.11.3 +// | | |__ | | | | | | version 3.11.1 // |_____|_____|_____|_|___| https://github.com/nlohmann/json // -// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann +// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann // SPDX-License-Identifier: MIT @@ -5218,10 +5069,10 @@ template class iteration_proxy_value // older GCCs are a bit fussy and require explicit noexcept specifiers on defaulted functions iteration_proxy_value(iteration_proxy_value&&) noexcept(std::is_nothrow_move_constructible::value - && std::is_nothrow_move_constructible::value) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor,cppcoreguidelines-noexcept-move-operations) + && std::is_nothrow_move_constructible::value) = default; iteration_proxy_value& operator=(iteration_proxy_value&&) noexcept(std::is_nothrow_move_assignable::value - && std::is_nothrow_move_assignable::value) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor,cppcoreguidelines-noexcept-move-operations) + && std::is_nothrow_move_assignable::value) = default; ~iteration_proxy_value() = default; /// dereference operator (needed for range-based for) @@ -5368,11 +5219,11 @@ namespace std #pragma clang diagnostic ignored "-Wmismatched-tags" #endif template -class tuple_size<::nlohmann::detail::iteration_proxy_value> // NOLINT(cert-dcl58-cpp) +class tuple_size<::nlohmann::detail::iteration_proxy_value> : public std::integral_constant {}; template -class tuple_element> // NOLINT(cert-dcl58-cpp) +class tuple_element> { public: using type = decltype( @@ -5411,7 +5262,7 @@ namespace detail /* * Note all external_constructor<>::construct functions need to call - * j.m_data.m_value.destroy(j.m_data.m_type) to avoid a memory leak in case j contains an + * j.m_value.destroy(j.m_type) to avoid a memory leak in case j contains an * allocated value (e.g., a string). See bug issue * https://github.com/nlohmann/json/issues/2865 for more information. */ @@ -5424,9 +5275,9 @@ struct external_constructor template static void construct(BasicJsonType& j, typename BasicJsonType::boolean_t b) noexcept { - j.m_data.m_value.destroy(j.m_data.m_type); - j.m_data.m_type = value_t::boolean; - j.m_data.m_value = b; + j.m_value.destroy(j.m_type); + j.m_type = value_t::boolean; + j.m_value = b; j.assert_invariant(); } }; @@ -5437,18 +5288,18 @@ struct external_constructor template static void construct(BasicJsonType& j, const typename BasicJsonType::string_t& s) { - j.m_data.m_value.destroy(j.m_data.m_type); - j.m_data.m_type = value_t::string; - j.m_data.m_value = s; + j.m_value.destroy(j.m_type); + j.m_type = value_t::string; + j.m_value = s; j.assert_invariant(); } template static void construct(BasicJsonType& j, typename BasicJsonType::string_t&& s) { - j.m_data.m_value.destroy(j.m_data.m_type); - j.m_data.m_type = value_t::string; - j.m_data.m_value = std::move(s); + j.m_value.destroy(j.m_type); + j.m_type = value_t::string; + j.m_value = std::move(s); j.assert_invariant(); } @@ -5457,9 +5308,9 @@ struct external_constructor int > = 0 > static void construct(BasicJsonType& j, const CompatibleStringType& str) { - j.m_data.m_value.destroy(j.m_data.m_type); - j.m_data.m_type = value_t::string; - j.m_data.m_value.string = j.template create(str); + j.m_value.destroy(j.m_type); + j.m_type = value_t::string; + j.m_value.string = j.template create(str); j.assert_invariant(); } }; @@ -5470,18 +5321,18 @@ struct external_constructor template static void construct(BasicJsonType& j, const typename BasicJsonType::binary_t& b) { - j.m_data.m_value.destroy(j.m_data.m_type); - j.m_data.m_type = value_t::binary; - j.m_data.m_value = typename BasicJsonType::binary_t(b); + j.m_value.destroy(j.m_type); + j.m_type = value_t::binary; + j.m_value = typename BasicJsonType::binary_t(b); j.assert_invariant(); } template static void construct(BasicJsonType& j, typename BasicJsonType::binary_t&& b) { - j.m_data.m_value.destroy(j.m_data.m_type); - j.m_data.m_type = value_t::binary; - j.m_data.m_value = typename BasicJsonType::binary_t(std::move(b)); + j.m_value.destroy(j.m_type); + j.m_type = value_t::binary; + j.m_value = typename BasicJsonType::binary_t(std::move(b)); j.assert_invariant(); } }; @@ -5492,9 +5343,9 @@ struct external_constructor template static void construct(BasicJsonType& j, typename BasicJsonType::number_float_t val) noexcept { - j.m_data.m_value.destroy(j.m_data.m_type); - j.m_data.m_type = value_t::number_float; - j.m_data.m_value = val; + j.m_value.destroy(j.m_type); + j.m_type = value_t::number_float; + j.m_value = val; j.assert_invariant(); } }; @@ -5505,9 +5356,9 @@ struct external_constructor template static void construct(BasicJsonType& j, typename BasicJsonType::number_unsigned_t val) noexcept { - j.m_data.m_value.destroy(j.m_data.m_type); - j.m_data.m_type = value_t::number_unsigned; - j.m_data.m_value = val; + j.m_value.destroy(j.m_type); + j.m_type = value_t::number_unsigned; + j.m_value = val; j.assert_invariant(); } }; @@ -5518,9 +5369,9 @@ struct external_constructor template static void construct(BasicJsonType& j, typename BasicJsonType::number_integer_t val) noexcept { - j.m_data.m_value.destroy(j.m_data.m_type); - j.m_data.m_type = value_t::number_integer; - j.m_data.m_value = val; + j.m_value.destroy(j.m_type); + j.m_type = value_t::number_integer; + j.m_value = val; j.assert_invariant(); } }; @@ -5531,9 +5382,9 @@ struct external_constructor template static void construct(BasicJsonType& j, const typename BasicJsonType::array_t& arr) { - j.m_data.m_value.destroy(j.m_data.m_type); - j.m_data.m_type = value_t::array; - j.m_data.m_value = arr; + j.m_value.destroy(j.m_type); + j.m_type = value_t::array; + j.m_value = arr; j.set_parents(); j.assert_invariant(); } @@ -5541,9 +5392,9 @@ struct external_constructor template static void construct(BasicJsonType& j, typename BasicJsonType::array_t&& arr) { - j.m_data.m_value.destroy(j.m_data.m_type); - j.m_data.m_type = value_t::array; - j.m_data.m_value = std::move(arr); + j.m_value.destroy(j.m_type); + j.m_type = value_t::array; + j.m_value = std::move(arr); j.set_parents(); j.assert_invariant(); } @@ -5556,9 +5407,9 @@ struct external_constructor using std::begin; using std::end; - j.m_data.m_value.destroy(j.m_data.m_type); - j.m_data.m_type = value_t::array; - j.m_data.m_value.array = j.template create(begin(arr), end(arr)); + j.m_value.destroy(j.m_type); + j.m_type = value_t::array; + j.m_value.array = j.template create(begin(arr), end(arr)); j.set_parents(); j.assert_invariant(); } @@ -5566,14 +5417,14 @@ struct external_constructor template static void construct(BasicJsonType& j, const std::vector& arr) { - j.m_data.m_value.destroy(j.m_data.m_type); - j.m_data.m_type = value_t::array; - j.m_data.m_value = value_t::array; - j.m_data.m_value.array->reserve(arr.size()); + j.m_value.destroy(j.m_type); + j.m_type = value_t::array; + j.m_value = value_t::array; + j.m_value.array->reserve(arr.size()); for (const bool x : arr) { - j.m_data.m_value.array->push_back(x); - j.set_parent(j.m_data.m_value.array->back()); + j.m_value.array->push_back(x); + j.set_parent(j.m_value.array->back()); } j.assert_invariant(); } @@ -5582,13 +5433,13 @@ struct external_constructor enable_if_t::value, int> = 0> static void construct(BasicJsonType& j, const std::valarray& arr) { - j.m_data.m_value.destroy(j.m_data.m_type); - j.m_data.m_type = value_t::array; - j.m_data.m_value = value_t::array; - j.m_data.m_value.array->resize(arr.size()); + j.m_value.destroy(j.m_type); + j.m_type = value_t::array; + j.m_value = value_t::array; + j.m_value.array->resize(arr.size()); if (arr.size() > 0) { - std::copy(std::begin(arr), std::end(arr), j.m_data.m_value.array->begin()); + std::copy(std::begin(arr), std::end(arr), j.m_value.array->begin()); } j.set_parents(); j.assert_invariant(); @@ -5601,9 +5452,9 @@ struct external_constructor template static void construct(BasicJsonType& j, const typename BasicJsonType::object_t& obj) { - j.m_data.m_value.destroy(j.m_data.m_type); - j.m_data.m_type = value_t::object; - j.m_data.m_value = obj; + j.m_value.destroy(j.m_type); + j.m_type = value_t::object; + j.m_value = obj; j.set_parents(); j.assert_invariant(); } @@ -5611,9 +5462,9 @@ struct external_constructor template static void construct(BasicJsonType& j, typename BasicJsonType::object_t&& obj) { - j.m_data.m_value.destroy(j.m_data.m_type); - j.m_data.m_type = value_t::object; - j.m_data.m_value = std::move(obj); + j.m_value.destroy(j.m_type); + j.m_type = value_t::object; + j.m_value = std::move(obj); j.set_parents(); j.assert_invariant(); } @@ -5625,9 +5476,9 @@ struct external_constructor using std::begin; using std::end; - j.m_data.m_value.destroy(j.m_data.m_type); - j.m_data.m_type = value_t::object; - j.m_data.m_value.object = j.template create(begin(obj), end(obj)); + j.m_value.destroy(j.m_type); + j.m_type = value_t::object; + j.m_value.object = j.template create(begin(obj), end(obj)); j.set_parents(); j.assert_invariant(); } @@ -5644,15 +5495,9 @@ inline void to_json(BasicJsonType& j, T b) noexcept external_constructor::construct(j, b); } -template < typename BasicJsonType, typename BoolRef, - enable_if_t < - ((std::is_same::reference, BoolRef>::value - && !std::is_same ::reference, typename BasicJsonType::boolean_t&>::value) - || (std::is_same::const_reference, BoolRef>::value - && !std::is_same ::const_reference>, - typename BasicJsonType::boolean_t >::value)) - && std::is_convertible::value, int > = 0 > -inline void to_json(BasicJsonType& j, const BoolRef& b) noexcept +template::reference&, typename BasicJsonType::boolean_t>::value, int> = 0> +inline void to_json(BasicJsonType& j, const std::vector::reference& b) noexcept { external_constructor::construct(j, static_cast(b)); } @@ -5867,10 +5712,10 @@ NLOHMANN_JSON_NAMESPACE_END // #include // __ _____ _____ _____ // __| | __| | | | JSON for Modern C++ -// | | |__ | | | | | | version 3.11.3 +// | | |__ | | | | | | version 3.11.1 // |_____|_____|_____|_|___| https://github.com/nlohmann/json // -// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann +// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann // SPDX-License-Identifier: MIT @@ -5979,10 +5824,10 @@ NLOHMANN_JSON_NAMESPACE_END // #include // __ _____ _____ _____ // __| | __| | | | JSON for Modern C++ -// | | |__ | | | | | | version 3.11.3 +// | | |__ | | | | | | version 3.11.1 // |_____|_____|_____|_|___| https://github.com/nlohmann/json // -// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann +// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann // SPDX-License-Identifier: MIT @@ -6112,10 +5957,10 @@ NLOHMANN_JSON_NAMESPACE_END // #include // __ _____ _____ _____ // __| | __| | | | JSON for Modern C++ -// | | |__ | | | | | | version 3.11.3 +// | | |__ | | | | | | version 3.11.1 // |_____|_____|_____|_|___| https://github.com/nlohmann/json // -// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann +// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann // SPDX-License-Identifier: MIT @@ -6132,16 +5977,17 @@ NLOHMANN_JSON_NAMESPACE_END #include // char_traits, string #include // make_pair, move #include // vector +#include // map // #include // #include // __ _____ _____ _____ // __| | __| | | | JSON for Modern C++ -// | | |__ | | | | | | version 3.11.3 +// | | |__ | | | | | | version 3.11.1 // |_____|_____|_____|_|___| https://github.com/nlohmann/json // -// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann +// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann // SPDX-License-Identifier: MIT @@ -6165,8 +6011,6 @@ NLOHMANN_JSON_NAMESPACE_END // #include -// #include - NLOHMANN_JSON_NAMESPACE_BEGIN namespace detail @@ -6213,6 +6057,7 @@ class file_input_adapter std::FILE* m_file; }; + /*! Input adapter for a (caching) istream. Ignores a UFT Byte Order Mark at beginning of input. Does not support changing the underlying std::streambuf @@ -6286,16 +6131,16 @@ class iterator_input_adapter : current(std::move(first)), end(std::move(last)) {} - typename char_traits::int_type get_character() + typename std::char_traits::int_type get_character() { if (JSON_HEDLEY_LIKELY(current != end)) { - auto result = char_traits::to_int_type(*current); + auto result = std::char_traits::to_int_type(*current); std::advance(current, 1); return result; } - return char_traits::eof(); + return std::char_traits::eof(); } private: @@ -6311,6 +6156,7 @@ class iterator_input_adapter } }; + template struct wide_string_input_helper; @@ -6434,7 +6280,7 @@ struct wide_string_input_helper } }; -// Wraps another input adapter to convert wide character types into individual bytes. +// Wraps another input apdater to convert wide character types into individual bytes. template class wide_string_input_adapter { @@ -6479,6 +6325,7 @@ class wide_string_input_adapter std::size_t utf8_bytes_filled = 0; }; + template struct iterator_input_adapter_factory { @@ -6635,10 +6482,10 @@ NLOHMANN_JSON_NAMESPACE_END // #include // __ _____ _____ _____ // __| | __| | | | JSON for Modern C++ -// | | |__ | | | | | | version 3.11.3 +// | | |__ | | | | | | version 3.11.1 // |_____|_____|_____|_|___| https://github.com/nlohmann/json // -// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann +// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann // SPDX-License-Identifier: MIT @@ -6780,6 +6627,7 @@ struct json_sax virtual ~json_sax() = default; }; + namespace detail { /*! @@ -6881,7 +6729,7 @@ class json_sax_dom_parser JSON_ASSERT(ref_stack.back()->is_object()); // add null at given key and store the reference for later - object_element = &(ref_stack.back()->m_data.m_value.object->operator[](val)); + object_element = &(ref_stack.back()->m_value.object->operator[](val)); return true; } @@ -6956,8 +6804,8 @@ class json_sax_dom_parser if (ref_stack.back()->is_array()) { - ref_stack.back()->m_data.m_value.array->emplace_back(std::forward(v)); - return &(ref_stack.back()->m_data.m_value.array->back()); + ref_stack.back()->m_value.array->emplace_back(std::forward(v)); + return &(ref_stack.back()->m_value.array->back()); } JSON_ASSERT(ref_stack.back()->is_object()); @@ -7076,7 +6924,7 @@ class json_sax_dom_callback_parser // add discarded value at given key and store the reference for later if (keep && ref_stack.back()) { - object_element = &(ref_stack.back()->m_data.m_value.object->operator[](val) = discarded); + object_element = &(ref_stack.back()->m_value.object->operator[](val) = discarded); } return true; @@ -7161,7 +7009,7 @@ class json_sax_dom_callback_parser // remove discarded value if (!keep && !ref_stack.empty() && ref_stack.back()->is_array()) { - ref_stack.back()->m_data.m_value.array->pop_back(); + ref_stack.back()->m_value.array->pop_back(); } return true; @@ -7228,7 +7076,7 @@ class json_sax_dom_callback_parser if (ref_stack.empty()) { root = std::move(value); - return {true, & root}; + return {true, &root}; } // skip this value if we already decided to skip the parent @@ -7244,8 +7092,8 @@ class json_sax_dom_callback_parser // array if (ref_stack.back()->is_array()) { - ref_stack.back()->m_data.m_value.array->emplace_back(std::move(value)); - return {true, & (ref_stack.back()->m_data.m_value.array->back())}; + ref_stack.back()->m_value.array->emplace_back(std::move(value)); + return {true, &(ref_stack.back()->m_value.array->back())}; } // object @@ -7367,10 +7215,10 @@ NLOHMANN_JSON_NAMESPACE_END // #include // __ _____ _____ _____ // __| | __| | | | JSON for Modern C++ -// | | |__ | | | | | | version 3.11.3 +// | | |__ | | | | | | version 3.11.1 // |_____|_____|_____|_|___| https://github.com/nlohmann/json // -// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann +// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann // SPDX-License-Identifier: MIT @@ -7391,8 +7239,6 @@ NLOHMANN_JSON_NAMESPACE_END // #include -// #include - NLOHMANN_JSON_NAMESPACE_BEGIN namespace detail @@ -7487,7 +7333,7 @@ class lexer : public lexer_base using number_float_t = typename BasicJsonType::number_float_t; using string_t = typename BasicJsonType::string_t; using char_type = typename InputAdapterType::char_type; - using char_int_type = typename char_traits::int_type; + using char_int_type = typename std::char_traits::int_type; public: using token_type = typename lexer_base::token_type; @@ -7594,7 +7440,7 @@ class lexer : public lexer_base for (auto range = ranges.begin(); range != ranges.end(); ++range) { get(); - if (JSON_HEDLEY_LIKELY(*range <= current && current <= *(++range))) // NOLINT(bugprone-inc-dec-in-conditions) + if (JSON_HEDLEY_LIKELY(*range <= current && current <= *(++range))) { add(current); } @@ -7637,7 +7483,7 @@ class lexer : public lexer_base switch (get()) { // end of file while parsing string - case char_traits::eof(): + case std::char_traits::eof(): { error_message = "invalid string: missing closing quote"; return token_type::parse_error; @@ -8226,7 +8072,7 @@ class lexer : public lexer_base { case '\n': case '\r': - case char_traits::eof(): + case std::char_traits::eof(): case '\0': return true; @@ -8243,7 +8089,7 @@ class lexer : public lexer_base { switch (get()) { - case char_traits::eof(): + case std::char_traits::eof(): case '\0': { error_message = "invalid comment; missing closing '*/'"; @@ -8672,10 +8518,10 @@ class lexer : public lexer_base token_type scan_literal(const char_type* literal_text, const std::size_t length, token_type return_type) { - JSON_ASSERT(char_traits::to_char_type(current) == literal_text[0]); + JSON_ASSERT(std::char_traits::to_char_type(current) == literal_text[0]); for (std::size_t i = 1; i < length; ++i) { - if (JSON_HEDLEY_UNLIKELY(char_traits::to_char_type(get()) != literal_text[i])) + if (JSON_HEDLEY_UNLIKELY(std::char_traits::to_char_type(get()) != literal_text[i])) { error_message = "invalid literal"; return token_type::parse_error; @@ -8693,7 +8539,7 @@ class lexer : public lexer_base { token_buffer.clear(); token_string.clear(); - token_string.push_back(char_traits::to_char_type(current)); + token_string.push_back(std::char_traits::to_char_type(current)); } /* @@ -8701,7 +8547,7 @@ class lexer : public lexer_base This function provides the interface to the used input adapter. It does not throw in case the input reached EOF, but returns a - `char_traits::eof()` in that case. Stores the scanned characters + `std::char_traits::eof()` in that case. Stores the scanned characters for use in error messages. @return character read from the input @@ -8721,9 +8567,9 @@ class lexer : public lexer_base current = ia.get_character(); } - if (JSON_HEDLEY_LIKELY(current != char_traits::eof())) + if (JSON_HEDLEY_LIKELY(current != std::char_traits::eof())) { - token_string.push_back(char_traits::to_char_type(current)); + token_string.push_back(std::char_traits::to_char_type(current)); } if (current == '\n') @@ -8762,7 +8608,7 @@ class lexer : public lexer_base --position.chars_read_current_line; } - if (JSON_HEDLEY_LIKELY(current != char_traits::eof())) + if (JSON_HEDLEY_LIKELY(current != std::char_traits::eof())) { JSON_ASSERT(!token_string.empty()); token_string.pop_back(); @@ -8956,7 +8802,7 @@ class lexer : public lexer_base // end of input (the null byte is needed when parsing from // string literals) case '\0': - case char_traits::eof(): + case std::char_traits::eof(): return token_type::end_of_input; // error @@ -8974,7 +8820,7 @@ class lexer : public lexer_base const bool ignore_comments = false; /// the current character - char_int_type current = char_traits::eof(); + char_int_type current = std::char_traits::eof(); /// whether the next get() call should just return current bool next_unget = false; @@ -9008,10 +8854,10 @@ NLOHMANN_JSON_NAMESPACE_END // #include // __ _____ _____ _____ // __| | __| | | | JSON for Modern C++ -// | | |__ | | | | | | version 3.11.3 +// | | |__ | | | | | | version 3.11.1 // |_____|_____|_____|_|___| https://github.com/nlohmann/json // -// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann +// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann // SPDX-License-Identifier: MIT @@ -9200,6 +9046,7 @@ static inline bool little_endianness(int num = 1) noexcept return *reinterpret_cast(&num) == 1; } + /////////////////// // binary reader // /////////////////// @@ -9217,7 +9064,7 @@ class binary_reader using binary_t = typename BasicJsonType::binary_t; using json_sax_t = SAX; using char_type = typename InputAdapterType::char_type; - using char_int_type = typename char_traits::int_type; + using char_int_type = typename std::char_traits::int_type; public: /*! @@ -9290,7 +9137,7 @@ class binary_reader get(); } - if (JSON_HEDLEY_UNLIKELY(current != char_traits::eof())) + if (JSON_HEDLEY_UNLIKELY(current != std::char_traits::eof())) { return sax->parse_error(chars_read, get_token_string(), parse_error::create(110, chars_read, exception_message(input_format, concat("expected end of input; last byte: 0x", get_token_string()), "value"), nullptr)); @@ -9373,7 +9220,7 @@ class binary_reader exception_message(input_format_t::bson, concat("string length must be at least 1, is ", std::to_string(len)), "string"), nullptr)); } - return get_string(input_format_t::bson, len - static_cast(1), result) && get() != char_traits::eof(); + return get_string(input_format_t::bson, len - static_cast(1), result) && get() != std::char_traits::eof(); } /*! @@ -9474,7 +9321,7 @@ class binary_reader { std::array cr{{}}; static_cast((std::snprintf)(cr.data(), cr.size(), "%.2hhX", static_cast(element_type))); // NOLINT(cppcoreguidelines-pro-type-vararg,hicpp-vararg) - const std::string cr_str{cr.data()}; + std::string cr_str{cr.data()}; return sax->parse_error(element_type_parse_position, cr_str, parse_error::create(114, element_type_parse_position, concat("Unsupported BSON record type 0x", cr_str), nullptr)); } @@ -9567,7 +9414,7 @@ class binary_reader switch (get_char ? get() : current) { // EOF - case char_traits::eof(): + case std::char_traits::eof(): return unexpect_eof(input_format_t::cbor, "value"); // Integer 0x00..0x17 (0..23) @@ -10342,7 +10189,7 @@ class binary_reader switch (get()) { // EOF - case char_traits::eof(): + case std::char_traits::eof(): return unexpect_eof(input_format_t::msgpack, "value"); // positive fixint @@ -11096,7 +10943,7 @@ class binary_reader return false; } - if (size_and_type.first != npos) + if (size_and_type.first != string_t::npos) { if (size_and_type.second != 0) { @@ -11297,7 +11144,7 @@ class binary_reader } if (is_ndarray) // ndarray dimensional vector can only contain integers, and can not embed another array { - return sax->parse_error(chars_read, get_token_string(), parse_error::create(113, chars_read, exception_message(input_format, "ndarray dimensional vector is not allowed", "size"), nullptr)); + return sax->parse_error(chars_read, get_token_string(), parse_error::create(113, chars_read, exception_message(input_format, "ndarray dimentional vector is not allowed", "size"), nullptr)); } std::vector dim; if (JSON_HEDLEY_UNLIKELY(!get_ubjson_ndarray_size(dim))) @@ -11329,7 +11176,7 @@ class binary_reader for (auto i : dim) { result *= i; - if (result == 0 || result == npos) // because dim elements shall not have zeros, result = 0 means overflow happened; it also can't be npos as it is used to initialize size in get_ubjson_size_type() + if (result == 0 || result == string_t::npos) // because dim elements shall not have zeros, result = 0 means overflow happened; it also can't be string_t::npos as it is used to initialize size in get_ubjson_size_type() { return sax->parse_error(chars_read, get_token_string(), out_of_range::create(408, exception_message(input_format, "excessive ndarray size caused overflow", "size"), nullptr)); } @@ -11375,7 +11222,7 @@ class binary_reader */ bool get_ubjson_size_type(std::pair& result, bool inside_ndarray = false) { - result.first = npos; // size + result.first = string_t::npos; // size result.second = 0; // type bool is_ndarray = false; @@ -11383,9 +11230,10 @@ class binary_reader if (current == '$') { + std::vector bjdx = {'[', '{', 'S', 'H', 'T', 'F', 'N', 'Z'}; // excluded markers in bjdata optimized type + result.second = get(); // must not ignore 'N', because 'N' maybe the type - if (input_format == input_format_t::bjdata - && JSON_HEDLEY_UNLIKELY(std::binary_search(bjd_optimized_type_markers.begin(), bjd_optimized_type_markers.end(), result.second))) + if (JSON_HEDLEY_UNLIKELY( input_format == input_format_t::bjdata && std::find(bjdx.begin(), bjdx.end(), result.second) != bjdx.end() )) { auto last_token = get_token_string(); return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read, @@ -11409,7 +11257,7 @@ class binary_reader exception_message(input_format, concat("expected '#' after type information; last byte: 0x", last_token), "size"), nullptr)); } - const bool is_error = get_ubjson_size_value(result.first, is_ndarray); + bool is_error = get_ubjson_size_value(result.first, is_ndarray); if (input_format == input_format_t::bjdata && is_ndarray) { if (inside_ndarray) @@ -11424,7 +11272,7 @@ class binary_reader if (current == '#') { - const bool is_error = get_ubjson_size_value(result.first, is_ndarray); + bool is_error = get_ubjson_size_value(result.first, is_ndarray); if (input_format == input_format_t::bjdata && is_ndarray) { return sax->parse_error(chars_read, get_token_string(), parse_error::create(112, chars_read, @@ -11444,7 +11292,7 @@ class binary_reader { switch (prefix) { - case char_traits::eof(): // EOF + case std::char_traits::eof(): // EOF return unexpect_eof(input_format, "value"); case 'T': // true @@ -11634,23 +11482,23 @@ class binary_reader // if bit-8 of size_and_type.second is set to 1, encode bjdata ndarray as an object in JData annotated array format (https://github.com/NeuroJSON/jdata): // {"_ArrayType_" : "typeid", "_ArraySize_" : [n1, n2, ...], "_ArrayData_" : [v1, v2, ...]} - if (input_format == input_format_t::bjdata && size_and_type.first != npos && (size_and_type.second & (1 << 8)) != 0) + if (input_format == input_format_t::bjdata && size_and_type.first != string_t::npos && (size_and_type.second & (1 << 8)) != 0) { + std::map bjdtype = {{'U', "uint8"}, {'i', "int8"}, {'u', "uint16"}, {'I', "int16"}, + {'m', "uint32"}, {'l', "int32"}, {'M', "uint64"}, {'L', "int64"}, {'d', "single"}, {'D', "double"}, {'C', "char"} + }; + size_and_type.second &= ~(static_cast(1) << 8); // use bit 8 to indicate ndarray, here we remove the bit to restore the type marker - auto it = std::lower_bound(bjd_types_map.begin(), bjd_types_map.end(), size_and_type.second, [](const bjd_type & p, char_int_type t) - { - return p.first < t; - }); + string_t key = "_ArrayType_"; - if (JSON_HEDLEY_UNLIKELY(it == bjd_types_map.end() || it->first != size_and_type.second)) + if (JSON_HEDLEY_UNLIKELY(bjdtype.count(size_and_type.second) == 0)) { auto last_token = get_token_string(); return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read, exception_message(input_format, "invalid byte: 0x" + last_token, "type"), nullptr)); } - string_t type = it->second; // sax->string() takes a reference - if (JSON_HEDLEY_UNLIKELY(!sax->key(key) || !sax->string(type))) + if (JSON_HEDLEY_UNLIKELY(!sax->key(key) || !sax->string(bjdtype[size_and_type.second]) )) { return false; } @@ -11677,7 +11525,7 @@ class binary_reader return (sax->end_array() && sax->end_object()); } - if (size_and_type.first != npos) + if (size_and_type.first != string_t::npos) { if (JSON_HEDLEY_UNLIKELY(!sax->start_array(size_and_type.first))) { @@ -11740,7 +11588,7 @@ class binary_reader } // do not accept ND-array size in objects in BJData - if (input_format == input_format_t::bjdata && size_and_type.first != npos && (size_and_type.second & (1 << 8)) != 0) + if (input_format == input_format_t::bjdata && size_and_type.first != string_t::npos && (size_and_type.second & (1 << 8)) != 0) { auto last_token = get_token_string(); return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read, @@ -11748,7 +11596,7 @@ class binary_reader } string_t key; - if (size_and_type.first != npos) + if (size_and_type.first != string_t::npos) { if (JSON_HEDLEY_UNLIKELY(!sax->start_object(size_and_type.first))) { @@ -11889,7 +11737,7 @@ class binary_reader This function provides the interface to the used input adapter. It does not throw in case the input reached EOF, but returns a -'ve valued - `char_traits::eof()` in that case. + `std::char_traits::eof()` in that case. @return character read from the input */ @@ -12031,7 +11879,7 @@ class binary_reader JSON_HEDLEY_NON_NULL(3) bool unexpect_eof(const input_format_t format, const char* context) const { - if (JSON_HEDLEY_UNLIKELY(current == char_traits::eof())) + if (JSON_HEDLEY_UNLIKELY(current == std::char_traits::eof())) { return sax->parse_error(chars_read, "", parse_error::create(110, chars_read, exception_message(format, "unexpected end of input", context), nullptr)); @@ -12092,13 +11940,11 @@ class binary_reader } private: - static JSON_INLINE_VARIABLE constexpr std::size_t npos = static_cast(-1); - /// input adapter InputAdapterType ia; /// the current character - char_int_type current = char_traits::eof(); + char_int_type current = std::char_traits::eof(); /// the number of characters read std::size_t chars_read = 0; @@ -12111,45 +11957,8 @@ class binary_reader /// the SAX parser json_sax_t* sax = nullptr; - - // excluded markers in bjdata optimized type -#define JSON_BINARY_READER_MAKE_BJD_OPTIMIZED_TYPE_MARKERS_ \ - make_array('F', 'H', 'N', 'S', 'T', 'Z', '[', '{') - -#define JSON_BINARY_READER_MAKE_BJD_TYPES_MAP_ \ - make_array( \ - bjd_type{'C', "char"}, \ - bjd_type{'D', "double"}, \ - bjd_type{'I', "int16"}, \ - bjd_type{'L', "int64"}, \ - bjd_type{'M', "uint64"}, \ - bjd_type{'U', "uint8"}, \ - bjd_type{'d', "single"}, \ - bjd_type{'i', "int8"}, \ - bjd_type{'l', "int32"}, \ - bjd_type{'m', "uint32"}, \ - bjd_type{'u', "uint16"}) - - JSON_PRIVATE_UNLESS_TESTED: - // lookup tables - // NOLINTNEXTLINE(cppcoreguidelines-non-private-member-variables-in-classes) - const decltype(JSON_BINARY_READER_MAKE_BJD_OPTIMIZED_TYPE_MARKERS_) bjd_optimized_type_markers = - JSON_BINARY_READER_MAKE_BJD_OPTIMIZED_TYPE_MARKERS_; - - using bjd_type = std::pair; - // NOLINTNEXTLINE(cppcoreguidelines-non-private-member-variables-in-classes) - const decltype(JSON_BINARY_READER_MAKE_BJD_TYPES_MAP_) bjd_types_map = - JSON_BINARY_READER_MAKE_BJD_TYPES_MAP_; - -#undef JSON_BINARY_READER_MAKE_BJD_OPTIMIZED_TYPE_MARKERS_ -#undef JSON_BINARY_READER_MAKE_BJD_TYPES_MAP_ }; -#ifndef JSON_HAS_CPP_17 - template - constexpr std::size_t binary_reader::npos; -#endif - } // namespace detail NLOHMANN_JSON_NAMESPACE_END @@ -12160,10 +11969,10 @@ NLOHMANN_JSON_NAMESPACE_END // #include // __ _____ _____ _____ // __| | __| | | | JSON for Modern C++ -// | | |__ | | | | | | version 3.11.3 +// | | |__ | | | | | | version 3.11.1 // |_____|_____|_____|_|___| https://github.com/nlohmann/json // -// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann +// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann // SPDX-License-Identifier: MIT @@ -12509,25 +12318,13 @@ class parser m_lexer.get_token_string(), parse_error::create(101, m_lexer.get_position(), exception_message(token_type::uninitialized, "value"), nullptr)); } - case token_type::end_of_input: - { - if (JSON_HEDLEY_UNLIKELY(m_lexer.get_position().chars_read_total == 1)) - { - return sax->parse_error(m_lexer.get_position(), - m_lexer.get_token_string(), - parse_error::create(101, m_lexer.get_position(), - "attempting to parse an empty input; check that your input string or stream contains the expected JSON", nullptr)); - } - return sax->parse_error(m_lexer.get_position(), - m_lexer.get_token_string(), - parse_error::create(101, m_lexer.get_position(), exception_message(token_type::literal_or_value, "value"), nullptr)); - } case token_type::uninitialized: case token_type::end_array: case token_type::end_object: case token_type::name_separator: case token_type::value_separator: + case token_type::end_of_input: case token_type::literal_or_value: default: // the last token was unexpected { @@ -12689,10 +12486,10 @@ NLOHMANN_JSON_NAMESPACE_END // #include // __ _____ _____ _____ // __| | __| | | | JSON for Modern C++ -// | | |__ | | | | | | version 3.11.3 +// | | |__ | | | | | | version 3.11.1 // |_____|_____|_____|_|___| https://github.com/nlohmann/json // -// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann +// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann // SPDX-License-Identifier: MIT @@ -12702,10 +12499,10 @@ NLOHMANN_JSON_NAMESPACE_END // #include // __ _____ _____ _____ // __| | __| | | | JSON for Modern C++ -// | | |__ | | | | | | version 3.11.3 +// | | |__ | | | | | | version 3.11.1 // |_____|_____|_____|_|___| https://github.com/nlohmann/json // -// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann +// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann // SPDX-License-Identifier: MIT @@ -12861,10 +12658,10 @@ NLOHMANN_JSON_NAMESPACE_END // #include // __ _____ _____ _____ // __| | __| | | | JSON for Modern C++ -// | | |__ | | | | | | version 3.11.3 +// | | |__ | | | | | | version 3.11.1 // |_____|_____|_____|_|___| https://github.com/nlohmann/json // -// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann +// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann // SPDX-License-Identifier: MIT @@ -12969,7 +12766,7 @@ class iter_impl // NOLINT(cppcoreguidelines-special-member-functions,hicpp-speci { JSON_ASSERT(m_object != nullptr); - switch (m_object->m_data.m_type) + switch (m_object->m_type) { case value_t::object: { @@ -13066,17 +12863,17 @@ class iter_impl // NOLINT(cppcoreguidelines-special-member-functions,hicpp-speci { JSON_ASSERT(m_object != nullptr); - switch (m_object->m_data.m_type) + switch (m_object->m_type) { case value_t::object: { - m_it.object_iterator = m_object->m_data.m_value.object->begin(); + m_it.object_iterator = m_object->m_value.object->begin(); break; } case value_t::array: { - m_it.array_iterator = m_object->m_data.m_value.array->begin(); + m_it.array_iterator = m_object->m_value.array->begin(); break; } @@ -13110,17 +12907,17 @@ class iter_impl // NOLINT(cppcoreguidelines-special-member-functions,hicpp-speci { JSON_ASSERT(m_object != nullptr); - switch (m_object->m_data.m_type) + switch (m_object->m_type) { case value_t::object: { - m_it.object_iterator = m_object->m_data.m_value.object->end(); + m_it.object_iterator = m_object->m_value.object->end(); break; } case value_t::array: { - m_it.array_iterator = m_object->m_data.m_value.array->end(); + m_it.array_iterator = m_object->m_value.array->end(); break; } @@ -13149,17 +12946,17 @@ class iter_impl // NOLINT(cppcoreguidelines-special-member-functions,hicpp-speci { JSON_ASSERT(m_object != nullptr); - switch (m_object->m_data.m_type) + switch (m_object->m_type) { case value_t::object: { - JSON_ASSERT(m_it.object_iterator != m_object->m_data.m_value.object->end()); + JSON_ASSERT(m_it.object_iterator != m_object->m_value.object->end()); return m_it.object_iterator->second; } case value_t::array: { - JSON_ASSERT(m_it.array_iterator != m_object->m_data.m_value.array->end()); + JSON_ASSERT(m_it.array_iterator != m_object->m_value.array->end()); return *m_it.array_iterator; } @@ -13193,17 +12990,17 @@ class iter_impl // NOLINT(cppcoreguidelines-special-member-functions,hicpp-speci { JSON_ASSERT(m_object != nullptr); - switch (m_object->m_data.m_type) + switch (m_object->m_type) { case value_t::object: { - JSON_ASSERT(m_it.object_iterator != m_object->m_data.m_value.object->end()); + JSON_ASSERT(m_it.object_iterator != m_object->m_value.object->end()); return &(m_it.object_iterator->second); } case value_t::array: { - JSON_ASSERT(m_it.array_iterator != m_object->m_data.m_value.array->end()); + JSON_ASSERT(m_it.array_iterator != m_object->m_value.array->end()); return &*m_it.array_iterator; } @@ -13246,7 +13043,7 @@ class iter_impl // NOLINT(cppcoreguidelines-special-member-functions,hicpp-speci { JSON_ASSERT(m_object != nullptr); - switch (m_object->m_data.m_type) + switch (m_object->m_type) { case value_t::object: { @@ -13297,7 +13094,7 @@ class iter_impl // NOLINT(cppcoreguidelines-special-member-functions,hicpp-speci { JSON_ASSERT(m_object != nullptr); - switch (m_object->m_data.m_type) + switch (m_object->m_type) { case value_t::object: { @@ -13344,7 +13141,7 @@ class iter_impl // NOLINT(cppcoreguidelines-special-member-functions,hicpp-speci JSON_ASSERT(m_object != nullptr); - switch (m_object->m_data.m_type) + switch (m_object->m_type) { case value_t::object: return (m_it.object_iterator == other.m_it.object_iterator); @@ -13389,7 +13186,7 @@ class iter_impl // NOLINT(cppcoreguidelines-special-member-functions,hicpp-speci JSON_ASSERT(m_object != nullptr); - switch (m_object->m_data.m_type) + switch (m_object->m_type) { case value_t::object: JSON_THROW(invalid_iterator::create(213, "cannot compare order of object iterators", m_object)); @@ -13445,7 +13242,7 @@ class iter_impl // NOLINT(cppcoreguidelines-special-member-functions,hicpp-speci { JSON_ASSERT(m_object != nullptr); - switch (m_object->m_data.m_type) + switch (m_object->m_type) { case value_t::object: JSON_THROW(invalid_iterator::create(209, "cannot use offsets with object iterators", m_object)); @@ -13524,7 +13321,7 @@ class iter_impl // NOLINT(cppcoreguidelines-special-member-functions,hicpp-speci { JSON_ASSERT(m_object != nullptr); - switch (m_object->m_data.m_type) + switch (m_object->m_type) { case value_t::object: JSON_THROW(invalid_iterator::create(209, "cannot use offsets with object iterators", m_object)); @@ -13553,7 +13350,7 @@ class iter_impl // NOLINT(cppcoreguidelines-special-member-functions,hicpp-speci { JSON_ASSERT(m_object != nullptr); - switch (m_object->m_data.m_type) + switch (m_object->m_type) { case value_t::object: JSON_THROW(invalid_iterator::create(208, "cannot use operator[] for object iterators", m_object)); @@ -13623,10 +13420,10 @@ NLOHMANN_JSON_NAMESPACE_END // #include // __ _____ _____ _____ // __| | __| | | | JSON for Modern C++ -// | | |__ | | | | | | version 3.11.3 +// | | |__ | | | | | | version 3.11.1 // |_____|_____|_____|_|___| https://github.com/nlohmann/json // -// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann +// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann // SPDX-License-Identifier: MIT @@ -13755,55 +13552,13 @@ NLOHMANN_JSON_NAMESPACE_END // #include -// #include -// __ _____ _____ _____ -// __| | __| | | | JSON for Modern C++ -// | | |__ | | | | | | version 3.11.3 -// |_____|_____|_____|_|___| https://github.com/nlohmann/json -// -// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann -// SPDX-License-Identifier: MIT - - - -#include // conditional, is_same - -// #include - - -NLOHMANN_JSON_NAMESPACE_BEGIN -namespace detail -{ - -/*! -@brief Default base class of the @ref basic_json class. - -So that the correct implementations of the copy / move ctors / assign operators -of @ref basic_json do not require complex case distinctions -(no base class / custom base class used as customization point), -@ref basic_json always has a base class. -By default, this class is used because it is empty and thus has no effect -on the behavior of @ref basic_json. -*/ -struct json_default_base {}; - -template -using json_base_class = typename std::conditional < - std::is_same::value, - json_default_base, - T - >::type; - -} // namespace detail -NLOHMANN_JSON_NAMESPACE_END - // #include // __ _____ _____ _____ // __| | __| | | | JSON for Modern C++ -// | | |__ | | | | | | version 3.11.3 +// | | |__ | | | | | | version 3.11.1 // |_____|_____|_____|_|___| https://github.com/nlohmann/json // -// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann +// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann // SPDX-License-Identifier: MIT @@ -14035,7 +13790,7 @@ class json_pointer const char* p = s.c_str(); char* p_end = nullptr; errno = 0; // strtoull doesn't reset errno - const unsigned long long res = std::strtoull(p, &p_end, 10); // NOLINT(runtime/int) + unsigned long long res = std::strtoull(p, &p_end, 10); // NOLINT(runtime/int) if (p == p_end // invalid input or empty string || errno == ERANGE // out of range || JSON_HEDLEY_UNLIKELY(static_cast(p_end - p) != s.size())) // incomplete read @@ -14191,7 +13946,7 @@ class json_pointer if (reference_token == "-") { // explicitly treat "-" as index beyond the end - ptr = &ptr->operator[](ptr->m_data.m_value.array->size()); + ptr = &ptr->operator[](ptr->m_value.array->size()); } else { @@ -14243,7 +13998,7 @@ class json_pointer { // "-" always fails the range check JSON_THROW(detail::out_of_range::create(402, detail::concat( - "array index '-' (", std::to_string(ptr->m_data.m_value.array->size()), + "array index '-' (", std::to_string(ptr->m_value.array->size()), ") is out of range"), ptr)); } @@ -14300,7 +14055,7 @@ class json_pointer if (JSON_HEDLEY_UNLIKELY(reference_token == "-")) { // "-" cannot be used for const access - JSON_THROW(detail::out_of_range::create(402, detail::concat("array index '-' (", std::to_string(ptr->m_data.m_value.array->size()), ") is out of range"), ptr)); + JSON_THROW(detail::out_of_range::create(402, detail::concat("array index '-' (", std::to_string(ptr->m_value.array->size()), ") is out of range"), ptr)); } // use unchecked array access @@ -14350,7 +14105,7 @@ class json_pointer { // "-" always fails the range check JSON_THROW(detail::out_of_range::create(402, detail::concat( - "array index '-' (", std::to_string(ptr->m_data.m_value.array->size()), + "array index '-' (", std::to_string(ptr->m_value.array->size()), ") is out of range"), ptr)); } @@ -14545,7 +14300,7 @@ class json_pointer { case detail::value_t::array: { - if (value.m_data.m_value.array->empty()) + if (value.m_value.array->empty()) { // flatten empty array as null result[reference_string] = nullptr; @@ -14553,10 +14308,10 @@ class json_pointer else { // iterate array and use index as reference string - for (std::size_t i = 0; i < value.m_data.m_value.array->size(); ++i) + for (std::size_t i = 0; i < value.m_value.array->size(); ++i) { flatten(detail::concat(reference_string, '/', std::to_string(i)), - value.m_data.m_value.array->operator[](i), result); + value.m_value.array->operator[](i), result); } } break; @@ -14564,7 +14319,7 @@ class json_pointer case detail::value_t::object: { - if (value.m_data.m_value.object->empty()) + if (value.m_value.object->empty()) { // flatten empty object as null result[reference_string] = nullptr; @@ -14572,7 +14327,7 @@ class json_pointer else { // iterate object and use keys as reference string - for (const auto& element : *value.m_data.m_value.object) + for (const auto& element : *value.m_value.object) { flatten(detail::concat(reference_string, '/', detail::escape(element.first)), element.second, result); } @@ -14619,7 +14374,7 @@ class json_pointer BasicJsonType result; // iterate the JSON object values - for (const auto& element : *value.m_data.m_value.object) + for (const auto& element : *value.m_value.object) { if (JSON_HEDLEY_UNLIKELY(!element.second.is_primitive())) { @@ -14651,154 +14406,66 @@ class json_pointer return result; } - public: -#if JSON_HAS_THREE_WAY_COMPARISON - /// @brief compares two JSON pointers for equality - /// @sa https://json.nlohmann.me/api/json_pointer/operator_eq/ - template - bool operator==(const json_pointer& rhs) const noexcept - { - return reference_tokens == rhs.reference_tokens; - } - - /// @brief compares JSON pointer and string for equality - /// @sa https://json.nlohmann.me/api/json_pointer/operator_eq/ - JSON_HEDLEY_DEPRECATED_FOR(3.11.2, operator==(json_pointer)) - bool operator==(const string_t& rhs) const - { - return *this == json_pointer(rhs); - } + /*! + @brief compares two JSON pointers for equality - /// @brief 3-way compares two JSON pointers - template - std::strong_ordering operator<=>(const json_pointer& rhs) const noexcept // *NOPAD* - { - return reference_tokens <=> rhs.reference_tokens; // *NOPAD* - } -#else - /// @brief compares two JSON pointers for equality - /// @sa https://json.nlohmann.me/api/json_pointer/operator_eq/ - template - // NOLINTNEXTLINE(readability-redundant-declaration) - friend bool operator==(const json_pointer& lhs, - const json_pointer& rhs) noexcept; + @param[in] lhs JSON pointer to compare + @param[in] rhs JSON pointer to compare + @return whether @a lhs is equal to @a rhs - /// @brief compares JSON pointer and string for equality - /// @sa https://json.nlohmann.me/api/json_pointer/operator_eq/ - template - // NOLINTNEXTLINE(readability-redundant-declaration) - friend bool operator==(const json_pointer& lhs, - const StringType& rhs); + @complexity Linear in the length of the JSON pointer - /// @brief compares string and JSON pointer for equality - /// @sa https://json.nlohmann.me/api/json_pointer/operator_eq/ - template - // NOLINTNEXTLINE(readability-redundant-declaration) - friend bool operator==(const StringType& lhs, - const json_pointer& rhs); - - /// @brief compares two JSON pointers for inequality - /// @sa https://json.nlohmann.me/api/json_pointer/operator_ne/ + @exceptionsafety No-throw guarantee: this function never throws exceptions. + */ template // NOLINTNEXTLINE(readability-redundant-declaration) - friend bool operator!=(const json_pointer& lhs, - const json_pointer& rhs) noexcept; + friend bool operator==(json_pointer const& lhs, + json_pointer const& rhs) noexcept; - /// @brief compares JSON pointer and string for inequality - /// @sa https://json.nlohmann.me/api/json_pointer/operator_ne/ - template - // NOLINTNEXTLINE(readability-redundant-declaration) - friend bool operator!=(const json_pointer& lhs, - const StringType& rhs); + /*! + @brief compares two JSON pointers for inequality - /// @brief compares string and JSON pointer for inequality - /// @sa https://json.nlohmann.me/api/json_pointer/operator_ne/ - template - // NOLINTNEXTLINE(readability-redundant-declaration) - friend bool operator!=(const StringType& lhs, - const json_pointer& rhs); + @param[in] lhs JSON pointer to compare + @param[in] rhs JSON pointer to compare + @return whether @a lhs is not equal @a rhs + + @complexity Linear in the length of the JSON pointer - /// @brief compares two JSON pointer for less-than + @exceptionsafety No-throw guarantee: this function never throws exceptions. + */ template // NOLINTNEXTLINE(readability-redundant-declaration) - friend bool operator<(const json_pointer& lhs, - const json_pointer& rhs) noexcept; -#endif + friend bool operator!=(json_pointer const& lhs, + json_pointer const& rhs) noexcept; - private: /// the reference tokens std::vector reference_tokens; }; -#if !JSON_HAS_THREE_WAY_COMPARISON // functions cannot be defined inside class due to ODR violations template -inline bool operator==(const json_pointer& lhs, - const json_pointer& rhs) noexcept +inline bool operator==(json_pointer const& lhs, + json_pointer const& rhs) noexcept { return lhs.reference_tokens == rhs.reference_tokens; } -template::string_t> -JSON_HEDLEY_DEPRECATED_FOR(3.11.2, operator==(json_pointer, json_pointer)) -inline bool operator==(const json_pointer& lhs, - const StringType& rhs) -{ - return lhs == json_pointer(rhs); -} - -template::string_t> -JSON_HEDLEY_DEPRECATED_FOR(3.11.2, operator==(json_pointer, json_pointer)) -inline bool operator==(const StringType& lhs, - const json_pointer& rhs) -{ - return json_pointer(lhs) == rhs; -} - template -inline bool operator!=(const json_pointer& lhs, - const json_pointer& rhs) noexcept -{ - return !(lhs == rhs); -} - -template::string_t> -JSON_HEDLEY_DEPRECATED_FOR(3.11.2, operator!=(json_pointer, json_pointer)) -inline bool operator!=(const json_pointer& lhs, - const StringType& rhs) +inline bool operator!=(json_pointer const& lhs, + json_pointer const& rhs) noexcept { return !(lhs == rhs); } -template::string_t> -JSON_HEDLEY_DEPRECATED_FOR(3.11.2, operator!=(json_pointer, json_pointer)) -inline bool operator!=(const StringType& lhs, - const json_pointer& rhs) -{ - return !(lhs == rhs); -} - -template -inline bool operator<(const json_pointer& lhs, - const json_pointer& rhs) noexcept -{ - return lhs.reference_tokens < rhs.reference_tokens; -} -#endif - NLOHMANN_JSON_NAMESPACE_END // #include // __ _____ _____ _____ // __| | __| | | | JSON for Modern C++ -// | | |__ | | | | | | version 3.11.3 +// | | |__ | | | | | | version 3.11.1 // |_____|_____|_____|_|___| https://github.com/nlohmann/json // -// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann +// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann // SPDX-License-Identifier: MIT @@ -14887,10 +14554,10 @@ NLOHMANN_JSON_NAMESPACE_END // #include // __ _____ _____ _____ // __| | __| | | | JSON for Modern C++ -// | | |__ | | | | | | version 3.11.3 +// | | |__ | | | | | | version 3.11.1 // |_____|_____|_____|_|___| https://github.com/nlohmann/json // -// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann +// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann // SPDX-License-Identifier: MIT @@ -14913,10 +14580,10 @@ NLOHMANN_JSON_NAMESPACE_END // #include // __ _____ _____ _____ // __| | __| | | | JSON for Modern C++ -// | | |__ | | | | | | version 3.11.3 +// | | |__ | | | | | | version 3.11.1 // |_____|_____|_____|_|___| https://github.com/nlohmann/json // -// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann +// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann // SPDX-License-Identifier: MIT @@ -15102,7 +14769,7 @@ class binary_writer { case value_t::object: { - write_bson_object(*j.m_data.m_value.object); + write_bson_object(*j.m_value.object); break; } @@ -15137,7 +14804,7 @@ class binary_writer case value_t::boolean: { - oa->write_character(j.m_data.m_value.boolean + oa->write_character(j.m_value.boolean ? to_char_type(0xF5) : to_char_type(0xF4)); break; @@ -15145,42 +14812,42 @@ class binary_writer case value_t::number_integer: { - if (j.m_data.m_value.number_integer >= 0) + if (j.m_value.number_integer >= 0) { // CBOR does not differentiate between positive signed // integers and unsigned integers. Therefore, we used the // code from the value_t::number_unsigned case here. - if (j.m_data.m_value.number_integer <= 0x17) + if (j.m_value.number_integer <= 0x17) { - write_number(static_cast(j.m_data.m_value.number_integer)); + write_number(static_cast(j.m_value.number_integer)); } - else if (j.m_data.m_value.number_integer <= (std::numeric_limits::max)()) + else if (j.m_value.number_integer <= (std::numeric_limits::max)()) { oa->write_character(to_char_type(0x18)); - write_number(static_cast(j.m_data.m_value.number_integer)); + write_number(static_cast(j.m_value.number_integer)); } - else if (j.m_data.m_value.number_integer <= (std::numeric_limits::max)()) + else if (j.m_value.number_integer <= (std::numeric_limits::max)()) { oa->write_character(to_char_type(0x19)); - write_number(static_cast(j.m_data.m_value.number_integer)); + write_number(static_cast(j.m_value.number_integer)); } - else if (j.m_data.m_value.number_integer <= (std::numeric_limits::max)()) + else if (j.m_value.number_integer <= (std::numeric_limits::max)()) { oa->write_character(to_char_type(0x1A)); - write_number(static_cast(j.m_data.m_value.number_integer)); + write_number(static_cast(j.m_value.number_integer)); } else { oa->write_character(to_char_type(0x1B)); - write_number(static_cast(j.m_data.m_value.number_integer)); + write_number(static_cast(j.m_value.number_integer)); } } else { // The conversions below encode the sign in the first // byte, and the value is converted to a positive number. - const auto positive_number = -1 - j.m_data.m_value.number_integer; - if (j.m_data.m_value.number_integer >= -24) + const auto positive_number = -1 - j.m_value.number_integer; + if (j.m_value.number_integer >= -24) { write_number(static_cast(0x20 + positive_number)); } @@ -15210,52 +14877,52 @@ class binary_writer case value_t::number_unsigned: { - if (j.m_data.m_value.number_unsigned <= 0x17) + if (j.m_value.number_unsigned <= 0x17) { - write_number(static_cast(j.m_data.m_value.number_unsigned)); + write_number(static_cast(j.m_value.number_unsigned)); } - else if (j.m_data.m_value.number_unsigned <= (std::numeric_limits::max)()) + else if (j.m_value.number_unsigned <= (std::numeric_limits::max)()) { oa->write_character(to_char_type(0x18)); - write_number(static_cast(j.m_data.m_value.number_unsigned)); + write_number(static_cast(j.m_value.number_unsigned)); } - else if (j.m_data.m_value.number_unsigned <= (std::numeric_limits::max)()) + else if (j.m_value.number_unsigned <= (std::numeric_limits::max)()) { oa->write_character(to_char_type(0x19)); - write_number(static_cast(j.m_data.m_value.number_unsigned)); + write_number(static_cast(j.m_value.number_unsigned)); } - else if (j.m_data.m_value.number_unsigned <= (std::numeric_limits::max)()) + else if (j.m_value.number_unsigned <= (std::numeric_limits::max)()) { oa->write_character(to_char_type(0x1A)); - write_number(static_cast(j.m_data.m_value.number_unsigned)); + write_number(static_cast(j.m_value.number_unsigned)); } else { oa->write_character(to_char_type(0x1B)); - write_number(static_cast(j.m_data.m_value.number_unsigned)); + write_number(static_cast(j.m_value.number_unsigned)); } break; } case value_t::number_float: { - if (std::isnan(j.m_data.m_value.number_float)) + if (std::isnan(j.m_value.number_float)) { // NaN is 0xf97e00 in CBOR oa->write_character(to_char_type(0xF9)); oa->write_character(to_char_type(0x7E)); oa->write_character(to_char_type(0x00)); } - else if (std::isinf(j.m_data.m_value.number_float)) + else if (std::isinf(j.m_value.number_float)) { // Infinity is 0xf97c00, -Infinity is 0xf9fc00 oa->write_character(to_char_type(0xf9)); - oa->write_character(j.m_data.m_value.number_float > 0 ? to_char_type(0x7C) : to_char_type(0xFC)); + oa->write_character(j.m_value.number_float > 0 ? to_char_type(0x7C) : to_char_type(0xFC)); oa->write_character(to_char_type(0x00)); } else { - write_compact_float(j.m_data.m_value.number_float, detail::input_format_t::cbor); + write_compact_float(j.m_value.number_float, detail::input_format_t::cbor); } break; } @@ -15263,7 +14930,7 @@ class binary_writer case value_t::string: { // step 1: write control byte and the string length - const auto N = j.m_data.m_value.string->size(); + const auto N = j.m_value.string->size(); if (N <= 0x17) { write_number(static_cast(0x60 + N)); @@ -15293,15 +14960,15 @@ class binary_writer // step 2: write the string oa->write_characters( - reinterpret_cast(j.m_data.m_value.string->c_str()), - j.m_data.m_value.string->size()); + reinterpret_cast(j.m_value.string->c_str()), + j.m_value.string->size()); break; } case value_t::array: { // step 1: write control byte and the array size - const auto N = j.m_data.m_value.array->size(); + const auto N = j.m_value.array->size(); if (N <= 0x17) { write_number(static_cast(0x80 + N)); @@ -15330,7 +14997,7 @@ class binary_writer // LCOV_EXCL_STOP // step 2: write each element - for (const auto& el : *j.m_data.m_value.array) + for (const auto& el : *j.m_value.array) { write_cbor(el); } @@ -15339,32 +15006,32 @@ class binary_writer case value_t::binary: { - if (j.m_data.m_value.binary->has_subtype()) + if (j.m_value.binary->has_subtype()) { - if (j.m_data.m_value.binary->subtype() <= (std::numeric_limits::max)()) + if (j.m_value.binary->subtype() <= (std::numeric_limits::max)()) { write_number(static_cast(0xd8)); - write_number(static_cast(j.m_data.m_value.binary->subtype())); + write_number(static_cast(j.m_value.binary->subtype())); } - else if (j.m_data.m_value.binary->subtype() <= (std::numeric_limits::max)()) + else if (j.m_value.binary->subtype() <= (std::numeric_limits::max)()) { write_number(static_cast(0xd9)); - write_number(static_cast(j.m_data.m_value.binary->subtype())); + write_number(static_cast(j.m_value.binary->subtype())); } - else if (j.m_data.m_value.binary->subtype() <= (std::numeric_limits::max)()) + else if (j.m_value.binary->subtype() <= (std::numeric_limits::max)()) { write_number(static_cast(0xda)); - write_number(static_cast(j.m_data.m_value.binary->subtype())); + write_number(static_cast(j.m_value.binary->subtype())); } - else if (j.m_data.m_value.binary->subtype() <= (std::numeric_limits::max)()) + else if (j.m_value.binary->subtype() <= (std::numeric_limits::max)()) { write_number(static_cast(0xdb)); - write_number(static_cast(j.m_data.m_value.binary->subtype())); + write_number(static_cast(j.m_value.binary->subtype())); } } // step 1: write control byte and the binary array size - const auto N = j.m_data.m_value.binary->size(); + const auto N = j.m_value.binary->size(); if (N <= 0x17) { write_number(static_cast(0x40 + N)); @@ -15394,7 +15061,7 @@ class binary_writer // step 2: write each element oa->write_characters( - reinterpret_cast(j.m_data.m_value.binary->data()), + reinterpret_cast(j.m_value.binary->data()), N); break; @@ -15403,7 +15070,7 @@ class binary_writer case value_t::object: { // step 1: write control byte and the object size - const auto N = j.m_data.m_value.object->size(); + const auto N = j.m_value.object->size(); if (N <= 0x17) { write_number(static_cast(0xA0 + N)); @@ -15432,7 +15099,7 @@ class binary_writer // LCOV_EXCL_STOP // step 2: write each element - for (const auto& el : *j.m_data.m_value.object) + for (const auto& el : *j.m_value.object) { write_cbor(el.first); write_cbor(el.second); @@ -15461,7 +15128,7 @@ class binary_writer case value_t::boolean: // true and false { - oa->write_character(j.m_data.m_value.boolean + oa->write_character(j.m_value.boolean ? to_char_type(0xC3) : to_char_type(0xC2)); break; @@ -15469,75 +15136,75 @@ class binary_writer case value_t::number_integer: { - if (j.m_data.m_value.number_integer >= 0) + if (j.m_value.number_integer >= 0) { // MessagePack does not differentiate between positive // signed integers and unsigned integers. Therefore, we used // the code from the value_t::number_unsigned case here. - if (j.m_data.m_value.number_unsigned < 128) + if (j.m_value.number_unsigned < 128) { // positive fixnum - write_number(static_cast(j.m_data.m_value.number_integer)); + write_number(static_cast(j.m_value.number_integer)); } - else if (j.m_data.m_value.number_unsigned <= (std::numeric_limits::max)()) + else if (j.m_value.number_unsigned <= (std::numeric_limits::max)()) { // uint 8 oa->write_character(to_char_type(0xCC)); - write_number(static_cast(j.m_data.m_value.number_integer)); + write_number(static_cast(j.m_value.number_integer)); } - else if (j.m_data.m_value.number_unsigned <= (std::numeric_limits::max)()) + else if (j.m_value.number_unsigned <= (std::numeric_limits::max)()) { // uint 16 oa->write_character(to_char_type(0xCD)); - write_number(static_cast(j.m_data.m_value.number_integer)); + write_number(static_cast(j.m_value.number_integer)); } - else if (j.m_data.m_value.number_unsigned <= (std::numeric_limits::max)()) + else if (j.m_value.number_unsigned <= (std::numeric_limits::max)()) { // uint 32 oa->write_character(to_char_type(0xCE)); - write_number(static_cast(j.m_data.m_value.number_integer)); + write_number(static_cast(j.m_value.number_integer)); } - else if (j.m_data.m_value.number_unsigned <= (std::numeric_limits::max)()) + else if (j.m_value.number_unsigned <= (std::numeric_limits::max)()) { // uint 64 oa->write_character(to_char_type(0xCF)); - write_number(static_cast(j.m_data.m_value.number_integer)); + write_number(static_cast(j.m_value.number_integer)); } } else { - if (j.m_data.m_value.number_integer >= -32) + if (j.m_value.number_integer >= -32) { // negative fixnum - write_number(static_cast(j.m_data.m_value.number_integer)); + write_number(static_cast(j.m_value.number_integer)); } - else if (j.m_data.m_value.number_integer >= (std::numeric_limits::min)() && - j.m_data.m_value.number_integer <= (std::numeric_limits::max)()) + else if (j.m_value.number_integer >= (std::numeric_limits::min)() && + j.m_value.number_integer <= (std::numeric_limits::max)()) { // int 8 oa->write_character(to_char_type(0xD0)); - write_number(static_cast(j.m_data.m_value.number_integer)); + write_number(static_cast(j.m_value.number_integer)); } - else if (j.m_data.m_value.number_integer >= (std::numeric_limits::min)() && - j.m_data.m_value.number_integer <= (std::numeric_limits::max)()) + else if (j.m_value.number_integer >= (std::numeric_limits::min)() && + j.m_value.number_integer <= (std::numeric_limits::max)()) { // int 16 oa->write_character(to_char_type(0xD1)); - write_number(static_cast(j.m_data.m_value.number_integer)); + write_number(static_cast(j.m_value.number_integer)); } - else if (j.m_data.m_value.number_integer >= (std::numeric_limits::min)() && - j.m_data.m_value.number_integer <= (std::numeric_limits::max)()) + else if (j.m_value.number_integer >= (std::numeric_limits::min)() && + j.m_value.number_integer <= (std::numeric_limits::max)()) { // int 32 oa->write_character(to_char_type(0xD2)); - write_number(static_cast(j.m_data.m_value.number_integer)); + write_number(static_cast(j.m_value.number_integer)); } - else if (j.m_data.m_value.number_integer >= (std::numeric_limits::min)() && - j.m_data.m_value.number_integer <= (std::numeric_limits::max)()) + else if (j.m_value.number_integer >= (std::numeric_limits::min)() && + j.m_value.number_integer <= (std::numeric_limits::max)()) { // int 64 oa->write_character(to_char_type(0xD3)); - write_number(static_cast(j.m_data.m_value.number_integer)); + write_number(static_cast(j.m_value.number_integer)); } } break; @@ -15545,48 +15212,48 @@ class binary_writer case value_t::number_unsigned: { - if (j.m_data.m_value.number_unsigned < 128) + if (j.m_value.number_unsigned < 128) { // positive fixnum - write_number(static_cast(j.m_data.m_value.number_integer)); + write_number(static_cast(j.m_value.number_integer)); } - else if (j.m_data.m_value.number_unsigned <= (std::numeric_limits::max)()) + else if (j.m_value.number_unsigned <= (std::numeric_limits::max)()) { // uint 8 oa->write_character(to_char_type(0xCC)); - write_number(static_cast(j.m_data.m_value.number_integer)); + write_number(static_cast(j.m_value.number_integer)); } - else if (j.m_data.m_value.number_unsigned <= (std::numeric_limits::max)()) + else if (j.m_value.number_unsigned <= (std::numeric_limits::max)()) { // uint 16 oa->write_character(to_char_type(0xCD)); - write_number(static_cast(j.m_data.m_value.number_integer)); + write_number(static_cast(j.m_value.number_integer)); } - else if (j.m_data.m_value.number_unsigned <= (std::numeric_limits::max)()) + else if (j.m_value.number_unsigned <= (std::numeric_limits::max)()) { // uint 32 oa->write_character(to_char_type(0xCE)); - write_number(static_cast(j.m_data.m_value.number_integer)); + write_number(static_cast(j.m_value.number_integer)); } - else if (j.m_data.m_value.number_unsigned <= (std::numeric_limits::max)()) + else if (j.m_value.number_unsigned <= (std::numeric_limits::max)()) { // uint 64 oa->write_character(to_char_type(0xCF)); - write_number(static_cast(j.m_data.m_value.number_integer)); + write_number(static_cast(j.m_value.number_integer)); } break; } case value_t::number_float: { - write_compact_float(j.m_data.m_value.number_float, detail::input_format_t::msgpack); + write_compact_float(j.m_value.number_float, detail::input_format_t::msgpack); break; } case value_t::string: { // step 1: write control byte and the string length - const auto N = j.m_data.m_value.string->size(); + const auto N = j.m_value.string->size(); if (N <= 31) { // fixstr @@ -15613,15 +15280,15 @@ class binary_writer // step 2: write the string oa->write_characters( - reinterpret_cast(j.m_data.m_value.string->c_str()), - j.m_data.m_value.string->size()); + reinterpret_cast(j.m_value.string->c_str()), + j.m_value.string->size()); break; } case value_t::array: { // step 1: write control byte and the array size - const auto N = j.m_data.m_value.array->size(); + const auto N = j.m_value.array->size(); if (N <= 15) { // fixarray @@ -15641,7 +15308,7 @@ class binary_writer } // step 2: write each element - for (const auto& el : *j.m_data.m_value.array) + for (const auto& el : *j.m_value.array) { write_msgpack(el); } @@ -15652,10 +15319,10 @@ class binary_writer { // step 0: determine if the binary type has a set subtype to // determine whether or not to use the ext or fixext types - const bool use_ext = j.m_data.m_value.binary->has_subtype(); + const bool use_ext = j.m_value.binary->has_subtype(); // step 1: write control byte and the byte string length - const auto N = j.m_data.m_value.binary->size(); + const auto N = j.m_value.binary->size(); if (N <= (std::numeric_limits::max)()) { std::uint8_t output_type{}; @@ -15700,18 +15367,18 @@ class binary_writer } else if (N <= (std::numeric_limits::max)()) { - const std::uint8_t output_type = use_ext - ? 0xC8 // ext 16 - : 0xC5; // bin 16 + std::uint8_t output_type = use_ext + ? 0xC8 // ext 16 + : 0xC5; // bin 16 oa->write_character(to_char_type(output_type)); write_number(static_cast(N)); } else if (N <= (std::numeric_limits::max)()) { - const std::uint8_t output_type = use_ext - ? 0xC9 // ext 32 - : 0xC6; // bin 32 + std::uint8_t output_type = use_ext + ? 0xC9 // ext 32 + : 0xC6; // bin 32 oa->write_character(to_char_type(output_type)); write_number(static_cast(N)); @@ -15720,12 +15387,12 @@ class binary_writer // step 1.5: if this is an ext type, write the subtype if (use_ext) { - write_number(static_cast(j.m_data.m_value.binary->subtype())); + write_number(static_cast(j.m_value.binary->subtype())); } // step 2: write the byte string oa->write_characters( - reinterpret_cast(j.m_data.m_value.binary->data()), + reinterpret_cast(j.m_value.binary->data()), N); break; @@ -15734,7 +15401,7 @@ class binary_writer case value_t::object: { // step 1: write control byte and the object size - const auto N = j.m_data.m_value.object->size(); + const auto N = j.m_value.object->size(); if (N <= 15) { // fixmap @@ -15754,7 +15421,7 @@ class binary_writer } // step 2: write each element - for (const auto& el : *j.m_data.m_value.object) + for (const auto& el : *j.m_value.object) { write_msgpack(el.first); write_msgpack(el.second); @@ -15794,7 +15461,7 @@ class binary_writer { if (add_prefix) { - oa->write_character(j.m_data.m_value.boolean + oa->write_character(j.m_value.boolean ? to_char_type('T') : to_char_type('F')); } @@ -15803,19 +15470,19 @@ class binary_writer case value_t::number_integer: { - write_number_with_ubjson_prefix(j.m_data.m_value.number_integer, add_prefix, use_bjdata); + write_number_with_ubjson_prefix(j.m_value.number_integer, add_prefix, use_bjdata); break; } case value_t::number_unsigned: { - write_number_with_ubjson_prefix(j.m_data.m_value.number_unsigned, add_prefix, use_bjdata); + write_number_with_ubjson_prefix(j.m_value.number_unsigned, add_prefix, use_bjdata); break; } case value_t::number_float: { - write_number_with_ubjson_prefix(j.m_data.m_value.number_float, add_prefix, use_bjdata); + write_number_with_ubjson_prefix(j.m_value.number_float, add_prefix, use_bjdata); break; } @@ -15825,10 +15492,10 @@ class binary_writer { oa->write_character(to_char_type('S')); } - write_number_with_ubjson_prefix(j.m_data.m_value.string->size(), true, use_bjdata); + write_number_with_ubjson_prefix(j.m_value.string->size(), true, use_bjdata); oa->write_characters( - reinterpret_cast(j.m_data.m_value.string->c_str()), - j.m_data.m_value.string->size()); + reinterpret_cast(j.m_value.string->c_str()), + j.m_value.string->size()); break; } @@ -15840,7 +15507,7 @@ class binary_writer } bool prefix_required = true; - if (use_type && !j.m_data.m_value.array->empty()) + if (use_type && !j.m_value.array->empty()) { JSON_ASSERT(use_count); const CharType first_prefix = ubjson_prefix(j.front(), use_bjdata); @@ -15863,10 +15530,10 @@ class binary_writer if (use_count) { oa->write_character(to_char_type('#')); - write_number_with_ubjson_prefix(j.m_data.m_value.array->size(), true, use_bjdata); + write_number_with_ubjson_prefix(j.m_value.array->size(), true, use_bjdata); } - for (const auto& el : *j.m_data.m_value.array) + for (const auto& el : *j.m_value.array) { write_ubjson(el, use_count, use_type, prefix_required, use_bjdata); } @@ -15886,7 +15553,7 @@ class binary_writer oa->write_character(to_char_type('[')); } - if (use_type && !j.m_data.m_value.binary->empty()) + if (use_type && !j.m_value.binary->empty()) { JSON_ASSERT(use_count); oa->write_character(to_char_type('$')); @@ -15896,21 +15563,21 @@ class binary_writer if (use_count) { oa->write_character(to_char_type('#')); - write_number_with_ubjson_prefix(j.m_data.m_value.binary->size(), true, use_bjdata); + write_number_with_ubjson_prefix(j.m_value.binary->size(), true, use_bjdata); } if (use_type) { oa->write_characters( - reinterpret_cast(j.m_data.m_value.binary->data()), - j.m_data.m_value.binary->size()); + reinterpret_cast(j.m_value.binary->data()), + j.m_value.binary->size()); } else { - for (size_t i = 0; i < j.m_data.m_value.binary->size(); ++i) + for (size_t i = 0; i < j.m_value.binary->size(); ++i) { oa->write_character(to_char_type('U')); - oa->write_character(j.m_data.m_value.binary->data()[i]); + oa->write_character(j.m_value.binary->data()[i]); } } @@ -15924,9 +15591,9 @@ class binary_writer case value_t::object: { - if (use_bjdata && j.m_data.m_value.object->size() == 3 && j.m_data.m_value.object->find("_ArrayType_") != j.m_data.m_value.object->end() && j.m_data.m_value.object->find("_ArraySize_") != j.m_data.m_value.object->end() && j.m_data.m_value.object->find("_ArrayData_") != j.m_data.m_value.object->end()) + if (use_bjdata && j.m_value.object->size() == 3 && j.m_value.object->find("_ArrayType_") != j.m_value.object->end() && j.m_value.object->find("_ArraySize_") != j.m_value.object->end() && j.m_value.object->find("_ArrayData_") != j.m_value.object->end()) { - if (!write_bjdata_ndarray(*j.m_data.m_value.object, use_count, use_type)) // decode bjdata ndarray in the JData format (https://github.com/NeuroJSON/jdata) + if (!write_bjdata_ndarray(*j.m_value.object, use_count, use_type)) // decode bjdata ndarray in the JData format (https://github.com/NeuroJSON/jdata) { break; } @@ -15938,7 +15605,7 @@ class binary_writer } bool prefix_required = true; - if (use_type && !j.m_data.m_value.object->empty()) + if (use_type && !j.m_value.object->empty()) { JSON_ASSERT(use_count); const CharType first_prefix = ubjson_prefix(j.front(), use_bjdata); @@ -15961,10 +15628,10 @@ class binary_writer if (use_count) { oa->write_character(to_char_type('#')); - write_number_with_ubjson_prefix(j.m_data.m_value.object->size(), true, use_bjdata); + write_number_with_ubjson_prefix(j.m_value.object->size(), true, use_bjdata); } - for (const auto& el : *j.m_data.m_value.object) + for (const auto& el : *j.m_value.object) { write_number_with_ubjson_prefix(el.first.size(), true, use_bjdata); oa->write_characters( @@ -16114,19 +15781,19 @@ class binary_writer void write_bson_unsigned(const string_t& name, const BasicJsonType& j) { - if (j.m_data.m_value.number_unsigned <= static_cast((std::numeric_limits::max)())) + if (j.m_value.number_unsigned <= static_cast((std::numeric_limits::max)())) { write_bson_entry_header(name, 0x10 /* int32 */); - write_number(static_cast(j.m_data.m_value.number_unsigned), true); + write_number(static_cast(j.m_value.number_unsigned), true); } - else if (j.m_data.m_value.number_unsigned <= static_cast((std::numeric_limits::max)())) + else if (j.m_value.number_unsigned <= static_cast((std::numeric_limits::max)())) { write_bson_entry_header(name, 0x12 /* int64 */); - write_number(static_cast(j.m_data.m_value.number_unsigned), true); + write_number(static_cast(j.m_value.number_unsigned), true); } else { - JSON_THROW(out_of_range::create(407, concat("integer number ", std::to_string(j.m_data.m_value.number_unsigned), " cannot be represented by BSON as it does not fit int64"), &j)); + JSON_THROW(out_of_range::create(407, concat("integer number ", std::to_string(j.m_value.number_unsigned), " cannot be represented by BSON as it does not fit int64"), &j)); } } @@ -16207,13 +15874,13 @@ class binary_writer switch (j.type()) { case value_t::object: - return header_size + calc_bson_object_size(*j.m_data.m_value.object); + return header_size + calc_bson_object_size(*j.m_value.object); case value_t::array: - return header_size + calc_bson_array_size(*j.m_data.m_value.array); + return header_size + calc_bson_array_size(*j.m_value.array); case value_t::binary: - return header_size + calc_bson_binary_size(*j.m_data.m_value.binary); + return header_size + calc_bson_binary_size(*j.m_value.binary); case value_t::boolean: return header_size + 1ul; @@ -16222,13 +15889,13 @@ class binary_writer return header_size + 8ul; case value_t::number_integer: - return header_size + calc_bson_integer_size(j.m_data.m_value.number_integer); + return header_size + calc_bson_integer_size(j.m_value.number_integer); case value_t::number_unsigned: - return header_size + calc_bson_unsigned_size(j.m_data.m_value.number_unsigned); + return header_size + calc_bson_unsigned_size(j.m_value.number_unsigned); case value_t::string: - return header_size + calc_bson_string_size(*j.m_data.m_value.string); + return header_size + calc_bson_string_size(*j.m_value.string); case value_t::null: return header_size + 0ul; @@ -16254,28 +15921,28 @@ class binary_writer switch (j.type()) { case value_t::object: - return write_bson_object_entry(name, *j.m_data.m_value.object); + return write_bson_object_entry(name, *j.m_value.object); case value_t::array: - return write_bson_array(name, *j.m_data.m_value.array); + return write_bson_array(name, *j.m_value.array); case value_t::binary: - return write_bson_binary(name, *j.m_data.m_value.binary); + return write_bson_binary(name, *j.m_value.binary); case value_t::boolean: - return write_bson_boolean(name, j.m_data.m_value.boolean); + return write_bson_boolean(name, j.m_value.boolean); case value_t::number_float: - return write_bson_double(name, j.m_data.m_value.number_float); + return write_bson_double(name, j.m_value.number_float); case value_t::number_integer: - return write_bson_integer(name, j.m_data.m_value.number_integer); + return write_bson_integer(name, j.m_value.number_integer); case value_t::number_unsigned: return write_bson_unsigned(name, j); case value_t::string: - return write_bson_string(name, *j.m_data.m_value.string); + return write_bson_string(name, *j.m_value.string); case value_t::null: return write_bson_null(name); @@ -16297,8 +15964,8 @@ class binary_writer */ static std::size_t calc_bson_object_size(const typename BasicJsonType::object_t& value) { - const std::size_t document_size = std::accumulate(value.begin(), value.end(), static_cast(0), - [](size_t result, const typename BasicJsonType::object_t::value_type & el) + std::size_t document_size = std::accumulate(value.begin(), value.end(), static_cast(0), + [](size_t result, const typename BasicJsonType::object_t::value_type & el) { return result += calc_bson_element_size(el.first, el.second); }); @@ -16548,35 +16215,35 @@ class binary_writer return 'Z'; case value_t::boolean: - return j.m_data.m_value.boolean ? 'T' : 'F'; + return j.m_value.boolean ? 'T' : 'F'; case value_t::number_integer: { - if ((std::numeric_limits::min)() <= j.m_data.m_value.number_integer && j.m_data.m_value.number_integer <= (std::numeric_limits::max)()) + if ((std::numeric_limits::min)() <= j.m_value.number_integer && j.m_value.number_integer <= (std::numeric_limits::max)()) { return 'i'; } - if ((std::numeric_limits::min)() <= j.m_data.m_value.number_integer && j.m_data.m_value.number_integer <= (std::numeric_limits::max)()) + if ((std::numeric_limits::min)() <= j.m_value.number_integer && j.m_value.number_integer <= (std::numeric_limits::max)()) { return 'U'; } - if ((std::numeric_limits::min)() <= j.m_data.m_value.number_integer && j.m_data.m_value.number_integer <= (std::numeric_limits::max)()) + if ((std::numeric_limits::min)() <= j.m_value.number_integer && j.m_value.number_integer <= (std::numeric_limits::max)()) { return 'I'; } - if (use_bjdata && ((std::numeric_limits::min)() <= j.m_data.m_value.number_integer && j.m_data.m_value.number_integer <= (std::numeric_limits::max)())) + if (use_bjdata && ((std::numeric_limits::min)() <= j.m_value.number_integer && j.m_value.number_integer <= (std::numeric_limits::max)())) { return 'u'; } - if ((std::numeric_limits::min)() <= j.m_data.m_value.number_integer && j.m_data.m_value.number_integer <= (std::numeric_limits::max)()) + if ((std::numeric_limits::min)() <= j.m_value.number_integer && j.m_value.number_integer <= (std::numeric_limits::max)()) { return 'l'; } - if (use_bjdata && ((std::numeric_limits::min)() <= j.m_data.m_value.number_integer && j.m_data.m_value.number_integer <= (std::numeric_limits::max)())) + if (use_bjdata && ((std::numeric_limits::min)() <= j.m_value.number_integer && j.m_value.number_integer <= (std::numeric_limits::max)())) { return 'm'; } - if ((std::numeric_limits::min)() <= j.m_data.m_value.number_integer && j.m_data.m_value.number_integer <= (std::numeric_limits::max)()) + if ((std::numeric_limits::min)() <= j.m_value.number_integer && j.m_value.number_integer <= (std::numeric_limits::max)()) { return 'L'; } @@ -16586,35 +16253,35 @@ class binary_writer case value_t::number_unsigned: { - if (j.m_data.m_value.number_unsigned <= static_cast((std::numeric_limits::max)())) + if (j.m_value.number_unsigned <= static_cast((std::numeric_limits::max)())) { return 'i'; } - if (j.m_data.m_value.number_unsigned <= static_cast((std::numeric_limits::max)())) + if (j.m_value.number_unsigned <= static_cast((std::numeric_limits::max)())) { return 'U'; } - if (j.m_data.m_value.number_unsigned <= static_cast((std::numeric_limits::max)())) + if (j.m_value.number_unsigned <= static_cast((std::numeric_limits::max)())) { return 'I'; } - if (use_bjdata && j.m_data.m_value.number_unsigned <= static_cast((std::numeric_limits::max)())) + if (use_bjdata && j.m_value.number_unsigned <= static_cast((std::numeric_limits::max)())) { return 'u'; } - if (j.m_data.m_value.number_unsigned <= static_cast((std::numeric_limits::max)())) + if (j.m_value.number_unsigned <= static_cast((std::numeric_limits::max)())) { return 'l'; } - if (use_bjdata && j.m_data.m_value.number_unsigned <= static_cast((std::numeric_limits::max)())) + if (use_bjdata && j.m_value.number_unsigned <= static_cast((std::numeric_limits::max)())) { return 'm'; } - if (j.m_data.m_value.number_unsigned <= static_cast((std::numeric_limits::max)())) + if (j.m_value.number_unsigned <= static_cast((std::numeric_limits::max)())) { return 'L'; } - if (use_bjdata && j.m_data.m_value.number_unsigned <= (std::numeric_limits::max)()) + if (use_bjdata && j.m_value.number_unsigned <= (std::numeric_limits::max)()) { return 'M'; } @@ -16623,7 +16290,7 @@ class binary_writer } case value_t::number_float: - return get_ubjson_float_prefix(j.m_data.m_value.number_float); + return get_ubjson_float_prefix(j.m_value.number_float); case value_t::string: return 'S'; @@ -16672,7 +16339,7 @@ class binary_writer std::size_t len = (value.at(key).empty() ? 0 : 1); for (const auto& el : value.at(key)) { - len *= static_cast(el.m_data.m_value.number_unsigned); + len *= static_cast(el.m_value.number_unsigned); } key = "_ArrayData_"; @@ -16694,70 +16361,70 @@ class binary_writer { for (const auto& el : value.at(key)) { - write_number(static_cast(el.m_data.m_value.number_unsigned), true); + write_number(static_cast(el.m_value.number_unsigned), true); } } else if (dtype == 'i') { for (const auto& el : value.at(key)) { - write_number(static_cast(el.m_data.m_value.number_integer), true); + write_number(static_cast(el.m_value.number_integer), true); } } else if (dtype == 'u') { for (const auto& el : value.at(key)) { - write_number(static_cast(el.m_data.m_value.number_unsigned), true); + write_number(static_cast(el.m_value.number_unsigned), true); } } else if (dtype == 'I') { for (const auto& el : value.at(key)) { - write_number(static_cast(el.m_data.m_value.number_integer), true); + write_number(static_cast(el.m_value.number_integer), true); } } else if (dtype == 'm') { for (const auto& el : value.at(key)) { - write_number(static_cast(el.m_data.m_value.number_unsigned), true); + write_number(static_cast(el.m_value.number_unsigned), true); } } else if (dtype == 'l') { for (const auto& el : value.at(key)) { - write_number(static_cast(el.m_data.m_value.number_integer), true); + write_number(static_cast(el.m_value.number_integer), true); } } else if (dtype == 'M') { for (const auto& el : value.at(key)) { - write_number(static_cast(el.m_data.m_value.number_unsigned), true); + write_number(static_cast(el.m_value.number_unsigned), true); } } else if (dtype == 'L') { for (const auto& el : value.at(key)) { - write_number(static_cast(el.m_data.m_value.number_integer), true); + write_number(static_cast(el.m_value.number_integer), true); } } else if (dtype == 'd') { for (const auto& el : value.at(key)) { - write_number(static_cast(el.m_data.m_value.number_float), true); + write_number(static_cast(el.m_value.number_float), true); } } else if (dtype == 'D') { for (const auto& el : value.at(key)) { - write_number(static_cast(el.m_data.m_value.number_float), true); + write_number(static_cast(el.m_value.number_float), true); } } return false; @@ -16881,11 +16548,11 @@ NLOHMANN_JSON_NAMESPACE_END // #include // __ _____ _____ _____ // __| | __| | | | JSON for Modern C++ -// | | |__ | | | | | | version 3.11.3 +// | | |__ | | | | | | version 3.11.1 // |_____|_____|_____|_|___| https://github.com/nlohmann/json // // SPDX-FileCopyrightText: 2008-2009 Björn Hoehrmann -// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann +// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann // SPDX-License-Identifier: MIT @@ -16906,11 +16573,11 @@ NLOHMANN_JSON_NAMESPACE_END // #include // __ _____ _____ _____ // __| | __| | | | JSON for Modern C++ -// | | |__ | | | | | | version 3.11.3 +// | | |__ | | | | | | version 3.11.1 // |_____|_____|_____|_|___| https://github.com/nlohmann/json // // SPDX-FileCopyrightText: 2009 Florian Loitsch -// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann +// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann // SPDX-License-Identifier: MIT @@ -17816,7 +17483,7 @@ void grisu2(char* buf, int& len, int& decimal_exponent, FloatType value) // NB: If the neighbors are computed for single-precision numbers, there is a single float // (7.0385307e-26f) which can't be recovered using strtod. The resulting double precision // value is off by 1 ulp. -#if 0 // NOLINT(readability-avoid-unconditional-preprocessor-if) +#if 0 const boundaries w = compute_boundaries(static_cast(value)); #else const boundaries w = compute_boundaries(value); @@ -18118,11 +17785,11 @@ class serializer const unsigned int indent_step, const unsigned int current_indent = 0) { - switch (val.m_data.m_type) + switch (val.m_type) { case value_t::object: { - if (val.m_data.m_value.object->empty()) + if (val.m_value.object->empty()) { o->write_characters("{}", 2); return; @@ -18140,8 +17807,8 @@ class serializer } // first n-1 elements - auto i = val.m_data.m_value.object->cbegin(); - for (std::size_t cnt = 0; cnt < val.m_data.m_value.object->size() - 1; ++cnt, ++i) + auto i = val.m_value.object->cbegin(); + for (std::size_t cnt = 0; cnt < val.m_value.object->size() - 1; ++cnt, ++i) { o->write_characters(indent_string.c_str(), new_indent); o->write_character('\"'); @@ -18152,8 +17819,8 @@ class serializer } // last element - JSON_ASSERT(i != val.m_data.m_value.object->cend()); - JSON_ASSERT(std::next(i) == val.m_data.m_value.object->cend()); + JSON_ASSERT(i != val.m_value.object->cend()); + JSON_ASSERT(std::next(i) == val.m_value.object->cend()); o->write_characters(indent_string.c_str(), new_indent); o->write_character('\"'); dump_escaped(i->first, ensure_ascii); @@ -18169,8 +17836,8 @@ class serializer o->write_character('{'); // first n-1 elements - auto i = val.m_data.m_value.object->cbegin(); - for (std::size_t cnt = 0; cnt < val.m_data.m_value.object->size() - 1; ++cnt, ++i) + auto i = val.m_value.object->cbegin(); + for (std::size_t cnt = 0; cnt < val.m_value.object->size() - 1; ++cnt, ++i) { o->write_character('\"'); dump_escaped(i->first, ensure_ascii); @@ -18180,8 +17847,8 @@ class serializer } // last element - JSON_ASSERT(i != val.m_data.m_value.object->cend()); - JSON_ASSERT(std::next(i) == val.m_data.m_value.object->cend()); + JSON_ASSERT(i != val.m_value.object->cend()); + JSON_ASSERT(std::next(i) == val.m_value.object->cend()); o->write_character('\"'); dump_escaped(i->first, ensure_ascii); o->write_characters("\":", 2); @@ -18195,7 +17862,7 @@ class serializer case value_t::array: { - if (val.m_data.m_value.array->empty()) + if (val.m_value.array->empty()) { o->write_characters("[]", 2); return; @@ -18213,8 +17880,8 @@ class serializer } // first n-1 elements - for (auto i = val.m_data.m_value.array->cbegin(); - i != val.m_data.m_value.array->cend() - 1; ++i) + for (auto i = val.m_value.array->cbegin(); + i != val.m_value.array->cend() - 1; ++i) { o->write_characters(indent_string.c_str(), new_indent); dump(*i, true, ensure_ascii, indent_step, new_indent); @@ -18222,9 +17889,9 @@ class serializer } // last element - JSON_ASSERT(!val.m_data.m_value.array->empty()); + JSON_ASSERT(!val.m_value.array->empty()); o->write_characters(indent_string.c_str(), new_indent); - dump(val.m_data.m_value.array->back(), true, ensure_ascii, indent_step, new_indent); + dump(val.m_value.array->back(), true, ensure_ascii, indent_step, new_indent); o->write_character('\n'); o->write_characters(indent_string.c_str(), current_indent); @@ -18235,16 +17902,16 @@ class serializer o->write_character('['); // first n-1 elements - for (auto i = val.m_data.m_value.array->cbegin(); - i != val.m_data.m_value.array->cend() - 1; ++i) + for (auto i = val.m_value.array->cbegin(); + i != val.m_value.array->cend() - 1; ++i) { dump(*i, false, ensure_ascii, indent_step, current_indent); o->write_character(','); } // last element - JSON_ASSERT(!val.m_data.m_value.array->empty()); - dump(val.m_data.m_value.array->back(), false, ensure_ascii, indent_step, current_indent); + JSON_ASSERT(!val.m_value.array->empty()); + dump(val.m_value.array->back(), false, ensure_ascii, indent_step, current_indent); o->write_character(']'); } @@ -18255,7 +17922,7 @@ class serializer case value_t::string: { o->write_character('\"'); - dump_escaped(*val.m_data.m_value.string, ensure_ascii); + dump_escaped(*val.m_value.string, ensure_ascii); o->write_character('\"'); return; } @@ -18277,24 +17944,24 @@ class serializer o->write_characters("\"bytes\": [", 10); - if (!val.m_data.m_value.binary->empty()) + if (!val.m_value.binary->empty()) { - for (auto i = val.m_data.m_value.binary->cbegin(); - i != val.m_data.m_value.binary->cend() - 1; ++i) + for (auto i = val.m_value.binary->cbegin(); + i != val.m_value.binary->cend() - 1; ++i) { dump_integer(*i); o->write_characters(", ", 2); } - dump_integer(val.m_data.m_value.binary->back()); + dump_integer(val.m_value.binary->back()); } o->write_characters("],\n", 3); o->write_characters(indent_string.c_str(), new_indent); o->write_characters("\"subtype\": ", 11); - if (val.m_data.m_value.binary->has_subtype()) + if (val.m_value.binary->has_subtype()) { - dump_integer(val.m_data.m_value.binary->subtype()); + dump_integer(val.m_value.binary->subtype()); } else { @@ -18308,21 +17975,21 @@ class serializer { o->write_characters("{\"bytes\":[", 10); - if (!val.m_data.m_value.binary->empty()) + if (!val.m_value.binary->empty()) { - for (auto i = val.m_data.m_value.binary->cbegin(); - i != val.m_data.m_value.binary->cend() - 1; ++i) + for (auto i = val.m_value.binary->cbegin(); + i != val.m_value.binary->cend() - 1; ++i) { dump_integer(*i); o->write_character(','); } - dump_integer(val.m_data.m_value.binary->back()); + dump_integer(val.m_value.binary->back()); } o->write_characters("],\"subtype\":", 12); - if (val.m_data.m_value.binary->has_subtype()) + if (val.m_value.binary->has_subtype()) { - dump_integer(val.m_data.m_value.binary->subtype()); + dump_integer(val.m_value.binary->subtype()); o->write_character('}'); } else @@ -18335,7 +18002,7 @@ class serializer case value_t::boolean: { - if (val.m_data.m_value.boolean) + if (val.m_value.boolean) { o->write_characters("true", 4); } @@ -18348,19 +18015,19 @@ class serializer case value_t::number_integer: { - dump_integer(val.m_data.m_value.number_integer); + dump_integer(val.m_value.number_integer); return; } case value_t::number_unsigned: { - dump_integer(val.m_data.m_value.number_unsigned); + dump_integer(val.m_value.number_unsigned); return; } case value_t::number_float: { - dump_float(val.m_data.m_value.number_float); + dump_float(val.m_value.number_float); return; } @@ -18934,8 +18601,8 @@ class serializer ? (byte & 0x3fu) | (codep << 6u) : (0xFFu >> type) & (byte); - const std::size_t index = 256u + static_cast(state) * 16u + static_cast(type); - JSON_ASSERT(index < utf8d.size()); + std::size_t index = 256u + static_cast(state) * 16u + static_cast(type); + JSON_ASSERT(index < 400); state = utf8d[index]; return state; } @@ -19002,10 +18669,10 @@ NLOHMANN_JSON_NAMESPACE_END // #include // __ _____ _____ _____ // __| | __| | | | JSON for Modern C++ -// | | |__ | | | | | | version 3.11.3 +// | | |__ | | | | | | version 3.11.1 // |_____|_____|_____|_|___| https://github.com/nlohmann/json // -// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann +// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann // SPDX-License-Identifier: MIT @@ -19122,7 +18789,7 @@ template , template::value, int> = 0> - T & at(KeyType && key) // NOLINT(cppcoreguidelines-missing-std-forward) + T & at(KeyType && key) { for (auto it = this->begin(); it != this->end(); ++it) { @@ -19150,7 +18817,7 @@ template , template::value, int> = 0> - const T & at(KeyType && key) const // NOLINT(cppcoreguidelines-missing-std-forward) + const T & at(KeyType && key) const { for (auto it = this->begin(); it != this->end(); ++it) { @@ -19184,7 +18851,7 @@ template , template::value, int> = 0> - size_type erase(KeyType && key) // NOLINT(cppcoreguidelines-missing-std-forward) + size_type erase(KeyType && key) { for (auto it = this->begin(); it != this->end(); ++it) { @@ -19275,7 +18942,7 @@ template , template::value, int> = 0> - size_type count(KeyType && key) const // NOLINT(cppcoreguidelines-missing-std-forward) + size_type count(KeyType && key) const { for (auto it = this->begin(); it != this->end(); ++it) { @@ -19301,7 +18968,7 @@ template , template::value, int> = 0> - iterator find(KeyType && key) // NOLINT(cppcoreguidelines-missing-std-forward) + iterator find(KeyType && key) { for (auto it = this->begin(); it != this->end(); ++it) { @@ -19364,9 +19031,7 @@ NLOHMANN_JSON_NAMESPACE_END #if defined(JSON_HAS_CPP_17) - #if JSON_HAS_STATIC_RTTI - #include - #endif + #include #include #endif @@ -19397,7 +19062,6 @@ The invariants are checked by member function assert_invariant(). */ NLOHMANN_BASIC_JSON_TPL_DECLARATION class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-special-member-functions) - : public ::nlohmann::detail::json_base_class { private: template friend struct detail::external_constructor; @@ -19424,7 +19088,6 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec /// workaround type for MSVC using basic_json_t = NLOHMANN_BASIC_JSON_TPL; - using json_base_class_t = ::nlohmann::detail::json_base_class; JSON_PRIVATE_UNLESS_TESTED: // convenience aliases for types residing in namespace detail; @@ -19496,6 +19159,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec /// @} + ///////////////////// // container types // ///////////////////// @@ -19537,6 +19201,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec /// @} + /// @brief returns the allocator associated with the container /// @sa https://json.nlohmann.me/api/basic_json/get_allocator/ static allocator_type get_allocator() @@ -19551,7 +19216,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec { basic_json result; - result["copyright"] = "(C) 2013-2023 Niels Lohmann"; + result["copyright"] = "(C) 2013-2022 Niels Lohmann"; result["name"] = "JSON for Modern C++"; result["url"] = "https://github.com/nlohmann/json"; result["version"]["string"] = @@ -19599,6 +19264,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec result["compiler"] = {{"family", "unknown"}, {"version", "unknown"}}; #endif + #if defined(_MSVC_LANG) result["compiler"]["c++"] = std::to_string(_MSVC_LANG); #elif defined(__cplusplus) @@ -19609,6 +19275,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec return result; } + /////////////////////////// // JSON value data types // /////////////////////////// @@ -19816,7 +19483,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec object = nullptr; // silence warning, see #821 if (JSON_HEDLEY_UNLIKELY(t == value_t::null)) { - JSON_THROW(other_error::create(500, "961c151d2e87f2686a955a9be24d316f1362bf21 3.11.3", nullptr)); // LCOV_EXCL_LINE + JSON_THROW(other_error::create(500, "961c151d2e87f2686a955a9be24d316f1362bf21 3.11.1", nullptr)); // LCOV_EXCL_LINE } break; } @@ -19855,16 +19522,6 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec void destroy(value_t t) { - if ( - (t == value_t::object && object == nullptr) || - (t == value_t::array && array == nullptr) || - (t == value_t::string && string == nullptr) || - (t == value_t::binary && binary == nullptr) - ) - { - //not initialized (e.g. due to exception in the ctor) - return; - } if (t == value_t::array || t == value_t::object) { // flatten the current json_value to a heap-allocated stack @@ -19895,18 +19552,18 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec // its children to the stack to be processed later if (current_item.is_array()) { - std::move(current_item.m_data.m_value.array->begin(), current_item.m_data.m_value.array->end(), std::back_inserter(stack)); + std::move(current_item.m_value.array->begin(), current_item.m_value.array->end(), std::back_inserter(stack)); - current_item.m_data.m_value.array->clear(); + current_item.m_value.array->clear(); } else if (current_item.is_object()) { - for (auto&& it : *current_item.m_data.m_value.object) + for (auto&& it : *current_item.m_value.object) { stack.push_back(std::move(it.second)); } - current_item.m_data.m_value.object->clear(); + current_item.m_value.object->clear(); } // it's now safe that current_item get destructed @@ -19983,10 +19640,10 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec */ void assert_invariant(bool check_parents = true) const noexcept { - JSON_ASSERT(m_data.m_type != value_t::object || m_data.m_value.object != nullptr); - JSON_ASSERT(m_data.m_type != value_t::array || m_data.m_value.array != nullptr); - JSON_ASSERT(m_data.m_type != value_t::string || m_data.m_value.string != nullptr); - JSON_ASSERT(m_data.m_type != value_t::binary || m_data.m_value.binary != nullptr); + JSON_ASSERT(m_type != value_t::object || m_value.object != nullptr); + JSON_ASSERT(m_type != value_t::array || m_value.array != nullptr); + JSON_ASSERT(m_type != value_t::string || m_value.string != nullptr); + JSON_ASSERT(m_type != value_t::binary || m_value.binary != nullptr); #if JSON_DIAGNOSTICS JSON_TRY @@ -20005,11 +19662,11 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec void set_parents() { #if JSON_DIAGNOSTICS - switch (m_data.m_type) + switch (m_type) { case value_t::array: { - for (auto& element : *m_data.m_value.array) + for (auto& element : *m_value.array) { element.m_parent = this; } @@ -20018,7 +19675,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec case value_t::object: { - for (auto& element : *m_data.m_value.object) + for (auto& element : *m_value.object) { element.second.m_parent = this; } @@ -20059,7 +19716,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec { // see https://github.com/nlohmann/json/issues/2838 JSON_ASSERT(type() == value_t::array); - if (JSON_HEDLEY_UNLIKELY(m_data.m_value.array->capacity() != old_capacity)) + if (JSON_HEDLEY_UNLIKELY(m_value.array->capacity() != old_capacity)) { // capacity has changed: update all parents set_parents(); @@ -20115,7 +19772,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec /// @brief create an empty value with a given type /// @sa https://json.nlohmann.me/api/basic_json/basic_json/ basic_json(const value_t v) - : m_data(v) + : m_type(v), m_value(v) { assert_invariant(); } @@ -20189,12 +19846,12 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec *this = nullptr; break; case value_t::discarded: - m_data.m_type = value_t::discarded; + m_type = value_t::discarded; break; default: // LCOV_EXCL_LINE JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE } - JSON_ASSERT(m_data.m_type == val.type()); + JSON_ASSERT(m_type == val.type()); set_parents(); assert_invariant(); } @@ -20210,10 +19867,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec bool is_an_object = std::all_of(init.begin(), init.end(), [](const detail::json_ref& element_ref) { - // The cast is to ensure op[size_type] is called, bearing in mind size_type may not be int; - // (many string types can be constructed from 0 via its null-pointer guise, so we get a - // broken call to op[key_type], the wrong semantics and a 4804 warning on Windows) - return element_ref->is_array() && element_ref->size() == 2 && (*element_ref)[static_cast(0)].is_string(); + return element_ref->is_array() && element_ref->size() == 2 && (*element_ref)[0].is_string(); }); // adjust type if type deduction is not wanted @@ -20235,22 +19889,22 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec if (is_an_object) { // the initializer list is a list of pairs -> create object - m_data.m_type = value_t::object; - m_data.m_value = value_t::object; + m_type = value_t::object; + m_value = value_t::object; for (auto& element_ref : init) { auto element = element_ref.moved_or_copied(); - m_data.m_value.object->emplace( - std::move(*((*element.m_data.m_value.array)[0].m_data.m_value.string)), - std::move((*element.m_data.m_value.array)[1])); + m_value.object->emplace( + std::move(*((*element.m_value.array)[0].m_value.string)), + std::move((*element.m_value.array)[1])); } } else { // the initializer list describes an array -> create array - m_data.m_type = value_t::array; - m_data.m_value.array = create(init.begin(), init.end()); + m_type = value_t::array; + m_value.array = create(init.begin(), init.end()); } set_parents(); @@ -20263,8 +19917,8 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec static basic_json binary(const typename binary_t::container_type& init) { auto res = basic_json(); - res.m_data.m_type = value_t::binary; - res.m_data.m_value = init; + res.m_type = value_t::binary; + res.m_value = init; return res; } @@ -20274,8 +19928,8 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec static basic_json binary(const typename binary_t::container_type& init, typename binary_t::subtype_type subtype) { auto res = basic_json(); - res.m_data.m_type = value_t::binary; - res.m_data.m_value = binary_t(init, subtype); + res.m_type = value_t::binary; + res.m_value = binary_t(init, subtype); return res; } @@ -20285,8 +19939,8 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec static basic_json binary(typename binary_t::container_type&& init) { auto res = basic_json(); - res.m_data.m_type = value_t::binary; - res.m_data.m_value = std::move(init); + res.m_type = value_t::binary; + res.m_value = std::move(init); return res; } @@ -20296,8 +19950,8 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec static basic_json binary(typename binary_t::container_type&& init, typename binary_t::subtype_type subtype) { auto res = basic_json(); - res.m_data.m_type = value_t::binary; - res.m_data.m_value = binary_t(std::move(init), subtype); + res.m_type = value_t::binary; + res.m_value = binary_t(std::move(init), subtype); return res; } @@ -20319,9 +19973,10 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec /// @brief construct an array with count copies of given value /// @sa https://json.nlohmann.me/api/basic_json/basic_json/ - basic_json(size_type cnt, const basic_json& val): - m_data{cnt, val} + basic_json(size_type cnt, const basic_json& val) + : m_type(value_t::array) { + m_value.array = create(cnt, val); set_parents(); assert_invariant(); } @@ -20343,10 +19998,10 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec } // copy type from first iterator - m_data.m_type = first.m_object->m_data.m_type; + m_type = first.m_object->m_type; // check if iterator range is complete for primitive values - switch (m_data.m_type) + switch (m_type) { case value_t::boolean: case value_t::number_float: @@ -20371,55 +20026,55 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec break; } - switch (m_data.m_type) + switch (m_type) { case value_t::number_integer: { - m_data.m_value.number_integer = first.m_object->m_data.m_value.number_integer; + m_value.number_integer = first.m_object->m_value.number_integer; break; } case value_t::number_unsigned: { - m_data.m_value.number_unsigned = first.m_object->m_data.m_value.number_unsigned; + m_value.number_unsigned = first.m_object->m_value.number_unsigned; break; } case value_t::number_float: { - m_data.m_value.number_float = first.m_object->m_data.m_value.number_float; + m_value.number_float = first.m_object->m_value.number_float; break; } case value_t::boolean: { - m_data.m_value.boolean = first.m_object->m_data.m_value.boolean; + m_value.boolean = first.m_object->m_value.boolean; break; } case value_t::string: { - m_data.m_value = *first.m_object->m_data.m_value.string; + m_value = *first.m_object->m_value.string; break; } case value_t::object: { - m_data.m_value.object = create(first.m_it.object_iterator, - last.m_it.object_iterator); + m_value.object = create(first.m_it.object_iterator, + last.m_it.object_iterator); break; } case value_t::array: { - m_data.m_value.array = create(first.m_it.array_iterator, - last.m_it.array_iterator); + m_value.array = create(first.m_it.array_iterator, + last.m_it.array_iterator); break; } case value_t::binary: { - m_data.m_value = *first.m_object->m_data.m_value.binary; + m_value = *first.m_object->m_value.binary; break; } @@ -20433,6 +20088,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec assert_invariant(); } + /////////////////////////////////////// // other constructors and destructor // /////////////////////////////////////// @@ -20445,59 +20101,58 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec /// @brief copy constructor /// @sa https://json.nlohmann.me/api/basic_json/basic_json/ basic_json(const basic_json& other) - : json_base_class_t(other) + : m_type(other.m_type) { - m_data.m_type = other.m_data.m_type; // check of passed value is valid other.assert_invariant(); - switch (m_data.m_type) + switch (m_type) { case value_t::object: { - m_data.m_value = *other.m_data.m_value.object; + m_value = *other.m_value.object; break; } case value_t::array: { - m_data.m_value = *other.m_data.m_value.array; + m_value = *other.m_value.array; break; } case value_t::string: { - m_data.m_value = *other.m_data.m_value.string; + m_value = *other.m_value.string; break; } case value_t::boolean: { - m_data.m_value = other.m_data.m_value.boolean; + m_value = other.m_value.boolean; break; } case value_t::number_integer: { - m_data.m_value = other.m_data.m_value.number_integer; + m_value = other.m_value.number_integer; break; } case value_t::number_unsigned: { - m_data.m_value = other.m_data.m_value.number_unsigned; + m_value = other.m_value.number_unsigned; break; } case value_t::number_float: { - m_data.m_value = other.m_data.m_value.number_float; + m_value = other.m_value.number_float; break; } case value_t::binary: { - m_data.m_value = *other.m_data.m_value.binary; + m_value = *other.m_value.binary; break; } @@ -20514,15 +20169,15 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec /// @brief move constructor /// @sa https://json.nlohmann.me/api/basic_json/basic_json/ basic_json(basic_json&& other) noexcept - : json_base_class_t(std::forward(other)), - m_data(std::move(other.m_data)) + : m_type(std::move(other.m_type)), + m_value(std::move(other.m_value)) { // check that passed value is valid other.assert_invariant(false); // invalidate payload - other.m_data.m_type = value_t::null; - other.m_data.m_value = {}; + other.m_type = value_t::null; + other.m_value = {}; set_parents(); assert_invariant(); @@ -20534,17 +20189,15 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec std::is_nothrow_move_constructible::value&& std::is_nothrow_move_assignable::value&& std::is_nothrow_move_constructible::value&& - std::is_nothrow_move_assignable::value&& - std::is_nothrow_move_assignable::value + std::is_nothrow_move_assignable::value ) { // check that passed value is valid other.assert_invariant(); using std::swap; - swap(m_data.m_type, other.m_data.m_type); - swap(m_data.m_value, other.m_data.m_value); - json_base_class_t::operator=(std::move(other)); + swap(m_type, other.m_type); + swap(m_value, other.m_value); set_parents(); assert_invariant(); @@ -20556,6 +20209,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec ~basic_json() noexcept { assert_invariant(false); + m_value.destroy(m_type); } /// @} @@ -20595,7 +20249,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec /// @sa https://json.nlohmann.me/api/basic_json/type/ constexpr value_t type() const noexcept { - return m_data.m_type; + return m_type; } /// @brief return whether type is primitive @@ -20616,14 +20270,14 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec /// @sa https://json.nlohmann.me/api/basic_json/is_null/ constexpr bool is_null() const noexcept { - return m_data.m_type == value_t::null; + return m_type == value_t::null; } /// @brief return whether value is a boolean /// @sa https://json.nlohmann.me/api/basic_json/is_boolean/ constexpr bool is_boolean() const noexcept { - return m_data.m_type == value_t::boolean; + return m_type == value_t::boolean; } /// @brief return whether value is a number @@ -20637,63 +20291,63 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec /// @sa https://json.nlohmann.me/api/basic_json/is_number_integer/ constexpr bool is_number_integer() const noexcept { - return m_data.m_type == value_t::number_integer || m_data.m_type == value_t::number_unsigned; + return m_type == value_t::number_integer || m_type == value_t::number_unsigned; } /// @brief return whether value is an unsigned integer number /// @sa https://json.nlohmann.me/api/basic_json/is_number_unsigned/ constexpr bool is_number_unsigned() const noexcept { - return m_data.m_type == value_t::number_unsigned; + return m_type == value_t::number_unsigned; } /// @brief return whether value is a floating-point number /// @sa https://json.nlohmann.me/api/basic_json/is_number_float/ constexpr bool is_number_float() const noexcept { - return m_data.m_type == value_t::number_float; + return m_type == value_t::number_float; } /// @brief return whether value is an object /// @sa https://json.nlohmann.me/api/basic_json/is_object/ constexpr bool is_object() const noexcept { - return m_data.m_type == value_t::object; + return m_type == value_t::object; } /// @brief return whether value is an array /// @sa https://json.nlohmann.me/api/basic_json/is_array/ constexpr bool is_array() const noexcept { - return m_data.m_type == value_t::array; + return m_type == value_t::array; } /// @brief return whether value is a string /// @sa https://json.nlohmann.me/api/basic_json/is_string/ constexpr bool is_string() const noexcept { - return m_data.m_type == value_t::string; + return m_type == value_t::string; } /// @brief return whether value is a binary array /// @sa https://json.nlohmann.me/api/basic_json/is_binary/ constexpr bool is_binary() const noexcept { - return m_data.m_type == value_t::binary; + return m_type == value_t::binary; } /// @brief return whether value is discarded /// @sa https://json.nlohmann.me/api/basic_json/is_discarded/ constexpr bool is_discarded() const noexcept { - return m_data.m_type == value_t::discarded; + return m_type == value_t::discarded; } /// @brief return the type of the JSON value (implicit) /// @sa https://json.nlohmann.me/api/basic_json/operator_value_t/ constexpr operator value_t() const noexcept { - return m_data.m_type; + return m_type; } /// @} @@ -20708,7 +20362,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec { if (JSON_HEDLEY_LIKELY(is_boolean())) { - return m_data.m_value.boolean; + return m_value.boolean; } JSON_THROW(type_error::create(302, detail::concat("type must be boolean, but is ", type_name()), this)); @@ -20717,97 +20371,97 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec /// get a pointer to the value (object) object_t* get_impl_ptr(object_t* /*unused*/) noexcept { - return is_object() ? m_data.m_value.object : nullptr; + return is_object() ? m_value.object : nullptr; } /// get a pointer to the value (object) constexpr const object_t* get_impl_ptr(const object_t* /*unused*/) const noexcept { - return is_object() ? m_data.m_value.object : nullptr; + return is_object() ? m_value.object : nullptr; } /// get a pointer to the value (array) array_t* get_impl_ptr(array_t* /*unused*/) noexcept { - return is_array() ? m_data.m_value.array : nullptr; + return is_array() ? m_value.array : nullptr; } /// get a pointer to the value (array) constexpr const array_t* get_impl_ptr(const array_t* /*unused*/) const noexcept { - return is_array() ? m_data.m_value.array : nullptr; + return is_array() ? m_value.array : nullptr; } /// get a pointer to the value (string) string_t* get_impl_ptr(string_t* /*unused*/) noexcept { - return is_string() ? m_data.m_value.string : nullptr; + return is_string() ? m_value.string : nullptr; } /// get a pointer to the value (string) constexpr const string_t* get_impl_ptr(const string_t* /*unused*/) const noexcept { - return is_string() ? m_data.m_value.string : nullptr; + return is_string() ? m_value.string : nullptr; } /// get a pointer to the value (boolean) boolean_t* get_impl_ptr(boolean_t* /*unused*/) noexcept { - return is_boolean() ? &m_data.m_value.boolean : nullptr; + return is_boolean() ? &m_value.boolean : nullptr; } /// get a pointer to the value (boolean) constexpr const boolean_t* get_impl_ptr(const boolean_t* /*unused*/) const noexcept { - return is_boolean() ? &m_data.m_value.boolean : nullptr; + return is_boolean() ? &m_value.boolean : nullptr; } /// get a pointer to the value (integer number) number_integer_t* get_impl_ptr(number_integer_t* /*unused*/) noexcept { - return is_number_integer() ? &m_data.m_value.number_integer : nullptr; + return is_number_integer() ? &m_value.number_integer : nullptr; } /// get a pointer to the value (integer number) constexpr const number_integer_t* get_impl_ptr(const number_integer_t* /*unused*/) const noexcept { - return is_number_integer() ? &m_data.m_value.number_integer : nullptr; + return is_number_integer() ? &m_value.number_integer : nullptr; } /// get a pointer to the value (unsigned number) number_unsigned_t* get_impl_ptr(number_unsigned_t* /*unused*/) noexcept { - return is_number_unsigned() ? &m_data.m_value.number_unsigned : nullptr; + return is_number_unsigned() ? &m_value.number_unsigned : nullptr; } /// get a pointer to the value (unsigned number) constexpr const number_unsigned_t* get_impl_ptr(const number_unsigned_t* /*unused*/) const noexcept { - return is_number_unsigned() ? &m_data.m_value.number_unsigned : nullptr; + return is_number_unsigned() ? &m_value.number_unsigned : nullptr; } /// get a pointer to the value (floating-point number) number_float_t* get_impl_ptr(number_float_t* /*unused*/) noexcept { - return is_number_float() ? &m_data.m_value.number_float : nullptr; + return is_number_float() ? &m_value.number_float : nullptr; } /// get a pointer to the value (floating-point number) constexpr const number_float_t* get_impl_ptr(const number_float_t* /*unused*/) const noexcept { - return is_number_float() ? &m_data.m_value.number_float : nullptr; + return is_number_float() ? &m_value.number_float : nullptr; } /// get a pointer to the value (binary) binary_t* get_impl_ptr(binary_t* /*unused*/) noexcept { - return is_binary() ? m_data.m_value.binary : nullptr; + return is_binary() ? m_value.binary : nullptr; } /// get a pointer to the value (binary) constexpr const binary_t* get_impl_ptr(const binary_t* /*unused*/) const noexcept { - return is_binary() ? m_data.m_value.binary : nullptr; + return is_binary() ? m_value.binary : nullptr; } /*! @@ -21190,7 +20844,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec #if defined(JSON_HAS_CPP_17) && (defined(__GNUC__) || (defined(_MSC_VER) && _MSC_VER >= 1910 && _MSC_VER <= 1914)) detail::negation>, #endif -#if defined(JSON_HAS_CPP_17) && JSON_HAS_STATIC_RTTI +#if defined(JSON_HAS_CPP_17) detail::negation>, #endif detail::is_detected_lazy @@ -21227,6 +20881,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec /// @} + //////////////////// // element access // //////////////////// @@ -21244,7 +20899,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec { JSON_TRY { - return set_parent(m_data.m_value.array->at(idx)); + return set_parent(m_value.array->at(idx)); } JSON_CATCH (std::out_of_range&) { @@ -21267,7 +20922,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec { JSON_TRY { - return m_data.m_value.array->at(idx); + return m_value.array->at(idx); } JSON_CATCH (std::out_of_range&) { @@ -21291,8 +20946,8 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec JSON_THROW(type_error::create(304, detail::concat("cannot use at() with ", type_name()), this)); } - auto it = m_data.m_value.object->find(key); - if (it == m_data.m_value.object->end()) + auto it = m_value.object->find(key); + if (it == m_value.object->end()) { JSON_THROW(out_of_range::create(403, detail::concat("key '", key, "' not found"), this)); } @@ -21311,8 +20966,8 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec JSON_THROW(type_error::create(304, detail::concat("cannot use at() with ", type_name()), this)); } - auto it = m_data.m_value.object->find(std::forward(key)); - if (it == m_data.m_value.object->end()) + auto it = m_value.object->find(std::forward(key)); + if (it == m_value.object->end()) { JSON_THROW(out_of_range::create(403, detail::concat("key '", string_t(std::forward(key)), "' not found"), this)); } @@ -21329,8 +20984,8 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec JSON_THROW(type_error::create(304, detail::concat("cannot use at() with ", type_name()), this)); } - auto it = m_data.m_value.object->find(key); - if (it == m_data.m_value.object->end()) + auto it = m_value.object->find(key); + if (it == m_value.object->end()) { JSON_THROW(out_of_range::create(403, detail::concat("key '", key, "' not found"), this)); } @@ -21349,8 +21004,8 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec JSON_THROW(type_error::create(304, detail::concat("cannot use at() with ", type_name()), this)); } - auto it = m_data.m_value.object->find(std::forward(key)); - if (it == m_data.m_value.object->end()) + auto it = m_value.object->find(std::forward(key)); + if (it == m_value.object->end()) { JSON_THROW(out_of_range::create(403, detail::concat("key '", string_t(std::forward(key)), "' not found"), this)); } @@ -21364,8 +21019,8 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec // implicitly convert null value to an empty array if (is_null()) { - m_data.m_type = value_t::array; - m_data.m_value.array = create(); + m_type = value_t::array; + m_value.array = create(); assert_invariant(); } @@ -21373,17 +21028,17 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec if (JSON_HEDLEY_LIKELY(is_array())) { // fill up array with null values if given idx is outside range - if (idx >= m_data.m_value.array->size()) + if (idx >= m_value.array->size()) { #if JSON_DIAGNOSTICS // remember array size & capacity before resizing - const auto old_size = m_data.m_value.array->size(); - const auto old_capacity = m_data.m_value.array->capacity(); + const auto old_size = m_value.array->size(); + const auto old_capacity = m_value.array->capacity(); #endif - m_data.m_value.array->resize(idx + 1); + m_value.array->resize(idx + 1); #if JSON_DIAGNOSTICS - if (JSON_HEDLEY_UNLIKELY(m_data.m_value.array->capacity() != old_capacity)) + if (JSON_HEDLEY_UNLIKELY(m_value.array->capacity() != old_capacity)) { // capacity has changed: update all parents set_parents(); @@ -21397,7 +21052,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec assert_invariant(); } - return m_data.m_value.array->operator[](idx); + return m_value.array->operator[](idx); } JSON_THROW(type_error::create(305, detail::concat("cannot use operator[] with a numeric argument with ", type_name()), this)); @@ -21410,7 +21065,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec // const operator[] only works for arrays if (JSON_HEDLEY_LIKELY(is_array())) { - return m_data.m_value.array->operator[](idx); + return m_value.array->operator[](idx); } JSON_THROW(type_error::create(305, detail::concat("cannot use operator[] with a numeric argument with ", type_name()), this)); @@ -21423,15 +21078,15 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec // implicitly convert null value to an empty object if (is_null()) { - m_data.m_type = value_t::object; - m_data.m_value.object = create(); + m_type = value_t::object; + m_value.object = create(); assert_invariant(); } // operator[] only works for objects if (JSON_HEDLEY_LIKELY(is_object())) { - auto result = m_data.m_value.object->emplace(std::move(key), nullptr); + auto result = m_value.object->emplace(std::move(key), nullptr); return set_parent(result.first->second); } @@ -21445,8 +21100,8 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec // const operator[] only works for objects if (JSON_HEDLEY_LIKELY(is_object())) { - auto it = m_data.m_value.object->find(key); - JSON_ASSERT(it != m_data.m_value.object->end()); + auto it = m_value.object->find(key); + JSON_ASSERT(it != m_value.object->end()); return it->second; } @@ -21476,15 +21131,15 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec // implicitly convert null value to an empty object if (is_null()) { - m_data.m_type = value_t::object; - m_data.m_value.object = create(); + m_type = value_t::object; + m_value.object = create(); assert_invariant(); } // operator[] only works for objects if (JSON_HEDLEY_LIKELY(is_object())) { - auto result = m_data.m_value.object->emplace(std::forward(key), nullptr); + auto result = m_value.object->emplace(std::forward(key), nullptr); return set_parent(result.first->second); } @@ -21500,32 +21155,22 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec // const operator[] only works for objects if (JSON_HEDLEY_LIKELY(is_object())) { - auto it = m_data.m_value.object->find(std::forward(key)); - JSON_ASSERT(it != m_data.m_value.object->end()); + auto it = m_value.object->find(std::forward(key)); + JSON_ASSERT(it != m_value.object->end()); return it->second; } JSON_THROW(type_error::create(305, detail::concat("cannot use operator[] with a string argument with ", type_name()), this)); } - private: - template - using is_comparable_with_object_key = detail::is_comparable < - object_comparator_t, const typename object_t::key_type&, KeyType >; - - template - using value_return_type = std::conditional < - detail::is_c_string_uncvref::value, - string_t, typename std::decay::type >; - - public: /// @brief access specified object element with default value /// @sa https://json.nlohmann.me/api/basic_json/value/ - template < class ValueType, detail::enable_if_t < - !detail::is_transparent::value + // this is the value(const typename object_t::key_type&) overload + template < class KeyType, class ValueType, detail::enable_if_t < + std::is_same::value && detail::is_getable::value - && !std::is_same>::value, int > = 0 > - ValueType value(const typename object_t::key_type& key, const ValueType& default_value) const + && !std::is_same::value, int > = 0 > + typename std::decay::type value(const KeyType& key, ValueType && default_value) const { // value only works for objects if (JSON_HEDLEY_LIKELY(is_object())) @@ -21534,10 +21179,10 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec const auto it = find(key); if (it != end()) { - return it->template get(); + return it->template get::type>(); } - return default_value; + return std::forward(default_value); } JSON_THROW(type_error::create(306, detail::concat("cannot use value() with ", type_name()), this)); @@ -21545,38 +21190,36 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec /// @brief access specified object element with default value /// @sa https://json.nlohmann.me/api/basic_json/value/ - template < class ValueType, class ReturnType = typename value_return_type::type, - detail::enable_if_t < - !detail::is_transparent::value - && detail::is_getable::value - && !std::is_same>::value, int > = 0 > - ReturnType value(const typename object_t::key_type& key, ValueType && default_value) const + /// overload for a default value of type const char* + string_t value(const typename object_t::key_type& key, const char* default_value) const { - // value only works for objects - if (JSON_HEDLEY_LIKELY(is_object())) - { - // if key is found, return value and given default value otherwise - const auto it = find(key); - if (it != end()) - { - return it->template get(); - } + return value(key, string_t(default_value)); + } - return std::forward(default_value); - } + // these two functions, in conjunction with value(const KeyType &, ValueType &&), + // resolve an ambiguity that would otherwise occur between the json_pointer and + // typename object_t::key_type & overloads + template < class ValueType, detail::enable_if_t < + detail::is_getable::value + && !std::is_same::value, int > = 0 > + typename std::decay::type value(const char* key, ValueType && default_value) const + { + return value(typename object_t::key_type(key), std::forward(default_value)); + } - JSON_THROW(type_error::create(306, detail::concat("cannot use value() with ", type_name()), this)); + string_t value(const char* key, const char* default_value) const + { + return value(typename object_t::key_type(key), string_t(default_value)); } /// @brief access specified object element with default value /// @sa https://json.nlohmann.me/api/basic_json/value/ - template < class ValueType, class KeyType, detail::enable_if_t < - detail::is_transparent::value - && !detail::is_json_pointer::value - && is_comparable_with_object_key::value - && detail::is_getable::value - && !std::is_same>::value, int > = 0 > - ValueType value(KeyType && key, const ValueType& default_value) const + /// using std::is_convertible in a std::enable_if will fail when using explicit conversions + template < class KeyType, class ValueType, detail::enable_if_t < + detail::is_getable::value + && !std::is_same::value + && detail::is_usable_as_basic_json_key_type::value, int > = 0 > + typename std::decay::type value(KeyType && key, ValueType && default_value) const { // value only works for objects if (JSON_HEDLEY_LIKELY(is_object())) @@ -21585,47 +21228,29 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec const auto it = find(std::forward(key)); if (it != end()) { - return it->template get(); + return it->template get::type>(); } - return default_value; + return std::forward(default_value); } JSON_THROW(type_error::create(306, detail::concat("cannot use value() with ", type_name()), this)); } - /// @brief access specified object element via JSON Pointer with default value + /// @brief access specified object element with default value /// @sa https://json.nlohmann.me/api/basic_json/value/ - template < class ValueType, class KeyType, class ReturnType = typename value_return_type::type, - detail::enable_if_t < - detail::is_transparent::value - && !detail::is_json_pointer::value - && is_comparable_with_object_key::value - && detail::is_getable::value - && !std::is_same>::value, int > = 0 > - ReturnType value(KeyType && key, ValueType && default_value) const + /// overload for a default value of type const char* + template < class KeyType, detail::enable_if_t < + !detail::is_json_pointer::value, int > = 0 > + string_t value(KeyType && key, const char* default_value) const { - // value only works for objects - if (JSON_HEDLEY_LIKELY(is_object())) - { - // if key is found, return value and given default value otherwise - const auto it = find(std::forward(key)); - if (it != end()) - { - return it->template get(); - } - - return std::forward(default_value); - } - - JSON_THROW(type_error::create(306, detail::concat("cannot use value() with ", type_name()), this)); + return value(std::forward(key), string_t(default_value)); } /// @brief access specified object element via JSON Pointer with default value /// @sa https://json.nlohmann.me/api/basic_json/value/ template < class ValueType, detail::enable_if_t < - detail::is_getable::value - && !std::is_same>::value, int > = 0 > + detail::is_getable::value, int> = 0 > ValueType value(const json_pointer& ptr, const ValueType& default_value) const { // value only works for objects @@ -21645,50 +21270,29 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec JSON_THROW(type_error::create(306, detail::concat("cannot use value() with ", type_name()), this)); } - /// @brief access specified object element via JSON Pointer with default value - /// @sa https://json.nlohmann.me/api/basic_json/value/ - template < class ValueType, class ReturnType = typename value_return_type::type, - detail::enable_if_t < - detail::is_getable::value - && !std::is_same>::value, int > = 0 > - ReturnType value(const json_pointer& ptr, ValueType && default_value) const - { - // value only works for objects - if (JSON_HEDLEY_LIKELY(is_object())) - { - // if pointer resolves a value, return it or use default value - JSON_TRY - { - return ptr.get_checked(this).template get(); - } - JSON_INTERNAL_CATCH (out_of_range&) - { - return std::forward(default_value); - } - } - - JSON_THROW(type_error::create(306, detail::concat("cannot use value() with ", type_name()), this)); - } - template < class ValueType, class BasicJsonType, detail::enable_if_t < - detail::is_basic_json::value - && detail::is_getable::value - && !std::is_same>::value, int > = 0 > + detail::is_getable::value, int> = 0 > JSON_HEDLEY_DEPRECATED_FOR(3.11.0, basic_json::json_pointer or nlohmann::json_pointer) // NOLINT(readability/alt_tokens) ValueType value(const ::nlohmann::json_pointer& ptr, const ValueType& default_value) const { return value(ptr.convert(), default_value); } - template < class ValueType, class BasicJsonType, class ReturnType = typename value_return_type::type, - detail::enable_if_t < - detail::is_basic_json::value - && detail::is_getable::value - && !std::is_same>::value, int > = 0 > + /// @brief access specified object element via JSON Pointer with default value + /// @sa https://json.nlohmann.me/api/basic_json/value/ + /// overload for a default value of type const char* + JSON_HEDLEY_NON_NULL(3) + string_t value(const json_pointer& ptr, const char* default_value) const + { + return value(ptr, string_t(default_value)); + } + + template JSON_HEDLEY_DEPRECATED_FOR(3.11.0, basic_json::json_pointer or nlohmann::json_pointer) // NOLINT(readability/alt_tokens) - ReturnType value(const ::nlohmann::json_pointer& ptr, ValueType && default_value) const + JSON_HEDLEY_NON_NULL(3) + string_t value(const typename ::nlohmann::json_pointer& ptr, const char* default_value) const { - return value(ptr.convert(), std::forward(default_value)); + return value(ptr.convert(), default_value); } /// @brief access the first element @@ -21738,7 +21342,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec IteratorType result = end(); - switch (m_data.m_type) + switch (m_type) { case value_t::boolean: case value_t::number_float: @@ -21755,32 +21359,32 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec if (is_string()) { AllocatorType alloc; - std::allocator_traits::destroy(alloc, m_data.m_value.string); - std::allocator_traits::deallocate(alloc, m_data.m_value.string, 1); - m_data.m_value.string = nullptr; + std::allocator_traits::destroy(alloc, m_value.string); + std::allocator_traits::deallocate(alloc, m_value.string, 1); + m_value.string = nullptr; } else if (is_binary()) { AllocatorType alloc; - std::allocator_traits::destroy(alloc, m_data.m_value.binary); - std::allocator_traits::deallocate(alloc, m_data.m_value.binary, 1); - m_data.m_value.binary = nullptr; + std::allocator_traits::destroy(alloc, m_value.binary); + std::allocator_traits::deallocate(alloc, m_value.binary, 1); + m_value.binary = nullptr; } - m_data.m_type = value_t::null; + m_type = value_t::null; assert_invariant(); break; } case value_t::object: { - result.m_it.object_iterator = m_data.m_value.object->erase(pos.m_it.object_iterator); + result.m_it.object_iterator = m_value.object->erase(pos.m_it.object_iterator); break; } case value_t::array: { - result.m_it.array_iterator = m_data.m_value.array->erase(pos.m_it.array_iterator); + result.m_it.array_iterator = m_value.array->erase(pos.m_it.array_iterator); break; } @@ -21808,7 +21412,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec IteratorType result = end(); - switch (m_data.m_type) + switch (m_type) { case value_t::boolean: case value_t::number_float: @@ -21826,33 +21430,33 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec if (is_string()) { AllocatorType alloc; - std::allocator_traits::destroy(alloc, m_data.m_value.string); - std::allocator_traits::deallocate(alloc, m_data.m_value.string, 1); - m_data.m_value.string = nullptr; + std::allocator_traits::destroy(alloc, m_value.string); + std::allocator_traits::deallocate(alloc, m_value.string, 1); + m_value.string = nullptr; } else if (is_binary()) { AllocatorType alloc; - std::allocator_traits::destroy(alloc, m_data.m_value.binary); - std::allocator_traits::deallocate(alloc, m_data.m_value.binary, 1); - m_data.m_value.binary = nullptr; + std::allocator_traits::destroy(alloc, m_value.binary); + std::allocator_traits::deallocate(alloc, m_value.binary, 1); + m_value.binary = nullptr; } - m_data.m_type = value_t::null; + m_type = value_t::null; assert_invariant(); break; } case value_t::object: { - result.m_it.object_iterator = m_data.m_value.object->erase(first.m_it.object_iterator, + result.m_it.object_iterator = m_value.object->erase(first.m_it.object_iterator, last.m_it.object_iterator); break; } case value_t::array: { - result.m_it.array_iterator = m_data.m_value.array->erase(first.m_it.array_iterator, + result.m_it.array_iterator = m_value.array->erase(first.m_it.array_iterator, last.m_it.array_iterator); break; } @@ -21877,7 +21481,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec JSON_THROW(type_error::create(307, detail::concat("cannot use erase() with ", type_name()), this)); } - return m_data.m_value.object->erase(std::forward(key)); + return m_value.object->erase(std::forward(key)); } template < typename KeyType, detail::enable_if_t < @@ -21890,10 +21494,10 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec JSON_THROW(type_error::create(307, detail::concat("cannot use erase() with ", type_name()), this)); } - const auto it = m_data.m_value.object->find(std::forward(key)); - if (it != m_data.m_value.object->end()) + const auto it = m_value.object->find(std::forward(key)); + if (it != m_value.object->end()) { - m_data.m_value.object->erase(it); + m_value.object->erase(it); return 1; } return 0; @@ -21931,7 +21535,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec JSON_THROW(out_of_range::create(401, detail::concat("array index ", std::to_string(idx), " is out of range"), this)); } - m_data.m_value.array->erase(m_data.m_value.array->begin() + static_cast(idx)); + m_value.array->erase(m_value.array->begin() + static_cast(idx)); } else { @@ -21941,6 +21545,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec /// @} + //////////// // lookup // //////////// @@ -21956,7 +21561,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec if (is_object()) { - result.m_it.object_iterator = m_data.m_value.object->find(key); + result.m_it.object_iterator = m_value.object->find(key); } return result; @@ -21970,7 +21575,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec if (is_object()) { - result.m_it.object_iterator = m_data.m_value.object->find(key); + result.m_it.object_iterator = m_value.object->find(key); } return result; @@ -21986,7 +21591,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec if (is_object()) { - result.m_it.object_iterator = m_data.m_value.object->find(std::forward(key)); + result.m_it.object_iterator = m_value.object->find(std::forward(key)); } return result; @@ -22002,7 +21607,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec if (is_object()) { - result.m_it.object_iterator = m_data.m_value.object->find(std::forward(key)); + result.m_it.object_iterator = m_value.object->find(std::forward(key)); } return result; @@ -22013,7 +21618,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec size_type count(const typename object_t::key_type& key) const { // return 0 for all nonobject types - return is_object() ? m_data.m_value.object->count(key) : 0; + return is_object() ? m_value.object->count(key) : 0; } /// @brief returns the number of occurrences of a key in a JSON object @@ -22023,14 +21628,14 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec size_type count(KeyType && key) const { // return 0 for all nonobject types - return is_object() ? m_data.m_value.object->count(std::forward(key)) : 0; + return is_object() ? m_value.object->count(std::forward(key)) : 0; } /// @brief check the existence of an element in a JSON object /// @sa https://json.nlohmann.me/api/basic_json/contains/ bool contains(const typename object_t::key_type& key) const { - return is_object() && m_data.m_value.object->find(key) != m_data.m_value.object->end(); + return is_object() && m_value.object->find(key) != m_value.object->end(); } /// @brief check the existence of an element in a JSON object @@ -22039,7 +21644,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec detail::is_usable_as_basic_json_key_type::value, int> = 0> bool contains(KeyType && key) const { - return is_object() && m_data.m_value.object->find(std::forward(key)) != m_data.m_value.object->end(); + return is_object() && m_value.object->find(std::forward(key)) != m_value.object->end(); } /// @brief check the existence of an element in a JSON object given a JSON pointer @@ -22049,15 +21654,16 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec return ptr.contains(this); } - template::value, int> = 0> + template JSON_HEDLEY_DEPRECATED_FOR(3.11.0, basic_json::json_pointer or nlohmann::json_pointer) // NOLINT(readability/alt_tokens) - bool contains(const typename ::nlohmann::json_pointer& ptr) const + bool contains(const typename ::nlohmann::json_pointer ptr) const { return ptr.contains(this); } /// @} + /////////////// // iterators // /////////////// @@ -22196,6 +21802,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec /// @} + ////////////// // capacity // ////////////// @@ -22207,7 +21814,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec /// @sa https://json.nlohmann.me/api/basic_json/empty/ bool empty() const noexcept { - switch (m_data.m_type) + switch (m_type) { case value_t::null: { @@ -22218,13 +21825,13 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec case value_t::array: { // delegate call to array_t::empty() - return m_data.m_value.array->empty(); + return m_value.array->empty(); } case value_t::object: { // delegate call to object_t::empty() - return m_data.m_value.object->empty(); + return m_value.object->empty(); } case value_t::string: @@ -22246,7 +21853,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec /// @sa https://json.nlohmann.me/api/basic_json/size/ size_type size() const noexcept { - switch (m_data.m_type) + switch (m_type) { case value_t::null: { @@ -22257,13 +21864,13 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec case value_t::array: { // delegate call to array_t::size() - return m_data.m_value.array->size(); + return m_value.array->size(); } case value_t::object: { // delegate call to object_t::size() - return m_data.m_value.object->size(); + return m_value.object->size(); } case value_t::string: @@ -22285,18 +21892,18 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec /// @sa https://json.nlohmann.me/api/basic_json/max_size/ size_type max_size() const noexcept { - switch (m_data.m_type) + switch (m_type) { case value_t::array: { // delegate call to array_t::max_size() - return m_data.m_value.array->max_size(); + return m_value.array->max_size(); } case value_t::object: { // delegate call to object_t::max_size() - return m_data.m_value.object->max_size(); + return m_value.object->max_size(); } case value_t::null: @@ -22317,6 +21924,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec /// @} + /////////////// // modifiers // /////////////// @@ -22328,53 +21936,53 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec /// @sa https://json.nlohmann.me/api/basic_json/clear/ void clear() noexcept { - switch (m_data.m_type) + switch (m_type) { case value_t::number_integer: { - m_data.m_value.number_integer = 0; + m_value.number_integer = 0; break; } case value_t::number_unsigned: { - m_data.m_value.number_unsigned = 0; + m_value.number_unsigned = 0; break; } case value_t::number_float: { - m_data.m_value.number_float = 0.0; + m_value.number_float = 0.0; break; } case value_t::boolean: { - m_data.m_value.boolean = false; + m_value.boolean = false; break; } case value_t::string: { - m_data.m_value.string->clear(); + m_value.string->clear(); break; } case value_t::binary: { - m_data.m_value.binary->clear(); + m_value.binary->clear(); break; } case value_t::array: { - m_data.m_value.array->clear(); + m_value.array->clear(); break; } case value_t::object: { - m_data.m_value.object->clear(); + m_value.object->clear(); break; } @@ -22398,15 +22006,15 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec // transform null object into an array if (is_null()) { - m_data.m_type = value_t::array; - m_data.m_value = value_t::array; + m_type = value_t::array; + m_value = value_t::array; assert_invariant(); } // add element to array (move semantics) - const auto old_capacity = m_data.m_value.array->capacity(); - m_data.m_value.array->push_back(std::move(val)); - set_parent(m_data.m_value.array->back(), old_capacity); + const auto old_capacity = m_value.array->capacity(); + m_value.array->push_back(std::move(val)); + set_parent(m_value.array->back(), old_capacity); // if val is moved from, basic_json move constructor marks it null, so we do not call the destructor } @@ -22431,15 +22039,15 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec // transform null object into an array if (is_null()) { - m_data.m_type = value_t::array; - m_data.m_value = value_t::array; + m_type = value_t::array; + m_value = value_t::array; assert_invariant(); } // add element to array - const auto old_capacity = m_data.m_value.array->capacity(); - m_data.m_value.array->push_back(val); - set_parent(m_data.m_value.array->back(), old_capacity); + const auto old_capacity = m_value.array->capacity(); + m_value.array->push_back(val); + set_parent(m_value.array->back(), old_capacity); } /// @brief add an object to an array @@ -22463,13 +22071,13 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec // transform null object into an object if (is_null()) { - m_data.m_type = value_t::object; - m_data.m_value = value_t::object; + m_type = value_t::object; + m_value = value_t::object; assert_invariant(); } // add element to object - auto res = m_data.m_value.object->insert(val); + auto res = m_value.object->insert(val); set_parent(res.first->second); } @@ -22519,15 +22127,15 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec // transform null object into an array if (is_null()) { - m_data.m_type = value_t::array; - m_data.m_value = value_t::array; + m_type = value_t::array; + m_value = value_t::array; assert_invariant(); } // add element to array (perfect forwarding) - const auto old_capacity = m_data.m_value.array->capacity(); - m_data.m_value.array->emplace_back(std::forward(args)...); - return set_parent(m_data.m_value.array->back(), old_capacity); + const auto old_capacity = m_value.array->capacity(); + m_value.array->emplace_back(std::forward(args)...); + return set_parent(m_value.array->back(), old_capacity); } /// @brief add an object to an object if key does not exist @@ -22544,13 +22152,13 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec // transform null object into an object if (is_null()) { - m_data.m_type = value_t::object; - m_data.m_value = value_t::object; + m_type = value_t::object; + m_value = value_t::object; assert_invariant(); } // add element to array (perfect forwarding) - auto res = m_data.m_value.object->emplace(std::forward(args)...); + auto res = m_value.object->emplace(std::forward(args)...); set_parent(res.first->second); // create result iterator and set iterator to the result of emplace @@ -22568,14 +22176,14 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec iterator insert_iterator(const_iterator pos, Args&& ... args) { iterator result(this); - JSON_ASSERT(m_data.m_value.array != nullptr); + JSON_ASSERT(m_value.array != nullptr); - auto insert_pos = std::distance(m_data.m_value.array->begin(), pos.m_it.array_iterator); - m_data.m_value.array->insert(pos.m_it.array_iterator, std::forward(args)...); - result.m_it.array_iterator = m_data.m_value.array->begin() + insert_pos; + auto insert_pos = std::distance(m_value.array->begin(), pos.m_it.array_iterator); + m_value.array->insert(pos.m_it.array_iterator, std::forward(args)...); + result.m_it.array_iterator = m_value.array->begin() + insert_pos; // This could have been written as: - // result.m_it.array_iterator = m_data.m_value.array->insert(pos.m_it.array_iterator, cnt, val); + // result.m_it.array_iterator = m_value.array->insert(pos.m_it.array_iterator, cnt, val); // but the return value of insert is missing in GCC 4.8, so it is written this way instead. set_parents(); @@ -22702,7 +22310,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec JSON_THROW(invalid_iterator::create(202, "iterators first and last must point to objects", this)); } - m_data.m_value.object->insert(first.m_it.object_iterator, last.m_it.object_iterator); + m_value.object->insert(first.m_it.object_iterator, last.m_it.object_iterator); } /// @brief updates a JSON object from another object, overwriting existing keys @@ -22719,8 +22327,8 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec // implicitly convert null value to an empty object if (is_null()) { - m_data.m_type = value_t::object; - m_data.m_value.object = create(); + m_type = value_t::object; + m_value.object = create(); assert_invariant(); } @@ -22745,16 +22353,16 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec { if (merge_objects && it.value().is_object()) { - auto it2 = m_data.m_value.object->find(it.key()); - if (it2 != m_data.m_value.object->end()) + auto it2 = m_value.object->find(it.key()); + if (it2 != m_value.object->end()) { it2->second.update(it.value(), true); continue; } } - m_data.m_value.object->operator[](it.key()) = it.value(); + m_value.object->operator[](it.key()) = it.value(); #if JSON_DIAGNOSTICS - m_data.m_value.object->operator[](it.key()).m_parent = this; + m_value.object->operator[](it.key()).m_parent = this; #endif } } @@ -22764,12 +22372,12 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec void swap(reference other) noexcept ( std::is_nothrow_move_constructible::value&& std::is_nothrow_move_assignable::value&& - std::is_nothrow_move_constructible::value&& // NOLINT(cppcoreguidelines-noexcept-swap,performance-noexcept-swap) + std::is_nothrow_move_constructible::value&& std::is_nothrow_move_assignable::value ) { - std::swap(m_data.m_type, other.m_data.m_type); - std::swap(m_data.m_value, other.m_data.m_value); + std::swap(m_type, other.m_type); + std::swap(m_value, other.m_value); set_parents(); other.set_parents(); @@ -22781,7 +22389,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec friend void swap(reference left, reference right) noexcept ( std::is_nothrow_move_constructible::value&& std::is_nothrow_move_assignable::value&& - std::is_nothrow_move_constructible::value&& // NOLINT(cppcoreguidelines-noexcept-swap,performance-noexcept-swap) + std::is_nothrow_move_constructible::value&& std::is_nothrow_move_assignable::value ) { @@ -22790,13 +22398,13 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec /// @brief exchanges the values /// @sa https://json.nlohmann.me/api/basic_json/swap/ - void swap(array_t& other) // NOLINT(bugprone-exception-escape,cppcoreguidelines-noexcept-swap,performance-noexcept-swap) + void swap(array_t& other) // NOLINT(bugprone-exception-escape) { // swap only works for arrays if (JSON_HEDLEY_LIKELY(is_array())) { using std::swap; - swap(*(m_data.m_value.array), other); + swap(*(m_value.array), other); } else { @@ -22806,13 +22414,13 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec /// @brief exchanges the values /// @sa https://json.nlohmann.me/api/basic_json/swap/ - void swap(object_t& other) // NOLINT(bugprone-exception-escape,cppcoreguidelines-noexcept-swap,performance-noexcept-swap) + void swap(object_t& other) // NOLINT(bugprone-exception-escape) { // swap only works for objects if (JSON_HEDLEY_LIKELY(is_object())) { using std::swap; - swap(*(m_data.m_value.object), other); + swap(*(m_value.object), other); } else { @@ -22822,13 +22430,13 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec /// @brief exchanges the values /// @sa https://json.nlohmann.me/api/basic_json/swap/ - void swap(string_t& other) // NOLINT(bugprone-exception-escape,cppcoreguidelines-noexcept-swap,performance-noexcept-swap) + void swap(string_t& other) // NOLINT(bugprone-exception-escape) { // swap only works for strings if (JSON_HEDLEY_LIKELY(is_string())) { using std::swap; - swap(*(m_data.m_value.string), other); + swap(*(m_value.string), other); } else { @@ -22838,13 +22446,13 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec /// @brief exchanges the values /// @sa https://json.nlohmann.me/api/basic_json/swap/ - void swap(binary_t& other) // NOLINT(bugprone-exception-escape,cppcoreguidelines-noexcept-swap,performance-noexcept-swap) + void swap(binary_t& other) // NOLINT(bugprone-exception-escape) { // swap only works for strings if (JSON_HEDLEY_LIKELY(is_binary())) { using std::swap; - swap(*(m_data.m_value.binary), other); + swap(*(m_value.binary), other); } else { @@ -22860,7 +22468,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec if (JSON_HEDLEY_LIKELY(is_binary())) { using std::swap; - swap(*(m_data.m_value.binary), other); + swap(*(m_value.binary), other); } else { @@ -22888,31 +22496,31 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec switch (lhs_type) \ { \ case value_t::array: \ - return (*lhs.m_data.m_value.array) op (*rhs.m_data.m_value.array); \ + return (*lhs.m_value.array) op (*rhs.m_value.array); \ \ case value_t::object: \ - return (*lhs.m_data.m_value.object) op (*rhs.m_data.m_value.object); \ + return (*lhs.m_value.object) op (*rhs.m_value.object); \ \ case value_t::null: \ return (null_result); \ \ case value_t::string: \ - return (*lhs.m_data.m_value.string) op (*rhs.m_data.m_value.string); \ + return (*lhs.m_value.string) op (*rhs.m_value.string); \ \ case value_t::boolean: \ - return (lhs.m_data.m_value.boolean) op (rhs.m_data.m_value.boolean); \ + return (lhs.m_value.boolean) op (rhs.m_value.boolean); \ \ case value_t::number_integer: \ - return (lhs.m_data.m_value.number_integer) op (rhs.m_data.m_value.number_integer); \ + return (lhs.m_value.number_integer) op (rhs.m_value.number_integer); \ \ case value_t::number_unsigned: \ - return (lhs.m_data.m_value.number_unsigned) op (rhs.m_data.m_value.number_unsigned); \ + return (lhs.m_value.number_unsigned) op (rhs.m_value.number_unsigned); \ \ case value_t::number_float: \ - return (lhs.m_data.m_value.number_float) op (rhs.m_data.m_value.number_float); \ + return (lhs.m_value.number_float) op (rhs.m_value.number_float); \ \ case value_t::binary: \ - return (*lhs.m_data.m_value.binary) op (*rhs.m_data.m_value.binary); \ + return (*lhs.m_value.binary) op (*rhs.m_value.binary); \ \ case value_t::discarded: \ default: \ @@ -22921,27 +22529,27 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec } \ else if (lhs_type == value_t::number_integer && rhs_type == value_t::number_float) \ { \ - return static_cast(lhs.m_data.m_value.number_integer) op rhs.m_data.m_value.number_float; \ + return static_cast(lhs.m_value.number_integer) op rhs.m_value.number_float; \ } \ else if (lhs_type == value_t::number_float && rhs_type == value_t::number_integer) \ { \ - return lhs.m_data.m_value.number_float op static_cast(rhs.m_data.m_value.number_integer); \ + return lhs.m_value.number_float op static_cast(rhs.m_value.number_integer); \ } \ else if (lhs_type == value_t::number_unsigned && rhs_type == value_t::number_float) \ { \ - return static_cast(lhs.m_data.m_value.number_unsigned) op rhs.m_data.m_value.number_float; \ + return static_cast(lhs.m_value.number_unsigned) op rhs.m_value.number_float; \ } \ else if (lhs_type == value_t::number_float && rhs_type == value_t::number_unsigned) \ { \ - return lhs.m_data.m_value.number_float op static_cast(rhs.m_data.m_value.number_unsigned); \ + return lhs.m_value.number_float op static_cast(rhs.m_value.number_unsigned); \ } \ else if (lhs_type == value_t::number_unsigned && rhs_type == value_t::number_integer) \ { \ - return static_cast(lhs.m_data.m_value.number_unsigned) op rhs.m_data.m_value.number_integer; \ + return static_cast(lhs.m_value.number_unsigned) op rhs.m_value.number_integer; \ } \ else if (lhs_type == value_t::number_integer && rhs_type == value_t::number_unsigned) \ { \ - return lhs.m_data.m_value.number_integer op static_cast(rhs.m_data.m_value.number_unsigned); \ + return lhs.m_value.number_integer op static_cast(rhs.m_value.number_unsigned); \ } \ else if(compares_unordered(lhs, rhs))\ {\ @@ -22958,8 +22566,8 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec // an operation is computed as an odd number of inverses of others static bool compares_unordered(const_reference lhs, const_reference rhs, bool inverse = false) noexcept { - if ((lhs.is_number_float() && std::isnan(lhs.m_data.m_value.number_float) && rhs.is_number()) - || (rhs.is_number_float() && std::isnan(rhs.m_data.m_value.number_float) && lhs.is_number())) + if ((lhs.is_number_float() && std::isnan(lhs.m_value.number_float) && rhs.is_number()) + || (rhs.is_number_float() && std::isnan(rhs.m_value.number_float) && lhs.is_number())) { return true; } @@ -23303,6 +22911,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec #endif // JSON_NO_IO /// @} + ///////////////////// // deserialization // ///////////////////// @@ -23459,7 +23068,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec JSON_HEDLEY_RETURNS_NON_NULL const char* type_name() const noexcept { - switch (m_data.m_type) + switch (m_type) { case value_t::null: return "null"; @@ -23483,43 +23092,17 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec } } + JSON_PRIVATE_UNLESS_TESTED: ////////////////////// // member variables // ////////////////////// - struct data - { - /// the type of the current element - value_t m_type = value_t::null; - - /// the value of the current element - json_value m_value = {}; - - data(const value_t v) - : m_type(v), m_value(v) - { - } - - data(size_type cnt, const basic_json& val) - : m_type(value_t::array) - { - m_value.array = create(cnt, val); - } - - data() noexcept = default; - data(data&&) noexcept = default; - data(const data&) noexcept = delete; - data& operator=(data&&) noexcept = delete; - data& operator=(const data&) noexcept = delete; - - ~data() noexcept - { - m_value.destroy(m_type); - } - }; + /// the type of the current element + value_t m_type = value_t::null; - data m_data = {}; + /// the value of the current element + json_value m_value = {}; #if JSON_DIAGNOSTICS /// a pointer to a parent value (for debugging purposes) @@ -23700,6 +23283,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec return from_cbor(ptr, ptr + len, strict, allow_exceptions, tag_handler); } + JSON_HEDLEY_WARN_UNUSED_RESULT JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_cbor(ptr, ptr + len)) static basic_json from_cbor(detail::span_input_adapter&& i, @@ -23823,6 +23407,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec return res ? result : basic_json(value_t::discarded); } + /// @brief create a JSON value from an input in BJData format /// @sa https://json.nlohmann.me/api/basic_json/from_bjdata/ template @@ -23950,7 +23535,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec return ptr.get_checked(this); } - template::value, int> = 0> + template JSON_HEDLEY_DEPRECATED_FOR(3.11.0, basic_json::json_pointer or nlohmann::json_pointer) // NOLINT(readability/alt_tokens) reference at(const ::nlohmann::json_pointer& ptr) { @@ -23964,7 +23549,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec return ptr.get_checked(this); } - template::value, int> = 0> + template JSON_HEDLEY_DEPRECATED_FOR(3.11.0, basic_json::json_pointer or nlohmann::json_pointer) // NOLINT(readability/alt_tokens) const_reference at(const ::nlohmann::json_pointer& ptr) const { @@ -24045,7 +23630,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec } // make sure the top element of the pointer exists - json_pointer const top_pointer = ptr.top(); + json_pointer top_pointer = ptr.top(); if (top_pointer != ptr) { result.at(top_pointer); @@ -24057,7 +23642,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec // parent must exist when performing patch add per RFC6902 specs basic_json& parent = result.at(ptr); - switch (parent.m_data.m_type) + switch (parent.m_type) { case value_t::null: case value_t::object: @@ -24103,7 +23688,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec }; // wrapper for "remove" operation; remove value at ptr - const auto operation_remove = [this, & result](json_pointer & ptr) + const auto operation_remove = [this, &result](json_pointer & ptr) { // get reference to parent of JSON pointer ptr const auto last_path = ptr.back(); @@ -24146,13 +23731,13 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec bool string_type) -> basic_json & { // find value - auto it = val.m_data.m_value.object->find(member); + auto it = val.m_value.object->find(member); // context-sensitive error message const auto error_msg = (op == "op") ? "operation" : detail::concat("operation '", op, '\''); // check if desired value is present - if (JSON_HEDLEY_UNLIKELY(it == val.m_data.m_value.object->end())) + if (JSON_HEDLEY_UNLIKELY(it == val.m_value.object->end())) { // NOLINTNEXTLINE(performance-inefficient-string-concatenation) JSON_THROW(parse_error::create(105, 0, detail::concat(error_msg, " must have member '", member, "'"), &val)); @@ -24207,7 +23792,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec json_pointer from_ptr(from_path); // the "from" location must exist - use at() - basic_json const v = result.at(from_ptr); + basic_json v = result.at(from_ptr); // The move operation is functionally identical to a // "remove" operation on the "from" location, followed @@ -24224,7 +23809,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec const json_pointer from_ptr(from_path); // the "from" location must exist - use at() - basic_json const v = result.at(from_ptr); + basic_json v = result.at(from_ptr); // The copy is functionally identical to an "add" // operation at the target location using the value @@ -24466,11 +24051,7 @@ inline namespace json_literals /// @brief user-defined string literal for JSON values /// @sa https://json.nlohmann.me/api/basic_json/operator_literal_json/ JSON_HEDLEY_NON_NULL(1) -#if !defined(JSON_HEDLEY_GCC_VERSION) || JSON_HEDLEY_GCC_VERSION_CHECK(4,9,0) - inline nlohmann::json operator ""_json(const char* s, std::size_t n) -#else - inline nlohmann::json operator "" _json(const char* s, std::size_t n) -#endif +inline nlohmann::json operator "" _json(const char* s, std::size_t n) { return nlohmann::json::parse(s, s + n); } @@ -24478,11 +24059,7 @@ JSON_HEDLEY_NON_NULL(1) /// @brief user-defined string literal for JSON pointer /// @sa https://json.nlohmann.me/api/basic_json/operator_literal_json_pointer/ JSON_HEDLEY_NON_NULL(1) -#if !defined(JSON_HEDLEY_GCC_VERSION) || JSON_HEDLEY_GCC_VERSION_CHECK(4,9,0) - inline nlohmann::json::json_pointer operator ""_json_pointer(const char* s, std::size_t n) -#else - inline nlohmann::json::json_pointer operator "" _json_pointer(const char* s, std::size_t n) -#endif +inline nlohmann::json::json_pointer operator "" _json_pointer(const char* s, std::size_t n) { return nlohmann::json::json_pointer(std::string(s, n)); } @@ -24501,7 +24078,7 @@ namespace std // NOLINT(cert-dcl58-cpp) /// @brief hash value for JSON objects /// @sa https://json.nlohmann.me/api/basic_json/std_hash/ NLOHMANN_BASIC_JSON_TPL_DECLARATION -struct hash // NOLINT(cert-dcl58-cpp) +struct hash { std::size_t operator()(const nlohmann::NLOHMANN_BASIC_JSON_TPL& j) const { @@ -24534,8 +24111,8 @@ struct less< ::nlohmann::detail::value_t> // do not remove the space after '<', /// @brief exchanges the values of two JSON objects /// @sa https://json.nlohmann.me/api/basic_json/std_swap/ NLOHMANN_BASIC_JSON_TPL_DECLARATION -inline void swap(nlohmann::NLOHMANN_BASIC_JSON_TPL& j1, nlohmann::NLOHMANN_BASIC_JSON_TPL& j2) noexcept( // NOLINT(readability-inconsistent-declaration-parameter-name, cert-dcl58-cpp) - is_nothrow_move_constructible::value&& // NOLINT(misc-redundant-expression,cppcoreguidelines-noexcept-swap,performance-noexcept-swap) +inline void swap(nlohmann::NLOHMANN_BASIC_JSON_TPL& j1, nlohmann::NLOHMANN_BASIC_JSON_TPL& j2) noexcept( // NOLINT(readability-inconsistent-declaration-parameter-name) + is_nothrow_move_constructible::value&& // NOLINT(misc-redundant-expression) is_nothrow_move_assignable::value) { j1.swap(j2); @@ -24546,22 +24123,17 @@ inline void swap(nlohmann::NLOHMANN_BASIC_JSON_TPL& j1, nlohmann::NLOHMANN_BASIC } // namespace std #if JSON_USE_GLOBAL_UDLS - #if !defined(JSON_HEDLEY_GCC_VERSION) || JSON_HEDLEY_GCC_VERSION_CHECK(4,9,0) - using nlohmann::literals::json_literals::operator ""_json; // NOLINT(misc-unused-using-decls,google-global-names-in-headers) - using nlohmann::literals::json_literals::operator ""_json_pointer; //NOLINT(misc-unused-using-decls,google-global-names-in-headers) - #else - using nlohmann::literals::json_literals::operator "" _json; // NOLINT(misc-unused-using-decls,google-global-names-in-headers) - using nlohmann::literals::json_literals::operator "" _json_pointer; //NOLINT(misc-unused-using-decls,google-global-names-in-headers) - #endif + using nlohmann::literals::json_literals::operator "" _json; // NOLINT(misc-unused-using-decls,google-global-names-in-headers) + using nlohmann::literals::json_literals::operator "" _json_pointer; //NOLINT(misc-unused-using-decls,google-global-names-in-headers) #endif // #include // __ _____ _____ _____ // __| | __| | | | JSON for Modern C++ -// | | |__ | | | | | | version 3.11.3 +// | | |__ | | | | | | version 3.11.1 // |_____|_____|_____|_|___| https://github.com/nlohmann/json // -// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann +// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann // SPDX-License-Identifier: MIT @@ -24596,17 +24168,16 @@ inline void swap(nlohmann::NLOHMANN_BASIC_JSON_TPL& j1, nlohmann::NLOHMANN_BASIC #undef JSON_HAS_EXPERIMENTAL_FILESYSTEM #undef JSON_HAS_THREE_WAY_COMPARISON #undef JSON_HAS_RANGES - #undef JSON_HAS_STATIC_RTTI #undef JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON #endif // #include // __ _____ _____ _____ // __| | __| | | | JSON for Modern C++ -// | | |__ | | | | | | version 3.11.3 +// | | |__ | | | | | | version 3.11.1 // |_____|_____|_____|_|___| https://github.com/nlohmann/json // -// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann +// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann // SPDX-License-Identifier: MIT From 1a7476df2c3e0479920de8fd629044872b43aafe Mon Sep 17 00:00:00 2001 From: Alex McCaskey Date: Thu, 25 Jul 2024 18:21:49 +0000 Subject: [PATCH 2/6] cleanup Signed-off-by: Alex McCaskey --- .github/workflows/build_and_test.yml | 3 +- .../drivers/pyscf/ExternalPySCFDriver.cpp | 31 ++--- .../drivers/pyscf/RESTPySCFDriver.cpp | 5 +- cudaqlib/operators/chemistry/molecule.h | 2 - python/CMakeLists.txt | 3 +- python/bindings/operators/py_operators.cpp | 14 +-- .../pyscf/generators/gas_phase_generator.py | 35 +++--- .../polarizable_embedded_generator.py | 109 ++++++++---------- python/tests/test_operators.py | 1 - python/tests/test_pyscf_tool.py | 29 +++-- tests/operators/OperatorsTester.cpp | 8 +- tools/chemistry/cudaq-pyscf.py | 27 ++--- 12 files changed, 113 insertions(+), 154 deletions(-) diff --git a/.github/workflows/build_and_test.yml b/.github/workflows/build_and_test.yml index d1fd6d5..ac3cde4 100644 --- a/.github/workflows/build_and_test.yml +++ b/.github/workflows/build_and_test.yml @@ -34,4 +34,5 @@ jobs: --build-arg="repo=${{github.event.pull_request.head.repo.full_name}}" -t cudaqlib-dev:local -f docker/ci/Dockerfile . - name: Run tests - run: docker run --rm cudaqlib-dev:local ctest --output-on-failure --test-dir cudaqlib/build \ No newline at end of file + run: docker run --rm cudaqlib-dev:local ctest --output-on-failure --test-dir cudaqlib/build + run: docker run --rm cudaqlib-dev:local python3 -m pytest cudaqlib/python/tests -v \ No newline at end of file diff --git a/cudaqlib/operators/chemistry/drivers/pyscf/ExternalPySCFDriver.cpp b/cudaqlib/operators/chemistry/drivers/pyscf/ExternalPySCFDriver.cpp index 939e89e..82b0a63 100644 --- a/cudaqlib/operators/chemistry/drivers/pyscf/ExternalPySCFDriver.cpp +++ b/cudaqlib/operators/chemistry/drivers/pyscf/ExternalPySCFDriver.cpp @@ -88,7 +88,7 @@ class external_pyscf // Import all the data we need from the execution. std::ifstream f(metadataFile); auto metadata = nlohmann::json::parse(f); - + printf("TEST\n%s\n", metadata.dump(4).c_str()); // Get the energy, num orbitals, and num qubits std::unordered_map energies; for (auto &[energyName, E] : metadata["energies"].items()) @@ -106,22 +106,16 @@ class external_pyscf // Get the operators fermion_op fermionOp(numQubits, energy); - std::unordered_map operators; - for (auto &[opFileName, opType] : metadata["operators"].items()) { - auto type = opType.get(); - if (type == "obi") - fermionOp.hpq.add(readInData(opFileName)); - else if (type == "tbi") - fermionOp.hpqrs.add(readInData(opFileName)); - - auto res = operators.insert({type, fermion_op(numQubits, energy)}); - if (type.find("obi") != std::string::npos) - res.first->second.hpq.set_data(readInData(opFileName)); - else - res.first->second.hpqrs.set_data(readInData(opFileName)); - - std::remove(opFileName.c_str()); - } + auto hpqElements = metadata["hpq"]["data"]; + auto hpqrsElements = metadata["hpqrs"]["data"]; + std::vector> hpqValues, hpqrsValues; + for (auto &element : hpqElements) + hpqValues.push_back({element[0].get(), element[1].get()}); + for (auto &element : hpqrsElements) + hpqrsValues.push_back( + {element[0].get(), element[1].get()}); + fermionOp.hpq.set_data(hpqValues); + fermionOp.hpqrs.set_data(hpqrsValues); // Transform to a spin operator auto transform = fermion_to_spin::get(options.fermion_to_string); @@ -129,8 +123,7 @@ class external_pyscf // Return the molecular hamiltonian return operators::molecular_hamiltonian{ - spinHamiltonian, std::move(fermionOp), num_electrons, numOrb, energy, - energies, std::move(operators)}; + spinHamiltonian, std::move(fermionOp), num_electrons, numOrb, energies}; } CUDAQ_REGISTER_MOLECULEPACKAGEDRIVER(external_pyscf) diff --git a/cudaqlib/operators/chemistry/drivers/pyscf/RESTPySCFDriver.cpp b/cudaqlib/operators/chemistry/drivers/pyscf/RESTPySCFDriver.cpp index 175a563..44cb2e2 100644 --- a/cudaqlib/operators/chemistry/drivers/pyscf/RESTPySCFDriver.cpp +++ b/cudaqlib/operators/chemistry/drivers/pyscf/RESTPySCFDriver.cpp @@ -32,7 +32,7 @@ class RESTPySCFDriver if (res.contains("status") && res["status"].get() == "available") return true; - } catch (std::exception& e) { + } catch (std::exception &e) { return false; } return true; @@ -114,8 +114,7 @@ class RESTPySCFDriver // Return the molecular hamiltonian return operators::molecular_hamiltonian{ - spinHamiltonian, std::move(fermionOp), num_electrons, numOrb, energy, - energies, std::move(operators)}; + spinHamiltonian, std::move(fermionOp), num_electrons, numOrb, energies}; } CUDAQ_REGISTER_MOLECULEPACKAGEDRIVER(RESTPySCFDriver) diff --git a/cudaqlib/operators/chemistry/molecule.h b/cudaqlib/operators/chemistry/molecule.h index 0810fce..396b394 100644 --- a/cudaqlib/operators/chemistry/molecule.h +++ b/cudaqlib/operators/chemistry/molecule.h @@ -50,9 +50,7 @@ struct molecular_hamiltonian { operators::fermion_op fermionOperator; std::size_t n_electrons; std::size_t n_orbitals; - double nuclear_repulsion; std::unordered_map energies; - std::unordered_map operators; }; struct molecule_options { diff --git a/python/CMakeLists.txt b/python/CMakeLists.txt index efc4a44..4431a8f 100644 --- a/python/CMakeLists.txt +++ b/python/CMakeLists.txt @@ -1,5 +1,5 @@ # ============================================================================ # -# Copyright (c) 2022 - 2023 NVIDIA Corporation & Affiliates. # +# Copyright (c) 2022 - 2024 NVIDIA Corporation & Affiliates. # # All rights reserved. # # # # This source code and the accompanying materials are made available under # @@ -58,4 +58,3 @@ if (NOT SKBUILD) else() install(TARGETS _pycudaqlib LIBRARY DESTINATION cudaqlib) endif() - diff --git a/python/bindings/operators/py_operators.cpp b/python/bindings/operators/py_operators.cpp index cb88b09..fba568d 100644 --- a/python/bindings/operators/py_operators.cpp +++ b/python/bindings/operators/py_operators.cpp @@ -22,13 +22,14 @@ void bindOperators(py::module &mod) { auto operators = mod.def_submodule("operators"); - operators.def("jordan_wigner", [](fermion_op& op) { + operators.def("jordan_wigner", [](fermion_op &op) { return fermion_to_spin::get("jordan_wigner")->generate(op); }); py::class_(operators, "fermion_to_spin") - .def_static("get", - [](const std::string &name) { return fermion_to_spin::get(name); }) + .def_static( + "get", + [](const std::string &name) { return fermion_to_spin::get(name); }) .def("generate", &fermion_to_spin::generate, ""); py::class_(operators, "OneBodyIntegrals", @@ -46,7 +47,7 @@ void bindOperators(py::module &mod) { m.shape[1], /* Strides (in bytes) for each index */ sizeof(std::complex)}); }); - + py::class_(operators, "TwoBodyIntegrals", py::buffer_protocol()) .def_buffer([](two_body_integrals &m) -> py::buffer_info { @@ -75,12 +76,9 @@ void bindOperators(py::module &mod) { py::class_(operators, "MolecularHamiltonian") .def_readonly("energies", &molecular_hamiltonian::energies) - .def_readonly("operators", &molecular_hamiltonian::operators) .def_readonly("hamiltonian", &molecular_hamiltonian::hamiltonian) .def_readonly("n_electrons", &molecular_hamiltonian::n_electrons) - .def_readonly("n_orbitals", &molecular_hamiltonian::n_orbitals) - .def_readonly("nuclear_repulsion", - &molecular_hamiltonian::nuclear_repulsion); + .def_readonly("n_orbitals", &molecular_hamiltonian::n_orbitals); operators.def( "create_molecule", diff --git a/python/cudaqlib/tools/chemistry/pyscf/generators/gas_phase_generator.py b/python/cudaqlib/tools/chemistry/pyscf/generators/gas_phase_generator.py index 979f8f0..569d93f 100644 --- a/python/cudaqlib/tools/chemistry/pyscf/generators/gas_phase_generator.py +++ b/python/cudaqlib/tools/chemistry/pyscf/generators/gas_phase_generator.py @@ -595,33 +595,26 @@ def get_spin_hamiltonian(self, xyz:str, spin:int, charge: int, basis:str, symmet h1e_cas, h2e_cas, ecore) energies['core_energy'] = ecore - # Dump obi and tbi to binary file. - if cache_data: - obi.astype(complex).tofile(f'{filename}_one_body.dat') - tbi.astype(complex).tofile(f'{filename}_two_body.dat') - ###################################################### # Dump energies / etc to a metadata file - metadata = {} - if cache_data: - metadata = { - 'num_electrons': nelec if nele_cas == None else nele_cas, - 'num_orbitals': norb if nele_cas == None else norb_cas, - 'hf_energy': myhf.e_tot, - 'energies': energies, - 'operators': { - f'{filename}_one_body.dat': 'obi', - f'{filename}_two_body.dat': 'tbi' - } + results = { + 'num_electrons': nelec if nele_cas == None else nele_cas, + 'num_orbitals': norb if nele_cas == None else norb_cas, + 'hf_energy': myhf.e_tot, + 'energies': energies, + 'hpq': {'data':[(x.real,x.imag) for x in obi.astype(complex).flatten().tolist()]}, + 'hpqrs': {'data': [(x.real, x.imag) for x in tbi.astype(complex).flatten().tolist()]}, + 'operators': { + f'{filename}_one_body.dat': 'obi', + f'{filename}_two_body.dat': 'tbi' } + } + if cache_data: with open(f'{filename}_metadata.json', 'w') as f: - json.dump(metadata, f) - - if nele_cas is None: - return (obi, tbi, e_nn, nelec, norb, metadata) + json.dump(results, f) - return (obi, tbi, ecore, nele_cas, norb_cas, metadata) + return results def generate(self, xyz, basis, **kwargs): if xyz == None: diff --git a/python/cudaqlib/tools/chemistry/pyscf/generators/polarizable_embedded_generator.py b/python/cudaqlib/tools/chemistry/pyscf/generators/polarizable_embedded_generator.py index c3f0167..dbc18c3 100644 --- a/python/cudaqlib/tools/chemistry/pyscf/generators/polarizable_embedded_generator.py +++ b/python/cudaqlib/tools/chemistry/pyscf/generators/polarizable_embedded_generator.py @@ -92,7 +92,7 @@ def get_spin_hamiltonian(self,xyz:str, potfile:str, spin:int, charge: int, basis print( 'WARN: UHF is not implemented yet for PE model in Cudaq. RHF & ROHF are only supported.' ) - + energies = {} ################################ @@ -127,8 +127,8 @@ def get_spin_hamiltonian(self,xyz:str, potfile:str, spin:int, charge: int, basis print('[Pyscf] Total HF energy with solvent:', mf_pe.e_tot) print('[Pyscf] Polarizable embedding energy from HF: ', mf_pe.with_solvent.e) - - energies['hf_energy'] = mf_pe.e_tot + + energies['hf_energy'] = mf_pe.e_tot dm = mf_pe.make_rdm1() @@ -147,7 +147,7 @@ def get_spin_hamiltonian(self,xyz:str, potfile:str, spin:int, charge: int, basis print('[pyscf] R-MP2 energy with solvent= ', mymp.e_tot) print('[Pyscf] Polarizable embedding energy from MP: ', mymp.with_solvent.e) - energies['r-mp2'] = mymp.e_tot + energies['r-mp2'] = mymp.e_tot energies['pe-mp2-energy'] = mymp.with_solvent.e if integrals_natorb or natorb: @@ -176,7 +176,7 @@ def get_spin_hamiltonian(self,xyz:str, potfile:str, spin:int, charge: int, basis print( '[pyscf] CASCI energy (using natural orbitals) with solvent= ', mycasci.e_tot) - energies['casci-natorb'] = mycasci.e_tot + energies['casci-natorb'] = mycasci.e_tot else: mycasci = mcscf.CASCI(mf_pe, norb_cas, nele_cas) @@ -205,7 +205,7 @@ def get_spin_hamiltonian(self,xyz:str, potfile:str, spin:int, charge: int, basis mycc.e_tot) print('[Pyscf] Polarizable embedding energy from CCSD: ', mycc.with_solvent.e) - + energies['ccsd-mo'] = mycc.e_tot energies['pe-ccsd-energy'] = mycc.with_solvent.e @@ -292,25 +292,18 @@ def get_spin_hamiltonian(self,xyz:str, potfile:str, spin:int, charge: int, basis obi, tbi, e_nn = self.generate_molecular_spin_ham_restricted( h1e, h2e, nuclear_repulsion) - # Dump obi and tbi to binary file. - if cache: - obi.astype(complex).tofile(f'{filename}_one_body.dat') - tbi.astype(complex).tofile(f'{filename}_two_body.dat') - # Compute the PE contribution to the Hamiltonian dm = mf_pe.make_rdm1() mype = PolEmbed(mol, potfile) E_pe, V_pe, V_es, V_ind = mype.get_pe_contribution(dm) - energies['pe-energy'] = E_pe + energies['pe-energy'] = E_pe # convert V_pe from atomic orbital to molecular orbital representation V_pe_mo = reduce(np.dot, (mf_pe.mo_coeff.T, V_pe, mf_pe.mo_coeff)) obi_pe = self.generate_pe_spin_ham_restricted(V_pe_mo) - if cache: - obi_pe.astype(complex).tofile(f'{filename}_pe_one_body.dat') - # V_pe_mo.asttype(complex).tofile(f'{filename}_v_pe_mo.dat') + energies['nuclear_energy'] = e_nn metadata = { 'num_electrons': nelec, @@ -318,17 +311,20 @@ def get_spin_hamiltonian(self,xyz:str, potfile:str, spin:int, charge: int, basis 'nuclear_energy': e_nn, 'hf_energy': mf_pe.e_tot, 'energies': energies, - 'operators': { - f'{filename}_pe_one_body.dat': 'pe_obi', - f'{filename}_one_body.dat': 'obi', - f'{filename}_two_body.dat': 'tbi' + 'hpq': { + 'data': [(x.real, x.imag) + for x in obi.astype(complex).flatten().tolist()] + }, + 'hpqrs': { + 'data': [(x.real, x.imag) + for x in tbi.astype(complex).flatten().tolist()] } } if cache: with open(f'{filename}_metadata.json', 'w') as f: json.dump(metadata, f) - return (obi, tbi, nuclear_repulsion, obi_pe, nelec, norb) + return metadata if integrals_natorb: mc = mcscf.CASCI(mf_pe, norb_cas, nele_cas) @@ -340,11 +336,6 @@ def get_spin_hamiltonian(self,xyz:str, potfile:str, spin:int, charge: int, basis obi, tbi, core_energy = self.generate_molecular_spin_ham_restricted( h1e_cas, h2e_cas, ecore) - # Dump obi and tbi to binary file. - if cache: - obi.astype(complex).tofile(f'{filename}_one_body.dat') - tbi.astype(complex).tofile(f'{filename}_two_body.dat') - if casci: dm = mcscf.make_rdm1(mycasci) @@ -360,12 +351,9 @@ def get_spin_hamiltonian(self,xyz:str, potfile:str, spin:int, charge: int, basis mycasci.ncore:mycasci.ncore + mycasci.ncas] obi_pe = self.generate_pe_spin_ham_restricted(V_pe_cas) - if cache: - obi_pe.astype(complex).tofile( - f'{filename}_pe_one_body.dat') - energies['core-energy'] = ecore - energies['pe-energy'] = E_pe + energies['core_energy'] = ecore + energies['pe-energy'] = E_pe metadata = { 'num_electrons': nele_cas, 'num_orbitals': norb_cas, @@ -373,17 +361,22 @@ def get_spin_hamiltonian(self,xyz:str, potfile:str, spin:int, charge: int, basis 'pe_energy': E_pe, 'hf_energy': mf_pe.e_tot, 'energies': energies, - 'operators': { - f'{filename}_pe_one_body.dat': 'pe_obi', - f'{filename}_one_body.dat': 'obi', - f'{filename}_two_body.dat': 'tbi' + 'hpq': { + 'data': + [(x.real, x.imag) + for x in obi.astype(complex).flatten().tolist()] + }, + 'hpqrs': { + 'data': + [(x.real, x.imag) + for x in tbi.astype(complex).flatten().tolist()] } } if cache: with open(f'{filename}_metadata.json', 'w') as f: json.dump(metadata, f) - return (obi, tbi, ecore, obi_pe, nele_cas, norb_cas) + return metadata raise ValueError('You should use casci=True.') @@ -410,12 +403,8 @@ def get_spin_hamiltonian(self,xyz:str, potfile:str, spin:int, charge: int, basis V_pe_cas = V_pe_mo[mycas.ncore:mycas.ncore + mycas.ncas, mycas.ncore:mycas.ncore + mycas.ncas] obi_pe = self.generate_pe_spin_ham_restricted(V_pe_cas) - if cache: - obi_pe.astype(complex).tofile(f'{filename}_pe_one_body.dat') - obi.astype(complex).tofile(f'{filename}_one_body.dat') - tbi.astype(complex).tofile(f'{filename}_two_body.dat') - energies ['pe-energy'] = E_pe - energies['core-energy'] = ecore + energies['pe-energy'] = E_pe + energies['core_energy'] = ecore metadata = { 'num_electrons': nele_cas, 'num_orbitals': norb_cas, @@ -423,17 +412,20 @@ def get_spin_hamiltonian(self,xyz:str, potfile:str, spin:int, charge: int, basis 'pe_energy': E_pe, 'hf_energy': mf_pe.e_tot, 'energies': energies, - 'operators': { - f'{filename}_pe_one_body.dat': 'pe_obi', - f'{filename}_one_body.dat': 'obi', - f'{filename}_two_body.dat': 'tbi' + 'hpq': { + 'data': [(x.real, x.imag) + for x in obi.astype(complex).flatten().tolist()] + }, + 'hpqrs': { + 'data': [(x.real, x.imag) + for x in tbi.astype(complex).flatten().tolist()] } } if cache: with open(f'{filename}_metadata.json', 'w') as f: json.dump(metadata, f) - return (obi, tbi, ecore, obi_pe, nele_cas, norb_cas) + return metadata mc = mcscf.CASCI(mf_pe, norb_cas, nele_cas) h1e_cas, ecore = mc.get_h1eff(mf_pe.mo_coeff) @@ -447,7 +439,6 @@ def get_spin_hamiltonian(self,xyz:str, potfile:str, spin:int, charge: int, basis # Compute the PE contribution to the Hamiltonian mype = PolEmbed(mol, potfile) E_pe, V_pe, V_es, V_ind = mype.get_pe_contribution(dm) - print('TESTING HERE, ', V_pe) #convert from ao to mo V_pe_mo = reduce(np.dot, (mf_pe.mo_coeff.T, V_pe, mf_pe.mo_coeff)) @@ -455,15 +446,9 @@ def get_spin_hamiltonian(self,xyz:str, potfile:str, spin:int, charge: int, basis V_pe_cas = V_pe_mo[mc.ncore:mc.ncore + mc.ncas, mc.ncore:mc.ncore + mc.ncas] obi_pe = self.generate_pe_spin_ham_restricted(V_pe_cas) - if cache: - obi.astype(complex).tofile(f'{filename}_one_body.dat') - tbi.astype(complex).tofile(f'{filename}_two_body.dat') - obi_pe.astype(complex).tofile(f'{filename}_pe_one_body.dat') - V_pe.astype(complex).tofile(f'{filename}_vpe.dat') - mf_pe.mo_coeff.astype(complex).tofile(f'{filename}_mo_coeff.dat') energies['pe-energy'] = E_pe - energies['core-energy'] = ecore + energies['core_energy'] = ecore metadata = { 'num_electrons': nele_cas, 'num_orbitals': norb_cas, @@ -471,19 +456,19 @@ def get_spin_hamiltonian(self,xyz:str, potfile:str, spin:int, charge: int, basis 'pe_energy': E_pe, 'hf_energy': mf_pe.e_tot, 'energies': energies, - 'operators': { - f'{filename}_pe_one_body.dat': 'pe_obi', - f'{filename}_one_body.dat': 'obi', - f'{filename}_two_body.dat': 'tbi', - f'{filename}_mo_coeff.dat': 'pe_mo_coeff_obi', - f'{filename}_vpe.dat': 'pe_vpe_obi' + 'hpq': { + 'data': [(x.real, x.imag) + for x in obi.astype(complex).flatten().tolist()] + }, + 'hpqrs': { + 'data': [(x.real, x.imag) + for x in tbi.astype(complex).flatten().tolist()] } } if cache: with open(f'{filename}_metadata.json', 'w') as f: json.dump(metadata, f) - - return (obi, tbi, ecore, obi_pe, nele_cas, norb_cas) + return metadata def generate(self, xyz, basis, **kwargs): requiredOptions = ['potfile', 'spin', 'charge'] diff --git a/python/tests/test_operators.py b/python/tests/test_operators.py index 1585e26..e600cd1 100644 --- a/python/tests/test_operators.py +++ b/python/tests/test_operators.py @@ -12,7 +12,6 @@ import numpy as np import cudaq, cudaqlib -from cudaq import spin def test_operators(): geometry = [('H', (0., 0., 0.)), ('H', (0., 0., .7474))] diff --git a/python/tests/test_pyscf_tool.py b/python/tests/test_pyscf_tool.py index 12a192f..f72c9ee 100644 --- a/python/tests/test_pyscf_tool.py +++ b/python/tests/test_pyscf_tool.py @@ -22,9 +22,10 @@ def test_gas_phase(): ccsd=True, verbose=True, cache=False) - assert np.isclose(1.058354, data[2], rtol=1e-6) - assert data[3] == 4 - assert data[4] == 6 + print(data['num_orbitals'], data['num_electrons']) + assert np.isclose(1.058354, data['energies']['nuclear_energy'], rtol=1e-6) + assert data['num_electrons'] == 4 + assert data['num_orbitals'] == 6 def test_gas_phase_active_space(): @@ -41,9 +42,10 @@ def test_gas_phase_active_space(): casscf=True, verbose=True, cache=False) - assert np.isclose(-96.32874, data[2], rtol=1e-3) - assert data[3] == 6 - assert data[4] == 6 + print(data['energies']) + assert np.isclose(-96.32874, data['energies']['core_energy'], rtol=1e-3) + assert data['num_electrons'] == 6 + assert data['num_orbitals'] == 6 def test_gas_phase_active_space_cudaq(): @@ -61,6 +63,7 @@ def test_gas_phase_active_space_cudaq(): casscf=True) print(molecule) + print(molecule.energies) assert molecule.n_electrons == 6 assert molecule.n_orbitals == 6 assert np.isclose(-107.49999, molecule.energies['hf_energy'], atol=1e-3) @@ -78,9 +81,10 @@ def test_pyscf_pe(): verbose=True, cache=False) - assert np.isclose(31.23082, data[2], rtol=1e-6) - assert data[4] == 16 - assert data[5] == 12 + print(data['energies']) + assert np.isclose(31.23082, data['energies']['nuclear_energy'], rtol=1e-6) + assert data['num_electrons'] == 16 + assert data['num_orbitals'] == 12 def test_pyscf_pe_active_space(): @@ -98,9 +102,10 @@ def test_pyscf_pe_active_space(): verbose=True, cache=False) - assert np.isclose(-101.419971, data[2], rtol=1e-6) - assert data[4] == 6 - assert data[5] == 6 + print(data['energies']) + assert np.isclose(-101.419971, data['energies']['core_energy'], rtol=1e-6) + assert data['num_electrons'] == 6 + assert data['num_orbitals'] == 6 def test_pyscf_cppe(): diff --git a/tests/operators/OperatorsTester.cpp b/tests/operators/OperatorsTester.cpp index d72d8b8..6fabe9f 100644 --- a/tests/operators/OperatorsTester.cpp +++ b/tests/operators/OperatorsTester.cpp @@ -10,8 +10,8 @@ #include #include -#include "cudaqlib/operators.h" #include "cudaq.h" +#include "cudaqlib/operators.h" std::vector> h2_hpq_data{ -1.24884680e+00, 0.00000000e+00, -9.24110683e-17, 0.00000000e+00, @@ -393,11 +393,11 @@ TEST(OperatorsTester, checkJordanWigner) { TEST(OperatorsTester, checkMolecule) { cudaq::operators::molecular_geometry geometry{{"H", {0., 0., 0.}}, {"H", {0., 0., .7474}}}; - auto molecule = cudaq::operators::create_molecule(geometry, "sto-3g", 0, 0, - {.driver="RESTPySCFDriver",.verbose = true}); + auto molecule = cudaq::operators::create_molecule( + geometry, "sto-3g", 0, 0, {.casci = true, .verbose = true}); molecule.hamiltonian.dump(); - // EXPECT_NEAR(molecule.fci_energy, -1.137, 1e-3); + EXPECT_NEAR(molecule.energies["fci_energy"], -1.137, 1e-3); EXPECT_NEAR(molecule.energies["hf_energy"], -1.1163255644, 1e-3); EXPECT_EQ(molecule.n_electrons, 2); EXPECT_EQ(molecule.n_orbitals, 2); diff --git a/tools/chemistry/cudaq-pyscf.py b/tools/chemistry/cudaq-pyscf.py index 6f9bfba..ecbac83 100755 --- a/tools/chemistry/cudaq-pyscf.py +++ b/tools/chemistry/cudaq-pyscf.py @@ -93,7 +93,8 @@ def iter_namespace(ns_pkg): k: v for (k, v) in vars(args).items() if k not in filterArgs } - hamiltonianGenerator.generate(args.xyz, args.basis, **filteredArgs) + res = hamiltonianGenerator.generate(args.xyz, args.basis, **filteredArgs) + print(res) exit(0) @@ -106,20 +107,8 @@ async def shutdown(): return Response(status_code=200, content='Server shutting down...') -Complex = Annotated[ - complex, - PlainValidator(lambda x: x if isinstance(x, complex) else complex( - x.real, x.imag)), - PlainSerializer(lambda x: (x.real, x.imag), return_type=tuple)] - - class IntegralsData(BaseModel): - data: List[Complex] - - @classmethod - def from_numpy(cls, array: np.ndarray): - return cls(data=array.flatten().tolist()) - + data: List[List] class MoleculeInput(BaseModel): @@ -172,11 +161,11 @@ async def create_molecule(molecule: MoleculeInput): filteredArgs['cache_data'] = False res = hamiltonianGenerator.generate(molecule.xyz, molecule.basis, **filteredArgs) - return Molecule(energies=res[-1]['energies'], - num_orbitals=res[-1]['num_orbitals'], - num_electrons=res[-1]['num_electrons'], - hpq=IntegralsData.from_numpy(res[0]), - hpqrs=IntegralsData.from_numpy(res[1])) + return Molecule(energies=res['energies'], + num_orbitals=res['num_orbitals'], + num_electrons=res['num_electrons'], + hpq=IntegralsData(data=res['hpq']['data']), + hpqrs=IntegralsData(data=res['hpqrs']['data'])) if __name__ == "__main__": From bd533ee4523426c3050bec657ec658339d2c29cd Mon Sep 17 00:00:00 2001 From: Alex McCaskey Date: Thu, 25 Jul 2024 18:22:40 +0000 Subject: [PATCH 3/6] clang format Signed-off-by: Alex McCaskey --- cudaqlib/gse.h | 5 ++--- cudaqlib/gse/adapt/adapt.h | 7 ++++--- cudaqlib/gse/utils/pools/spin_complement_gsd.cpp | 1 - cudaqlib/operators/chemistry/MoleculePackageDriver.h | 2 +- cudaqlib/operators/chemistry/molecule.h | 4 ++-- cudaqlib/operators/fermion/fermion_to_spin.h | 1 - cudaqlib/optim/optimizer.h | 2 +- cudaqlib/utils/extension_point.h | 2 +- cudaqlib/utils/library_utils.h | 2 +- tests/gse/AdaptTester.cpp | 2 +- tests/gse/VQETester.cpp | 2 +- tests/optim/OptimTester.cpp | 2 +- 12 files changed, 15 insertions(+), 17 deletions(-) diff --git a/cudaqlib/gse.h b/cudaqlib/gse.h index 774b76b..6a35bda 100644 --- a/cudaqlib/gse.h +++ b/cudaqlib/gse.h @@ -9,8 +9,7 @@ #pragma once #include "gse/adapt/adapt.h" -#include "gse/vqe/vqe.h" #include "gse/utils/operator_pool.h" -#include "gse/utils/pools/uccsd_pool.h" #include "gse/utils/pools/spin_complement_gsd.h" - +#include "gse/utils/pools/uccsd_pool.h" +#include "gse/vqe/vqe.h" diff --git a/cudaqlib/gse/adapt/adapt.h b/cudaqlib/gse/adapt/adapt.h index 51d9f40..25d93fb 100644 --- a/cudaqlib/gse/adapt/adapt.h +++ b/cudaqlib/gse/adapt/adapt.h @@ -35,8 +35,8 @@ struct AdaptKernel { template auto adapt_vqe(const InitialState &initialState, const spin_op &H, - const std::vector &poolList, optim::optimizer &optimizer, - observe_gradient *gradient, + const std::vector &poolList, + optim::optimizer &optimizer, observe_gradient *gradient, const adapt_options options = adapt_options()) { AdaptKernel kernel; @@ -112,7 +112,8 @@ auto adapt_vqe(const InitialState &initialState, const spin_op &H, template auto adapt_vqe(const InitialState &initialState, const spin_op &H, - const std::vector &operatorPool, optim::optimizer &optimizer, + const std::vector &operatorPool, + optim::optimizer &optimizer, const adapt_options options = adapt_options()) { return adapt_vqe(initialState, H, operatorPool, optimizer, nullptr, options); } diff --git a/cudaqlib/gse/utils/pools/spin_complement_gsd.cpp b/cudaqlib/gse/utils/pools/spin_complement_gsd.cpp index 144dc50..6a5d10e 100644 --- a/cudaqlib/gse/utils/pools/spin_complement_gsd.cpp +++ b/cudaqlib/gse/utils/pools/spin_complement_gsd.cpp @@ -19,7 +19,6 @@ std::vector spin_complement_gsd::generate( auto numOrbitals = std::any_cast(iter->second); - std::vector pool; auto numQubits = 2 * numOrbitals; std::vector alphaOrbs, betaOrbs; diff --git a/cudaqlib/operators/chemistry/MoleculePackageDriver.h b/cudaqlib/operators/chemistry/MoleculePackageDriver.h index 181d176..d0f9735 100644 --- a/cudaqlib/operators/chemistry/MoleculePackageDriver.h +++ b/cudaqlib/operators/chemistry/MoleculePackageDriver.h @@ -33,7 +33,7 @@ class MoleculePackageDriver : public extension_point { CUDAQ_DEFINE_EXTENSION_IMPL(MoleculePackageDriver) -#define CUDAQ_REGISTER_MOLECULEPACKAGEDRIVER(TYPE) \ +#define CUDAQ_REGISTER_MOLECULEPACKAGEDRIVER(TYPE) \ static inline const std::string class_identifier = #TYPE; \ static std::unique_ptr create() { \ return std::make_unique(); \ diff --git a/cudaqlib/operators/chemistry/molecule.h b/cudaqlib/operators/chemistry/molecule.h index 396b394..1b72c5f 100644 --- a/cudaqlib/operators/chemistry/molecule.h +++ b/cudaqlib/operators/chemistry/molecule.h @@ -8,8 +8,8 @@ #pragma once -#include "cudaqlib/operators/fermion/fermion_op.h" #include "cudaq/spin_op.h" +#include "cudaqlib/operators/fermion/fermion_op.h" #include @@ -39,7 +39,7 @@ class molecular_geometry { auto begin() const { return atoms.cbegin(); }; auto end() const { return atoms.cend(); } std::string name() const; - static molecular_geometry from_xyz(const std::string& xyzFile); + static molecular_geometry from_xyz(const std::string &xyzFile); }; /// @brief The `molecular_hamiltonian` type holds all the pertinent diff --git a/cudaqlib/operators/fermion/fermion_to_spin.h b/cudaqlib/operators/fermion/fermion_to_spin.h index dd90262..8b1d1a4 100644 --- a/cudaqlib/operators/fermion/fermion_to_spin.h +++ b/cudaqlib/operators/fermion/fermion_to_spin.h @@ -23,7 +23,6 @@ class fermion_to_spin : public extension_point { /// generate an equivalent operator on spins. virtual spin_op generate(const fermion_op &fermionOp) = 0; virtual ~fermion_to_spin() {} - }; CUDAQ_DEFINE_EXTENSION_IMPL(fermion_to_spin) diff --git a/cudaqlib/optim/optimizer.h b/cudaqlib/optim/optimizer.h index e0ed1c9..8d80f0b 100644 --- a/cudaqlib/optim/optimizer.h +++ b/cudaqlib/optim/optimizer.h @@ -139,7 +139,7 @@ class optimizer : public extension_point { CUDAQ_DEFINE_EXTENSION_IMPL(optimizer) -#define CUDAQ_REGISTER_OPTIMIZER(TYPE) \ +#define CUDAQ_REGISTER_OPTIMIZER(TYPE) \ static inline const std::string class_identifier = #TYPE; \ static std::unique_ptr create() { \ return std::make_unique(); \ diff --git a/cudaqlib/utils/extension_point.h b/cudaqlib/utils/extension_point.h index e4a9d41..d921092 100644 --- a/cudaqlib/utils/extension_point.h +++ b/cudaqlib/utils/extension_point.h @@ -48,7 +48,7 @@ class extension_point { #define CONCAT(a, b) CONCAT_INNER(a, b) #define CONCAT_INNER(a, b) a##b -#define CUDAQ_DEFINE_EXTENSION_IMPL(TYPE) \ +#define CUDAQ_DEFINE_EXTENSION_IMPL(TYPE) \ namespace details { \ template \ class CONCAT(TYPE, _impl) : public TYPE { \ diff --git a/cudaqlib/utils/library_utils.h b/cudaqlib/utils/library_utils.h index 86151cf..1319a86 100644 --- a/cudaqlib/utils/library_utils.h +++ b/cudaqlib/utils/library_utils.h @@ -56,4 +56,4 @@ inline static std::string getCUDAQLibraryPath() { return data.path; } -} // namespace cudaq::__internal__ +} // namespace cudaqlib::__internal__ diff --git a/tests/gse/AdaptTester.cpp b/tests/gse/AdaptTester.cpp index 62d421f..8c94aca 100644 --- a/tests/gse/AdaptTester.cpp +++ b/tests/gse/AdaptTester.cpp @@ -9,8 +9,8 @@ #include #include -#include "cudaqlib/gse.h" #include "cudaq.h" +#include "cudaqlib/gse.h" TEST(GSETester, checkSimpleAdapt) { diff --git a/tests/gse/VQETester.cpp b/tests/gse/VQETester.cpp index 4270489..4a3b8a7 100644 --- a/tests/gse/VQETester.cpp +++ b/tests/gse/VQETester.cpp @@ -9,8 +9,8 @@ #include #include -#include "cudaqlib/gse.h" #include "cudaq.h" +#include "cudaqlib/gse.h" TEST(GSETester, checkVqe) { diff --git a/tests/optim/OptimTester.cpp b/tests/optim/OptimTester.cpp index ed07354..a49855f 100644 --- a/tests/optim/OptimTester.cpp +++ b/tests/optim/OptimTester.cpp @@ -9,8 +9,8 @@ #include #include -#include "cudaqlib/optim.h" #include "cudaq.h" +#include "cudaqlib/optim.h" TEST(OptimTester, checkLBFGS) { From 9524c93cbdf31593ba4c888ddef7ab9bdda79b80 Mon Sep 17 00:00:00 2001 From: Alex McCaskey Date: Thu, 25 Jul 2024 18:24:05 +0000 Subject: [PATCH 4/6] fix error Signed-off-by: Alex McCaskey --- .github/workflows/build_and_test.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build_and_test.yml b/.github/workflows/build_and_test.yml index ac3cde4..8f24abb 100644 --- a/.github/workflows/build_and_test.yml +++ b/.github/workflows/build_and_test.yml @@ -34,5 +34,5 @@ jobs: --build-arg="repo=${{github.event.pull_request.head.repo.full_name}}" -t cudaqlib-dev:local -f docker/ci/Dockerfile . - name: Run tests - run: docker run --rm cudaqlib-dev:local ctest --output-on-failure --test-dir cudaqlib/build - run: docker run --rm cudaqlib-dev:local python3 -m pytest cudaqlib/python/tests -v \ No newline at end of file + run: docker run --rm cudaqlib-dev:local ctest --output-on-failure --test-dir cudaqlib/build \ + && docker run --rm cudaqlib-dev:local python3 -m pytest cudaqlib/python/tests -v \ No newline at end of file From 754e5231f89030cfe76116b07839c2b69d7b5fe0 Mon Sep 17 00:00:00 2001 From: Alex McCaskey Date: Thu, 25 Jul 2024 18:29:02 +0000 Subject: [PATCH 5/6] cleanup Signed-off-by: Alex McCaskey --- cudaqlib/operators/CMakeLists.txt | 2 +- cudaqlib/operators/fermion/fermion_op.cpp | 14 -------------- cudaqlib/operators/fermion/fermion_op.h | 2 -- 3 files changed, 1 insertion(+), 17 deletions(-) diff --git a/cudaqlib/operators/CMakeLists.txt b/cudaqlib/operators/CMakeLists.txt index 3e098ef..2dd862d 100644 --- a/cudaqlib/operators/CMakeLists.txt +++ b/cudaqlib/operators/CMakeLists.txt @@ -31,7 +31,7 @@ target_include_directories(${LIBRARY_NAME} $ $) -target_link_libraries(${LIBRARY_NAME} PUBLIC cudaq::cudaq cudaq::cudaq-common) +target_link_libraries(${LIBRARY_NAME} PUBLIC cudaq::cudaq) install( TARGETS ${LIBRARY_NAME} diff --git a/cudaqlib/operators/fermion/fermion_op.cpp b/cudaqlib/operators/fermion/fermion_op.cpp index c36bd2a..4e23ded 100644 --- a/cudaqlib/operators/fermion/fermion_op.cpp +++ b/cudaqlib/operators/fermion/fermion_op.cpp @@ -19,12 +19,6 @@ one_body_integrals::one_body_integrals(const std::vector &shape) new std::complex[shape[0] * shape[1]]); } -void one_body_integrals::add(const std::vector> &data) { - auto *local = unOwnedData == nullptr ? ownedData.get() : unOwnedData; - xt::adapt(local, shape[0] * shape[1], xt::no_ownership(), shape) += - xt::adapt(data.data(), shape[0] * shape[1], xt::no_ownership(), shape); -} - void one_body_integrals::set_data( const std::vector> &data) { std::complex *ptr = nullptr; @@ -47,14 +41,6 @@ void one_body_integrals::dump() { << '\n'; } -void two_body_integrals::add(const std::vector> &data) { - auto *local = unOwnedData == nullptr ? ownedData.get() : unOwnedData; - xt::adapt(local, shape[0] * shape[1] * shape[2] * shape[3], - xt::no_ownership(), shape) += - xt::adapt(data.data(), shape[0] * shape[1] * shape[2] * shape[3], - xt::no_ownership(), shape); -} - two_body_integrals::two_body_integrals(const std::vector &shape) : shape(shape) { assert(shape.size() == 4); diff --git a/cudaqlib/operators/fermion/fermion_op.h b/cudaqlib/operators/fermion/fermion_op.h index 98d7e23..2e1c62e 100644 --- a/cudaqlib/operators/fermion/fermion_op.h +++ b/cudaqlib/operators/fermion/fermion_op.h @@ -28,7 +28,6 @@ class one_body_integrals { one_body_integrals(const std::vector &shape); std::complex &operator()(std::size_t i, std::size_t j) const; void dump(); - void add(const std::vector> &data); void set_data(const std::vector> &data); std::complex *raw_data() { if (ownedData) @@ -54,7 +53,6 @@ class two_body_integrals { std::complex &operator()(std::size_t p, std::size_t q, std::size_t r, std::size_t s) const; void dump(); - void add(const std::vector> &data); void set_data(const std::vector> &data); std::complex *raw_data() { if (ownedData) From 2b0d3157dc07510fd597343aeed18f13147a401d Mon Sep 17 00:00:00 2001 From: Alex McCaskey Date: Thu, 25 Jul 2024 22:11:35 +0000 Subject: [PATCH 6/6] add one particle op Signed-off-by: Alex McCaskey --- cudaqlib/operators/chemistry/molecule.cpp | 29 +++++++++++++++++++++- python/bindings/operators/py_operators.cpp | 2 ++ tests/operators/OperatorsTester.cpp | 8 ++++++ 3 files changed, 38 insertions(+), 1 deletion(-) diff --git a/cudaqlib/operators/chemistry/molecule.cpp b/cudaqlib/operators/chemistry/molecule.cpp index d7e0585..66c53ed 100644 --- a/cudaqlib/operators/chemistry/molecule.cpp +++ b/cudaqlib/operators/chemistry/molecule.cpp @@ -108,6 +108,33 @@ void molecule_options::dump() { << "\n]\n"; } -spin_op one_particle_op(std::size_t p, std::size_t q) { return spin_op(); } +spin_op one_particle_op(std::size_t p, std::size_t q) { + + if (p == q) + return 0.5 * spin::i(p) - 0.5 * spin::z(p); + + std::complex coeff(0., 1.); + double m = -.25; + if (p > q) { + std::swap(p, q); + coeff = std::conj(coeff); + } + + std::vector z_indices; + for (auto i : cudaq::range((long)p + 1, (long)q)) + z_indices.push_back(i); + + auto parity = spin::z(z_indices.front()); + for (std::size_t i = 1; i < z_indices.size(); i++) { + parity *= spin::z(i); + } + + auto ret = m * spin::x(p) * parity * spin::x(q); + + ret += m * spin::y(p) * parity * spin::y(q); + ret -= coeff * m * spin::y(p) * parity * spin::x(q); + ret += coeff * m * spin::x(p) * parity * spin::y(q); + return ret; +} } // namespace cudaq::operators diff --git a/python/bindings/operators/py_operators.cpp b/python/bindings/operators/py_operators.cpp index fba568d..91d067f 100644 --- a/python/bindings/operators/py_operators.cpp +++ b/python/bindings/operators/py_operators.cpp @@ -80,6 +80,8 @@ void bindOperators(py::module &mod) { .def_readonly("n_electrons", &molecular_hamiltonian::n_electrons) .def_readonly("n_orbitals", &molecular_hamiltonian::n_orbitals); + operators.def("one_particle_op", &one_particle_op, ""); + operators.def( "create_molecule", [](py::list geometry, const std::string basis, int spin, int charge, diff --git a/tests/operators/OperatorsTester.cpp b/tests/operators/OperatorsTester.cpp index 6fabe9f..e4b7216 100644 --- a/tests/operators/OperatorsTester.cpp +++ b/tests/operators/OperatorsTester.cpp @@ -502,4 +502,12 @@ H -0.4691 -0.7570 0.0 // molecule.hamiltonian.dump(); EXPECT_EQ(molecule.n_electrons, 6); EXPECT_EQ(molecule.n_orbitals, 6); +} + +TEST(OperatorsTester, checkOneParticleOp) { + auto op = cudaq::operators::one_particle_op(4, 4); + op.dump(); + + op = cudaq::operators::one_particle_op(2, 4); + op.dump(); } \ No newline at end of file