From 50ee3ee69b753e87ee4c298cf118715c697d2ac1 Mon Sep 17 00:00:00 2001 From: Martin Staley Date: Mon, 1 Nov 2021 22:19:16 -0600 Subject: [PATCH 01/39] A few build-system preliminaries. --- CMakeLists.txt | 1 + cmake/GNDStk_dependencies.cmake | 14 ++++++++++++++ src/GNDStk.hpp | 3 +++ 3 files changed, 18 insertions(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index a33c52da1..860548540 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -42,6 +42,7 @@ target_link_libraries( GNDStk INTERFACE catch-adapter INTERFACE pugixml-adapter INTERFACE nlohmann_json::nlohmann_json + INTERFACE HighFive ) add_executable( json2class.exe diff --git a/cmake/GNDStk_dependencies.cmake b/cmake/GNDStk_dependencies.cmake index 46c409ac9..5b6258457 100644 --- a/cmake/GNDStk_dependencies.cmake +++ b/cmake/GNDStk_dependencies.cmake @@ -34,6 +34,12 @@ FetchContent_Declare(json GIT_SHALLOW true ) +FetchContent_Declare(hdf5 + GIT_REPOSITORY https://github.com/BlueBrain/HighFive.git + GIT_TAG origin/master + GIT_SHALLOW TRUE + ) + FetchContent_GetProperties(json) set(JSON_BuildTests OFF CACHE INTERNAL "") if(NOT json_POPULATED) @@ -41,6 +47,13 @@ if(NOT json_POPULATED) add_subdirectory(${json_SOURCE_DIR} ${json_BINARY_DIR} EXCLUDE_FROM_ALL) endif() +FetchContent_GetProperties(hdf5) +set(HDF5_BuildTests OFF CACHE INTERNAL "") +if(NOT hdf5_POPULATED) + FetchContent_Populate(hdf5) + add_subdirectory(${hdf5_SOURCE_DIR} ${hdf5_BINARY_DIR} EXCLUDE_FROM_ALL) +endif() + FetchContent_Declare( pybind11 GIT_REPOSITORY https://github.com/pybind/pybind11 GIT_TAG v2.6.1 @@ -57,5 +70,6 @@ FetchContent_MakeAvailable( Log pugixml-adapter json + hdf5 pybind11 ) diff --git a/src/GNDStk.hpp b/src/GNDStk.hpp index c665be5ae..601b4556f 100644 --- a/src/GNDStk.hpp +++ b/src/GNDStk.hpp @@ -8,6 +8,9 @@ #include "pugixml.hpp" #include "nlohmann/json.hpp" +#define HIGHFIVE_USE_BOOST OFF +#include +#include #include "Log.hpp" From e4d56ea75d61a4fb8aede0e05370ccb3e128c54f Mon Sep 17 00:00:00 2001 From: Wim Haeck Date: Tue, 2 Nov 2021 11:28:43 -0600 Subject: [PATCH 02/39] Updatong cmake dependencies --- cmake/GNDStk_dependencies.cmake | 20 ++++++++------------ 1 file changed, 8 insertions(+), 12 deletions(-) diff --git a/cmake/GNDStk_dependencies.cmake b/cmake/GNDStk_dependencies.cmake index 5b6258457..3b64e7ace 100644 --- a/cmake/GNDStk_dependencies.cmake +++ b/cmake/GNDStk_dependencies.cmake @@ -34,12 +34,6 @@ FetchContent_Declare(json GIT_SHALLOW true ) -FetchContent_Declare(hdf5 - GIT_REPOSITORY https://github.com/BlueBrain/HighFive.git - GIT_TAG origin/master - GIT_SHALLOW TRUE - ) - FetchContent_GetProperties(json) set(JSON_BuildTests OFF CACHE INTERNAL "") if(NOT json_POPULATED) @@ -47,12 +41,14 @@ if(NOT json_POPULATED) add_subdirectory(${json_SOURCE_DIR} ${json_BINARY_DIR} EXCLUDE_FROM_ALL) endif() -FetchContent_GetProperties(hdf5) -set(HDF5_BuildTests OFF CACHE INTERNAL "") -if(NOT hdf5_POPULATED) - FetchContent_Populate(hdf5) - add_subdirectory(${hdf5_SOURCE_DIR} ${hdf5_BINARY_DIR} EXCLUDE_FROM_ALL) -endif() +FetchContent_Declare(hdf5 + GIT_REPOSITORY https://github.com/BlueBrain/HighFive.git + GIT_TAG origin/master + GIT_SHALLOW TRUE + ) +set( HIGHFIVE_USE_BOOST OFF CACHE INTERNAL "" ) +set( HIGHFIVE_UNIT_TESTS OFF CACHE INTERNAL "" ) +set( HIGHFIVE_EXAMPLES OFF CACHE INTERNAL "" ) FetchContent_Declare( pybind11 GIT_REPOSITORY https://github.com/pybind/pybind11 From fc0c91eb7b142471169da4e939419e6a4ae053df Mon Sep 17 00:00:00 2001 From: Wim Haeck Date: Tue, 2 Nov 2021 16:49:33 -0600 Subject: [PATCH 03/39] Updating CI to get hdf5 installed --- .github/workflows/ContinuousIntegration.yml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/.github/workflows/ContinuousIntegration.yml b/.github/workflows/ContinuousIntegration.yml index 6f987cf69..42b62e842 100644 --- a/.github/workflows/ContinuousIntegration.yml +++ b/.github/workflows/ContinuousIntegration.yml @@ -18,6 +18,12 @@ jobs: build_type: [ Debug, Release ] steps: + - name: Install hdf5 libraries for Linux + if: matrix.os == 'ubuntu-18.04' + run: sudo apt-get install libhdf5-dev + - name: Install hdf5 libraries for MacOS + if: matrix.os == 'macos-10.15' + run: brew install hdf5 - name: which CXX run: | which ${{matrix.cxx}} From 90c38c839915524e10e2c9df0f360a37e155a70b Mon Sep 17 00:00:00 2001 From: Wim Haeck Date: Tue, 2 Nov 2021 16:52:54 -0600 Subject: [PATCH 04/39] Removing compiler definition --- src/GNDStk.hpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/GNDStk.hpp b/src/GNDStk.hpp index 601b4556f..a20fecc4f 100644 --- a/src/GNDStk.hpp +++ b/src/GNDStk.hpp @@ -8,7 +8,6 @@ #include "pugixml.hpp" #include "nlohmann/json.hpp" -#define HIGHFIVE_USE_BOOST OFF #include #include #include "Log.hpp" From 717a4fe0b56f6d072b7e40d988927dcc4b7307a3 Mon Sep 17 00:00:00 2001 From: Martin Staley Date: Sun, 14 Nov 2021 21:42:43 -0700 Subject: [PATCH 05/39] Work-in-progress. Some files aren't finished yet, and will be uploaded in a few days. So, this particular update won't build!! Added broad infrastructure for HDF5 handling... ...Wrapper class ...Assignment operators ...convert() functions ...Constructors ...read() functions ...write() functions Etc. Completed many (not all) HDF5 capabilities. Very basic HDF5 write needs to be smarter (not string-only). HDF5 reading still needs work. Touchups are needed here and there throughout the new HDF5 code. In particular, we need smart, non-string handling. Small tweaks were made to XML and JSON material, for consistency. Some comment changes and other odds and ends. --- autogen/json2class.cpp | 7 +- cmake/unit_testing.cmake | 1 + python/src/definitions.hpp | 2 +- src/GNDStk.hpp | 4 +- src/GNDStk/Component.hpp | 5 +- src/GNDStk/HDF5.hpp | 94 +++++++++++++ src/GNDStk/HDF5/src/assign.hpp | 32 +++++ src/GNDStk/HDF5/src/ctor.hpp | 116 ++++++++++++++++ src/GNDStk/HDF5/src/read.hpp | 155 +++++++++++++++++++++ src/GNDStk/HDF5/src/write.hpp | 89 ++++++++++++ src/GNDStk/HDF5/test/CMakeLists.txt | 18 +++ src/GNDStk/HDF5/test/HDF5.test.cpp | 17 +++ src/GNDStk/JSON.hpp | 1 - src/GNDStk/JSON/src/ctor.hpp | 40 +++++- src/GNDStk/JSON/src/write.hpp | 2 +- src/GNDStk/JSON/test/JSON.test.cpp | 2 +- src/GNDStk/Node.hpp | 2 +- src/GNDStk/Node/src/assign.hpp | 2 +- src/GNDStk/Node/src/detail.hpp | 4 +- src/GNDStk/Node/src/read.hpp | 7 +- src/GNDStk/Node/src/write.hpp | 5 +- src/GNDStk/Tree.hpp | 4 +- src/GNDStk/Tree/src/ctor.hpp | 14 +- src/GNDStk/XML.hpp | 1 - src/GNDStk/XML/src/assign.hpp | 7 +- src/GNDStk/XML/src/ctor.hpp | 43 ++++-- src/GNDStk/XML/test/XML.test.cpp | 2 +- src/GNDStk/convert.hpp | 1 + src/GNDStk/convert/src/HDF5.hpp | 202 ++++++++++++++++++++++++++++ src/GNDStk/utility.hpp | 34 +++-- 30 files changed, 859 insertions(+), 54 deletions(-) create mode 100644 src/GNDStk/HDF5.hpp create mode 100644 src/GNDStk/HDF5/src/assign.hpp create mode 100644 src/GNDStk/HDF5/src/ctor.hpp create mode 100644 src/GNDStk/HDF5/src/read.hpp create mode 100644 src/GNDStk/HDF5/src/write.hpp create mode 100644 src/GNDStk/HDF5/test/CMakeLists.txt create mode 100644 src/GNDStk/HDF5/test/HDF5.test.cpp create mode 100644 src/GNDStk/convert/src/HDF5.hpp diff --git a/autogen/json2class.cpp b/autogen/json2class.cpp index d708d40e4..ff626775a 100644 --- a/autogen/json2class.cpp +++ b/autogen/json2class.cpp @@ -4,7 +4,7 @@ // ----------------------------------------------------------------------------- #include "GNDStk.hpp" -#include "cstring" +#include using namespace njoy::GNDStk::core; // Report cases of nodes that have no metadata, and zero or one child node(s). @@ -478,6 +478,11 @@ void getClassMetadata( }; if (m.defaultValue != "") { // If it has a default, then presumably it isn't required... + // fixme Should print a real, useful error message here. The mistake + // in question is something a user could easily make!! Look at other + // assert()s in this file as well; assert should be more for internal + // sanity checks than for diagnostic messages, as they aren't very + // helpful to typical users. assert(!metaRHS["required"]); } diff --git a/cmake/unit_testing.cmake b/cmake/unit_testing.cmake index 11e3c4532..0874dd594 100644 --- a/cmake/unit_testing.cmake +++ b/cmake/unit_testing.cmake @@ -20,6 +20,7 @@ add_subdirectory( src/GNDStk/string2type/test ) add_subdirectory( src/GNDStk/Meta/test ) add_subdirectory( src/GNDStk/XML/test ) add_subdirectory( src/GNDStk/JSON/test ) +add_subdirectory( src/GNDStk/HDF5/test ) add_subdirectory( src/GNDStk/Node/test ) add_subdirectory( src/GNDStk/keyword/test ) add_subdirectory( src/GNDStk/Child/test ) diff --git a/python/src/definitions.hpp b/python/src/definitions.hpp index 230bd1d99..3534c5a3f 100644 --- a/python/src/definitions.hpp +++ b/python/src/definitions.hpp @@ -45,7 +45,7 @@ void addStandardComponentDefinitions( PythonClass& component ) { return Component( node ); }, python::arg( "string" ), - "Read the component from an XML or json string\n\n" + "Read the component from an XML or JSON string\n\n" "An exception is raised if something goes wrong while reading the\n" "component\n\n" "Arguments:\n" diff --git a/src/GNDStk.hpp b/src/GNDStk.hpp index 601b4556f..0a6cdfba3 100644 --- a/src/GNDStk.hpp +++ b/src/GNDStk.hpp @@ -8,7 +8,6 @@ #include "pugixml.hpp" #include "nlohmann/json.hpp" -#define HIGHFIVE_USE_BOOST OFF #include #include #include "Log.hpp" @@ -66,6 +65,7 @@ namespace GNDStk { // external-library wrappers #include "GNDStk/XML.hpp" #include "GNDStk/JSON.hpp" +#include "GNDStk/HDF5.hpp" // string/Node to/from type #include "GNDStk/string2type.hpp" @@ -99,7 +99,7 @@ namespace GNDStk { #include "GNDStk/node2type.hpp" #include "GNDStk/type2node.hpp" -// xml/json/tree conversions +// XML/JSON/HDF5/Tree conversions #include "GNDStk/convert.hpp" // fixme See above fixme diff --git a/src/GNDStk/Component.hpp b/src/GNDStk/Component.hpp index 942acea86..9abe4a34a 100644 --- a/src/GNDStk/Component.hpp +++ b/src/GNDStk/Component.hpp @@ -87,8 +87,9 @@ class Component : public BodyText } // Component << std::string - // Meaning: read the string's content (currently XML or JSON) into an object - // of the Component's DERIVED class. Uses Node's << std::string capability. + // Meaning: read the string's content (currently XML, JSON, or HDF5) into + // an object of the Component's DERIVED class. Uses Node's << std::string + // capability, which does most of the work. void operator<<(const std::string &str) { try { diff --git a/src/GNDStk/HDF5.hpp b/src/GNDStk/HDF5.hpp new file mode 100644 index 000000000..1b29905cc --- /dev/null +++ b/src/GNDStk/HDF5.hpp @@ -0,0 +1,94 @@ + +// ----------------------------------------------------------------------------- +// HDF5 +// Wraps HighFive::File +// ----------------------------------------------------------------------------- + +class HDF5 { +public: + + // data + HighFive::File *file = nullptr; + std::string filename = "";///perhaps can use file->getName() + mutable bool temporary = false; + +private: + + void removeTemporary() const + { + if (filename != "" && temporary) { + std::ifstream ifs(filename); + if (!ifs) + return; // apparently removed already, so no need to remove + ifs.close(); // prior to remove + if (remove(filename.c_str()) != 0) { + log::error( + "Unable to remove temporary file \"{}\"", filename); + log::member( + "HDF5::removeTemporary(), with filename \"{}\"", filename); + } + } + } + +public: + + // clear + HDF5 &clear() + { + delete file; file = nullptr; + removeTemporary(); + filename = ""; + temporary = false; + return *this; + } + + // empty + bool empty() const + { + return file == nullptr; + } + + // destructor + ~HDF5() + { + delete file; + removeTemporary(); + } + + // constructors, assignment + #include "GNDStk/HDF5/src/ctor.hpp" + #include "GNDStk/HDF5/src/assign.hpp" + + // read, write + #include "GNDStk/HDF5/src/read.hpp" + #include "GNDStk/HDF5/src/write.hpp" + +}; // class HDF5 + + + +// ----------------------------------------------------------------------------- +// I/O +// ----------------------------------------------------------------------------- + +// operator>> +inline std::istream &operator>>(std::istream &is, HDF5 &obj) +{ + try { + return obj.read(is); + } catch (...) { + log::function("istream >> HDF5"); + throw; + } +} + +// operator<< +inline std::ostream &operator<<(std::ostream &os, const HDF5 &obj) +{ + try { + return obj.write(os); + } catch (...) { + log::function("ostream << HDF5"); + throw; + } +} diff --git a/src/GNDStk/HDF5/src/assign.hpp b/src/GNDStk/HDF5/src/assign.hpp new file mode 100644 index 000000000..b3df8d1f1 --- /dev/null +++ b/src/GNDStk/HDF5/src/assign.hpp @@ -0,0 +1,32 @@ + +// ----------------------------------------------------------------------------- +// HDF5 Assignment +// ----------------------------------------------------------------------------- + +// move +HDF5 &operator=(HDF5 &&other) +{ + clear(); + file = std::move(other.file); + filename = std::move(other.filename); + temporary = std::move(other.temporary); + + other.file = nullptr; + other.filename = ""; + other.temporary = false; + + return *this; +} + +// copy +HDF5 &operator=(const HDF5 &other) +{ + try { + if (!convert(other,*this)) + throw std::exception{}; + } catch (...) { + log::assign("HDF5 = HDF5"); + throw; + } + return *this; +} diff --git a/src/GNDStk/HDF5/src/ctor.hpp b/src/GNDStk/HDF5/src/ctor.hpp new file mode 100644 index 000000000..2fd76437a --- /dev/null +++ b/src/GNDStk/HDF5/src/ctor.hpp @@ -0,0 +1,116 @@ + +// ----------------------------------------------------------------------------- +// HDF5 Constructors +// ----------------------------------------------------------------------------- + +// ------------------------ +// Basics +// ------------------------ + +// default +HDF5() { } + +// move +HDF5(HDF5 &&other) : + file(std::move(other.file)), + filename(std::move(other.filename)), + temporary(std::move(other.temporary)) +{ + other.file = nullptr; + other.filename = ""; + other.temporary = false; +} + +// copy +HDF5(const HDF5 &other) +{ + try { + if (!convert(other,*this)) + throw std::exception{}; + } catch (...) { + log::ctor("HDF5(HDF5)"); + throw; + } +} + + +// ------------------------ +// From other classes +// ------------------------ + +// From XML +explicit HDF5(const XML &x) +{ + try { + if (!convert(x,*this)) + throw std::exception{}; + } catch (...) { + log::ctor("HDF5(XML)"); + throw; + } +} + +// From JSON +explicit HDF5(const JSON &j) +{ + try { + if (!convert(j,*this)) + throw std::exception{}; + } catch (...) { + log::ctor("HDF5(JSON)"); + throw; + } +} + +// From Node +explicit HDF5(const Node &n) +{ + try { + if (!convert(n,*this)) + throw std::exception{}; + } catch (...) { + log::ctor("HDF5(Node)"); + throw; + } +} + +// From Tree +explicit HDF5(const Tree &t) +{ + try { + if (!convert(t,*this)) + throw std::exception{}; + } catch (...) { + log::ctor("HDF5(Tree)"); + throw; + } +} + + +// ------------------------ +// From file and istream +// ------------------------ + +// From file +explicit HDF5(const std::string &filename) +{ + try { + if (!read(filename)) + throw std::exception{}; + } catch (...) { + log::ctor("HDF5(\"{}\")", filename); + throw; + } +} + +// From istream +explicit HDF5(std::istream &is) +{ + try { + if (!read(is)) + throw std::exception{}; + } catch (...) { + log::ctor("HDF5(istream)"); + throw; + } +} diff --git a/src/GNDStk/HDF5/src/read.hpp b/src/GNDStk/HDF5/src/read.hpp new file mode 100644 index 000000000..8f85097b5 --- /dev/null +++ b/src/GNDStk/HDF5/src/read.hpp @@ -0,0 +1,155 @@ + +// ----------------------------------------------------------------------------- +// HDF5.read() +// ----------------------------------------------------------------------------- + +/* +DISCUSSION + +While this may seem goofy and inefficient, our read(istream) function actually +transfers the istream's content to a temporary *file*, then calls read(filename) +on the temporary file. That function, in turn, uses the underlying HighFive HDF5 +library's read-from-file capability, in order to do the actual work of reading +HDF5 content into an internal data structure. + +Normally, one might do the reverse: use a read-from-istream as a helper to a +read-from-file, with the latter opening the file as an ifstream, then calling +the former to do the heavy lifting. Indeed, our read-from-file functions for +XML and JSON do just that. + +Here, we did things in the seemingly backwards way for a simple reason: at the +time of this writing, we see no capability in HighFive to read from an istream! +Just to read directly from a file. + +One might ask why we chose to implement this arguably convoluted read-from- +istream at all. Our reason: we're intentionally designing all of our file-format +classes (at present: XML, JSON, and HDF5) to "look and feel" as consistent as +possible with one another. This uniformity helps make the code - for all formats +and throughout GNDStk - to look as consistent as reasonably possible. This helps +with debugging and testing, and gives users a more-uniform interface. +*/ + + +// ----------------------------------------------------------------------------- +// read(istream) +// ----------------------------------------------------------------------------- + +// fixme +// We may want to detect whether or not the istream is in std::ios::binary +// mode. If it isn't, then copying it absolutely correctly, to a temporary +// file, might be problematic. We'll use get() and put(), below, but could +// something like platform-dependent line endings still be a problem? Play +// around with this to see what's what. + +// fixme +// Is there a way to detect if any additional content appears in the istream, +// AFTER the HDF5 content itself? If there is, then - ideally - we should +// truncate the copy-to-temporary-file process after the end of HDF5 content, +// leaving the istream's streampos at that point. (But this situation might +// not realistically arise in practice.) + +std::istream &read(std::istream &is) +{ + // Clear present contents. + clear(); + + // Current stream position. We'll rewind to this point if an error occurs. + const std::streampos pos = is.tellg(); + + // Generate a file name that's suitable for safely creating a temporary file. + // L_tmpnam and tmpnam() are from . In case anyone wonders, we don't + // need a +1 in the [L_tmpnam] here :-). + static char buffer[L_tmpnam]; + filename = tmpnam(buffer); + // fixme Possibly check if tmpnam() is screwy and the file actually exists? + + try { + // Open temporary file. This *should* work, but we check anyway. + std::ofstream ofs(filename, std::ios::binary); + if (!ofs) { + log::error("Unable to open temporary file \"{}\"", filename); + throw std::exception{}; + } + + // Copy bytes from the istream to the temporary file. + char ch; + while (is.get(ch) && ofs) + ofs.put(ch); + ofs.close(); + // fixme Maybe examine/check stream states here. + + // Call read(filename) to read HDF5 content from the temporary file. + // See our detailed discussion above. + if (!read(filename)) + throw std::exception{}; + } catch (...) { + temporary = true; // after read(filename), which makes it false + removeTemporary(); + log::member("HDF5.read(istream) (uses a temporary file)"); + detail::failback(is,pos); + } + + // done + temporary = true; // after read(filename), which makes it false + assert(!is.bad()); + /// assert(!is.fail()); + assert(is.eof()); + ///assert(false); + + // zzz above, we should clear is' flags as long as the *only* problems + // is fail(), *AND* eof() (so that eof is why it failed); I think at + // least that that's correct. + is.clear();///for now + return is; +} + + +// ----------------------------------------------------------------------------- +// read(file name) +// ----------------------------------------------------------------------------- + +// The parameter is intentionally value, not reference, so that it can't +// be surreptitiously set to "" by the clear() call if the actual parameter +// happens to be this->filename - which it *is*, in fact, if this read() +// is called from the above istream read()! (And, although it's unlikely, +// someone could conceivably make such a call directly instead of through +// the above read(), in for example a scenario where the file might have +// changed on disk and someone wants it to be re-read.) We don't run into +// a similar problem with the XML or JSON read()s, not just because their +// read(istream)s don't call their read(file name)s, but also because they +// simply don't, at present, have std::string member data that might be +// aliased by a parameter like name below, so that a clear() accidentally +// clears the parameter. +bool read(const std::string name) +{ + clear(); + filename = name; + bool ret = false; + + // Test that the file can be opened. The HighFive::File(filename) call, + // below, in fact opens and reads the file. This "test open" allows us + // to provide diagnostics that are similar to those that we provide in + // our read() functions for other file formats. Note: if this function's + // name parameter had been by-reference, right here is where we might + // inadvertently have filename == ""; see the earlier remark! + std::ifstream ifs(filename, std::ios::binary); + if (ifs) { + ifs.close(); + try { + file = new HighFive::File(filename, HighFive::File::ReadOnly); + ret = true; // all's well - our "test open" and HighFive's reading + } catch (...) { + log::error("file = HighFive::File(filename, ReadOnly)\n" + "threw an exception"); + } + } else { + log::error("Could not open file \"{}\" for input", filename); + } + + if (!ret) + log::member("HDF5.read(\"{}\")", filename); + + // done + temporary = false; + return ret; +} diff --git a/src/GNDStk/HDF5/src/write.hpp b/src/GNDStk/HDF5/src/write.hpp new file mode 100644 index 000000000..32fe71b06 --- /dev/null +++ b/src/GNDStk/HDF5/src/write.hpp @@ -0,0 +1,89 @@ + +// ----------------------------------------------------------------------------- +// HDF5.write() +// ----------------------------------------------------------------------------- + +// ------------------------ +// write(ostream) +// ------------------------ + +std::ostream &write(std::ostream &os, const bool decl = true) const +{ + (void)decl; // unused + char ch; + + try { + if (empty()) { + static char tempname[L_tmpnam]; + tmpnam(tempname); + + HighFive::File blank( + tempname, + HighFive::File::ReadWrite | + HighFive::File::Create | + HighFive::File::Truncate + ); + blank.flush(); + + std::ifstream ifs(tempname, std::ios::binary); + if (!ifs) { + log::error("Unable to open temporary file \"{}\"", tempname); + throw std::exception{}; + } + while (ifs.get(ch) && os) + os.put(ch); + + ifs.close(); // prior to remove... + if (remove(tempname) != 0) { + log::error("Unable to remove temporary file \"{}\"", tempname); + throw std::exception{}; + } + } else { + std::ifstream ifs(filename, std::ios::binary); + if (!ifs) { + log::error("Unable to open file \"{}\"", filename); + throw std::exception{}; + } + while (ifs.get(ch) && os) + os.put(ch); + } + } catch (...) { + log::member("HDF5.write(ostream)"); + os.setstate(std::ios::failbit); + } + // fixme Maybe examine/check stream states after above copies + + // done + return os; +} + + +// ------------------------ +// write(file name) +// ------------------------ + +bool write(const std::string &filename, const bool decl = true) const +{ + // well, I suppose it's possible... + if (filename == this->filename) { + temporary = false; + return true; + } + + // open file + std::ofstream ofs(filename, std::ios::binary); + if (!ofs) { + log::error("Could not open file \"{}\" for output", filename); + log::member("HDF5.write(\"{}\")", filename); + return false; + } + + // write to ostream + if (!write(ofs,decl)) { + log::member("HDF5.write(\"{}\")", filename); + return false; + } + + // done + return true; +} diff --git a/src/GNDStk/HDF5/test/CMakeLists.txt b/src/GNDStk/HDF5/test/CMakeLists.txt new file mode 100644 index 000000000..1a0b31a76 --- /dev/null +++ b/src/GNDStk/HDF5/test/CMakeLists.txt @@ -0,0 +1,18 @@ + +add_executable( GNDStk.HDF5.test HDF5.test.cpp ) +target_compile_options( GNDStk.HDF5.test PRIVATE ${${PREFIX}_common_flags} +$<$:${${PREFIX}_strict_flags}>$<$: +${${PREFIX}_DEBUG_flags} +$<$:${${PREFIX}_coverage_flags}>> +$<$: +${${PREFIX}_RELEASE_flags} +$<$:${${PREFIX}_link_time_optimization_flags}> +$<$:${${PREFIX}_nonportable_optimization_flags}>> + +${CXX_appended_flags} ${GNDStk_appended_flags} ) +target_link_libraries( GNDStk.HDF5.test PUBLIC GNDStk ) +file( GLOB resources "resources/*" ) +foreach( resource ${resources}) + file( COPY "${resource}" DESTINATION "${CMAKE_CURRENT_BINARY_DIR}" ) +endforeach() +add_test( NAME GNDStk.HDF5 COMMAND GNDStk.HDF5.test ) diff --git a/src/GNDStk/HDF5/test/HDF5.test.cpp b/src/GNDStk/HDF5/test/HDF5.test.cpp new file mode 100644 index 000000000..92a40df51 --- /dev/null +++ b/src/GNDStk/HDF5/test/HDF5.test.cpp @@ -0,0 +1,17 @@ + +#define CATCH_CONFIG_MAIN + +#include "catch.hpp" +#include "GNDStk.hpp" + +using namespace njoy::GNDStk; + +// ----------------------------------------------------------------------------- +// SCENARIO +// ----------------------------------------------------------------------------- + +SCENARIO("Testing GNDStk HDF5") { + + /// fixme adapt code from the corresponding JSON test + +} diff --git a/src/GNDStk/JSON.hpp b/src/GNDStk/JSON.hpp index 571607101..23a8a7444 100644 --- a/src/GNDStk/JSON.hpp +++ b/src/GNDStk/JSON.hpp @@ -23,7 +23,6 @@ class JSON { // easily. This could be hacked in some way, of course, and it's worth noting // that the GNDS document speaks of basically such a hack. -MFS - // external JSON-library document nlohmann::json doc; // clear diff --git a/src/GNDStk/JSON/src/ctor.hpp b/src/GNDStk/JSON/src/ctor.hpp index 68c571014..9823ee32d 100644 --- a/src/GNDStk/JSON/src/ctor.hpp +++ b/src/GNDStk/JSON/src/ctor.hpp @@ -3,6 +3,10 @@ // JSON Constructors // ----------------------------------------------------------------------------- +// ------------------------ +// Basics +// ------------------------ + // default JSON() = default; @@ -10,8 +14,8 @@ JSON() = default; JSON(JSON &&) = default; // copy -JSON(const JSON &j) -try: doc(j.doc) +JSON(const JSON &other) +try: doc(other.doc) { } catch (...) { @@ -19,7 +23,12 @@ catch (...) { throw; } -// XML + +// ------------------------ +// From other classes +// ------------------------ + +// From XML explicit JSON(const XML &x) { try { @@ -31,7 +40,19 @@ explicit JSON(const XML &x) } } -// Node +// From HDF5 +explicit JSON(const HDF5 &h) +{ + try { + if (!convert(h,*this)) + throw std::exception{}; + } catch (...) { + log::ctor("JSON(HDF5)"); + throw; + } +} + +// From Node explicit JSON(const Node &n) { try { @@ -43,7 +64,7 @@ explicit JSON(const Node &n) } } -// Tree +// From Tree explicit JSON(const Tree &t) { try { @@ -55,7 +76,12 @@ explicit JSON(const Tree &t) } } -// file name + +// ------------------------ +// From file and istream +// ------------------------ + +// From file explicit JSON(const std::string &filename) { try { @@ -67,7 +93,7 @@ explicit JSON(const std::string &filename) } } -// istream +// From istream explicit JSON(std::istream &is) { try { diff --git a/src/GNDStk/JSON/src/write.hpp b/src/GNDStk/JSON/src/write.hpp index 6ecc8e0fc..82b9c37cb 100644 --- a/src/GNDStk/JSON/src/write.hpp +++ b/src/GNDStk/JSON/src/write.hpp @@ -9,7 +9,7 @@ std::ostream &write(std::ostream &os, const bool decl = true) const { - (void)decl; // ignored + (void)decl; // unused, for now (some changes may be forthcoming) // call nlohmann::json's write capability try { diff --git a/src/GNDStk/JSON/test/JSON.test.cpp b/src/GNDStk/JSON/test/JSON.test.cpp index d0fa98fad..1dd390a3c 100644 --- a/src/GNDStk/JSON/test/JSON.test.cpp +++ b/src/GNDStk/JSON/test/JSON.test.cpp @@ -188,7 +188,7 @@ SCENARIO("Testing GNDStk JSON") { } } - // from file name + // from file WHEN("We construct a JSON from a file") { const JSON j("n-069_Tm_170-covar.json"); THEN("It should produce an equivalent to the Tree made from the file") { diff --git a/src/GNDStk/Node.hpp b/src/GNDStk/Node.hpp index b52156b09..ec48ef4d4 100644 --- a/src/GNDStk/Node.hpp +++ b/src/GNDStk/Node.hpp @@ -172,7 +172,7 @@ inline std::istream &operator>>(std::istream &is, Node &node) // Node << std::string // Note that this is an INPUT operator to Node! -// Treating the std::string as a "file" with XML, JSON, etc. content, read it +// Treating the std::string as a "file" with XML, JSON, or HDF5 content, read it // into the Node. We return void, not the Node, so users don't incorrectly think // that the < -void node2Node(const NODE &, NODE &); +void node2node(const NODE &, NODE &); diff --git a/src/GNDStk/Node/src/read.hpp b/src/GNDStk/Node/src/read.hpp index 12c1a74c2..964069f67 100644 --- a/src/GNDStk/Node/src/read.hpp +++ b/src/GNDStk/Node/src/read.hpp @@ -6,7 +6,7 @@ // Cases: // // 1. read(istream, FileType) -// 2. read(file name, FileType) calls 1 after making istream from file name +// 2. read(file name, FileType) calls 1 after making istream from file // 3. read(istream, string ) calls 1 after making FileType from string // 4. read(file name, string ) calls 2 after making FileType from string // @@ -157,8 +157,9 @@ std::istream &read( if (!convert(JSON(is), *this, decl)) throw std::exception{}; } else if (format == FileType::hdf5) { - log::error("Node.read() for HDF5 is not implemented yet"); - throw std::exception{}; + // assume HDF5; so, create Node by converting from a temporary HDF5... + if (!convert(HDF5(is), *this, decl)) + throw std::exception{}; } else { // The earlier logic is such that this shouldn't happen; consider // removing at some point diff --git a/src/GNDStk/Node/src/write.hpp b/src/GNDStk/Node/src/write.hpp index d0a585cfe..8116355eb 100644 --- a/src/GNDStk/Node/src/write.hpp +++ b/src/GNDStk/Node/src/write.hpp @@ -12,7 +12,7 @@ // // General cases: // 1. write(ostream, FileType) -// 2. write(file name, FileType) calls 1 after making ostream from file name +// 2. write(file name, FileType) calls 1 after making ostream from file // 3. write(ostream, string ) calls 1 after making FileType from string // 4. write(file name, string ) calls 2 after making FileType from string @@ -136,8 +136,7 @@ std::ostream &write( JSON(*this).write(os,decl); } else if (format == FileType::hdf5) { // write via a temporary hdf5 object... - log::error("Node.write() for HDF5 is not implemented yet"); - throw std::exception{}; + HDF5(*this).write(os,decl); } else { // null or text: use our plain text format return write(os,0); diff --git a/src/GNDStk/Tree.hpp b/src/GNDStk/Tree.hpp index d675c8e1b..def3aea56 100644 --- a/src/GNDStk/Tree.hpp +++ b/src/GNDStk/Tree.hpp @@ -50,8 +50,8 @@ class Tree : public Node { // We pull out top() first, rather than deferring immediately to Node's // operator==, because Tree can contain a "declaration node" that might - // indicate properties such as whether the data came from an XML file or - // a JSON file. Those properties can be put to good use for other things, + // indicate properties such as whether the data came from an XML, JSON, + // or HDF5 file. Those properties can be put to good use for other things, // but won't play a role in a Tree comparison. // operator== diff --git a/src/GNDStk/Tree/src/ctor.hpp b/src/GNDStk/Tree/src/ctor.hpp index 2bbdfcfb2..7a4dc3779 100644 --- a/src/GNDStk/Tree/src/ctor.hpp +++ b/src/GNDStk/Tree/src/ctor.hpp @@ -24,7 +24,7 @@ Tree(const Tree &other) : Node{} // ----------------------------------------------------------------------------- -// From XML and JSON objects +// From XML, JSON, and HDF5 objects // ----------------------------------------------------------------------------- // XML @@ -51,6 +51,18 @@ explicit Tree(const JSON &j) } } +// HDF5 +explicit Tree(const HDF5 &h) +{ + try { + if (!convert(h,*this)) + throw std::exception{}; + } catch (...) { + log::ctor("Tree(HDF5)"); + throw; + } +} + // ----------------------------------------------------------------------------- diff --git a/src/GNDStk/XML.hpp b/src/GNDStk/XML.hpp index 65c4faeed..20d84a722 100644 --- a/src/GNDStk/XML.hpp +++ b/src/GNDStk/XML.hpp @@ -7,7 +7,6 @@ class XML { public: - // external XML-library document pugi::xml_document doc; // clear diff --git a/src/GNDStk/XML/src/assign.hpp b/src/GNDStk/XML/src/assign.hpp index 7389b8a42..1196de3ac 100644 --- a/src/GNDStk/XML/src/assign.hpp +++ b/src/GNDStk/XML/src/assign.hpp @@ -7,11 +7,12 @@ XML &operator=(XML &&) = default; // copy -// Note: pugi::xml_document's is inaccessible -XML &operator=(const XML &x) +// Note: pugi::xml_document's copy assignment is inaccessible; +// otherwise, this could = default. +XML &operator=(const XML &other) { try { - if (!convert(x,*this)) + if (!convert(other,*this)) throw std::exception{}; } catch (...) { log::assign("XML = XML"); diff --git a/src/GNDStk/XML/src/ctor.hpp b/src/GNDStk/XML/src/ctor.hpp index e2e035285..7c94e75b3 100644 --- a/src/GNDStk/XML/src/ctor.hpp +++ b/src/GNDStk/XML/src/ctor.hpp @@ -3,6 +3,10 @@ // XML Constructors // ----------------------------------------------------------------------------- +// ------------------------ +// Basics +// ------------------------ + // default XML() = default; @@ -10,11 +14,12 @@ XML() = default; XML(XML &&) = default; // copy -// Note: pugi::xml_document's is inaccessible -XML(const XML &x) +// Note: pugi::xml_document's copy constructor is inaccessible; otherwise we'd +// use it here, as we do in JSON's copy constructor, instead of using convert(). +XML(const XML &other) { try { - if (!convert(x,*this)) + if (!convert(other,*this)) throw std::exception{}; } catch (...) { log::ctor("XML(XML)"); @@ -22,7 +27,12 @@ XML(const XML &x) } } -// JSON + +// ------------------------ +// From other classes +// ------------------------ + +// From JSON explicit XML(const JSON &j) { try { @@ -34,7 +44,19 @@ explicit XML(const JSON &j) } } -// Node +// From HDF5 +explicit XML(const HDF5 &h) +{ + try { + if (!convert(h,*this)) + throw std::exception{}; + } catch (...) { + log::ctor("XML(HDF5)"); + throw; + } +} + +// From Node explicit XML(const Node &n) { try { @@ -46,7 +68,7 @@ explicit XML(const Node &n) } } -// Tree +// From Tree explicit XML(const Tree &t) { try { @@ -58,7 +80,12 @@ explicit XML(const Tree &t) } } -// file name + +// ------------------------ +// From file and istream +// ------------------------ + +// From file explicit XML(const std::string &filename) { try { @@ -70,7 +97,7 @@ explicit XML(const std::string &filename) } } -// istream +// From istream explicit XML(std::istream &is) { try { diff --git a/src/GNDStk/XML/test/XML.test.cpp b/src/GNDStk/XML/test/XML.test.cpp index a55cba0be..f183743f1 100644 --- a/src/GNDStk/XML/test/XML.test.cpp +++ b/src/GNDStk/XML/test/XML.test.cpp @@ -133,7 +133,7 @@ SCENARIO("Testing GNDStk XML") { } } - // from file name + // from file // Note: Things like this are of course tested indirectly // all over the place. WHEN("We construct an XML from a file") { diff --git a/src/GNDStk/convert.hpp b/src/GNDStk/convert.hpp index 6ba39a5f4..d6f01e99e 100644 --- a/src/GNDStk/convert.hpp +++ b/src/GNDStk/convert.hpp @@ -5,3 +5,4 @@ #include "GNDStk/convert/src/tree.hpp" #include "GNDStk/convert/src/XML.hpp" #include "GNDStk/convert/src/JSON.hpp" +#include "GNDStk/convert/src/HDF5.hpp" diff --git a/src/GNDStk/convert/src/HDF5.hpp b/src/GNDStk/convert/src/HDF5.hpp new file mode 100644 index 000000000..2156c4948 --- /dev/null +++ b/src/GNDStk/convert/src/HDF5.hpp @@ -0,0 +1,202 @@ + +// ----------------------------------------------------------------------------- +// convert(*,HDF5) +// That is, convert to HDF5 objects +// ----------------------------------------------------------------------------- + +// ----------------------------------------------------------------------------- +// Node ==> HDF5 +// ----------------------------------------------------------------------------- + +inline bool convert(const Node &node, HDF5 &h) +{ + // clear + h.clear(); + + // for the HDF5 + static char buffer[L_tmpnam]; + h.filename = tmpnam(buffer); + + static const std::string context = "convert(Node,HDF5)"; + try { + + // Open temporary file. This *should* work, but we check anyway. + std::ofstream ofs(h.filename, std::ios::binary); + if (!ofs) { + log::error("Unable to open temporary file \"{}\"", h.filename); + throw std::exception{}; + } + ofs.close(); + + h.file = new HighFive::File( + h.filename, + HighFive::File::ReadWrite | + HighFive::File::Create | + HighFive::File::Truncate + ); + h.temporary = true; + + // Probably a regular Node + if (node.name != "") { + bool ret = detail::node2hdf5(node,*h.file); + h.file->flush(); + return ret; + } + + // Probably a Tree... + if (node.metadata.size() != 0) { + log::warning( + "Encountered Node with empty name \"\",\n" + "but the Node also contains metadata.\n" + "Not expected in this context. We'll ignore the metadata." + ); + log::function(context); + } + + bool found_decl = false; + bool found_top = false; + + for (auto &c : node.children) { + if (c->name == "xml" || c->name == "json" || c->name == "hdf5") { + // looks like a declaration node + if (found_decl) { + // already seen + log::warning( + "Encountered Node with empty name \"\",\n" + "and > 1 child nodes that look like " + "declaration nodes.\n" + "Not expected in this context. " + "For HDF5, we're ignoring declaration nodes anyway." + ); + log::function(context); + } + found_decl = true; + } else { + // looks like a regular node + /**/ + /// We really need to relax this business about requiring that there + /// be only ONE top-level node. The XML format allows only one + /// document node (and GNDS, probably because of XML, has just one), + /// but JSON and HDF5 allow more (or less!) than one. And we're + /// going to be writing the NDI3 format with this code; it shouldn't + /// have this limitation. + /**/ + if (found_top) { + // already seen + log::warning( + "Encountered Node with empty name \"\",\n" + "and > 1 child nodes that look like " + "regular (non-declaration) nodes.\n" + "Not expected in this context. " + "We'll convert all the child nodes." + ); + log::function(context); + } + if (!detail::node2hdf5(*c,*h.file)) + return false; + h.file->flush(); + found_top = true; + } // else + } // for + + } catch (...) { + log::function(context); + throw; + } + + // done + return true; +} + + + +// ----------------------------------------------------------------------------- +// Tree ==> HDF5 +// ----------------------------------------------------------------------------- + +inline bool convert(const Tree &tree, HDF5 &h) +{ + try { + if (tree.has_top()) + detail::check_top(tree.top().name, "Tree", "convert(Tree,HDF5)"); + return convert(*(const Node *)&tree, h); + } catch (...) { + log::function("convert(Tree,HDF5)"); + throw; + } +} + + + +// ----------------------------------------------------------------------------- +// XML ==> HDF5 +// ----------------------------------------------------------------------------- + +inline bool convert(const XML &x, HDF5 &h) +{ + // temporary + Tree t; + + // convert + try { + return convert(x,t) && convert(t,h); + } catch (...) { + log::function("convert(XML,HDF5)"); + throw; + } +} + + + +// ----------------------------------------------------------------------------- +// JSON ==> HDF5 +// ----------------------------------------------------------------------------- + +inline bool convert(const JSON &j, HDF5 &h) +{ + // temporary + Tree t; + + // convert + try { + return convert(j,t) && convert(t,h); + } catch (...) { + log::function("convert(JSON,HDF5)"); + throw; + } +} + + + +// ----------------------------------------------------------------------------- +// HDF5 ==> HDF5 +// For completeness +// ----------------------------------------------------------------------------- + +inline bool convert(const HDF5 &from, HDF5 &to) +{ + if (&to == &from) + return true; + + // clear + to.clear(); + + // convert + try { + if (!from.empty()) { + std::ifstream ifs(from.filename, std::ios::binary); + if (!ifs) { + log::error("Unable to open file \"{}\"", from.filename); + throw std::exception{}; + } + if (!to.read(ifs)) + throw std::exception{}; + } + } catch (...) { + log::function("convert(HDF5,HDF5)"); + throw; + } + + // done + return true; +} diff --git a/src/GNDStk/utility.hpp b/src/GNDStk/utility.hpp index 1c0979664..0110a46eb 100644 --- a/src/GNDStk/utility.hpp +++ b/src/GNDStk/utility.hpp @@ -323,44 +323,54 @@ inline void assign(const std::string &str, Args &&...args) // ----------------------------------------------------------------------------- // Forward declarations: some classes; convert // We're not fans of having lots of forward declarations, but these are here -// because (1) the relevant classes (Tree, XML, JSON) use these functions in, -// e.g., their constructors, which are defined in-class; and (2) the convert() +// because (1) relevant classes (Tree, XML, JSON, HDF5) use these functions in, +// e.g., their constructors, which are defined in-class; and (2) our convert() // functions in turn work with the classes and thus need the class definitions // to be available. The alternative would be to mostly define the classes, but // only declare their constructors; then define the convert()s; then finally // define the constructors. We think the forward declarations are clearer. // ----------------------------------------------------------------------------- -// Node +// Node, Tree class Node; - -// Tree class Tree; -// XML, JSON +// XML, JSON, HDF5 class XML; class JSON; +class HDF5; -// Node to {XML,JSON} -bool convert(const Node &, XML &x); -bool convert(const Node &, JSON &j); +// Node to {XML,JSON,HDF5} +bool convert(const Node &, XML &); +bool convert(const Node &, JSON &); +bool convert(const Node &, HDF5 &); -// Tree to {Tree,XML,JSON} +// Tree to {Tree,XML,JSON,HDF5} bool convert(const Tree &, Tree &); bool convert(const Tree &, XML &); bool convert(const Tree &, JSON &); +bool convert(const Tree &, HDF5 &); -// XML to {Node,Tree,XML,JSON} +// XML to {Node,Tree,XML,JSON,HDF5} bool convert(const XML &, Node &, const bool); bool convert(const XML &, Tree &); bool convert(const XML &, XML &); bool convert(const XML &, JSON &); +bool convert(const XML &, HDF5 &); -// JSON to {Node,Tree,XML,JSON} +// JSON to {Node,Tree,XML,JSON,HDF5} bool convert(const JSON &, Node &, const bool); bool convert(const JSON &, Tree &); bool convert(const JSON &, XML &); bool convert(const JSON &, JSON &); +bool convert(const JSON &, HDF5 &); + +// HDF5 to {Node,Tree,XML,JSON,HDF5} +bool convert(const HDF5 &, Node &, const bool); +bool convert(const HDF5 &, Tree &); +bool convert(const HDF5 &, XML &); +bool convert(const HDF5 &, JSON &); +bool convert(const HDF5 &, HDF5 &); From 316b6d7cc30ddec1d819d6b4c1e670a594ec19b9 Mon Sep 17 00:00:00 2001 From: Martin Staley Date: Wed, 17 Nov 2021 00:35:09 -0700 Subject: [PATCH 06/39] Extended the autogenerator to support a ProjectDir entry. To be used for non-GNDS products, e.g. NDI3. When ProjectDir is given, namespaces and various other constructs are done differently. Made miscellaneous small improvements in various other files. For example: direct read() and write() in Component, aligning with Node's. So: autogenerated classes have those read()s and write(); there's no need for a user to explicitly go through Node. --- autogen/json2class.cpp | 222 ++++++++++++++++++----------- src/GNDStk/Component.hpp | 13 +- src/GNDStk/Component/src/read.hpp | 54 +++++++ src/GNDStk/Component/src/write.hpp | 49 ++++++- src/GNDStk/Node.hpp | 36 +++-- src/GNDStk/Node/src/write.hpp | 22 +++ src/GNDStk/Support/src/detail.hpp | 4 +- src/GNDStk/Tree.hpp | 34 +++-- 8 files changed, 318 insertions(+), 116 deletions(-) create mode 100644 src/GNDStk/Component/src/read.hpp diff --git a/autogen/json2class.cpp b/autogen/json2class.cpp index 23ea31157..3a14ea2e5 100644 --- a/autogen/json2class.cpp +++ b/autogen/json2class.cpp @@ -62,7 +62,7 @@ struct InfoMetadata { // - a GNDStk::defaulted // but (in contrast with child nodes) can't make it be a vector of metadata. // An individual metadatum may be a vector in its own right, as in an XML - // construct such as (so that meta is a vector of + // construct such as (so that meta is a vector of // integers). We mean here that there isn't a vector of such [meta] entries, // and shouldn't be (XML wouldn't allow it). std::string name; @@ -160,6 +160,7 @@ struct InfoSpecs { std::string JSONDir; std::vector JSONFiles; std::string GNDSDir; + std::string ProjectDir; std::string Version; // Version, but with '_' in place of '.' @@ -206,9 +207,7 @@ struct InfoSpecs { // Print text describing an action the code is about to take void action(const std::string &str) { - std::cout - << "\n" - << colors::plain::blue << str << "..." << colors::reset << std::endl; + std::cout << colors::plain::blue << str << colors::reset << std::endl; } // Is the string all whitespace? @@ -858,7 +857,8 @@ void writeClassPrefix(writer &out, const PerClass &per) void writeClassForComponent(writer &out, const PerClass &per) { // using [name for variant] = ... - out(); + if (per.variants.size()) + out(); for (const auto &v : per.variants) { out(1,"using @ = std::variant<", v.type); int count = 0, total = v.children.size(); @@ -931,7 +931,7 @@ void writeClassForComponent(writer &out, const PerClass &per) // Class suffix void writeClassSuffix( - writer &out, const PerClass &per, const std::string &version + writer &out, const PerClass &per, const InfoSpecs &specs ) { // assignment out(); @@ -951,8 +951,13 @@ void writeClassSuffix( out(1,"// Custom functionality"); out(1,smallComment); out(); - out(1,"#include \"GNDStk/@/@/@/src/custom.hpp\"", - version, per.nsname, per.clname); + if (specs.ProjectDir == "") { + out(1,"#include \"GNDStk/@/@/@/src/custom.hpp\"", + specs.Version, per.nsname, per.clname); + } else { + out(1,"#include \"@/@/@/@/src/custom.hpp\"", + specs.ProjectDir, specs.Version, per.nsname, per.clname); + } // class+namespace end out(); @@ -963,7 +968,6 @@ void writeClassSuffix( - // ----------------------------------------------------------------------------- // writeClass* // For metadata, children, and variant children @@ -1378,10 +1382,10 @@ void writeClass(PerClass &per, const InfoSpecs &specs) writer out(false); // output: class begin - writeClassPrefix(out,per); + writeClassPrefix(out, per); // output: for the Component base - writeClassForComponent(out,per); + writeClassForComponent(out, per); // output: using directives out(); @@ -1428,7 +1432,7 @@ void writeClass(PerClass &per, const InfoSpecs &specs) writeClassCtors(out, per); // output: class end - writeClassSuffix(out, per, specs.Version); + writeClassSuffix(out, per, specs); // done per.code = out.str(); @@ -1574,6 +1578,7 @@ void commandLine( static const std::string input = "JSONDir"; static const std::string files = "JSONFiles"; static const std::string output = "GNDSDir"; + static const std::string project = "ProjectDir"; // optional static const std::string version = "Version"; static const std::string changes = "Changes"; @@ -1598,6 +1603,8 @@ void commandLine( specs.JSONDir = jmain[input]; specs.JSONFiles = std::vector(jmain[files]); specs.GNDSDir = jmain[output]; + if (jmain.contains(project)) + specs.ProjectDir = jmain[project]; specs.Version = jmain[version]; specs.VersionUnderscore = replace(specs.Version, '.', '_'); @@ -1606,14 +1613,22 @@ void commandLine( file = specs.JSONDir + '/' + file; // File names - specs.hppVersion = specs.GNDSDir + "/src/GNDStk/" + specs.Version + ".hpp"; - specs.hppKey = specs.GNDSDir + "/src/GNDStk/" + specs.Version + "/key.hpp"; + if (specs.ProjectDir == "") { + specs.hppVersion = specs.GNDSDir + "/src/GNDStk/"; + specs.hppKey = specs.GNDSDir + "/src/GNDStk/"; + } else { + specs.hppVersion = specs.ProjectDir + "/src/" + specs.ProjectDir + "/"; + specs.hppKey = specs.ProjectDir + "/src/" + specs.ProjectDir + "/"; + } + specs.hppVersion += specs.Version + ".hpp"; + specs.hppKey += specs.Version + "/key.hpp"; // Report on "singletons" if (singletons) { - action("Finding possible simplifications"); + action("\nFinding possible simplifications..."); for (const std::string &file : specs.JSONFiles) printSingletons(file); + action("Done looking for simplifications."); } // Changes? @@ -1648,15 +1663,22 @@ void preprocessClass( // Given the base GNDS directory and the GNDS version, as obtained earlier // from the JSON input file to this tool, compute relevant directory names. - const std::string - // For the present namespace: C++ and Python directories. The present - // namespace probably contains multiple classes, so its directories - // may have been created already, but that's fine. - nsdir = specs.GNDSDir + "/src/GNDStk/" + specs.Version + "/" + nsname, - nsdirpy = specs.GNDSDir + "/python/src/" + specs.Version + "/" + nsname, - // For the present class: C++ source and test directories. - clsrc = nsdir + "/" + clname + "/src", - cltest = nsdir + "/" + clname + "/test"; + std::string nsdir, nsdirpy; + // For the present namespace: C++ and Python directories. The present + // namespace probably contains multiple classes, so its directories + // may have been created already, but that's fine. + if (specs.ProjectDir == "") { + nsdir = specs.GNDSDir + "/src/GNDStk"; + nsdirpy = specs.GNDSDir + "/python/src"; + } else { + nsdir = specs.ProjectDir + "/src/" + specs.ProjectDir; + nsdirpy = specs.ProjectDir + "/python/src"; + } + nsdir += "/" + specs.Version + "/" + nsname; + nsdirpy += "/" + specs.Version + "/" + nsname; + // For the present class: C++ source and test directories. + const std::string clsrc = nsdir + "/" + clname + "/src"; + const std::string cltest = nsdir + "/" + clname + "/test"; // Create the above directories, if (and only if) they don't already exist. system(("mkdir -p " + nsdir ).data()); @@ -1713,7 +1735,7 @@ void preprocessClass( // names are computed as part of the "information" for the maps just mentioned. void preprocessFiles(InfoSpecs &specs) { - action("Preprocessing input files"); + action("\nPreprocessing input files..."); // files for (const std::string &file : specs.JSONFiles) { const nlohmann::json jmain = readJSONFile(file,true); @@ -1722,6 +1744,7 @@ void preprocessFiles(InfoSpecs &specs) for (const auto &cl : jmain.items()) preprocessClass(specs, nsname, cl); } + action("Done preprocessing."); } // preprocessFiles @@ -1812,7 +1835,7 @@ void getClass( // getFiles void getFiles(InfoSpecs &specs) { - action("Creating classes"); + action("\nCreating classes..."); // files for (const std::string &file : specs.JSONFiles) { const nlohmann::json jmain = readJSONFile(file,true); @@ -1821,6 +1844,7 @@ void getFiles(InfoSpecs &specs) for (const auto &cl : jmain.items()) getClass(specs, nsname, cl); } + action("Done creating classes."); } // getFiles @@ -1872,8 +1896,15 @@ void fileGNDStkVersion(const InfoSpecs &specs) // Create an overarching file for this version writer out(specs.hppVersion); out(); - out("#ifndef NJOY_GNDSTK_@", allcaps(specs.VersionUnderscore)); - out("#define NJOY_GNDSTK_@", allcaps(specs.VersionUnderscore)); + if (specs.ProjectDir == "") { + out("#ifndef NJOY_GNDSTK_@", allcaps(specs.VersionUnderscore)); + out("#define NJOY_GNDSTK_@", allcaps(specs.VersionUnderscore)); + } else { + out("#ifndef GUARD_@_@", + allcaps(specs.ProjectDir), allcaps(specs.VersionUnderscore)); + out("#define GUARD_@_@", + allcaps(specs.ProjectDir), allcaps(specs.VersionUnderscore)); + } std::string nsname_last = ""; for (auto &c : specs.class2data) { @@ -1882,41 +1913,25 @@ void fileGNDStkVersion(const InfoSpecs &specs) if (nsname != nsname_last) out(); nsname_last = nsname; - out("#include \"GNDStk/@/@/@.hpp\"", specs.Version, nsname, clname); + if (specs.ProjectDir == "") + out("#include \"GNDStk/@/@/@.hpp\"", + specs.Version, nsname, clname); + else + out("#include \"@/@/@/@.hpp\"", + specs.ProjectDir, specs.Version, nsname, clname); } out(); - out("#include \"GNDStk/@/key.hpp\"", specs.Version); + if (specs.ProjectDir == "") + out("#include \"GNDStk/@/key.hpp\"", specs.Version); + else + out("#include \"@/@/key.hpp\"", specs.ProjectDir, specs.Version); out(); out("#endif"); } // fileGNDStkVersion -// fixme Reconsider the arrangement described here... // fileGNDStkKey -const std::string file_key_comment = -R"***( -This file contains Meta and Child objects for metadata and child nodes in the -current GNDS version. These may prove to be useful if you wish to use the Core -Interface in conjunction with the autogenerated classes for this GNDS version. - -Within the outer njoy::GNDStk::version namespace below, the remaining namespace -arrangement was chosen to make the use of these objects smooth and logical. - -Meta and Child objects are collectively called "keys." Meta keys are placed -into key::meta. Child keys correspond to autogenerated classes, each of which -is already in some namespace; we thus use theNamespace::key::child::. That way, -an autogenerated class [ns::Foo] has [ns::key::foo] as its Child object, and -a "using namespace ns" allows the class and the Child object to be [Foo] and -[key::foo], respectively. (If we reordered ns:: and key::, that wouldn't work.) - -Within key::, we use meta:: and child:: around Meta and Child objects, just in -case there exist any identical GNDS metadata names and child-node names. (That -can, in fact, happen). The "using namespace meta" and "using namespace child" -directives then make the Meta<> and Child<> objects appear directly in key::, -so that "meta::" and "child::" are needed only to disambiguate identical names. -)***"; - void fileGNDStkKey(const InfoSpecs &specs) { // ------------------------ @@ -1963,16 +1978,25 @@ void fileGNDStkKey(const InfoSpecs &specs) writer out(specs.hppKey); out(); - out("/*",false); - out(file_key_comment,false); - out("*/"); - out(); - out("#ifndef NJOY_GNDSTK_@_KEY", allcaps(specs.VersionUnderscore)); - out("#define NJOY_GNDSTK_@_KEY", allcaps(specs.VersionUnderscore)); + if (specs.ProjectDir == "") { + out("#ifndef NJOY_GNDSTK_@_KEY", allcaps(specs.VersionUnderscore)); + out("#define NJOY_GNDSTK_@_KEY", allcaps(specs.VersionUnderscore)); + } else { + out("#ifndef GUARD_@_@_KEY", + allcaps(specs.ProjectDir), allcaps(specs.VersionUnderscore)); + out("#define GUARD_@_@_KEY", + allcaps(specs.ProjectDir), allcaps(specs.VersionUnderscore)); + } out(); - out("namespace njoy {"); - out("namespace GNDStk {"); + if (specs.ProjectDir == "") { + out("namespace njoy {"); + out("namespace GNDStk {"); + } else { + out("namespace @ {", specs.ProjectDir); + } out("namespace @ {", specs.VersionUnderscore); + out(); + out("using namespace njoy::GNDStk::core;"); // ------------------------ // Meta<> objects @@ -2037,8 +2061,12 @@ void fileGNDStkKey(const InfoSpecs &specs) out(largeComment); out(); out("} // namespace @", specs.VersionUnderscore); - out("} // namespace GNDStk"); - out("} // namespace njoy"); + if (specs.ProjectDir == "") { + out("} // namespace GNDStk"); + out("} // namespace njoy"); + } else { + out("} // namespace @", specs.ProjectDir); + } out(); out("#endif"); } // fileGNDStkKey @@ -2050,35 +2078,56 @@ void fileGNDStkClass( ) { // class-specific hpp file writer out(per.hppGNDStk); - const std::string guard = - "NJOY_GNDSTK_" + allcaps(specs.VersionUnderscore) + "_" + - allcaps(per.nsname) + "_" + allcaps(per.clname); + std::string guard; + if (specs.ProjectDir == "") { + guard = "NJOY_GNDSTK_" + + allcaps(specs.VersionUnderscore) + "_" + + allcaps(per.nsname) + "_" + allcaps(per.clname); + } else { + guard = "GUARD_" + allcaps(specs.ProjectDir) + "_" + + allcaps(specs.VersionUnderscore) + "_" + + allcaps(per.nsname) + "_" + allcaps(per.clname); + } out(); out("#ifndef @", guard); out("#define @", guard); out(); - out("// core interface"); + out("// GNDStk Core Interface"); out("#include \"GNDStk.hpp\""); if (c2d.dependencies.size() > 0) { out(); - out("// @ dependencies", specs.Version); - for (const auto &dep : c2d.dependencies) - out("#include \"GNDStk/@/@/@.hpp\"", - specs.Version, dep.nsname, dep.clname); + out("// Dependencies"); + if (specs.ProjectDir == "") { + for (const auto &dep : c2d.dependencies) + out("#include \"GNDStk/@/@/@.hpp\"", + specs.Version, dep.nsname, dep.clname); + } else { + for (const auto &dep : c2d.dependencies) + out("#include \"@/@/@/@.hpp\"", + specs.ProjectDir, specs.Version, dep.nsname, dep.clname); + } } out(); - out("namespace njoy {"); - out("namespace GNDStk {"); + if (specs.ProjectDir == "") { + out("namespace njoy {"); + out("namespace GNDStk {"); + } else { + out("namespace @ {", specs.ProjectDir); + } out("namespace @ {", specs.VersionUnderscore); out(); out("using namespace njoy::GNDStk::core;"); out(per.code,false); out("} // namespace @", specs.VersionUnderscore); - out("} // namespace GNDStk"); - out("} // namespace njoy"); + if (specs.ProjectDir == "") { + out("} // namespace GNDStk"); + out("} // namespace njoy"); + } else { + out("} // namespace @", specs.ProjectDir); + } out(); out("#endif"); } // fileGNDStkClass @@ -2112,7 +2161,10 @@ void filePythonNamespace(const InfoSpecs &specs, const PerNamespace &per) out(1,"// create the @ submodule", per.nsname); out(1,"python::module submodule = module.def_submodule("); out(2,"\"@\",", per.nsname); - out(2,"\"GNDS @ @\"", specs.Version, per.nsname); + if (specs.ProjectDir == "") + out(2,"\"GNDS @ @\"", specs.Version, per.nsname); + else + out(2,"\"@ @ @\"", specs.ProjectDir, specs.Version, per.nsname); out(1,");"); out(); @@ -2201,7 +2253,12 @@ void filePythonClass(const InfoSpecs &specs, const PerClass &per) out(); out("// local includes"); - out("#include \"GNDStk/@/@/@.hpp\"", specs.Version, nsname, clname); + if (specs.ProjectDir == "") + out("#include \"GNDStk/@/@/@.hpp\"", + specs.Version, nsname, clname); + else + out("#include \"@/@/@/@.hpp\"", + specs.ProjectDir, specs.Version, nsname, clname); out("#include \"definitions.hpp\""); out(); @@ -2216,8 +2273,13 @@ void filePythonClass(const InfoSpecs &specs, const PerClass &per) out("// @ wrapper", clname); out("void wrap@(python::module &module)", clname); out("{"); - out(1,"using namespace njoy::GNDStk;"); - out(1,"using namespace njoy::GNDStk::@;", specs.VersionUnderscore); + if (specs.ProjectDir == "") { + out(1,"using namespace njoy::GNDStk;"); + out(1,"using namespace njoy::GNDStk::@;", specs.VersionUnderscore); + } else { + out(1,"using namespace @;", specs.ProjectDir); + out(1,"using namespace @::@;", specs.ProjectDir, specs.VersionUnderscore); + } out(); out(1,"// type aliases"); out(1,"using Component = @::@;", nsname, clname); diff --git a/src/GNDStk/Component.hpp b/src/GNDStk/Component.hpp index 9abe4a34a..636ac4ef4 100644 --- a/src/GNDStk/Component.hpp +++ b/src/GNDStk/Component.hpp @@ -60,12 +60,13 @@ class Component : public BodyText public: + #include "GNDStk/Component/src/read.hpp" + #include "GNDStk/Component/src/write.hpp" #include "GNDStk/Component/src/fromNode.hpp" #include "GNDStk/Component/src/sort.hpp" #include "GNDStk/Component/src/toNode.hpp" // conversion to Node - #include "GNDStk/Component/src/write.hpp" - // You can (but don't need to) override the following in DERIVED + // You can (but need not) override the following in DERIVED static std::string namespaceName() { return ""; } // derived @@ -86,10 +87,10 @@ class Component : public BodyText } } - // Component << std::string + // Component << string // Meaning: read the string's content (currently XML, JSON, or HDF5) into - // an object of the Component's DERIVED class. Uses Node's << std::string - // capability, which does most of the work. + // an object of the Component's DERIVED class. Uses Node's << string, which + // does most of the work. void operator<<(const std::string &str) { try { @@ -114,5 +115,5 @@ std::ostream &operator<<( std::ostream &os, const Component &obj ) { - return obj.write(os); + return obj.write(os,0); } diff --git a/src/GNDStk/Component/src/read.hpp b/src/GNDStk/Component/src/read.hpp new file mode 100644 index 000000000..af5556ff5 --- /dev/null +++ b/src/GNDStk/Component/src/read.hpp @@ -0,0 +1,54 @@ + +// ----------------------------------------------------------------------------- +// Component::read() +// Via Node, and using Node's available read() functions. +// So, autogenerated classes can directly use .read(...). +// ----------------------------------------------------------------------------- + +// read(istream, FileType) +std::istream &read( + std::istream &is, + FileType format = FileType::null, + const bool decl = false +) { + Node node; + std::istream &ret = node.read(is, format, decl); + derived() = DERIVED(node); + return ret; +} + +// read(file name, FileType) +bool read( + const std::string &filename, + const FileType format = FileType::null, + const bool decl = false +) { + Node node; + bool ret = node.read(filename, format, decl); + derived() = DERIVED(node); + return ret; +} + +// read(istream, string) +std::istream &read( + std::istream &is, + const std::string &format, + const bool decl = false +) { + Node node; + std::istream &ret = node.read(is, format, decl); + derived() = DERIVED(node); + return ret; +} + +// read(file name, string) +bool read( + const std::string &filename, + const std::string &format, + const bool decl = false +) { + Node node; + bool ret = node.read(filename, format, decl); + derived() = DERIVED(node); + return ret; +} diff --git a/src/GNDStk/Component/src/write.hpp b/src/GNDStk/Component/src/write.hpp index a2a8507bb..eeab38313 100644 --- a/src/GNDStk/Component/src/write.hpp +++ b/src/GNDStk/Component/src/write.hpp @@ -1,9 +1,9 @@ // ----------------------------------------------------------------------------- -// Component::write() +// Component::write(), for "prettyprinting" // ----------------------------------------------------------------------------- -std::ostream &write(std::ostream &os = std::cout, const int level = 0) const +std::ostream &write(std::ostream &os, const int level) const { try { // Indent, write header, newline @@ -79,7 +79,7 @@ std::ostream &write(std::ostream &os = std::cout, const int level = 0) const if constexpr (detail::hasWriteOneArg) { // DERIVED::write() doesn't take an indentation level; we handle here std::ostringstream tmp; - derived().write(tmp); + derived().write(tmp,0); if (tmp.str().size() != 0) os << indentTo(level+1); for (char c : tmp.str()) @@ -124,3 +124,46 @@ std::ostream &write(std::ostream &os = std::cout, const int level = 0) const throw; } } + + +// ----------------------------------------------------------------------------- +// Component::write() +// Via Node, and using Node's available write() functions. +// So, autogenerated classes can directly use .write(...). +// ----------------------------------------------------------------------------- + +// write(ostream, FileType) +std::ostream &write( + std::ostream &os = std::cout, + const FileType format = FileType::null, + const bool decl = false +) const { + return Node(*this).write(os, format, decl); +} + +// write(file name, FileType) +bool write( + const std::string &filename, + FileType format = FileType::null, + const bool decl = false +) const { + return Node(*this).write(filename, format, decl); +} + +// write(ostream, string) +std::ostream &write( + std::ostream &os, + const std::string &format, + const bool decl = false +) const { + return Node(*this).write(os, format, decl); +} + +// write(file name, string) +bool write( + const std::string &filename, + const std::string &format, + const bool decl = false +) const { + return Node(*this).write(filename, format, decl); +} diff --git a/src/GNDStk/Node.hpp b/src/GNDStk/Node.hpp index ec48ef4d4..10dab51eb 100644 --- a/src/GNDStk/Node.hpp +++ b/src/GNDStk/Node.hpp @@ -156,7 +156,7 @@ class Node { // ----------------------------------------------------------------------------- -// I/O +// Stream I/O // ----------------------------------------------------------------------------- // operator>> @@ -170,7 +170,25 @@ inline std::istream &operator>>(std::istream &is, Node &node) } } -// Node << std::string +// operator<< +inline std::ostream &operator<<(std::ostream &os, const Node &node) +{ + try { + return node.write(os); + } catch (...) { + log::function("ostream << Node"); + throw; + } +} + + +// ----------------------------------------------------------------------------- +// I/O with respect to a string +// The string is considered to have content that would otherwise be in a file. +// So, this is convenience for reading and writing, for instance, XML snippets. +// ----------------------------------------------------------------------------- + +// Node << string // Note that this is an INPUT operator to Node! // Treating the std::string as a "file" with XML, JSON, or HDF5 content, read it // into the Node. We return void, not the Node, so users don't incorrectly think @@ -180,20 +198,12 @@ inline void operator<<(Node &node, const std::string &str) { try { std::istringstream iss(str); - iss >> node; + node.read(iss); } catch (...) { log::function("Node << string"); throw; } } -// operator<< -inline std::ostream &operator<<(std::ostream &os, const Node &node) -{ - try { - return node.write(os); - } catch (...) { - log::function("ostream << Node"); - throw; - } -} +// string >> Node +// fixme Write and test this diff --git a/src/GNDStk/Node/src/write.hpp b/src/GNDStk/Node/src/write.hpp index 8116355eb..4bae62dff 100644 --- a/src/GNDStk/Node/src/write.hpp +++ b/src/GNDStk/Node/src/write.hpp @@ -19,10 +19,13 @@ // ----------------------------------------------------------------------------- +// Helper // write(ostream, int level) // For FileType::text // ----------------------------------------------------------------------------- +private: + std::ostream &write(std::ostream &os, const int level) const { // indentation: spaces for current and next levels @@ -66,10 +69,19 @@ std::ostream &write(std::ostream &os, const int level) const // ----------------------------------------------------------------------------- +// Helper // write(file name, int level) // For FileType::text // ----------------------------------------------------------------------------- +private: + +// fixme I noticed that this write() variant isn't used (other write() functions +// with filename go through ostream first, and call the earlier write() helper +// with const int level). Decide if there's any reason to keep it. If we do keep +// it, then it needs to be exercised in the test suite, which it isn't now. +#if 0 + bool write(const std::string &filename, const int level) const { // open file @@ -90,12 +102,16 @@ bool write(const std::string &filename, const int level) const return true; } +#endif + // ----------------------------------------------------------------------------- // 1. write(ostream, FileType) // ----------------------------------------------------------------------------- +public: + std::ostream &write( std::ostream &os = std::cout, const FileType format = FileType::null, @@ -161,6 +177,8 @@ std::ostream &write( // 2. write(file name, FileType) // ----------------------------------------------------------------------------- +public: + bool write( const std::string &filename, FileType format = FileType::null, @@ -235,6 +253,8 @@ bool write( // 3. write(ostream, string) // ----------------------------------------------------------------------------- +public: + std::ostream &write( std::ostream &os, const std::string &format, @@ -268,6 +288,8 @@ std::ostream &write( // 4. write(file name, string) // ----------------------------------------------------------------------------- +public: + bool write( const std::string &filename, const std::string &format, diff --git a/src/GNDStk/Support/src/detail.hpp b/src/GNDStk/Support/src/detail.hpp index db43f50c9..2738f12de 100644 --- a/src/GNDStk/Support/src/detail.hpp +++ b/src/GNDStk/Support/src/detail.hpp @@ -19,7 +19,7 @@ class MapTypeString { static inline const std::vector value = {""}; static bool find(const std::string &str) { - return std::find(value.begin(),value.end(),str) != value.end(); + return std::find(value.begin(), value.end(), str) != value.end(); } }; @@ -34,7 +34,7 @@ class MapTypeString { static inline const std::vector value = vec; \ static bool find(const std::string &str) \ { \ - return std::find(value.begin(),value.end(),str) != value.end(); \ + return std::find(value.begin(), value.end(), str) != value.end(); \ } \ } diff --git a/src/GNDStk/Tree.hpp b/src/GNDStk/Tree.hpp index def3aea56..8fb16b214 100644 --- a/src/GNDStk/Tree.hpp +++ b/src/GNDStk/Tree.hpp @@ -81,7 +81,7 @@ class Tree : public Node { // ----------------------------------------------------------------------------- -// I/O +// Stream I/O // ----------------------------------------------------------------------------- // operator>> @@ -95,27 +95,37 @@ inline std::istream &operator>>(std::istream &is, Tree &tree) } } -// Tree << std::string -// Note that this is an INPUT operator to Tree! -// Other comments as for Node << std::string -inline void operator<<(Tree &tree, const std::string &str) +// operator<< +inline std::ostream &operator<<(std::ostream &os, const Tree &tree) { try { - std::istringstream iss(str); - iss >> tree; + return tree.write(os); } catch (...) { - log::function("Tree << string"); + log::function("ostream << Tree"); throw; } } -// operator<< -inline std::ostream &operator<<(std::ostream &os, const Tree &tree) + +// ----------------------------------------------------------------------------- +// I/O with respect to a string +// As for Node. +// ----------------------------------------------------------------------------- + +// fixme Not currently tested +// Tree << string +// Note that this is an INPUT operator to Tree! +// Other comments as for Node << string +inline void operator<<(Tree &tree, const std::string &str) { try { - return tree.write(os); + std::istringstream iss(str); + tree.read(iss); } catch (...) { - log::function("ostream << Tree"); + log::function("Tree << string"); throw; } } + +// string >> Tree +// fixme Write and test this From 5d8653b887dfcaafbf87028bdd5fcabf0697fec7 Mon Sep 17 00:00:00 2001 From: Martin Staley Date: Thu, 18 Nov 2021 00:25:20 -0700 Subject: [PATCH 07/39] Lots of not-yet-finished work on an HDF5 read/write capability. Won't compile right now, but wanted to get this in. --- src/GNDStk/HDF5/src/read.hpp | 13 +- src/GNDStk/convert/src/JSON.hpp | 35 ++- src/GNDStk/convert/src/XML.hpp | 26 ++- src/GNDStk/convert/src/detail.hpp | 374 ++++++++++++++++++++++++++---- src/GNDStk/convert/src/tree.hpp | 129 ++++++++++- src/GNDStk/utility.hpp | 6 +- 6 files changed, 518 insertions(+), 65 deletions(-) diff --git a/src/GNDStk/HDF5/src/read.hpp b/src/GNDStk/HDF5/src/read.hpp index 8f85097b5..d7473a0e7 100644 --- a/src/GNDStk/HDF5/src/read.hpp +++ b/src/GNDStk/HDF5/src/read.hpp @@ -1,4 +1,6 @@ +needs work... + // ----------------------------------------------------------------------------- // HDF5.read() // ----------------------------------------------------------------------------- @@ -34,6 +36,8 @@ with debugging and testing, and gives users a more-uniform interface. // read(istream) // ----------------------------------------------------------------------------- +/// zzz integrate these fixmes into regular remarks + // fixme // We may want to detect whether or not the istream is in std::ios::binary // mode. If it isn't, then copying it absolutely correctly, to a temporary @@ -63,6 +67,12 @@ std::istream &read(std::istream &is) filename = tmpnam(buffer); // fixme Possibly check if tmpnam() is screwy and the file actually exists? + /* +zzz +Have HDF5::createTemporary() +Should probably make it append .h5 + */ + try { // Open temporary file. This *should* work, but we check anyway. std::ofstream ofs(filename, std::ios::binary); @@ -142,9 +152,8 @@ bool read(const std::string name) log::error("file = HighFive::File(filename, ReadOnly)\n" "threw an exception"); } - } else { + } else log::error("Could not open file \"{}\" for input", filename); - } if (!ret) log::member("HDF5.read(\"{}\")", filename); diff --git a/src/GNDStk/convert/src/JSON.hpp b/src/GNDStk/convert/src/JSON.hpp index 20257eb03..d1f5e911f 100644 --- a/src/GNDStk/convert/src/JSON.hpp +++ b/src/GNDStk/convert/src/JSON.hpp @@ -13,18 +13,14 @@ inline bool convert(const Node &node, JSON &j) // clear j.clear(); - // See comments for convert(Node,XML); smiilar ones apply here, except - // that JSON files don't have declaration nodes. - static const std::string context = "convert(Node,JSON)"; try { // Probably a regular Node if (node.name != "") - return detail::node2json(node, j.doc); + return detail::node2json(node,j.doc); // Probably a Tree... - if (node.metadata.size() != 0) { log::warning( "Encountered Node with empty name \"\",\n" @@ -65,14 +61,14 @@ inline bool convert(const Node &node, JSON &j) ); log::function(context); } - if (!detail::node2json(*c, j.doc)) + if (!detail::node2json(*c,j.doc)) return false; found_top = true; - } - } + } // else + } // for } catch (...) { - log::function("convert(Tree,JSON)"); + log::function(context); throw; } @@ -122,6 +118,27 @@ inline bool convert(const XML &x, JSON &j) +// ----------------------------------------------------------------------------- +// HDF5 ==> JSON +// ----------------------------------------------------------------------------- + +// As above, goes through a tree. +inline bool convert(const HDF5 &h, JSON &j) +{ + // temporary + Tree t; + + // convert + try { + return convert(h,t) && convert(t,j); + } catch (...) { + log::function("convert(HDF5,JSON)"); + throw; + } +} + + + // ----------------------------------------------------------------------------- // JSON ==> JSON // For completeness diff --git a/src/GNDStk/convert/src/XML.hpp b/src/GNDStk/convert/src/XML.hpp index cb3e90592..82b9300c4 100644 --- a/src/GNDStk/convert/src/XML.hpp +++ b/src/GNDStk/convert/src/XML.hpp @@ -44,12 +44,11 @@ inline bool convert(const Node &node, XML &x) if (node.name != "") { // A Tree should have name == "" at the root level, so we don't // consider this to be a Tree. Just do a straight Node conversion. - return detail::node2xml(node, x.doc); + return detail::node2xml(node,x.doc); } // Henceforth it's presumably a Tree, unless someone gave the name "" // to a regular node, which they really shouldn't have done... - if (node.metadata.size() != 0) { log::warning( "Encountered Node with empty name \"\",\n" @@ -94,7 +93,7 @@ inline bool convert(const Node &node, XML &x) ); log::function(context); } - if (!detail::node2xml(*c, x.doc)) + if (!detail::node2xml(*c,x.doc)) return false; found_top = true; } @@ -196,3 +195,24 @@ inline bool convert(const JSON &j, XML &x) throw; } } + + + +// ----------------------------------------------------------------------------- +// HDF5 ==> XML +// ----------------------------------------------------------------------------- + +// As above, goes through a tree. +inline bool convert(const HDF5 &h, XML &x) +{ + // temporary + Tree t; + + // convert + try { + return convert(h,t) && convert(t,x); + } catch (...) { + log::function("convert(HDF5,XML)"); + throw; + } +} diff --git a/src/GNDStk/convert/src/detail.hpp b/src/GNDStk/convert/src/detail.hpp index 960b823f0..6b4c405ad 100644 --- a/src/GNDStk/convert/src/detail.hpp +++ b/src/GNDStk/convert/src/detail.hpp @@ -1,11 +1,12 @@ +needs work... + namespace detail { // ----------------------------------------------------------------------------- -// Helpers for convert(*,JSON) +// node2json // ----------------------------------------------------------------------------- -// node2json template bool node2json( const NODE &node, nlohmann::json &j, @@ -19,8 +20,7 @@ bool node2json( const std::string nameOriginal = node.name; const std::string nameSuffixed = node.name + suffix; - // This also triggers node creation, in the event that the node exists but - // is null (so that nothing is entered later), e.g. in XML's . + // Create new json in j auto &json = j[nameSuffixed]; // ------------------------ @@ -66,7 +66,7 @@ bool node2json( // ----------------------------------------------------------------------------- -// Helpers for convert(*,tree) +// xml2node // ----------------------------------------------------------------------------- /* @@ -90,22 +90,26 @@ namespace pugi } */ -// internal_error_xml2node -inline bool internal_error_xml2node(const std::string &str) + +// Helper: error_xml2node +inline void error_xml2node(const std::string &str) { log::error( "Internal error in detail::xml2node(pugi::xml_node,Node):\n" - "type pugi::{} found, but not handled, as sub-element", - str + "type pugi::{} found, but not handled, as sub-element", str ); throw std::exception{}; - return false; // in case we allow exceptions to be turned off } + +// xml2node // pugi::xml_node ==> Node template bool xml2node(const pugi::xml_node &xnode, NODE &node) { + static const std::string context = + "detail::xml2node(pugi::xml_node, Node)"; + // check destination node if (!node.empty()) { log::error( @@ -132,17 +136,17 @@ bool xml2node(const pugi::xml_node &xnode, NODE &node) // I don't think that the following should ever appear in this context if (xsub.type() == pugi::node_document) - return internal_error_xml2node("node_document"); + error_xml2node("node_document"); if (xsub.type() == pugi::node_declaration) - return internal_error_xml2node("node_declaration"); + error_xml2node("node_declaration"); // For now I won't handle these; let's ensure that we don't see them if (xsub.type() == pugi::node_null) - return internal_error_xml2node("node_null"); + error_xml2node("node_null"); if (xsub.type() == pugi::node_pi) - return internal_error_xml2node("node_pi"); + error_xml2node("node_pi"); if (xsub.type() == pugi::node_doctype) - return internal_error_xml2node("node_doctype"); + error_xml2node("node_doctype"); // ------------------------ // element (typical case) @@ -153,7 +157,7 @@ bool xml2node(const pugi::xml_node &xnode, NODE &node) if (!xml2node(xsub,node.add())) return false; } catch (...) { - // recursive; no point printing error context, so just throw + log::function(context); throw; } continue; @@ -207,6 +211,10 @@ bool xml2node(const pugi::xml_node &xnode, NODE &node) +// ----------------------------------------------------------------------------- +// json2node +// ----------------------------------------------------------------------------- + // nlohmann::json::const_iterator ==> Node // Why the iterator rather than the json object? I found that there were some // seemingly funny semantics in the json library. As we can see below, we have @@ -217,33 +225,38 @@ bool xml2node(const pugi::xml_node &xnode, NODE &node) // iterator form rather than the range-based-for form. Perhaps there's a way // to reformulate all this in a shorter way, but this is what we have for now. -// Helper -inline bool internal_error_json2node(const std::string &str) + +// Helper: error_json2node +inline void error_json2node(const std::string &str) { log::error( "Internal error in detail::json2node(nlohmann::json,Node):\n" - "message is \"{}\"; please let us know about this", - str + "message is \"{}\"; please let us know about this", str ); throw std::exception{}; - return false; // in case we allow exceptions turned off } +// json2node template bool json2node(const nlohmann::json::const_iterator &iter, NODE &node) { + static const std::string context = + "detail::json2node(nlohmann::json::const_iterator, Node)"; + // the node sent here should be fresh, ready to receive entries... if (!node.empty()) - return internal_error_json2node("!node.empty()"); + error_json2node("!node.empty()"); - // non-object cases were handled before a caller calls this function... + // non-object cases should have been handled + // before any caller calls this function... if (!iter->is_object()) - return internal_error_json2node("!iter->is_object()"); + error_json2node("!iter->is_object()"); - // any "attributes" key should have been handled in the caller... + // any "attributes" key (a specially-named "child node" that we use in JSON + // in order to identify attributes) should have been handled in the caller... if (iter.key() == "attributes") - return internal_error_json2node("iter.key() == \"attributes\""); + error_json2node("iter.key() == \"attributes\""); // key,value ==> node name, json value to bring in node.name = iter.key(); @@ -268,7 +281,7 @@ bool json2node(const nlohmann::json::const_iterator &iter, NODE &node) if (!json2node(elem,node.add())) return false; } catch (...) { - // recursive; no point printing error context; just throw + log::function(context); throw; } } else if (elem->is_null()) { @@ -277,7 +290,7 @@ bool json2node(const nlohmann::json::const_iterator &iter, NODE &node) node.add().name = elem.key(); } else { // no other cases are handled right now - return internal_error_json2node("unhandled JSON value type"); + error_json2node("unhandled JSON value type"); } } @@ -287,9 +300,292 @@ bool json2node(const nlohmann::json::const_iterator &iter, NODE &node) +// ----------------------------------------------------------------------------- +// node2hdf5 +// ----------------------------------------------------------------------------- + +// Here, OBJECT is either HighFive::File or HighFive::Group +template +bool node2hdf5( + const NODE &node, OBJECT &h, + const std::string &suffix = "" +) { + // As for JSON; see the comment in node2json() + const std::string nameOriginal = node.name; + const std::string nameSuffixed = node.name + suffix; + + // Create new group in h + HighFive::Group group = h.createGroup(nameSuffixed); + + // ------------------------ + // metadata ==> group + // ------------------------ + + if (suffix != "") + group.createAttribute(std::string("nodeName"), nameOriginal); + + for (auto &meta : node.metadata) + group.createAttribute(meta.first, meta.second); + + /* +zzz +we should see what this actually produces +but we should actually have it be more intelligent than the JSON code +understand block data +understand cdata/pcdata/comment/text system in Node/Tree + */ + + // ------------------------ + // children ==> group + // ------------------------ + + // Logic as for JSON; see the comment in node2json() + std::map childNames; + for (auto &c : node.children) { + auto iter = childNames.find(c->name); + if (iter == childNames.end()) + childNames.insert({c->name,0}); // once (so far) + else + iter->second = 1; // more than once + } + + // Now revisit and process the child nodes + for (auto &c : node.children) { + const std::size_t counter = childNames.find(c->name)->second++; + if (!node2hdf5(*c, group, counter ? std::to_string(counter-1) : "")) + return false; + } + + // Done + return true; +} + + + +// ----------------------------------------------------------------------------- +// hdf5attr2node +// ----------------------------------------------------------------------------- + +inline bool hdf5attr2node( + const HighFive::Attribute &attr, + Node &node +) { + (void)attr; + (void)node; + + // print + const auto print = [](auto &value) { std::cout << value << std::endl; }; + + const HighFive::DataType attrType = attr.getDataType(); + + if (attrType == HighFive::AtomicType{}) + print(" ==> char "); + if (attrType == HighFive::AtomicType{}) + print(" ==> signed char "); + if (attrType == HighFive::AtomicType{}) + print(" ==> unsigned char "); + if (attrType == HighFive::AtomicType{}) + print(" ==> short "); + if (attrType == HighFive::AtomicType{}) + print(" ==> unsigned short "); + if (attrType == HighFive::AtomicType{}) + print(" ==> int "); + if (attrType == HighFive::AtomicType{}) + print(" ==> unsigned "); + if (attrType == HighFive::AtomicType{}) + print(" ==> long "); + if (attrType == HighFive::AtomicType{}) + print(" ==> unsigned long "); + if (attrType == HighFive::AtomicType{}) + print(" ==> long long "); + if (attrType == HighFive::AtomicType{}) + print(" ==> unsigned long long"); + if (attrType == HighFive::AtomicType{}) + print(" ==> float "); + if (attrType == HighFive::AtomicType{}) + print(" ==> double "); + if (attrType == HighFive::AtomicType{}) + print(" ==> std::string "); + if (attrType == HighFive::AtomicType{}) + print(" ==> bool "); + + // zzz write this; + + return true; +} + + + +// ----------------------------------------------------------------------------- +// hdf52node +// ----------------------------------------------------------------------------- + +// Helper: error_hdf52node +inline void error_hdf52node(const std::string &str) +{ + log::error( + "Internal error in detail::hdf52node(HighFive::Object,Node):\n" + "message is \"{}\"; please let us know about this", str + ); + throw std::exception{}; +} + + +// hdf52node +template +bool hdf52node( + const HighFive::Group &group, + const std::string &groupName, + NODE &node, + const bool decl = false +) { + static const std::string context = + "detail::hdf52node(HighFive::Group, std::string, Node)"; + + if (!decl) { + // the node sent here should be fresh, ready to receive entries... + if (!node.empty()) + error_hdf52node("!node.empty()"); + + // group name ==> node name + node.name = groupName; + + // get metadata from HDF5 attributes + for (auto &attrName : group.listAttributeNames()) + hdf5attr2node(group.getAttribute(attrName), node); + } + + // ------------------------ + // get children from + // HDF5 sub-groups + // ------------------------ + + /// bool saw_dataset + /* + In XML: + + 1.2 3.4 5.6 + 7.8 9.0 + + + In Tree/Node: + foo + energy + pcdata + text="1.2 3.4 5.6" + velocity + pcdata + text="7.8 9.0" + + In HDF5: // zzz Meaning, we should set it up this way! + group "foo" + dataset "energy" + can have attributes!! + + dataset "velocity" + can have attributes!! + + + The above way seems like a good (more importantly, apparently viable) manner + in which to handle XML "pcdata" (plain character data). + + What about XML "cdata" - which we get from those XML "" nodes? + It doesn't seem like those should be considered "data sets." (Unlike Pcdata + nodes, which, at least in GNDS, are clearly data sets.) + + For XML CDATA, it would seem reasonable to have essentially the same handling + we have for Node itself, or for JSON. + + Let's consider some XML: + + + + Independent of what we do in Node/Tree, and in JSON, let's think about what + makes sense in HDF5... + + group "documentation" + attribute "name" + group "cdata" + attribute "text" + + OK, well, that's basically what we do for JSON, except that we don't need + that obnoxious JSON "attributes" middleman. + */ + + for (auto &elemName : group.listObjectNames()) { + switch (group.getObjectType(elemName)) { + + // File + case HighFive::ObjectType::File : + error_hdf52node("ObjectType \"File\" not expected here"); + break; + + // Group + case HighFive::ObjectType::Group : + try { + if (!hdf52node(group.getGroup(elemName), elemName, node.add())) + return false; + } catch (...) { + log::function(context); + throw; + } + break; + + // UserDataType + case HighFive::ObjectType::UserDataType : + error_hdf52node("unhandled ObjectType \"UserDataType\""); + break; + + // DataSpace (not to be confused with Dataset) + case HighFive::ObjectType::DataSpace : + error_hdf52node("ObjectType \"DataSpace\" not expected here"); + break; + + // Dataset + case HighFive::ObjectType::Dataset : + std::cout << "Must handle HighFive Dataset!" << std::endl; + // zzz Must handle! And, remember, Datasets can have attributes. + break; + + // Attribute + case HighFive::ObjectType::Attribute : + // Re: the error message... + // Wait, why wouldn't an attribute show up here? :-) Apparently, + // group.listObjectNames() (used in the for-loop we're in right + // now) doesn't include attribute names! Which is why we had the + // earlier for-loop (the one that used group.listAttributeNames()) + // in order to handle attributes. + error_hdf52node("ObjectType \"Attribute\" not expected here"); + break; + + // Other + case HighFive::ObjectType::Other : + error_hdf52node("unhandled ObjectType \"Other\""); + break; + + // default + default: + error_hdf52node("unhandled ObjectType"); + break; + + } // switch + } // for + + // done + return true; +} + + + +// ----------------------------------------------------------------------------- +// node2node +// ----------------------------------------------------------------------------- + // Node ==> Node template -inline void node2Node(const NODE &from, NODE &to) +void node2node(const NODE &from, NODE &to) { // clear to.clear(); @@ -303,16 +599,16 @@ inline void node2Node(const NODE &from, NODE &to) // children for (auto &c : from.children) - node2Node(*c, to.add()); + node2node(*c, to.add()); } // ----------------------------------------------------------------------------- -// Helpers for convert(*,XML) +// node2xml // ----------------------------------------------------------------------------- -// check_special +// Helper: check_special template bool check_special(const NODE &node, const std::string &label) { @@ -352,9 +648,7 @@ bool check_special(const NODE &node, const std::string &label) return true; } - - -// write_cdata +// Helper: write_cdata template bool write_cdata(const NODE &node, pugi::xml_node &xnode) { @@ -363,7 +657,7 @@ bool write_cdata(const NODE &node, pugi::xml_node &xnode) return true; } -// write_pcdata +// Helper: write_pcdata template bool write_pcdata(const NODE &node, pugi::xml_node &xnode) { @@ -372,7 +666,7 @@ bool write_pcdata(const NODE &node, pugi::xml_node &xnode) return true; } -// write_comment +// Helper: write_comment template bool write_comment(const NODE &node, pugi::xml_node &xnode) { @@ -382,11 +676,13 @@ bool write_comment(const NODE &node, pugi::xml_node &xnode) } - // node2xml template bool node2xml(const NODE &node, pugi::xml_node &x) { + static const std::string context = + "detail::node2xml(Node, pugi::xml_node)"; + // name pugi::xml_node xnode = x.append_child(node.name.data()); @@ -409,7 +705,7 @@ bool node2xml(const NODE &node, pugi::xml_node &x) if (!node2xml(*child,xnode)) return false; } catch (...) { - // recursive; no point in printing error context; just throw + log::function(context); throw; } } diff --git a/src/GNDStk/convert/src/tree.hpp b/src/GNDStk/convert/src/tree.hpp index c83be7d40..520a6a64c 100644 --- a/src/GNDStk/convert/src/tree.hpp +++ b/src/GNDStk/convert/src/tree.hpp @@ -1,10 +1,11 @@ +needs work... + // ----------------------------------------------------------------------------- // convert(*,Tree) // That is, convert to Tree objects -// // Also: -// convert(*,Node) for * = XML/JSON +// convert(*,Node) for * = XML/JSON/HDF5 // ----------------------------------------------------------------------------- // ----------------------------------------------------------------------------- @@ -50,7 +51,7 @@ inline bool convert(const XML &x, Node &node, const bool decl) // clear the receiving object node.clear(); - // optionally, give it a boilerplate declaration node + // optionally, make a boilerplate declaration node if (decl) node.add("xml"); // <== indicates that we built the object from an XML @@ -166,7 +167,7 @@ inline bool convert(const JSON &j, Node &node, const bool decl) // clear the receiving object node.clear(); - // optionally, give it a boilerplate declaration node + // optionally, make a boilerplate declaration node if (decl) node.add("json"); // <== indicates that we built the object from a JSON @@ -180,9 +181,8 @@ inline bool convert(const JSON &j, Node &node, const bool decl) // validate // ------------------------ - const std::size_t size = j.doc.size(); - // possibly redundant with the earlier empty() test, but harmless + const std::size_t size = j.doc.size(); if (size == 0) return true; @@ -197,16 +197,16 @@ inline bool convert(const JSON &j, Node &node, const bool decl) // convert the nodes // ------------------------ - const std::string name = j.doc.begin().key(); - // See comment above check_top() call in convert(XML,Node) above. // JSON documents don't have "declaration nodes," as XML documents // do, but here we interpret the bool decl parameter as essentially // indicating whether we're reading a Node (decl == false) or full // Tree (decl == true); and, the latter case suggests we're at the // top level, and should thus validate it as a top-level GNDS node. - if (decl) + if (decl) { + const std::string name = j.doc.begin().key(); detail::check_top(name, "JSON", "convert(JSON,Node)"); + } // visit the node, and its children recursively if (!detail::json2node(j.doc.begin(), decl ? node.add() : node)) @@ -232,3 +232,114 @@ inline bool convert(const JSON &j, Tree &tree) throw; } } + + + +// ----------------------------------------------------------------------------- +// HDF5 ==> Node +// HDF5 ==> Tree +// ----------------------------------------------------------------------------- + +/* +Remark + +HighFive::File, and by extension GNDStk::HDF5 (our simple wrapper around +HighFive::File, to assist in providing uniform behavior between XML, JSON, +and HDF5), refers to an entire HDF file. Unlike XML and JSON, it apparently +can't refer to just part of such a file, i.e. part of an HDF5 hierarchy. The +upshot: convert(HDF5,Tree) may be far more meaningful than convert(HDF5,Node), +as the former (Tree) is for a full GNDS hierarchy, the latter for possibly +a partial hierarchy. I'll leave the Node case, though. It will have slightly +different behavior than the Tree case does, due to the decl flag; and also, +the Tree version will call the Node version to do most of the work. We might +consider, at some point, having something like convert(HighFive::Group,Node), +i.e. with a HighFive::Group rather than a HighFive::File, but such a thing +might or might not prove to be useful. A HighFive::Group would end up coming +from a HighFive::File, rather than being on its own like a "snippet" of XML +or JSON could be. We'll see how things hash out. +*/ + +// HDF5 ==> Node +inline bool convert(const HDF5 &h, Node &node, const bool decl) +{ + // ------------------------ + // bookkeeping + // ------------------------ + + // clear the receiving object + node.clear(); + + // optionally, make a boilerplate declaration node + Node *declnode = nullptr; + if (decl) { + // indicates that we built the object from an HDF5... + declnode = &node.add("hdf5"); + } + + // empty hdf5 document? + if (h.empty()) + return true; + + try { + // for brevity + const HighFive::File &file = *h.file; + + // size == 0: not empty in the earlier (h.file == nullptr) sense, + // but, here, meaning that there's nothing in the HDF document + const std::size_t size = file.getNumberObjects(); + if (size == 0) + return true; + + // ------------------------ + // convert the nodes + // ------------------------ + + const HighFive::Group &group = file.getGroup("/"); + + // if decl, then put any top-level attributes into the "hdf5" + // child node that would have been created above + if (decl) + for (auto &attrName : group.listAttributeNames()) + if (!detail::hdf5attr2node(group.getAttribute(attrName), *declnode)) + return false; + + // visit the rest of the "/" group + if (!detail::hdf52node(group, "/", decl ? node.add() : node, decl)) + return false; + +#if 0 + // zzz see what can slip into the detail function... + // visit the remaining objects, and their sub-groups recursively + for (const std::string &name : names) { + const HighFive::ObjectType type = file.getObjectType(name); + if (type == HighFive::ObjectType::Group) { + detail::check_top(name, "HDF5", "convert(HDF5,Node)"); + const HighFive::Group &g = file.getGroup(name); + if (!detail::hdf52node(g, name, decl ? node.add() : node)) + return false; + } else if (type != HighFive::ObjectType::Attribute) { + assert(false); /// want group or attribute at top level + } + } +#endif + + } catch (...) { + log::function("convert(HDF5,Node)"); + throw; + } + + // done + return true; +} + + +// HDF5 ==> Tree +inline bool convert(const HDF5 &h, Tree &tree) +{ + try { + return convert(h, *(Node*)&tree, true); + } catch (...) { + log::function("convert(HDF5,Tree)"); + throw; + } +} diff --git a/src/GNDStk/utility.hpp b/src/GNDStk/utility.hpp index 0110a46eb..32d37bb0c 100644 --- a/src/GNDStk/utility.hpp +++ b/src/GNDStk/utility.hpp @@ -352,21 +352,21 @@ bool convert(const Tree &, JSON &); bool convert(const Tree &, HDF5 &); // XML to {Node,Tree,XML,JSON,HDF5} -bool convert(const XML &, Node &, const bool); +bool convert(const XML &, Node &, const bool = false); bool convert(const XML &, Tree &); bool convert(const XML &, XML &); bool convert(const XML &, JSON &); bool convert(const XML &, HDF5 &); // JSON to {Node,Tree,XML,JSON,HDF5} -bool convert(const JSON &, Node &, const bool); +bool convert(const JSON &, Node &, const bool = false); bool convert(const JSON &, Tree &); bool convert(const JSON &, XML &); bool convert(const JSON &, JSON &); bool convert(const JSON &, HDF5 &); // HDF5 to {Node,Tree,XML,JSON,HDF5} -bool convert(const HDF5 &, Node &, const bool); +bool convert(const HDF5 &, Node &, const bool = false); bool convert(const HDF5 &, Tree &); bool convert(const HDF5 &, XML &); bool convert(const HDF5 &, JSON &); From 31a4b6575a0b4daa1d27f76f0179b7bdbb2bcd9f Mon Sep 17 00:00:00 2001 From: Martin Staley Date: Thu, 18 Nov 2021 01:00:41 -0700 Subject: [PATCH 08/39] comment --- src/GNDStk/convert/src/tree.hpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/GNDStk/convert/src/tree.hpp b/src/GNDStk/convert/src/tree.hpp index 520a6a64c..8a171cb8e 100644 --- a/src/GNDStk/convert/src/tree.hpp +++ b/src/GNDStk/convert/src/tree.hpp @@ -303,6 +303,7 @@ inline bool convert(const HDF5 &h, Node &node, const bool decl) if (!detail::hdf5attr2node(group.getAttribute(attrName), *declnode)) return false; +may need unconditional false last argument here... // visit the rest of the "/" group if (!detail::hdf52node(group, "/", decl ? node.add() : node, decl)) return false; From 44c71dbed42468156059a949c4651cec8ca9acb9 Mon Sep 17 00:00:00 2001 From: Martin Staley Date: Thu, 18 Nov 2021 01:02:24 -0700 Subject: [PATCH 09/39] fix --- src/GNDStk/convert/src/tree.hpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/GNDStk/convert/src/tree.hpp b/src/GNDStk/convert/src/tree.hpp index 8a171cb8e..4dfb24f04 100644 --- a/src/GNDStk/convert/src/tree.hpp +++ b/src/GNDStk/convert/src/tree.hpp @@ -303,7 +303,8 @@ inline bool convert(const HDF5 &h, Node &node, const bool decl) if (!detail::hdf5attr2node(group.getAttribute(attrName), *declnode)) return false; -may need unconditional false last argument here... +may need unconditional "top"=true last argument here... +or something like that // visit the rest of the "/" group if (!detail::hdf52node(group, "/", decl ? node.add() : node, decl)) return false; From 20fb5a26223fc9be2900c595505da9f8484e4fab Mon Sep 17 00:00:00 2001 From: Martin Staley Date: Thu, 18 Nov 2021 11:35:46 -0700 Subject: [PATCH 10/39] Moving something around. --- autogen/v1.9.json | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/autogen/v1.9.json b/autogen/v1.9.json index 87bde7140..fdc6ad62e 100644 --- a/autogen/v1.9.json +++ b/autogen/v1.9.json @@ -1,4 +1,7 @@ { + "GNDSDir": "test", + "Version": "v1.9", + "JSONDir": "v1.9", "JSONFiles": [ "summary_abstract.json", @@ -19,7 +22,5 @@ "summary_tsl.json" ], - "GNDSDir": "test", - "Version": "v1.9", "Changes": "changes.json" } From 769916a8cfd264046346de900e2101bbb75bb906 Mon Sep 17 00:00:00 2001 From: Martin Staley Date: Thu, 18 Nov 2021 11:36:56 -0700 Subject: [PATCH 11/39] Addition to .gitignore. --- autogen/.gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/autogen/.gitignore b/autogen/.gitignore index 321656c44..5de84783e 100644 --- a/autogen/.gitignore +++ b/autogen/.gitignore @@ -1 +1,2 @@ json2class.exe +test From cf218ec3438b814b3ba9b748c9e0c996b3a5ab77 Mon Sep 17 00:00:00 2001 From: Martin Staley Date: Mon, 22 Nov 2021 10:34:16 -0700 Subject: [PATCH 12/39] Another setter capability in generated classes, and other improvements. For [optional] vector child-node fields, there's a setter that takes an element to push_back. If the optional has no value, it's given one first. Experience showed that something like this would be helpful. Updated code generator accordingly. Also, combined the default and "from fields" constructors in generated classes. This makes the generated classes shorter, and also, based on our experience with a prototype data format, proves to make object construction simpler. A generated class might have, for instance, a few metadata, followed by one or more vector or optional-vector child nodes. It's convenient for someone to initialize the object with metadata, and then to add vector elements individually later. This change helps make this process simpler and shorter. I also implemented another feature that experience with a prototype autogenerated set of classes suggested would be helpful. Before, getters with index or label looked for *metadata* named "index" or "label". Now, if no metadatum called "index" exists in the type of the vector's element (or any of its alternatives, if it's a variant), then index is interpreted to be a regular vector index, as in the "[]" operator. Note that someone who uses the code generator must be aware that the interpretation of (index) getters therefore depends fundamentally on whether or not the relevant vector element type has, or doesn't have, an "index" metadatum. This change means we essentially get an additional feature for free, as (index) previously would just fail unless an "index" metadatum were found. Removed a "GNDS"-centric comment in Component prettyprinted output. The comment probably wasn't particularly informative anyway. Updated test codes to reflect this change. --- autogen/json2class.cpp | 143 ++++++++++--------- src/GNDStk/Component.hpp | 5 +- src/GNDStk/Component/src/detail.hpp | 115 +++++++++------ src/GNDStk/Component/src/setter.hpp | 29 ++++ src/GNDStk/Component/src/write.hpp | 92 +++++++++++- src/GNDStk/Component/test/Component.test.cpp | 2 +- src/GNDStk/Component/test/detail.test.cpp | 2 +- src/GNDStk/Component/test/write.test.cpp | 52 +++---- src/GNDStk/HDF5/src/read.hpp | 2 - src/GNDStk/convert/src/detail.hpp | 2 - src/GNDStk/convert/src/tree.hpp | 6 +- src/GNDStk/precision/test/precision.test.cpp | 40 +++--- 12 files changed, 321 insertions(+), 169 deletions(-) create mode 100644 src/GNDStk/Component/src/setter.hpp diff --git a/autogen/json2class.cpp b/autogen/json2class.cpp index 3a14ea2e5..1eb86389c 100644 --- a/autogen/json2class.cpp +++ b/autogen/json2class.cpp @@ -1107,24 +1107,31 @@ void writeClassSetterChild( out(1,"@ &@(const @ &obj)", parent.clname, child.name, child.typeFull); out(2,"{ @() = obj; return *this; }", child.name); - const auto indlab = - [&out,&parent,&child](const auto &T, const auto &par) - { - // T par: index or label parameter - out(); - out(1,"// @(@,value)", child.name, par); - out(1,"@ &@(", parent.clname, child.name); - out(2,"const @@,", T, par); - out(2,"const @ &obj", child.type); - out(1,") {"); - out(2,"@(@) = obj; return *this;", child.name, par); - out(1,"}"); - }; - - // with index or label + // if vector or optional if (child.isVector) { + const auto indlab = + [&out,&parent,&child](const auto &T, const auto &par) + { + // T par: index or label parameter + out(); + out(1,"// @(@,value)", child.name, par); + out(1,"@ &@(", parent.clname, child.name); + out(2,"const @@,", T, par); + out(2,"const @ &obj", child.type); + out(1,") {"); + out(2,"@(@) = obj; return *this;", child.name, par); + out(1,"}"); + }; + + // with index or label indlab("std::size_t ", "index"); indlab("std::string &", "label"); + + // push vector element + out(); + out(1,"// @(value) for vector push_back", child.name); + out(1,"@ &@(const @ &obj)", parent.clname, child.name, child.type); + out(2,"{ setter(@(), obj); return *this; }", child.name); } } // writeClassSetterChild @@ -1264,48 +1271,17 @@ void writeClassCtorBody(writer &out, const std::string &argName) // writeClassCtors void writeClassCtors(writer &out, const PerClass &per) { - // ctor: default - out(); - out(1,"// default"); - out(1,"@() :", per.clname); - writeClassCtorComponent(out, per, false); - out(); - writeClassCtorBody(out, ""); - - // ctor: copy - out(); - out(1,"// copy"); - out(1,"@(const @ &other) :", per.clname, per.clname); - writeClassCtorComponent(out, per, true); - out(","); - out(2,"content{other.content}"); - writeClassCtorBody(out, "other"); - - // ctor: move - out(); - out(1,"// move"); - out(1,"@(@ &&other) :", per.clname, per.clname); - writeClassCtorComponent(out, per, true); - out(","); - out(2,"content{std::move(other.content)}"); - writeClassCtorBody(out, "other"); - - // ctor: node - out(); - out(1,"// from node"); - out(1,"@(const Node &node) :", per.clname); - writeClassCtorComponent(out, per, false); - out(); - writeClassCtorBody(out, "node"); - // ------------------------ - // ctor: fields + // ctor: default, + // and from fields // ------------------------ const auto total = per.nfields(); if (total != 0) { out(); - out(1,"// from fields"); + out(1,"// default, and from fields"); + + // informational message, if applicable for (const auto &m : per.metadata) if (m.isDefaulted) { out(1,"// std::optional replaces Defaulted; " @@ -1314,21 +1290,25 @@ void writeClassCtors(writer &out, const PerClass &per) } // signature, and base constructor call - // Note: we don't need "explicit" unless this constructor can be called - // with one argument. We'll always write it, however, in case someone - // modifies the auto-generated constructor (say, giving its arguments - // defaults) in such a way that is *can* be called with one argument. - // But we'd rather nobody modify the auto-generated classes. int count = 0; out(1,"explicit @(", per.clname); - for (const auto &m : per.metadata) - out(2,"const @ &@@", + + for (const auto &m : per.metadata) { + out(2,"const @ &@ =", m.isDefaulted ? "std::optional<" + m.type + ">" : m.typeFull, - m.name, ++count < total ? "," : ""); - for (const auto &c : per.children) - out(2,"const @ &@@", c.typeFull, c.name, ++count < total ? "," : ""); - for (const auto &v : per.variants) - out(2,"const @ &@@", v.typeFull, v.name, ++count < total ? "," : ""); + m.name /*, ++count < total ? "," : ""*/ ); + out(3,"@{}@", m.typeFull, ++count < total ? "," : ""); + } + for (const auto &c : per.children) { + out(2,"const @ &@ =", c.typeFull, + c.name /*, ++count < total ? "," : ""*/ ); + out(3,"@{}@", c.typeFull, ++count < total ? "," : ""); + } + for (const auto &v : per.variants) { + out(2,"const @ &@ =", v.typeFull, + v.name /*, ++count < total ? "," : ""*/ ); + out(3,"@{}@", v.typeFull, ++count < total ? "," : ""); + } out(1,") :"); writeClassCtorComponent(out, per, false); @@ -1353,6 +1333,41 @@ void writeClassCtors(writer &out, const PerClass &per) writeClassCtorBody(out, ""); } + // ------------------------ + // ctor: copy + // ------------------------ + + out(); + out(1,"// copy"); + out(1,"@(const @ &other) :", per.clname, per.clname); + writeClassCtorComponent(out, per, true); + out(","); + out(2,"content{other.content}"); + writeClassCtorBody(out, "other"); + + // ------------------------ + // ctor: move + // ------------------------ + + out(); + out(1,"// move"); + out(1,"@(@ &&other) :", per.clname, per.clname); + writeClassCtorComponent(out, per, true); + out(","); + out(2,"content{std::move(other.content)}"); + writeClassCtorBody(out, "other"); + + // ------------------------ + // ctor: node + // ------------------------ + + out(); + out(1,"// from node"); + out(1,"@(const Node &node) :", per.clname); + writeClassCtorComponent(out, per, false); + out(); + writeClassCtorBody(out, "node"); + // ------------------------ // ctor: vector // ------------------------ @@ -1427,7 +1442,7 @@ void writeClass(PerClass &per, const InfoSpecs &specs) // output: constructors out(); out(1,smallComment); - out(1,"// Construction"); + out(1,"// Constructors"); out(1,smallComment); writeClassCtors(out, per); diff --git a/src/GNDStk/Component.hpp b/src/GNDStk/Component.hpp index 636ac4ef4..0667a576f 100644 --- a/src/GNDStk/Component.hpp +++ b/src/GNDStk/Component.hpp @@ -51,9 +51,10 @@ class Component : public BodyText // See comments in finish.hpp #include "GNDStk/Component/src/finish.hpp" - // Intermediaries between derived-class getters, and getter functions - // in detail::. These shorten the code in the derived classes. + // Helpers for derived-class getters/setters. + // These shorten the code in the derived classes. #include "GNDStk/Component/src/getter.hpp" + #include "GNDStk/Component/src/setter.hpp" // Fallback for documentation() if DERIVED doesn't have help static inline helpMap help; diff --git a/src/GNDStk/Component/src/detail.hpp b/src/GNDStk/Component/src/detail.hpp index 05cf4322d..18966455b 100644 --- a/src/GNDStk/Component/src/detail.hpp +++ b/src/GNDStk/Component/src/detail.hpp @@ -407,58 +407,83 @@ const T &getter( static const std::string context = "getter {}::{}.{}({}) on vector"; try { - // todo Make this more efficient, e.g. by assuming that the vector's - // elements are sorted by index, so that the wanted value is likely - // to be found at [index]. - const T *selected = nullptr; - - for (auto &v : vec) { - const T *ptr = nullptr; - - if constexpr (isVariant::value) { - // T == variant - std::visit( - [&v,&index,&ptr](auto &&alternative) - { - if constexpr (hasIndex) - if (alternative.index() == index) - ptr = &v; - }, - v + if constexpr (hasIndex) { + // hasIndex + // T (or at least one alternative in T, if T is a variant) has a + // metadatum called "index". In this case, this function's size_t + // index parameter is interpreted to mean: find the object with + // an "index" metadatum that matches the parameter. Importantly, + // then, index in this case is ***NOT*** a C++ [index] index! + + // fixme Make the following more efficient, e.g. by assuming that the + // vector's elements are sorted by index, so that the wanted value is + // likely to be found at [index], even though (as stated above) [index] + // is not the interpretation here... + const T *selected = nullptr; + + for (auto &v : vec) { + const T *ptr = nullptr; + + if constexpr (isVariant::value) { + // T == variant + std::visit( + [&v,&index,&ptr](auto &&alternative) + { + if constexpr (hasIndex) + if (alternative.index() == index) + ptr = &v; + }, + v + ); + } else { + // T != variant + if constexpr (hasIndex) + if (v.index() == index) + ptr = &v; + } + + if (!ptr) + continue; + + if (selected) { + log::warning( + "Element with metadatum \"index\" {} was already found " + "in the vector.\n" + "Keeping the first element that was found.", + index + ); + log::member(context, nsname, clname, field, index); + } else + selected = ptr; + } // for + + if (!selected) { + log::error( + "Element with metadatum \"index\" {} was not found " + "in the vector" + std::string(vec.size() + ? "." + : ";\nin fact the vector is empty."), + index ); - } else { - // T != variant - if constexpr (hasIndex) - if (v.index() == index) - ptr = &v; + throw std::exception{}; } + return *selected; - if (!ptr) - continue; - - if (selected) { - log::warning( - "Element with index {} was already found in the vector.\n" - "Keeping the first element that was found.", - index - ); - log::member(context, nsname, clname, field, index); - } else - selected = ptr; - } // for + } else { - if (!selected) { - log::error( - "Element with index {} was not found in the vector" + - std::string(vec.size() ? "." : ";\nin fact the vector is empty."), - index - ); - throw std::exception{}; + // !hasIndex + // No "index" is anywhere to be found in T. Here, then, we interpret + // this function's index parameter to be a regular, C++ [index] index. + if (!(index < vec.size())) { + log::error( + "Index {} is out of range; vector size is {}.", + vec.size()); + throw std::exception{}; + } + return vec[index]; } - return *selected; - } catch (...) { // context // Example: prints "getter containers::Axes.axis(100)" diff --git a/src/GNDStk/Component/src/setter.hpp b/src/GNDStk/Component/src/setter.hpp new file mode 100644 index 000000000..58b4a1e96 --- /dev/null +++ b/src/GNDStk/Component/src/setter.hpp @@ -0,0 +1,29 @@ + +// Like getter.hpp, but to help with *setters* in Component-derived classes. + +// push_back a value into the vector. +template< + class T, class FROM, + class = std::enable_if_t< + std::is_constructible_v || std::is_convertible_v + > +> +void setter(std::vector &vec, const FROM &value) +{ + vec.push_back(value); +} + +// Create an empty vector in the optional if it has no value, then +// push_back a value into the vector. +template< + class T, class FROM, + class = std::enable_if_t< + std::is_constructible_v || std::is_convertible_v + > +> +void setter(std::optional> &opt, const FROM &value) +{ + if (!opt.has_value()) + opt = std::vector{}; + opt->push_back(value); +} diff --git a/src/GNDStk/Component/src/write.hpp b/src/GNDStk/Component/src/write.hpp index eeab38313..7eed91358 100644 --- a/src/GNDStk/Component/src/write.hpp +++ b/src/GNDStk/Component/src/write.hpp @@ -13,13 +13,19 @@ std::ostream &write(std::ostream &os, const int level) const detail::fullName(DERIVED::namespaceName(), DERIVED::className()) ) + " " + detail::colorize_brace("{") + - (comments + /* + // fixme We may not actually want this. It's arguably largely clutter, + // and besides, someone may have used GNDStk's code generator to make + // a different library - for which "GNDS" verbiage may be confusing. + (comments ? " " + detail::colorize_comment( std::string("// GNDS: ") + DERIVED::GNDSName() ) : "" - ) + "\n" + ) + + */ + "\n" ); if constexpr (std::is_same_v>) { @@ -126,6 +132,7 @@ std::ostream &write(std::ostream &os, const int level) const } + // ----------------------------------------------------------------------------- // Component::write() // Via Node, and using Node's available write() functions. @@ -167,3 +174,84 @@ bool write( ) const { return Node(*this).write(filename, format, decl); } + + + +// ----------------------------------------------------------------------------- +// print +// Simple version of the prettyprinting write(), for user ease and familiarity. +// ----------------------------------------------------------------------------- + +/* +REMARK +A long remark about a short function. :-) + +Python has print(), and we anticipate having many Python-aware users. This, +first and foremost, is the reason for this function's existence. + +Also, importantly, we've provided a series of write() functions, above, that +mirror Node's various write()s. The Component class is designed to imbue its +derived classes with a wealth of functionality, and, in this vein, we're taking +advantage of Component's ability to convert objects of those derived classes +to Node (an ability that Component also gives us!) and to thereby make Node's +write()s available to them. + +Node's write()s can do a number of things, including, for example, writing to +XML, and also writing to an internal debug format we have in GNDStk. Given the +above write()s - which, again, are intentionally designed (and this includes +their default arguments) to mirror Node's - a call to .write() in fact ends up +going to GNDStk's Debug format. + +A user, however, printing a Component-derived class, would probably much prefer +our prettyprinting capability! Not our internal debug format. So, instead of +changing up these write() functions - making them, in effect, be inconsistent +with Node's write() functions - we'll instead give users a "simple prettyprint +to C++ standard output" call by doing exactly what we're doing here: providing +a print(), like Python does, and with a name that's different from "write" so +that no conflict exists. + +Note that our print() does something small but important: it prints a newline +at the end, which in this context a user will expect. + +Wait a minute, doesn't the main prettyprint write() already do a newline? No, +in fact, it doesn't, and as some readers may realize, it shouldn't. Just as C++ +doesn't automatically end something it prints (an integer, say, or a floating- +point number) with a newline, neither should a well-mannered system for printing +class objects. Whether a newline is appropriate, or not, depends on context. + +If you write std::cout << 1.23 << std::endl, you expect one line, with "1.23", +followed by a newline via std::endl, then the cursor ready at the beginning of +the very next line. Write std::cout << obj << std::endl, where obj is of some +user-defined type with a stream output operator that prints its own newline (but +shouldn't!), and now the cursor, after printing, will be *two* lines down, after +an intervening blank line. Which raises a question: why the different behavior? + +It may seem convenient for "large" things to print with a newline automatically, +but doing so creates inconsistent behavior between different types of printed +objects, and inconsistencies beget unpredictability. + +Moreover, Component-derived classes often contain instances of other Component- +derived classes. In the above write(), an enclosing object will place its own +newlines - only where appropriate, and NOT where not appropriate - between its +constituent parts. If those parts did their own thing in this respect, they'd +stymie the ability of the enclosing class to do the right thing. + +Just for fun, we'll give print() both const and non-const versions (one would +normally expect only a const version), and with a "builder pattern" that mirrors +that of the setters that GNDStk's code generator gives its generated classes. +This way, someone could actually prettyprint an object *while* it's being built, +builder style. Perhaps some users would find this to be useful for visualizing +what's happening as they create their objects. +*/ + +const DERIVED &print(const int level = 0) const +{ + write(std::cout,level) << std::endl; + return *static_cast(this); +} + +DERIVED &print(const int level = 0) +{ + write(std::cout,level) << std::endl; + return *static_cast(this); +} diff --git a/src/GNDStk/Component/test/Component.test.cpp b/src/GNDStk/Component/test/Component.test.cpp index 5c524cc2c..4dd94d196 100644 --- a/src/GNDStk/Component/test/Component.test.cpp +++ b/src/GNDStk/Component/test/Component.test.cpp @@ -164,7 +164,7 @@ SCENARIO("Testing GNDStk Component") { color = false; // avoid cluttering the checked output below const std::string expected = - "DerivedData { // GNDS: data\n" + "DerivedData {\n" " foo : 12\n" " bar : 34.56\n" "} // DerivedData" diff --git a/src/GNDStk/Component/test/detail.test.cpp b/src/GNDStk/Component/test/detail.test.cpp index 3011e0182..4c138d5dc 100644 --- a/src/GNDStk/Component/test/detail.test.cpp +++ b/src/GNDStk/Component/test/detail.test.cpp @@ -333,7 +333,7 @@ SCENARIO("Testing Component detail:: writeComponentPart()") { // value.write(stream,level) to be called instead. // So we get the same result from each call. const std::string expected = - " Derived { // GNDS: none\n" + " Derived {\n" " foo : 56\n" " bar : 7.8\n" " } // Derived"; diff --git a/src/GNDStk/Component/test/write.test.cpp b/src/GNDStk/Component/test/write.test.cpp index 88ef0b3f5..aeade0982 100644 --- a/src/GNDStk/Component/test/write.test.cpp +++ b/src/GNDStk/Component/test/write.test.cpp @@ -44,42 +44,42 @@ SCENARIO("Component write()") { inline const std::string &CorrectWriteText() { static const std::string ret = -R"***(proto::ReactionSuite { // GNDS: reactionSuite +R"***(proto::ReactionSuite { evaluation : ENDF/B-8.0 format : 1.9 interaction : // optional; has no value projectile : n projectileFrame : lab target : H2 - proto::Reactions { // GNDS: reactions + proto::Reactions { reaction [ - proto::Reaction { // GNDS: reaction + proto::Reaction { ENDF_MT : 16 fissionGenre : // optional; has no value label : 2n + H1 - proto::CrossSection { // GNDS: crossSection + proto::CrossSection { XYs1d regions1d [ - proto::XYs1d { // GNDS: XYs1d + proto::XYs1d { index : // optional; has no value interpolation : // defaulted; is its default (lin-lin) label : eval outerDomainValue : // optional; has no value - proto::Axes { // GNDS: axes + proto::Axes { href : // optional; has no value axis grid [ - proto::Axis { // GNDS: axis + proto::Axis { index : 0 label : crossSection unit : b } // proto::Axis - proto::Axis { // GNDS: axis + proto::Axis { index : 1 label : energy_in unit : eV } // proto::Axis ] } // proto::Axes - proto::Values { // GNDS: values + proto::Values { length : // optional; has no value start : // defaulted; is its default (0) valueType : // defaulted; is its default (double) @@ -150,23 +150,23 @@ R"***(proto::ReactionSuite { // GNDS: reactionSuite ] } // proto::CrossSection } // proto::Reaction - proto::Reaction { // GNDS: reaction + proto::Reaction { ENDF_MT : 102 fissionGenre : // optional; has no value label : H3 + photon - proto::CrossSection { // GNDS: crossSection + proto::CrossSection { XYs1d regions1d [ - proto::Regions1d { // GNDS: regions1d + proto::Regions1d { label : eval outerDomainValue : // optional; has no value XYs1d [ - proto::XYs1d { // GNDS: XYs1d + proto::XYs1d { index : 0 interpolation : log-log label : // optional; has no value outerDomainValue : // optional; has no value axes : // optional; has no value - proto::Values { // GNDS: values + proto::Values { length : // optional; has no value start : // defaulted; is its default (0) valueType : // defaulted; is its default (double) @@ -177,13 +177,13 @@ R"***(proto::ReactionSuite { // GNDS: reactionSuite 5.00000000e+03 1.19000000e-06 1.00000000e+04 1.00000000e-06 } // proto::Values } // proto::XYs1d - proto::XYs1d { // GNDS: XYs1d + proto::XYs1d { index : 1 interpolation : // defaulted; is its default (lin-lin) label : // optional; has no value outerDomainValue : // optional; has no value axes : // optional; has no value - proto::Values { // GNDS: values + proto::Values { length : // optional; has no value start : // defaulted; is its default (0) valueType : // defaulted; is its default (double) @@ -261,15 +261,15 @@ R"***(proto::ReactionSuite { // GNDS: reactionSuite } // proto::Values } // proto::XYs1d ] - proto::Axes { // GNDS: axes + proto::Axes { href : // optional; has no value axis grid [ - proto::Axis { // GNDS: axis + proto::Axis { index : 0 label : crossSection unit : b } // proto::Axis - proto::Axis { // GNDS: axis + proto::Axis { index : 1 label : energy_in unit : eV @@ -280,33 +280,33 @@ R"***(proto::ReactionSuite { // GNDS: reactionSuite ] } // proto::CrossSection } // proto::Reaction - proto::Reaction { // GNDS: reaction + proto::Reaction { ENDF_MT : 2 fissionGenre : // optional; has no value label : n + H2 - proto::CrossSection { // GNDS: crossSection + proto::CrossSection { XYs1d regions1d [ - proto::XYs1d { // GNDS: XYs1d + proto::XYs1d { index : // optional; has no value interpolation : // defaulted; is its default (lin-lin) label : eval outerDomainValue : // optional; has no value - proto::Axes { // GNDS: axes + proto::Axes { href : // optional; has no value axis grid [ - proto::Axis { // GNDS: axis + proto::Axis { index : 0 label : crossSection unit : b } // proto::Axis - proto::Axis { // GNDS: axis + proto::Axis { index : 1 label : energy_in unit : eV } // proto::Axis ] } // proto::Axes - proto::Values { // GNDS: values + proto::Values { length : // optional; has no value start : // defaulted; is its default (0) valueType : // defaulted; is its default (double) diff --git a/src/GNDStk/HDF5/src/read.hpp b/src/GNDStk/HDF5/src/read.hpp index d7473a0e7..aa02d4a0a 100644 --- a/src/GNDStk/HDF5/src/read.hpp +++ b/src/GNDStk/HDF5/src/read.hpp @@ -1,6 +1,4 @@ -needs work... - // ----------------------------------------------------------------------------- // HDF5.read() // ----------------------------------------------------------------------------- diff --git a/src/GNDStk/convert/src/detail.hpp b/src/GNDStk/convert/src/detail.hpp index 6b4c405ad..025acc4d1 100644 --- a/src/GNDStk/convert/src/detail.hpp +++ b/src/GNDStk/convert/src/detail.hpp @@ -1,6 +1,4 @@ -needs work... - namespace detail { // ----------------------------------------------------------------------------- diff --git a/src/GNDStk/convert/src/tree.hpp b/src/GNDStk/convert/src/tree.hpp index 4dfb24f04..3945e1c00 100644 --- a/src/GNDStk/convert/src/tree.hpp +++ b/src/GNDStk/convert/src/tree.hpp @@ -1,6 +1,4 @@ -needs work... - // ----------------------------------------------------------------------------- // convert(*,Tree) // That is, convert to Tree objects @@ -303,8 +301,8 @@ inline bool convert(const HDF5 &h, Node &node, const bool decl) if (!detail::hdf5attr2node(group.getAttribute(attrName), *declnode)) return false; -may need unconditional "top"=true last argument here... -or something like that + /// may need unconditional "top"=true last argument here... + /// or something like that... // visit the rest of the "/" group if (!detail::hdf52node(group, "/", decl ? node.add() : node, decl)) return false; diff --git a/src/GNDStk/precision/test/precision.test.cpp b/src/GNDStk/precision/test/precision.test.cpp index f851a9334..8db41101f 100644 --- a/src/GNDStk/precision/test/precision.test.cpp +++ b/src/GNDStk/precision/test/precision.test.cpp @@ -560,7 +560,7 @@ SCENARIO("Precision code in BodyText::toNode(), " // ------------------------ const std::string printed_metadata_individual = -R"***(precision::Numbers { // GNDS: numbers +R"***(precision::Numbers { adouble : 1.414214 afloat : 1.7321 aquad : 2.23606798 @@ -575,7 +575,7 @@ R"***(precision::Numbers { // GNDS: numbers )***"; const std::string printed_metadata_real = -R"***(precision::Numbers { // GNDS: numbers +R"***(precision::Numbers { adouble : 1.41 afloat : 1.73 aquad : 2.24 @@ -590,7 +590,7 @@ R"***(precision::Numbers { // GNDS: numbers )***"; const std::string printed_gndstk_individual = -R"***(precision::Numbers { // GNDS: numbers +R"***(precision::Numbers { adouble : 1.4142136 afloat : 1.73205 aquad : 2.236067977 @@ -605,7 +605,7 @@ R"***(precision::Numbers { // GNDS: numbers )***"; const std::string printed_gndstk_real = -R"***(precision::Numbers { // GNDS: numbers +R"***(precision::Numbers { adouble : 1.414 afloat : 1.732 aquad : 2.236 @@ -725,28 +725,28 @@ R"***( // ------------------------ const std::string block_data_individual = -R"***(precision::Numbers { // GNDS: numbers +R"***(precision::Numbers { adouble : // defaulted; is its default (1.414) afloat : // defaulted; is its default (1.732) aquad : // defaulted; is its default (2.236) bdouble : // defaulted; is its default (2.449) bfloat : // defaulted; is its default (2.646) bquad : // defaulted; is its default (2.828) - precision::Doubles { // GNDS: doubles + precision::Doubles { length : // optional; has no value start : // defaulted; is its default (0) valueType : // optional; has no value 3.352228 7.682296 2.777747 5.5397 4.773971 6.288709 } // precision::Doubles - precision::Floats { // GNDS: floats + precision::Floats { length : // optional; has no value start : // defaulted; is its default (0) valueType : // optional; has no value 8.4019 3.9438 7.831 7.9844 9.1165 1.9755 } // precision::Floats - precision::Quads { // GNDS: quads + precision::Quads { length : // optional; has no value start : // defaulted; is its default (0) valueType : // optional; has no value @@ -758,28 +758,28 @@ R"***(precision::Numbers { // GNDS: numbers )***"; const std::string block_data_real = -R"***(precision::Numbers { // GNDS: numbers +R"***(precision::Numbers { adouble : // defaulted; is its default (1.414) afloat : // defaulted; is its default (1.732) aquad : // defaulted; is its default (2.236) bdouble : // defaulted; is its default (2.449) bfloat : // defaulted; is its default (2.646) bquad : // defaulted; is its default (2.828) - precision::Doubles { // GNDS: doubles + precision::Doubles { length : // optional; has no value start : // defaulted; is its default (0) valueType : // optional; has no value 3.35 7.68 2.78 5.54 4.77 6.29 } // precision::Doubles - precision::Floats { // GNDS: floats + precision::Floats { length : // optional; has no value start : // defaulted; is its default (0) valueType : // optional; has no value 8.4 3.94 7.83 7.98 9.12 1.98 } // precision::Floats - precision::Quads { // GNDS: quads + precision::Quads { length : // optional; has no value start : // defaulted; is its default (0) valueType : // optional; has no value @@ -791,28 +791,28 @@ R"***(precision::Numbers { // GNDS: numbers )***"; const std::string block_gndstk_individual = -R"***(precision::Numbers { // GNDS: numbers +R"***(precision::Numbers { adouble : // defaulted; is its default (1.4142136) afloat : // defaulted; is its default (1.73205) aquad : // defaulted; is its default (2.236067977) bdouble : // defaulted; is its default (2.4494897) bfloat : // defaulted; is its default (2.64575) bquad : // defaulted; is its default (2.828427125) - precision::Doubles { // GNDS: doubles + precision::Doubles { length : // optional; has no value start : // defaulted; is its default (0) valueType : // optional; has no value 3.3522276 7.6822959 2.7777471 5.5396996 4.7739705 6.2887092 } // precision::Doubles - precision::Floats { // GNDS: floats + precision::Floats { length : // optional; has no value start : // defaulted; is its default (0) valueType : // optional; has no value 8.40188 3.94383 7.83099 7.9844 9.11647 1.97551 } // precision::Floats - precision::Quads { // GNDS: quads + precision::Quads { length : // optional; has no value start : // defaulted; is its default (0) valueType : // optional; has no value @@ -824,28 +824,28 @@ R"***(precision::Numbers { // GNDS: numbers )***"; const std::string block_gndstk_real = -R"***(precision::Numbers { // GNDS: numbers +R"***(precision::Numbers { adouble : // defaulted; is its default (1.414) afloat : // defaulted; is its default (1.732) aquad : // defaulted; is its default (2.236) bdouble : // defaulted; is its default (2.449) bfloat : // defaulted; is its default (2.646) bquad : // defaulted; is its default (2.828) - precision::Doubles { // GNDS: doubles + precision::Doubles { length : // optional; has no value start : // defaulted; is its default (0) valueType : // optional; has no value 3.352 7.682 2.778 5.54 4.774 6.289 } // precision::Doubles - precision::Floats { // GNDS: floats + precision::Floats { length : // optional; has no value start : // defaulted; is its default (0) valueType : // optional; has no value 8.402 3.944 7.831 7.984 9.116 1.976 } // precision::Floats - precision::Quads { // GNDS: quads + precision::Quads { length : // optional; has no value start : // defaulted; is its default (0) valueType : // optional; has no value From cdff3fcb300630ccac27719ef4e42472e9b3da01 Mon Sep 17 00:00:00 2001 From: Martin Staley Date: Mon, 22 Nov 2021 13:39:11 -0700 Subject: [PATCH 13/39] Suppress potential warning due to unused parameters in one branch of an if-constexpr. --- src/GNDStk/Component/src/detail.hpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/GNDStk/Component/src/detail.hpp b/src/GNDStk/Component/src/detail.hpp index 18966455b..972765753 100644 --- a/src/GNDStk/Component/src/detail.hpp +++ b/src/GNDStk/Component/src/detail.hpp @@ -263,6 +263,9 @@ bool writeComponentPart( const std::string &color ) { if constexpr (is_base_of_Component::value) { + // Suppress "unused parameter" warnings + (void)value; (void)maxlen; + (void)label; (void)color; // T is derived from Component, and thus inherits a write() value.write(os,level); } else { From d58d5bede16ed0a8ed7625f98836eee16137fba0 Mon Sep 17 00:00:00 2001 From: Martin Staley Date: Sun, 28 Nov 2021 23:42:21 -0700 Subject: [PATCH 14/39] Small change to fix issue Tom found with a particular compiler. --- autogen/json2class.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/autogen/json2class.cpp b/autogen/json2class.cpp index 1eb86389c..704b40ee8 100644 --- a/autogen/json2class.cpp +++ b/autogen/json2class.cpp @@ -1616,7 +1616,8 @@ void commandLine( // Extract information from the command line .json specs.JSONDir = jmain[input]; - specs.JSONFiles = std::vector(jmain[files]); + for (const auto &str : jmain[files]) + specs.JSONFiles.push_back(str); specs.GNDSDir = jmain[output]; if (jmain.contains(project)) specs.ProjectDir = jmain[project]; From 06e3297385fb572d1324bf883b064b9f9b56b9a2 Mon Sep 17 00:00:00 2001 From: Martin Staley Date: Tue, 30 Nov 2021 10:47:24 -0700 Subject: [PATCH 15/39] Some work on the code generator, mostly to simplify some things. Regenerated the prototype codes. The changes to these also reflect other work I'd done recently on the code generator, as they hadn't been regenerated for a while. --- autogen/json2class.cpp | 206 ++++++------------ autogen/prototype.json | 22 +- .../v1.9/transport/ReactionSuite.python.cpp | 17 -- src/GNDStk/v1.9.hpp | 4 +- src/GNDStk/v1.9/containers/Axes.hpp | 45 ++-- src/GNDStk/v1.9/containers/Axis.hpp | 46 ++-- src/GNDStk/v1.9/containers/Grid.hpp | 67 +++--- src/GNDStk/v1.9/containers/Link.hpp | 34 +-- src/GNDStk/v1.9/containers/Regions1d.hpp | 58 +++-- src/GNDStk/v1.9/containers/Values.hpp | 48 ++-- src/GNDStk/v1.9/containers/XYs1d.hpp | 68 +++--- src/GNDStk/v1.9/key.hpp | 28 +-- src/GNDStk/v1.9/transport/CrossSection.hpp | 39 ++-- src/GNDStk/v1.9/transport/Reaction.hpp | 54 ++--- src/GNDStk/v1.9/transport/ReactionSuite.hpp | 72 +++--- src/GNDStk/v1.9/transport/Reactions.hpp | 40 ++-- 16 files changed, 331 insertions(+), 517 deletions(-) diff --git a/autogen/json2class.cpp b/autogen/json2class.cpp index 704b40ee8..b500d6fe4 100644 --- a/autogen/json2class.cpp +++ b/autogen/json2class.cpp @@ -157,11 +157,11 @@ struct PerClass { // as well as various processed information struct InfoSpecs { // From the .json file on the command line + std::string Path; + std::string Project; + std::string Version; std::string JSONDir; std::vector JSONFiles; - std::string GNDSDir; - std::string ProjectDir; - std::string Version; // Version, but with '_' in place of '.' std::string VersionUnderscore; @@ -951,13 +951,8 @@ void writeClassSuffix( out(1,"// Custom functionality"); out(1,smallComment); out(); - if (specs.ProjectDir == "") { - out(1,"#include \"GNDStk/@/@/@/src/custom.hpp\"", - specs.Version, per.nsname, per.clname); - } else { - out(1,"#include \"@/@/@/@/src/custom.hpp\"", - specs.ProjectDir, specs.Version, per.nsname, per.clname); - } + out(1,"#include \"@/@/@/@/src/custom.hpp\"", + specs.Project, specs.Version, per.nsname, per.clname); // class+namespace end out(); @@ -1294,19 +1289,17 @@ void writeClassCtors(writer &out, const PerClass &per) out(1,"explicit @(", per.clname); for (const auto &m : per.metadata) { - out(2,"const @ &@ =", - m.isDefaulted ? "std::optional<" + m.type + ">" : m.typeFull, - m.name /*, ++count < total ? "," : ""*/ ); - out(3,"@{}@", m.typeFull, ++count < total ? "," : ""); + const std::string type = + m.isDefaulted ? "std::optional<" + m.type + ">" : m.typeFull; + out(2,"const @ &@ =", type, m.name); + out(3,"@{}@", type, ++count < total ? "," : ""); } for (const auto &c : per.children) { - out(2,"const @ &@ =", c.typeFull, - c.name /*, ++count < total ? "," : ""*/ ); + out(2,"const @ &@ =", c.typeFull, c.name); out(3,"@{}@", c.typeFull, ++count < total ? "," : ""); } for (const auto &v : per.variants) { - out(2,"const @ &@ =", v.typeFull, - v.name /*, ++count < total ? "," : ""*/ ); + out(2,"const @ &@ =", v.typeFull, v.name); out(3,"@{}@", v.typeFull, ++count < total ? "," : ""); } @@ -1589,12 +1582,12 @@ void commandLine( const int argc, const char *const *const argv, InfoSpecs &specs ) { - // Keys we'll look for + // JSON keys we'll look for + static const std::string path = "Path"; + static const std::string project = "Project"; + static const std::string version = "Version"; static const std::string input = "JSONDir"; static const std::string files = "JSONFiles"; - static const std::string output = "GNDSDir"; - static const std::string project = "ProjectDir"; // optional - static const std::string version = "Version"; static const std::string changes = "Changes"; // Usage @@ -1607,21 +1600,23 @@ void commandLine( const nlohmann::json jmain = readJSONFile(argv[1]); // Validate content - if (!(jmain.contains(input) && jmain.contains(output) && - jmain.contains(files) && jmain.contains(version))) { - log::error("The input json file needs {}, {}, {}, and {}", - input, files, output, version); + if (!(jmain.contains(version) && + jmain.contains(input) && + jmain.contains(files))) { + log::error("The input json file needs {}, {}, and {}", + version, input, files); throw std::exception{}; } // Extract information from the command line .json - specs.JSONDir = jmain[input]; + specs.Path = jmain.contains(path) ? jmain[path] : "."; + specs.Project = jmain.contains(project) ? jmain[project] : "GNDStk"; + specs.Version = jmain[version]; + specs.JSONDir = jmain[input]; for (const auto &str : jmain[files]) specs.JSONFiles.push_back(str); - specs.GNDSDir = jmain[output]; - if (jmain.contains(project)) - specs.ProjectDir = jmain[project]; - specs.Version = jmain[version]; + + // Version, with underscores in place of periods specs.VersionUnderscore = replace(specs.Version, '.', '_'); // Prepend the JSON file names with their directory @@ -1629,15 +1624,10 @@ void commandLine( file = specs.JSONDir + '/' + file; // File names - if (specs.ProjectDir == "") { - specs.hppVersion = specs.GNDSDir + "/src/GNDStk/"; - specs.hppKey = specs.GNDSDir + "/src/GNDStk/"; - } else { - specs.hppVersion = specs.ProjectDir + "/src/" + specs.ProjectDir + "/"; - specs.hppKey = specs.ProjectDir + "/src/" + specs.ProjectDir + "/"; - } - specs.hppVersion += specs.Version + ".hpp"; - specs.hppKey += specs.Version + "/key.hpp"; + const std::string base = + specs.Path + "/" + specs.Project + "/src/" + specs.Project + "/"; + specs.hppVersion = base + specs.Version + ".hpp"; + specs.hppKey = base + specs.Version + "/key.hpp"; // Report on "singletons" if (singletons) { @@ -1677,21 +1667,14 @@ void preprocessClass( // custom files as needed // ------------------------ - // Given the base GNDS directory and the GNDS version, as obtained earlier - // from the JSON input file to this tool, compute relevant directory names. - std::string nsdir, nsdirpy; // For the present namespace: C++ and Python directories. The present - // namespace probably contains multiple classes, so its directories + // namespace probably contains multiple classes, so these directories // may have been created already, but that's fine. - if (specs.ProjectDir == "") { - nsdir = specs.GNDSDir + "/src/GNDStk"; - nsdirpy = specs.GNDSDir + "/python/src"; - } else { - nsdir = specs.ProjectDir + "/src/" + specs.ProjectDir; - nsdirpy = specs.ProjectDir + "/python/src"; - } - nsdir += "/" + specs.Version + "/" + nsname; - nsdirpy += "/" + specs.Version + "/" + nsname; + const std::string nsdir = specs.Path + "/" + specs.Project + + "/src/" + specs.Project + "/" + specs.Version + "/" + nsname; + const std::string nsdirpy = specs.Path + "/" + specs.Project + + "/python/src" + "/" + specs.Version + "/" + nsname; + // For the present class: C++ source and test directories. const std::string clsrc = nsdir + "/" + clname + "/src"; const std::string cltest = nsdir + "/" + clname + "/test"; @@ -1912,15 +1895,8 @@ void fileGNDStkVersion(const InfoSpecs &specs) // Create an overarching file for this version writer out(specs.hppVersion); out(); - if (specs.ProjectDir == "") { - out("#ifndef NJOY_GNDSTK_@", allcaps(specs.VersionUnderscore)); - out("#define NJOY_GNDSTK_@", allcaps(specs.VersionUnderscore)); - } else { - out("#ifndef GUARD_@_@", - allcaps(specs.ProjectDir), allcaps(specs.VersionUnderscore)); - out("#define GUARD_@_@", - allcaps(specs.ProjectDir), allcaps(specs.VersionUnderscore)); - } + out("#ifndef @_@", allcaps(specs.Project), allcaps(specs.VersionUnderscore)); + out("#define @_@", allcaps(specs.Project), allcaps(specs.VersionUnderscore)); std::string nsname_last = ""; for (auto &c : specs.class2data) { @@ -1929,19 +1905,12 @@ void fileGNDStkVersion(const InfoSpecs &specs) if (nsname != nsname_last) out(); nsname_last = nsname; - if (specs.ProjectDir == "") - out("#include \"GNDStk/@/@/@.hpp\"", - specs.Version, nsname, clname); - else - out("#include \"@/@/@/@.hpp\"", - specs.ProjectDir, specs.Version, nsname, clname); + out("#include \"@/@/@/@.hpp\"", + specs.Project, specs.Version, nsname, clname); } out(); - if (specs.ProjectDir == "") - out("#include \"GNDStk/@/key.hpp\"", specs.Version); - else - out("#include \"@/@/key.hpp\"", specs.ProjectDir, specs.Version); + out("#include \"@/@/key.hpp\"", specs.Project, specs.Version); out(); out("#endif"); } // fileGNDStkVersion @@ -1994,22 +1963,14 @@ void fileGNDStkKey(const InfoSpecs &specs) writer out(specs.hppKey); out(); - if (specs.ProjectDir == "") { - out("#ifndef NJOY_GNDSTK_@_KEY", allcaps(specs.VersionUnderscore)); - out("#define NJOY_GNDSTK_@_KEY", allcaps(specs.VersionUnderscore)); - } else { - out("#ifndef GUARD_@_@_KEY", - allcaps(specs.ProjectDir), allcaps(specs.VersionUnderscore)); - out("#define GUARD_@_@_KEY", - allcaps(specs.ProjectDir), allcaps(specs.VersionUnderscore)); - } + out("#ifndef @_@_KEY", + allcaps(specs.Project), allcaps(specs.VersionUnderscore)); + out("#define @_@_KEY", + allcaps(specs.Project), allcaps(specs.VersionUnderscore)); out(); - if (specs.ProjectDir == "") { + if (specs.Project == "GNDStk") // <== use namespace njoy only for this out("namespace njoy {"); - out("namespace GNDStk {"); - } else { - out("namespace @ {", specs.ProjectDir); - } + out("namespace @ {", specs.Project); out("namespace @ {", specs.VersionUnderscore); out(); out("using namespace njoy::GNDStk::core;"); @@ -2077,12 +2038,9 @@ void fileGNDStkKey(const InfoSpecs &specs) out(largeComment); out(); out("} // namespace @", specs.VersionUnderscore); - if (specs.ProjectDir == "") { - out("} // namespace GNDStk"); + out("} // namespace @", specs.Project); + if (specs.Project == "GNDStk") // <== end namespace njoy only for this out("} // namespace njoy"); - } else { - out("} // namespace @", specs.ProjectDir); - } out(); out("#endif"); } // fileGNDStkKey @@ -2094,16 +2052,11 @@ void fileGNDStkClass( ) { // class-specific hpp file writer out(per.hppGNDStk); - std::string guard; - if (specs.ProjectDir == "") { - guard = "NJOY_GNDSTK_" + - allcaps(specs.VersionUnderscore) + "_" + - allcaps(per.nsname) + "_" + allcaps(per.clname); - } else { - guard = "GUARD_" + allcaps(specs.ProjectDir) + "_" + - allcaps(specs.VersionUnderscore) + "_" + - allcaps(per.nsname) + "_" + allcaps(per.clname); - } + const std::string guard = + allcaps(specs.Project) + "_" + + allcaps(specs.VersionUnderscore) + "_" + + allcaps(per.nsname) + "_" + + allcaps(per.clname); out(); out("#ifndef @", guard); @@ -2115,35 +2068,23 @@ void fileGNDStkClass( if (c2d.dependencies.size() > 0) { out(); out("// Dependencies"); - if (specs.ProjectDir == "") { - for (const auto &dep : c2d.dependencies) - out("#include \"GNDStk/@/@/@.hpp\"", - specs.Version, dep.nsname, dep.clname); - } else { - for (const auto &dep : c2d.dependencies) - out("#include \"@/@/@/@.hpp\"", - specs.ProjectDir, specs.Version, dep.nsname, dep.clname); - } + for (const auto &dep : c2d.dependencies) + out("#include \"@/@/@/@.hpp\"", + specs.Project, specs.Version, dep.nsname, dep.clname); } out(); - if (specs.ProjectDir == "") { + if (specs.Project == "GNDStk") out("namespace njoy {"); - out("namespace GNDStk {"); - } else { - out("namespace @ {", specs.ProjectDir); - } + out("namespace @ {", specs.Project); out("namespace @ {", specs.VersionUnderscore); out(); out("using namespace njoy::GNDStk::core;"); out(per.code,false); out("} // namespace @", specs.VersionUnderscore); - if (specs.ProjectDir == "") { - out("} // namespace GNDStk"); + out("} // namespace @", specs.Project); + if (specs.Project == "GNDStk") out("} // namespace njoy"); - } else { - out("} // namespace @", specs.ProjectDir); - } out(); out("#endif"); } // fileGNDStkClass @@ -2177,10 +2118,10 @@ void filePythonNamespace(const InfoSpecs &specs, const PerNamespace &per) out(1,"// create the @ submodule", per.nsname); out(1,"python::module submodule = module.def_submodule("); out(2,"\"@\",", per.nsname); - if (specs.ProjectDir == "") - out(2,"\"GNDS @ @\"", specs.Version, per.nsname); + if (specs.Project == "GNDStk") + out(2,"\"GNDS @ @\"", specs.Version, per.nsname); // "GNDS", not "GNDStk" else - out(2,"\"@ @ @\"", specs.ProjectDir, specs.Version, per.nsname); + out(2,"\"@ @ @\"", specs.Project, specs.Version, per.nsname); out(1,");"); out(); @@ -2269,12 +2210,8 @@ void filePythonClass(const InfoSpecs &specs, const PerClass &per) out(); out("// local includes"); - if (specs.ProjectDir == "") - out("#include \"GNDStk/@/@/@.hpp\"", - specs.Version, nsname, clname); - else - out("#include \"@/@/@/@.hpp\"", - specs.ProjectDir, specs.Version, nsname, clname); + out("#include \"@/@/@/@.hpp\"", + specs.Project, specs.Version, nsname, clname); out("#include \"definitions.hpp\""); out(); @@ -2289,13 +2226,10 @@ void filePythonClass(const InfoSpecs &specs, const PerClass &per) out("// @ wrapper", clname); out("void wrap@(python::module &module)", clname); out("{"); - if (specs.ProjectDir == "") { - out(1,"using namespace njoy::GNDStk;"); - out(1,"using namespace njoy::GNDStk::@;", specs.VersionUnderscore); - } else { - out(1,"using namespace @;", specs.ProjectDir); - out(1,"using namespace @::@;", specs.ProjectDir, specs.VersionUnderscore); - } + const std::string prefix = specs.Project == "GNDStk" ? "njoy::" : ""; + out(1,"using namespace @@;", prefix, specs.Project); + out(1,"using namespace @@::@;", + prefix, specs.Project, specs.VersionUnderscore); out(); out(1,"// type aliases"); out(1,"using Component = @::@;", nsname, clname); diff --git a/autogen/prototype.json b/autogen/prototype.json index 856a88ec1..c09994388 100644 --- a/autogen/prototype.json +++ b/autogen/prototype.json @@ -1,20 +1,27 @@ { "comment" : [ - "GNDSDir", - " Base GNDStk directory into which the autogenerator tool", - " should place src/GNDStk/version.hpp and src/GNDStk/version/*", + "Path", + " Path to the Project directory.", + " Optional (defaults to .).", + "", + "Project", + " Base project directory into which the code generator should", + " place files. IMPORTANT: this should be a **plain** name only,", + " without any directory path. Use Path for that, if it's needed.", + " Optional (defaults to GNDStk).", "", "JSONDir", " Directory where the listed .json input files are located", "", "TO AUTOGENERATE THE PROTOTYPE IN THE REAL GNDStk HIERARCHY", - " Set GNDSDir to .. if you run json2class.exe from within", - " GNDStk/autogen/, where GNDStk/ is the cloned repository", + " Set Path to ../.. if you run json2class.exe from within", + " GNDStk/autogen/, where GNDStk/ is the cloned repository.", + " This (../..) is where GNDStk is located.", "", - "Do NOT end the directories (JSONDir and GNDSDir) with a /" + "Do NOT end directories with a /" ], - "GNDSDir": "..", + "Path": "../..", "Version": "v1.9", "JSONDir": "prototype", @@ -22,5 +29,6 @@ "generalPurpose.json", "reactionSuite.json" ], + "Changes": "changes.json" } diff --git a/python/src/v1.9/transport/ReactionSuite.python.cpp b/python/src/v1.9/transport/ReactionSuite.python.cpp index 664310fc2..894e0e0d4 100644 --- a/python/src/v1.9/transport/ReactionSuite.python.cpp +++ b/python/src/v1.9/transport/ReactionSuite.python.cpp @@ -88,23 +88,6 @@ void wrapReactionSuite(python::module &module) python::overload_cast<>(&Component::reactions), Component::documentation("reactions").data() ) - .def_static( - - "from_file", - [] ( const std::string& filename ) -> Component { - - using namespace njoy::GNDStk::core; - Tree tree( filename ); - - return Component( tree( child::reactionSuite ) ); - }, - python::arg( "filename" ), - "Read a reaction suite from an XML or json file\n\n" - "An exception is raised if something goes wrong while reading the\n" - "component\n\n" - "Arguments:\n" - " filename the name of the file" - ) ; // add standard component definitions diff --git a/src/GNDStk/v1.9.hpp b/src/GNDStk/v1.9.hpp index a38502179..641ac82b7 100644 --- a/src/GNDStk/v1.9.hpp +++ b/src/GNDStk/v1.9.hpp @@ -2,8 +2,8 @@ // THIS FILE WAS AUTOGENERATED! // DO NOT MODIFY! -#ifndef NJOY_GNDSTK_V1_9 -#define NJOY_GNDSTK_V1_9 +#ifndef GNDSTK_V1_9 +#define GNDSTK_V1_9 #include "GNDStk/v1.9/containers/Axes.hpp" #include "GNDStk/v1.9/containers/Axis.hpp" diff --git a/src/GNDStk/v1.9/containers/Axes.hpp b/src/GNDStk/v1.9/containers/Axes.hpp index cee1b9753..36743f775 100644 --- a/src/GNDStk/v1.9/containers/Axes.hpp +++ b/src/GNDStk/v1.9/containers/Axes.hpp @@ -2,13 +2,13 @@ // THIS FILE WAS AUTOGENERATED! // DO NOT MODIFY! -#ifndef NJOY_GNDSTK_V1_9_CONTAINERS_AXES -#define NJOY_GNDSTK_V1_9_CONTAINERS_AXES +#ifndef GNDSTK_V1_9_CONTAINERS_AXES +#define GNDSTK_V1_9_CONTAINERS_AXES -// core interface +// GNDStk Core Interface #include "GNDStk.hpp" -// v1.9 dependencies +// Dependencies #include "GNDStk/v1.9/containers/Axis.hpp" #include "GNDStk/v1.9/containers/Grid.hpp" @@ -164,6 +164,10 @@ class Axes : public Component { axis_grid(label) = obj; return *this; } + // axis_grid(value) for vector push_back + Axes &axis_grid(const axis_grid_t &obj) + { setter(axis_grid(), obj); return *this; } + // axis(index,value) Axes &axis( const std::size_t index, @@ -201,15 +205,24 @@ class Axes : public Component { } // ------------------------ - // Construction + // Constructors // ------------------------ - // default - Axes() : + // default, and from fields + explicit Axes( + const std::optional &href = + std::optional{}, + const std::vector &axis_grid = + std::vector{} + ) : Component{ BodyText{}, content.href, content.axis_grid + }, + content{ + href, + axis_grid } { Component::finish(); @@ -250,24 +263,6 @@ class Axes : public Component { Component::finish(node); } - // from fields - explicit Axes( - const std::optional &href, - const std::vector &axis_grid - ) : - Component{ - BodyText{}, - content.href, - content.axis_grid - }, - content{ - href, - axis_grid - } - { - Component::finish(); - } - // ------------------------ // Assignment // ------------------------ diff --git a/src/GNDStk/v1.9/containers/Axis.hpp b/src/GNDStk/v1.9/containers/Axis.hpp index 2fb9d900f..db63421da 100644 --- a/src/GNDStk/v1.9/containers/Axis.hpp +++ b/src/GNDStk/v1.9/containers/Axis.hpp @@ -2,10 +2,10 @@ // THIS FILE WAS AUTOGENERATED! // DO NOT MODIFY! -#ifndef NJOY_GNDSTK_V1_9_CONTAINERS_AXIS -#define NJOY_GNDSTK_V1_9_CONTAINERS_AXIS +#ifndef GNDSTK_V1_9_CONTAINERS_AXIS +#define GNDSTK_V1_9_CONTAINERS_AXIS -// core interface +// GNDStk Core Interface #include "GNDStk.hpp" namespace njoy { @@ -25,7 +25,6 @@ namespace containers { class Axis : public Component { - // ------------------------ // For Component // ------------------------ @@ -116,16 +115,28 @@ class Axis : public Component { { unit() = obj; return *this; } // ------------------------ - // Construction + // Constructors // ------------------------ - // default - Axis() : + // default, and from fields + explicit Axis( + const std::optional &index = + std::optional{}, + const std::optional &label = + std::optional{}, + const std::optional &unit = + std::optional{} + ) : Component{ BodyText{}, content.index, content.label, content.unit + }, + content{ + index, + label, + unit } { Component::finish(); @@ -169,27 +180,6 @@ class Axis : public Component { Component::finish(node); } - // from fields - explicit Axis( - const std::optional &index, - const std::optional &label, - const std::optional &unit - ) : - Component{ - BodyText{}, - content.index, - content.label, - content.unit - }, - content{ - index, - label, - unit - } - { - Component::finish(); - } - // ------------------------ // Assignment // ------------------------ diff --git a/src/GNDStk/v1.9/containers/Grid.hpp b/src/GNDStk/v1.9/containers/Grid.hpp index bf20dbf93..a77a58558 100644 --- a/src/GNDStk/v1.9/containers/Grid.hpp +++ b/src/GNDStk/v1.9/containers/Grid.hpp @@ -2,13 +2,13 @@ // THIS FILE WAS AUTOGENERATED! // DO NOT MODIFY! -#ifndef NJOY_GNDSTK_V1_9_CONTAINERS_GRID -#define NJOY_GNDSTK_V1_9_CONTAINERS_GRID +#ifndef GNDSTK_V1_9_CONTAINERS_GRID +#define GNDSTK_V1_9_CONTAINERS_GRID -// core interface +// GNDStk Core Interface #include "GNDStk.hpp" -// v1.9 dependencies +// Dependencies #include "GNDStk/v1.9/containers/Link.hpp" #include "GNDStk/v1.9/containers/Values.hpp" @@ -188,11 +188,25 @@ class Grid : public Component { { if (obj) link_values(obj.value()); return *this; } // ------------------------ - // Construction + // Constructors // ------------------------ - // default - Grid() : + // default, and from fields + // std::optional replaces Defaulted; this class knows the default(s) + explicit Grid( + const std::optional &index = + std::optional{}, + const std::optional &interpolation = + std::optional{}, + const std::optional &label = + std::optional{}, + const std::optional &style = + std::optional{}, + const std::optional &unit = + std::optional{}, + const link_values_t &link_values = + link_values_t{} + ) : Component{ BodyText{}, content.index, @@ -201,6 +215,14 @@ class Grid : public Component { content.style, content.unit, content.link_values + }, + content{ + index, + Defaulted(defaults.interpolation,interpolation), + label, + style, + unit, + link_values } { Component::finish(); @@ -253,37 +275,6 @@ class Grid : public Component { Component::finish(node); } - // from fields - // std::optional replaces Defaulted; this class knows the default(s) - explicit Grid( - const std::optional &index, - const std::optional &interpolation, - const std::optional &label, - const std::optional &style, - const std::optional &unit, - const link_values_t &link_values - ) : - Component{ - BodyText{}, - content.index, - content.interpolation, - content.label, - content.style, - content.unit, - content.link_values - }, - content{ - index, - Defaulted(defaults.interpolation,interpolation), - label, - style, - unit, - link_values - } - { - Component::finish(); - } - // ------------------------ // Assignment // ------------------------ diff --git a/src/GNDStk/v1.9/containers/Link.hpp b/src/GNDStk/v1.9/containers/Link.hpp index 0367513d2..f5ba82bc4 100644 --- a/src/GNDStk/v1.9/containers/Link.hpp +++ b/src/GNDStk/v1.9/containers/Link.hpp @@ -2,10 +2,10 @@ // THIS FILE WAS AUTOGENERATED! // DO NOT MODIFY! -#ifndef NJOY_GNDSTK_V1_9_CONTAINERS_LINK -#define NJOY_GNDSTK_V1_9_CONTAINERS_LINK +#ifndef GNDSTK_V1_9_CONTAINERS_LINK +#define GNDSTK_V1_9_CONTAINERS_LINK -// core interface +// GNDStk Core Interface #include "GNDStk.hpp" namespace njoy { @@ -25,7 +25,6 @@ namespace containers { class Link : public Component { - // ------------------------ // For Component // ------------------------ @@ -90,14 +89,20 @@ class Link : public Component { { href() = obj; return *this; } // ------------------------ - // Construction + // Constructors // ------------------------ - // default - Link() : + // default, and from fields + explicit Link( + const std::string &href = + std::string{} + ) : Component{ BodyText{}, content.href + }, + content{ + href } { Component::finish(); @@ -135,21 +140,6 @@ class Link : public Component { Component::finish(node); } - // from fields - explicit Link( - const std::string &href - ) : - Component{ - BodyText{}, - content.href - }, - content{ - href - } - { - Component::finish(); - } - // ------------------------ // Assignment // ------------------------ diff --git a/src/GNDStk/v1.9/containers/Regions1d.hpp b/src/GNDStk/v1.9/containers/Regions1d.hpp index c1a3c1002..251262d72 100644 --- a/src/GNDStk/v1.9/containers/Regions1d.hpp +++ b/src/GNDStk/v1.9/containers/Regions1d.hpp @@ -2,13 +2,13 @@ // THIS FILE WAS AUTOGENERATED! // DO NOT MODIFY! -#ifndef NJOY_GNDSTK_V1_9_CONTAINERS_REGIONS1D -#define NJOY_GNDSTK_V1_9_CONTAINERS_REGIONS1D +#ifndef GNDSTK_V1_9_CONTAINERS_REGIONS1D +#define GNDSTK_V1_9_CONTAINERS_REGIONS1D -// core interface +// GNDStk Core Interface #include "GNDStk.hpp" -// v1.9 dependencies +// Dependencies #include "GNDStk/v1.9/containers/XYs1d.hpp" #include "GNDStk/v1.9/containers/Axes.hpp" @@ -29,7 +29,6 @@ namespace containers { class Regions1d : public Component { - // ------------------------ // For Component // ------------------------ @@ -158,22 +157,41 @@ class Regions1d : public Component { XYs1d(label) = obj; return *this; } + // XYs1d(value) for vector push_back + Regions1d &XYs1d(const containers::XYs1d &obj) + { setter(XYs1d(), obj); return *this; } + // axes(value) Regions1d &axes(const std::optional &obj) { axes() = obj; return *this; } // ------------------------ - // Construction + // Constructors // ------------------------ - // default - Regions1d() : + // default, and from fields + explicit Regions1d( + const std::optional &label = + std::optional{}, + const std::optional &outerDomainValue = + std::optional{}, + const std::vector &XYs1d = + std::vector{}, + const std::optional &axes = + std::optional{} + ) : Component{ BodyText{}, content.label, content.outerDomainValue, content.XYs1d, content.axes + }, + content{ + label, + outerDomainValue, + XYs1d, + axes } { Component::finish(); @@ -220,30 +238,6 @@ class Regions1d : public Component { Component::finish(node); } - // from fields - explicit Regions1d( - const std::optional &label, - const std::optional &outerDomainValue, - const std::vector &XYs1d, - const std::optional &axes - ) : - Component{ - BodyText{}, - content.label, - content.outerDomainValue, - content.XYs1d, - content.axes - }, - content{ - label, - outerDomainValue, - XYs1d, - axes - } - { - Component::finish(); - } - // ------------------------ // Assignment // ------------------------ diff --git a/src/GNDStk/v1.9/containers/Values.hpp b/src/GNDStk/v1.9/containers/Values.hpp index 257ea0d1e..f3d987e3a 100644 --- a/src/GNDStk/v1.9/containers/Values.hpp +++ b/src/GNDStk/v1.9/containers/Values.hpp @@ -2,10 +2,10 @@ // THIS FILE WAS AUTOGENERATED! // DO NOT MODIFY! -#ifndef NJOY_GNDSTK_V1_9_CONTAINERS_VALUES -#define NJOY_GNDSTK_V1_9_CONTAINERS_VALUES +#ifndef GNDSTK_V1_9_CONTAINERS_VALUES +#define GNDSTK_V1_9_CONTAINERS_VALUES -// core interface +// GNDStk Core Interface #include "GNDStk.hpp" namespace njoy { @@ -25,7 +25,6 @@ namespace containers { class Values : public Component { - // ------------------------ // For Component // ------------------------ @@ -123,16 +122,29 @@ class Values : public Component { { BodyText::valueType(content.valueType = obj); return *this; } // ------------------------ - // Construction + // Constructors // ------------------------ - // default - Values() : + // default, and from fields + // std::optional replaces Defaulted; this class knows the default(s) + explicit Values( + const std::optional &length = + std::optional{}, + const std::optional &start = + std::optional{}, + const std::optional &valueType = + std::optional{} + ) : Component{ BodyText{}, content.length, content.start, content.valueType + }, + content{ + length, + Defaulted(defaults.start,start), + Defaulted(defaults.valueType,valueType) } { Component::finish(); @@ -176,28 +188,6 @@ class Values : public Component { Component::finish(node); } - // from fields - // std::optional replaces Defaulted; this class knows the default(s) - explicit Values( - const std::optional &length, - const std::optional &start, - const std::optional &valueType - ) : - Component{ - BodyText{}, - content.length, - content.start, - content.valueType - }, - content{ - length, - Defaulted(defaults.start,start), - Defaulted(defaults.valueType,valueType) - } - { - Component::finish(); - } - // from vector template>> Values(const std::vector &vector) : diff --git a/src/GNDStk/v1.9/containers/XYs1d.hpp b/src/GNDStk/v1.9/containers/XYs1d.hpp index 6cf404257..7e0d294e6 100644 --- a/src/GNDStk/v1.9/containers/XYs1d.hpp +++ b/src/GNDStk/v1.9/containers/XYs1d.hpp @@ -2,13 +2,13 @@ // THIS FILE WAS AUTOGENERATED! // DO NOT MODIFY! -#ifndef NJOY_GNDSTK_V1_9_CONTAINERS_XYS1D -#define NJOY_GNDSTK_V1_9_CONTAINERS_XYS1D +#ifndef GNDSTK_V1_9_CONTAINERS_XYS1D +#define GNDSTK_V1_9_CONTAINERS_XYS1D -// core interface +// GNDStk Core Interface #include "GNDStk.hpp" -// v1.9 dependencies +// Dependencies #include "GNDStk/v1.9/containers/Axes.hpp" #include "GNDStk/v1.9/containers/Values.hpp" @@ -29,7 +29,6 @@ namespace containers { class XYs1d : public Component { - // ------------------------ // For Component // ------------------------ @@ -164,11 +163,25 @@ class XYs1d : public Component { { values() = obj; return *this; } // ------------------------ - // Construction + // Constructors // ------------------------ - // default - XYs1d() : + // default, and from fields + // std::optional replaces Defaulted; this class knows the default(s) + explicit XYs1d( + const std::optional &index = + std::optional{}, + const std::optional &interpolation = + std::optional{}, + const std::optional &label = + std::optional{}, + const std::optional &outerDomainValue = + std::optional{}, + const std::optional &axes = + std::optional{}, + const containers::Values &values = + containers::Values{} + ) : Component{ BodyText{}, content.index, @@ -177,6 +190,14 @@ class XYs1d : public Component { content.outerDomainValue, content.axes, content.values + }, + content{ + index, + Defaulted(defaults.interpolation,interpolation), + label, + outerDomainValue, + axes, + values } { Component::finish(); @@ -229,37 +250,6 @@ class XYs1d : public Component { Component::finish(node); } - // from fields - // std::optional replaces Defaulted; this class knows the default(s) - explicit XYs1d( - const std::optional &index, - const std::optional &interpolation, - const std::optional &label, - const std::optional &outerDomainValue, - const std::optional &axes, - const containers::Values &values - ) : - Component{ - BodyText{}, - content.index, - content.interpolation, - content.label, - content.outerDomainValue, - content.axes, - content.values - }, - content{ - index, - Defaulted(defaults.interpolation,interpolation), - label, - outerDomainValue, - axes, - values - } - { - Component::finish(); - } - // ------------------------ // Assignment // ------------------------ diff --git a/src/GNDStk/v1.9/key.hpp b/src/GNDStk/v1.9/key.hpp index 214b239e0..fef5c5206 100644 --- a/src/GNDStk/v1.9/key.hpp +++ b/src/GNDStk/v1.9/key.hpp @@ -2,35 +2,15 @@ // THIS FILE WAS AUTOGENERATED! // DO NOT MODIFY! -/* -This file contains Meta and Child objects for metadata and child nodes in the -current GNDS version. These may prove to be useful if you wish to use the Core -Interface in conjunction with the autogenerated classes for this GNDS version. - -Within the outer njoy::GNDStk::version namespace below, the remaining namespace -arrangement was chosen to make the use of these objects smooth and logical. - -Meta and Child objects are collectively called "keys." Meta keys are placed -into key::meta. Child keys correspond to autogenerated classes, each of which -is already in some namespace; we thus use theNamespace::key::child::. That way, -an autogenerated class [ns::Foo] has [ns::key::foo] as its Child object, and -a "using namespace ns" allows the class and the Child object to be [Foo] and -[key::foo], respectively. (If we reordered ns:: and key::, that wouldn't work.) - -Within key::, we use meta:: and child:: around Meta and Child objects, just in -case there exist any identical GNDS metadata names and child-node names. (That -can, in fact, happen). The "using namespace meta" and "using namespace child" -directives then make the Meta<> and Child<> objects appear directly in key::, -so that "meta::" and "child::" are needed only to disambiguate identical names. -*/ - -#ifndef NJOY_GNDSTK_V1_9_KEY -#define NJOY_GNDSTK_V1_9_KEY +#ifndef GNDSTK_V1_9_KEY +#define GNDSTK_V1_9_KEY namespace njoy { namespace GNDStk { namespace v1_9 { +using namespace njoy::GNDStk::core; + // ----------------------------------------------------------------------------- // key::meta:: diff --git a/src/GNDStk/v1.9/transport/CrossSection.hpp b/src/GNDStk/v1.9/transport/CrossSection.hpp index 12aeb298f..39ecb5650 100644 --- a/src/GNDStk/v1.9/transport/CrossSection.hpp +++ b/src/GNDStk/v1.9/transport/CrossSection.hpp @@ -2,13 +2,13 @@ // THIS FILE WAS AUTOGENERATED! // DO NOT MODIFY! -#ifndef NJOY_GNDSTK_V1_9_TRANSPORT_CROSSSECTION -#define NJOY_GNDSTK_V1_9_TRANSPORT_CROSSSECTION +#ifndef GNDSTK_V1_9_TRANSPORT_CROSSSECTION +#define GNDSTK_V1_9_TRANSPORT_CROSSSECTION -// core interface +// GNDStk Core Interface #include "GNDStk.hpp" -// v1.9 dependencies +// Dependencies #include "GNDStk/v1.9/containers/XYs1d.hpp" #include "GNDStk/v1.9/containers/Regions1d.hpp" @@ -149,6 +149,10 @@ class CrossSection : public Component { XYs1d_regions1d(label) = obj; return *this; } + // XYs1d_regions1d(value) for vector push_back + CrossSection &XYs1d_regions1d(const XYs1d_regions1d_t &obj) + { setter(XYs1d_regions1d(), obj); return *this; } + // XYs1d(index,value) CrossSection &XYs1d( const std::size_t index, @@ -186,14 +190,20 @@ class CrossSection : public Component { } // ------------------------ - // Construction + // Constructors // ------------------------ - // default - CrossSection() : + // default, and from fields + explicit CrossSection( + const std::vector &XYs1d_regions1d = + std::vector{} + ) : Component{ BodyText{}, content.XYs1d_regions1d + }, + content{ + XYs1d_regions1d } { Component::finish(); @@ -231,21 +241,6 @@ class CrossSection : public Component { Component::finish(node); } - // from fields - explicit CrossSection( - const std::vector &XYs1d_regions1d - ) : - Component{ - BodyText{}, - content.XYs1d_regions1d - }, - content{ - XYs1d_regions1d - } - { - Component::finish(); - } - // ------------------------ // Assignment // ------------------------ diff --git a/src/GNDStk/v1.9/transport/Reaction.hpp b/src/GNDStk/v1.9/transport/Reaction.hpp index bb15a3f88..99cd2a72a 100644 --- a/src/GNDStk/v1.9/transport/Reaction.hpp +++ b/src/GNDStk/v1.9/transport/Reaction.hpp @@ -2,13 +2,13 @@ // THIS FILE WAS AUTOGENERATED! // DO NOT MODIFY! -#ifndef NJOY_GNDSTK_V1_9_TRANSPORT_REACTION -#define NJOY_GNDSTK_V1_9_TRANSPORT_REACTION +#ifndef GNDSTK_V1_9_TRANSPORT_REACTION +#define GNDSTK_V1_9_TRANSPORT_REACTION -// core interface +// GNDStk Core Interface #include "GNDStk.hpp" -// v1.9 dependencies +// Dependencies #include "GNDStk/v1.9/transport/CrossSection.hpp" namespace njoy { @@ -28,7 +28,6 @@ namespace transport { class Reaction : public Component { - // ------------------------ // For Component // ------------------------ @@ -134,17 +133,32 @@ class Reaction : public Component { { crossSection() = obj; return *this; } // ------------------------ - // Construction + // Constructors // ------------------------ - // default - Reaction() : + // default, and from fields + explicit Reaction( + const int &ENDF_MT = + int{}, + const std::optional &fissionGenre = + std::optional{}, + const std::string &label = + std::string{}, + const transport::CrossSection &crossSection = + transport::CrossSection{} + ) : Component{ BodyText{}, content.ENDF_MT, content.fissionGenre, content.label, content.crossSection + }, + content{ + ENDF_MT, + fissionGenre, + label, + crossSection } { Component::finish(); @@ -191,30 +205,6 @@ class Reaction : public Component { Component::finish(node); } - // from fields - explicit Reaction( - const int &ENDF_MT, - const std::optional &fissionGenre, - const std::string &label, - const transport::CrossSection &crossSection - ) : - Component{ - BodyText{}, - content.ENDF_MT, - content.fissionGenre, - content.label, - content.crossSection - }, - content{ - ENDF_MT, - fissionGenre, - label, - crossSection - } - { - Component::finish(); - } - // ------------------------ // Assignment // ------------------------ diff --git a/src/GNDStk/v1.9/transport/ReactionSuite.hpp b/src/GNDStk/v1.9/transport/ReactionSuite.hpp index 86601b7d2..f6143d338 100644 --- a/src/GNDStk/v1.9/transport/ReactionSuite.hpp +++ b/src/GNDStk/v1.9/transport/ReactionSuite.hpp @@ -2,13 +2,13 @@ // THIS FILE WAS AUTOGENERATED! // DO NOT MODIFY! -#ifndef NJOY_GNDSTK_V1_9_TRANSPORT_REACTIONSUITE -#define NJOY_GNDSTK_V1_9_TRANSPORT_REACTIONSUITE +#ifndef GNDSTK_V1_9_TRANSPORT_REACTIONSUITE +#define GNDSTK_V1_9_TRANSPORT_REACTIONSUITE -// core interface +// GNDStk Core Interface #include "GNDStk.hpp" -// v1.9 dependencies +// Dependencies #include "GNDStk/v1.9/transport/Reactions.hpp" namespace njoy { @@ -28,7 +28,6 @@ namespace transport { class ReactionSuite : public Component { - // ------------------------ // For Component // ------------------------ @@ -173,11 +172,26 @@ class ReactionSuite : public Component { { reactions() = obj; return *this; } // ------------------------ - // Construction + // Constructors // ------------------------ - // default - ReactionSuite() : + // default, and from fields + explicit ReactionSuite( + const std::string &evaluation = + std::string{}, + const std::string &format = + std::string{}, + const std::optional &interaction = + std::optional{}, + const std::string &projectile = + std::string{}, + const enums::Frame &projectileFrame = + enums::Frame{}, + const std::string &target = + std::string{}, + const std::optional &reactions = + std::optional{} + ) : Component{ BodyText{}, content.evaluation, @@ -187,6 +201,15 @@ class ReactionSuite : public Component { content.projectileFrame, content.target, content.reactions + }, + content{ + evaluation, + format, + interaction, + projectile, + projectileFrame, + target, + reactions } { Component::finish(); @@ -242,39 +265,6 @@ class ReactionSuite : public Component { Component::finish(node); } - // from fields - explicit ReactionSuite( - const std::string &evaluation, - const std::string &format, - const std::optional &interaction, - const std::string &projectile, - const enums::Frame &projectileFrame, - const std::string &target, - const std::optional &reactions - ) : - Component{ - BodyText{}, - content.evaluation, - content.format, - content.interaction, - content.projectile, - content.projectileFrame, - content.target, - content.reactions - }, - content{ - evaluation, - format, - interaction, - projectile, - projectileFrame, - target, - reactions - } - { - Component::finish(); - } - // ------------------------ // Assignment // ------------------------ diff --git a/src/GNDStk/v1.9/transport/Reactions.hpp b/src/GNDStk/v1.9/transport/Reactions.hpp index bf92b5bdc..80576766e 100644 --- a/src/GNDStk/v1.9/transport/Reactions.hpp +++ b/src/GNDStk/v1.9/transport/Reactions.hpp @@ -2,13 +2,13 @@ // THIS FILE WAS AUTOGENERATED! // DO NOT MODIFY! -#ifndef NJOY_GNDSTK_V1_9_TRANSPORT_REACTIONS -#define NJOY_GNDSTK_V1_9_TRANSPORT_REACTIONS +#ifndef GNDSTK_V1_9_TRANSPORT_REACTIONS +#define GNDSTK_V1_9_TRANSPORT_REACTIONS -// core interface +// GNDStk Core Interface #include "GNDStk.hpp" -// v1.9 dependencies +// Dependencies #include "GNDStk/v1.9/transport/Reaction.hpp" namespace njoy { @@ -28,7 +28,6 @@ namespace transport { class Reactions : public Component { - // ------------------------ // For Component // ------------------------ @@ -120,15 +119,25 @@ class Reactions : public Component { reaction(label) = obj; return *this; } + // reaction(value) for vector push_back + Reactions &reaction(const transport::Reaction &obj) + { setter(reaction(), obj); return *this; } + // ------------------------ - // Construction + // Constructors // ------------------------ - // default - Reactions() : + // default, and from fields + explicit Reactions( + const std::vector &reaction = + std::vector{} + ) : Component{ BodyText{}, content.reaction + }, + content{ + reaction } { Component::finish(); @@ -166,21 +175,6 @@ class Reactions : public Component { Component::finish(node); } - // from fields - explicit Reactions( - const std::vector &reaction - ) : - Component{ - BodyText{}, - content.reaction - }, - content{ - reaction - } - { - Component::finish(); - } - // ------------------------ // Assignment // ------------------------ From f74e57886de9d2a9640741ab8b7b4a3972d67904 Mon Sep 17 00:00:00 2001 From: Martin Staley Date: Mon, 6 Dec 2021 11:33:31 -0700 Subject: [PATCH 16/39] Code generator changes to support data-only nodes. That is to say, classes that have no metadata or child nodes, but still have data, e.g. with 1.2 3.4 5.6. OCD'd a cmake-related file. Some more work regarding HDF5 format. Still not entirely complete. I think ".hdf"/".HDF" aren't used as HDF5 file extensions. They need a '5'. Made some diagnostic-message terminology more consistent. --- autogen/json2class.cpp | 34 +++++++++++---- cmake/GNDStk_dependencies.cmake | 42 +++++++++---------- docs/primer.rst | 8 ++-- src/GNDStk.hpp | 2 +- src/GNDStk/BodyText/src/get.hpp | 6 ++- src/GNDStk/Component.hpp | 10 ++++- src/GNDStk/Component/src/ctor.hpp | 2 +- src/GNDStk/Component/src/detail.hpp | 1 - src/GNDStk/Component/src/fromNode.hpp | 2 +- src/GNDStk/Component/src/sort.hpp | 2 +- src/GNDStk/Component/src/toNodeBody.hpp | 2 +- src/GNDStk/Component/src/write.hpp | 2 +- src/GNDStk/HDF5.hpp | 9 ++-- src/GNDStk/HDF5/src/read.hpp | 2 +- src/GNDStk/HDF5/src/write.hpp | 6 +-- src/GNDStk/Node/src/detail.hpp | 6 +-- src/GNDStk/Tree/src/reset.hpp | 8 ++-- src/GNDStk/common/src/detail.hpp | 2 +- src/GNDStk/convert.hpp | 2 +- src/GNDStk/convert/src/HDF5.hpp | 4 +- src/GNDStk/convert/src/{tree.hpp => Tree.hpp} | 4 +- src/GNDStk/utility.hpp | 7 +--- 22 files changed, 91 insertions(+), 72 deletions(-) rename src/GNDStk/convert/src/{tree.hpp => Tree.hpp} (98%) diff --git a/autogen/json2class.cpp b/autogen/json2class.cpp index b500d6fe4..74d20b212 100644 --- a/autogen/json2class.cpp +++ b/autogen/json2class.cpp @@ -1231,10 +1231,10 @@ void writeClassSetters(writer &out, const PerClass &per) // writeClassCtorComponent void writeClassCtorComponent( - writer &out, const PerClass &per, const bool hasOther + writer &out, const PerClass &per, const bool copyOrMove ) { out(2,"Component{"); - out(3, hasOther ? "other" : "BodyText{}", false); + out(3, copyOrMove ? "other.baseBodyText()" : "BodyText{}", false); for (const auto &m : per.metadata) { // metadata out(","); @@ -1272,8 +1272,14 @@ void writeClassCtors(writer &out, const PerClass &per) // ------------------------ const auto total = per.nfields(); - if (total != 0) { + out(); + + if (total == 0) { + out(1,"// default"); + out(1,"@() :", per.clname); + writeClassCtorComponent(out, per, false); out(); + } else { out(1,"// default, and from fields"); // informational message, if applicable @@ -1321,11 +1327,11 @@ void writeClassCtors(writer &out, const PerClass &per) for (const auto &v : per.variants) out(3,"@@", v.name, ++count < total ? "," : ""); out(2,"}"); - - // body - writeClassCtorBody(out, ""); } + // body + writeClassCtorBody(out, ""); + // ------------------------ // ctor: copy // ------------------------ @@ -1567,9 +1573,11 @@ void printSingletons(const std::string &file) const auto metadata = getMetadataJSON(rhs); const auto children = getChildrenJSON(rhs); + const bool data = rhs.contains("data") && !rhs["data"].is_null(); + const bool body = rhs.contains("bodyText") && !rhs["bodyText"].is_null(); - if (metadata.size() == 0 && children.size() == 0) - log::info("Class \"{}\" has no metadata and no children", parent); + if (metadata.size() == 0 && children.size() == 0 && !data && !body) + log::info("Class \"{}\" has no metadata, children, or data", parent); if (metadata.size() == 0 && children.size() == 1) log::info("Class \"{}\" has no metadata and just one child", parent); } @@ -1821,7 +1829,15 @@ void getClass( const bool body = classRHS.contains(bodystr) && !classRHS[bodystr].is_null(); assert(!(data && body)); // not both per.isData = data || body; - per.dataType = data ? classRHS[datastr] : ""; + if (data) { + // A type change, as with metadata, could be wanted in this context as + // well. Perhaps the name "mapMetaType" (and the location and name for + // it in the changes.json file) should be modified to reflect this + const std::string type = classRHS[datastr]; + const auto it = specs.mapMetaType.find(type); + per.dataType = it == specs.mapMetaType.end() ? type : it->second; + } else + per.dataType = ""; // per.code will contain printed C++ code for the class itself writeClass(per,specs); diff --git a/cmake/GNDStk_dependencies.cmake b/cmake/GNDStk_dependencies.cmake index 3b64e7ace..722310e9c 100644 --- a/cmake/GNDStk_dependencies.cmake +++ b/cmake/GNDStk_dependencies.cmake @@ -10,28 +10,28 @@ include( FetchContent ) # Declare project dependencies ######################################################################## -FetchContent_Declare( catch-adapter - GIT_REPOSITORY http://github.com/njoy/catch-adapter - GIT_TAG origin/master - GIT_SHALLOW TRUE +FetchContent_Declare(catch-adapter + GIT_REPOSITORY http://github.com/njoy/catch-adapter + GIT_TAG origin/master + GIT_SHALLOW TRUE ) -FetchContent_Declare( Log - GIT_REPOSITORY http://github.com/njoy/Log - GIT_TAG origin/build/fetchcontent - GIT_SHALLOW TRUE +FetchContent_Declare(Log + GIT_REPOSITORY http://github.com/njoy/Log + GIT_TAG origin/build/fetchcontent + GIT_SHALLOW TRUE ) -FetchContent_Declare( pugixml-adapter - GIT_REPOSITORY http://github.com/njoy/pugixml-adapter - GIT_TAG origin/master - GIT_SHALLOW TRUE +FetchContent_Declare(pugixml-adapter + GIT_REPOSITORY http://github.com/njoy/pugixml-adapter + GIT_TAG origin/master + GIT_SHALLOW TRUE ) FetchContent_Declare(json - GIT_REPOSITORY https://github.com/nlohmann/json.git - GIT_TAG v3.7.3 - GIT_SHALLOW true + GIT_REPOSITORY https://github.com/nlohmann/json.git + GIT_TAG v3.7.3 + GIT_SHALLOW TRUE ) FetchContent_GetProperties(json) @@ -46,14 +46,14 @@ FetchContent_Declare(hdf5 GIT_TAG origin/master GIT_SHALLOW TRUE ) -set( HIGHFIVE_USE_BOOST OFF CACHE INTERNAL "" ) +set( HIGHFIVE_USE_BOOST OFF CACHE INTERNAL "" ) set( HIGHFIVE_UNIT_TESTS OFF CACHE INTERNAL "" ) -set( HIGHFIVE_EXAMPLES OFF CACHE INTERNAL "" ) +set( HIGHFIVE_EXAMPLES OFF CACHE INTERNAL "" ) -FetchContent_Declare( pybind11 - GIT_REPOSITORY https://github.com/pybind/pybind11 - GIT_TAG v2.6.1 - GIT_SHALLOW TRUE +FetchContent_Declare(pybind11 + GIT_REPOSITORY https://github.com/pybind/pybind11 + GIT_TAG v2.6.1 + GIT_SHALLOW TRUE ) diff --git a/docs/primer.rst b/docs/primer.rst index 724fb8f2b..3de4cfd7b 100644 --- a/docs/primer.rst +++ b/docs/primer.rst @@ -262,8 +262,6 @@ or can be a direct string: ``"xml"``, etc. A direct string is shorter and slightly easier to type -- but, if mistyped, would lead to a run-time error, not a compile-time error, if that matters to you in this simple context. -**HDF5 is not supported at this time!** Just XML and JSON. - *You should seldom, if ever, need to provide the second argument*. Absent the second argument, **GNDStk determines the file type automatically**, and we doubt that you'll have any objections to that. If you do choose provide the second @@ -276,9 +274,9 @@ as we attempt to read the file pursuant to the (incorrect) forced format. GNDStk uses the "file magic number," not the file name, to determine file type automatically. The file magic number really means the first byte, or bytes, -of the file. XML files always begin with a ``<`` character. HDF files (not -supported yet) begin with ASCII 137 and a few other specific bytes. If the -first byte is neither of those values, then GNDStk assumes JSON format. +of the file. XML files always begin with a ``<`` character. HDF5 files begin +with ASCII 137 and a few other specific bytes. If the first byte is neither +of those values, then GNDStk assumes JSON format. A nice thing about using the file magic number, not the file name, is that it works for ``std::istream``, for which a "file name" isn't even available. diff --git a/src/GNDStk.hpp b/src/GNDStk.hpp index 0a6cdfba3..42c45dfac 100644 --- a/src/GNDStk.hpp +++ b/src/GNDStk.hpp @@ -99,7 +99,7 @@ namespace GNDStk { #include "GNDStk/node2type.hpp" #include "GNDStk/type2node.hpp" -// XML/JSON/HDF5/Tree conversions +// Tree/XML/JSON/HDF5 conversions #include "GNDStk/convert.hpp" // fixme See above fixme diff --git a/src/GNDStk/BodyText/src/get.hpp b/src/GNDStk/BodyText/src/get.hpp index c2ff03d81..0ab133d0a 100644 --- a/src/GNDStk/BodyText/src/get.hpp +++ b/src/GNDStk/BodyText/src/get.hpp @@ -383,7 +383,11 @@ std::conditional_t< if constexpr (runtime) { detail::MapStringType( valueType(), - [this](auto &&t) { get>>(); } + [this](auto &&t) + { + // clang seems to need this-> explicitly to *not* emit a warning + this->get>>(); + } ); // We can't return the specific variant alternative that was just put // in place; it depended on a run-time check. So, we return the whole diff --git a/src/GNDStk/Component.hpp b/src/GNDStk/Component.hpp index 0667a576f..a1d383c23 100644 --- a/src/GNDStk/Component.hpp +++ b/src/GNDStk/Component.hpp @@ -20,6 +20,8 @@ class Component : public BodyText using body = BodyText; using typename body::VariantOfVectors; using typename body::VariantOfScalars; + static inline constexpr bool hasFields = + !std::is_same_v>; // Links to fields in the object of the derived class. I can't find a way // to do this in a decltype(DERIVED::keys())-aware manner, because DERIVED @@ -70,6 +72,11 @@ class Component : public BodyText // You can (but need not) override the following in DERIVED static std::string namespaceName() { return ""; } + // base + // Convenient access to the BodyText base class + body &baseBodyText() { return *this; } + const body &baseBodyText() const { return *this; } + // derived // Convenient access to the derived class DERIVED &derived() @@ -82,8 +89,7 @@ class Component : public BodyText { try { return DERIVED::help.at(subject); - } - catch ( ... ) { + } catch ( ... ) { return "No help information is available"; } } diff --git a/src/GNDStk/Component/src/ctor.hpp b/src/GNDStk/Component/src/ctor.hpp index f289a5058..e6be43ce2 100644 --- a/src/GNDStk/Component/src/ctor.hpp +++ b/src/GNDStk/Component/src/ctor.hpp @@ -22,7 +22,7 @@ Component(const body &other, ARGS &...args) : body(other) // The parameters that are sent to this constructor must EXACTLY reflect // what we'd get from a DERIVED::keys() multi-query. - if constexpr (std::is_same_v>) { + if constexpr (!hasFields) { // keys is "empty" (std::tuple<>); that's OK, as long as ARGS is too static_assert( std::is_same_v, std::tuple<>>, diff --git a/src/GNDStk/Component/src/detail.hpp b/src/GNDStk/Component/src/detail.hpp index 972765753..d8078758c 100644 --- a/src/GNDStk/Component/src/detail.hpp +++ b/src/GNDStk/Component/src/detail.hpp @@ -3,7 +3,6 @@ template class Component; - namespace detail { // ----------------------------------------------------------------------------- diff --git a/src/GNDStk/Component/src/fromNode.hpp b/src/GNDStk/Component/src/fromNode.hpp index f7760b4ca..b4b51eff2 100644 --- a/src/GNDStk/Component/src/fromNode.hpp +++ b/src/GNDStk/Component/src/fromNode.hpp @@ -30,7 +30,7 @@ void fromNode(const Node &node) throw std::exception{}; } - if constexpr (std::is_same_v>) { + if constexpr (!hasFields) { // consistency check; then nothing further to do assert(0 == links.size()); } else { diff --git a/src/GNDStk/Component/src/sort.hpp b/src/GNDStk/Component/src/sort.hpp index 68dd7b309..b21f0ed1f 100644 --- a/src/GNDStk/Component/src/sort.hpp +++ b/src/GNDStk/Component/src/sort.hpp @@ -6,7 +6,7 @@ void sort() { try { - if constexpr (std::is_same_v>) { + if constexpr (!hasFields) { // Consistency check; then nothing further to do assert(0 == links.size()); } else { diff --git a/src/GNDStk/Component/src/toNodeBody.hpp b/src/GNDStk/Component/src/toNodeBody.hpp index a5182a737..e0fecf6e1 100644 --- a/src/GNDStk/Component/src/toNodeBody.hpp +++ b/src/GNDStk/Component/src/toNodeBody.hpp @@ -12,7 +12,7 @@ if constexpr (hasBodyText) { } // 3. Write fields -if constexpr (std::is_same_v>) { +if constexpr (!hasFields) { // consistency check assert(0 == links.size()); } else { diff --git a/src/GNDStk/Component/src/write.hpp b/src/GNDStk/Component/src/write.hpp index 7eed91358..3922dd71b 100644 --- a/src/GNDStk/Component/src/write.hpp +++ b/src/GNDStk/Component/src/write.hpp @@ -28,7 +28,7 @@ std::ostream &write(std::ostream &os, const int level) const "\n" ); - if constexpr (std::is_same_v>) { + if constexpr (!hasFields) { // Consistency check assert(0 == links.size()); } else { diff --git a/src/GNDStk/HDF5.hpp b/src/GNDStk/HDF5.hpp index 1b29905cc..a515409d7 100644 --- a/src/GNDStk/HDF5.hpp +++ b/src/GNDStk/HDF5.hpp @@ -9,7 +9,7 @@ class HDF5 { // data HighFive::File *file = nullptr; - std::string filename = "";///perhaps can use file->getName() + std::string filename = ""; mutable bool temporary = false; private: @@ -22,8 +22,8 @@ class HDF5 { return; // apparently removed already, so no need to remove ifs.close(); // prior to remove if (remove(filename.c_str()) != 0) { - log::error( - "Unable to remove temporary file \"{}\"", filename); + log::warning( + "Could not remove temporary file \"{}\"", filename); log::member( "HDF5::removeTemporary(), with filename \"{}\"", filename); } @@ -35,7 +35,8 @@ class HDF5 { // clear HDF5 &clear() { - delete file; file = nullptr; + delete file; + file = nullptr; removeTemporary(); filename = ""; temporary = false; diff --git a/src/GNDStk/HDF5/src/read.hpp b/src/GNDStk/HDF5/src/read.hpp index aa02d4a0a..76f30b4b5 100644 --- a/src/GNDStk/HDF5/src/read.hpp +++ b/src/GNDStk/HDF5/src/read.hpp @@ -75,7 +75,7 @@ Should probably make it append .h5 // Open temporary file. This *should* work, but we check anyway. std::ofstream ofs(filename, std::ios::binary); if (!ofs) { - log::error("Unable to open temporary file \"{}\"", filename); + log::error("Could not open temporary file \"{}\"", filename); throw std::exception{}; } diff --git a/src/GNDStk/HDF5/src/write.hpp b/src/GNDStk/HDF5/src/write.hpp index 32fe71b06..86ce05f77 100644 --- a/src/GNDStk/HDF5/src/write.hpp +++ b/src/GNDStk/HDF5/src/write.hpp @@ -27,7 +27,7 @@ std::ostream &write(std::ostream &os, const bool decl = true) const std::ifstream ifs(tempname, std::ios::binary); if (!ifs) { - log::error("Unable to open temporary file \"{}\"", tempname); + log::error("Could not open temporary file \"{}\"", tempname); throw std::exception{}; } while (ifs.get(ch) && os) @@ -35,13 +35,13 @@ std::ostream &write(std::ostream &os, const bool decl = true) const ifs.close(); // prior to remove... if (remove(tempname) != 0) { - log::error("Unable to remove temporary file \"{}\"", tempname); + log::error("Could not remove temporary file \"{}\"", tempname); throw std::exception{}; } } else { std::ifstream ifs(filename, std::ios::binary); if (!ifs) { - log::error("Unable to open file \"{}\"", filename); + log::error("Could not open file \"{}\"", filename); throw std::exception{}; } while (ifs.get(ch) && os) diff --git a/src/GNDStk/Node/src/detail.hpp b/src/GNDStk/Node/src/detail.hpp index cb1a7a170..7230a614f 100644 --- a/src/GNDStk/Node/src/detail.hpp +++ b/src/GNDStk/Node/src/detail.hpp @@ -721,9 +721,9 @@ inline void warning_io_data( // error_format_read inline const std::string error_format_read = "FileType::text not allowed in Node.read(). " - "Our \"text\" file format is intended" - "mainly for debug writing, not for reading. " - "Consider xml, json, or hdf5" + "Our \"text\" file format is intended " + "for debug writing, not for reading. " + "Consider FileType:: xml, json, or hdf5" ; diff --git a/src/GNDStk/Tree/src/reset.hpp b/src/GNDStk/Tree/src/reset.hpp index a5f56f3ea..bf0c5fc01 100644 --- a/src/GNDStk/Tree/src/reset.hpp +++ b/src/GNDStk/Tree/src/reset.hpp @@ -46,9 +46,9 @@ Tree &reset( // Declaration node: "xml", etc. // This can specify an eventual intended file format // for the GNDS hierarchy. - if (format == FileType::xml - || format == FileType::null - || format == FileType::text + if (format == FileType::xml || + format == FileType::null || + format == FileType::text ) { // xml, null, tree add("xml"); @@ -57,11 +57,9 @@ Tree &reset( } else if (format == FileType::json) { // json add("json"); - // any use for version and encoding? } else if (format == FileType::hdf5) { // hdf5 add("hdf5"); - // any use for version and encoding? } else { log::error( "Internal error in Tree.reset(" + detail::keyname(kwd) diff --git a/src/GNDStk/common/src/detail.hpp b/src/GNDStk/common/src/detail.hpp index 2fbd6b089..38af5eeb1 100644 --- a/src/GNDStk/common/src/detail.hpp +++ b/src/GNDStk/common/src/detail.hpp @@ -27,7 +27,7 @@ class convert_pcdata_text_t { return; } log::error( - "Unable to find metadatum key \"text\" in the current Node (\"{}\")", + "Could not find metadatum key \"text\" in the current Node (\"{}\")", node.name ); throw std::exception{}; diff --git a/src/GNDStk/convert.hpp b/src/GNDStk/convert.hpp index d6f01e99e..a8d4b4221 100644 --- a/src/GNDStk/convert.hpp +++ b/src/GNDStk/convert.hpp @@ -2,7 +2,7 @@ #include "GNDStk/convert/src/detail.hpp" // convert to: -#include "GNDStk/convert/src/tree.hpp" +#include "GNDStk/convert/src/Tree.hpp" #include "GNDStk/convert/src/XML.hpp" #include "GNDStk/convert/src/JSON.hpp" #include "GNDStk/convert/src/HDF5.hpp" diff --git a/src/GNDStk/convert/src/HDF5.hpp b/src/GNDStk/convert/src/HDF5.hpp index 2156c4948..8b8068981 100644 --- a/src/GNDStk/convert/src/HDF5.hpp +++ b/src/GNDStk/convert/src/HDF5.hpp @@ -23,7 +23,7 @@ inline bool convert(const Node &node, HDF5 &h) // Open temporary file. This *should* work, but we check anyway. std::ofstream ofs(h.filename, std::ios::binary); if (!ofs) { - log::error("Unable to open temporary file \"{}\"", h.filename); + log::error("Could not open temporary file \"{}\"", h.filename); throw std::exception{}; } ofs.close(); @@ -186,7 +186,7 @@ inline bool convert(const HDF5 &from, HDF5 &to) if (!from.empty()) { std::ifstream ifs(from.filename, std::ios::binary); if (!ifs) { - log::error("Unable to open file \"{}\"", from.filename); + log::error("Could not open file \"{}\"", from.filename); throw std::exception{}; } if (!to.read(ifs)) diff --git a/src/GNDStk/convert/src/tree.hpp b/src/GNDStk/convert/src/Tree.hpp similarity index 98% rename from src/GNDStk/convert/src/tree.hpp rename to src/GNDStk/convert/src/Tree.hpp index 3945e1c00..192f13d4e 100644 --- a/src/GNDStk/convert/src/tree.hpp +++ b/src/GNDStk/convert/src/Tree.hpp @@ -243,7 +243,7 @@ Remark HighFive::File, and by extension GNDStk::HDF5 (our simple wrapper around HighFive::File, to assist in providing uniform behavior between XML, JSON, -and HDF5), refers to an entire HDF file. Unlike XML and JSON, it apparently +and HDF5), refers to an entire HDF5 file. Unlike XML and JSON, it apparently can't refer to just part of such a file, i.e. part of an HDF5 hierarchy. The upshot: convert(HDF5,Tree) may be far more meaningful than convert(HDF5,Node), as the former (Tree) is for a full GNDS hierarchy, the latter for possibly @@ -283,7 +283,7 @@ inline bool convert(const HDF5 &h, Node &node, const bool decl) const HighFive::File &file = *h.file; // size == 0: not empty in the earlier (h.file == nullptr) sense, - // but, here, meaning that there's nothing in the HDF document + // but, here, meaning that there's nothing in the HDF5 document const std::size_t size = file.getNumberObjects(); if (size == 0) return true; diff --git a/src/GNDStk/utility.hpp b/src/GNDStk/utility.hpp index 32d37bb0c..35345ef4c 100644 --- a/src/GNDStk/utility.hpp +++ b/src/GNDStk/utility.hpp @@ -434,9 +434,7 @@ inline bool endsin_json(const std::string &str) inline bool endsin_hdf5(const std::string &str) { return - endsin(str,".hdf" ) - || endsin(str,".HDF" ) - || endsin(str,".h5" ) + endsin(str,".h5" ) || endsin(str,".H5" ) || endsin(str,".hdf5") || endsin(str,".HDF5") @@ -484,8 +482,7 @@ inline bool eq_json(const std::string &str) inline bool eq_hdf5(const std::string &str) { return - nocasecmp(str,"hdf" ) - || nocasecmp(str,"h5" ) + nocasecmp(str,"h5" ) || nocasecmp(str,"hdf5") || nocasecmp(str,"he5" ); } From f9449303a172dcdd3a041654bb914ef557732c1c Mon Sep 17 00:00:00 2001 From: Martin Staley Date: Mon, 6 Dec 2021 11:50:05 -0700 Subject: [PATCH 17/39] Regenerated prototype classes. --- src/GNDStk/v1.9/containers/Axes.hpp | 4 ++-- src/GNDStk/v1.9/containers/Axis.hpp | 4 ++-- src/GNDStk/v1.9/containers/Grid.hpp | 4 ++-- src/GNDStk/v1.9/containers/Link.hpp | 4 ++-- src/GNDStk/v1.9/containers/Regions1d.hpp | 4 ++-- src/GNDStk/v1.9/containers/Values.hpp | 4 ++-- src/GNDStk/v1.9/containers/XYs1d.hpp | 4 ++-- src/GNDStk/v1.9/transport/CrossSection.hpp | 4 ++-- src/GNDStk/v1.9/transport/Reaction.hpp | 4 ++-- src/GNDStk/v1.9/transport/ReactionSuite.hpp | 4 ++-- src/GNDStk/v1.9/transport/Reactions.hpp | 4 ++-- 11 files changed, 22 insertions(+), 22 deletions(-) diff --git a/src/GNDStk/v1.9/containers/Axes.hpp b/src/GNDStk/v1.9/containers/Axes.hpp index 36743f775..4bcfe64d7 100644 --- a/src/GNDStk/v1.9/containers/Axes.hpp +++ b/src/GNDStk/v1.9/containers/Axes.hpp @@ -231,7 +231,7 @@ class Axes : public Component { // copy Axes(const Axes &other) : Component{ - other, + other.baseBodyText(), content.href, content.axis_grid }, @@ -243,7 +243,7 @@ class Axes : public Component { // move Axes(Axes &&other) : Component{ - other, + other.baseBodyText(), content.href, content.axis_grid }, diff --git a/src/GNDStk/v1.9/containers/Axis.hpp b/src/GNDStk/v1.9/containers/Axis.hpp index db63421da..1ceb75616 100644 --- a/src/GNDStk/v1.9/containers/Axis.hpp +++ b/src/GNDStk/v1.9/containers/Axis.hpp @@ -145,7 +145,7 @@ class Axis : public Component { // copy Axis(const Axis &other) : Component{ - other, + other.baseBodyText(), content.index, content.label, content.unit @@ -158,7 +158,7 @@ class Axis : public Component { // move Axis(Axis &&other) : Component{ - other, + other.baseBodyText(), content.index, content.label, content.unit diff --git a/src/GNDStk/v1.9/containers/Grid.hpp b/src/GNDStk/v1.9/containers/Grid.hpp index a77a58558..83322cab1 100644 --- a/src/GNDStk/v1.9/containers/Grid.hpp +++ b/src/GNDStk/v1.9/containers/Grid.hpp @@ -231,7 +231,7 @@ class Grid : public Component { // copy Grid(const Grid &other) : Component{ - other, + other.baseBodyText(), content.index, content.interpolation, content.label, @@ -247,7 +247,7 @@ class Grid : public Component { // move Grid(Grid &&other) : Component{ - other, + other.baseBodyText(), content.index, content.interpolation, content.label, diff --git a/src/GNDStk/v1.9/containers/Link.hpp b/src/GNDStk/v1.9/containers/Link.hpp index f5ba82bc4..c0221a03b 100644 --- a/src/GNDStk/v1.9/containers/Link.hpp +++ b/src/GNDStk/v1.9/containers/Link.hpp @@ -111,7 +111,7 @@ class Link : public Component { // copy Link(const Link &other) : Component{ - other, + other.baseBodyText(), content.href }, content{other.content} @@ -122,7 +122,7 @@ class Link : public Component { // move Link(Link &&other) : Component{ - other, + other.baseBodyText(), content.href }, content{std::move(other.content)} diff --git a/src/GNDStk/v1.9/containers/Regions1d.hpp b/src/GNDStk/v1.9/containers/Regions1d.hpp index 251262d72..cf34fbfe4 100644 --- a/src/GNDStk/v1.9/containers/Regions1d.hpp +++ b/src/GNDStk/v1.9/containers/Regions1d.hpp @@ -200,7 +200,7 @@ class Regions1d : public Component { // copy Regions1d(const Regions1d &other) : Component{ - other, + other.baseBodyText(), content.label, content.outerDomainValue, content.XYs1d, @@ -214,7 +214,7 @@ class Regions1d : public Component { // move Regions1d(Regions1d &&other) : Component{ - other, + other.baseBodyText(), content.label, content.outerDomainValue, content.XYs1d, diff --git a/src/GNDStk/v1.9/containers/Values.hpp b/src/GNDStk/v1.9/containers/Values.hpp index f3d987e3a..73166a432 100644 --- a/src/GNDStk/v1.9/containers/Values.hpp +++ b/src/GNDStk/v1.9/containers/Values.hpp @@ -153,7 +153,7 @@ class Values : public Component { // copy Values(const Values &other) : Component{ - other, + other.baseBodyText(), content.length, content.start, content.valueType @@ -166,7 +166,7 @@ class Values : public Component { // move Values(Values &&other) : Component{ - other, + other.baseBodyText(), content.length, content.start, content.valueType diff --git a/src/GNDStk/v1.9/containers/XYs1d.hpp b/src/GNDStk/v1.9/containers/XYs1d.hpp index 7e0d294e6..8d37f5aaa 100644 --- a/src/GNDStk/v1.9/containers/XYs1d.hpp +++ b/src/GNDStk/v1.9/containers/XYs1d.hpp @@ -206,7 +206,7 @@ class XYs1d : public Component { // copy XYs1d(const XYs1d &other) : Component{ - other, + other.baseBodyText(), content.index, content.interpolation, content.label, @@ -222,7 +222,7 @@ class XYs1d : public Component { // move XYs1d(XYs1d &&other) : Component{ - other, + other.baseBodyText(), content.index, content.interpolation, content.label, diff --git a/src/GNDStk/v1.9/transport/CrossSection.hpp b/src/GNDStk/v1.9/transport/CrossSection.hpp index 39ecb5650..2f62eec41 100644 --- a/src/GNDStk/v1.9/transport/CrossSection.hpp +++ b/src/GNDStk/v1.9/transport/CrossSection.hpp @@ -212,7 +212,7 @@ class CrossSection : public Component { // copy CrossSection(const CrossSection &other) : Component{ - other, + other.baseBodyText(), content.XYs1d_regions1d }, content{other.content} @@ -223,7 +223,7 @@ class CrossSection : public Component { // move CrossSection(CrossSection &&other) : Component{ - other, + other.baseBodyText(), content.XYs1d_regions1d }, content{std::move(other.content)} diff --git a/src/GNDStk/v1.9/transport/Reaction.hpp b/src/GNDStk/v1.9/transport/Reaction.hpp index 99cd2a72a..65bba5d06 100644 --- a/src/GNDStk/v1.9/transport/Reaction.hpp +++ b/src/GNDStk/v1.9/transport/Reaction.hpp @@ -167,7 +167,7 @@ class Reaction : public Component { // copy Reaction(const Reaction &other) : Component{ - other, + other.baseBodyText(), content.ENDF_MT, content.fissionGenre, content.label, @@ -181,7 +181,7 @@ class Reaction : public Component { // move Reaction(Reaction &&other) : Component{ - other, + other.baseBodyText(), content.ENDF_MT, content.fissionGenre, content.label, diff --git a/src/GNDStk/v1.9/transport/ReactionSuite.hpp b/src/GNDStk/v1.9/transport/ReactionSuite.hpp index f6143d338..47068ca83 100644 --- a/src/GNDStk/v1.9/transport/ReactionSuite.hpp +++ b/src/GNDStk/v1.9/transport/ReactionSuite.hpp @@ -218,7 +218,7 @@ class ReactionSuite : public Component { // copy ReactionSuite(const ReactionSuite &other) : Component{ - other, + other.baseBodyText(), content.evaluation, content.format, content.interaction, @@ -235,7 +235,7 @@ class ReactionSuite : public Component { // move ReactionSuite(ReactionSuite &&other) : Component{ - other, + other.baseBodyText(), content.evaluation, content.format, content.interaction, diff --git a/src/GNDStk/v1.9/transport/Reactions.hpp b/src/GNDStk/v1.9/transport/Reactions.hpp index 80576766e..ef30fe85f 100644 --- a/src/GNDStk/v1.9/transport/Reactions.hpp +++ b/src/GNDStk/v1.9/transport/Reactions.hpp @@ -146,7 +146,7 @@ class Reactions : public Component { // copy Reactions(const Reactions &other) : Component{ - other, + other.baseBodyText(), content.reaction }, content{other.content} @@ -157,7 +157,7 @@ class Reactions : public Component { // move Reactions(Reactions &&other) : Component{ - other, + other.baseBodyText(), content.reaction }, content{std::move(other.content)} From d111a400088ec7ea959187fc30ec8b61547b15d8 Mon Sep 17 00:00:00 2001 From: Martin Staley Date: Mon, 6 Dec 2021 21:05:59 -0700 Subject: [PATCH 18/39] More work on HDF5. --- src/GNDStk/HDF5.hpp | 49 +++++++++-- src/GNDStk/HDF5/src/assign.hpp | 1 + src/GNDStk/HDF5/src/read.hpp | 150 +++++++++++++++----------------- src/GNDStk/HDF5/src/write.hpp | 70 ++++++++++----- src/GNDStk/JSON/src/write.hpp | 2 +- src/GNDStk/convert/src/HDF5.hpp | 14 +-- 6 files changed, 163 insertions(+), 123 deletions(-) diff --git a/src/GNDStk/HDF5.hpp b/src/GNDStk/HDF5.hpp index a515409d7..2b86d1c2c 100644 --- a/src/GNDStk/HDF5.hpp +++ b/src/GNDStk/HDF5.hpp @@ -12,21 +12,52 @@ class HDF5 { std::string filename = ""; mutable bool temporary = false; + // file modes + static inline const auto modeRead = + HighFive::File::ReadOnly; + static inline const auto modeWrite = + HighFive::File::ReadWrite | + HighFive::File::Create | + HighFive::File::Truncate; + + // temporaryName() + static std::string temporaryName() + { + // Generate a file name that's supposed to be suitable for safely creating + // a temporary file. L_tmpnam and tmpnam() are from . In case + // anyone wonders, we don't need a +1 in the [L_tmpnam]. :-) + static char buffer[L_tmpnam]; + + while (true) { + const std::string name = std::string(tmpnam(buffer)) + ".h5"; + std::ifstream ifs(name, std::ios::binary); + if (!ifs) // <== as should be the case + return name; + + // Well that's weird; the tmpnam()-generated file name (admittedly, + // with our added ".h5") refers to a file that already exists. :-/ + log::info("Generated temporary HDF5 file name \"{}\" " + "is already in use.\n" + "That's harmless, but it really shouldn't happen.\n" + "Generating another name....", name); + } + } + private: void removeTemporary() const { - if (filename != "" && temporary) { + if (temporary && filename != "") { std::ifstream ifs(filename); if (!ifs) - return; // apparently removed already, so no need to remove - ifs.close(); // prior to remove - if (remove(filename.c_str()) != 0) { - log::warning( - "Could not remove temporary file \"{}\"", filename); - log::member( - "HDF5::removeTemporary(), with filename \"{}\"", filename); - } + return; // removed already, or was not there (e.g. creation error) + + ifs.close(); // prior to removal... + if (remove(filename.data()) == 0) + return; // remove() succeeded + + log::warning("Could not remove temporary HDF5 file \"{}\"", filename); + log::member("HDF5::removeTemporary(), with filename \"{}\"", filename); } } diff --git a/src/GNDStk/HDF5/src/assign.hpp b/src/GNDStk/HDF5/src/assign.hpp index b3df8d1f1..b7dfc43ce 100644 --- a/src/GNDStk/HDF5/src/assign.hpp +++ b/src/GNDStk/HDF5/src/assign.hpp @@ -7,6 +7,7 @@ HDF5 &operator=(HDF5 &&other) { clear(); + file = std::move(other.file); filename = std::move(other.filename); temporary = std::move(other.temporary); diff --git a/src/GNDStk/HDF5/src/read.hpp b/src/GNDStk/HDF5/src/read.hpp index 76f30b4b5..e9de0e4a6 100644 --- a/src/GNDStk/HDF5/src/read.hpp +++ b/src/GNDStk/HDF5/src/read.hpp @@ -6,27 +6,33 @@ /* DISCUSSION -While this may seem goofy and inefficient, our read(istream) function actually -transfers the istream's content to a temporary *file*, then calls read(filename) -on the temporary file. That function, in turn, uses the underlying HighFive HDF5 -library's read-from-file capability, in order to do the actual work of reading -HDF5 content into an internal data structure. - -Normally, one might do the reverse: use a read-from-istream as a helper to a -read-from-file, with the latter opening the file as an ifstream, then calling -the former to do the heavy lifting. Indeed, our read-from-file functions for -XML and JSON do just that. - -Here, we did things in the seemingly backwards way for a simple reason: at the -time of this writing, we see no capability in HighFive to read from an istream! -Just to read directly from a file. +While this may appear at first glance to be inefficient, our read(istream) +function actually transfers the istream's contents to a temporary file, then +calls read(filename) on the temporary file. That function, in turn, uses the +underlying HighFive HDF5 library's read-from-file capability in order to do the +actual work of providing an interface into HDF5 data. + +Normally, one might do the reverse: use read-from-istream as a helper to read- +from-file, with the latter opening the file as an ifstream, then calling the +former to do the heavy lifting. Indeed, our read-from-file functions for XML +and JSON do precisely that. + +Here, however, we did things in the seemingly backwards way for the simple +reason that, at the time of this writing, we see no capability in HighFive to +read from an istream! Just to read directly from a file. While we haven't looked +into the details, we think HighFive isn't actually reading the file (or much of +the file) into an internal data structure, as the XML and JSON librarys do, but +instead reads little or nothing, maintains a handle to the file itself (making +the file, in effect, act as a data structure on disk, instead of one in memory), +and then deals with the file when, and only when, someone reads or writes data. One might ask why we chose to implement this arguably convoluted read-from- -istream at all. Our reason: we're intentionally designing all of our file-format -classes (at present: XML, JSON, and HDF5) to "look and feel" as consistent as -possible with one another. This uniformity helps make the code - for all formats -and throughout GNDStk - to look as consistent as reasonably possible. This helps -with debugging and testing, and gives users a more-uniform interface. +istream at all - as opposed to supporting only read-from-file, given that a file +has to be involved either way. Our reason is simply that we're designing all of +our file-format classes (at present: XML, JSON, and HDF5) to behave as similarly +as possible with one another. This uniformity helps make the code - for all the +formats and throughout GNDStk - look and feel as consistent as possible. This +helps with debugging and testing, and gives users a more-uniform interface. */ @@ -34,42 +40,19 @@ with debugging and testing, and gives users a more-uniform interface. // read(istream) // ----------------------------------------------------------------------------- -/// zzz integrate these fixmes into regular remarks - -// fixme -// We may want to detect whether or not the istream is in std::ios::binary -// mode. If it isn't, then copying it absolutely correctly, to a temporary -// file, might be problematic. We'll use get() and put(), below, but could -// something like platform-dependent line endings still be a problem? Play -// around with this to see what's what. - -// fixme -// Is there a way to detect if any additional content appears in the istream, -// AFTER the HDF5 content itself? If there is, then - ideally - we should -// truncate the copy-to-temporary-file process after the end of HDF5 content, -// leaving the istream's streampos at that point. (But this situation might -// not realistically arise in practice.) - std::istream &read(std::istream &is) { // Clear present contents. clear(); // Current stream position. We'll rewind to this point if an error occurs. + // Of course it's probably at 0 - I doubt we'd be dealing with HDF5 content + // that's mixed with something else - but we do the following elsewhere, + // and will be consistent with that behavior here. const std::streampos pos = is.tellg(); - // Generate a file name that's suitable for safely creating a temporary file. - // L_tmpnam and tmpnam() are from . In case anyone wonders, we don't - // need a +1 in the [L_tmpnam] here :-). - static char buffer[L_tmpnam]; - filename = tmpnam(buffer); - // fixme Possibly check if tmpnam() is screwy and the file actually exists? - - /* -zzz -Have HDF5::createTemporary() -Should probably make it append .h5 - */ + // Name for temporary file. + filename = temporaryName(); try { // Open temporary file. This *should* work, but we check anyway. @@ -79,35 +62,37 @@ Should probably make it append .h5 throw std::exception{}; } - // Copy bytes from the istream to the temporary file. + // Copy bytes from the istream to the temporary file. We copy all bytes; + // so, we suppose that something might go awry if someone somehow attached + // non-HDF5 bytes beyond the end (which we can't detect) of the HDF5 + // material. But, that would be a very strange thing for someone to do. char ch; while (is.get(ch) && ofs) ofs.put(ch); + if (!(is.fail() && is.eof() && !is.bad() && ofs.good())) { + log::error( + "Error writing istream HDF5 contents to temporary file \"{}\"", + filename); + ofs.close(); + throw std::exception{}; + } ofs.close(); - // fixme Maybe examine/check stream states here. // Call read(filename) to read HDF5 content from the temporary file. - // See our detailed discussion above. + // See our detailed discussion earlier. if (!read(filename)) throw std::exception{}; } catch (...) { - temporary = true; // after read(filename), which makes it false - removeTemporary(); log::member("HDF5.read(istream) (uses a temporary file)"); + temporary = true; // possibly after read(filename), which makes it false + clear(); // which also does removeTemporary() detail::failback(is,pos); + return is; } // done temporary = true; // after read(filename), which makes it false - assert(!is.bad()); - /// assert(!is.fail()); - assert(is.eof()); - ///assert(false); - - // zzz above, we should clear is' flags as long as the *only* problems - // is fail(), *AND* eof() (so that eof is why it failed); I think at - // least that that's correct. - is.clear();///for now + is.clear(std::ios_base::eofbit); // as expected return is; } @@ -116,36 +101,35 @@ Should probably make it append .h5 // read(file name) // ----------------------------------------------------------------------------- -// The parameter is intentionally value, not reference, so that it can't -// be surreptitiously set to "" by the clear() call if the actual parameter -// happens to be this->filename - which it *is*, in fact, if this read() -// is called from the above istream read()! (And, although it's unlikely, -// someone could conceivably make such a call directly instead of through -// the above read(), in for example a scenario where the file might have -// changed on disk and someone wants it to be re-read.) We don't run into -// a similar problem with the XML or JSON read()s, not just because their -// read(istream)s don't call their read(file name)s, but also because they -// simply don't, at present, have std::string member data that might be -// aliased by a parameter like name below, so that a clear() accidentally -// clears the parameter. +// The parameter is intentionally by-value, not by-reference, so that it won't +// surreptitiously be set to "" by the clear() call if the actual parameter +// happens to be this->filename - which it is, in fact, if this read() is called +// from the above read(istream). (And, although it's unlikely, someone could +// conceivably make such a call directly instead of through the above read(), +// in for example a scenario where the file might have changed on disk and +// someone wants it to be re-read.) We don't run into a similar problem with +// the XML or JSON read()s, not just because their read(istream)s don't call +// their read(file name)s, but also because they simply do not, at present, +// have std::string member data that might be aliased by a parameter like the +// one below, so that a clear() accidentally clears the parameter. bool read(const std::string name) { clear(); filename = name; + // Note: if this function's name parameter had been by-reference, right here + // is where we might inadvertently have filename == ""; see the above remark bool ret = false; - // Test that the file can be opened. The HighFive::File(filename) call, - // below, in fact opens and reads the file. This "test open" allows us - // to provide diagnostics that are similar to those that we provide in - // our read() functions for other file formats. Note: if this function's - // name parameter had been by-reference, right here is where we might - // inadvertently have filename == ""; see the earlier remark! + // Test that the file can be opened. The upcoming HighFive::File(filename) + // call does, in fact, open the file. However, this "test open" allows us + // to provide diagnostics that resemble those that we provide in our read() + // functions for other file formats. std::ifstream ifs(filename, std::ios::binary); if (ifs) { ifs.close(); try { - file = new HighFive::File(filename, HighFive::File::ReadOnly); - ret = true; // all's well - our "test open" and HighFive's reading + file = new HighFive::File(filename, modeRead); + ret = true; // all's well - our "test open," and HighFive's reading } catch (...) { log::error("file = HighFive::File(filename, ReadOnly)\n" "threw an exception"); @@ -153,8 +137,10 @@ bool read(const std::string name) } else log::error("Could not open file \"{}\" for input", filename); - if (!ret) + if (!ret) { log::member("HDF5.read(\"{}\")", filename); + clear(); + } // done temporary = false; diff --git a/src/GNDStk/HDF5/src/write.hpp b/src/GNDStk/HDF5/src/write.hpp index 86ce05f77..2c613c0a8 100644 --- a/src/GNDStk/HDF5/src/write.hpp +++ b/src/GNDStk/HDF5/src/write.hpp @@ -9,49 +9,75 @@ std::ostream &write(std::ostream &os, const bool decl = true) const { - (void)decl; // unused + (void)decl; // unused, at least for now char ch; + os.clear(); try { if (empty()) { - static char tempname[L_tmpnam]; - tmpnam(tempname); - - HighFive::File blank( - tempname, - HighFive::File::ReadWrite | - HighFive::File::Create | - HighFive::File::Truncate - ); - blank.flush(); - - std::ifstream ifs(tempname, std::ios::binary); + // This HDF5 object is empty, so we'll create valid "stub" HDF5 output. + // First, create a temporary stub HDF5 file. We go through this file, + // not directly into the ostream, because, as we've written elsewhere, + // the HDF5 library deals directly with files, not with streams. This + // go-through-a-temporary process thus appears to be necessary. + const std::string tmpName = temporaryName(); + HighFive::File stub(tmpName.data(), modeWrite); + stub.flush(); // file should be there now + + // Open the temporary stub file + std::ifstream ifs(tmpName, std::ios::binary); if (!ifs) { - log::error("Could not open temporary file \"{}\"", tempname); + log::error("Could not open temporary HDF5 file \"{}\" " + "for writing to ostream", tmpName); throw std::exception{}; } + + // Transfer the temporary stub file's contents to the ostream while (ifs.get(ch) && os) os.put(ch); + const bool good = ifs.fail() && ifs.eof() && !ifs.bad() && os.good(); - ifs.close(); // prior to remove... - if (remove(tempname) != 0) { - log::error("Could not remove temporary file \"{}\"", tempname); + // Close and remove the temporary stub file + ifs.close(); // prior to removal... + if (remove(tmpName.data()) != 0) { + log::warning( + "Could not remove temporary HDF5 file \"{}\"", tmpName); + log::member("HDF5.write(ostream)"); + } + + if (!good) { + log::error( + "Error writing temporary HDF5 file \"{}\"'s contents to ostream", + tmpName); throw std::exception{}; } + } else { + // This HDF5 object is not empty. Writing it to an ostream - this + // function's purpose - amounts to copying bytes *from* the file to + // which the HDF5 object refers, *to* the ostream. std::ifstream ifs(filename, std::ios::binary); if (!ifs) { - log::error("Could not open file \"{}\"", filename); + log::error("Could not open HDF5 file \"{}\" " + "for writing to ostream", filename); throw std::exception{}; } + + // Transfer the file's contents to the ostream while (ifs.get(ch) && os) os.put(ch); + if (!(ifs.fail() && ifs.eof() && !ifs.bad() && os.good())) { + ifs.close(); + log::error( + "Error writing HDF5 file \"{}\"'s contents to ostream", filename); + throw std::exception{}; + } } + } catch (...) { log::member("HDF5.write(ostream)"); os.setstate(std::ios::failbit); } - // fixme Maybe examine/check stream states after above copies // done return os; @@ -64,9 +90,11 @@ std::ostream &write(std::ostream &os, const bool decl = true) const bool write(const std::string &filename, const bool decl = true) const { - // well, I suppose it's possible... + // well, I suppose it's possible that the file we're wanting to write the + // HDF5 object to, is the same file the HDF5 object already references... if (filename == this->filename) { - temporary = false; + file->flush(); // <== for good measure + temporary = false; // <== and since filename was specifically asked for return true; } diff --git a/src/GNDStk/JSON/src/write.hpp b/src/GNDStk/JSON/src/write.hpp index 82b9c37cb..0ed835021 100644 --- a/src/GNDStk/JSON/src/write.hpp +++ b/src/GNDStk/JSON/src/write.hpp @@ -9,7 +9,7 @@ std::ostream &write(std::ostream &os, const bool decl = true) const { - (void)decl; // unused, for now (some changes may be forthcoming) + (void)decl; // unused, at least for now // call nlohmann::json's write capability try { diff --git a/src/GNDStk/convert/src/HDF5.hpp b/src/GNDStk/convert/src/HDF5.hpp index 8b8068981..94ef7830f 100644 --- a/src/GNDStk/convert/src/HDF5.hpp +++ b/src/GNDStk/convert/src/HDF5.hpp @@ -14,26 +14,20 @@ inline bool convert(const Node &node, HDF5 &h) h.clear(); // for the HDF5 - static char buffer[L_tmpnam]; - h.filename = tmpnam(buffer); + h.filename = h.temporaryName(); static const std::string context = "convert(Node,HDF5)"; try { - // Open temporary file. This *should* work, but we check anyway. + // Open temporary HDF5 file. This *should* work, but we check anyway. std::ofstream ofs(h.filename, std::ios::binary); if (!ofs) { - log::error("Could not open temporary file \"{}\"", h.filename); + log::error("Could not open temporary HDF5 file \"{}\"", h.filename); throw std::exception{}; } ofs.close(); - h.file = new HighFive::File( - h.filename, - HighFive::File::ReadWrite | - HighFive::File::Create | - HighFive::File::Truncate - ); + h.file = new HighFive::File(h.filename, HDF5::modeWrite); h.temporary = true; // Probably a regular Node From 41026c5f5a08799dd933fa9806061b04ee1b75b0 Mon Sep 17 00:00:00 2001 From: Martin Staley Date: Fri, 10 Dec 2021 00:36:03 -0700 Subject: [PATCH 19/39] Basic HDF5 capability is complete. Isn't very smart for output; just keeps everything as strings. That will be remedied at a later time. Was tested for functionality on entire set of GNDS v1.9 files. All converted. ...original total XML size: 2.9G ...new total HDF5 size: 21G So, a little over a factor of 7 larger. :-/ Miscellaneous other code changes were put in place during this work. Made a few diagnostic messages, and other minor constructs here and there, more consistent with one another. Added a convert() that proved to be needed for a certain disambiguation. This was noticed while working on some HDF5 input capabilities. --- src/GNDStk/Node/src/read.hpp | 6 +- src/GNDStk/Tree/src/reset.hpp | 9 +- src/GNDStk/convert/src/HDF5.hpp | 12 +- src/GNDStk/convert/src/JSON.hpp | 2 +- src/GNDStk/convert/src/Tree.hpp | 78 ++---- src/GNDStk/convert/src/detail.hpp | 402 +++++++++++++++++------------- src/GNDStk/string2type.hpp | 15 ++ src/GNDStk/type2string.hpp | 6 + src/GNDStk/utility.hpp | 2 +- 9 files changed, 284 insertions(+), 248 deletions(-) diff --git a/src/GNDStk/Node/src/read.hpp b/src/GNDStk/Node/src/read.hpp index 964069f67..d0f6b5eaf 100644 --- a/src/GNDStk/Node/src/read.hpp +++ b/src/GNDStk/Node/src/read.hpp @@ -162,10 +162,10 @@ std::istream &read( throw std::exception{}; } else { // The earlier logic is such that this shouldn't happen; consider - // removing at some point + // removing it at some point log::error( - "Internal error: unrecognized file format. " - "Please report this to us"); + "Internal error: unrecognized file format.\n" + "Please report this to us."); throw std::exception{}; } } catch (...) { diff --git a/src/GNDStk/Tree/src/reset.hpp b/src/GNDStk/Tree/src/reset.hpp index bf0c5fc01..f8951fcbf 100644 --- a/src/GNDStk/Tree/src/reset.hpp +++ b/src/GNDStk/Tree/src/reset.hpp @@ -62,11 +62,10 @@ Tree &reset( add("hdf5"); } else { log::error( - "Internal error in Tree.reset(" + detail::keyname(kwd) - + ",format,...):\n" - "Unrecognized file format; apparently, we missed something. " - "Please report this to us" - ); + "Internal error in Tree.reset(" + detail::keyname(kwd) + + ", format, ...):\n" + "Unrecognized file format; apparently, we missed something.\n" + "Please report this to us."); throw std::exception{}; } diff --git a/src/GNDStk/convert/src/HDF5.hpp b/src/GNDStk/convert/src/HDF5.hpp index 94ef7830f..ac2c79c2a 100644 --- a/src/GNDStk/convert/src/HDF5.hpp +++ b/src/GNDStk/convert/src/HDF5.hpp @@ -30,9 +30,9 @@ inline bool convert(const Node &node, HDF5 &h) h.file = new HighFive::File(h.filename, HDF5::modeWrite); h.temporary = true; - // Probably a regular Node + // Probably a regular Node... if (node.name != "") { - bool ret = detail::node2hdf5(node,*h.file); + const bool ret = detail::node2hdf5(node,*h.file); h.file->flush(); return ret; } @@ -67,14 +67,6 @@ inline bool convert(const Node &node, HDF5 &h) found_decl = true; } else { // looks like a regular node - /**/ - /// We really need to relax this business about requiring that there - /// be only ONE top-level node. The XML format allows only one - /// document node (and GNDS, probably because of XML, has just one), - /// but JSON and HDF5 allow more (or less!) than one. And we're - /// going to be writing the NDI3 format with this code; it shouldn't - /// have this limitation. - /**/ if (found_top) { // already seen log::warning( diff --git a/src/GNDStk/convert/src/JSON.hpp b/src/GNDStk/convert/src/JSON.hpp index d1f5e911f..cfbb93ff2 100644 --- a/src/GNDStk/convert/src/JSON.hpp +++ b/src/GNDStk/convert/src/JSON.hpp @@ -16,7 +16,7 @@ inline bool convert(const Node &node, JSON &j) static const std::string context = "convert(Node,JSON)"; try { - // Probably a regular Node + // Probably a regular Node... if (node.name != "") return detail::node2json(node,j.doc); diff --git a/src/GNDStk/convert/src/Tree.hpp b/src/GNDStk/convert/src/Tree.hpp index 192f13d4e..cc8fe7857 100644 --- a/src/GNDStk/convert/src/Tree.hpp +++ b/src/GNDStk/convert/src/Tree.hpp @@ -243,18 +243,16 @@ Remark HighFive::File, and by extension GNDStk::HDF5 (our simple wrapper around HighFive::File, to assist in providing uniform behavior between XML, JSON, -and HDF5), refers to an entire HDF5 file. Unlike XML and JSON, it apparently -can't refer to just part of such a file, i.e. part of an HDF5 hierarchy. The +and HDF5), references an entire HDF5 file. Unlike XML and JSON, it apparently +can't reference just part of such a file, i.e. part of an HDF5 hierarchy. The upshot: convert(HDF5,Tree) may be far more meaningful than convert(HDF5,Node), -as the former (Tree) is for a full GNDS hierarchy, the latter for possibly -a partial hierarchy. I'll leave the Node case, though. It will have slightly -different behavior than the Tree case does, due to the decl flag; and also, -the Tree version will call the Node version to do most of the work. We might -consider, at some point, having something like convert(HighFive::Group,Node), -i.e. with a HighFive::Group rather than a HighFive::File, but such a thing -might or might not prove to be useful. A HighFive::Group would end up coming -from a HighFive::File, rather than being on its own like a "snippet" of XML -or JSON could be. We'll see how things hash out. +as the Tree is for a full GNDS hierarchy, Node for possibly a partial hierarchy. +I'll keep the Node case, though. It will have slightly different behavior, due +to the decl flag. Also, the Tree version will call the Node version to do most +of the work. We might consider having a convert(HighFive::Group,Node), i.e. with +a HighFive::Group rather than a HighFive::File, but such a thing might or might +not prove to be useful. A HighFive::Group would come from a HighFive::File; it +wouldn't be a string on its own, like a "snippet" of XML or JSON. */ // HDF5 ==> Node @@ -268,61 +266,31 @@ inline bool convert(const HDF5 &h, Node &node, const bool decl) node.clear(); // optionally, make a boilerplate declaration node - Node *declnode = nullptr; - if (decl) { - // indicates that we built the object from an HDF5... - declnode = &node.add("hdf5"); - } + Node *const declnode = decl + ? &node.add("hdf5") // indicates that we built the object from an HDF5 + : nullptr; // empty hdf5 document? if (h.empty()) return true; - try { - // for brevity - const HighFive::File &file = *h.file; - - // size == 0: not empty in the earlier (h.file == nullptr) sense, - // but, here, meaning that there's nothing in the HDF5 document - const std::size_t size = file.getNumberObjects(); - if (size == 0) - return true; - - // ------------------------ - // convert the nodes - // ------------------------ - - const HighFive::Group &group = file.getGroup("/"); + // not empty in the earlier (h.file == nullptr) sense, + // but with no real content in the HDF5 document? + const HighFive::Group &group = h.file->getGroup("/"); + if (group.getNumberAttributes() == 0 && group.getNumberObjects() == 0) + return true; - // if decl, then put any top-level attributes into the "hdf5" - // child node that would have been created above + try { + // if decl, then place any top-level attributes that exist, in the HDF5, + // into the Node's "hdf5" child that would have been created above if (decl) for (auto &attrName : group.listAttributeNames()) - if (!detail::hdf5attr2node(group.getAttribute(attrName), *declnode)) + if (!detail::hdf5attr2node(group.getAttribute(attrName),*declnode)) return false; - /// may need unconditional "top"=true last argument here... - /// or something like that... - // visit the rest of the "/" group - if (!detail::hdf52node(group, "/", decl ? node.add() : node, decl)) + // visit the rest of "/" + if (!detail::hdf52node(group, "/", node, !decl)) return false; - -#if 0 - // zzz see what can slip into the detail function... - // visit the remaining objects, and their sub-groups recursively - for (const std::string &name : names) { - const HighFive::ObjectType type = file.getObjectType(name); - if (type == HighFive::ObjectType::Group) { - detail::check_top(name, "HDF5", "convert(HDF5,Node)"); - const HighFive::Group &g = file.getGroup(name); - if (!detail::hdf52node(g, name, decl ? node.add() : node)) - return false; - } else if (type != HighFive::ObjectType::Attribute) { - assert(false); /// want group or attribute at top level - } - } -#endif - } catch (...) { log::function("convert(HDF5,Node)"); throw; diff --git a/src/GNDStk/convert/src/detail.hpp b/src/GNDStk/convert/src/detail.hpp index 025acc4d1..55dafd93e 100644 --- a/src/GNDStk/convert/src/detail.hpp +++ b/src/GNDStk/convert/src/detail.hpp @@ -88,34 +88,32 @@ namespace pugi } */ - // Helper: error_xml2node -inline void error_xml2node(const std::string &str) +inline void error_xml2node(const std::string &type) { log::error( - "Internal error in detail::xml2node(pugi::xml_node,Node):\n" - "type pugi::{} found, but not handled, as sub-element", str + "Internal error in xml2node(pugi::xml_node, Node):\n" + "Type pugi::{} found, but not handled, as sub-element.", + type ); throw std::exception{}; } - // xml2node // pugi::xml_node ==> Node template bool xml2node(const pugi::xml_node &xnode, NODE &node) { static const std::string context = - "detail::xml2node(pugi::xml_node, Node)"; + "xml2node(pugi::xml_node, Node)"; // check destination node if (!node.empty()) { log::error( - "Internal error in detail::xml2node(pugi::xml_node,Node):\n" - "destination Node is supposed to arrive here empty, but didn't" + "Internal error in xml2node(pugi::xml_node, Node):\n" + "Destination Node is supposed to arrive here empty, but didn't." ); throw std::exception{}; - return false; } // name @@ -196,11 +194,10 @@ bool xml2node(const pugi::xml_node &xnode, NODE &node) // ------------------------ log::error( - "Internal error in detail::xml2node(pugi::xml_node,Node):\n" - "we've encountered a pugi:: node type that we don't know about" + "Internal error in xml2node(pugi::xml_node, Node):\n" + "Encountered a pugi:: node type that we don't know about." ); throw std::exception{}; - return false; } // done @@ -223,24 +220,23 @@ bool xml2node(const pugi::xml_node &xnode, NODE &node) // iterator form rather than the range-based-for form. Perhaps there's a way // to reformulate all this in a shorter way, but this is what we have for now. - // Helper: error_json2node -inline void error_json2node(const std::string &str) +inline void error_json2node(const std::string &message) { log::error( - "Internal error in detail::json2node(nlohmann::json,Node):\n" - "message is \"{}\"; please let us know about this", str + "Internal error in json2node(nlohmann::json, Node):\n" + "Message: \"{}\".", + message ); throw std::exception{}; } - // json2node template bool json2node(const nlohmann::json::const_iterator &iter, NODE &node) { static const std::string context = - "detail::json2node(nlohmann::json::const_iterator, Node)"; + "json2node(nlohmann::json::const_iterator, Node)"; // the node sent here should be fresh, ready to receive entries... if (!node.empty()) @@ -304,11 +300,9 @@ bool json2node(const nlohmann::json::const_iterator &iter, NODE &node) // Here, OBJECT is either HighFive::File or HighFive::Group template -bool node2hdf5( - const NODE &node, OBJECT &h, - const std::string &suffix = "" -) { - // As for JSON; see the comment in node2json() +bool node2hdf5(const NODE &node, OBJECT &h, const std::string &suffix = "") +{ + // As with JSON; see the comment in node2json() const std::string nameOriginal = node.name; const std::string nameSuffixed = node.name + suffix; @@ -316,28 +310,30 @@ bool node2hdf5( HighFive::Group group = h.createGroup(nameSuffixed); // ------------------------ - // metadata ==> group + // metadata ==> file/group // ------------------------ + // nodeName if appropriate (as with JSON, allows recovery of original name) if (suffix != "") group.createAttribute(std::string("nodeName"), nameOriginal); + // existing attributes for (auto &meta : node.metadata) group.createAttribute(meta.first, meta.second); - /* -zzz -we should see what this actually produces -but we should actually have it be more intelligent than the JSON code -understand block data -understand cdata/pcdata/comment/text system in Node/Tree - */ + // todo + // Right now, we're doing a straight translation of our internal Node + // structure's string-based storage scheme, where everything (including + // in particular the text from XML CDATA and PCDATA nodes) is stored + // internally as std::strings. Of course, for HDF5 we'll actually want + // to recognize those constructs and write HDF5 DataSets instead! For + // now, we'll just get *something* working. // ------------------------ - // children ==> group + // children ==> file/group // ------------------------ - // Logic as for JSON; see the comment in node2json() + // Logic as with JSON; see the comment in node2json() std::map childNames; for (auto &c : node.children) { auto iter = childNames.find(c->name); @@ -362,54 +358,146 @@ understand cdata/pcdata/comment/text system in Node/Tree // ----------------------------------------------------------------------------- // hdf5attr2node +// For HighFive::Attribute +// ----------------------------------------------------------------------------- + +// Helper: attrTYPE2node +template +bool attrTYPE2node(const HighFive::Attribute &attr, NODE &node) +{ + if (attr.getDataType() == HighFive::AtomicType{}) { + const std::string attrName = attr.getName(); + const std::size_t attrSize = attr.getSpace().getElementCount(); + + // Scalar case. Includes bool. + if (attrSize == 1) { + T scalar; + attr.read(scalar); + node.add(attrName,scalar); + return true; + } + + // Vector case. EXcludes bool, as HighFive (perhaps HDF5 in general?) + // doesn't appear to support it in this case. Indeed, the body of the + // if-constexpr doesn't *compile* with bool. (Hence our if-constexpr.) + if constexpr (!std::is_same_v) { + std::vector vector; + vector.reserve(attrSize); + attr.read(vector); + node.add(attrName,vector); + return true; + } + } + + return false; +} + +// hdf5attr2node +template +bool hdf5attr2node(const HighFive::Attribute &attr, NODE &node) +{ + // HighFive's documentation leaves much to be desired. I used what I found + // in HighFive/include/highfive/bits/H5DataType_misc.hpp to get an idea of + // what attribute *types* are allowed. That file also had some handling of + // C-style fixed-length strings, as with char[length], and std::complex as + // well. It didn't have long double, which I'd have liked, but that's fine. + // I won't bother with fixed-length strings or with std::complex right now, + // but will support the rest. + if (attrTYPE2node(attr,node)) return true; + if (attrTYPE2node(attr,node)) return true; + if (attrTYPE2node(attr,node)) return true; + if (attrTYPE2node(attr,node)) return true; + if (attrTYPE2node(attr,node)) return true; + if (attrTYPE2node(attr,node)) return true; + if (attrTYPE2node(attr,node)) return true; + if (attrTYPE2node(attr,node)) return true; + if (attrTYPE2node(attr,node)) return true; + if (attrTYPE2node(attr,node)) return true; + if (attrTYPE2node(attr,node)) return true; + if (attrTYPE2node(attr,node)) return true; + if (attrTYPE2node(attr,node)) return true; + if (attrTYPE2node(attr,node)) return true; + if (attrTYPE2node(attr,node)) return true; + + log::error( + "HDF5 Attribute \"{}\"'s DataType \"{}\" is not handled at this time.", + attr.getName(), attr.getDataType().string()); + log::function("hdf5attr2node(HighFive::Attribute, Node)"); + + return false; +} + + + +// ----------------------------------------------------------------------------- +// hdf5data2node +// For HighFive::DataSet // ----------------------------------------------------------------------------- -inline bool hdf5attr2node( - const HighFive::Attribute &attr, - Node &node +// Helper: dataTYPE2node +template +bool dataTYPE2node(const HighFive::DataSet &data, NODE &node) +{ + if (data.getDataType() == HighFive::AtomicType{}) { + // Comments as in the similar helper function attrTYPE2node()... + const std::size_t dataSize = data.getElementCount(); + + if (dataSize == 1) { + T scalar; + data.read(scalar); + node.add("pcdata").add("text",scalar); + return true; + } + + if constexpr (!std::is_same_v) { + std::vector vector; + vector.reserve(dataSize); + data.read(vector); + node.add("pcdata").add("text",vector); + return true; + } + } + + return false; +} + +// hdf5data2node +template +bool hdf5data2node( + const HighFive::DataSet &data, const std::string &dataName, + NODE &node ) { - (void)attr; - (void)node; - - // print - const auto print = [](auto &value) { std::cout << value << std::endl; }; - - const HighFive::DataType attrType = attr.getDataType(); - - if (attrType == HighFive::AtomicType{}) - print(" ==> char "); - if (attrType == HighFive::AtomicType{}) - print(" ==> signed char "); - if (attrType == HighFive::AtomicType{}) - print(" ==> unsigned char "); - if (attrType == HighFive::AtomicType{}) - print(" ==> short "); - if (attrType == HighFive::AtomicType{}) - print(" ==> unsigned short "); - if (attrType == HighFive::AtomicType{}) - print(" ==> int "); - if (attrType == HighFive::AtomicType{}) - print(" ==> unsigned "); - if (attrType == HighFive::AtomicType{}) - print(" ==> long "); - if (attrType == HighFive::AtomicType{}) - print(" ==> unsigned long "); - if (attrType == HighFive::AtomicType{}) - print(" ==> long long "); - if (attrType == HighFive::AtomicType{}) - print(" ==> unsigned long long"); - if (attrType == HighFive::AtomicType{}) - print(" ==> float "); - if (attrType == HighFive::AtomicType{}) - print(" ==> double "); - if (attrType == HighFive::AtomicType{}) - print(" ==> std::string "); - if (attrType == HighFive::AtomicType{}) - print(" ==> bool "); - - // zzz write this; + // node name + node.name = dataName; - return true; + // the data set's attributes + for (auto &attrName : data.listAttributeNames()) + if (!hdf5attr2node(data.getAttribute(attrName), node)) + return false; + + // the data set's data + if (dataTYPE2node(data,node)) return true; + if (dataTYPE2node(data,node)) return true; + if (dataTYPE2node(data,node)) return true; + if (dataTYPE2node(data,node)) return true; + if (dataTYPE2node(data,node)) return true; + if (dataTYPE2node(data,node)) return true; + if (dataTYPE2node(data,node)) return true; + if (dataTYPE2node(data,node)) return true; + if (dataTYPE2node(data,node)) return true; + if (dataTYPE2node(data,node)) return true; + if (dataTYPE2node(data,node)) return true; + if (dataTYPE2node(data,node)) return true; + if (dataTYPE2node(data,node)) return true; + if (dataTYPE2node(data,node)) return true; + if (dataTYPE2node(data,node)) return true; + + log::error( + "HDF5 DataSet \"{}\"'s DataType \"{}\" is not handled at this time.", + dataName, data.getDataType().string()); + log::function("hdf5data2node(HighFive::DataSet, dataName, Node)"); + + return false; } @@ -419,108 +507,65 @@ inline bool hdf5attr2node( // ----------------------------------------------------------------------------- // Helper: error_hdf52node -inline void error_hdf52node(const std::string &str) +inline void error_hdf52node(const std::string &message) { log::error( - "Internal error in detail::hdf52node(HighFive::Object,Node):\n" - "message is \"{}\"; please let us know about this", str + "Internal error in hdf52node(HighFive::Group, std::string, Node):\n" + "Message: \"{}\".", + message ); throw std::exception{}; } - // hdf52node template bool hdf52node( - const HighFive::Group &group, - const std::string &groupName, - NODE &node, - const bool decl = false + const HighFive::Group &group, const std::string &groupName, + NODE &node, const bool requireEmpty = true ) { static const std::string context = - "detail::hdf52node(HighFive::Group, std::string, Node)"; + "hdf52node(HighFive::Group, std::string, Node)"; - if (!decl) { - // the node sent here should be fresh, ready to receive entries... - if (!node.empty()) - error_hdf52node("!node.empty()"); + // The node sent here should be fresh, ready to receive entries + if (requireEmpty && !node.empty()) + error_hdf52node("!node.empty()"); - // group name ==> node name + // ------------------------ + // HDF5 group name + // ==> node name + // ------------------------ + + // if "/" then we're at the top-level node, which we call "" internally + if (groupName != "/") node.name = groupName; - // get metadata from HDF5 attributes + // ------------------------ + // HDF5 attributes + // ==> metadata + // ------------------------ + + // if "/" then attributes were handled, in a special way, by the caller + if (groupName != "/") for (auto &attrName : group.listAttributeNames()) - hdf5attr2node(group.getAttribute(attrName), node); - } + if (!hdf5attr2node(group.getAttribute(attrName), node)) + return false; // ------------------------ - // get children from // HDF5 sub-groups + // ==> children // ------------------------ - /// bool saw_dataset - /* - In XML: - - 1.2 3.4 5.6 - 7.8 9.0 - - - In Tree/Node: - foo - energy - pcdata - text="1.2 3.4 5.6" - velocity - pcdata - text="7.8 9.0" - - In HDF5: // zzz Meaning, we should set it up this way! - group "foo" - dataset "energy" - can have attributes!! - - dataset "velocity" - can have attributes!! - - - The above way seems like a good (more importantly, apparently viable) manner - in which to handle XML "pcdata" (plain character data). - - What about XML "cdata" - which we get from those XML "" nodes? - It doesn't seem like those should be considered "data sets." (Unlike Pcdata - nodes, which, at least in GNDS, are clearly data sets.) - - For XML CDATA, it would seem reasonable to have essentially the same handling - we have for Node itself, or for JSON. - - Let's consider some XML: - - - - Independent of what we do in Node/Tree, and in JSON, let's think about what - makes sense in HDF5... - - group "documentation" - attribute "name" - group "cdata" - attribute "text" - - OK, well, that's basically what we do for JSON, except that we don't need - that obnoxious JSON "attributes" middleman. - */ - for (auto &elemName : group.listObjectNames()) { switch (group.getObjectType(elemName)) { // File + // NOT EXPECTED IN THIS CONTEXT case HighFive::ObjectType::File : error_hdf52node("ObjectType \"File\" not expected here"); break; // Group + // ACTION: call the present function recursively case HighFive::ObjectType::Group : try { if (!hdf52node(group.getGroup(elemName), elemName, node.add())) @@ -532,40 +577,54 @@ bool hdf52node( break; // UserDataType + // NOT HANDLED; perhaps we could provide something in the future case HighFive::ObjectType::UserDataType : - error_hdf52node("unhandled ObjectType \"UserDataType\""); + error_hdf52node("ObjectType \"UserDataType\" not handled"); break; // DataSpace (not to be confused with Dataset) + // NOT EXPECTED IN THIS CONTEXT case HighFive::ObjectType::DataSpace : error_hdf52node("ObjectType \"DataSpace\" not expected here"); break; // Dataset + // ACTION: handle the DataSet's data case HighFive::ObjectType::Dataset : - std::cout << "Must handle HighFive Dataset!" << std::endl; - // zzz Must handle! And, remember, Datasets can have attributes. + try { + if (!hdf5data2node( + group.getDataSet(elemName), + elemName, + node.add() + )) + return false; + } catch (...) { + log::function(context); + throw; + } break; // Attribute + // NOT EXPECTED IN THIS CONTEXT case HighFive::ObjectType::Attribute : - // Re: the error message... - // Wait, why wouldn't an attribute show up here? :-) Apparently, // group.listObjectNames() (used in the for-loop we're in right - // now) doesn't include attribute names! Which is why we had the - // earlier for-loop (the one that used group.listAttributeNames()) - // in order to handle attributes. + // now) apparently doesn't include attribute names - which is fine, + // because we already handled attributes earlier. So, here, we just + // produce an error if ObjectType::Attribute inexplicably made an + // appearance here, where we don't expect it. error_hdf52node("ObjectType \"Attribute\" not expected here"); break; // Other + // NOT HANDLED; we're not sure when this would arise case HighFive::ObjectType::Other : - error_hdf52node("unhandled ObjectType \"Other\""); + error_hdf52node("ObjectType \"Other\" not handled"); break; // default + // NOT HANDLED; presumably our switch has covered all bases already default: - error_hdf52node("unhandled ObjectType"); + error_hdf52node("ObjectType [unknown] not handled"); break; } // switch @@ -612,35 +671,32 @@ bool check_special(const NODE &node, const std::string &label) { if (node.children.size() != 0) { log::error( - "Internal error in detail::node2xml(Node,pugi::xml_node):\n" - "ill-formed <" + label + "> node; " - "should have 0 children, but has {}", + "Internal error in node2xml(Node, pugi::xml_node):\n" + "Ill-formed <" + label + "> node; " + "should have 0 children, but has {}.", node.children.size() ); throw std::exception{}; - return false; } if (node.metadata.size() != 1) { log::error( - "Internal error in detail::node2xml(Node,pugi::xml_node):\n" - "ill-formed <" + label + "> node; " - "should have 1 metadatum, but has {}", + "Internal error in node2xml(Node, pugi::xml_node):\n" + "Ill-formed <" + label + "> node; " + "should have 1 metadatum, but has {}.", node.metadata.size() ); throw std::exception{}; - return false; } if (node.metadata.begin()->first != "text") { log::error( - "Internal error in detail::node2xml(Node,pugi::xml_node):\n" - "ill-formed <" + label + "> node; " - "should have metadatum key \"text\", but has key \"{}\"", + "Internal error in node2xml(Node, pugi::xml_node):\n" + "Ill-formed <" + label + "> node; " + "should have metadatum key \"text\", but has key \"{}\".", node.metadata.begin()->first ); throw std::exception{}; - return false; } return true; @@ -679,7 +735,7 @@ template bool node2xml(const NODE &node, pugi::xml_node &x) { static const std::string context = - "detail::node2xml(Node, pugi::xml_node)"; + "node2xml(Node, pugi::xml_node)"; // name pugi::xml_node xnode = x.append_child(node.name.data()); @@ -727,7 +783,7 @@ inline void check_top( std::string message = "Name \"{}\" in {} object's top-level node is not recognized\n" "in our list of allowable names for top-level GNDS nodes:\n"; - for (const std::string &n : detail::AllowedTop) + for (const std::string &n : AllowedTop) message += " \"" + n + "\"\n"; message += "Creating node \"{}\" anyway..."; log::warning(message, name, classname, name); diff --git a/src/GNDStk/string2type.hpp b/src/GNDStk/string2type.hpp index edbd7f838..634c9ff62 100644 --- a/src/GNDStk/string2type.hpp +++ b/src/GNDStk/string2type.hpp @@ -55,6 +55,21 @@ inline void convert(std::istream &is, T &value) } } +/* +/// fixme Will probably need this eventually, to resolve a similar ambiguity +/// to the one I encountered with convert(string,ostream). I anticipate this +/// issue arising when node2hdf5() is outfitted with proper type awareness, +/// and in particular when we try to do a convert(string,vector), +/// which (see next commented block below) first converts the string to an +/// istringstream, then needs to resolve convert(i[string]stream,string). + +// string +inline void convert(std::istream &is, std::string &value) +{ + is >> value; +} +*/ + // pair template inline void convert(std::istream &is, std::pair &p) diff --git a/src/GNDStk/type2string.hpp b/src/GNDStk/type2string.hpp index 1ae8f0c38..ffee2823a 100644 --- a/src/GNDStk/type2string.hpp +++ b/src/GNDStk/type2string.hpp @@ -34,6 +34,12 @@ inline void convert(const T &value, std::ostream &os) } } +// string +inline void convert(const std::string &value, std::ostream &os) +{ + os << value; +} + // pair template inline void convert(const std::pair &p, std::ostream &os) diff --git a/src/GNDStk/utility.hpp b/src/GNDStk/utility.hpp index 35345ef4c..9ab8aee30 100644 --- a/src/GNDStk/utility.hpp +++ b/src/GNDStk/utility.hpp @@ -136,7 +136,7 @@ inline std::string diagnostic( { "info", "\033[36;21m" }, // cyan { "warning", "\033[33;1m" }, // yellow { "error", "\033[31;21m" }, // red - { "debug", "\033[37;21m" } // white + { "debug", "\033[37;1m" } // white }; static const std::string under = "\033[4m"; // underline on static const std::string unoff = "\033[24m"; // underline off From 3e70eede910283d088962d4e12ec875af32193d9 Mon Sep 17 00:00:00 2001 From: Martin Staley Date: Fri, 10 Dec 2021 23:34:19 -0700 Subject: [PATCH 20/39] Name change: BodyText to BlockData. The former was taken from GNDS, but the latter is much more descriptive. --- autogen/json2class.cpp | 12 +- cmake/unit_testing.cmake | 2 +- src/GNDStk.hpp | 2 +- src/GNDStk/{BodyText.hpp => BlockData.hpp} | 44 +-- .../{BodyText => BlockData}/src/assign.hpp | 12 +- .../{BodyText => BlockData}/src/colors.hpp | 0 .../{BodyText => BlockData}/src/detail.hpp | 0 .../{BodyText => BlockData}/src/fromNode.hpp | 14 +- .../{BodyText => BlockData}/src/get.hpp | 24 +- .../{BodyText => BlockData}/src/params.hpp | 6 +- .../{BodyText => BlockData}/src/string.hpp | 2 +- .../{BodyText => BlockData}/src/sync.hpp | 4 +- .../{BodyText => BlockData}/src/toNode.hpp | 4 +- .../{BodyText => BlockData}/src/types.hpp | 0 .../{BodyText => BlockData}/src/write.hpp | 0 .../test/BlockData.test.cpp} | 56 ++-- .../test/CMakeLists.txt | 10 +- .../test/assign.test.cpp | 32 +- .../test/detail.test.cpp | 2 +- .../test/fromNode.test.cpp | 28 +- .../{BodyText => BlockData}/test/get.test.cpp | 282 +++++++++--------- .../test/params.test.cpp | 34 +-- .../test/string.test.cpp | 14 +- .../test/sync.test.cpp | 48 +-- .../test/toNode.test.cpp | 64 ++-- .../test/types.test.cpp | 8 +- .../test/write.test.cpp | 32 +- src/GNDStk/Component.hpp | 16 +- src/GNDStk/Component/src/detail.hpp | 2 +- src/GNDStk/Component/src/finish.hpp | 10 +- src/GNDStk/Component/src/fromNode.hpp | 2 +- src/GNDStk/Component/src/toNode.hpp | 10 +- src/GNDStk/Component/src/toNodeBody.hpp | 2 +- src/GNDStk/Component/src/write.hpp | 4 +- src/GNDStk/Component/test/Component.test.cpp | 8 +- src/GNDStk/Component/test/ctor.test.cpp | 4 +- src/GNDStk/Component/test/detail.test.cpp | 2 +- src/GNDStk/Component/test/finish.test.cpp | 18 +- src/GNDStk/Component/test/fromNode.test.cpp | 2 +- src/GNDStk/Component/test/getter.test.cpp | 2 +- src/GNDStk/Component/test/prototype.hpp | 82 ++--- src/GNDStk/precision/test/precision.test.cpp | 8 +- src/GNDStk/precision/test/precision.test.hpp | 78 ++--- src/GNDStk/utility.hpp | 4 +- src/GNDStk/v1.9/containers/Axes.hpp | 8 +- src/GNDStk/v1.9/containers/Axis.hpp | 8 +- src/GNDStk/v1.9/containers/Grid.hpp | 8 +- src/GNDStk/v1.9/containers/Link.hpp | 8 +- src/GNDStk/v1.9/containers/Regions1d.hpp | 8 +- src/GNDStk/v1.9/containers/Values.hpp | 22 +- .../v1.9/containers/Values/src/custom.hpp | 2 +- src/GNDStk/v1.9/containers/XYs1d.hpp | 8 +- src/GNDStk/v1.9/transport/CrossSection.hpp | 8 +- src/GNDStk/v1.9/transport/Reaction.hpp | 8 +- src/GNDStk/v1.9/transport/ReactionSuite.hpp | 8 +- src/GNDStk/v1.9/transport/Reactions.hpp | 8 +- 56 files changed, 547 insertions(+), 547 deletions(-) rename src/GNDStk/{BodyText.hpp => BlockData.hpp} (82%) rename src/GNDStk/{BodyText => BlockData}/src/assign.hpp (88%) rename src/GNDStk/{BodyText => BlockData}/src/colors.hpp (100%) rename src/GNDStk/{BodyText => BlockData}/src/detail.hpp (100%) rename src/GNDStk/{BodyText => BlockData}/src/fromNode.hpp (72%) rename src/GNDStk/{BodyText => BlockData}/src/get.hpp (95%) rename src/GNDStk/{BodyText => BlockData}/src/params.hpp (93%) rename src/GNDStk/{BodyText => BlockData}/src/string.hpp (94%) rename src/GNDStk/{BodyText => BlockData}/src/sync.hpp (82%) rename src/GNDStk/{BodyText => BlockData}/src/toNode.hpp (97%) rename src/GNDStk/{BodyText => BlockData}/src/types.hpp (100%) rename src/GNDStk/{BodyText => BlockData}/src/write.hpp (100%) rename src/GNDStk/{BodyText/test/BodyText.test.cpp => BlockData/test/BlockData.test.cpp} (78%) rename src/GNDStk/{BodyText => BlockData}/test/CMakeLists.txt (72%) rename src/GNDStk/{BodyText => BlockData}/test/assign.test.cpp (90%) rename src/GNDStk/{BodyText => BlockData}/test/detail.test.cpp (99%) rename src/GNDStk/{BodyText => BlockData}/test/fromNode.test.cpp (79%) rename src/GNDStk/{BodyText => BlockData}/test/get.test.cpp (69%) rename src/GNDStk/{BodyText => BlockData}/test/params.test.cpp (84%) rename src/GNDStk/{BodyText => BlockData}/test/string.test.cpp (83%) rename src/GNDStk/{BodyText => BlockData}/test/sync.test.cpp (88%) rename src/GNDStk/{BodyText => BlockData}/test/toNode.test.cpp (86%) rename src/GNDStk/{BodyText => BlockData}/test/types.test.cpp (95%) rename src/GNDStk/{BodyText => BlockData}/test/write.test.cpp (90%) diff --git a/autogen/json2class.cpp b/autogen/json2class.cpp index 74d20b212..d2c44ddce 100644 --- a/autogen/json2class.cpp +++ b/autogen/json2class.cpp @@ -1151,7 +1151,7 @@ void writeClassSetters(writer &out, const PerClass &per) out(1,"// @(value)", m.name); // special cases: we want to send length, start, and valueType - // to the BodyText base as well + // to the BlockData base as well const bool special = per.isData && (m.name == "length" || m.name == "start" || m.name == "valueType"); @@ -1160,10 +1160,10 @@ void writeClassSetters(writer &out, const PerClass &per) // note that if type is optional, a T can still be sent out(1,"@ &@(const @ &obj)", per.clname, m.name, m.typeFull); if (special && m.isDefaulted) - out(2,"{ BodyText::@(content.@ = obj); return *this; }", + out(2,"{ BlockData::@(content.@ = obj); return *this; }", m.name, m.name); if (special && !m.isDefaulted) - out(2,"{ BodyText::@(@() = obj); return *this; }", + out(2,"{ BlockData::@(@() = obj); return *this; }", m.name, m.name); if (!special && m.isDefaulted) out(2,"{ content.@ = obj; return *this; }", @@ -1176,7 +1176,7 @@ void writeClassSetters(writer &out, const PerClass &per) if (m.isDefaulted) { out(1,"@ &@(const std::optional<@> &obj)", per.clname, m.name, m.type); special - ? out(2,"{ BodyText::@(content.@ = obj); return *this; }", + ? out(2,"{ BlockData::@(content.@ = obj); return *this; }", m.name, m.name) : out(2,"{ content.@ = obj; return *this; }", m.name); } @@ -1234,7 +1234,7 @@ void writeClassCtorComponent( writer &out, const PerClass &per, const bool copyOrMove ) { out(2,"Component{"); - out(3, copyOrMove ? "other.baseBodyText()" : "BodyText{}", false); + out(3, copyOrMove ? "other.baseBlockData()" : "BlockData{}", false); for (const auto &m : per.metadata) { // metadata out(","); @@ -1405,7 +1405,7 @@ void writeClass(PerClass &per, const InfoSpecs &specs) out(); out(1,"using Component::construct;"); if (per.isData) - out(1,"using BodyText::operator=;"); + out(1,"using BlockData::operator=;"); // output: defaults (applicable only to metadata) out(); diff --git a/cmake/unit_testing.cmake b/cmake/unit_testing.cmake index c17167b09..8406f6b40 100644 --- a/cmake/unit_testing.cmake +++ b/cmake/unit_testing.cmake @@ -27,7 +27,7 @@ add_subdirectory( src/GNDStk/Child/test ) add_subdirectory( src/GNDStk/convert/test ) add_subdirectory( src/GNDStk/utility/test ) add_subdirectory( src/GNDStk/Component/test ) -add_subdirectory( src/GNDStk/BodyText/test ) +add_subdirectory( src/GNDStk/BlockData/test ) add_subdirectory( src/GNDStk/precision/test ) add_subdirectory( src/GNDStk/enums/Encoding/test ) diff --git a/src/GNDStk.hpp b/src/GNDStk.hpp index 42c45dfac..24012ac91 100644 --- a/src/GNDStk.hpp +++ b/src/GNDStk.hpp @@ -110,7 +110,7 @@ namespace misc { using namespace common; } #include "GNDStk/Support.hpp" // Base classes for primary Standard Interface data classes -#include "GNDStk/BodyText.hpp" +#include "GNDStk/BlockData.hpp" #include "GNDStk/Component.hpp" diff --git a/src/GNDStk/BodyText.hpp b/src/GNDStk/BlockData.hpp similarity index 82% rename from src/GNDStk/BodyText.hpp rename to src/GNDStk/BlockData.hpp index 7b963fd0c..e32f31da8 100644 --- a/src/GNDStk/BodyText.hpp +++ b/src/GNDStk/BlockData.hpp @@ -2,20 +2,20 @@ // Printing-related colors. // todo Eventually, this probably belongs in a more context-agnostic // location, such as GNDStk's utility.hpp file or something like it. -#include "GNDStk/BodyText/src/colors.hpp" +#include "GNDStk/BlockData/src/colors.hpp" // Miscellaneous helper constructs. -#include "GNDStk/BodyText/src/detail.hpp" +#include "GNDStk/BlockData/src/detail.hpp" // ----------------------------------------------------------------------------- -// BodyText +// BlockData // The case is specialized and has the fun stuff. This one needs -// just a bit of content, in order to facilitate uniform treatment of BodyText. +// just a bit of content, in order to facilitate uniform treatment of BlockData. // ----------------------------------------------------------------------------- -template -class BodyText { +template +class BlockData { public: using VariantOfVectors = std::variant; using VariantOfScalars = std::variant; @@ -26,22 +26,22 @@ class BodyText { // ----------------------------------------------------------------------------- -// BodyText +// BlockData // // Designed to be flexible, smart, and safe. Does lots of checks, and, for the // DATA == void case, can essentially re-form itself depending on what type of // data someone tries to extract. // // For efficiency in the DATA == void case, an application might want to copy -// to its own vector (e.g. auto myvec = mybodytext.get>()) +// to its own vector (e.g. auto myvec = myblockdata.get>()) // in order to do work on (or with) the vector there, before copying it back. // ----------------------------------------------------------------------------- template -class BodyText { +class BlockData { public: - #include "GNDStk/BodyText/src/types.hpp" + #include "GNDStk/BlockData/src/types.hpp" // For convenience in various SFINAE and if-constexpr constructs static inline constexpr bool runtime = detail::isVoid; @@ -88,22 +88,22 @@ class BodyText { // struct vars { length, start, valueType } // Includes public getters and setters for those. // We won't use valueType if DATA != void. - #include "GNDStk/BodyText/src/params.hpp" + #include "GNDStk/BlockData/src/params.hpp" // trim - // Flag: should the conversion of BodyText data back into textual data, + // Flag: should the conversion of BlockData data back into textual data, // in a Node, trim zeros from the start and end of the output? mutable bool trim = true; // Getters and setters for the raw string: - #include "GNDStk/BodyText/src/string.hpp" + #include "GNDStk/BlockData/src/string.hpp" // active() Active active() const { return act; } // clear() // Clears the vector, or the active vector alternative in the variant. - BodyText &clear() + BlockData &clear() { if constexpr (runtime) std::visit([](auto &&alt) { alt.clear(); }, variant); @@ -117,7 +117,7 @@ class BodyText { // size() // Returns the size of the vector, or of the active vector alternative in // the variant. Depending on what someone may or may not have done with the - // current BodyText object, size() might or might not reflect the values of + // current BlockData object, size() might or might not reflect the values of // length and/or start, or reflect the current contents of the raw string. std::size_t size() const { @@ -128,21 +128,21 @@ class BodyText { } // Various vector get() functions, and the type-specific doubles() etc. - #include "GNDStk/BodyText/src/get.hpp" + #include "GNDStk/BlockData/src/get.hpp" // Read/write data, from/to a Node - #include "GNDStk/BodyText/src/fromNode.hpp" - #include "GNDStk/BodyText/src/toNode.hpp" + #include "GNDStk/BlockData/src/fromNode.hpp" + #include "GNDStk/BlockData/src/toNode.hpp" // Write to ostream // Not to be confused with the process of writing data to a Node - #include "GNDStk/BodyText/src/write.hpp" + #include "GNDStk/BlockData/src/write.hpp" // Pull/push length/start/valueType from/to derived-class struct content - #include "GNDStk/BodyText/src/sync.hpp" + #include "GNDStk/BlockData/src/sync.hpp" // Assignment // From string or vector; the former == calling our raw string setter - #include "GNDStk/BodyText/src/assign.hpp" + #include "GNDStk/BlockData/src/assign.hpp" -}; // class BodyText +}; // class BlockData diff --git a/src/GNDStk/BodyText/src/assign.hpp b/src/GNDStk/BlockData/src/assign.hpp similarity index 88% rename from src/GNDStk/BodyText/src/assign.hpp rename to src/GNDStk/BlockData/src/assign.hpp index b1b975822..e7e9b5a7c 100644 --- a/src/GNDStk/BodyText/src/assign.hpp +++ b/src/GNDStk/BlockData/src/assign.hpp @@ -4,7 +4,7 @@ // Same effect as the string(new string) setter // ----------------------------------------------------------------------------- -BodyText &operator=(const std::string &str) +BlockData &operator=(const std::string &str) { return string(str); } @@ -17,15 +17,15 @@ BodyText &operator=(const std::string &str) /* DISCUSSION -Elsewhere, a BodyText object can be made from a GNDS node. From GNDS, we get +Elsewhere, a BlockData object can be made from a GNDS node. From GNDS, we get a text string (copied to the rawstring field), from which a vector of values can be created on an as-needed basis. A GNDS node might also give us any of length, start, and valueType, which, when pulling data from the Node, we'll use if they're there, or otherwise assume to be our defaults. -Here, we're allowing for an assignment BodyText = vector. For this assignment, +Here, we're allowing for an assignment BlockData = vector. For this assignment, the caller should send the full, complete vector of values that's appropriate -for the GNDS Node whose data this BodyText object is intended to represent. +for the GNDS Node whose data this BlockData object is intended to represent. Specifically: the vector should contain whatever leading and/or trailing 0s the full data vector is supposed to have. The length and start values are @@ -40,14 +40,14 @@ assigning here.) As for valueType, this function attempts to guess it from the vector's element type, and sets it to "", the empty string, if we don't recognize that type. -If a vector that's assigned from, here, is still in play when this BodyText's +If a vector that's assigned from, here, is still in play when this BlockData's data are written to a Node (see the toNode() function), then toNode() will recompute length and start automatically, based on the vector's beginning and ending content, if the "trim" flag is set. See toNode() for more information. */ template -std::enable_if_t, BodyText &> +std::enable_if_t, BlockData &> operator=(const std::vector &vec) { // set the raw string to "", because it's no longer considered meaningful diff --git a/src/GNDStk/BodyText/src/colors.hpp b/src/GNDStk/BlockData/src/colors.hpp similarity index 100% rename from src/GNDStk/BodyText/src/colors.hpp rename to src/GNDStk/BlockData/src/colors.hpp diff --git a/src/GNDStk/BodyText/src/detail.hpp b/src/GNDStk/BlockData/src/detail.hpp similarity index 100% rename from src/GNDStk/BodyText/src/detail.hpp rename to src/GNDStk/BlockData/src/detail.hpp diff --git a/src/GNDStk/BodyText/src/fromNode.hpp b/src/GNDStk/BlockData/src/fromNode.hpp similarity index 72% rename from src/GNDStk/BodyText/src/fromNode.hpp rename to src/GNDStk/BlockData/src/fromNode.hpp index c54b50027..0c7366d80 100644 --- a/src/GNDStk/BodyText/src/fromNode.hpp +++ b/src/GNDStk/BlockData/src/fromNode.hpp @@ -1,15 +1,15 @@ // ----------------------------------------------------------------------------- -// BodyText::fromNode(Node) +// BlockData::fromNode(Node) // ----------------------------------------------------------------------------- void fromNode(const Node &node) { // length, start, and valueType might be present in the Node, but we won't - // fetch any of them here. Elsewhere, the current BodyText object should have - // its length, start, and valueType pulled from those respective values in - // an object of a class derived from Component (which in turn derives from - // BodyText). That object's content will have been pulled from the same Node. + // fetch any of them here. Elsewhere, the current BlockData object should + // have its length, start, and valueType pulled from those respective values + // in an object of a class derived from Component, which in turn derives from + // BlockData. That object's content will have been pulled from the same Node. // Here, we just get the Node's values: "plain character data" in XML terms. bool found = false; @@ -18,7 +18,7 @@ void fromNode(const Node &node) if (!found) { rawstring = ""; - // Warning, re: why are we in BodyText if there's no body text? + // Warning, re: why are we in BlockData if there's no body text? // Perhaps it's possible that the Node has a non-default length and/or // start, so that the values are all supposed to be...zero. Until and // unless we discover otherwise, however, we doubt that that would be @@ -29,7 +29,7 @@ void fromNode(const Node &node) "(plain\ncharacter data), " "but no such content was found in the GNDS node." ); - log::member("BodyText::fromNode(Node, with name \"{}\")", node.name); + log::member("BlockData::fromNode(Node, with name \"{}\")", node.name); } // Above, we set the raw string. The following reflects this, so that the diff --git a/src/GNDStk/BodyText/src/get.hpp b/src/GNDStk/BlockData/src/get.hpp similarity index 95% rename from src/GNDStk/BodyText/src/get.hpp rename to src/GNDStk/BlockData/src/get.hpp index 0ab133d0a..11c522bb2 100644 --- a/src/GNDStk/BodyText/src/get.hpp +++ b/src/GNDStk/BlockData/src/get.hpp @@ -107,7 +107,7 @@ If active == vector: If the variant already contains a vector: Return it; we're done. - *** Under the correct and normal use of BodyText, *** + *** Under the correct and normal use of BlockData, *** *** this simple action will probably be the most common. *** Else: @@ -117,7 +117,7 @@ If active == vector: In the active == vector case, length, start, and valueType aren't considered to be relevant, and play no role. We consider those values to be meaningful -ONLY in relation to BodyText's raw string, and we deal with them here only +ONLY in relation to BlockData's raw string, and we deal with them here only if and when we make the vector from the raw string. That way, callers can access, manipulate, and even completely change the @@ -144,7 +144,7 @@ vector in the variant. Note that because the variant was declared to be mutable, we were indeed able to rebuild the vector if doing so was necessary. But we'll still return a *const* reference in that case, because the present object is conceptually const, and a caller shouldn't therefore be allowed to -modify the vector outside of BodyText's machinery. +modify the vector outside of BlockData's machinery. Of course we also have a non-const version, for a non-const *this. */ @@ -168,7 +168,7 @@ std::enable_if_t< if (active() == Active::string) { static const std::string context_rebuilding = - "BodyText::get>(), remade from raw string"; + "BlockData::get>(), remade from raw string"; // Completely rebuild the vector from the raw string, making use of // length, start, and valueType. @@ -261,7 +261,7 @@ std::enable_if_t< // and a call get>() was made, meaning that the caller // wants a vector. // - // BodyText is intended to store just one vector - one that represents + // BlockData is intended to store just one vector - one that represents // values in a GNDS node that has "body text." We don't, and shouldn't, // try to juggle multiple vectors of different types. Therefore, we'll // attempt to convert the existing vector to one of the requested type, @@ -274,7 +274,7 @@ std::enable_if_t< log::info( "Re-forming vector of one type into vector of another type;\n" "was this intentional?"); - log::member("BodyText::get>()"); + log::member("BlockData::get>()"); // Initialize a new vector that will soon replace the old one VECTOR newVector; @@ -325,12 +325,12 @@ std::enable_if_t< // These trigger a complete rebuild of the vector, if it isn't already of type // vector for the given T. This is intentional, in order to provide maximum // flexibility. However, be aware of it, for the sake of efficiency! In general, -// when using a BodyText object, we recommend sticking with one underlying type. +// when using a BlockData object, we recommend sticking with one underlying type. // For DATA != void (so that we have a vector): // T == DATA is required, so that returning an element of the vector will // return a reference to T. (A constructibility/convertibility requirement that -// we have in other BodyText-related code thus needs to be more stringent here. +// we have in other BlockData-related code thus needs to be more stringent here. // We can't just be able to make a T from a DATA. Those must in fact be the same // type, because we return a reference.) @@ -349,7 +349,7 @@ get(const std::size_t n) const try { return get>()[n]; } catch (...) { - log::member("BodyText::get({})", n); + log::member("BlockData::get({})", n); throw; } } @@ -450,7 +450,7 @@ std::conditional_t< return vector[n]; } } catch (...) { - log::member("BodyText::get({})", n); + log::member("BlockData::get({})", n); throw; } } @@ -479,7 +479,7 @@ std::conditional_t< // In case anyone wonders, D (not just DATA) is needed below because SFINAE // applies when template argument *deduction* is taking place. DATA is already -// fixed, by context - we're in BodyText - and thus it isn't being +// fixed, by context - we're in BlockData - and thus it isn't being // deduced here. Templating these (otherwise non-template) functions with an // argument that defaults to DATA, then using that argument in the SFINAE, is // a simple trick that makes the SFINAE work as intended. As for VOID, it's @@ -495,7 +495,7 @@ get(const std::size_t n) get(); return vector[n]; } catch (...) { - log::member("BodyText::get({})", n); + log::member("BlockData::get({})", n); throw; } } diff --git a/src/GNDStk/BodyText/src/params.hpp b/src/GNDStk/BlockData/src/params.hpp similarity index 93% rename from src/GNDStk/BodyText/src/params.hpp rename to src/GNDStk/BlockData/src/params.hpp index c545310f1..ce542b125 100644 --- a/src/GNDStk/BodyText/src/params.hpp +++ b/src/GNDStk/BlockData/src/params.hpp @@ -74,7 +74,7 @@ const std::string &valueType() const // ----------------------------------------------------------------------------- // length -BodyText &length(const std::optional &opt) +BlockData &length(const std::optional &opt) { if (opt.has_value()) vars.length = opt.value(); @@ -82,7 +82,7 @@ BodyText &length(const std::optional &opt) } // start -BodyText &start(const std::optional &opt) +BlockData &start(const std::optional &opt) { if (opt.has_value()) vars.start = opt.value(); @@ -90,7 +90,7 @@ BodyText &start(const std::optional &opt) } // valueType -BodyText &valueType(const std::optional &opt) +BlockData &valueType(const std::optional &opt) { if (opt.has_value()) vars.valueType = opt.value(); diff --git a/src/GNDStk/BodyText/src/string.hpp b/src/GNDStk/BlockData/src/string.hpp similarity index 94% rename from src/GNDStk/BodyText/src/string.hpp rename to src/GNDStk/BlockData/src/string.hpp index 6ffef6fca..7b40d34e3 100644 --- a/src/GNDStk/BodyText/src/string.hpp +++ b/src/GNDStk/BlockData/src/string.hpp @@ -16,7 +16,7 @@ const std::string &string() const // string(new string) // Builder pattern: return *this, so callers can use this function smoothly // in conjunction with the setters for length, start, and valueType. -BodyText &string(const std::string &str) +BlockData &string(const std::string &str) { clear(); // <== the vector, because it's no longer considered meaningful rawstring = str; diff --git a/src/GNDStk/BodyText/src/sync.hpp b/src/GNDStk/BlockData/src/sync.hpp similarity index 82% rename from src/GNDStk/BodyText/src/sync.hpp rename to src/GNDStk/BlockData/src/sync.hpp index 98fa02830..c582aa063 100644 --- a/src/GNDStk/BodyText/src/sync.hpp +++ b/src/GNDStk/BlockData/src/sync.hpp @@ -1,8 +1,8 @@ // pullFromDerived(derived) -// Make this BodyText's length, start, and valueType be consistent with any or +// Make this BlockData's length, start, and valueType be consistent with any or // all such parameters that exist in the given object. Remember that this class, -// BodyText, is a base of Component, which is a base of some other class. +// BlockData, is a base of Component, which is a base of some other class. template void pullFromDerived(const T &obj) { diff --git a/src/GNDStk/BodyText/src/toNode.hpp b/src/GNDStk/BlockData/src/toNode.hpp similarity index 97% rename from src/GNDStk/BodyText/src/toNode.hpp rename to src/GNDStk/BlockData/src/toNode.hpp index 3f9dde5dc..3b83e6455 100644 --- a/src/GNDStk/BodyText/src/toNode.hpp +++ b/src/GNDStk/BlockData/src/toNode.hpp @@ -1,6 +1,6 @@ // ----------------------------------------------------------------------------- -// BodyText::toNode +// BlockData::toNode // This is called by Component's conversion-to-Node (not toNode()) function. // It's "toNode()" here, not a conversion, because we're simply writing text // that Component's full conversion-to-Node will place into the Node itself. @@ -36,7 +36,7 @@ void toNode(std::string &text, DERIVED &derived) const (get(0) == "" || get(size()-1) == "") ) { log::warning( - "BodyText.toNode() called with BodyText " + "BlockData.toNode() called with BlockData " "trim flag == false, but active\n" "data are in a vector. Printing " "leading/trailing empty strings\n" diff --git a/src/GNDStk/BodyText/src/types.hpp b/src/GNDStk/BlockData/src/types.hpp similarity index 100% rename from src/GNDStk/BodyText/src/types.hpp rename to src/GNDStk/BlockData/src/types.hpp diff --git a/src/GNDStk/BodyText/src/write.hpp b/src/GNDStk/BlockData/src/write.hpp similarity index 100% rename from src/GNDStk/BodyText/src/write.hpp rename to src/GNDStk/BlockData/src/write.hpp diff --git a/src/GNDStk/BodyText/test/BodyText.test.cpp b/src/GNDStk/BlockData/test/BlockData.test.cpp similarity index 78% rename from src/GNDStk/BodyText/test/BodyText.test.cpp rename to src/GNDStk/BlockData/test/BlockData.test.cpp index 09cb28cc8..e6ef42fa1 100644 --- a/src/GNDStk/BodyText/test/BodyText.test.cpp +++ b/src/GNDStk/BlockData/test/BlockData.test.cpp @@ -11,15 +11,15 @@ using namespace njoy::GNDStk::core; // Scenario for DATA == void // ----------------------------------------------------------------------------- -SCENARIO("Testing GNDStk BodyText with DATA == void") { - // Most BodyText functionality is tested in the individual test files. +SCENARIO("Testing GNDStk BlockData with DATA == void") { + // Most BlockData functionality is tested in the individual test files. // There are just a few things we'll do here. - // Ensure that we can make const and non-const and BodyText - // objects. Note that BodyText has only a default constructor. + // Ensure that we can make const and non-const and BlockData + // objects. Note that BlockData has only a default constructor. - GIVEN("A const BodyText cbtextt") { - const BodyText cbtextt; + GIVEN("A const BlockData cbtextt") { + const BlockData cbtextt; THEN("It constructed correctly, and its data are as expected") { CHECK(cbtextt.length () == 0); CHECK(cbtextt.size () == 0); @@ -28,15 +28,15 @@ SCENARIO("Testing GNDStk BodyText with DATA == void") { } } - GIVEN("A const BodyText cbtextf") { - const BodyText cbtextf; + GIVEN("A const BlockData cbtextf") { + const BlockData cbtextf; THEN("It constructed correctly") { // no data for } } - GIVEN("A non-const BodyText nbtextt") { - BodyText nbtextt; + GIVEN("A non-const BlockData nbtextt") { + BlockData nbtextt; THEN("It constructed correctly, and its data are as expected") { CHECK(nbtextt.length () == 0); CHECK(nbtextt.size () == 0); @@ -45,21 +45,21 @@ SCENARIO("Testing GNDStk BodyText with DATA == void") { } } - GIVEN("A non-const BodyText nbtextf") { - BodyText nbtextf; + GIVEN("A non-const BlockData nbtextf") { + BlockData nbtextf; THEN("It constructed correctly") { // no data for } } // clear() and size() are defined (at the time of this writing) in the - // BodyText.hpp file itself, so we'll test them here. size() actually + // BlockData.hpp file itself, so we'll test them here. size() actually // was used in various tests, and thus was indirectly tested elsewhere. - GIVEN("A BodyText") { + GIVEN("A BlockData") { // clear WHEN("We test clear()") { - BodyText b; + BlockData b; // try int THEN("size() works correctly for vector") { @@ -88,7 +88,7 @@ SCENARIO("Testing GNDStk BodyText with DATA == void") { // size WHEN("We test size()") { - BodyText b; + BlockData b; // try int THEN("size() works correctly for vector") { @@ -128,10 +128,10 @@ SCENARIO("Testing GNDStk BodyText with DATA == void") { // Scenario for DATA != void // ----------------------------------------------------------------------------- -SCENARIO("Testing GNDStk BodyText with DATA != void") { +SCENARIO("Testing GNDStk BlockData with DATA != void") { - GIVEN("A const BodyText cbtextt") { - const BodyText cbtextt; + GIVEN("A const BlockData cbtextt") { + const BlockData cbtextt; THEN("It constructed correctly, and its data are as expected") { CHECK(cbtextt.length () == 0); CHECK(cbtextt.size () == 0); @@ -140,15 +140,15 @@ SCENARIO("Testing GNDStk BodyText with DATA != void") { } } - GIVEN("A const BodyText cbtextf") { - const BodyText cbtextf; + GIVEN("A const BlockData cbtextf") { + const BlockData cbtextf; THEN("It constructed correctly") { // no data for } } - GIVEN("A non-const BodyText nbtextt") { - BodyText nbtextt; + GIVEN("A non-const BlockData nbtextt") { + BlockData nbtextt; THEN("It constructed correctly, and its data are as expected") { CHECK(nbtextt.length () == 0); CHECK(nbtextt.size () == 0); @@ -157,17 +157,17 @@ SCENARIO("Testing GNDStk BodyText with DATA != void") { } } - GIVEN("A non-const BodyText nbtextf") { - BodyText nbtextf; + GIVEN("A non-const BlockData nbtextf") { + BlockData nbtextf; THEN("It constructed correctly") { // no data for } } - GIVEN("A BodyText") { + GIVEN("A BlockData") { // clear WHEN("We test clear()") { - BodyText b; + BlockData b; THEN("size() works correctly") { b = std::vector{1,2,3,4,5}; CHECK(b.size() == 5); @@ -178,7 +178,7 @@ SCENARIO("Testing GNDStk BodyText with DATA != void") { // size WHEN("We test size()") { - BodyText b; + BlockData b; THEN("size() works correctly") { b = std::vector{"one","two","three","four","five"}; CHECK(b.size() == 5); diff --git a/src/GNDStk/BodyText/test/CMakeLists.txt b/src/GNDStk/BlockData/test/CMakeLists.txt similarity index 72% rename from src/GNDStk/BodyText/test/CMakeLists.txt rename to src/GNDStk/BlockData/test/CMakeLists.txt index 37cdf9076..c8916af70 100644 --- a/src/GNDStk/BodyText/test/CMakeLists.txt +++ b/src/GNDStk/BlockData/test/CMakeLists.txt @@ -1,6 +1,6 @@ -add_executable( GNDStk.BodyText.test - BodyText.test.cpp +add_executable( GNDStk.BlockData.test + BlockData.test.cpp assign.test.cpp detail.test.cpp fromNode.test.cpp @@ -11,7 +11,7 @@ add_executable( GNDStk.BodyText.test toNode.test.cpp types.test.cpp write.test.cpp ) -target_compile_options( GNDStk.BodyText.test PRIVATE ${${PREFIX}_common_flags} +target_compile_options( GNDStk.BlockData.test PRIVATE ${${PREFIX}_common_flags} $<$:${${PREFIX}_strict_flags}>$<$: ${${PREFIX}_DEBUG_flags} $<$:${${PREFIX}_coverage_flags}>> @@ -21,5 +21,5 @@ $<$:${${PREFIX}_link_time_optimization_flags}> $<$:${${PREFIX}_nonportable_optimization_flags}>> ${CXX_appended_flags} ${GNDStk_appended_flags} ) -target_link_libraries( GNDStk.BodyText.test PUBLIC GNDStk ) -add_test( NAME GNDStk.BodyText COMMAND GNDStk.BodyText.test ) +target_link_libraries( GNDStk.BlockData.test PUBLIC GNDStk ) +add_test( NAME GNDStk.BlockData COMMAND GNDStk.BlockData.test ) diff --git a/src/GNDStk/BodyText/test/assign.test.cpp b/src/GNDStk/BlockData/test/assign.test.cpp similarity index 90% rename from src/GNDStk/BodyText/test/assign.test.cpp rename to src/GNDStk/BlockData/test/assign.test.cpp index 7326ae81d..b4ca50da0 100644 --- a/src/GNDStk/BodyText/test/assign.test.cpp +++ b/src/GNDStk/BlockData/test/assign.test.cpp @@ -9,13 +9,13 @@ using namespace njoy::GNDStk::core; // Scenario for DATA == void // ----------------------------------------------------------------------------- -SCENARIO("BodyText assignment operators") { - GIVEN("A default-constructed BodyText object") { +SCENARIO("BlockData assignment operators") { + GIVEN("A default-constructed BlockData object") { // Default value of raw string is as expected WHEN("We examine the raw string") { THEN("It is as expected") { - BodyText b; + BlockData b; CHECK(b.string() == ""); } } @@ -23,7 +23,7 @@ SCENARIO("BodyText assignment operators") { // Assignment from string works WHEN("We assign from a string") { THEN("The raw string has the correct value, and vector size() == 0") { - BodyText b; + BlockData b; // to ensure it clears the vector below... b = std::vector(10); @@ -40,7 +40,7 @@ SCENARIO("BodyText assignment operators") { // Assignment from vector works WHEN("We assign from a vector") { THEN("The variant has the correct value, and raw string == \"\"") { - BodyText b; + BlockData b; // to ensure it clears the raw string etc. below... b = "foo bar"; @@ -70,7 +70,7 @@ SCENARIO("BodyText assignment operators") { // Assign from vector; should set valueType WHEN("We assign from a vector") { THEN("valueType is set correctly") { - BodyText b; + BlockData b; b.string("foo").valueType("unknown"); CHECK(b.valueType() == "unknown"); @@ -83,7 +83,7 @@ SCENARIO("BodyText assignment operators") { // Assign from vector; should set valueType WHEN("We assign from a vector") { THEN("valueType is set correctly") { - BodyText b; + BlockData b; b.string("foo").valueType("unknown"); CHECK(b.valueType() == "unknown"); @@ -96,7 +96,7 @@ SCENARIO("BodyText assignment operators") { // For now, non-{int,double} sets valueType == "" WHEN("We assign from a vector") { THEN("valueType is set correctly") { - BodyText b; + BlockData b; b.string("foo").valueType("unknown"); CHECK(b.valueType() == "unknown"); @@ -114,13 +114,13 @@ SCENARIO("BodyText assignment operators") { // Scenario for DATA != void // ----------------------------------------------------------------------------- -SCENARIO("BodyText assignment operators") { - GIVEN("A default-constructed BodyText object") { +SCENARIO("BlockData assignment operators") { + GIVEN("A default-constructed BlockData object") { // Default value of raw string is as expected WHEN("We examine the raw string") { THEN("It is as expected") { - BodyText b; + BlockData b; CHECK(b.string() == ""); } } @@ -128,7 +128,7 @@ SCENARIO("BodyText assignment operators") { // Assignment from string works WHEN("We assign from a string") { THEN("The raw string has the correct value, and vector size() == 0") { - BodyText b; + BlockData b; // to ensure it clears the vector below... b = std::vector(10); @@ -145,7 +145,7 @@ SCENARIO("BodyText assignment operators") { // Assignment from vector works WHEN("We assign from a vector") { THEN("The vector has the correct value, and raw string == \"\"") { - BodyText b; + BlockData b; // to ensure it clears the raw string etc. below... b = "foo bar"; @@ -175,7 +175,7 @@ SCENARIO("BodyText assignment operators") { // Assign from vector; should set valueType WHEN("We assign from a vector") { THEN("valueType is set correctly") { - BodyText b; + BlockData b; b.string("foo").valueType("unknown"); CHECK(b.valueType() == "unknown"); @@ -188,7 +188,7 @@ SCENARIO("BodyText assignment operators") { // Assign from vector; should set valueType WHEN("We assign from a vector") { THEN("valueType is set correctly") { - BodyText b; + BlockData b; b.string("foo").valueType("unknown"); CHECK(b.valueType() == "unknown"); @@ -201,7 +201,7 @@ SCENARIO("BodyText assignment operators") { // For now, non-{int,double} sets valueType == "" WHEN("We assign from a vector") { THEN("valueType is set correctly") { - BodyText b; + BlockData b; b.string("foo").valueType("unknown"); CHECK(b.valueType() == "unknown"); diff --git a/src/GNDStk/BodyText/test/detail.test.cpp b/src/GNDStk/BlockData/test/detail.test.cpp similarity index 99% rename from src/GNDStk/BodyText/test/detail.test.cpp rename to src/GNDStk/BlockData/test/detail.test.cpp index 5083a4f2e..64b9cb577 100644 --- a/src/GNDStk/BodyText/test/detail.test.cpp +++ b/src/GNDStk/BlockData/test/detail.test.cpp @@ -9,7 +9,7 @@ inline std::string bar = "bar"; // Scenario // ----------------------------------------------------------------------------- -SCENARIO("Testing various BodyText-related detail:: constructs") { +SCENARIO("Testing various BlockData-related detail:: constructs") { // ------------------------ // scalarize diff --git a/src/GNDStk/BodyText/test/fromNode.test.cpp b/src/GNDStk/BlockData/test/fromNode.test.cpp similarity index 79% rename from src/GNDStk/BodyText/test/fromNode.test.cpp rename to src/GNDStk/BlockData/test/fromNode.test.cpp index 25e6c5059..5893cb3d5 100644 --- a/src/GNDStk/BodyText/test/fromNode.test.cpp +++ b/src/GNDStk/BlockData/test/fromNode.test.cpp @@ -9,12 +9,12 @@ using namespace njoy::GNDStk::core; // Scenario for DATA == void // ----------------------------------------------------------------------------- -SCENARIO("BodyText fromNode()") { +SCENARIO("BlockData fromNode()") { GIVEN("A Node with no \"body text\"") { - WHEN("BodyText.fromNode(the node) is called") { - THEN("The BodyText's raw string is \"\", as expected") { - BodyText b; + WHEN("BlockData.fromNode(the node) is called") { + THEN("The BlockData's raw string is \"\", as expected") { + BlockData b; b.string("This string should be replaced"); CHECK(b.string() != ""); @@ -27,9 +27,9 @@ SCENARIO("BodyText fromNode()") { } GIVEN("A Node with some \"body text\"") { - WHEN("BodyText.fromNode(the node) is called") { - THEN("The BodyText's raw string equals the text from the Node") { - BodyText b; + WHEN("BlockData.fromNode(the node) is called") { + THEN("The BlockData's raw string equals the text from the Node") { + BlockData b; b.string("This string should be replaced"); CHECK(b.string() != ""); @@ -64,12 +64,12 @@ SCENARIO("BodyText fromNode()") { // Scenario for DATA != void // ----------------------------------------------------------------------------- -SCENARIO("BodyText fromNode()") { +SCENARIO("BlockData fromNode()") { GIVEN("A Node with no \"body text\"") { - WHEN("BodyText.fromNode(the node) is called") { - THEN("The BodyText's raw string is \"\", as expected") { - BodyText b; + WHEN("BlockData.fromNode(the node) is called") { + THEN("The BlockData's raw string is \"\", as expected") { + BlockData b; b.string("This string should be replaced"); CHECK(b.string() != ""); @@ -82,9 +82,9 @@ SCENARIO("BodyText fromNode()") { } GIVEN("A Node with some \"body text\"") { - WHEN("BodyText.fromNode(the node) is called") { - THEN("The BodyText's raw string equals the text from the Node") { - BodyText b; + WHEN("BlockData.fromNode(the node) is called") { + THEN("The BlockData's raw string equals the text from the Node") { + BlockData b; b.string("This string should be replaced"); CHECK(b.string() != ""); diff --git a/src/GNDStk/BodyText/test/get.test.cpp b/src/GNDStk/BlockData/test/get.test.cpp similarity index 69% rename from src/GNDStk/BodyText/test/get.test.cpp rename to src/GNDStk/BlockData/test/get.test.cpp index 4179ce9af..cc029fd23 100644 --- a/src/GNDStk/BodyText/test/get.test.cpp +++ b/src/GNDStk/BlockData/test/get.test.cpp @@ -33,33 +33,33 @@ void scenario_get_vector() // ------------------------ // 0 elements in string - { BodyText b; b.start(0).length(0).string(""); + { BlockData b; b.start(0).length(0).string(""); CHECK((b.template get() == ivec{})); } - { BodyText b; b.start(0).length(4).string(""); + { BlockData b; b.start(0).length(4).string(""); CHECK((b.template get() == ivec{{0,0,0,0}})); } - { BodyText b; b.start(1).length(5).string(""); + { BlockData b; b.start(1).length(5).string(""); CHECK((b.template get() == ivec{{0,0,0,0,0}})); } - { BodyText b; b.start(2).length(6).string(""); + { BlockData b; b.start(2).length(6).string(""); CHECK((b.template get() == ivec{{0,0,0,0,0,0}})); } // 1 element in string - { BodyText b; b.start(0).length(0).string("-12"); + { BlockData b; b.start(0).length(0).string("-12"); CHECK((b.template get() == ivec(1,-12))); } - { BodyText b; b.start(0).length(4).string("-12"); + { BlockData b; b.start(0).length(4).string("-12"); CHECK((b.template get() == ivec{{-12,0,0,0}})); } - { BodyText b; b.start(1).length(5).string("-12"); + { BlockData b; b.start(1).length(5).string("-12"); CHECK((b.template get() == ivec{{0,-12,0,0,0}})); } - { BodyText b; b.start(2).length(6).string("-12"); + { BlockData b; b.start(2).length(6).string("-12"); CHECK((b.template get() == ivec{{0,0,-12,0,0,0}})); } // 3 elements in string - { BodyText b; b.start(0).length(0).string("-12 34 -56"); + { BlockData b; b.start(0).length(0).string("-12 34 -56"); CHECK((b.template get() == ivec{{-12,34,-56}})); } - { BodyText b; b.start(0).length(4).string("-12 34 -56"); + { BlockData b; b.start(0).length(4).string("-12 34 -56"); CHECK((b.template get() == ivec{{-12,34,-56,0}})); } - { BodyText b; b.start(1).length(5).string("-12 34 -56"); + { BlockData b; b.start(1).length(5).string("-12 34 -56"); CHECK((b.template get() == ivec{{0,-12,34,-56,0}})); } - { BodyText b; b.start(2).length(6).string("-12 34 -56"); + { BlockData b; b.start(2).length(6).string("-12 34 -56"); CHECK((b.template get() == ivec{{0,0,-12,34,-56,0}})); } // ------------------------ @@ -67,33 +67,33 @@ void scenario_get_vector() // ------------------------ // 0 elements in string - { BodyText b; b.start(0).length(0).string(""); + { BlockData b; b.start(0).length(0).string(""); CHECK((b.template get() == fvec{})); } - { BodyText b; b.start(0).length(4).string(""); + { BlockData b; b.start(0).length(4).string(""); CHECK((b.template get() == fvec{{0,0,0,0}})); } - { BodyText b; b.start(1).length(5).string(""); + { BlockData b; b.start(1).length(5).string(""); CHECK((b.template get() == fvec{{0,0,0,0,0}})); } - { BodyText b; b.start(2).length(6).string(""); + { BlockData b; b.start(2).length(6).string(""); CHECK((b.template get() == fvec{{0,0,0,0,0,0}})); } // 1 element in string - { BodyText b; b.start(0).length(0).string("1.2"); + { BlockData b; b.start(0).length(0).string("1.2"); CHECK((b.template get() == fvec(1,1.2))); } - { BodyText b; b.start(0).length(4).string("1.2"); + { BlockData b; b.start(0).length(4).string("1.2"); CHECK((b.template get() == fvec{{1.2,0,0,0}})); } - { BodyText b; b.start(1).length(5).string("1.2"); + { BlockData b; b.start(1).length(5).string("1.2"); CHECK((b.template get() == fvec{{0,1.2,0,0,0}})); } - { BodyText b; b.start(2).length(6).string("1.2"); + { BlockData b; b.start(2).length(6).string("1.2"); CHECK((b.template get() == fvec{{0,0,1.2,0,0,0}})); } // 3 elements in string - { BodyText b; b.start(0).length(0).string("1.2 3.4 5.6"); + { BlockData b; b.start(0).length(0).string("1.2 3.4 5.6"); CHECK((b.template get() == fvec{{1.2,3.4,5.6}})); } - { BodyText b; b.start(0).length(4).string("1.2 3.4 5.6"); + { BlockData b; b.start(0).length(4).string("1.2 3.4 5.6"); CHECK((b.template get() == fvec{{1.2,3.4,5.6,0}})); } - { BodyText b; b.start(1).length(5).string("1.2 3.4 5.6"); + { BlockData b; b.start(1).length(5).string("1.2 3.4 5.6"); CHECK((b.template get() == fvec{{0,1.2,3.4,5.6,0}})); } - { BodyText b; b.start(2).length(6).string("1.2 3.4 5.6"); + { BlockData b; b.start(2).length(6).string("1.2 3.4 5.6"); CHECK((b.template get() == fvec{{0,0,1.2,3.4,5.6,0}})); } // ------------------------ @@ -101,33 +101,33 @@ void scenario_get_vector() // ------------------------ // 0 elements in string - { BodyText b; b.start(0).length(0).string(""); + { BlockData b; b.start(0).length(0).string(""); CHECK((b.template get() == svec{})); } - { BodyText b; b.start(0).length(4).string(""); + { BlockData b; b.start(0).length(4).string(""); CHECK((b.template get() == svec{{"","","",""}})); } - { BodyText b; b.start(1).length(5).string(""); + { BlockData b; b.start(1).length(5).string(""); CHECK((b.template get() == svec{{"","","","",""}})); } - { BodyText b; b.start(2).length(6).string(""); + { BlockData b; b.start(2).length(6).string(""); CHECK((b.template get() == svec{{"","","","","",""}})); } // 1 element in string - { BodyText b; b.start(0).length(0).string("ab"); + { BlockData b; b.start(0).length(0).string("ab"); CHECK((b.template get() == svec(1,"ab"))); } - { BodyText b; b.start(0).length(4).string("ab"); + { BlockData b; b.start(0).length(4).string("ab"); CHECK((b.template get() == svec{{"ab","","",""}})); } - { BodyText b; b.start(1).length(5).string("ab"); + { BlockData b; b.start(1).length(5).string("ab"); CHECK((b.template get() == svec{{"","ab","","",""}})); } - { BodyText b; b.start(2).length(6).string("ab"); + { BlockData b; b.start(2).length(6).string("ab"); CHECK((b.template get() == svec{{"","","ab","","",""}})); } // 3 elements in string - { BodyText b; b.start(0).length(0).string("ab cd ef"); + { BlockData b; b.start(0).length(0).string("ab cd ef"); CHECK((b.template get() == svec{{"ab","cd","ef"}})); } - { BodyText b; b.start(0).length(4).string("ab cd ef"); + { BlockData b; b.start(0).length(4).string("ab cd ef"); CHECK((b.template get() == svec{{"ab","cd","ef",""}})); } - { BodyText b; b.start(1).length(5).string("ab cd ef"); + { BlockData b; b.start(1).length(5).string("ab cd ef"); CHECK((b.template get() == svec{{"","ab","cd","ef",""}})); } - { BodyText b; b.start(2).length(6).string("ab cd ef"); + { BlockData b; b.start(2).length(6).string("ab cd ef"); CHECK((b.template get() == svec{{"","","ab","cd","ef",""}})); } // ------------------------ @@ -135,46 +135,46 @@ void scenario_get_vector() // ------------------------ // 0 elements in string - { BodyText b; b.start(0).length(0).string(""); + { BlockData b; b.start(0).length(0).string(""); CHECK((b.template get() == uvec{})); } - { BodyText b; b.start(0).length(4).string(""); + { BlockData b; b.start(0).length(4).string(""); CHECK((b.template get() == uvec{{0,0,0,0}})); } - { BodyText b; b.start(1).length(5).string(""); + { BlockData b; b.start(1).length(5).string(""); CHECK((b.template get() == uvec{{0,0,0,0,0}})); } - { BodyText b; b.start(2).length(6).string(""); + { BlockData b; b.start(2).length(6).string(""); CHECK((b.template get() == uvec{{0,0,0,0,0,0}})); } // 1 element in string - { BodyText b; b.start(0).length(0).string("12"); + { BlockData b; b.start(0).length(0).string("12"); CHECK((b.template get() == uvec(1,12))); } - { BodyText b; b.start(0).length(4).string("12"); + { BlockData b; b.start(0).length(4).string("12"); CHECK((b.template get() == uvec{{12,0,0,0}})); } - { BodyText b; b.start(1).length(5).string("12"); + { BlockData b; b.start(1).length(5).string("12"); CHECK((b.template get() == uvec{{0,12,0,0,0}})); } - { BodyText b; b.start(2).length(6).string("12"); + { BlockData b; b.start(2).length(6).string("12"); CHECK((b.template get() == uvec{{0,0,12,0,0,0}})); } // 3 elements in string - { BodyText b; b.start(0).length(0).string("12 34 56"); + { BlockData b; b.start(0).length(0).string("12 34 56"); CHECK((b.template get() == uvec{{12,34,56}})); } - { BodyText b; b.start(0).length(4).string("12 34 56"); + { BlockData b; b.start(0).length(4).string("12 34 56"); CHECK((b.template get() == uvec{{12,34,56,0}})); } - { BodyText b; b.start(1).length(5).string("12 34 56"); + { BlockData b; b.start(1).length(5).string("12 34 56"); CHECK((b.template get() == uvec{{0,12,34,56,0}})); } - { BodyText b; b.start(2).length(6).string("12 34 56"); + { BlockData b; b.start(2).length(6).string("12 34 56"); CHECK((b.template get() == uvec{{0,0,12,34,56,0}})); } } -// For BodyText -SCENARIO("BodyText get()") { - GIVEN("A BodyText object") { +// For BlockData +SCENARIO("BlockData get()") { + GIVEN("A BlockData object") { scenario_get_vector(); } } -// For BodyText -SCENARIO("BodyText get()") { - GIVEN("A BodyText object") { +// For BlockData +SCENARIO("BlockData get()") { + GIVEN("A BlockData object") { scenario_get_vector(); } } @@ -194,32 +194,32 @@ void scenario_get_template_n() // ------------------------ // 0 elements in string - { BodyText b; b.start(0).length(0).string(""); /* no elements */ } - { BodyText b; b.start(0).length(4).string(""); + { BlockData b; b.start(0).length(0).string(""); /* no elements */ } + { BlockData b; b.start(0).length(4).string(""); CHECK(b.template get(1) == 0); } - { BodyText b; b.start(1).length(5).string(""); + { BlockData b; b.start(1).length(5).string(""); CHECK(b.template get(2) == 0); } - { BodyText b; b.start(2).length(6).string(""); + { BlockData b; b.start(2).length(6).string(""); CHECK(b.template get(3) == 0); } // 1 element in string - { BodyText b; b.start(0).length(0).string("-12"); + { BlockData b; b.start(0).length(0).string("-12"); CHECK(b.template get(0) == -12); } - { BodyText b; b.start(0).length(4).string("-12"); + { BlockData b; b.start(0).length(4).string("-12"); CHECK(b.template get(1) == 0); } - { BodyText b; b.start(1).length(5).string("-12"); + { BlockData b; b.start(1).length(5).string("-12"); CHECK(b.template get(2) == 0); } - { BodyText b; b.start(2).length(6).string("-12"); + { BlockData b; b.start(2).length(6).string("-12"); CHECK(b.template get(3) == 0); } // 3 elements in string - { BodyText b; b.start(0).length(0).string("-12 34 -56"); + { BlockData b; b.start(0).length(0).string("-12 34 -56"); CHECK(b.template get(0) == -12); } - { BodyText b; b.start(0).length(4).string("-12 34 -56"); + { BlockData b; b.start(0).length(4).string("-12 34 -56"); CHECK(b.template get(1) == 34); } - { BodyText b; b.start(1).length(5).string("-12 34 -56"); + { BlockData b; b.start(1).length(5).string("-12 34 -56"); CHECK(b.template get(2) == 34); } - { BodyText b; b.start(2).length(6).string("-12 34 -56"); + { BlockData b; b.start(2).length(6).string("-12 34 -56"); CHECK(b.template get(3) == 34); } // ------------------------ @@ -227,32 +227,32 @@ void scenario_get_template_n() // ------------------------ // 0 elements in string - { BodyText b; b.start(0).length(0).string(""); /* no elements */ } - { BodyText b; b.start(0).length(4).string(""); + { BlockData b; b.start(0).length(0).string(""); /* no elements */ } + { BlockData b; b.start(0).length(4).string(""); CHECK(b.template get(1) == 0); } - { BodyText b; b.start(1).length(5).string(""); + { BlockData b; b.start(1).length(5).string(""); CHECK(b.template get(2) == 0); } - { BodyText b; b.start(2).length(6).string(""); + { BlockData b; b.start(2).length(6).string(""); CHECK(b.template get(3) == 0); } // 1 element in string - { BodyText b; b.start(0).length(0).string("1.2"); + { BlockData b; b.start(0).length(0).string("1.2"); CHECK(b.template get(0) == 1.2); } - { BodyText b; b.start(0).length(4).string("1.2"); + { BlockData b; b.start(0).length(4).string("1.2"); CHECK(b.template get(1) == 0); } - { BodyText b; b.start(1).length(5).string("1.2"); + { BlockData b; b.start(1).length(5).string("1.2"); CHECK(b.template get(2) == 0); } - { BodyText b; b.start(2).length(6).string("1.2"); + { BlockData b; b.start(2).length(6).string("1.2"); CHECK(b.template get(3) == 0); } // 3 elements in string - { BodyText b; b.start(0).length(0).string("1.2 3.4 5.6"); + { BlockData b; b.start(0).length(0).string("1.2 3.4 5.6"); CHECK(b.template get(0) == 1.2); } - { BodyText b; b.start(0).length(4).string("1.2 3.4 5.6"); + { BlockData b; b.start(0).length(4).string("1.2 3.4 5.6"); CHECK(b.template get(1) == 3.4); } - { BodyText b; b.start(1).length(5).string("1.2 3.4 5.6"); + { BlockData b; b.start(1).length(5).string("1.2 3.4 5.6"); CHECK(b.template get(2) == 3.4); } - { BodyText b; b.start(2).length(6).string("1.2 3.4 5.6"); + { BlockData b; b.start(2).length(6).string("1.2 3.4 5.6"); CHECK(b.template get(3) == 3.4); } // ------------------------ @@ -260,32 +260,32 @@ void scenario_get_template_n() // ------------------------ // 0 elements in string - { BodyText b; b.start(0).length(0).string(""); /* no elements */ } - { BodyText b; b.start(0).length(4).string(""); + { BlockData b; b.start(0).length(0).string(""); /* no elements */ } + { BlockData b; b.start(0).length(4).string(""); CHECK(b.template get(1) == ""); } - { BodyText b; b.start(1).length(5).string(""); + { BlockData b; b.start(1).length(5).string(""); CHECK(b.template get(2) == ""); } - { BodyText b; b.start(2).length(6).string(""); + { BlockData b; b.start(2).length(6).string(""); CHECK(b.template get(3) == ""); } // 1 element in string - { BodyText b; b.start(0).length(0).string("ab"); + { BlockData b; b.start(0).length(0).string("ab"); CHECK(b.template get(0) == "ab"); } - { BodyText b; b.start(0).length(4).string("ab"); + { BlockData b; b.start(0).length(4).string("ab"); CHECK(b.template get(1) == ""); } - { BodyText b; b.start(1).length(5).string("ab"); + { BlockData b; b.start(1).length(5).string("ab"); CHECK(b.template get(2) == ""); } - { BodyText b; b.start(2).length(6).string("ab"); + { BlockData b; b.start(2).length(6).string("ab"); CHECK(b.template get(3) == ""); } // 3 elements in string - { BodyText b; b.start(0).length(0).string("ab cd ef"); + { BlockData b; b.start(0).length(0).string("ab cd ef"); CHECK(b.template get(0) == "ab"); } - { BodyText b; b.start(0).length(4).string("ab cd ef"); + { BlockData b; b.start(0).length(4).string("ab cd ef"); CHECK(b.template get(1) == "cd"); } - { BodyText b; b.start(1).length(5).string("ab cd ef"); + { BlockData b; b.start(1).length(5).string("ab cd ef"); CHECK(b.template get(2) == "cd"); } - { BodyText b; b.start(2).length(6).string("ab cd ef"); + { BlockData b; b.start(2).length(6).string("ab cd ef"); CHECK(b.template get(3) == "cd"); } // ------------------------ @@ -293,45 +293,45 @@ void scenario_get_template_n() // ------------------------ // 0 elements in string - { BodyText b; b.start(0).length(0).string(""); /* no elements */ } - { BodyText b; b.start(0).length(4).string(""); + { BlockData b; b.start(0).length(0).string(""); /* no elements */ } + { BlockData b; b.start(0).length(4).string(""); CHECK(b.template get(1) == 0); } - { BodyText b; b.start(1).length(5).string(""); + { BlockData b; b.start(1).length(5).string(""); CHECK(b.template get(2) == 0); } - { BodyText b; b.start(2).length(6).string(""); + { BlockData b; b.start(2).length(6).string(""); CHECK(b.template get(3) == 0); } // 1 element in string - { BodyText b; b.start(0).length(0).string("12"); + { BlockData b; b.start(0).length(0).string("12"); CHECK(b.template get(0) == 12); } - { BodyText b; b.start(0).length(4).string("12"); + { BlockData b; b.start(0).length(4).string("12"); CHECK(b.template get(1) == 0); } - { BodyText b; b.start(1).length(5).string("12"); + { BlockData b; b.start(1).length(5).string("12"); CHECK(b.template get(2) == 0); } - { BodyText b; b.start(2).length(6).string("12"); + { BlockData b; b.start(2).length(6).string("12"); CHECK(b.template get(3) == 0); } // 3 elements in string - { BodyText b; b.start(0).length(0).string("12 34 56"); + { BlockData b; b.start(0).length(0).string("12 34 56"); CHECK(b.template get(0) == 12); } - { BodyText b; b.start(0).length(4).string("12 34 56"); + { BlockData b; b.start(0).length(4).string("12 34 56"); CHECK(b.template get(1) == 34); } - { BodyText b; b.start(1).length(5).string("12 34 56"); + { BlockData b; b.start(1).length(5).string("12 34 56"); CHECK(b.template get(2) == 34); } - { BodyText b; b.start(2).length(6).string("12 34 56"); + { BlockData b; b.start(2).length(6).string("12 34 56"); CHECK(b.template get(3) == 34); } } -// For BodyText -SCENARIO("BodyText get(n)") { - GIVEN("A BodyText object") { +// For BlockData +SCENARIO("BlockData get(n)") { + GIVEN("A BlockData object") { scenario_get_template_n(); } } -// For BodyText -SCENARIO("BodyText get(n)") { - GIVEN("A BodyText object") { +// For BlockData +SCENARIO("BlockData get(n)") { + GIVEN("A BlockData object") { scenario_get_template_n(); } } @@ -342,15 +342,15 @@ SCENARIO("BodyText get(n)") { // 3. Scenario: get() // ----------------------------------------------------------------------------- -// For BodyText -SCENARIO("BodyText get()") { - GIVEN("A BodyText object") { +// For BlockData +SCENARIO("BlockData get()") { + GIVEN("A BlockData object") { using ivec = std::vector; using fvec = std::vector; using svec = std::vector; - BodyText b; + BlockData b; b.start(2).length(6).string("-12 34 -56"); b.valueType("Integer32"); @@ -377,28 +377,28 @@ SCENARIO("BodyText get()") { } // SCENARIO -// For BodyText -SCENARIO("BodyText get()") { - GIVEN("A BodyText object") { +// For BlockData +SCENARIO("BlockData get()") { + GIVEN("A BlockData object") { using ivec = std::vector; using fvec = std::vector; using svec = std::vector; { - BodyText b; + BlockData b; b.start(2).length(6).string("-12 34 -56"); CHECK((b.get() == ivec{{0,0,-12,34,-56,0}})); } { - BodyText b; + BlockData b; b.start(2).length(6).string("1.2 3.4 5.6"); CHECK((b.get() == fvec{{0,0,1.2,3.4,5.6,0}})); } { - BodyText b; + BlockData b; b.start(2).length(6).string("ab cd ef"); CHECK((b.get() == svec{{"","","ab","cd","ef",""}})); } @@ -412,11 +412,11 @@ SCENARIO("BodyText get()") { // 4. Scenario: get(n) // ----------------------------------------------------------------------------- -// For BodyText -SCENARIO("BodyText get(n)") { - GIVEN("A BodyText object") { +// For BlockData +SCENARIO("BlockData get(n)") { + GIVEN("A BlockData object") { - BodyText b; + BlockData b; // ------------------------ // get(n) form @@ -514,16 +514,16 @@ SCENARIO("BodyText get(n)") { } // SCENARIO -// For BodyText -SCENARIO("BodyText get(n)") { - GIVEN("A BodyText object") { +// For BlockData +SCENARIO("BlockData get(n)") { + GIVEN("A BlockData object") { // ------------------------ // get(n) form // ------------------------ { - BodyText b; + BlockData b; b.start(2).length(6).string("-12 34 -56"); CHECK(( b.get(0) == 0 )); CHECK(( b.get(1) == 0 )); @@ -534,7 +534,7 @@ SCENARIO("BodyText get(n)") { } { - BodyText b; + BlockData b; b.start(2).length(6).string("1.2 3.4 5.6"); CHECK(( b.get(0) == 0 )); CHECK(( b.get(1) == 0 )); @@ -545,7 +545,7 @@ SCENARIO("BodyText get(n)") { } { - BodyText b; + BlockData b; b.start(2).length(8).string("ab cd ef 123 4.5"); CHECK(( b.get(0) == "" )); CHECK(( b.get(1) == "" )); @@ -562,7 +562,7 @@ SCENARIO("BodyText get(n)") { // ------------------------ { - BodyText b; + BlockData b; b.start(2).length(6).string("-12 34 -56"); CHECK(( b[0] == 0 )); CHECK(( b[1] == 0 )); @@ -573,7 +573,7 @@ SCENARIO("BodyText get(n)") { } { - BodyText b; + BlockData b; b.start(2).length(6).string("1.2 3.4 5.6"); CHECK(( b[0] == 0 )); CHECK(( b[1] == 0 )); @@ -584,7 +584,7 @@ SCENARIO("BodyText get(n)") { } { - BodyText b; + BlockData b; b.start(2).length(6).string("ab cd ef"); CHECK(( b[0] == "" )); CHECK(( b[1] == "" )); @@ -608,7 +608,7 @@ template void scenario_get_named() { { - BodyText b; + BlockData b; b.start(2).length(6).string("-12 34 -56"); auto result = b.ints(); @@ -631,10 +631,10 @@ void scenario_get_named() } { - BodyText b; + BlockData b; b.start(2).length(6).string("1.2 3.4 5.6"); - const BodyText &bconst = b; // ensure it works with const + const BlockData &bconst = b; // ensure it works with const const auto result = bconst.doubles(); CHECK((std::is_same_v>)); @@ -655,7 +655,7 @@ void scenario_get_named() } { - BodyText b; + BlockData b; b.start(2).length(6).string("ab cd ef"); const auto &result = b.strings(); @@ -678,16 +678,16 @@ void scenario_get_named() } } -// For BodyText -SCENARIO("BodyText type-specific get functions: doubles() etc.") { - GIVEN("A BodyText object") { +// For BlockData +SCENARIO("BlockData type-specific get functions: doubles() etc.") { + GIVEN("A BlockData object") { scenario_get_named(); } } -// For BodyText -SCENARIO("BodyText type-specific get functions: doubles() etc.") { - GIVEN("A BodyText object") { +// For BlockData +SCENARIO("BlockData type-specific get functions: doubles() etc.") { + GIVEN("A BlockData object") { scenario_get_named(); } } diff --git a/src/GNDStk/BodyText/test/params.test.cpp b/src/GNDStk/BlockData/test/params.test.cpp similarity index 84% rename from src/GNDStk/BodyText/test/params.test.cpp rename to src/GNDStk/BlockData/test/params.test.cpp index 7e43e3e32..e7c853f1f 100644 --- a/src/GNDStk/BodyText/test/params.test.cpp +++ b/src/GNDStk/BlockData/test/params.test.cpp @@ -15,7 +15,7 @@ void scenario_params() // Default values of parameters are as expected WHEN("We examine the default length, start, and valueType") { THEN("They are as expected") { - BodyText b; + BlockData b; CHECK(b.length() == 0); CHECK(b.start() == 0); CHECK(b.valueType() == ""); @@ -25,17 +25,17 @@ void scenario_params() // length setter/getter works WHEN("We set length, then get and verify") { THEN("It works for a plain value") { - BodyText b; + BlockData b; b.length(12); CHECK(b.length() == 12); } THEN("It works for optional-with-value") { - BodyText b; + BlockData b; b.length(std::optional(34)); CHECK(b.length() == 34); } THEN("It works for optional-without-value (remains unchanged)") { - BodyText b; + BlockData b; b.length(56); b.length(std::optional(std::nullopt)); CHECK(b.length() == 56); @@ -45,17 +45,17 @@ void scenario_params() // start setter/getter works WHEN("We set start, then get and verify") { THEN("It works for a plain value") { - BodyText b; + BlockData b; b.start(11); CHECK(b.start() == 11); } THEN("It works for optional-with-value") { - BodyText b; + BlockData b; b.start(std::optional(13)); CHECK(b.start() == 13); } THEN("It works for optional-without-value (remains unchanged)") { - BodyText b; + BlockData b; b.start(17); b.start(std::optional(std::nullopt)); CHECK(b.start() == 17); @@ -65,17 +65,17 @@ void scenario_params() // valueType setter/getter works WHEN("We set valueType, then get and verify") { THEN("It works for a plain value") { - BodyText b; + BlockData b; b.valueType("unknown"); CHECK(b.valueType() == "unknown"); } THEN("It works for optional-with-value") { - BodyText b; + BlockData b; b.valueType(std::optional("Integer32")); CHECK(b.valueType() == "Integer32"); } THEN("It works for optional-without-value (remains unchanged)") { - BodyText b; + BlockData b; b.valueType("Float64"); b.valueType(std::optional(std::nullopt)); CHECK(b.valueType() == "Float64"); @@ -85,7 +85,7 @@ void scenario_params() // Combo of the above, using builder-pattern nature of the setters WHEN("We set length/start/valueType together, then get and verify") { THEN("It works for a plain value") { - BodyText b; + BlockData b; b.length(1) .start(2) .valueType("a"); @@ -94,7 +94,7 @@ void scenario_params() CHECK(b.valueType() == "a"); } THEN("It works for optional-with-value") { - BodyText b; + BlockData b; b.length(std::optional(3)) .start(std::optional(4)) .valueType(std::optional("b")); @@ -103,7 +103,7 @@ void scenario_params() CHECK(b.valueType() == "b"); } THEN("It works for optional-without-value (remains unchanged)") { - BodyText b; + BlockData b; b.length(100).start(200).valueType("c"); b.length(std::optional(std::nullopt)) .start(std::optional(std::nullopt)) @@ -120,14 +120,14 @@ void scenario_params() // Scenarios // ----------------------------------------------------------------------------- -SCENARIO("BodyText length/start/valueType") { - GIVEN("A default-constructed BodyText object") { +SCENARIO("BlockData length/start/valueType") { + GIVEN("A default-constructed BlockData object") { scenario_params(); } } -SCENARIO("BodyText length/start/valueType") { - GIVEN("A default-constructed BodyText object") { +SCENARIO("BlockData length/start/valueType") { + GIVEN("A default-constructed BlockData object") { scenario_params(); } } diff --git a/src/GNDStk/BodyText/test/string.test.cpp b/src/GNDStk/BlockData/test/string.test.cpp similarity index 83% rename from src/GNDStk/BodyText/test/string.test.cpp rename to src/GNDStk/BlockData/test/string.test.cpp index 549b38041..7fa8b830a 100644 --- a/src/GNDStk/BodyText/test/string.test.cpp +++ b/src/GNDStk/BlockData/test/string.test.cpp @@ -15,7 +15,7 @@ void scenario_string() // Default value of raw string is as expected WHEN("We examine the raw string") { THEN("It is as expected") { - BodyText b; + BlockData b; CHECK(b.string() == ""); } } @@ -23,7 +23,7 @@ void scenario_string() // Raw string setter/getter works WHEN("We set the raw string") { THEN("It has the correct value, and vector size() == 0 too") { - BodyText b; + BlockData b; // to ensure it clears below... b = std::vector(10); @@ -40,7 +40,7 @@ void scenario_string() // Test in conjunction with length, start, and valueType WHEN("We set string, length, start, and valueType together") { THEN("All values check out") { - BodyText b; + BlockData b; b.string("3 4 5 6").length(10).start(2).valueType("Integer32"); CHECK(b.length() == 10); @@ -56,14 +56,14 @@ void scenario_string() // Scenarios // ----------------------------------------------------------------------------- -SCENARIO("BodyText string()") { - GIVEN("A default-constructed BodyText object") { +SCENARIO("BlockData string()") { + GIVEN("A default-constructed BlockData object") { scenario_string(); } } -SCENARIO("BodyText string()") { - GIVEN("A default-constructed BodyText object") { +SCENARIO("BlockData string()") { + GIVEN("A default-constructed BlockData object") { scenario_string(); } } diff --git a/src/GNDStk/BodyText/test/sync.test.cpp b/src/GNDStk/BlockData/test/sync.test.cpp similarity index 88% rename from src/GNDStk/BodyText/test/sync.test.cpp rename to src/GNDStk/BlockData/test/sync.test.cpp index 24df290c7..ee3fae38c 100644 --- a/src/GNDStk/BodyText/test/sync.test.cpp +++ b/src/GNDStk/BlockData/test/sync.test.cpp @@ -21,7 +21,7 @@ void scenario_pull() struct { } content; } derived; - BodyText b; + BlockData b; b.length(100).start(200).valueType("300"); b.pullFromDerived(derived); // should do nothing here CHECK(b.length() == 100); @@ -36,7 +36,7 @@ void scenario_pull() int length = 10; } content; } derived; - BodyText b; + BlockData b; b.length(11).start(12).valueType("13"); b.pullFromDerived(derived); CHECK(b.length() == 10); @@ -51,7 +51,7 @@ void scenario_pull() int start = 14; } content; } derived; - BodyText b; + BlockData b; b.length(15).start(16).valueType("17"); b.pullFromDerived(derived); CHECK(b.length() == 15); @@ -66,7 +66,7 @@ void scenario_pull() std::string valueType = "18"; } content; } derived; - BodyText b; + BlockData b; b.length(19).start(20).valueType("21"); b.pullFromDerived(derived); CHECK(b.length() == 19); @@ -82,7 +82,7 @@ void scenario_pull() std::string valueType = "23"; } content; } derived; - BodyText b; + BlockData b; b.length(24).start(25).valueType("26"); b.pullFromDerived(derived); CHECK(b.length() == 24); @@ -98,7 +98,7 @@ void scenario_pull() std::string valueType = "28"; } content; } derived; - BodyText b; + BlockData b; b.length(29).start(30).valueType("31"); b.pullFromDerived(derived); CHECK(b.length() == 27); @@ -114,7 +114,7 @@ void scenario_pull() int start = 33; } content; } derived; - BodyText b; + BlockData b; b.length(34).start(35).valueType("36"); b.pullFromDerived(derived); CHECK(b.length() == 32); @@ -131,7 +131,7 @@ void scenario_pull() std::string valueType = "39"; } content; } derived; - BodyText b; + BlockData b; b.length(40).start(41).valueType("42"); b.pullFromDerived(derived); CHECK(b.length() == 37); @@ -142,14 +142,14 @@ void scenario_pull() } -SCENARIO("BodyText pull from content") { - GIVEN("A BodyText object") { +SCENARIO("BlockData pull from content") { + GIVEN("A BlockData object") { scenario_pull(); } } -SCENARIO("BodyText pull from content") { - GIVEN("A BodyText object") { +SCENARIO("BlockData pull from content") { + GIVEN("A BlockData object") { scenario_pull(); } } @@ -172,7 +172,7 @@ void scenario_push() int ignored = 123456; // not length, start, or valueType } content; } derived; - BodyText b; + BlockData b; b.length(0).start(0).valueType("0"); b.pushToDerived(derived); // should do nothing here CHECK(derived.content.ignored == 123456); @@ -185,7 +185,7 @@ void scenario_push() int length = 10; } content; } derived; - BodyText b; + BlockData b; b.length(11).start(12).valueType("13"); b.pushToDerived(derived); CHECK(derived.content.length == 11); @@ -198,7 +198,7 @@ void scenario_push() int start = 14; } content; } derived; - BodyText b; + BlockData b; b.length(15).start(16).valueType("17"); b.pushToDerived(derived); CHECK(derived.content.start == 16); @@ -211,7 +211,7 @@ void scenario_push() std::string valueType = "18"; } content; } derived; - BodyText b; + BlockData b; b.length(19).start(20).valueType("21"); b.pushToDerived(derived); CHECK(derived.content.valueType == "21"); @@ -225,7 +225,7 @@ void scenario_push() std::string valueType = "23"; } content; } derived; - BodyText b; + BlockData b; b.length(24).start(25).valueType("26"); b.pushToDerived(derived); CHECK(derived.content.start == 25); @@ -240,7 +240,7 @@ void scenario_push() std::string valueType = "28"; } content; } derived; - BodyText b; + BlockData b; b.length(29).start(30).valueType("31"); b.pushToDerived(derived); CHECK(derived.content.length == 29); @@ -255,7 +255,7 @@ void scenario_push() int start = 33; } content; } derived; - BodyText b; + BlockData b; b.length(34).start(35).valueType("36"); b.pushToDerived(derived); CHECK(derived.content.length == 34); @@ -271,7 +271,7 @@ void scenario_push() std::string valueType = "39"; } content; } derived; - BodyText b; + BlockData b; b.length(40).start(41).valueType("42"); b.pushToDerived(derived); CHECK(derived.content.length == 40); @@ -282,14 +282,14 @@ void scenario_push() } -SCENARIO("BodyText push to content") { - GIVEN("A BodyText object") { +SCENARIO("BlockData push to content") { + GIVEN("A BlockData object") { scenario_push(); } } -SCENARIO("BodyText push to content") { - GIVEN("A BodyText object") { +SCENARIO("BlockData push to content") { + GIVEN("A BlockData object") { scenario_push(); } } diff --git a/src/GNDStk/BodyText/test/toNode.test.cpp b/src/GNDStk/BlockData/test/toNode.test.cpp similarity index 86% rename from src/GNDStk/BodyText/test/toNode.test.cpp rename to src/GNDStk/BlockData/test/toNode.test.cpp index c54fb43ad..192945167 100644 --- a/src/GNDStk/BodyText/test/toNode.test.cpp +++ b/src/GNDStk/BlockData/test/toNode.test.cpp @@ -11,16 +11,16 @@ using namespace njoy::GNDStk::core; // Tests use either void for each template parameter, or int, double, // std::string, and char, in that order. In the former case, we're testing -// toNode() for the generic BodyText<...,void>. In the latter case, we're -// testing toNode() for non-generic BodyText. +// toNode() for the generic BlockData<...,void>. In the latter case, we're +// testing toNode() for non-generic BlockData. template void scenario_toNode() { - // Default-constructed BodyText - GIVEN("A default-constructed BodyText") { + // Default-constructed BlockData + GIVEN("A default-constructed BlockData") { WHEN("toNode() is called") { THEN("The computed text string is empty") { - const BodyText b; + const BlockData b; std::string text = "abc"; struct { @@ -40,13 +40,13 @@ void scenario_toNode() } } - // BodyText, after being given a particular raw string and parameters - GIVEN("A BodyText, with given raw string and parameters") { + // BlockData, after being given a particular raw string and parameters + GIVEN("A BlockData, with given raw string and parameters") { WHEN("toNode() is called") { THEN("The computed text string is as expected, " "and the parameters remain as given" ) { - BodyText b; + BlockData b; b.string("0 12 34 56 0 0") .start(100).length(200).valueType("hello"); @@ -58,7 +58,7 @@ void scenario_toNode() // Someone who sets the raw string directly (as opposed to using // a vector) is stating that they want *exactly* that raw string, - // including any 0s or anything else. To have BodyText's trim flag + // including any 0s or anything else. To have BlockData's trim flag // be relevant, use a vector. // w/trim == true (shouldn't matter here; applies to vector) @@ -80,13 +80,13 @@ void scenario_toNode() } } - // BodyText, after being given a particular vector - GIVEN("A BodyText, assigned from a particular vector") { + // BlockData, after being given a particular vector + GIVEN("A BlockData, assigned from a particular vector") { WHEN("toNode() is called") { THEN("The computed text string is as expected, " "and the parameters were computed properly" ) { - BodyText b; + BlockData b; // what's set here should be replaced upon assignment from vector b.string("a b c").start(10).length(20).valueType("foobar"); @@ -118,13 +118,13 @@ void scenario_toNode() } } - // BodyText, after being given a particular vector - GIVEN("A BodyText, assigned from a particular vector") { + // BlockData, after being given a particular vector + GIVEN("A BlockData, assigned from a particular vector") { WHEN("toNode() is called") { THEN("The computed text string is as expected, " "and the parameters were computed properly" ) { - BodyText b; + BlockData b; // what's set here should be replaced upon assignment from vector b.string("d e f").start(100).length(200).valueType("foobar"); @@ -156,15 +156,15 @@ void scenario_toNode() } } - // BodyText, after being given a particular vector + // BlockData, after being given a particular vector // A key point here is to ensure that ""s (string "zeros") are properly // trimmed at the beginning and end. - GIVEN("A BodyText, assigned from a particular vector") { + GIVEN("A BlockData, assigned from a particular vector") { WHEN("toNode() is called") { THEN("The computed text string is as expected, " "and the parameters were computed properly" ) { - BodyText b; + BlockData b; // what's set here should be replaced upon assignment from vector b.string("d e f").start(100).length(200).valueType("foobar"); @@ -200,14 +200,14 @@ void scenario_toNode() } } - // BodyText, after being given a particular vector + // BlockData, after being given a particular vector // For T something other than int, double, and std::string - GIVEN("A BodyText, assigned from a particular vector") { + GIVEN("A BlockData, assigned from a particular vector") { WHEN("toNode() is called") { THEN("The computed text string is as expected, " "and the parameters were computed properly" ) { - BodyText b; + BlockData b; // what's set here should be replaced upon assignment from vector b.string("x y z").start(100).length(200).valueType("foobar"); @@ -232,7 +232,7 @@ void scenario_toNode() // Test various configurations of content{} when calling toNode(). Basically, // these test whether toNode properly updates whichever of length, start, and // valueType are in .content of toNode()'s second argument. - GIVEN("A BodyText, with vector") { + GIVEN("A BlockData, with vector") { WHEN("toNode() is called") { // none of length, start, valueType @@ -242,7 +242,7 @@ void scenario_toNode() int ignored = 12345; } content; } derived; - BodyText b; std::string text; + BlockData b; std::string text; b = std::vector{{0,0,10,20,30,0,0,0}}; b.toNode(text,derived); // toNode doesn't care about what's *not* length/start/valueType... @@ -256,7 +256,7 @@ void scenario_toNode() int length = 0; } content; } derived; - BodyText b; std::string text; + BlockData b; std::string text; b = std::vector{{0,0,10,20,30,0,0,0}}; b.toNode(text,derived); CHECK(derived.content.length == 8); @@ -269,7 +269,7 @@ void scenario_toNode() int start = 0; } content; } derived; - BodyText b; std::string text; + BlockData b; std::string text; b = std::vector{{0,0,10,20,30,0,0,0}}; b.toNode(text,derived); CHECK(derived.content.start == 2); @@ -282,7 +282,7 @@ void scenario_toNode() std::string valueType = ""; } content; } derived; - BodyText b; std::string text; + BlockData b; std::string text; b = std::vector{{0,0,10,20,30,0,0,0}}; b.toNode(text,derived); CHECK(derived.content.valueType == "Integer32"); @@ -296,7 +296,7 @@ void scenario_toNode() std::string valueType = ""; } content; } derived; - BodyText b; std::string text; + BlockData b; std::string text; b = std::vector{{0,0,10,20,30,0,0,0}}; b.toNode(text,derived); CHECK(derived.content.start == 2); @@ -311,7 +311,7 @@ void scenario_toNode() std::string valueType = ""; } content; } derived; - BodyText b; std::string text; + BlockData b; std::string text; b = std::vector{{0,0,10,20,30,0,0,0}}; b.toNode(text,derived); CHECK(derived.content.length == 8); @@ -326,7 +326,7 @@ void scenario_toNode() int start = 0; } content; } derived; - BodyText b; std::string text; + BlockData b; std::string text; b = std::vector{{0,0,10,20,30,0,0,0}}; b.toNode(text,derived); CHECK(derived.content.length == 8); @@ -342,7 +342,7 @@ void scenario_toNode() std::string valueType = ""; } content; } derived; - BodyText b; std::string text; + BlockData b; std::string text; b = std::vector{{0,0,10,20,30,0,0,0}}; b.toNode(text,derived); CHECK(derived.content.length == 8); @@ -358,10 +358,10 @@ void scenario_toNode() // Scenario // ----------------------------------------------------------------------------- -SCENARIO("BodyText toNode()") { +SCENARIO("BlockData toNode()") { scenario_toNode(); } -SCENARIO("BodyText toNode()") { +SCENARIO("BlockData toNode()") { scenario_toNode(); } diff --git a/src/GNDStk/BodyText/test/types.test.cpp b/src/GNDStk/BlockData/test/types.test.cpp similarity index 95% rename from src/GNDStk/BodyText/test/types.test.cpp rename to src/GNDStk/BlockData/test/types.test.cpp index 57274301f..64cf88dab 100644 --- a/src/GNDStk/BodyText/test/types.test.cpp +++ b/src/GNDStk/BlockData/test/types.test.cpp @@ -8,19 +8,19 @@ using namespace njoy::GNDStk::core; // Scenario // ----------------------------------------------------------------------------- -SCENARIO("BodyText data types") { +SCENARIO("BlockData data types") { GIVEN("std::vector for certain specific Ts") { - WHEN("Via BodyText, we make variants of vectors and of scalars") { + WHEN("Via BlockData, we make variants of vectors and of scalars") { // vector type - using vv = BodyText::VariantOfVectors; + using vv = BlockData::VariantOfVectors; THEN("The variant-of-vector size should be correct") { CHECK(std::variant_size_v == 15); } vv vectors; // scalar type - using vs = BodyText::VariantOfScalars; + using vs = BlockData::VariantOfScalars; THEN("The variant-of-scalar size should be correct") { CHECK(std::variant_size_v == 15); } diff --git a/src/GNDStk/BodyText/test/write.test.cpp b/src/GNDStk/BlockData/test/write.test.cpp similarity index 90% rename from src/GNDStk/BodyText/test/write.test.cpp rename to src/GNDStk/BlockData/test/write.test.cpp index ac0095b27..76658b947 100644 --- a/src/GNDStk/BodyText/test/write.test.cpp +++ b/src/GNDStk/BlockData/test/write.test.cpp @@ -13,10 +13,10 @@ using namespace njoy::GNDStk::core; template void scenario_write_string_active() { - GIVEN("A BodyText with an empty raw string") { - WHEN("BodyText.write() is called") { + GIVEN("A BlockData with an empty raw string") { + WHEN("BlockData.write() is called") { THEN("Nothing is printed") { - BodyText b; + BlockData b; b = std::vector{{'a','b','c'}}; b.string(""); // should make string (not vector) active std::ostringstream oss; @@ -30,10 +30,10 @@ void scenario_write_string_active() } } - GIVEN("A BodyText with a non-empty raw string") { - WHEN("BodyText.write() is called") { + GIVEN("A BlockData with a non-empty raw string") { + WHEN("BlockData.write() is called") { THEN("The raw string and a newline are printed") { - BodyText b; + BlockData b; b = std::vector{{'a','b','c'}}; b.string("foo bar"); // should make string (not vector) active @@ -51,12 +51,12 @@ void scenario_write_string_active() } // For DATA == void -SCENARIO("BodyText write(), when the raw string is active") { +SCENARIO("BlockData write(), when the raw string is active") { scenario_write_string_active(); } // For DATA != void -SCENARIO("BodyText write(), when the raw string is active") { +SCENARIO("BlockData write(), when the raw string is active") { scenario_write_string_active(); } @@ -69,10 +69,10 @@ SCENARIO("BodyText write(), when the raw string is active") { template void scenario_write_vector_active() { - GIVEN("A BodyText with an empty vector") { - WHEN("BodyText.write() is called") { + GIVEN("A BlockData with an empty vector") { + WHEN("BlockData.write() is called") { THEN("Nothing is printed") { - BodyText b; + BlockData b; b.string("should be ignored"); // because vector is forthcoming... b = std::vector{}; std::ostringstream oss; @@ -86,10 +86,10 @@ void scenario_write_vector_active() } } - GIVEN("A BodyText with a non-empty vector") { - WHEN("BodyText.write() is called") { + GIVEN("A BlockData with a non-empty vector") { + WHEN("BlockData.write() is called") { THEN("The vector and a newline are printed") { - BodyText b; + BlockData b; b.string("should be ignored"); // because vector is forthcoming... b = std::vector{{2,3,5,7,11,13,17,19,21,23}}; std::ostringstream oss; @@ -216,11 +216,11 @@ void scenario_write_vector_active() } // For DATA == void -SCENARIO("BodyText write(), when a vector is active") { +SCENARIO("BlockData write(), when a vector is active") { scenario_write_vector_active(); } // For DATA != void -SCENARIO("BodyText write(), when a vector is active") { +SCENARIO("BlockData write(), when a vector is active") { scenario_write_vector_active(); } diff --git a/src/GNDStk/Component.hpp b/src/GNDStk/Component.hpp index a1d383c23..dda289377 100644 --- a/src/GNDStk/Component.hpp +++ b/src/GNDStk/Component.hpp @@ -13,11 +13,11 @@ using helpMap = std::map; // Component // ----------------------------------------------------------------------------- -template -class Component : public BodyText +template +class Component : public BlockData { // For convenience - using body = BodyText; + using body = BlockData; using typename body::VariantOfVectors; using typename body::VariantOfScalars; static inline constexpr bool hasFields = @@ -73,9 +73,9 @@ class Component : public BodyText static std::string namespaceName() { return ""; } // base - // Convenient access to the BodyText base class - body &baseBodyText() { return *this; } - const body &baseBodyText() const { return *this; } + // Convenient access to the BlockData base class + body &baseBlockData() { return *this; } + const body &baseBlockData() const { return *this; } // derived // Convenient access to the derived class @@ -117,10 +117,10 @@ class Component : public BodyText // ostream << Component // ----------------------------------------------------------------------------- -template +template std::ostream &operator<<( std::ostream &os, - const Component &obj + const Component &obj ) { return obj.write(os,0); } diff --git a/src/GNDStk/Component/src/detail.hpp b/src/GNDStk/Component/src/detail.hpp index d8078758c..93e84c791 100644 --- a/src/GNDStk/Component/src/detail.hpp +++ b/src/GNDStk/Component/src/detail.hpp @@ -1,6 +1,6 @@ // Forward declaration, needed by some things later -template +template class Component; namespace detail { diff --git a/src/GNDStk/Component/src/finish.hpp b/src/GNDStk/Component/src/finish.hpp index 864f5d5bf..a45fcab02 100644 --- a/src/GNDStk/Component/src/finish.hpp +++ b/src/GNDStk/Component/src/finish.hpp @@ -88,9 +88,9 @@ bool construct(const std::vector &) { return true; } void finish() { - // If hasBodyText == true (else no-op), have Component's BodyText base + // If hasBlockData == true (else no-op), have Component's BlockData base // get length, start, and valueType, as available, from the derived class - if constexpr (hasBodyText) + if constexpr (hasBlockData) body::pullFromDerived(derived()); // Based on the derived class' keys(), locate and sort derived-class fields @@ -109,7 +109,7 @@ void finish() void finish(const DERIVED &other) { // length, start, valueType - if constexpr (hasBodyText) + if constexpr (hasBlockData) body::pullFromDerived(derived()); // derived-class vector fields @@ -132,11 +132,11 @@ void finish(const DERIVED &other) void finish(const Node &node) { // Read fields from the Node into the derived object. This applies the keys() - // multi-query in the derived class, and also runs BodyText::fromNode() if + // multi-query in the derived class, and also runs BlockData::fromNode() if // the Node has body text, in order to get the Node's string of "body text". fromNode(node); - if constexpr (hasBodyText) { + if constexpr (hasBlockData) { // length, start, valueType body::pullFromDerived(derived()); // make vector diff --git a/src/GNDStk/Component/src/fromNode.hpp b/src/GNDStk/Component/src/fromNode.hpp index b4b51eff2..94ef7a88f 100644 --- a/src/GNDStk/Component/src/fromNode.hpp +++ b/src/GNDStk/Component/src/fromNode.hpp @@ -54,7 +54,7 @@ void fromNode(const Node &node) } // body text, a.k.a. XML "pcdata" (plain character data), if any - if constexpr (hasBodyText) + if constexpr (hasBlockData) body::fromNode(node); } catch (...) { diff --git a/src/GNDStk/Component/src/toNode.hpp b/src/GNDStk/Component/src/toNode.hpp index 52c291d5b..7db6577a8 100644 --- a/src/GNDStk/Component/src/toNode.hpp +++ b/src/GNDStk/Component/src/toNode.hpp @@ -6,17 +6,17 @@ // Normally we'd need just a const version of a conversion operator, and, if // we needed a non-const version at all, it could build on the const version. -// A glitch in the present circumstances is that BodyText::toNode(), which is +// A glitch in the present circumstances is that BlockData::toNode(), which is // called from within these, splits const and non-const cases, and that needs -// to be preserved here. So, then, why does BodyText::toNode() have a non-const -// version? The issue is that in the non-const case, BodyText::toNode() may +// to be preserved here. So, then, why does BlockData::toNode() have a non-const +// version? The issue is that in the non-const case, BlockData::toNode() may // need to deal with a vector (not just an original "body text" string as may -// have been read into a const BodyText). And, dealing with a vector means +// have been read into a const BlockData). And, dealing with a vector means // computing a proper length, start, and valueType while doing toNode() - and // pushing those up to the class derived from Component, as it's from that // class that those fields are written to the Node. The need to compute proper // values for those parameters is why we need the non-const case. (And we can't -// just make length etc. mutable in BodyText, as the length etc. in the derived +// just make length etc. mutable in BlockData, as the length etc. in the derived // class come into play too.) Maybe we'll work out a different way to handle // all this, but for now, we have the following. diff --git a/src/GNDStk/Component/src/toNodeBody.hpp b/src/GNDStk/Component/src/toNodeBody.hpp index e0fecf6e1..8ea104ab7 100644 --- a/src/GNDStk/Component/src/toNodeBody.hpp +++ b/src/GNDStk/Component/src/toNodeBody.hpp @@ -3,7 +3,7 @@ Node node(DERIVED::GNDSName()); // 2. Body text, if applicable -if constexpr (hasBodyText) { +if constexpr (hasBlockData) { // GNDStk uses a "text" metadatum of a "pcdata" child node for this std::string &text = node.add("pcdata").add("text","").second; // Note: the following call might compute length, start, and valueType; diff --git a/src/GNDStk/Component/src/write.hpp b/src/GNDStk/Component/src/write.hpp index 3922dd71b..f9b9bd479 100644 --- a/src/GNDStk/Component/src/write.hpp +++ b/src/GNDStk/Component/src/write.hpp @@ -102,8 +102,8 @@ std::ostream &write(std::ostream &os, const int level) const os << std::endl; } - // BodyText, if any - if constexpr (hasBodyText) + // BlockData, if any + if constexpr (hasBlockData) body::write(os,level+1); // Indent, write footer, NO newline diff --git a/src/GNDStk/Component/test/Component.test.cpp b/src/GNDStk/Component/test/Component.test.cpp index 4dd94d196..1f6a6e0aa 100644 --- a/src/GNDStk/Component/test/Component.test.cpp +++ b/src/GNDStk/Component/test/Component.test.cpp @@ -25,7 +25,7 @@ class DerivedT : public Component static auto className() { return "DerivedT"; } static auto GNDSName() { return "none"; } static auto keys() { return std::tuple<>{}; } - DerivedT() : Component(BodyText{}) { } + DerivedT() : Component(BlockData{}) { } }; @@ -42,7 +42,7 @@ class DerivedF : public Component static auto className() { return "DerivedF"; } static auto GNDSName() { return "none"; } static auto keys() { return std::tuple<>{}; } - DerivedF() : Component(BodyText{}) { } + DerivedF() : Component(BlockData{}) { } }; @@ -73,7 +73,7 @@ class DerivedData : public Component DerivedData() : Component( - BodyText{}, + BlockData{}, content.foo, content.bar ) @@ -82,7 +82,7 @@ class DerivedData : public Component DerivedData(const Node &node) : Component( - BodyText{}, + BlockData{}, content.foo, content.bar ) diff --git a/src/GNDStk/Component/test/ctor.test.cpp b/src/GNDStk/Component/test/ctor.test.cpp index 74e5ed7b0..076a2c1ae 100644 --- a/src/GNDStk/Component/test/ctor.test.cpp +++ b/src/GNDStk/Component/test/ctor.test.cpp @@ -33,7 +33,7 @@ class DerivedNothing : public Component public: - DerivedNothing() : Component(BodyText{}) + DerivedNothing() : Component(BlockData{}) { Component::finish(); } @@ -62,7 +62,7 @@ class DerivedSomething : public Component DerivedSomething() : Component( - BodyText{}, + BlockData{}, content.foo, content.bar ) diff --git a/src/GNDStk/Component/test/detail.test.cpp b/src/GNDStk/Component/test/detail.test.cpp index 4c138d5dc..0b891b3fa 100644 --- a/src/GNDStk/Component/test/detail.test.cpp +++ b/src/GNDStk/Component/test/detail.test.cpp @@ -87,7 +87,7 @@ class Derived : public Component { int foo = 56; double bar = 7.8; - Derived() : Component(BodyText{},foo,bar) { } + Derived() : Component(BlockData{},foo,bar) { } }; diff --git a/src/GNDStk/Component/test/finish.test.cpp b/src/GNDStk/Component/test/finish.test.cpp index 59d7edab3..7985c4a34 100644 --- a/src/GNDStk/Component/test/finish.test.cpp +++ b/src/GNDStk/Component/test/finish.test.cpp @@ -106,7 +106,7 @@ class DerivedValue : public Component // ctor: default DerivedValue() : Component( - BodyText{}, + BlockData{}, content.length, content.start, content.valueType, content.indices ) { @@ -129,7 +129,7 @@ class DerivedValue : public Component // ctor: node DerivedValue(const Node &node) : Component{ - BodyText{}, + BlockData{}, content.length, content.start, content.valueType, content.indices } { @@ -140,7 +140,7 @@ class DerivedValue : public Component // ctor: vector DerivedValue(const std::vector &vec) : Component{ - BodyText{}, + BlockData{}, content.length, content.start, content.valueType, content.indices } { @@ -243,7 +243,7 @@ class DerivedPlain : public Component // ctor: default DerivedPlain() : Component( - BodyText{}, + BlockData{}, content.foo, content.bar, content.labels ) { @@ -266,7 +266,7 @@ class DerivedPlain : public Component // ctor: node DerivedPlain(const Node &node) : Component{ - BodyText{}, + BlockData{}, content.foo, content.bar, content.labels } { @@ -300,7 +300,7 @@ SCENARIO("Component finish()") { // Ensure that finish() called the construct() in the derived class... CHECK(test::construct1DerivedValue == true); - // Ensure that finish() did a BodyText::pullFromDerived() + // Ensure that finish() did a BlockData::pullFromDerived() CHECK(d.length() == 11); CHECK(d.start() == 3); CHECK(d.valueType() == "foobar"); @@ -357,7 +357,7 @@ SCENARIO("Component finish()") { test::DerivedValue d(node); CHECK(test::construct3DerivedValue == true); - // Here, the following values in the underlying BodyText should + // Here, the following values in the underlying BlockData should // reflect those that were brought in through the above string. CHECK(d.length() == 10); CHECK(d.start() == 2); @@ -388,7 +388,7 @@ SCENARIO("Component finish()") { CHECK(test::construct4DerivedValue == true); // Here, the finish(vector) function was called, which in turn called - // BodyText's operator=(vector), which sets the following according + // BlockData's operator=(vector), which sets the following according // to what's actually in the vector CHECK(d.length() == 3); CHECK(d.start() == 0); // <== always the case in this context @@ -400,7 +400,7 @@ SCENARIO("Component finish()") { CHECK(Approx(d.get(1)) == 2.71828); CHECK(Approx(d.get(2)) == 1.41421); - // And, BodyText's operator=(vector) as mentioned above should also + // And, BlockData's operator=(vector) as mentioned above should also // have changed the corresponding values back up in the derived class CHECK(d.content.length == 3); CHECK(d.content.start == 0); diff --git a/src/GNDStk/Component/test/fromNode.test.cpp b/src/GNDStk/Component/test/fromNode.test.cpp index 55a9e5cae..971f174e7 100644 --- a/src/GNDStk/Component/test/fromNode.test.cpp +++ b/src/GNDStk/Component/test/fromNode.test.cpp @@ -19,7 +19,7 @@ Component does the following: - Calls Component's fromNode() function to read known fields from the Node into the derived class object. - - If the Node has "body text," syncs certain fields in the BodyText (base + - If the Node has "body text," syncs certain fields in the BlockData (base of Component) class, with fields in the derived class. Then, converts a raw body-text string into a vector of values. diff --git a/src/GNDStk/Component/test/getter.test.cpp b/src/GNDStk/Component/test/getter.test.cpp index 46e815e43..a36fe4c15 100644 --- a/src/GNDStk/Component/test/getter.test.cpp +++ b/src/GNDStk/Component/test/getter.test.cpp @@ -56,7 +56,7 @@ class TestGetter : public Component // constructor: default // ------------------------ - TestGetter() : Component{ BodyText{} } + TestGetter() : Component{ BlockData{} } { // Component::finish(); = not needed here } diff --git a/src/GNDStk/Component/test/prototype.hpp b/src/GNDStk/Component/test/prototype.hpp index 3952495f4..fcddc1e49 100644 --- a/src/GNDStk/Component/test/prototype.hpp +++ b/src/GNDStk/Component/test/prototype.hpp @@ -184,19 +184,19 @@ class Values : public Component { // length(value) auto &length(const std::optional &obj) - { BodyText::length(length() = obj); return *this; } + { BlockData::length(length() = obj); return *this; } // start(value) auto &start(const Defaulted &obj) - { BodyText::start(content.start = obj); return *this; } + { BlockData::start(content.start = obj); return *this; } auto &start(const int &obj) - { BodyText::start(content.start = obj); return *this; } + { BlockData::start(content.start = obj); return *this; } // valueType(value) auto &valueType(const Defaulted &obj) - { BodyText::valueType(content.valueType = obj); return *this; } + { BlockData::valueType(content.valueType = obj); return *this; } auto &valueType(const std::string &obj) - { BodyText::valueType(content.valueType = obj); return *this; } + { BlockData::valueType(content.valueType = obj); return *this; } // ------------------------ // Construction @@ -205,7 +205,7 @@ class Values : public Component { // default Values() : Component{ - BodyText{}, + BlockData{}, content.length, content.start, content.valueType @@ -243,7 +243,7 @@ class Values : public Component { // from node Values(const Node &node) : Component{ - BodyText{}, + BlockData{}, content.length, content.start, content.valueType @@ -259,7 +259,7 @@ class Values : public Component { const Defaulted &valueType ) : Component{ - BodyText{}, + BlockData{}, content.length, content.start, content.valueType @@ -280,7 +280,7 @@ class Values : public Component { const std::string &valueType ) : Component{ - BodyText{}, + BlockData{}, content.length, content.start, content.valueType @@ -388,7 +388,7 @@ class Link : public Component { // default Link() : Component{ - BodyText{}, + BlockData{}, content.href } { @@ -420,7 +420,7 @@ class Link : public Component { // from node Link(const Node &node) : Component{ - BodyText{}, + BlockData{}, content.href } { @@ -432,7 +432,7 @@ class Link : public Component { const std::string &href ) : Component{ - BodyText{}, + BlockData{}, content.href }, content{ @@ -628,7 +628,7 @@ class Grid : public Component { // default Grid() : Component{ - BodyText{}, + BlockData{}, content.index, content.interpolation, content.label, @@ -675,7 +675,7 @@ class Grid : public Component { // from node Grid(const Node &node) : Component{ - BodyText{}, + BlockData{}, content.index, content.interpolation, content.label, @@ -697,7 +697,7 @@ class Grid : public Component { const LINK_VALUES &link_values ) : Component{ - BodyText{}, + BlockData{}, content.index, content.interpolation, content.label, @@ -727,7 +727,7 @@ class Grid : public Component { const LINK_VALUES &link_values ) : Component{ - BodyText{}, + BlockData{}, content.index, content.interpolation, content.label, @@ -865,7 +865,7 @@ class Axis : public Component { // default Axis() : Component{ - BodyText{}, + BlockData{}, content.index, content.label, content.unit @@ -903,7 +903,7 @@ class Axis : public Component { // from node Axis(const Node &node) : Component{ - BodyText{}, + BlockData{}, content.index, content.label, content.unit @@ -919,7 +919,7 @@ class Axis : public Component { const std::optional &unit ) : Component{ - BodyText{}, + BlockData{}, content.index, content.label, content.unit @@ -1132,7 +1132,7 @@ class Axes : public Component { // default Axes() : Component{ - BodyText{}, + BlockData{}, content.href, content.axis_grid } @@ -1167,7 +1167,7 @@ class Axes : public Component { // from node Axes(const Node &node) : Component{ - BodyText{}, + BlockData{}, content.href, content.axis_grid } @@ -1181,7 +1181,7 @@ class Axes : public Component { const std::vector &axis_grid ) : Component{ - BodyText{}, + BlockData{}, content.href, content.axis_grid }, @@ -1354,7 +1354,7 @@ class XYs1d : public Component { // default XYs1d() : Component{ - BodyText{}, + BlockData{}, content.index, content.interpolation, content.label, @@ -1401,7 +1401,7 @@ class XYs1d : public Component { // from node XYs1d(const Node &node) : Component{ - BodyText{}, + BlockData{}, content.index, content.interpolation, content.label, @@ -1423,7 +1423,7 @@ class XYs1d : public Component { const proto::Values &values ) : Component{ - BodyText{}, + BlockData{}, content.index, content.interpolation, content.label, @@ -1453,7 +1453,7 @@ class XYs1d : public Component { const proto::Values &values ) : Component{ - BodyText{}, + BlockData{}, content.index, content.interpolation, content.label, @@ -1635,7 +1635,7 @@ class Regions1d : public Component { // default Regions1d() : Component{ - BodyText{}, + BlockData{}, content.label, content.outerDomainValue, content.XYs1d, @@ -1676,7 +1676,7 @@ class Regions1d : public Component { // from node Regions1d(const Node &node) : Component{ - BodyText{}, + BlockData{}, content.label, content.outerDomainValue, content.XYs1d, @@ -1694,7 +1694,7 @@ class Regions1d : public Component { const std::optional &axes ) : Component{ - BodyText{}, + BlockData{}, content.label, content.outerDomainValue, content.XYs1d, @@ -1893,7 +1893,7 @@ class CrossSection : public Component { // default CrossSection() : Component{ - BodyText{}, + BlockData{}, content.XYs1d_regions1d } { @@ -1925,7 +1925,7 @@ class CrossSection : public Component { // from node CrossSection(const Node &node) : Component{ - BodyText{}, + BlockData{}, content.XYs1d_regions1d } { @@ -1937,7 +1937,7 @@ class CrossSection : public Component { const std::vector &XYs1d_regions1d ) : Component{ - BodyText{}, + BlockData{}, content.XYs1d_regions1d }, content{ @@ -2079,7 +2079,7 @@ class Reaction : public Component { // default Reaction() : Component{ - BodyText{}, + BlockData{}, content.ENDF_MT, content.fissionGenre, content.label, @@ -2120,7 +2120,7 @@ class Reaction : public Component { // from node Reaction(const Node &node) : Component{ - BodyText{}, + BlockData{}, content.ENDF_MT, content.fissionGenre, content.label, @@ -2138,7 +2138,7 @@ class Reaction : public Component { const proto::CrossSection &crossSection ) : Component{ - BodyText{}, + BlockData{}, content.ENDF_MT, content.fissionGenre, content.label, @@ -2272,7 +2272,7 @@ class Reactions : public Component { // default Reactions() : Component{ - BodyText{}, + BlockData{}, content.reaction } { @@ -2304,7 +2304,7 @@ class Reactions : public Component { // from node Reactions(const Node &node) : Component{ - BodyText{}, + BlockData{}, content.reaction } { @@ -2316,7 +2316,7 @@ class Reactions : public Component { const std::vector &reaction ) : Component{ - BodyText{}, + BlockData{}, content.reaction }, content{ @@ -2497,7 +2497,7 @@ class ReactionSuite : public Component { // default ReactionSuite() : Component{ - BodyText{}, + BlockData{}, content.evaluation, content.format, content.interaction, @@ -2547,7 +2547,7 @@ class ReactionSuite : public Component { // from node ReactionSuite(const Node &node) : Component{ - BodyText{}, + BlockData{}, content.evaluation, content.format, content.interaction, @@ -2571,7 +2571,7 @@ class ReactionSuite : public Component { const std::optional &reactions ) : Component{ - BodyText{}, + BlockData{}, content.evaluation, content.format, content.interaction, diff --git a/src/GNDStk/precision/test/precision.test.cpp b/src/GNDStk/precision/test/precision.test.cpp index 8db41101f..180358cb8 100644 --- a/src/GNDStk/precision/test/precision.test.cpp +++ b/src/GNDStk/precision/test/precision.test.cpp @@ -149,7 +149,7 @@ SCENARIO("Precision code in the convert()s between stream and real, " // SCENARIO // ----------------------------------------------------------------------------- -SCENARIO("Precision code in BodyText::get(), " +SCENARIO("Precision code in BlockData::get(), " "for reworking a data vector to have a different data type") { // Context/action: @@ -356,7 +356,7 @@ SCENARIO("Precision code in BodyText::get(), " // SCENARIO // ----------------------------------------------------------------------------- -SCENARIO("Precision code in BodyText::get(), " +SCENARIO("Precision code in BlockData::get(), " "for converting from a raw string to a vector of data") { // Context/action: @@ -423,7 +423,7 @@ SCENARIO("Precision code in BodyText::get(), " // SCENARIO // ----------------------------------------------------------------------------- -SCENARIO("Precision code in BodyText::toNode(), " +SCENARIO("Precision code in BlockData::toNode(), " "for writing... VALUES THAT ARE TO GO HERE") { // Context/action: @@ -861,7 +861,7 @@ R"***(precision::Numbers { // SCENARIO // ------------------------ -SCENARIO("Precision code in BodyText::write(), " +SCENARIO("Precision code in BlockData::write(), " "for writing data blocks with Component::write()'s prettyprinter") { // Context/action: diff --git a/src/GNDStk/precision/test/precision.test.hpp b/src/GNDStk/precision/test/precision.test.hpp index 531e64571..8d80a117b 100644 --- a/src/GNDStk/precision/test/precision.test.hpp +++ b/src/GNDStk/precision/test/precision.test.hpp @@ -36,7 +36,7 @@ class Floats : public Component { public: using Component::construct; - using BodyText::operator=; + using BlockData::operator=; // ------------------------ // Relevant defaults @@ -89,17 +89,17 @@ class Floats : public Component { // length(value) Floats &length(const std::optional &obj) - { BodyText::length(length() = obj); return *this; } + { BlockData::length(length() = obj); return *this; } // start(value) Floats &start(const Defaulted &obj) - { BodyText::start(content.start = obj); return *this; } + { BlockData::start(content.start = obj); return *this; } Floats &start(const std::optional &obj) - { BodyText::start(content.start = obj); return *this; } + { BlockData::start(content.start = obj); return *this; } // valueType(value) Floats &valueType(const std::optional &obj) - { BodyText::valueType(valueType() = obj); return *this; } + { BlockData::valueType(valueType() = obj); return *this; } // ------------------------ // Construction @@ -108,7 +108,7 @@ class Floats : public Component { // default Floats() : Component{ - BodyText{}, + BlockData{}, content.length, content.start, content.valueType @@ -146,7 +146,7 @@ class Floats : public Component { // from node Floats(const Node &node) : Component{ - BodyText{}, + BlockData{}, content.length, content.start, content.valueType @@ -163,7 +163,7 @@ class Floats : public Component { const std::optional &valueType ) : Component{ - BodyText{}, + BlockData{}, content.length, content.start, content.valueType @@ -181,7 +181,7 @@ class Floats : public Component { template>> Floats(const std::vector &vector) : Component{ - BodyText{}, + BlockData{}, content.length, content.start, content.valueType @@ -242,7 +242,7 @@ class Doubles : public Component { public: using Component::construct; - using BodyText::operator=; + using BlockData::operator=; // ------------------------ // Relevant defaults @@ -295,17 +295,17 @@ class Doubles : public Component { // length(value) Doubles &length(const std::optional &obj) - { BodyText::length(length() = obj); return *this; } + { BlockData::length(length() = obj); return *this; } // start(value) Doubles &start(const Defaulted &obj) - { BodyText::start(content.start = obj); return *this; } + { BlockData::start(content.start = obj); return *this; } Doubles &start(const std::optional &obj) - { BodyText::start(content.start = obj); return *this; } + { BlockData::start(content.start = obj); return *this; } // valueType(value) Doubles &valueType(const std::optional &obj) - { BodyText::valueType(valueType() = obj); return *this; } + { BlockData::valueType(valueType() = obj); return *this; } // ------------------------ // Construction @@ -314,7 +314,7 @@ class Doubles : public Component { // default Doubles() : Component{ - BodyText{}, + BlockData{}, content.length, content.start, content.valueType @@ -352,7 +352,7 @@ class Doubles : public Component { // from node Doubles(const Node &node) : Component{ - BodyText{}, + BlockData{}, content.length, content.start, content.valueType @@ -369,7 +369,7 @@ class Doubles : public Component { const std::optional &valueType ) : Component{ - BodyText{}, + BlockData{}, content.length, content.start, content.valueType @@ -387,7 +387,7 @@ class Doubles : public Component { template>> Doubles(const std::vector &vector) : Component{ - BodyText{}, + BlockData{}, content.length, content.start, content.valueType @@ -448,7 +448,7 @@ class Quads : public Component { public: using Component::construct; - using BodyText::operator=; + using BlockData::operator=; // ------------------------ // Relevant defaults @@ -501,17 +501,17 @@ class Quads : public Component { // length(value) Quads &length(const std::optional &obj) - { BodyText::length(length() = obj); return *this; } + { BlockData::length(length() = obj); return *this; } // start(value) Quads &start(const Defaulted &obj) - { BodyText::start(content.start = obj); return *this; } + { BlockData::start(content.start = obj); return *this; } Quads &start(const std::optional &obj) - { BodyText::start(content.start = obj); return *this; } + { BlockData::start(content.start = obj); return *this; } // valueType(value) Quads &valueType(const std::optional &obj) - { BodyText::valueType(valueType() = obj); return *this; } + { BlockData::valueType(valueType() = obj); return *this; } // ------------------------ // Construction @@ -520,7 +520,7 @@ class Quads : public Component { // default Quads() : Component{ - BodyText{}, + BlockData{}, content.length, content.start, content.valueType @@ -558,7 +558,7 @@ class Quads : public Component { // from node Quads(const Node &node) : Component{ - BodyText{}, + BlockData{}, content.length, content.start, content.valueType @@ -575,7 +575,7 @@ class Quads : public Component { const std::optional &valueType ) : Component{ - BodyText{}, + BlockData{}, content.length, content.start, content.valueType @@ -593,7 +593,7 @@ class Quads : public Component { template>> Quads(const std::vector &vector) : Component{ - BodyText{}, + BlockData{}, content.length, content.start, content.valueType @@ -654,7 +654,7 @@ class Reals : public Component { public: using Component::construct; - using BodyText::operator=; + using BlockData::operator=; // ------------------------ // Relevant defaults @@ -707,17 +707,17 @@ class Reals : public Component { // length(value) Reals &length(const std::optional &obj) - { BodyText::length(length() = obj); return *this; } + { BlockData::length(length() = obj); return *this; } // start(value) Reals &start(const Defaulted &obj) - { BodyText::start(content.start = obj); return *this; } + { BlockData::start(content.start = obj); return *this; } Reals &start(const std::optional &obj) - { BodyText::start(content.start = obj); return *this; } + { BlockData::start(content.start = obj); return *this; } // valueType(value) Reals &valueType(const std::optional &obj) - { BodyText::valueType(valueType() = obj); return *this; } + { BlockData::valueType(valueType() = obj); return *this; } // ------------------------ // Construction @@ -726,7 +726,7 @@ class Reals : public Component { // default Reals() : Component{ - BodyText{}, + BlockData{}, content.length, content.start, content.valueType @@ -764,7 +764,7 @@ class Reals : public Component { // from node Reals(const Node &node) : Component{ - BodyText{}, + BlockData{}, content.length, content.start, content.valueType @@ -781,7 +781,7 @@ class Reals : public Component { const std::optional &valueType ) : Component{ - BodyText{}, + BlockData{}, content.length, content.start, content.valueType @@ -799,7 +799,7 @@ class Reals : public Component { template>> Reals(const std::vector &vector) : Component{ - BodyText{}, + BlockData{}, content.length, content.start, content.valueType @@ -1040,7 +1040,7 @@ class Numbers : public Component { // default Numbers() : Component{ - BodyText{}, + BlockData{}, content.adouble, content.afloat, content.aquad, @@ -1099,7 +1099,7 @@ class Numbers : public Component { // from node Numbers(const Node &node) : Component{ - BodyText{}, + BlockData{}, content.adouble, content.afloat, content.aquad, @@ -1130,7 +1130,7 @@ class Numbers : public Component { const std::optional &reals ) : Component{ - BodyText{}, + BlockData{}, content.adouble, content.afloat, content.aquad, diff --git a/src/GNDStk/utility.hpp b/src/GNDStk/utility.hpp index 9ab8aee30..de7c6a9d7 100644 --- a/src/GNDStk/utility.hpp +++ b/src/GNDStk/utility.hpp @@ -178,8 +178,8 @@ inline bool comments = true; // For printing. // When writing a Component with its generic write() function (or its stream -// output, which uses write()), AND the Component is based on a BodyText with -// hasBodyText == true, values will be printed with GNDStk::columns across. +// output, which uses write()), AND the Component is based on a BlockData with +// hasBlockData == true, values will be printed with GNDStk::columns across. // "columns" is aliased to "across" for convenience, because, at the time of // this writing, GNDStk has a Meta<> object, named "columns", which would also // be in scope if the core namespace is used. So, a user might prefer to use diff --git a/src/GNDStk/v1.9/containers/Axes.hpp b/src/GNDStk/v1.9/containers/Axes.hpp index 4bcfe64d7..77ab9159e 100644 --- a/src/GNDStk/v1.9/containers/Axes.hpp +++ b/src/GNDStk/v1.9/containers/Axes.hpp @@ -216,7 +216,7 @@ class Axes : public Component { std::vector{} ) : Component{ - BodyText{}, + BlockData{}, content.href, content.axis_grid }, @@ -231,7 +231,7 @@ class Axes : public Component { // copy Axes(const Axes &other) : Component{ - other.baseBodyText(), + other.baseBlockData(), content.href, content.axis_grid }, @@ -243,7 +243,7 @@ class Axes : public Component { // move Axes(Axes &&other) : Component{ - other.baseBodyText(), + other.baseBlockData(), content.href, content.axis_grid }, @@ -255,7 +255,7 @@ class Axes : public Component { // from node Axes(const Node &node) : Component{ - BodyText{}, + BlockData{}, content.href, content.axis_grid } diff --git a/src/GNDStk/v1.9/containers/Axis.hpp b/src/GNDStk/v1.9/containers/Axis.hpp index 1ceb75616..003b833f3 100644 --- a/src/GNDStk/v1.9/containers/Axis.hpp +++ b/src/GNDStk/v1.9/containers/Axis.hpp @@ -128,7 +128,7 @@ class Axis : public Component { std::optional{} ) : Component{ - BodyText{}, + BlockData{}, content.index, content.label, content.unit @@ -145,7 +145,7 @@ class Axis : public Component { // copy Axis(const Axis &other) : Component{ - other.baseBodyText(), + other.baseBlockData(), content.index, content.label, content.unit @@ -158,7 +158,7 @@ class Axis : public Component { // move Axis(Axis &&other) : Component{ - other.baseBodyText(), + other.baseBlockData(), content.index, content.label, content.unit @@ -171,7 +171,7 @@ class Axis : public Component { // from node Axis(const Node &node) : Component{ - BodyText{}, + BlockData{}, content.index, content.label, content.unit diff --git a/src/GNDStk/v1.9/containers/Grid.hpp b/src/GNDStk/v1.9/containers/Grid.hpp index 83322cab1..07ab1c195 100644 --- a/src/GNDStk/v1.9/containers/Grid.hpp +++ b/src/GNDStk/v1.9/containers/Grid.hpp @@ -208,7 +208,7 @@ class Grid : public Component { link_values_t{} ) : Component{ - BodyText{}, + BlockData{}, content.index, content.interpolation, content.label, @@ -231,7 +231,7 @@ class Grid : public Component { // copy Grid(const Grid &other) : Component{ - other.baseBodyText(), + other.baseBlockData(), content.index, content.interpolation, content.label, @@ -247,7 +247,7 @@ class Grid : public Component { // move Grid(Grid &&other) : Component{ - other.baseBodyText(), + other.baseBlockData(), content.index, content.interpolation, content.label, @@ -263,7 +263,7 @@ class Grid : public Component { // from node Grid(const Node &node) : Component{ - BodyText{}, + BlockData{}, content.index, content.interpolation, content.label, diff --git a/src/GNDStk/v1.9/containers/Link.hpp b/src/GNDStk/v1.9/containers/Link.hpp index c0221a03b..7f06746d8 100644 --- a/src/GNDStk/v1.9/containers/Link.hpp +++ b/src/GNDStk/v1.9/containers/Link.hpp @@ -98,7 +98,7 @@ class Link : public Component { std::string{} ) : Component{ - BodyText{}, + BlockData{}, content.href }, content{ @@ -111,7 +111,7 @@ class Link : public Component { // copy Link(const Link &other) : Component{ - other.baseBodyText(), + other.baseBlockData(), content.href }, content{other.content} @@ -122,7 +122,7 @@ class Link : public Component { // move Link(Link &&other) : Component{ - other.baseBodyText(), + other.baseBlockData(), content.href }, content{std::move(other.content)} @@ -133,7 +133,7 @@ class Link : public Component { // from node Link(const Node &node) : Component{ - BodyText{}, + BlockData{}, content.href } { diff --git a/src/GNDStk/v1.9/containers/Regions1d.hpp b/src/GNDStk/v1.9/containers/Regions1d.hpp index cf34fbfe4..f28147400 100644 --- a/src/GNDStk/v1.9/containers/Regions1d.hpp +++ b/src/GNDStk/v1.9/containers/Regions1d.hpp @@ -181,7 +181,7 @@ class Regions1d : public Component { std::optional{} ) : Component{ - BodyText{}, + BlockData{}, content.label, content.outerDomainValue, content.XYs1d, @@ -200,7 +200,7 @@ class Regions1d : public Component { // copy Regions1d(const Regions1d &other) : Component{ - other.baseBodyText(), + other.baseBlockData(), content.label, content.outerDomainValue, content.XYs1d, @@ -214,7 +214,7 @@ class Regions1d : public Component { // move Regions1d(Regions1d &&other) : Component{ - other.baseBodyText(), + other.baseBlockData(), content.label, content.outerDomainValue, content.XYs1d, @@ -228,7 +228,7 @@ class Regions1d : public Component { // from node Regions1d(const Node &node) : Component{ - BodyText{}, + BlockData{}, content.label, content.outerDomainValue, content.XYs1d, diff --git a/src/GNDStk/v1.9/containers/Values.hpp b/src/GNDStk/v1.9/containers/Values.hpp index 73166a432..e014fbdc0 100644 --- a/src/GNDStk/v1.9/containers/Values.hpp +++ b/src/GNDStk/v1.9/containers/Values.hpp @@ -53,7 +53,7 @@ class Values : public Component { public: using Component::construct; - using BodyText::operator=; + using BlockData::operator=; // ------------------------ // Relevant defaults @@ -107,19 +107,19 @@ class Values : public Component { // length(value) Values &length(const std::optional &obj) - { BodyText::length(length() = obj); return *this; } + { BlockData::length(length() = obj); return *this; } // start(value) Values &start(const Defaulted &obj) - { BodyText::start(content.start = obj); return *this; } + { BlockData::start(content.start = obj); return *this; } Values &start(const std::optional &obj) - { BodyText::start(content.start = obj); return *this; } + { BlockData::start(content.start = obj); return *this; } // valueType(value) Values &valueType(const Defaulted &obj) - { BodyText::valueType(content.valueType = obj); return *this; } + { BlockData::valueType(content.valueType = obj); return *this; } Values &valueType(const std::optional &obj) - { BodyText::valueType(content.valueType = obj); return *this; } + { BlockData::valueType(content.valueType = obj); return *this; } // ------------------------ // Constructors @@ -136,7 +136,7 @@ class Values : public Component { std::optional{} ) : Component{ - BodyText{}, + BlockData{}, content.length, content.start, content.valueType @@ -153,7 +153,7 @@ class Values : public Component { // copy Values(const Values &other) : Component{ - other.baseBodyText(), + other.baseBlockData(), content.length, content.start, content.valueType @@ -166,7 +166,7 @@ class Values : public Component { // move Values(Values &&other) : Component{ - other.baseBodyText(), + other.baseBlockData(), content.length, content.start, content.valueType @@ -179,7 +179,7 @@ class Values : public Component { // from node Values(const Node &node) : Component{ - BodyText{}, + BlockData{}, content.length, content.start, content.valueType @@ -192,7 +192,7 @@ class Values : public Component { template>> Values(const std::vector &vector) : Component{ - BodyText{}, + BlockData{}, content.length, content.start, content.valueType diff --git a/src/GNDStk/v1.9/containers/Values/src/custom.hpp b/src/GNDStk/v1.9/containers/Values/src/custom.hpp index 562142c21..f77ea0919 100644 --- a/src/GNDStk/v1.9/containers/Values/src/custom.hpp +++ b/src/GNDStk/v1.9/containers/Values/src/custom.hpp @@ -44,7 +44,7 @@ const std::optional< std::string >& valueType, const std::vector< T >& values ) : Component{ - BodyText{}, + BlockData{}, content.length, content.start, content.valueType diff --git a/src/GNDStk/v1.9/containers/XYs1d.hpp b/src/GNDStk/v1.9/containers/XYs1d.hpp index 8d37f5aaa..65be739fd 100644 --- a/src/GNDStk/v1.9/containers/XYs1d.hpp +++ b/src/GNDStk/v1.9/containers/XYs1d.hpp @@ -183,7 +183,7 @@ class XYs1d : public Component { containers::Values{} ) : Component{ - BodyText{}, + BlockData{}, content.index, content.interpolation, content.label, @@ -206,7 +206,7 @@ class XYs1d : public Component { // copy XYs1d(const XYs1d &other) : Component{ - other.baseBodyText(), + other.baseBlockData(), content.index, content.interpolation, content.label, @@ -222,7 +222,7 @@ class XYs1d : public Component { // move XYs1d(XYs1d &&other) : Component{ - other.baseBodyText(), + other.baseBlockData(), content.index, content.interpolation, content.label, @@ -238,7 +238,7 @@ class XYs1d : public Component { // from node XYs1d(const Node &node) : Component{ - BodyText{}, + BlockData{}, content.index, content.interpolation, content.label, diff --git a/src/GNDStk/v1.9/transport/CrossSection.hpp b/src/GNDStk/v1.9/transport/CrossSection.hpp index 2f62eec41..5b86a214f 100644 --- a/src/GNDStk/v1.9/transport/CrossSection.hpp +++ b/src/GNDStk/v1.9/transport/CrossSection.hpp @@ -199,7 +199,7 @@ class CrossSection : public Component { std::vector{} ) : Component{ - BodyText{}, + BlockData{}, content.XYs1d_regions1d }, content{ @@ -212,7 +212,7 @@ class CrossSection : public Component { // copy CrossSection(const CrossSection &other) : Component{ - other.baseBodyText(), + other.baseBlockData(), content.XYs1d_regions1d }, content{other.content} @@ -223,7 +223,7 @@ class CrossSection : public Component { // move CrossSection(CrossSection &&other) : Component{ - other.baseBodyText(), + other.baseBlockData(), content.XYs1d_regions1d }, content{std::move(other.content)} @@ -234,7 +234,7 @@ class CrossSection : public Component { // from node CrossSection(const Node &node) : Component{ - BodyText{}, + BlockData{}, content.XYs1d_regions1d } { diff --git a/src/GNDStk/v1.9/transport/Reaction.hpp b/src/GNDStk/v1.9/transport/Reaction.hpp index 65bba5d06..795623b0f 100644 --- a/src/GNDStk/v1.9/transport/Reaction.hpp +++ b/src/GNDStk/v1.9/transport/Reaction.hpp @@ -148,7 +148,7 @@ class Reaction : public Component { transport::CrossSection{} ) : Component{ - BodyText{}, + BlockData{}, content.ENDF_MT, content.fissionGenre, content.label, @@ -167,7 +167,7 @@ class Reaction : public Component { // copy Reaction(const Reaction &other) : Component{ - other.baseBodyText(), + other.baseBlockData(), content.ENDF_MT, content.fissionGenre, content.label, @@ -181,7 +181,7 @@ class Reaction : public Component { // move Reaction(Reaction &&other) : Component{ - other.baseBodyText(), + other.baseBlockData(), content.ENDF_MT, content.fissionGenre, content.label, @@ -195,7 +195,7 @@ class Reaction : public Component { // from node Reaction(const Node &node) : Component{ - BodyText{}, + BlockData{}, content.ENDF_MT, content.fissionGenre, content.label, diff --git a/src/GNDStk/v1.9/transport/ReactionSuite.hpp b/src/GNDStk/v1.9/transport/ReactionSuite.hpp index 47068ca83..0fc398065 100644 --- a/src/GNDStk/v1.9/transport/ReactionSuite.hpp +++ b/src/GNDStk/v1.9/transport/ReactionSuite.hpp @@ -193,7 +193,7 @@ class ReactionSuite : public Component { std::optional{} ) : Component{ - BodyText{}, + BlockData{}, content.evaluation, content.format, content.interaction, @@ -218,7 +218,7 @@ class ReactionSuite : public Component { // copy ReactionSuite(const ReactionSuite &other) : Component{ - other.baseBodyText(), + other.baseBlockData(), content.evaluation, content.format, content.interaction, @@ -235,7 +235,7 @@ class ReactionSuite : public Component { // move ReactionSuite(ReactionSuite &&other) : Component{ - other.baseBodyText(), + other.baseBlockData(), content.evaluation, content.format, content.interaction, @@ -252,7 +252,7 @@ class ReactionSuite : public Component { // from node ReactionSuite(const Node &node) : Component{ - BodyText{}, + BlockData{}, content.evaluation, content.format, content.interaction, diff --git a/src/GNDStk/v1.9/transport/Reactions.hpp b/src/GNDStk/v1.9/transport/Reactions.hpp index ef30fe85f..4c740fc4b 100644 --- a/src/GNDStk/v1.9/transport/Reactions.hpp +++ b/src/GNDStk/v1.9/transport/Reactions.hpp @@ -133,7 +133,7 @@ class Reactions : public Component { std::vector{} ) : Component{ - BodyText{}, + BlockData{}, content.reaction }, content{ @@ -146,7 +146,7 @@ class Reactions : public Component { // copy Reactions(const Reactions &other) : Component{ - other.baseBodyText(), + other.baseBlockData(), content.reaction }, content{other.content} @@ -157,7 +157,7 @@ class Reactions : public Component { // move Reactions(Reactions &&other) : Component{ - other.baseBodyText(), + other.baseBlockData(), content.reaction }, content{std::move(other.content)} @@ -168,7 +168,7 @@ class Reactions : public Component { // from node Reactions(const Node &node) : Component{ - BodyText{}, + BlockData{}, content.reaction } { From 92e0019c349cf5ca708300eb64410888ed6d6d5c Mon Sep 17 00:00:00 2001 From: Martin Staley Date: Sun, 12 Dec 2021 00:19:00 -0700 Subject: [PATCH 21/39] Remove allow-as-top-level-GNDS-node flag in Child class. This is the first of a few simplifications I've been planning to do with the code base. Having `Child<>` objects contain a flag, indicating "is a node of this name allowable as a top-level GNDS node," originally seemed like a good idea. With our later decision to autogenerate GNDS Standard Interfaces from GNDS specs, having such a capability in the Core Interface really isn't necessary. The Core Interface can be safely generic, uncluttered with the capability of checking such a thing. Users will prefer our GNDS Standard Interfaces, which, having been generated from GNDS specifications, will be designed so that GNDS hierarchies will have the correct structure. Our Code Generator is also being used to design another (non-GNDS) library, and more such uses may follow. Checking if a root node has a valid *GNDS* name clearly wouldn't be wanted for other libraries. For this reason, we'd already switched off the check by default. At this point, however, we don't think that having even the ability to check such a thing, in the Core Interface, is worth the extra clutter that it creates in the code base. --- src/GNDStk/Child.hpp | 81 ++++------------------ src/GNDStk/Child/src/operator.hpp | 62 +++-------------- src/GNDStk/Child/test/Child.test.cpp | 11 +-- src/GNDStk/Child/test/operator.test.cpp | 39 ----------- src/GNDStk/Node/src/special.hpp | 16 ++--- src/GNDStk/Node/test/assign.test.cpp | 2 +- src/GNDStk/Tree/src/reset.hpp | 10 --- src/GNDStk/basic/src/child.hpp | 11 ++- src/GNDStk/convert/src/HDF5.hpp | 2 - src/GNDStk/convert/src/JSON.hpp | 2 - src/GNDStk/convert/src/Tree.hpp | 18 ----- src/GNDStk/convert/src/XML.hpp | 2 - src/GNDStk/convert/src/detail.hpp | 23 ------- src/GNDStk/keyword/src/child.hpp | 14 ++-- src/GNDStk/keyword/test/keyword.test.cpp | 86 ++++++++++++------------ src/GNDStk/misc/src/child.hpp | 11 ++- src/GNDStk/utility.hpp | 11 --- 17 files changed, 90 insertions(+), 311 deletions(-) diff --git a/src/GNDStk/Child.hpp b/src/GNDStk/Child.hpp index 4cb0bc77c..00e201b25 100644 --- a/src/GNDStk/Child.hpp +++ b/src/GNDStk/Child.hpp @@ -72,12 +72,6 @@ class Child { const TYPE object; CONVERTER converter; // optional custom converter; needs operator() FILTER filter; // optional custom filter; needs operator() -private: - // allowable as top-level? - // We make this private, with a setter and a getter, so that the setter - // can register the name as "allowable as top-level" if we set to true. - bool canBeTopLevel; -public: // ------------------------ // constructors @@ -87,36 +81,14 @@ class Child { // name, type // name, type, converter // name, type, converter, filter - // name, type, converter, filter, top explicit Child( const std::string &n, const TYPE &t = TYPE{}, const CONVERTER &c = CONVERTER{}, - const FILTER &f = FILTER{}, - const bool canbetop = false + const FILTER &f = FILTER{} ) : name(n), object(t), converter(c), filter(f) - { - top(canbetop); - } - - // ------------------------ - // top(): allowable - // as a top-level node? - // ------------------------ - - // top() - bool top() const - { - return canBeTopLevel; - } - - // top(bool) - void top(const bool t) - { - if (t) detail::AllowedTop.insert(name); - canBeTopLevel = t; - } + { } // ------------------------ // simple functions @@ -128,7 +100,7 @@ class Child { auto basic() const { return Child( - name, filter, canBeTopLevel // converter not possible here + name, filter // converter not possible here ); } @@ -137,7 +109,7 @@ class Child { auto one() const { return Child( - name, object, converter, filter, canBeTopLevel + name, object, converter, filter ); } @@ -146,7 +118,7 @@ class Child { auto many() const { return Child( - name, object, converter, filter, canBeTopLevel + name, object, converter, filter ); } }; @@ -173,10 +145,6 @@ class Child { // name, filter std::string name; FILTER filter; // optional custom filter; needs operator() -private: - // allowable as top-level? - bool canBeTopLevel; -public: // ------------------------ // constructors @@ -184,34 +152,12 @@ class Child { // name // name, filter - // name, filter, top explicit Child( const std::string &n, - const FILTER &f = FILTER{}, - const bool t = false + const FILTER &f = FILTER{} ) : name(n), filter(f) - { - top(t); - } - - // ------------------------ - // top(): allowable - // as a top-level node? - // ------------------------ - - // top() - bool top() const - { - return canBeTopLevel; - } - - // top(bool) - void top(const bool t) - { - if (t) detail::AllowedTop.insert(name); - canBeTopLevel = t; - } + { } // ------------------------ // simple functions @@ -222,21 +168,21 @@ class Child { // we're already void; this is here for consistency with the general case. auto basic() const { - return Child(name,filter,canBeTopLevel); + return Child(name,filter); } // one() // Produce an equivalent Child, but formulated as Allow::one auto one() const { - return Child(name,filter,canBeTopLevel); + return Child(name,filter); } // many() // Produce an equivalent Child, but formulated as Allow::many auto many() const { - return Child(name,filter,canBeTopLevel); + return Child(name,filter); } }; @@ -246,10 +192,9 @@ class Child { // Macro // ----------------------------------------------------------------------------- -// For Child building. This macro doesn't handle the optional "top-level" -// flag, the converter, or the filter; we don't believe those will be needed -// very often. If you do need to provide one or both, construct a Child -// in some other way than by using this macro. +// For Child building. This macro doesn't handle the converter or the filter; +// we don't believe those will be needed very often. If you do need to provide +// one or both, construct a Child in some other way than by using this macro. #define GNDSTK_MAKE_CHILD(TYPE,name,ALLOW) \ inline const Child name(#name) diff --git a/src/GNDStk/Child/src/operator.hpp b/src/GNDStk/Child/src/operator.hpp index 0bbe2c677..b6df6bf06 100644 --- a/src/GNDStk/Child/src/operator.hpp +++ b/src/GNDStk/Child/src/operator.hpp @@ -16,42 +16,6 @@ inline auto operator-(const Child &kwd) -// ----------------------------------------------------------------------------- -// operator~: Allow as top-level -// operator!: Disallow as top-level -// -// We don't expect much use of these, but someone may occasionally find the -// first (more likely) or the second (less likely) to be helpful. The unary -// operators that we chose for these purposes seemed like the best, given a -// limited selection. One could think: (T)ilde for (T)op; Not for Not. -// ----------------------------------------------------------------------------- - -// operator~ -template -inline auto operator~(const Child &kwd) -{ - auto ret = kwd; - ret.top(true); - return ret; -} - -// operator! -// fixme This switches off the canBeTopLevel flag in an individual Child, -// but we actually use the namespace-scope set AllowedTop when we -// determine if a particular name is allowed as a top-level node. So, turning -// of a Child's previously-true top-level designator does not, at the moment, -// have any meaningful effect anywhere. We'll look at this more carefully -// sometime. For now, this just isn't a super important issue. -template -inline auto operator!(const Child &kwd) -{ - auto ret = kwd; - ret.top(false); - return ret; -} - - - // ----------------------------------------------------------------------------- // T/Child // Change type to T @@ -68,8 +32,7 @@ inline auto operator/( kwd.name, object, kwd.converter, - kwd.filter, - kwd.top() + kwd.filter ); } @@ -84,8 +47,7 @@ inline auto operator/( kwd.name, object, CONVERTER{}, // because the input Child didn't have one - kwd.filter, - kwd.top() + kwd.filter ); } @@ -174,8 +136,7 @@ inline Child< kwd.name, kwd.object, converter, // the new one; not kwd.converter! - kwd.filter, - kwd.top() + kwd.filter ); } @@ -215,8 +176,7 @@ inline auto operator--( kwd.name, kwd.object, C{}, - kwd.filter, - kwd.top() + kwd.filter ); } @@ -267,8 +227,7 @@ inline auto operator+( kwd.name, kwd.object, kwd.converter, - filter, // the new one - kwd.top() + filter // the new one ); } @@ -280,8 +239,7 @@ inline auto operator+( ) { return Child( kwd.name, - filter, // the new one - kwd.top() + filter // the new one ); } @@ -305,9 +263,7 @@ inline auto operator||( // both names, space-separated; this gets special treatment elsewhere a.name + " " + b.name, // need a filter; use the first Child's - a.filter, - // if either is top-level enabled - a.top() || b.top() + a.filter ); } @@ -329,8 +285,6 @@ inline auto operator||( // both names, space-separated; this gets special treatment elsewhere a.name + " " + b.name, // need an object, converter, and filter; use the first Child's - a.object, a.converter, a.filter, - // if either is top-level enabled - a.top() || b.top() + a.object, a.converter, a.filter ); } diff --git a/src/GNDStk/Child/test/Child.test.cpp b/src/GNDStk/Child/test/Child.test.cpp index ac43846b9..c0de1b37e 100644 --- a/src/GNDStk/Child/test/Child.test.cpp +++ b/src/GNDStk/Child/test/Child.test.cpp @@ -24,28 +24,24 @@ SCENARIO("Testing GNDStk Child") { const Child foo("foo"); CHECK(foo.name == "foo"); - CHECK(!foo.top()); } WHEN("Constructed with (name,converter)") { const Child foo("foo", 0.0, converter{}); CHECK(foo.name == "foo"); - CHECK(!foo.top()); } WHEN("Constructed with (name,converter,filter)") { const Child foo("foo", 0.0, converter{}, filter); CHECK(foo.name == "foo"); - CHECK(!foo.top()); } WHEN("Constructed with (name,converter,filter,top)") { const Child - foo("foo", 0.0, converter{}, filter, true); + foo("foo", 0.0, converter{}, filter); CHECK(foo.name == "foo"); - CHECK(foo.top()); } } @@ -55,21 +51,18 @@ SCENARIO("Testing GNDStk Child") { const Child foo("foo"); CHECK(foo.name == "foo"); - CHECK(!foo.top()); } WHEN("Constructed with (name,filter)") { const Child foo("foo", filter); CHECK(foo.name == "foo"); - CHECK(!foo.top()); } WHEN("Constructed with (name,filter,top)") { const Child - foo("foo", filter, true); + foo("foo", filter); CHECK(foo.name == "foo"); - CHECK(foo.top()); } } } diff --git a/src/GNDStk/Child/test/operator.test.cpp b/src/GNDStk/Child/test/operator.test.cpp index 1ec2af774..af7646875 100644 --- a/src/GNDStk/Child/test/operator.test.cpp +++ b/src/GNDStk/Child/test/operator.test.cpp @@ -128,45 +128,6 @@ SCENARIO("Testing GNDStk Child operators") { } } - // ------------------------ - // ~Child - // !Child - // top() - // top(bool) - // ------------------------ - - GIVEN("Some Child objects") { - const Child foo("foo"); - const Child bar("bar"); - Child one("one"); - one.top(true); - Child two("two"); - two.top(true); - - CHECK(!foo.top()); - CHECK(!bar.top()); - CHECK(one.top()); - CHECK(two.top()); - - WHEN("We apply ~Child") { - THEN("Top-level is enabled") { - CHECK((~foo).top()); - CHECK((~bar).top()); - CHECK((~one).top()); - CHECK((~two).top()); - } - } - - WHEN("We apply !Child") { - THEN("Top-level is disabled") { - CHECK(!(!foo).top()); - CHECK(!(!bar).top()); - CHECK(!(!one).top()); - CHECK(!(!two).top()); - } - } - } - // ------------------------ // type/Child // ------------------------ diff --git a/src/GNDStk/Node/src/special.hpp b/src/GNDStk/Node/src/special.hpp index b4da55a48..777727158 100644 --- a/src/GNDStk/Node/src/special.hpp +++ b/src/GNDStk/Node/src/special.hpp @@ -56,15 +56,13 @@ const std::string &documentation(bool &found = detail::default_bool) const return found = true, *s; // top-level? - // I.e., assume we're perhaps in the root tree node, a.k.a. "over the top" - // node, look for any of our allowable top-level nodes, e.g. reactionSuite, - // and, if found, perform the above lookup (in the lambda) in that node. - for (auto &top : detail::AllowedTop) { - bool found_top = false; // found this particular top-level node? - const Node &n = one(top,found_top); - if (found_top && look(n,s)) - return found = true, *s; - } + // If we're in what looks like the root node of a tree (named "" - the empty + // string), then look in all of the top-level nodes. In a properly formatted + // GNDS file, there will be just one such node, e.g. reactionSuite. + if (name == "") + for (auto &ptr : children) + if (look(*ptr,s)) + return found = true, *s; // not found // Static, for reference return. Set to "" each time, just in case someone diff --git a/src/GNDStk/Node/test/assign.test.cpp b/src/GNDStk/Node/test/assign.test.cpp index 9279b1baa..e1ced3192 100644 --- a/src/GNDStk/Node/test/assign.test.cpp +++ b/src/GNDStk/Node/test/assign.test.cpp @@ -7,7 +7,7 @@ SCENARIO("Testing GNDStk Node assignment") { GIVEN("A tree read from a GNDS file") { Tree tree("n-008_O_016.xml"); - WHEN("We assign: Node = tree.top") { + WHEN("We assign: Node = tree.top()") { Node node; // put some initial content into the node... diff --git a/src/GNDStk/Tree/src/reset.hpp b/src/GNDStk/Tree/src/reset.hpp index f8951fcbf..0d17decf8 100644 --- a/src/GNDStk/Tree/src/reset.hpp +++ b/src/GNDStk/Tree/src/reset.hpp @@ -32,16 +32,6 @@ Tree &reset( // Begin a new tree clear(); - // Warn if the given Child doesn't look valid for a top-level GNDS node - if (!kwd.top()) { - log::warning( - "Tree.reset(" + detail::keyname(kwd) + ") called, " - "but the Node as given by the\n" - "Child object is not encoded as being suitable for a top-level\n" - "GNDS node (bool Child.top() is false)" - ); - } - try { // Declaration node: "xml", etc. // This can specify an eventual intended file format diff --git a/src/GNDStk/basic/src/child.hpp b/src/GNDStk/basic/src/child.hpp index 7241c6a2c..0daa7c787 100644 --- a/src/GNDStk/basic/src/child.hpp +++ b/src/GNDStk/basic/src/child.hpp @@ -20,17 +20,16 @@ namespace child { // Allowable top-level nodes, per LLNL-TR-774621-DRAFT // ----------------------------------------------------------------------------- -// Note: the ~ (tilde) makes them allowed as top-level nodes inline const auto - PoPs = ~Child("PoPs"); + PoPs = Child("PoPs"); inline const auto - reactionSuite = ~Child("reactionSuite"); + reactionSuite = Child("reactionSuite"); inline const auto - covarianceSuite = ~Child("covarianceSuite"); + covarianceSuite = Child("covarianceSuite"); inline const auto - thermalScattering = ~Child("thermalScattering"); + thermalScattering = Child("thermalScattering"); inline const auto - fissionFragmentData = ~Child("fissionFragmentData"); + fissionFragmentData = Child("fissionFragmentData"); diff --git a/src/GNDStk/convert/src/HDF5.hpp b/src/GNDStk/convert/src/HDF5.hpp index ac2c79c2a..2dac262ab 100644 --- a/src/GNDStk/convert/src/HDF5.hpp +++ b/src/GNDStk/convert/src/HDF5.hpp @@ -103,8 +103,6 @@ inline bool convert(const Node &node, HDF5 &h) inline bool convert(const Tree &tree, HDF5 &h) { try { - if (tree.has_top()) - detail::check_top(tree.top().name, "Tree", "convert(Tree,HDF5)"); return convert(*(const Node *)&tree, h); } catch (...) { log::function("convert(Tree,HDF5)"); diff --git a/src/GNDStk/convert/src/JSON.hpp b/src/GNDStk/convert/src/JSON.hpp index cfbb93ff2..b0c94dc79 100644 --- a/src/GNDStk/convert/src/JSON.hpp +++ b/src/GNDStk/convert/src/JSON.hpp @@ -85,8 +85,6 @@ inline bool convert(const Node &node, JSON &j) inline bool convert(const Tree &tree, JSON &j) { try { - if (tree.has_top()) - detail::check_top(tree.top().name, "Tree", "convert(Tree,JSON)"); return convert(*(const Node *)&tree, j); } catch (...) { log::function("convert(Tree,JSON)"); diff --git a/src/GNDStk/convert/src/Tree.hpp b/src/GNDStk/convert/src/Tree.hpp index cc8fe7857..a2952b5fa 100644 --- a/src/GNDStk/convert/src/Tree.hpp +++ b/src/GNDStk/convert/src/Tree.hpp @@ -115,13 +115,6 @@ inline bool convert(const XML &x, Node &node, const bool decl) node.one("xml").add(xattr.name(), xattr.value()); } else { // Document node - // We'll assume that a check for this being a valid top-level - // GNDS node aligns with whether or not we're interested in any - // declaration node that might exist, as both of those concerns - // are associated with being at the top level of a GNDS tree - if (decl) - detail::check_top(name, "XML", "convert(XML,Node)"); - // Visit the node, and its children recursively if (!detail::xml2node(xnode, decl ? node.add() : node)) return false; @@ -195,17 +188,6 @@ inline bool convert(const JSON &j, Node &node, const bool decl) // convert the nodes // ------------------------ - // See comment above check_top() call in convert(XML,Node) above. - // JSON documents don't have "declaration nodes," as XML documents - // do, but here we interpret the bool decl parameter as essentially - // indicating whether we're reading a Node (decl == false) or full - // Tree (decl == true); and, the latter case suggests we're at the - // top level, and should thus validate it as a top-level GNDS node. - if (decl) { - const std::string name = j.doc.begin().key(); - detail::check_top(name, "JSON", "convert(JSON,Node)"); - } - // visit the node, and its children recursively if (!detail::json2node(j.doc.begin(), decl ? node.add() : node)) return false; diff --git a/src/GNDStk/convert/src/XML.hpp b/src/GNDStk/convert/src/XML.hpp index 82b9300c4..7f482e1f6 100644 --- a/src/GNDStk/convert/src/XML.hpp +++ b/src/GNDStk/convert/src/XML.hpp @@ -117,8 +117,6 @@ inline bool convert(const Node &node, XML &x) inline bool convert(const Tree &tree, XML &x) { try { - if (tree.has_top()) - detail::check_top(tree.top().name, "Tree", "convert(Tree,XML)"); return convert(*(const Node *)&tree, x); } catch (...) { log::function("convert(Tree,XML)"); diff --git a/src/GNDStk/convert/src/detail.hpp b/src/GNDStk/convert/src/detail.hpp index 55dafd93e..1d673ada7 100644 --- a/src/GNDStk/convert/src/detail.hpp +++ b/src/GNDStk/convert/src/detail.hpp @@ -768,27 +768,4 @@ bool node2xml(const NODE &node, pugi::xml_node &x) return true; } - - -// ----------------------------------------------------------------------------- -// check_top -// ----------------------------------------------------------------------------- - -inline void check_top( - const std::string &name, - const std::string &classname, - const std::string &context -) { - if (GNDStk::top && AllowedTop.find(name) == AllowedTop.end()) { - std::string message = - "Name \"{}\" in {} object's top-level node is not recognized\n" - "in our list of allowable names for top-level GNDS nodes:\n"; - for (const std::string &n : AllowedTop) - message += " \"" + n + "\"\n"; - message += "Creating node \"{}\" anyway..."; - log::warning(message, name, classname, name); - log::function(context); - } -} - } // namespace detail diff --git a/src/GNDStk/keyword/src/child.hpp b/src/GNDStk/keyword/src/child.hpp index 5b37e5b68..d65c5f025 100644 --- a/src/GNDStk/keyword/src/child.hpp +++ b/src/GNDStk/keyword/src/child.hpp @@ -3,7 +3,7 @@ // keyword_t.child() // ----------------------------------------------------------------------------- -// child(name,converter,filter,top) +// child(name[,type[,converter[,filter]]]) // To make a Child template< class TYPE, @@ -20,14 +20,13 @@ static Child< const std::string &name, const TYPE &object = TYPE{}, const CONVERTER &converter = CONVERTER{}, - const FILTER &filter = FILTER{}, - const bool top = false + const FILTER &filter = FILTER{} ) { - return Child(name,object,converter,filter,top); + return Child(name,object,converter,filter); } -// child(name,filter,top) +// child(name[,filter]) // To make a Child template< class TYPE = void, @@ -41,8 +40,7 @@ static Child< FILTER > child( const std::string &name, - const FILTER &filter = FILTER{}, - const bool top = false + const FILTER &filter = FILTER{} ) { - return Child(name,filter,top); + return Child(name,filter); } diff --git a/src/GNDStk/keyword/test/keyword.test.cpp b/src/GNDStk/keyword/test/keyword.test.cpp index 72ec2fb06..15ffca82d 100644 --- a/src/GNDStk/keyword/test/keyword.test.cpp +++ b/src/GNDStk/keyword/test/keyword.test.cpp @@ -347,36 +347,36 @@ SCENARIO("Testing GNDStk keyword") { // The commented-out cases are ambiguous: // TYPE for , or FILTER for ? { - { auto c = keyword.child ("c" ); } - // { auto c = keyword.child ("c", 0 ); } - { auto c = keyword.child ("c", 0, detail::convert_t{} ); } - { auto c = keyword.child ("c", 0, detail::convert_t{}, detail::noFilter{} ); } - { auto c = keyword.child ("c", 0, detail::convert_t{}, detail::noFilter{}, false); } - { auto c = keyword.child< > ("c" ); } - // { auto c = keyword.child< > ("c", 0 ); } - { auto c = keyword.child< > ("c", 0, detail::convert_t{} ); } - { auto c = keyword.child< > ("c", 0, detail::convert_t{}, detail::noFilter{} ); } - { auto c = keyword.child< > ("c", 0, detail::convert_t{}, detail::noFilter{}, false); } - { auto c = keyword.child ("c" ); } - { auto c = keyword.child ("c", 0 ); } - { auto c = keyword.child ("c", 0, detail::convert_t{} ); } - { auto c = keyword.child ("c", 0, detail::convert_t{}, detail::noFilter{} ); } - { auto c = keyword.child ("c", 0, detail::convert_t{}, detail::noFilter{}, false); } - { auto c = keyword.child ("c" ); } - { auto c = keyword.child ("c", 0 ); } - { auto c = keyword.child ("c", 0, detail::convert_t{} ); } - { auto c = keyword.child ("c", 0, detail::convert_t{}, detail::noFilter{} ); } - { auto c = keyword.child ("c", 0, detail::convert_t{}, detail::noFilter{}, false); } - { auto c = keyword.child ("c" ); } - { auto c = keyword.child ("c", 0 ); } - { auto c = keyword.child ("c", 0, detail::convert_t{} ); } - { auto c = keyword.child ("c", 0, detail::convert_t{}, detail::noFilter{} ); } - { auto c = keyword.child ("c", 0, detail::convert_t{}, detail::noFilter{}, false); } - { auto c = keyword.child ("c" ); } - { auto c = keyword.child ("c", 0 ); } - { auto c = keyword.child ("c", 0, detail::convert_t{} ); } - { auto c = keyword.child ("c", 0, detail::convert_t{}, detail::noFilter{} ); } - { auto c = keyword.child ("c", 0, detail::convert_t{}, detail::noFilter{}, false); } + { auto c = keyword.child ("c" ); } + // { auto c = keyword.child ("c", 0 ); } + { auto c = keyword.child ("c", 0, detail::convert_t{} ); } + { auto c = keyword.child ("c", 0, detail::convert_t{}, detail::noFilter{}); } + { auto c = keyword.child ("c", 0, detail::convert_t{}, detail::noFilter{}); } + { auto c = keyword.child< > ("c" ); } + // { auto c = keyword.child< > ("c", 0 ); } + { auto c = keyword.child< > ("c", 0, detail::convert_t{} ); } + { auto c = keyword.child< > ("c", 0, detail::convert_t{}, detail::noFilter{}); } + { auto c = keyword.child< > ("c", 0, detail::convert_t{}, detail::noFilter{}); } + { auto c = keyword.child ("c" ); } + { auto c = keyword.child ("c", 0 ); } + { auto c = keyword.child ("c", 0, detail::convert_t{} ); } + { auto c = keyword.child ("c", 0, detail::convert_t{}, detail::noFilter{}); } + { auto c = keyword.child ("c", 0, detail::convert_t{}, detail::noFilter{}); } + { auto c = keyword.child ("c" ); } + { auto c = keyword.child ("c", 0 ); } + { auto c = keyword.child ("c", 0, detail::convert_t{} ); } + { auto c = keyword.child ("c", 0, detail::convert_t{}, detail::noFilter{}); } + { auto c = keyword.child ("c", 0, detail::convert_t{}, detail::noFilter{}); } + { auto c = keyword.child ("c" ); } + { auto c = keyword.child ("c", 0 ); } + { auto c = keyword.child ("c", 0, detail::convert_t{} ); } + { auto c = keyword.child ("c", 0, detail::convert_t{}, detail::noFilter{}); } + { auto c = keyword.child ("c", 0, detail::convert_t{}, detail::noFilter{}); } + { auto c = keyword.child ("c" ); } + { auto c = keyword.child ("c", 0 ); } + { auto c = keyword.child ("c", 0, detail::convert_t{} ); } + { auto c = keyword.child ("c", 0, detail::convert_t{}, detail::noFilter{}); } + { auto c = keyword.child ("c", 0, detail::convert_t{}, detail::noFilter{}); } } // ------------------------ @@ -385,20 +385,20 @@ SCENARIO("Testing GNDStk keyword") { // The commented-out cases are ambiguous, as above. { - { auto c = keyword.child ("c" ); } - // { auto c = keyword.child ("c", detail::noFilter{} ); } + { auto c = keyword.child ("c" ); } + // { auto c = keyword.child ("c", detail::noFilter{}); } { auto c = keyword.child ("c", detail::noFilter{}, false); } - { auto c = keyword.child< > ("c" ); } - // { auto c = keyword.child< > ("c", detail::noFilter{} ); } + { auto c = keyword.child< > ("c" ); } + // { auto c = keyword.child< > ("c", detail::noFilter{}); } { auto c = keyword.child< > ("c", detail::noFilter{}, false); } - { auto c = keyword.child ("c" ); } - { auto c = keyword.child ("c", detail::noFilter{} ); } - { auto c = keyword.child ("c", detail::noFilter{}, false); } - { auto c = keyword.child ("c" ); } - { auto c = keyword.child ("c", detail::noFilter{} ); } - { auto c = keyword.child ("c", detail::noFilter{}, false); } - { auto c = keyword.child ("c" ); } - { auto c = keyword.child ("c", detail::noFilter{} ); } - { auto c = keyword.child ("c", detail::noFilter{}, false); } + { auto c = keyword.child ("c" ); } + { auto c = keyword.child ("c", detail::noFilter{}); } + { auto c = keyword.child ("c", detail::noFilter{}); } + { auto c = keyword.child ("c" ); } + { auto c = keyword.child ("c", detail::noFilter{}); } + { auto c = keyword.child ("c", detail::noFilter{}); } + { auto c = keyword.child ("c" ); } + { auto c = keyword.child ("c", detail::noFilter{}); } + { auto c = keyword.child ("c", detail::noFilter{}); } } } diff --git a/src/GNDStk/misc/src/child.hpp b/src/GNDStk/misc/src/child.hpp index 60b31ea1c..54fb786f4 100644 --- a/src/GNDStk/misc/src/child.hpp +++ b/src/GNDStk/misc/src/child.hpp @@ -5,17 +5,16 @@ namespace child { // Allowable top-level nodes, per LLNL-TR-774621-DRAFT // ----------------------------------------------------------------------------- -// Note: the ~ (tilde) makes them allowed as top-level nodes inline const auto - PoPs = ~Child("PoPs"); + PoPs = Child("PoPs"); inline const auto - reactionSuite = ~Child("reactionSuite"); + reactionSuite = Child("reactionSuite"); inline const auto - covarianceSuite = ~Child("covarianceSuite"); + covarianceSuite = Child("covarianceSuite"); inline const auto - thermalScattering = ~Child("thermalScattering"); + thermalScattering = Child("thermalScattering"); inline const auto - fissionFragmentData = ~Child("fissionFragmentData"); + fissionFragmentData = Child("fissionFragmentData"); diff --git a/src/GNDStk/utility.hpp b/src/GNDStk/utility.hpp index de7c6a9d7..2a8f363fe 100644 --- a/src/GNDStk/utility.hpp +++ b/src/GNDStk/utility.hpp @@ -16,11 +16,6 @@ inline std::string indentTo(const int level) // Should Node's debugging output print addresses and parent-node addresses? inline bool parents = false; -// top -// When reading, check whether the document node is in our list of allowable -// GNDS top-level nodes -inline bool top = false; - // file type / format enum class FileType { // default, automagick, etc. @@ -66,12 +61,6 @@ inline std::set AllowedDecl = { "hdf5", }; -// allowable top-level GNDS nodes -inline std::set AllowedTop = { - // added as they're identified - // in our Child class -}; - // noFilter class noFilter { public: From 3b7706405330e92a14a45055b31ace23664574d3 Mon Sep 17 00:00:00 2001 From: Martin Staley Date: Sun, 12 Dec 2021 22:42:44 -0700 Subject: [PATCH 22/39] Removed an old, deprecated "keyword builder" capability. The removed material was for a very old capability that was intended to help users make Meta<> and Child<> objects. I hadn't given it much in the way of capabilities yet, but then it was all superseded by the ability to easily manipulate `Meta<>` and `Child<>` objects, e.g. with constructs such as `int{}/Meta<>(...)` to change the type associated with the `Meta<>` object. The old keyword builder stuff never got much use, didn't have much to offer, and simply isn't needed any longer -- better capabilities exist, and in fact have existed for a long time. I just hadn't gotten around to removing the old code. Removing it means a bit less code, one less executable to build in the test suite, and nothing really lost. --- cmake/unit_testing.cmake | 1 - src/GNDStk.hpp | 1 - src/GNDStk/Child.hpp | 2 +- src/GNDStk/Node/test/add.test.cpp | 22 +- src/GNDStk/Node/test/call.test.cpp | 8 +- src/GNDStk/Node/test/child.test.cpp | 12 +- src/GNDStk/Node/test/meta.test.cpp | 10 +- src/GNDStk/keyword.hpp | 17 - src/GNDStk/keyword/src/child.hpp | 46 -- src/GNDStk/keyword/src/meta.hpp | 35 -- src/GNDStk/keyword/test/CMakeLists.txt | 18 - src/GNDStk/keyword/test/keyword.test.cpp | 404 ------------------ .../test/resources/n-069_Tm_170-covar.xml | 25 -- 13 files changed, 27 insertions(+), 574 deletions(-) delete mode 100644 src/GNDStk/keyword.hpp delete mode 100644 src/GNDStk/keyword/src/child.hpp delete mode 100644 src/GNDStk/keyword/src/meta.hpp delete mode 100644 src/GNDStk/keyword/test/CMakeLists.txt delete mode 100644 src/GNDStk/keyword/test/keyword.test.cpp delete mode 100644 src/GNDStk/keyword/test/resources/n-069_Tm_170-covar.xml diff --git a/cmake/unit_testing.cmake b/cmake/unit_testing.cmake index 8406f6b40..edbfe29b9 100644 --- a/cmake/unit_testing.cmake +++ b/cmake/unit_testing.cmake @@ -22,7 +22,6 @@ add_subdirectory( src/GNDStk/XML/test ) add_subdirectory( src/GNDStk/JSON/test ) add_subdirectory( src/GNDStk/HDF5/test ) add_subdirectory( src/GNDStk/Node/test ) -add_subdirectory( src/GNDStk/keyword/test ) add_subdirectory( src/GNDStk/Child/test ) add_subdirectory( src/GNDStk/convert/test ) add_subdirectory( src/GNDStk/utility/test ) diff --git a/src/GNDStk.hpp b/src/GNDStk.hpp index 24012ac91..db6afdad6 100644 --- a/src/GNDStk.hpp +++ b/src/GNDStk.hpp @@ -75,7 +75,6 @@ namespace GNDStk { #include "GNDStk/convert_t.hpp" #include "GNDStk/Meta.hpp" #include "GNDStk/Child.hpp" -#include "GNDStk/keyword.hpp" #include "GNDStk/or.hpp" // optional, with default diff --git a/src/GNDStk/Child.hpp b/src/GNDStk/Child.hpp index 00e201b25..ce1a3bee3 100644 --- a/src/GNDStk/Child.hpp +++ b/src/GNDStk/Child.hpp @@ -35,7 +35,7 @@ ALLOW tree(...,axes,axis) gives back a container of axis objects, not a single axis object, because - our Child axis keyword has ALLOW == Allow::any. Note that axes, not to be + our Child axis object has ALLOW == Allow::any. Note that axes, not to be confused with axis, has ALLOW == Allow::one because it's expected just once. CONVERTER diff --git a/src/GNDStk/Node/test/add.test.cpp b/src/GNDStk/Node/test/add.test.cpp index 7a4b926b4..d5b8ad701 100644 --- a/src/GNDStk/Node/test/add.test.cpp +++ b/src/GNDStk/Node/test/add.test.cpp @@ -70,10 +70,10 @@ SCENARIO("Testing GNDStk Node add()") { n.add("4",dimensions2d(12,34)); // metadata, Meta key - auto v = keyword.meta("AStringViaVoid"); - auto str = keyword.meta("AString"); - auto dbl = keyword.meta("ADouble"); - auto dim = keyword.meta("Dimensions"); + auto v = Meta("AStringViaVoid"); + auto str = Meta("AString"); + auto dbl = Meta("ADouble"); + auto dim = Meta("Dimensions"); n.add(v); n.add(v,"fred"); n.add(str); @@ -85,8 +85,8 @@ SCENARIO("Testing GNDStk Node add()") { // these need the = TYPE on class T in the metadata Node.add() functions: n.add(dim,{321,987}); CHECK(n.metadata.back().second == "321,987"); - auto optdim = keyword.meta>("OptDim"); - auto defdim = Defaulted({1,2})/keyword.meta<>("DefDim"); + auto optdim = Meta>("OptDim"); + auto defdim = Defaulted({1,2})/Meta<>("DefDim"); n.add(optdim,{321,987}); CHECK(n.metadata.back().second == "321,987"); n.add(defdim,{321,987}); @@ -105,13 +105,13 @@ SCENARIO("Testing GNDStk Node add()") { // ------------------------ // ------------------------ - auto foo = keyword.child("foo"); - auto numbers = keyword.child< + auto foo = Child("foo"); + auto numbers = Child< std::vector, Allow::one - >("pcdata",std::vector{},detail::convert_pcdata_text_t{}); + >("pcdata",std::vector{})/detail::convert_pcdata_text_t{}; - auto nrepeat = keyword.child("repeated node"); + auto nrepeat = Child("repeated node"); Node node1; node1.name = "aa11"; Node node2; node2.name = "bb22"; Node node3; node3.name = "cc33"; @@ -128,7 +128,7 @@ SCENARIO("Testing GNDStk Node add()") { // dim2d doesn't happen to have a default constructor, so we'll need // to give it a value in the following Child. For just the .add()s, // the value isn't used. - auto drepeat = keyword.child("dimension",dim2d{0,0}); + auto drepeat = Child("dimension",dim2d{0,0}); const dim2d a(1,2), b(3,4), c(5,6), d(7,8), e(9,10); n.add(drepeat,{a,b,c,d}); n.add(drepeat,e); diff --git a/src/GNDStk/Node/test/call.test.cpp b/src/GNDStk/Node/test/call.test.cpp index 9e3349b33..60e5fabfa 100644 --- a/src/GNDStk/Node/test/call.test.cpp +++ b/src/GNDStk/Node/test/call.test.cpp @@ -265,12 +265,12 @@ SCENARIO("Testing GNDStk Node operator()") { Tree tree("n-008_O_016.xml"); // Child objects with Allow::one - auto temperature = keyword.child("temperature"); - auto styles = keyword.child("styles"); + auto temperature = Child("temperature"); + auto styles = Child("styles"); // Child objects with Allow::many - auto isotope = keyword.child("isotope"); - auto isotope_node = keyword.child("isotope"); + auto isotope = Child("isotope"); + auto isotope_node = Child("isotope"); GIVEN("The top-level node from a tree object") { diff --git a/src/GNDStk/Node/test/child.test.cpp b/src/GNDStk/Node/test/child.test.cpp index 93943d4be..db29582a7 100644 --- a/src/GNDStk/Node/test/child.test.cpp +++ b/src/GNDStk/Node/test/child.test.cpp @@ -75,19 +75,19 @@ inline void convert(const Node &n, isotope_t &iso) // Child objects with Allow::one auto temperature = - keyword.child("temperature"); + Child("temperature"); auto styles = - keyword.child("styles"); + Child("styles"); auto documentations = - keyword.child,Allow::one>("documentations"); + Child,Allow::one>("documentations"); // Child objects with Allow::many auto isotope = - keyword.child("isotope"); + Child("isotope"); auto isotope_node = - keyword.child("isotope"); + Child("isotope"); auto nuclide_foo_or_bar_node = - keyword.child,Allow::many>("nuclide"); + Child,Allow::many>("nuclide"); // ----------------------------------------------------------------------------- diff --git a/src/GNDStk/Node/test/meta.test.cpp b/src/GNDStk/Node/test/meta.test.cpp index 45a17835b..cdc0aa72e 100644 --- a/src/GNDStk/Node/test/meta.test.cpp +++ b/src/GNDStk/Node/test/meta.test.cpp @@ -28,14 +28,14 @@ SCENARIO("Testing GNDStk Node meta()") { CHECK(consttop.meta("format") == "1.99"); } - auto format = keyword.meta("format"); + auto format = Meta("format"); CHECK(top.has_meta(format)); double f = top.meta(format); CHECK(f == 1.99); WHEN("Node.meta(\"key\",found) is called for a key that isn't there") { // try something that doesn't work - auto foobar = keyword.meta("foobar"); + auto foobar = Meta("foobar"); CHECK(!top.has_meta(foobar)); // doesn't have bool found = true; f = top.meta(foobar,found); // foobar isn't there @@ -47,8 +47,8 @@ SCENARIO("Testing GNDStk Node meta()") { WHEN("Node.meta(Meta) is called") { // string and void Meta ==> string - auto sstring = keyword.meta("evaluation"); - auto vstring = keyword.meta("evaluation"); + auto sstring = Meta("evaluation"); + auto vstring = Meta("evaluation"); std::string sstr = top.meta(sstring); std::string vstr = top.meta(vstring); CHECK(sstr == "ENDF/B-8.0"); @@ -56,7 +56,7 @@ SCENARIO("Testing GNDStk Node meta()") { // meta case should trigger a reference return... (void)&top.meta(vstring); - auto var = keyword.meta>("format"); + auto var = Meta>("format"); auto s = top.meta(var); auto d = top.meta(var); CHECK(s == "1.99"); diff --git a/src/GNDStk/keyword.hpp b/src/GNDStk/keyword.hpp deleted file mode 100644 index b6f929996..000000000 --- a/src/GNDStk/keyword.hpp +++ /dev/null @@ -1,17 +0,0 @@ - -// ----------------------------------------------------------------------------- -// This file defines constructs that are intended to help us, and users, -// create Meta and Child objects. -// ----------------------------------------------------------------------------- - -// keyword_t -class keyword_t { -public: - #include "GNDStk/keyword/src/meta.hpp" - #include "GNDStk/keyword/src/child.hpp" -}; - -// keyword -// An object of the keyword_t type. -// Useful for creating Meta and Child objects. -inline const keyword_t keyword; diff --git a/src/GNDStk/keyword/src/child.hpp b/src/GNDStk/keyword/src/child.hpp deleted file mode 100644 index d65c5f025..000000000 --- a/src/GNDStk/keyword/src/child.hpp +++ /dev/null @@ -1,46 +0,0 @@ - -// ----------------------------------------------------------------------------- -// keyword_t.child() -// ----------------------------------------------------------------------------- - -// child(name[,type[,converter[,filter]]]) -// To make a Child -template< - class TYPE, - Allow ALLOW = Allow::one, - class CONVERTER = typename detail::default_converter::type, - class FILTER = detail::noFilter -> -static Child< - typename detail::isNotVoid::type, // ensure TYPE != void - ALLOW, - CONVERTER, - FILTER -> child( - const std::string &name, - const TYPE &object = TYPE{}, - const CONVERTER &converter = CONVERTER{}, - const FILTER &filter = FILTER{} -) { - return Child(name,object,converter,filter); -} - - -// child(name[,filter]) -// To make a Child -template< - class TYPE = void, - Allow ALLOW = Allow::one, - class FILTER = detail::noFilter -> -static Child< - typename detail::is_void::type, // ensure TYPE == void - ALLOW, - void, - FILTER -> child( - const std::string &name, - const FILTER &filter = FILTER{} -) { - return Child(name,filter); -} diff --git a/src/GNDStk/keyword/src/meta.hpp b/src/GNDStk/keyword/src/meta.hpp deleted file mode 100644 index d0ebaa934..000000000 --- a/src/GNDStk/keyword/src/meta.hpp +++ /dev/null @@ -1,35 +0,0 @@ - -// ----------------------------------------------------------------------------- -// keyword_t.meta() -// ----------------------------------------------------------------------------- - -// meta(name,converter) -// To make a Meta -template< - class TYPE, - class CONVERTER = typename detail::default_converter::type -> -static Meta< - typename detail::isNotVoid::type, // ensure TYPE != void - CONVERTER -> meta( - const std::string &name, - const TYPE &object = TYPE{}, - const CONVERTER &converter = CONVERTER{} -) { - return Meta{name,object,converter}; -} - - -// meta(name) -// To make a Meta -template< - class TYPE = void -> -static Meta< - typename detail::is_void::type // ensure TYPE == void -> meta( - const std::string &name -) { - return Meta(name); -} diff --git a/src/GNDStk/keyword/test/CMakeLists.txt b/src/GNDStk/keyword/test/CMakeLists.txt deleted file mode 100644 index a39ef1a71..000000000 --- a/src/GNDStk/keyword/test/CMakeLists.txt +++ /dev/null @@ -1,18 +0,0 @@ - -add_executable( GNDStk.keyword.test keyword.test.cpp ) -target_compile_options( GNDStk.keyword.test PRIVATE ${${PREFIX}_common_flags} -$<$:${${PREFIX}_strict_flags}>$<$: -${${PREFIX}_DEBUG_flags} -$<$:${${PREFIX}_coverage_flags}>> -$<$: -${${PREFIX}_RELEASE_flags} -$<$:${${PREFIX}_link_time_optimization_flags}> -$<$:${${PREFIX}_nonportable_optimization_flags}>> - -${CXX_appended_flags} ${GNDStk_appended_flags} ) -target_link_libraries( GNDStk.keyword.test PUBLIC GNDStk ) -file( GLOB resources "resources/*" ) -foreach( resource ${resources}) - file( COPY "${resource}" DESTINATION "${CMAKE_CURRENT_BINARY_DIR}" ) -endforeach() -add_test( NAME GNDStk.keyword COMMAND GNDStk.keyword.test ) \ No newline at end of file diff --git a/src/GNDStk/keyword/test/keyword.test.cpp b/src/GNDStk/keyword/test/keyword.test.cpp deleted file mode 100644 index 15ffca82d..000000000 --- a/src/GNDStk/keyword/test/keyword.test.cpp +++ /dev/null @@ -1,404 +0,0 @@ - -#define CATCH_CONFIG_MAIN - -#include "catch.hpp" -#include "GNDStk.hpp" - -using namespace njoy::GNDStk; -using std::string; - - - -// ----------------------------------------------------------------------------- -// Custom types -// ----------------------------------------------------------------------------- - -// ------------------------ -// version_t -// ------------------------ - -// class -struct version_t { - int major = -1; - int minor = -1; - int patch = -1; -}; - -// operator>> -std::istream &operator>>(std::istream &s, version_t &obj) -{ - char ch; // '.' - return s >> obj.major >> ch >> obj.minor >> ch >> obj.patch; -} - -// ------------------------ -// date_t -// ------------------------ - -// class -struct date_t { - int year = -1; - int month = -1; - int day = -1; -}; - -// operator>> -std::istream &operator>>(std::istream &s, date_t &obj) -{ - char ch; // '-' - return s >> obj.year >> ch >> obj.month >> ch >> obj.day; -} - -// ------------------------ -// shape_t -// ------------------------ - -// class -struct shape_t { - // or maybe it should cols, rows; not important for this example - int rows = -1; - int cols = -1; -}; - -// operator>> -std::istream &operator>>(std::istream &s, shape_t &obj) -{ - char ch; // ',' - return s >> obj.rows >> ch >> obj.cols; -} - -// ------------------------ -// values_t -// ------------------------ - -// class -using values_t = std::vector; - -// ------------------------ -// manifest_t -// ------------------------ - -// class -struct manifest_t { - string information; -}; - -// convert -template -void convert(const NODE &node, manifest_t &man) -{ - std::ostringstream oss; - - // name - oss << "node: \"" << node.name << '"' << std::endl; - - // metadata - oss << " metadata:" << std::endl; - for (auto &m : node.metadata) - oss << " \"" << m.first << '"' << std::endl; - - // children - oss << " children:" << std::endl; - for (auto &c : node.children) - oss << " \"" << c->name << '"' << std::endl; - - man.information = oss.str(); -} - - - -// ----------------------------------------------------------------------------- -// Some literal strings representing correct values -// ----------------------------------------------------------------------------- - -static const std::string manifest_tree = -R"***(node: "" - metadata: - children: - "xml" - "covarianceSuite" -)***"; - -static const std::string manifest_covarianceSuite = -R"***(node: "covarianceSuite" - metadata: - "projectile" - "target" - "evaluation" - "format" - children: - "styles" - "externalFiles" - "parameterCovariances" -)***"; - -static const std::string manifest_parameterCovariances = -R"***(node: "parameterCovariance" - metadata: - "label" - children: - "rowData" - "parameterCovarianceMatrix" -)***"; - - - -// ----------------------------------------------------------------------------- -// Scenario -// ----------------------------------------------------------------------------- - -SCENARIO("Testing GNDStk keyword") { - - using namespace misc; - - // tree - const njoy::GNDStk::Tree tree("n-069_Tm_170-covar.xml"); - - // ------------------------ - // exercise some built-ins - // ------------------------ - - WHEN("We access a tree using some built-in Child and Meta objects") { - CHECK(tree(xml).metadata.size() == 2); - CHECK(tree(xml).children.size() == 0); - CHECK(tree(xml,version) == "1.0"); - CHECK(tree(xml,encoding) == "UTF-8"); - CHECK(tree(covarianceSuite).metadata.size() == 4); - CHECK(tree(covarianceSuite).children.size() == 3); - CHECK(tree(covarianceSuite,projectile) == "n"); - CHECK(tree(covarianceSuite,target) == "Tm170"); - CHECK(tree(covarianceSuite,evaluation) == "ENDF/B-8.0"); - CHECK(tree(covarianceSuite,format) == 1.9); - CHECK(tree(covarianceSuite,styles).metadata.size() == 0); - CHECK(tree(covarianceSuite,styles).children.size() == 1); - CHECK(tree(covarianceSuite,styles,--evaluated).metadata.size() == 4); - CHECK(tree(covarianceSuite,styles,--evaluated).children.size() == 2); - CHECK(tree(covarianceSuite,styles,--evaluated,misc::meta::label) == "eval"); - } // WHEN - - - // ------------------------ - // make our own - // ------------------------ - - // for metadata - auto myversion = keyword.meta("version"); - auto mydate = keyword.meta("date"); - auto myshape = keyword.meta("shape",shape_t{},detail::convert_t{}); - - // for children - // The following is just like GNDStk::common::numeric, - // or equivalently, GNDStk::[basic or core]::numeric. - auto mynumbers = keyword.child - ("pcdata",values_t{},detail::convert_pcdata_text_t{}); - - // In the following, a name of "" means to stay at the current node - auto mymanifest = keyword.child(""); - - auto vers = tree(xml,myversion); - - - // ------------------------ - // use them - // ------------------------ - - WHEN("We build our own Child and Meta objects, using keyword_t") { - - THEN("Try extracting xml version") { - // Extract version into *our* version type - // Specifically: myversion keyword ==> version_t - CHECK(vers.major == 1); - CHECK(vers.minor == 0); - } - - THEN("Try extracting covarianceSuite/styles/evaluated/version") { - // Now extract version - vers = tree(covarianceSuite,styles,--evaluated,myversion); - CHECK(vers.major == 8); - CHECK(vers.minor == 0); - CHECK(vers.patch == 1); - } - - // For brevity, let's make a shortcut to - auto &eval = tree(covarianceSuite,styles,--evaluated); - - THEN("Try extracting covarianceSuite/styles/evaluated/date") { - // Extract date in , via the shortcut - // Specifically: mydate keyword ==> date_t - auto date = eval(mydate); - CHECK(date.year == 2011); - CHECK(date.month == 10); - CHECK(date.day == 1); - } - - // Pull out , to make some upcoming queries shorter - auto &arr = tree( - covarianceSuite, parameterCovariances, --parameterCovariance, - --parameterCovarianceMatrix, array); - - THEN("Try extracting .../array/shape") { - // Extract shape into our shape type - // Specifically: myshape keyword ==> shape_t - auto shape = arr(myshape); - CHECK(shape.rows == 78); - CHECK(shape.cols == 78); - } - - THEN("Try extracting .../array/values") { - // Extract values into our values_t type, - // which is vector. - // Specifically: myshape keyword ==> shape_t - auto val = arr(--child::values,mynumbers); - CHECK(val[0] == 0.015); - CHECK(val[1] == 0); - CHECK(val[2] == 0); - CHECK(val[3] == 0); - CHECK(val[4] == 4.5e-5); - } - - } // WHEN - - - // ------------------------ - // Special keyword - // with lookup "" - // ------------------------ - - // Special keyword: mymanifest, a child keyword with lookup key "". - // Meaning: for the currently active Node, print its name, the names - // of its metadata, and the names of its children. This demonstrates - // how we could build various "x-ray" or "dictionary" type tools. - // See how manifest_t is set up, earlier in this file. - - // Examine the tree itself - WHEN("We use a special \"\"-named keyword to examine tree") { - auto man = tree(mymanifest); - CHECK(man.information == manifest_tree); - } - - // Let's look at what's in the top-level GNDS node. Note that top() - // gets us the top-level node here, from which we call (manifest); - // we do *not* write tree.top(manifest), which wouldn't make sense. - WHEN("We use a special \"\"-named keyword to examine tree.top()") { - auto man = tree.top()(mymanifest); - CHECK(man.information == manifest_covarianceSuite); - } - - // Of course we can do this as well, knowing that covarianceSuite - // is the top-level node - WHEN("We use a special \"\"-named keyword to examine ") { - auto man = tree(covarianceSuite, mymanifest); - CHECK(man.information == manifest_covarianceSuite); - } - - // And let's dig further: - WHEN("We use a special \"\"-named keyword to examine " - ".../") { - auto man = tree( - covarianceSuite, parameterCovariances, - --parameterCovariance, mymanifest - ); - CHECK(man.information == manifest_parameterCovariances); - } - - - // ------------------------ - // Exercise keyword - // builder... - // ------------------------ - - // To properly test this, we should really have something like the Boost - // demangle library, to print a representation of the *type* that's being - // created. For now, let's just make sure that the expressions are valid. - - // ------------------------ - // ...metadata, type - // ------------------------ - - { - { auto m = keyword.meta ("m" ); } - { auto m = keyword.meta ("m", 0 ); } - { auto m = keyword.meta ("m", 0, detail::convert_t{}); } - { auto m = keyword.meta< > ("m" ); } - { auto m = keyword.meta< > ("m", 0 ); } - { auto m = keyword.meta< > ("m", 0, detail::convert_t{}); } - { auto m = keyword.meta ("m" ); } - { auto m = keyword.meta ("m", 0 ); } - { auto m = keyword.meta ("m", 0, detail::convert_t{}); } - { auto m = keyword.meta ("m" ); } - { auto m = keyword.meta ("m", 0 ); } - { auto m = keyword.meta ("m", 0, detail::convert_t{}); } - } - - // ------------------------ - // ...metadata, void - // ------------------------ - - { - { auto m = keyword.meta ("m"); } - { auto m = keyword.meta< > ("m"); } - { auto m = keyword.meta ("m"); } - } - - // ------------------------ - // ...children, type - // ------------------------ - - // The commented-out cases are ambiguous: - // TYPE for , or FILTER for ? - { - { auto c = keyword.child ("c" ); } - // { auto c = keyword.child ("c", 0 ); } - { auto c = keyword.child ("c", 0, detail::convert_t{} ); } - { auto c = keyword.child ("c", 0, detail::convert_t{}, detail::noFilter{}); } - { auto c = keyword.child ("c", 0, detail::convert_t{}, detail::noFilter{}); } - { auto c = keyword.child< > ("c" ); } - // { auto c = keyword.child< > ("c", 0 ); } - { auto c = keyword.child< > ("c", 0, detail::convert_t{} ); } - { auto c = keyword.child< > ("c", 0, detail::convert_t{}, detail::noFilter{}); } - { auto c = keyword.child< > ("c", 0, detail::convert_t{}, detail::noFilter{}); } - { auto c = keyword.child ("c" ); } - { auto c = keyword.child ("c", 0 ); } - { auto c = keyword.child ("c", 0, detail::convert_t{} ); } - { auto c = keyword.child ("c", 0, detail::convert_t{}, detail::noFilter{}); } - { auto c = keyword.child ("c", 0, detail::convert_t{}, detail::noFilter{}); } - { auto c = keyword.child ("c" ); } - { auto c = keyword.child ("c", 0 ); } - { auto c = keyword.child ("c", 0, detail::convert_t{} ); } - { auto c = keyword.child ("c", 0, detail::convert_t{}, detail::noFilter{}); } - { auto c = keyword.child ("c", 0, detail::convert_t{}, detail::noFilter{}); } - { auto c = keyword.child ("c" ); } - { auto c = keyword.child ("c", 0 ); } - { auto c = keyword.child ("c", 0, detail::convert_t{} ); } - { auto c = keyword.child ("c", 0, detail::convert_t{}, detail::noFilter{}); } - { auto c = keyword.child ("c", 0, detail::convert_t{}, detail::noFilter{}); } - { auto c = keyword.child ("c" ); } - { auto c = keyword.child ("c", 0 ); } - { auto c = keyword.child ("c", 0, detail::convert_t{} ); } - { auto c = keyword.child ("c", 0, detail::convert_t{}, detail::noFilter{}); } - { auto c = keyword.child ("c", 0, detail::convert_t{}, detail::noFilter{}); } - } - - // ------------------------ - // ...children, void - // ------------------------ - - // The commented-out cases are ambiguous, as above. - { - { auto c = keyword.child ("c" ); } - // { auto c = keyword.child ("c", detail::noFilter{}); } - { auto c = keyword.child ("c", detail::noFilter{}, false); } - { auto c = keyword.child< > ("c" ); } - // { auto c = keyword.child< > ("c", detail::noFilter{}); } - { auto c = keyword.child< > ("c", detail::noFilter{}, false); } - { auto c = keyword.child ("c" ); } - { auto c = keyword.child ("c", detail::noFilter{}); } - { auto c = keyword.child ("c", detail::noFilter{}); } - { auto c = keyword.child ("c" ); } - { auto c = keyword.child ("c", detail::noFilter{}); } - { auto c = keyword.child ("c", detail::noFilter{}); } - { auto c = keyword.child ("c" ); } - { auto c = keyword.child ("c", detail::noFilter{}); } - { auto c = keyword.child ("c", detail::noFilter{}); } - } -} diff --git a/src/GNDStk/keyword/test/resources/n-069_Tm_170-covar.xml b/src/GNDStk/keyword/test/resources/n-069_Tm_170-covar.xml deleted file mode 100644 index 3ea648853..000000000 --- a/src/GNDStk/keyword/test/resources/n-069_Tm_170-covar.xml +++ /dev/null @@ -1,25 +0,0 @@ - - - - - - - - - - - - - - - - - - - - 0.015 0 0 0 4.5e-5 0.015 3e-2 0 0 0 1.35e-4 0.015 2e-2 0 0 0 1.5e-3 0.012 5e-2 0 0 0 1.875e-3 6e-2 5e-2 0 0 0 1.05e-4 0.015 0.1 0 0 0 6e-4 0.012 0.1 0 0 0 2.25e-4 0.012 0.2 0 0 0 5.25e-3 0.012 0.2 0 0 0 3.45e-3 0.012 0.3 0 0 0 4.5e-4 0.012 0.3 0 0 0 3e-3 0.012 0.4 0 0 0 9e-3 0.012 0.4 0 0 0 1.425e-3 0.012 - - - - - From b1fb7fc997530d12cdd047291db53af3710836db Mon Sep 17 00:00:00 2001 From: Martin Staley Date: Tue, 14 Dec 2021 00:26:08 -0700 Subject: [PATCH 23/39] Reformulation of HDF5-related temporary file handling. Gets rid of the annoying compiler warning about `tmpnam()`. The new formulation required a number of changes in the logic here and there. --- src/GNDStk/HDF5.hpp | 90 +++++++++--------- src/GNDStk/HDF5/src/assign.hpp | 8 +- src/GNDStk/HDF5/src/ctor.hpp | 10 +- src/GNDStk/HDF5/src/read.hpp | 161 +++++++++++--------------------- src/GNDStk/HDF5/src/write.hpp | 80 ++++++++-------- src/GNDStk/convert/src/HDF5.hpp | 42 ++++----- src/GNDStk/convert/src/Tree.hpp | 4 +- 7 files changed, 174 insertions(+), 221 deletions(-) diff --git a/src/GNDStk/HDF5.hpp b/src/GNDStk/HDF5.hpp index 2b86d1c2c..29d716dd1 100644 --- a/src/GNDStk/HDF5.hpp +++ b/src/GNDStk/HDF5.hpp @@ -8,9 +8,9 @@ class HDF5 { public: // data - HighFive::File *file = nullptr; + int fileDesc = 0; + HighFive::File *filePtr = nullptr; std::string filename = ""; - mutable bool temporary = false; // file modes static inline const auto modeRead = @@ -21,70 +21,74 @@ class HDF5 { HighFive::File::Truncate; // temporaryName() - static std::string temporaryName() + static std::string temporaryName(int &desc) { - // Generate a file name that's supposed to be suitable for safely creating - // a temporary file. L_tmpnam and tmpnam() are from . In case - // anyone wonders, we don't need a +1 in the [L_tmpnam]. :-) - static char buffer[L_tmpnam]; + static const int maxTry = 10; + int count = 0; + + desc = 0; + std::string name; while (true) { - const std::string name = std::string(tmpnam(buffer)) + ".h5"; - std::ifstream ifs(name, std::ios::binary); - if (!ifs) // <== as should be the case - return name; - - // Well that's weird; the tmpnam()-generated file name (admittedly, - // with our added ".h5") refers to a file that already exists. :-/ - log::info("Generated temporary HDF5 file name \"{}\" " - "is already in use.\n" - "That's harmless, but it really shouldn't happen.\n" - "Generating another name....", name); + name = "GNDStk-tmp-XXXXXX.h5"; + if ((desc = mkstemps(name.data(),3)) > 0) + break; + + log::warning( + "Creation of temporary file with mkstemps() failed.\n" + "Message: \"{}\"", + strerror(errno) + ); + + if (++count == maxTry) { + log::error( + "Maximum number {} of temporary file " + "creation failures reached; bailing out", + maxTry + ); + throw std::exception{}; + } } - } - -private: - void removeTemporary() const - { - if (temporary && filename != "") { - std::ifstream ifs(filename); - if (!ifs) - return; // removed already, or was not there (e.g. creation error) - - ifs.close(); // prior to removal... - if (remove(filename.data()) == 0) - return; // remove() succeeded + /* + auto ret = unlink(name.data()); + std::cout << "unlink == " << ret << std::endl;/// + std::cout << "fileDesc == " << desc << std::endl;/// + std::cout << "fileName == " << '"' << name << '"' << std::endl;/// + */ - log::warning("Could not remove temporary HDF5 file \"{}\"", filename); - log::member("HDF5::removeTemporary(), with filename \"{}\"", filename); - } + return name; } -public: - // clear HDF5 &clear() { - delete file; - file = nullptr; - removeTemporary(); + if (fileDesc > 0 && filePtr) + filePtr->flush(); + delete filePtr; + filePtr = nullptr; + + if (fileDesc > 0) + close(fileDesc); + fileDesc = 0; + + if (filename != "") + unlink(filename.data()); filename = ""; - temporary = false; + return *this; } // empty bool empty() const { - return file == nullptr; + return filePtr == nullptr; } // destructor ~HDF5() { - delete file; - removeTemporary(); + clear(); } // constructors, assignment diff --git a/src/GNDStk/HDF5/src/assign.hpp b/src/GNDStk/HDF5/src/assign.hpp index b7dfc43ce..4ef61744b 100644 --- a/src/GNDStk/HDF5/src/assign.hpp +++ b/src/GNDStk/HDF5/src/assign.hpp @@ -8,13 +8,13 @@ HDF5 &operator=(HDF5 &&other) { clear(); - file = std::move(other.file); + fileDesc = std::move(other.fileDesc); + filePtr = std::move(other.filePtr); filename = std::move(other.filename); - temporary = std::move(other.temporary); - other.file = nullptr; + other.fileDesc = 0; + other.filePtr = nullptr; other.filename = ""; - other.temporary = false; return *this; } diff --git a/src/GNDStk/HDF5/src/ctor.hpp b/src/GNDStk/HDF5/src/ctor.hpp index 2fd76437a..4e894b24b 100644 --- a/src/GNDStk/HDF5/src/ctor.hpp +++ b/src/GNDStk/HDF5/src/ctor.hpp @@ -12,13 +12,13 @@ HDF5() { } // move HDF5(HDF5 &&other) : - file(std::move(other.file)), - filename(std::move(other.filename)), - temporary(std::move(other.temporary)) + fileDesc(std::move(other.fileDesc)), + filePtr (std::move(other.filePtr)), + filename(std::move(other.filename)) { - other.file = nullptr; + other.fileDesc = 0; + other.filePtr = nullptr; other.filename = ""; - other.temporary = false; } // copy diff --git a/src/GNDStk/HDF5/src/read.hpp b/src/GNDStk/HDF5/src/read.hpp index e9de0e4a6..58ffe462d 100644 --- a/src/GNDStk/HDF5/src/read.hpp +++ b/src/GNDStk/HDF5/src/read.hpp @@ -3,96 +3,66 @@ // HDF5.read() // ----------------------------------------------------------------------------- -/* -DISCUSSION - -While this may appear at first glance to be inefficient, our read(istream) -function actually transfers the istream's contents to a temporary file, then -calls read(filename) on the temporary file. That function, in turn, uses the -underlying HighFive HDF5 library's read-from-file capability in order to do the -actual work of providing an interface into HDF5 data. - -Normally, one might do the reverse: use read-from-istream as a helper to read- -from-file, with the latter opening the file as an ifstream, then calling the -former to do the heavy lifting. Indeed, our read-from-file functions for XML -and JSON do precisely that. - -Here, however, we did things in the seemingly backwards way for the simple -reason that, at the time of this writing, we see no capability in HighFive to -read from an istream! Just to read directly from a file. While we haven't looked -into the details, we think HighFive isn't actually reading the file (or much of -the file) into an internal data structure, as the XML and JSON librarys do, but -instead reads little or nothing, maintains a handle to the file itself (making -the file, in effect, act as a data structure on disk, instead of one in memory), -and then deals with the file when, and only when, someone reads or writes data. - -One might ask why we chose to implement this arguably convoluted read-from- -istream at all - as opposed to supporting only read-from-file, given that a file -has to be involved either way. Our reason is simply that we're designing all of -our file-format classes (at present: XML, JSON, and HDF5) to behave as similarly -as possible with one another. This uniformity helps make the code - for all the -formats and throughout GNDStk - look and feel as consistent as possible. This -helps with debugging and testing, and gives users a more-uniform interface. -*/ - - // ----------------------------------------------------------------------------- // read(istream) // ----------------------------------------------------------------------------- std::istream &read(std::istream &is) { + static const std::string context = + "HDF5.read(istream) (uses a temporary file)"; + // Clear present contents. clear(); + // Re: temporary file. + int desc; + const std::string name = temporaryName(desc); + + // Open temporary file. This *should* work, but we check anyway. + std::ofstream ofs(name, std::ios::binary); + if (!ofs) { + log::error("Could not open temporary file \"{}\"", name); + log::member(context); + return is; + } + // Current stream position. We'll rewind to this point if an error occurs. // Of course it's probably at 0 - I doubt we'd be dealing with HDF5 content - // that's mixed with something else - but we do the following elsewhere, - // and will be consistent with that behavior here. + // that's mixed with something else - but we do the following elsewhere and + // will be consistent with that behavior here. const std::streampos pos = is.tellg(); - // Name for temporary file. - filename = temporaryName(); + // Copy the istream's bytes to the temporary file. We copy all bytes, + // so we suppose something might go awry if someone somehow attached + // non-HDF5 bytes beyond the end (which we can't detect) of the HDF5 + // material. However, that would be a strange thing for someone to do. + char ch; + while (is.get(ch) && ofs) + ofs.put(ch); + if (!(is.fail() && is.eof() && !is.bad() && ofs.good())) { + log::error( + "Error writing istream's contents to temporary file \"{}\"", name); + log::member(context); + detail::failback(is,pos); + return is; + } + ofs.close(); try { - // Open temporary file. This *should* work, but we check anyway. - std::ofstream ofs(filename, std::ios::binary); - if (!ofs) { - log::error("Could not open temporary file \"{}\"", filename); - throw std::exception{}; - } - - // Copy bytes from the istream to the temporary file. We copy all bytes; - // so, we suppose that something might go awry if someone somehow attached - // non-HDF5 bytes beyond the end (which we can't detect) of the HDF5 - // material. But, that would be a very strange thing for someone to do. - char ch; - while (is.get(ch) && ofs) - ofs.put(ch); - if (!(is.fail() && is.eof() && !is.bad() && ofs.good())) { - log::error( - "Error writing istream HDF5 contents to temporary file \"{}\"", - filename); - ofs.close(); - throw std::exception{}; - } - ofs.close(); - - // Call read(filename) to read HDF5 content from the temporary file. - // See our detailed discussion earlier. - if (!read(filename)) - throw std::exception{}; - } catch (...) { - log::member("HDF5.read(istream) (uses a temporary file)"); - temporary = true; // possibly after read(filename), which makes it false - clear(); // which also does removeTemporary() - detail::failback(is,pos); + filePtr = new HighFive::File(name,modeRead); + filename = name; + fileDesc = desc; + is.clear(std::ios_base::eofbit); // as expected return is; + } catch (...) { + log::error("Call 'new HighFive::File(\"{}\",ReadOnly)' " + "threw an exception", name); } - // done - temporary = true; // after read(filename), which makes it false - is.clear(std::ios_base::eofbit); // as expected + log::member(context); + delete filePtr; + detail::failback(is,pos); return is; } @@ -101,48 +71,29 @@ std::istream &read(std::istream &is) // read(file name) // ----------------------------------------------------------------------------- -// The parameter is intentionally by-value, not by-reference, so that it won't -// surreptitiously be set to "" by the clear() call if the actual parameter -// happens to be this->filename - which it is, in fact, if this read() is called -// from the above read(istream). (And, although it's unlikely, someone could -// conceivably make such a call directly instead of through the above read(), -// in for example a scenario where the file might have changed on disk and -// someone wants it to be re-read.) We don't run into a similar problem with -// the XML or JSON read()s, not just because their read(istream)s don't call -// their read(file name)s, but also because they simply do not, at present, -// have std::string member data that might be aliased by a parameter like the -// one below, so that a clear() accidentally clears the parameter. bool read(const std::string name) { clear(); - filename = name; - // Note: if this function's name parameter had been by-reference, right here - // is where we might inadvertently have filename == ""; see the above remark - bool ret = false; - // Test that the file can be opened. The upcoming HighFive::File(filename) - // call does, in fact, open the file. However, this "test open" allows us - // to provide diagnostics that resemble those that we provide in our read() - // functions for other file formats. - std::ifstream ifs(filename, std::ios::binary); + // Test that the file can be opened. The upcoming HighFive::File(...) call + // does, in fact, open the file. However, a "test open" allows us to provide + // diagnostics that resemble those that we provide in our read() functions + // for other file formats. + std::ifstream ifs(name, std::ios::binary); if (ifs) { ifs.close(); try { - file = new HighFive::File(filename, modeRead); - ret = true; // all's well - our "test open," and HighFive's reading + filePtr = new HighFive::File(name,modeRead); + filename = name; + return true; } catch (...) { - log::error("file = HighFive::File(filename, ReadOnly)\n" - "threw an exception"); + log::error("Call 'new HighFive::File(\"{}\",ReadOnly)' " + "threw an exception", name); } } else - log::error("Could not open file \"{}\" for input", filename); - - if (!ret) { - log::member("HDF5.read(\"{}\")", filename); - clear(); - } + log::error("Could not open file \"{}\"", name); - // done - temporary = false; - return ret; + log::member("HDF5.read(\"{}\")", name); + delete filePtr; + return false; } diff --git a/src/GNDStk/HDF5/src/write.hpp b/src/GNDStk/HDF5/src/write.hpp index 2c613c0a8..be3164a54 100644 --- a/src/GNDStk/HDF5/src/write.hpp +++ b/src/GNDStk/HDF5/src/write.hpp @@ -9,45 +9,46 @@ std::ostream &write(std::ostream &os, const bool decl = true) const { + static const std::string context = "HDF5.write(ostream)"; + (void)decl; // unused, at least for now char ch; os.clear(); try { if (empty()) { - // This HDF5 object is empty, so we'll create valid "stub" HDF5 output. - // First, create a temporary stub HDF5 file. We go through this file, - // not directly into the ostream, because, as we've written elsewhere, - // the HDF5 library deals directly with files, not with streams. This - // go-through-a-temporary process thus appears to be necessary. - const std::string tmpName = temporaryName(); - HighFive::File stub(tmpName.data(), modeWrite); - stub.flush(); // file should be there now - - // Open the temporary stub file + // This HDF5 object is empty. We'll place "stub" HDF5 output into + // a temporary file, then read the contents into the ostream. Using + // a temporary file is necessary here, as it is elsewhere, because + // HighFive deals directly with files, not with streams. + int tmpDesc; + const std::string tmpName = temporaryName(tmpDesc); + { // scoped, so the HighFive::File is "closed" at the end + HighFive::File stub(tmpName.data(), modeWrite); + stub.flush(); // a file should be there now + } + + // Open the temporary file std::ifstream ifs(tmpName, std::ios::binary); if (!ifs) { - log::error("Could not open temporary HDF5 file \"{}\" " + log::error("Could not open temporary file \"{}\" " "for writing to ostream", tmpName); throw std::exception{}; } - // Transfer the temporary stub file's contents to the ostream + // Transfer the temporary file's contents to the ostream while (ifs.get(ch) && os) os.put(ch); const bool good = ifs.fail() && ifs.eof() && !ifs.bad() && os.good(); + ifs.close(); - // Close and remove the temporary stub file - ifs.close(); // prior to removal... - if (remove(tmpName.data()) != 0) { - log::warning( - "Could not remove temporary HDF5 file \"{}\"", tmpName); - log::member("HDF5.write(ostream)"); - } + // Finally, close via tmpDesc. Combined with temporaryName()'s + // call to unlink(), this should trigger removal of the file. + close(tmpDesc); if (!good) { log::error( - "Error writing temporary HDF5 file \"{}\"'s contents to ostream", + "Error writing temporary file \"{}\"'s contents to ostream", tmpName); throw std::exception{}; } @@ -56,9 +57,11 @@ std::ostream &write(std::ostream &os, const bool decl = true) const // This HDF5 object is not empty. Writing it to an ostream - this // function's purpose - amounts to copying bytes *from* the file to // which the HDF5 object refers, *to* the ostream. + filePtr->flush(); + std::ifstream ifs(filename, std::ios::binary); if (!ifs) { - log::error("Could not open HDF5 file \"{}\" " + log::error("Could not open file \"{}\" " "for writing to ostream", filename); throw std::exception{}; } @@ -66,16 +69,19 @@ std::ostream &write(std::ostream &os, const bool decl = true) const // Transfer the file's contents to the ostream while (ifs.get(ch) && os) os.put(ch); - if (!(ifs.fail() && ifs.eof() && !ifs.bad() && os.good())) { - ifs.close(); + const bool good = ifs.fail() && ifs.eof() && !ifs.bad() && os.good(); + ifs.close(); + + if (!good) { log::error( - "Error writing HDF5 file \"{}\"'s contents to ostream", filename); + "Error writing file \"{}\"'s contents to ostream", + filename); throw std::exception{}; } } } catch (...) { - log::member("HDF5.write(ostream)"); + log::member(context); os.setstate(std::ios::failbit); } @@ -88,30 +94,28 @@ std::ostream &write(std::ostream &os, const bool decl = true) const // write(file name) // ------------------------ -bool write(const std::string &filename, const bool decl = true) const +bool write(const std::string &name, const bool decl = true) const { - // well, I suppose it's possible that the file we're wanting to write the - // HDF5 object to, is the same file the HDF5 object already references... - if (filename == this->filename) { - file->flush(); // <== for good measure - temporary = false; // <== and since filename was specifically asked for + // Well, I suppose it's possible... + if (!empty() && name == filename) { + filePtr->flush(); return true; } - // open file - std::ofstream ofs(filename, std::ios::binary); + // Open file + std::ofstream ofs(name, std::ios::binary); if (!ofs) { - log::error("Could not open file \"{}\" for output", filename); - log::member("HDF5.write(\"{}\")", filename); + log::error("Could not open file \"{}\" for output", name); + log::member("HDF5.write(\"{}\")", name); return false; } - // write to ostream + // Write to ostream if (!write(ofs,decl)) { - log::member("HDF5.write(\"{}\")", filename); + log::member("HDF5.write(\"{}\")", name); return false; } - // done + // Done return true; } diff --git a/src/GNDStk/convert/src/HDF5.hpp b/src/GNDStk/convert/src/HDF5.hpp index 2dac262ab..460a20731 100644 --- a/src/GNDStk/convert/src/HDF5.hpp +++ b/src/GNDStk/convert/src/HDF5.hpp @@ -14,26 +14,16 @@ inline bool convert(const Node &node, HDF5 &h) h.clear(); // for the HDF5 - h.filename = h.temporaryName(); + h.filename = h.temporaryName(h.fileDesc); static const std::string context = "convert(Node,HDF5)"; try { - - // Open temporary HDF5 file. This *should* work, but we check anyway. - std::ofstream ofs(h.filename, std::ios::binary); - if (!ofs) { - log::error("Could not open temporary HDF5 file \"{}\"", h.filename); - throw std::exception{}; - } - ofs.close(); - - h.file = new HighFive::File(h.filename, HDF5::modeWrite); - h.temporary = true; + h.filePtr = new HighFive::File(h.filename, HDF5::modeWrite); // Probably a regular Node... if (node.name != "") { - const bool ret = detail::node2hdf5(node,*h.file); - h.file->flush(); + const bool ret = detail::node2hdf5(node,*h.filePtr); + h.filePtr->flush(); return ret; } @@ -78,9 +68,10 @@ inline bool convert(const Node &node, HDF5 &h) ); log::function(context); } - if (!detail::node2hdf5(*c,*h.file)) + const bool ret = detail::node2hdf5(*c,*h.filePtr); + h.filePtr->flush(); + if (!ret) return false; - h.file->flush(); found_top = true; } // else } // for @@ -159,23 +150,26 @@ inline bool convert(const JSON &j, HDF5 &h) inline bool convert(const HDF5 &from, HDF5 &to) { + // self? if (&to == &from) return true; // clear to.clear(); + // empty? + if (from.empty()) + return true; + // convert try { - if (!from.empty()) { - std::ifstream ifs(from.filename, std::ios::binary); - if (!ifs) { - log::error("Could not open file \"{}\"", from.filename); - throw std::exception{}; - } - if (!to.read(ifs)) - throw std::exception{}; + std::ifstream ifs(from.filename, std::ios::binary); + if (!ifs) { + log::error("Could not open file \"{}\"", from.filename); + throw std::exception{}; } + if (!to.read(ifs)) + throw std::exception{}; } catch (...) { log::function("convert(HDF5,HDF5)"); throw; diff --git a/src/GNDStk/convert/src/Tree.hpp b/src/GNDStk/convert/src/Tree.hpp index a2952b5fa..561f2fdf3 100644 --- a/src/GNDStk/convert/src/Tree.hpp +++ b/src/GNDStk/convert/src/Tree.hpp @@ -256,9 +256,9 @@ inline bool convert(const HDF5 &h, Node &node, const bool decl) if (h.empty()) return true; - // not empty in the earlier (h.file == nullptr) sense, + // not empty in the earlier (h.filePtr == nullptr) sense, // but with no real content in the HDF5 document? - const HighFive::Group &group = h.file->getGroup("/"); + const HighFive::Group &group = h.filePtr->getGroup("/"); if (group.getNumberAttributes() == 0 && group.getNumberObjects() == 0) return true; From f4c86202860feaebe5eb6ddf92e2bff913823d38 Mon Sep 17 00:00:00 2001 From: Martin Staley Date: Wed, 15 Dec 2021 23:37:29 -0700 Subject: [PATCH 24/39] Cleaned-up and improved logic related to HDF5 handling. Made certain HDF5-related operations more efficient. --- src/GNDStk/HDF5.hpp | 33 ++++++++++------------------- src/GNDStk/HDF5/src/assign.hpp | 4 ++-- src/GNDStk/HDF5/src/ctor.hpp | 8 +++---- src/GNDStk/HDF5/src/write.hpp | 37 +++++++++++++++++---------------- src/GNDStk/Node/src/write.hpp | 16 +++++++++++--- src/GNDStk/convert/src/HDF5.hpp | 11 +++++----- src/GNDStk/utility.hpp | 2 +- 7 files changed, 55 insertions(+), 56 deletions(-) diff --git a/src/GNDStk/HDF5.hpp b/src/GNDStk/HDF5.hpp index 29d716dd1..92a50ec30 100644 --- a/src/GNDStk/HDF5.hpp +++ b/src/GNDStk/HDF5.hpp @@ -8,9 +8,9 @@ class HDF5 { public: // data - int fileDesc = 0; HighFive::File *filePtr = nullptr; std::string filename = ""; + int fileDesc = 0; // file modes static inline const auto modeRead = @@ -26,13 +26,10 @@ class HDF5 { static const int maxTry = 10; int count = 0; - desc = 0; - std::string name; - while (true) { - name = "GNDStk-tmp-XXXXXX.h5"; + std::string name = "GNDStk-tmp-XXXXXX.h5"; if ((desc = mkstemps(name.data(),3)) > 0) - break; + return name; log::warning( "Creation of temporary file with mkstemps() failed.\n" @@ -49,32 +46,24 @@ class HDF5 { throw std::exception{}; } } - - /* - auto ret = unlink(name.data()); - std::cout << "unlink == " << ret << std::endl;/// - std::cout << "fileDesc == " << desc << std::endl;/// - std::cout << "fileName == " << '"' << name << '"' << std::endl;/// - */ - - return name; } // clear HDF5 &clear() { - if (fileDesc > 0 && filePtr) + if (filePtr) filePtr->flush(); - delete filePtr; - filePtr = nullptr; - if (fileDesc > 0) + if (fileDesc > 0) { close(fileDesc); - fileDesc = 0; + if (filename != "") // should be, if (fileDesc > 0) + unlink(filename.data()); + } - if (filename != "") - unlink(filename.data()); + fileDesc = 0; filename = ""; + delete filePtr; + filePtr = nullptr; return *this; } diff --git a/src/GNDStk/HDF5/src/assign.hpp b/src/GNDStk/HDF5/src/assign.hpp index 4ef61744b..39945c92d 100644 --- a/src/GNDStk/HDF5/src/assign.hpp +++ b/src/GNDStk/HDF5/src/assign.hpp @@ -8,13 +8,13 @@ HDF5 &operator=(HDF5 &&other) { clear(); - fileDesc = std::move(other.fileDesc); filePtr = std::move(other.filePtr); filename = std::move(other.filename); + fileDesc = std::move(other.fileDesc); - other.fileDesc = 0; other.filePtr = nullptr; other.filename = ""; + other.fileDesc = 0; return *this; } diff --git a/src/GNDStk/HDF5/src/ctor.hpp b/src/GNDStk/HDF5/src/ctor.hpp index 4e894b24b..80391b1e4 100644 --- a/src/GNDStk/HDF5/src/ctor.hpp +++ b/src/GNDStk/HDF5/src/ctor.hpp @@ -12,13 +12,13 @@ HDF5() { } // move HDF5(HDF5 &&other) : - fileDesc(std::move(other.fileDesc)), - filePtr (std::move(other.filePtr)), - filename(std::move(other.filename)) + filePtr (std::move(other.filePtr )), + filename(std::move(other.filename)), + fileDesc(std::move(other.fileDesc)) { - other.fileDesc = 0; other.filePtr = nullptr; other.filename = ""; + other.fileDesc = 0; } // copy diff --git a/src/GNDStk/HDF5/src/write.hpp b/src/GNDStk/HDF5/src/write.hpp index be3164a54..19a10cfa3 100644 --- a/src/GNDStk/HDF5/src/write.hpp +++ b/src/GNDStk/HDF5/src/write.hpp @@ -10,53 +10,52 @@ std::ostream &write(std::ostream &os, const bool decl = true) const { static const std::string context = "HDF5.write(ostream)"; - - (void)decl; // unused, at least for now - char ch; os.clear(); + (void)decl; // unused, at least for now try { if (empty()) { // This HDF5 object is empty. We'll place "stub" HDF5 output into - // a temporary file, then read the contents into the ostream. Using - // a temporary file is necessary here, as it is elsewhere, because - // HighFive deals directly with files, not with streams. - int tmpDesc; - const std::string tmpName = temporaryName(tmpDesc); + // a temporary file, then copy the file's contents to the ostream. + // A temporary is used here, as it is elsewhere in our HDF handling, + // because HighFive deals directly with files, not with streams. + int stubDesc; + const std::string stubName = temporaryName(stubDesc); { // scoped, so the HighFive::File is "closed" at the end - HighFive::File stub(tmpName.data(), modeWrite); + HighFive::File stub(stubName.data(), modeWrite); stub.flush(); // a file should be there now } // Open the temporary file - std::ifstream ifs(tmpName, std::ios::binary); + std::ifstream ifs(stubName, std::ios::binary); if (!ifs) { log::error("Could not open temporary file \"{}\" " - "for writing to ostream", tmpName); + "for writing to ostream", stubName); throw std::exception{}; } // Transfer the temporary file's contents to the ostream + char ch; while (ifs.get(ch) && os) os.put(ch); const bool good = ifs.fail() && ifs.eof() && !ifs.bad() && os.good(); ifs.close(); - // Finally, close via tmpDesc. Combined with temporaryName()'s - // call to unlink(), this should trigger removal of the file. - close(tmpDesc); + // Cleanup + close(stubDesc); + unlink(stubName.data()); + // Check status if (!good) { log::error( "Error writing temporary file \"{}\"'s contents to ostream", - tmpName); + stubName); throw std::exception{}; } } else { - // This HDF5 object is not empty. Writing it to an ostream - this - // function's purpose - amounts to copying bytes *from* the file to - // which the HDF5 object refers, *to* the ostream. + // This HDF5 object is not empty. Writing it to an ostream amounts + // to copying bytes from *filePtr's file to the ostream. filePtr->flush(); std::ifstream ifs(filename, std::ios::binary); @@ -67,11 +66,13 @@ std::ostream &write(std::ostream &os, const bool decl = true) const } // Transfer the file's contents to the ostream + char ch; while (ifs.get(ch) && os) os.put(ch); const bool good = ifs.fail() && ifs.eof() && !ifs.bad() && os.good(); ifs.close(); + // Check status if (!good) { log::error( "Error writing file \"{}\"'s contents to ostream", diff --git a/src/GNDStk/Node/src/write.hpp b/src/GNDStk/Node/src/write.hpp index 4bae62dff..614cfceb5 100644 --- a/src/GNDStk/Node/src/write.hpp +++ b/src/GNDStk/Node/src/write.hpp @@ -115,7 +115,12 @@ bool write(const std::string &filename, const int level) const std::ostream &write( std::ostream &os = std::cout, const FileType format = FileType::null, - const bool decl = false + const bool decl = false, + // If circumstances are such that we end up writing an HDF5, the following + // may be != "" if the ostream is from an ofstream. In that case, the HDF5 + // writer can produce output directly into the intended file, bypassing the + // need to create a temporary file and transfer its contents to the ostream. + const std::string &filename = "" ) const { // Discussion. @@ -152,7 +157,12 @@ std::ostream &write( JSON(*this).write(os,decl); } else if (format == FileType::hdf5) { // write via a temporary hdf5 object... - HDF5(*this).write(os,decl); + if (filename == "") + HDF5(*this).write(os,decl); + else { + HDF5 tmp; + convert(*this,tmp,filename); + } } else { // null or text: use our plain text format return write(os,0); @@ -238,7 +248,7 @@ bool write( } // Call write(ostream) to do the remaining work. - if (!write(ofs, format, decl)) + if (!write(ofs, format, decl, filename)) throw std::exception{}; return bool(ofs); } catch (...) { diff --git a/src/GNDStk/convert/src/HDF5.hpp b/src/GNDStk/convert/src/HDF5.hpp index 460a20731..246218102 100644 --- a/src/GNDStk/convert/src/HDF5.hpp +++ b/src/GNDStk/convert/src/HDF5.hpp @@ -8,15 +8,14 @@ // Node ==> HDF5 // ----------------------------------------------------------------------------- -inline bool convert(const Node &node, HDF5 &h) +inline bool convert(const Node &node, HDF5 &h, const std::string &name) { - // clear - h.clear(); + static const std::string context = "convert(Node,HDF5)"; - // for the HDF5 - h.filename = h.temporaryName(h.fileDesc); + // Prepare the HDF5 + h.clear(); + h.filename = name != "" ? name : h.temporaryName(h.fileDesc); - static const std::string context = "convert(Node,HDF5)"; try { h.filePtr = new HighFive::File(h.filename, HDF5::modeWrite); diff --git a/src/GNDStk/utility.hpp b/src/GNDStk/utility.hpp index 2a8f363fe..0f157c965 100644 --- a/src/GNDStk/utility.hpp +++ b/src/GNDStk/utility.hpp @@ -332,7 +332,7 @@ class HDF5; // Node to {XML,JSON,HDF5} bool convert(const Node &, XML &); bool convert(const Node &, JSON &); -bool convert(const Node &, HDF5 &); +bool convert(const Node &, HDF5 &, const std::string & = ""); // Tree to {Tree,XML,JSON,HDF5} bool convert(const Tree &, Tree &); From 04df13e261d278eacd9d7a0c582c9911fd537008 Mon Sep 17 00:00:00 2001 From: Martin Staley Date: Wed, 15 Dec 2021 23:44:20 -0700 Subject: [PATCH 25/39] Name change. --- src/GNDStk/HDF5.hpp | 8 ++++---- src/GNDStk/HDF5/src/assign.hpp | 4 ++-- src/GNDStk/HDF5/src/ctor.hpp | 4 ++-- src/GNDStk/HDF5/src/read.hpp | 4 ++-- src/GNDStk/HDF5/src/write.hpp | 8 ++++---- src/GNDStk/convert/src/HDF5.hpp | 8 ++++---- 6 files changed, 18 insertions(+), 18 deletions(-) diff --git a/src/GNDStk/HDF5.hpp b/src/GNDStk/HDF5.hpp index 92a50ec30..62dcacb2f 100644 --- a/src/GNDStk/HDF5.hpp +++ b/src/GNDStk/HDF5.hpp @@ -9,7 +9,7 @@ class HDF5 { // data HighFive::File *filePtr = nullptr; - std::string filename = ""; + std::string fileName = ""; int fileDesc = 0; // file modes @@ -56,12 +56,12 @@ class HDF5 { if (fileDesc > 0) { close(fileDesc); - if (filename != "") // should be, if (fileDesc > 0) - unlink(filename.data()); + if (fileName != "") // should be, if (fileDesc > 0) + unlink(fileName.data()); } fileDesc = 0; - filename = ""; + fileName = ""; delete filePtr; filePtr = nullptr; diff --git a/src/GNDStk/HDF5/src/assign.hpp b/src/GNDStk/HDF5/src/assign.hpp index 39945c92d..1fc148fa7 100644 --- a/src/GNDStk/HDF5/src/assign.hpp +++ b/src/GNDStk/HDF5/src/assign.hpp @@ -9,11 +9,11 @@ HDF5 &operator=(HDF5 &&other) clear(); filePtr = std::move(other.filePtr); - filename = std::move(other.filename); + fileName = std::move(other.fileName); fileDesc = std::move(other.fileDesc); other.filePtr = nullptr; - other.filename = ""; + other.fileName = ""; other.fileDesc = 0; return *this; diff --git a/src/GNDStk/HDF5/src/ctor.hpp b/src/GNDStk/HDF5/src/ctor.hpp index 80391b1e4..f2fd7494d 100644 --- a/src/GNDStk/HDF5/src/ctor.hpp +++ b/src/GNDStk/HDF5/src/ctor.hpp @@ -13,11 +13,11 @@ HDF5() { } // move HDF5(HDF5 &&other) : filePtr (std::move(other.filePtr )), - filename(std::move(other.filename)), + fileName(std::move(other.fileName)), fileDesc(std::move(other.fileDesc)) { other.filePtr = nullptr; - other.filename = ""; + other.fileName = ""; other.fileDesc = 0; } diff --git a/src/GNDStk/HDF5/src/read.hpp b/src/GNDStk/HDF5/src/read.hpp index 58ffe462d..0f23c6e26 100644 --- a/src/GNDStk/HDF5/src/read.hpp +++ b/src/GNDStk/HDF5/src/read.hpp @@ -51,7 +51,7 @@ std::istream &read(std::istream &is) ofs.close(); try { filePtr = new HighFive::File(name,modeRead); - filename = name; + fileName = name; fileDesc = desc; is.clear(std::ios_base::eofbit); // as expected return is; @@ -84,7 +84,7 @@ bool read(const std::string name) ifs.close(); try { filePtr = new HighFive::File(name,modeRead); - filename = name; + fileName = name; return true; } catch (...) { log::error("Call 'new HighFive::File(\"{}\",ReadOnly)' " diff --git a/src/GNDStk/HDF5/src/write.hpp b/src/GNDStk/HDF5/src/write.hpp index 19a10cfa3..7f6df7c94 100644 --- a/src/GNDStk/HDF5/src/write.hpp +++ b/src/GNDStk/HDF5/src/write.hpp @@ -58,10 +58,10 @@ std::ostream &write(std::ostream &os, const bool decl = true) const // to copying bytes from *filePtr's file to the ostream. filePtr->flush(); - std::ifstream ifs(filename, std::ios::binary); + std::ifstream ifs(fileName, std::ios::binary); if (!ifs) { log::error("Could not open file \"{}\" " - "for writing to ostream", filename); + "for writing to ostream", fileName); throw std::exception{}; } @@ -76,7 +76,7 @@ std::ostream &write(std::ostream &os, const bool decl = true) const if (!good) { log::error( "Error writing file \"{}\"'s contents to ostream", - filename); + fileName); throw std::exception{}; } } @@ -98,7 +98,7 @@ std::ostream &write(std::ostream &os, const bool decl = true) const bool write(const std::string &name, const bool decl = true) const { // Well, I suppose it's possible... - if (!empty() && name == filename) { + if (!empty() && name == fileName) { filePtr->flush(); return true; } diff --git a/src/GNDStk/convert/src/HDF5.hpp b/src/GNDStk/convert/src/HDF5.hpp index 246218102..2ca422dfa 100644 --- a/src/GNDStk/convert/src/HDF5.hpp +++ b/src/GNDStk/convert/src/HDF5.hpp @@ -14,10 +14,10 @@ inline bool convert(const Node &node, HDF5 &h, const std::string &name) // Prepare the HDF5 h.clear(); - h.filename = name != "" ? name : h.temporaryName(h.fileDesc); + h.fileName = name != "" ? name : h.temporaryName(h.fileDesc); try { - h.filePtr = new HighFive::File(h.filename, HDF5::modeWrite); + h.filePtr = new HighFive::File(h.fileName, HDF5::modeWrite); // Probably a regular Node... if (node.name != "") { @@ -162,9 +162,9 @@ inline bool convert(const HDF5 &from, HDF5 &to) // convert try { - std::ifstream ifs(from.filename, std::ios::binary); + std::ifstream ifs(from.fileName, std::ios::binary); if (!ifs) { - log::error("Could not open file \"{}\"", from.filename); + log::error("Could not open file \"{}\"", from.fileName); throw std::exception{}; } if (!to.read(ifs)) From 1debaa6f4ca9c9b60edf01320c7c2b45fb0e6582 Mon Sep 17 00:00:00 2001 From: Martin Staley Date: Fri, 17 Dec 2021 21:40:39 -0700 Subject: [PATCH 26/39] Terminology change re: body text. A while back, I renamed class BodyText to class BlockData. It turns out that the "body [text]" terminology still appeared here and there. This PR basically completes the terminology change. I renamed relevant constructs, and removed "body" terminology at least in regards to block data. --- autogen/json2class.cpp | 2 +- src/GNDStk/BlockData.hpp | 36 +++--- src/GNDStk/BlockData/src/assign.hpp | 4 +- src/GNDStk/BlockData/src/colors.hpp | 2 +- src/GNDStk/BlockData/src/fromNode.hpp | 14 +-- src/GNDStk/BlockData/src/get.hpp | 105 +++++++++--------- src/GNDStk/BlockData/src/params.hpp | 4 +- src/GNDStk/BlockData/src/toNode.hpp | 8 +- src/GNDStk/BlockData/test/BlockData.test.cpp | 8 +- src/GNDStk/BlockData/test/assign.test.cpp | 8 +- src/GNDStk/BlockData/test/fromNode.test.cpp | 16 +-- src/GNDStk/BlockData/test/get.test.cpp | 40 +++---- src/GNDStk/BlockData/test/params.test.cpp | 32 +++--- src/GNDStk/BlockData/test/string.test.cpp | 12 +- src/GNDStk/BlockData/test/sync.test.cpp | 44 ++++---- src/GNDStk/BlockData/test/toNode.test.cpp | 4 +- src/GNDStk/BlockData/test/write.test.cpp | 24 ++-- src/GNDStk/Component.hpp | 22 ++-- src/GNDStk/Component/src/ctor.hpp | 2 +- src/GNDStk/Component/src/detail.hpp | 2 +- src/GNDStk/Component/src/finish.hpp | 22 ++-- src/GNDStk/Component/src/fromNode.hpp | 4 +- src/GNDStk/Component/src/toNode.hpp | 6 +- .../src/{toNodeBody.hpp => toNodeData.hpp} | 4 +- src/GNDStk/Component/src/write.hpp | 2 +- src/GNDStk/Component/test/finish.test.cpp | 13 ++- src/GNDStk/Component/test/fromNode.test.cpp | 12 +- src/GNDStk/precision.hpp | 2 +- src/GNDStk/precision/src/detail.hpp | 2 +- src/GNDStk/precision/test/precision.test.cpp | 6 +- src/GNDStk/precision/test/precision.test.hpp | 8 +- src/GNDStk/v1.9/containers/Values.hpp | 2 +- 32 files changed, 237 insertions(+), 235 deletions(-) rename src/GNDStk/Component/src/{toNodeBody.hpp => toNodeData.hpp} (94%) diff --git a/autogen/json2class.cpp b/autogen/json2class.cpp index d2c44ddce..f70a84192 100644 --- a/autogen/json2class.cpp +++ b/autogen/json2class.cpp @@ -1375,7 +1375,7 @@ void writeClassCtors(writer &out, const PerClass &per) out(); out(1,"// from vector"); out(1,"template>>"); + "std::enable_if_t>>"); out(1,"@(const std::vector &vector) :", per.clname); writeClassCtorComponent(out, per, false); out(); diff --git a/src/GNDStk/BlockData.hpp b/src/GNDStk/BlockData.hpp index e32f31da8..6227ca216 100644 --- a/src/GNDStk/BlockData.hpp +++ b/src/GNDStk/BlockData.hpp @@ -9,12 +9,12 @@ // ----------------------------------------------------------------------------- -// BlockData -// The case is specialized and has the fun stuff. This one needs +// BlockData +// The case is specialized and has the fun stuff. This one needs // just a bit of content, in order to facilitate uniform treatment of BlockData. // ----------------------------------------------------------------------------- -template +template class BlockData { public: using VariantOfVectors = std::variant; @@ -26,32 +26,32 @@ class BlockData { // ----------------------------------------------------------------------------- -// BlockData +// BlockData // // Designed to be flexible, smart, and safe. Does lots of checks, and, for the -// DATA == void case, can essentially re-form itself depending on what type of -// data someone tries to extract. +// DATATYPE == void case, can essentially re-form itself depending on what type +// of data someone tries to extract. // -// For efficiency in the DATA == void case, an application might want to copy +// For efficiency in the DATATYPE == void case, an application may want to copy // to its own vector (e.g. auto myvec = myblockdata.get>()) // in order to do work on (or with) the vector there, before copying it back. // ----------------------------------------------------------------------------- -template -class BlockData { +template +class BlockData { public: #include "GNDStk/BlockData/src/types.hpp" // For convenience in various SFINAE and if-constexpr constructs - static inline constexpr bool runtime = detail::isVoid; + static inline constexpr bool runtime = detail::isVoid; template struct is_supported { static inline constexpr bool value = ( runtime && detail::isAlternative) || (!runtime && ( - std::is_constructible_v || - std::is_convertible_v + std::is_constructible_v || + std::is_convertible_v )); }; template @@ -71,15 +71,15 @@ class BlockData { // Vector of . // Mutable, so that we can defer processing of the raw string into // a vector until, and unless, a caller *asks* for the vector. - // This will be used if, and only if, DATA == void. + // This will be used if, and only if, DATATYPE == void. mutable VariantOfVectors variant; - // Vector of - // This will be used if, and only if, DATA != void. + // Vector of + // This will be used if, and only if, DATATYPE != void. // data_t is used in a few places where, without it, we'd create compilation // errors by using "void" in invalid ways. The "int" below is arbitrary - // essentially a placeholder; the following is only used when !runtime. - using data_t = std::conditional_t; + using data_t = std::conditional_t; mutable std::vector vector; public: @@ -87,7 +87,7 @@ class BlockData { // Parameters that affect interpretation of the raw string: // struct vars { length, start, valueType } // Includes public getters and setters for those. - // We won't use valueType if DATA != void. + // We won't use valueType if DATATYPE != void. #include "GNDStk/BlockData/src/params.hpp" // trim @@ -145,4 +145,4 @@ class BlockData { // From string or vector; the former == calling our raw string setter #include "GNDStk/BlockData/src/assign.hpp" -}; // class BlockData +}; // class BlockData diff --git a/src/GNDStk/BlockData/src/assign.hpp b/src/GNDStk/BlockData/src/assign.hpp index e7e9b5a7c..a64598e18 100644 --- a/src/GNDStk/BlockData/src/assign.hpp +++ b/src/GNDStk/BlockData/src/assign.hpp @@ -61,13 +61,13 @@ operator=(const std::vector &vec) // assign vector if constexpr (runtime) variant = vec; - else if constexpr (std::is_same_v) + else if constexpr (std::is_same_v) vector = vec; else { vector.clear(); vector.reserve(vec.size()); for (const T &element : vec) - vector.push_back(DATA(element)); + vector.push_back(DATATYPE(element)); } act = Active::vector; diff --git a/src/GNDStk/BlockData/src/colors.hpp b/src/GNDStk/BlockData/src/colors.hpp index f8850fde7..0f0c0affb 100644 --- a/src/GNDStk/BlockData/src/colors.hpp +++ b/src/GNDStk/BlockData/src/colors.hpp @@ -80,7 +80,7 @@ inline std::string bracket = plain::yellow; inline std::string optional = plain::cyan; inline std::string defaulted = plain::blue; -// Values in nodes with "body text" +// Values in nodes with block data inline std::string value = plain::white; // Comments diff --git a/src/GNDStk/BlockData/src/fromNode.hpp b/src/GNDStk/BlockData/src/fromNode.hpp index 0c7366d80..d23d9b5c0 100644 --- a/src/GNDStk/BlockData/src/fromNode.hpp +++ b/src/GNDStk/BlockData/src/fromNode.hpp @@ -18,14 +18,14 @@ void fromNode(const Node &node) if (!found) { rawstring = ""; - // Warning, re: why are we in BlockData if there's no body text? - // Perhaps it's possible that the Node has a non-default length and/or - // start, so that the values are all supposed to be...zero. Until and - // unless we discover otherwise, however, we doubt that that would be - // the case, and will consider a Node's lack of plain character data, - // in the present context, to be something that merits a warning. + // Warning, re: why are we in BlockData if there's no block + // data? Perhaps the Node has a non-default length and/or start, so that + // the values are all supposed to be...zero. Until and unless we discover + // otherwise, however, we doubt that that would be the case, and will + // consider a Node's lack of plain character data, in the present context, + // to be something that merits a warning. log::warning( - "Component marked as having \"body text\", a.k.a. XML \"pcdata\" " + "Component marked as having block data, a.k.a. XML \"pcdata\" " "(plain\ncharacter data), " "but no such content was found in the GNDS node." ); diff --git a/src/GNDStk/BlockData/src/get.hpp b/src/GNDStk/BlockData/src/get.hpp index 11c522bb2..2b41893e8 100644 --- a/src/GNDStk/BlockData/src/get.hpp +++ b/src/GNDStk/BlockData/src/get.hpp @@ -5,7 +5,7 @@ /* ------------------------ -When DATA == void +When DATATYPE == void ------------------------ Case 1 @@ -42,28 +42,28 @@ Type-specific getters with specific names: For example, name == doubles when T == double. ------------------------ -When DATA != void +When DATATYPE != void ------------------------ Case 1 Return reference to [const] vector: get> const get> -T must == DATA. +T must == DATATYPE. Case 2 Return reference to [const] T: get(n) const get(n) -T must == DATA. +T must == DATATYPE. Case 3 -Return reference to [const] vector +Return reference to [const] vector get() const get() Case 4 -Return reference to [const] DATA: +Return reference to [const] DATATYPE: get(n) const operator[](n) const get(n) @@ -71,13 +71,14 @@ Return reference to [const] DATA: Case 5 Type-specific getters with a specific name: - const std::vector &name() const - std::vector &name() - const DATA &name(n) const - DATA &name(n) -For example, name == doubles if DATA == double. Unlike in the DATA == void case, -we won't have this set of functions for each of name == doubles, name == ints, -name == strings, etc., but only for the name that's appropriate for type DATA. + const std::vector &name() const + std::vector &name() + const DATATYPE &name(n) const + DATATYPE &name(n) +For example, name == doubles if DATATYPE == double. Unlike in the DATATYPE == +void case, we won't have this set of functions for each of name == doubles, +name == ints, name == strings, etc., but only for the name that's appropriate +for type DATATYPE. */ @@ -154,7 +155,7 @@ Of course we also have a non-const version, for a non-const *this. template std::enable_if_t< ( runtime && detail::isAlternative) || - (!runtime && std::is_same_v>), + (!runtime && std::is_same_v>), const VECTOR & > get() const { @@ -262,7 +263,7 @@ std::enable_if_t< // wants a vector. // // BlockData is intended to store just one vector - one that represents - // values in a GNDS node that has "body text." We don't, and shouldn't, + // values in a GNDS node that has block data. We don't, and shouldn't, // try to juggle multiple vectors of different types. Therefore, we'll // attempt to convert the existing vector to one of the requested type, // then place the new vector into the variant (replacing the old one.) @@ -308,7 +309,7 @@ std::enable_if_t< template std::enable_if_t< ( runtime && detail::isAlternative) || - (!runtime && std::is_same_v>), + (!runtime && std::is_same_v>), VECTOR & > get() { @@ -321,18 +322,18 @@ std::enable_if_t< // 2. get(n) // ----------------------------------------------------------------------------- -// For DATA == void (so that we have a variants>): +// For DATATYPE == void (so that we have a variants>): // These trigger a complete rebuild of the vector, if it isn't already of type // vector for the given T. This is intentional, in order to provide maximum // flexibility. However, be aware of it, for the sake of efficiency! In general, // when using a BlockData object, we recommend sticking with one underlying type. -// For DATA != void (so that we have a vector): -// T == DATA is required, so that returning an element of the vector will -// return a reference to T. (A constructibility/convertibility requirement that -// we have in other BlockData-related code thus needs to be more stringent here. -// We can't just be able to make a T from a DATA. Those must in fact be the same -// type, because we return a reference.) +// For DATATYPE != void (so that we have a vector): +// T == DATATYPE is required, so that returning an element of the +// vector will return a reference to T. (A constructibility/ +// convertibility requirement that we have in other BlockData-related code thus +// needs to be more stringent here. We can't just be able to make a T from a +// DATATYPE. They must in fact be the same type, because we return a reference.) // For both of the above cases: // If the string (not the variant or the vector) is active, then a rebuild from @@ -341,7 +342,7 @@ std::enable_if_t< // const template std::enable_if_t< - supported && (runtime || std::is_same_v), + supported && (runtime || std::is_same_v), const T & > get(const std::size_t n) const @@ -357,7 +358,7 @@ get(const std::size_t n) const // non-const template std::enable_if_t< - supported && (runtime || std::is_same_v), + supported && (runtime || std::is_same_v), T & > get(const std::size_t n) @@ -369,15 +370,15 @@ get(const std::size_t n) // ----------------------------------------------------------------------------- // 3. get() -// If DATA == void, returns a variants>. -// If DATA != void, returns a vector<>. +// If DATATYPE == void, returns a variants>. +// If DATATYPE != void, returns a vector<>. // ----------------------------------------------------------------------------- // const std::conditional_t< runtime, const VariantOfVectors &, - const std::vector & + const std::vector & > get() const { if constexpr (runtime) { @@ -395,7 +396,7 @@ std::conditional_t< return variant; } else { // Simpler, but we do still need a get (in case the *string* is active). - get>(); + get>(); return vector; } } @@ -404,14 +405,14 @@ std::conditional_t< std::conditional_t< runtime, VariantOfVectors &, - std::vector & + std::vector & > get() { return const_cast< std::conditional_t< runtime, VariantOfVectors &, - std::vector & + std::vector & > >(std::as_const(*this).get()); } @@ -421,11 +422,11 @@ std::conditional_t< // ----------------------------------------------------------------------------- // 4. get(n) // -// If DATA == void, returns a variant (by value, because the returned -// object must be made on-the-fly from our variants>). +// If DATATYPE == void, returns a variant (by value, because the +// returned object must be made on-the-fly from our variants>). // -// If DATA != void, returns a scalar of type [const] DATA (by reference, because -// it's available directly in our vector). +// If DATATYPE != void, returns a scalar of type [const] DATATYPE (by reference, +// because it's available directly in our vector). // ----------------------------------------------------------------------------- // ------------------------ @@ -470,24 +471,24 @@ std::conditional_t< // non-const // ------------------------ -// If DATA == void: +// If DATATYPE == void: // Not needed, because the const versions return by value. // -// If DATA != void: -// Meaningful, because returns are by reference in this (DATA != void) case. +// If DATATYPE != void: +// Meaningful, because returns are by reference in this (DATATYPE != void) case. // So, we'll enable non-const versions for this case only. -// In case anyone wonders, D (not just DATA) is needed below because SFINAE -// applies when template argument *deduction* is taking place. DATA is already -// fixed, by context - we're in BlockData - and thus it isn't being -// deduced here. Templating these (otherwise non-template) functions with an -// argument that defaults to DATA, then using that argument in the SFINAE, is -// a simple trick that makes the SFINAE work as intended. As for VOID, it's -// necessary in order for the following to be unambiguous with the template -// versions of get(n) that are defined elsewhere in this file. +// In case anyone wonders, D (not just DATATYPE) is needed below because SFINAE +// applies when template argument *deduction* is taking place. DATATYPE is +// already fixed, by context - we're in BlockData - and thus it +// isn't being deduced here. Templating these (otherwise non-template) functions +// with an argument that defaults to DATATYPE, then using that argument in the +// SFINAE, is a simple trick that makes the SFINAE work as intended. As for +// VOID, it's necessary in order for the following to be unambiguous with the +// template versions of get(n) that are defined elsewhere in this file. // get(n) -template +template std::enable_if_t && !detail::isVoid, data_t &> get(const std::size_t n) { @@ -501,7 +502,7 @@ get(const std::size_t n) } // operator[](n) -template +template std::enable_if_t, data_t &> operator[](const std::size_t n) { @@ -524,25 +525,25 @@ operator[](const std::size_t n) #define GNDSTK_MAKE_GETTER(name,TYPE) \ \ - template \ + template \ std::enable_if_t< \ detail::isVoid || \ std::is_same_v, const std::vector & \ > name() const { return get>(); } \ \ - template \ + template \ std::enable_if_t< \ detail::isVoid || \ std::is_same_v, std::vector & \ > name() { return get>(); } \ \ - template \ + template \ std::enable_if_t< \ detail::isVoid || \ std::is_same_v, const TYPE & \ > name(const std::size_t n) const { return get(n); } \ \ - template \ + template \ std::enable_if_t< \ detail::isVoid || \ std::is_same_v, TYPE & \ diff --git a/src/GNDStk/BlockData/src/params.hpp b/src/GNDStk/BlockData/src/params.hpp index ce542b125..1dd94685c 100644 --- a/src/GNDStk/BlockData/src/params.hpp +++ b/src/GNDStk/BlockData/src/params.hpp @@ -12,7 +12,7 @@ Quoted [slightly edited] from the official JSON specification files for GNDS: values that are not stored. This attribute should only be used when the sum of start and the number of listed values do not add to the total number of data values. This should only happen when there are - trailing zeros not listed in the body text. + trailing zeros not listed in the block data. start Default: 0 @@ -35,7 +35,7 @@ our GNDS Standard Interface code autogeneration tool produces. // consistent with vector data; so, mutable. mutable struct { // Any of these might or might not have appeared in a particular node that - // had body text. For uniformity, we have them all here, and with defaults. + // had block data. For uniformity, we have them all here, and with defaults. std::size_t length = 0; std::size_t start = 0; std::string valueType = ""; diff --git a/src/GNDStk/BlockData/src/toNode.hpp b/src/GNDStk/BlockData/src/toNode.hpp index 3b83e6455..a2cb60495 100644 --- a/src/GNDStk/BlockData/src/toNode.hpp +++ b/src/GNDStk/BlockData/src/toNode.hpp @@ -7,7 +7,7 @@ // ----------------------------------------------------------------------------- // Use either (1) the original raw string, or (2) the variant of vectors or the -// vector (depending on DATA ==/!= void), based on whether or not the string +// vector (depending on DATATYPE ==/!= void), based on whether or not the string // is active. length, start, and valueType might be computed too, in which case // they're also changed in the derived class in order to keep things consistent. template @@ -22,11 +22,11 @@ void toNode(std::string &text, DERIVED &derived) const // Use the vector... const bool isStringVector = ( runtime && std::holds_alternative>(variant)) || - (!runtime && std::is_same_v); + (!runtime && std::is_same_v); if constexpr ( runtime || - (!runtime && std::is_same_v) + (!runtime && std::is_same_v) ) { // the run-time if's get() calls below won't // necessarily make sense without the above if-constexpr @@ -59,7 +59,7 @@ void toNode(std::string &text, DERIVED &derived) const if constexpr (runtime) vars.valueType = detail::visitMapTypeString(variant); else - vars.valueType = detail::MapTypeString::value[0]; + vars.valueType = detail::MapTypeString::value[0]; pushToDerived(derived); // Values diff --git a/src/GNDStk/BlockData/test/BlockData.test.cpp b/src/GNDStk/BlockData/test/BlockData.test.cpp index e6ef42fa1..a2ff62c4a 100644 --- a/src/GNDStk/BlockData/test/BlockData.test.cpp +++ b/src/GNDStk/BlockData/test/BlockData.test.cpp @@ -8,10 +8,10 @@ using namespace njoy::GNDStk::core; // ----------------------------------------------------------------------------- -// Scenario for DATA == void +// Scenario for DATATYPE == void // ----------------------------------------------------------------------------- -SCENARIO("Testing GNDStk BlockData with DATA == void") { +SCENARIO("Testing GNDStk BlockData with DATATYPE == void") { // Most BlockData functionality is tested in the individual test files. // There are just a few things we'll do here. @@ -125,10 +125,10 @@ SCENARIO("Testing GNDStk BlockData with DATA == void") { // ----------------------------------------------------------------------------- -// Scenario for DATA != void +// Scenario for DATATYPE != void // ----------------------------------------------------------------------------- -SCENARIO("Testing GNDStk BlockData with DATA != void") { +SCENARIO("Testing GNDStk BlockData with DATATYPE != void") { GIVEN("A const BlockData cbtextt") { const BlockData cbtextt; diff --git a/src/GNDStk/BlockData/test/assign.test.cpp b/src/GNDStk/BlockData/test/assign.test.cpp index b4ca50da0..14bba69d0 100644 --- a/src/GNDStk/BlockData/test/assign.test.cpp +++ b/src/GNDStk/BlockData/test/assign.test.cpp @@ -6,10 +6,10 @@ using namespace njoy::GNDStk::core; // ----------------------------------------------------------------------------- -// Scenario for DATA == void +// Scenario for DATATYPE == void // ----------------------------------------------------------------------------- -SCENARIO("BlockData assignment operators") { +SCENARIO("BlockData assignment operators") { GIVEN("A default-constructed BlockData object") { // Default value of raw string is as expected @@ -111,10 +111,10 @@ SCENARIO("BlockData assignment operators") { // ----------------------------------------------------------------------------- -// Scenario for DATA != void +// Scenario for DATATYPE != void // ----------------------------------------------------------------------------- -SCENARIO("BlockData assignment operators") { +SCENARIO("BlockData assignment operators") { GIVEN("A default-constructed BlockData object") { // Default value of raw string is as expected diff --git a/src/GNDStk/BlockData/test/fromNode.test.cpp b/src/GNDStk/BlockData/test/fromNode.test.cpp index 5893cb3d5..9fbfacb73 100644 --- a/src/GNDStk/BlockData/test/fromNode.test.cpp +++ b/src/GNDStk/BlockData/test/fromNode.test.cpp @@ -6,12 +6,12 @@ using namespace njoy::GNDStk::core; // ----------------------------------------------------------------------------- -// Scenario for DATA == void +// Scenario for DATATYPE == void // ----------------------------------------------------------------------------- -SCENARIO("BlockData fromNode()") { +SCENARIO("BlockData fromNode()") { - GIVEN("A Node with no \"body text\"") { + GIVEN("A Node with no \"block data\"") { WHEN("BlockData.fromNode(the node) is called") { THEN("The BlockData's raw string is \"\", as expected") { BlockData b; @@ -26,7 +26,7 @@ SCENARIO("BlockData fromNode()") { } } - GIVEN("A Node with some \"body text\"") { + GIVEN("A Node with some \"block data\"") { WHEN("BlockData.fromNode(the node) is called") { THEN("The BlockData's raw string equals the text from the Node") { BlockData b; @@ -61,12 +61,12 @@ SCENARIO("BlockData fromNode()") { // ----------------------------------------------------------------------------- -// Scenario for DATA != void +// Scenario for DATATYPE != void // ----------------------------------------------------------------------------- -SCENARIO("BlockData fromNode()") { +SCENARIO("BlockData fromNode()") { - GIVEN("A Node with no \"body text\"") { + GIVEN("A Node with no \"block data\"") { WHEN("BlockData.fromNode(the node) is called") { THEN("The BlockData's raw string is \"\", as expected") { BlockData b; @@ -81,7 +81,7 @@ SCENARIO("BlockData fromNode()") { } } - GIVEN("A Node with some \"body text\"") { + GIVEN("A Node with some \"block data\"") { WHEN("BlockData.fromNode(the node) is called") { THEN("The BlockData's raw string equals the text from the Node") { BlockData b; diff --git a/src/GNDStk/BlockData/test/get.test.cpp b/src/GNDStk/BlockData/test/get.test.cpp index cc029fd23..ea9a430ff 100644 --- a/src/GNDStk/BlockData/test/get.test.cpp +++ b/src/GNDStk/BlockData/test/get.test.cpp @@ -165,15 +165,15 @@ void scenario_get_vector() CHECK((b.template get() == uvec{{0,0,12,34,56,0}})); } } -// For BlockData -SCENARIO("BlockData get()") { +// For BlockData +SCENARIO("BlockData get()") { GIVEN("A BlockData object") { scenario_get_vector(); } } -// For BlockData -SCENARIO("BlockData get()") { +// For BlockData +SCENARIO("BlockData get()") { GIVEN("A BlockData object") { scenario_get_vector(); } @@ -322,15 +322,15 @@ void scenario_get_template_n() CHECK(b.template get(3) == 34); } } -// For BlockData -SCENARIO("BlockData get(n)") { +// For BlockData +SCENARIO("BlockData get(n)") { GIVEN("A BlockData object") { scenario_get_template_n(); } } -// For BlockData -SCENARIO("BlockData get(n)") { +// For BlockData +SCENARIO("BlockData get(n)") { GIVEN("A BlockData object") { scenario_get_template_n(); } @@ -342,8 +342,8 @@ SCENARIO("BlockData get(n)") { // 3. Scenario: get() // ----------------------------------------------------------------------------- -// For BlockData -SCENARIO("BlockData get()") { +// For BlockData +SCENARIO("BlockData get()") { GIVEN("A BlockData object") { using ivec = std::vector; @@ -377,8 +377,8 @@ SCENARIO("BlockData get()") { } // SCENARIO -// For BlockData -SCENARIO("BlockData get()") { +// For BlockData +SCENARIO("BlockData get()") { GIVEN("A BlockData object") { using ivec = std::vector; @@ -412,8 +412,8 @@ SCENARIO("BlockData get()") { // 4. Scenario: get(n) // ----------------------------------------------------------------------------- -// For BlockData -SCENARIO("BlockData get(n)") { +// For BlockData +SCENARIO("BlockData get(n)") { GIVEN("A BlockData object") { BlockData b; @@ -514,8 +514,8 @@ SCENARIO("BlockData get(n)") { } // SCENARIO -// For BlockData -SCENARIO("BlockData get(n)") { +// For BlockData +SCENARIO("BlockData get(n)") { GIVEN("A BlockData object") { // ------------------------ @@ -678,15 +678,15 @@ void scenario_get_named() } } -// For BlockData -SCENARIO("BlockData type-specific get functions: doubles() etc.") { +// For BlockData +SCENARIO("BlockData type-specific get functions: doubles() etc.") { GIVEN("A BlockData object") { scenario_get_named(); } } -// For BlockData -SCENARIO("BlockData type-specific get functions: doubles() etc.") { +// For BlockData +SCENARIO("BlockData type-specific get functions: doubles() etc.") { GIVEN("A BlockData object") { scenario_get_named(); } diff --git a/src/GNDStk/BlockData/test/params.test.cpp b/src/GNDStk/BlockData/test/params.test.cpp index e7c853f1f..6fae3e1c6 100644 --- a/src/GNDStk/BlockData/test/params.test.cpp +++ b/src/GNDStk/BlockData/test/params.test.cpp @@ -9,13 +9,13 @@ using namespace njoy::GNDStk::core; // Helper // ----------------------------------------------------------------------------- -template +template void scenario_params() { // Default values of parameters are as expected WHEN("We examine the default length, start, and valueType") { THEN("They are as expected") { - BlockData b; + BlockData b; CHECK(b.length() == 0); CHECK(b.start() == 0); CHECK(b.valueType() == ""); @@ -25,17 +25,17 @@ void scenario_params() // length setter/getter works WHEN("We set length, then get and verify") { THEN("It works for a plain value") { - BlockData b; + BlockData b; b.length(12); CHECK(b.length() == 12); } THEN("It works for optional-with-value") { - BlockData b; + BlockData b; b.length(std::optional(34)); CHECK(b.length() == 34); } THEN("It works for optional-without-value (remains unchanged)") { - BlockData b; + BlockData b; b.length(56); b.length(std::optional(std::nullopt)); CHECK(b.length() == 56); @@ -45,17 +45,17 @@ void scenario_params() // start setter/getter works WHEN("We set start, then get and verify") { THEN("It works for a plain value") { - BlockData b; + BlockData b; b.start(11); CHECK(b.start() == 11); } THEN("It works for optional-with-value") { - BlockData b; + BlockData b; b.start(std::optional(13)); CHECK(b.start() == 13); } THEN("It works for optional-without-value (remains unchanged)") { - BlockData b; + BlockData b; b.start(17); b.start(std::optional(std::nullopt)); CHECK(b.start() == 17); @@ -65,17 +65,17 @@ void scenario_params() // valueType setter/getter works WHEN("We set valueType, then get and verify") { THEN("It works for a plain value") { - BlockData b; + BlockData b; b.valueType("unknown"); CHECK(b.valueType() == "unknown"); } THEN("It works for optional-with-value") { - BlockData b; + BlockData b; b.valueType(std::optional("Integer32")); CHECK(b.valueType() == "Integer32"); } THEN("It works for optional-without-value (remains unchanged)") { - BlockData b; + BlockData b; b.valueType("Float64"); b.valueType(std::optional(std::nullopt)); CHECK(b.valueType() == "Float64"); @@ -85,7 +85,7 @@ void scenario_params() // Combo of the above, using builder-pattern nature of the setters WHEN("We set length/start/valueType together, then get and verify") { THEN("It works for a plain value") { - BlockData b; + BlockData b; b.length(1) .start(2) .valueType("a"); @@ -94,7 +94,7 @@ void scenario_params() CHECK(b.valueType() == "a"); } THEN("It works for optional-with-value") { - BlockData b; + BlockData b; b.length(std::optional(3)) .start(std::optional(4)) .valueType(std::optional("b")); @@ -103,7 +103,7 @@ void scenario_params() CHECK(b.valueType() == "b"); } THEN("It works for optional-without-value (remains unchanged)") { - BlockData b; + BlockData b; b.length(100).start(200).valueType("c"); b.length(std::optional(std::nullopt)) .start(std::optional(std::nullopt)) @@ -120,13 +120,13 @@ void scenario_params() // Scenarios // ----------------------------------------------------------------------------- -SCENARIO("BlockData length/start/valueType") { +SCENARIO("BlockData length/start/valueType") { GIVEN("A default-constructed BlockData object") { scenario_params(); } } -SCENARIO("BlockData length/start/valueType") { +SCENARIO("BlockData length/start/valueType") { GIVEN("A default-constructed BlockData object") { scenario_params(); } diff --git a/src/GNDStk/BlockData/test/string.test.cpp b/src/GNDStk/BlockData/test/string.test.cpp index 7fa8b830a..02e3b08d5 100644 --- a/src/GNDStk/BlockData/test/string.test.cpp +++ b/src/GNDStk/BlockData/test/string.test.cpp @@ -9,13 +9,13 @@ using namespace njoy::GNDStk::core; // Helper // ----------------------------------------------------------------------------- -template +template void scenario_string() { // Default value of raw string is as expected WHEN("We examine the raw string") { THEN("It is as expected") { - BlockData b; + BlockData b; CHECK(b.string() == ""); } } @@ -23,7 +23,7 @@ void scenario_string() // Raw string setter/getter works WHEN("We set the raw string") { THEN("It has the correct value, and vector size() == 0 too") { - BlockData b; + BlockData b; // to ensure it clears below... b = std::vector(10); @@ -40,7 +40,7 @@ void scenario_string() // Test in conjunction with length, start, and valueType WHEN("We set string, length, start, and valueType together") { THEN("All values check out") { - BlockData b; + BlockData b; b.string("3 4 5 6").length(10).start(2).valueType("Integer32"); CHECK(b.length() == 10); @@ -56,13 +56,13 @@ void scenario_string() // Scenarios // ----------------------------------------------------------------------------- -SCENARIO("BlockData string()") { +SCENARIO("BlockData string()") { GIVEN("A default-constructed BlockData object") { scenario_string(); } } -SCENARIO("BlockData string()") { +SCENARIO("BlockData string()") { GIVEN("A default-constructed BlockData object") { scenario_string(); } diff --git a/src/GNDStk/BlockData/test/sync.test.cpp b/src/GNDStk/BlockData/test/sync.test.cpp index ee3fae38c..54e723016 100644 --- a/src/GNDStk/BlockData/test/sync.test.cpp +++ b/src/GNDStk/BlockData/test/sync.test.cpp @@ -11,7 +11,7 @@ using namespace njoy::GNDStk::core; // ----------------------------------------------------------------------------- // Helper -template +template void scenario_pull() { WHEN("pullFromDerived() is called") { @@ -21,7 +21,7 @@ void scenario_pull() struct { } content; } derived; - BlockData b; + BlockData b; b.length(100).start(200).valueType("300"); b.pullFromDerived(derived); // should do nothing here CHECK(b.length() == 100); @@ -36,7 +36,7 @@ void scenario_pull() int length = 10; } content; } derived; - BlockData b; + BlockData b; b.length(11).start(12).valueType("13"); b.pullFromDerived(derived); CHECK(b.length() == 10); @@ -51,7 +51,7 @@ void scenario_pull() int start = 14; } content; } derived; - BlockData b; + BlockData b; b.length(15).start(16).valueType("17"); b.pullFromDerived(derived); CHECK(b.length() == 15); @@ -66,7 +66,7 @@ void scenario_pull() std::string valueType = "18"; } content; } derived; - BlockData b; + BlockData b; b.length(19).start(20).valueType("21"); b.pullFromDerived(derived); CHECK(b.length() == 19); @@ -82,7 +82,7 @@ void scenario_pull() std::string valueType = "23"; } content; } derived; - BlockData b; + BlockData b; b.length(24).start(25).valueType("26"); b.pullFromDerived(derived); CHECK(b.length() == 24); @@ -98,7 +98,7 @@ void scenario_pull() std::string valueType = "28"; } content; } derived; - BlockData b; + BlockData b; b.length(29).start(30).valueType("31"); b.pullFromDerived(derived); CHECK(b.length() == 27); @@ -114,7 +114,7 @@ void scenario_pull() int start = 33; } content; } derived; - BlockData b; + BlockData b; b.length(34).start(35).valueType("36"); b.pullFromDerived(derived); CHECK(b.length() == 32); @@ -131,7 +131,7 @@ void scenario_pull() std::string valueType = "39"; } content; } derived; - BlockData b; + BlockData b; b.length(40).start(41).valueType("42"); b.pullFromDerived(derived); CHECK(b.length() == 37); @@ -142,13 +142,13 @@ void scenario_pull() } -SCENARIO("BlockData pull from content") { +SCENARIO("BlockData pull from content") { GIVEN("A BlockData object") { scenario_pull(); } } -SCENARIO("BlockData pull from content") { +SCENARIO("BlockData pull from content") { GIVEN("A BlockData object") { scenario_pull(); } @@ -161,7 +161,7 @@ SCENARIO("BlockData pull from content") { // ----------------------------------------------------------------------------- // Helper -template +template void scenario_push() { WHEN("pushToDerived() is called") { @@ -172,7 +172,7 @@ void scenario_push() int ignored = 123456; // not length, start, or valueType } content; } derived; - BlockData b; + BlockData b; b.length(0).start(0).valueType("0"); b.pushToDerived(derived); // should do nothing here CHECK(derived.content.ignored == 123456); @@ -185,7 +185,7 @@ void scenario_push() int length = 10; } content; } derived; - BlockData b; + BlockData b; b.length(11).start(12).valueType("13"); b.pushToDerived(derived); CHECK(derived.content.length == 11); @@ -198,7 +198,7 @@ void scenario_push() int start = 14; } content; } derived; - BlockData b; + BlockData b; b.length(15).start(16).valueType("17"); b.pushToDerived(derived); CHECK(derived.content.start == 16); @@ -211,7 +211,7 @@ void scenario_push() std::string valueType = "18"; } content; } derived; - BlockData b; + BlockData b; b.length(19).start(20).valueType("21"); b.pushToDerived(derived); CHECK(derived.content.valueType == "21"); @@ -225,7 +225,7 @@ void scenario_push() std::string valueType = "23"; } content; } derived; - BlockData b; + BlockData b; b.length(24).start(25).valueType("26"); b.pushToDerived(derived); CHECK(derived.content.start == 25); @@ -240,7 +240,7 @@ void scenario_push() std::string valueType = "28"; } content; } derived; - BlockData b; + BlockData b; b.length(29).start(30).valueType("31"); b.pushToDerived(derived); CHECK(derived.content.length == 29); @@ -255,7 +255,7 @@ void scenario_push() int start = 33; } content; } derived; - BlockData b; + BlockData b; b.length(34).start(35).valueType("36"); b.pushToDerived(derived); CHECK(derived.content.length == 34); @@ -271,7 +271,7 @@ void scenario_push() std::string valueType = "39"; } content; } derived; - BlockData b; + BlockData b; b.length(40).start(41).valueType("42"); b.pushToDerived(derived); CHECK(derived.content.length == 40); @@ -282,13 +282,13 @@ void scenario_push() } -SCENARIO("BlockData push to content") { +SCENARIO("BlockData push to content") { GIVEN("A BlockData object") { scenario_push(); } } -SCENARIO("BlockData push to content") { +SCENARIO("BlockData push to content") { GIVEN("A BlockData object") { scenario_push(); } diff --git a/src/GNDStk/BlockData/test/toNode.test.cpp b/src/GNDStk/BlockData/test/toNode.test.cpp index 192945167..bcd6e1b8a 100644 --- a/src/GNDStk/BlockData/test/toNode.test.cpp +++ b/src/GNDStk/BlockData/test/toNode.test.cpp @@ -358,10 +358,10 @@ void scenario_toNode() // Scenario // ----------------------------------------------------------------------------- -SCENARIO("BlockData toNode()") { +SCENARIO("BlockData toNode()") { scenario_toNode(); } -SCENARIO("BlockData toNode()") { +SCENARIO("BlockData toNode()") { scenario_toNode(); } diff --git a/src/GNDStk/BlockData/test/write.test.cpp b/src/GNDStk/BlockData/test/write.test.cpp index 76658b947..14f773a39 100644 --- a/src/GNDStk/BlockData/test/write.test.cpp +++ b/src/GNDStk/BlockData/test/write.test.cpp @@ -10,13 +10,13 @@ using namespace njoy::GNDStk::core; // ----------------------------------------------------------------------------- // Helper -template +template void scenario_write_string_active() { GIVEN("A BlockData with an empty raw string") { WHEN("BlockData.write() is called") { THEN("Nothing is printed") { - BlockData b; + BlockData b; b = std::vector{{'a','b','c'}}; b.string(""); // should make string (not vector) active std::ostringstream oss; @@ -33,7 +33,7 @@ void scenario_write_string_active() GIVEN("A BlockData with a non-empty raw string") { WHEN("BlockData.write() is called") { THEN("The raw string and a newline are printed") { - BlockData b; + BlockData b; b = std::vector{{'a','b','c'}}; b.string("foo bar"); // should make string (not vector) active @@ -50,13 +50,13 @@ void scenario_write_string_active() } } -// For DATA == void -SCENARIO("BlockData write(), when the raw string is active") { +// For DATATYPE == void +SCENARIO("BlockData write(), when the raw string is active") { scenario_write_string_active(); } -// For DATA != void -SCENARIO("BlockData write(), when the raw string is active") { +// For DATATYPE != void +SCENARIO("BlockData write(), when the raw string is active") { scenario_write_string_active(); } @@ -66,7 +66,7 @@ SCENARIO("BlockData write(), when the raw string is active") { // ----------------------------------------------------------------------------- // Helper -template +template void scenario_write_vector_active() { GIVEN("A BlockData with an empty vector") { @@ -215,12 +215,12 @@ void scenario_write_vector_active() } } -// For DATA == void -SCENARIO("BlockData write(), when a vector is active") { +// For DATATYPE == void +SCENARIO("BlockData write(), when a vector is active") { scenario_write_vector_active(); } -// For DATA != void -SCENARIO("BlockData write(), when a vector is active") { +// For DATATYPE != void +SCENARIO("BlockData write(), when a vector is active") { scenario_write_vector_active(); } diff --git a/src/GNDStk/Component.hpp b/src/GNDStk/Component.hpp index dda289377..f96d03d9e 100644 --- a/src/GNDStk/Component.hpp +++ b/src/GNDStk/Component.hpp @@ -13,13 +13,13 @@ using helpMap = std::map; // Component // ----------------------------------------------------------------------------- -template -class Component : public BlockData +template +class Component : public BlockData { // For convenience - using body = BlockData; - using typename body::VariantOfVectors; - using typename body::VariantOfScalars; + using BLOCKDATA = BlockData; + using typename BLOCKDATA::VariantOfVectors; + using typename BLOCKDATA::VariantOfScalars; static inline constexpr bool hasFields = !std::is_same_v>; @@ -37,12 +37,12 @@ class Component : public BlockData // Copy and move *assignments* have the right behavior, however. Component &operator=(const Component &other) { - body::operator=(other); + BLOCKDATA::operator=(other); return *this; } Component &operator=(Component &&other) { - body::operator=(std::move(other)); + BLOCKDATA::operator=(std::move(other)); return *this; } @@ -74,8 +74,8 @@ class Component : public BlockData // base // Convenient access to the BlockData base class - body &baseBlockData() { return *this; } - const body &baseBlockData() const { return *this; } + BLOCKDATA &baseBlockData() { return *this; } + const BLOCKDATA &baseBlockData() const { return *this; } // derived // Convenient access to the derived class @@ -117,10 +117,10 @@ class Component : public BlockData // ostream << Component // ----------------------------------------------------------------------------- -template +template std::ostream &operator<<( std::ostream &os, - const Component &obj + const Component &obj ) { return obj.write(os,0); } diff --git a/src/GNDStk/Component/src/ctor.hpp b/src/GNDStk/Component/src/ctor.hpp index e6be43ce2..560b8c959 100644 --- a/src/GNDStk/Component/src/ctor.hpp +++ b/src/GNDStk/Component/src/ctor.hpp @@ -8,7 +8,7 @@ friend DERIVED; // ctor: fields template -Component(const body &other, ARGS &...args) : body(other) +Component(const BLOCKDATA &other, ARGS &...args) : BLOCKDATA(other) { // static_assert needs string literal #define pairing_error \ diff --git a/src/GNDStk/Component/src/detail.hpp b/src/GNDStk/Component/src/detail.hpp index 93e84c791..34e99b580 100644 --- a/src/GNDStk/Component/src/detail.hpp +++ b/src/GNDStk/Component/src/detail.hpp @@ -1,6 +1,6 @@ // Forward declaration, needed by some things later -template +template class Component; namespace detail { diff --git a/src/GNDStk/Component/src/finish.hpp b/src/GNDStk/Component/src/finish.hpp index a45fcab02..c6dd4eae4 100644 --- a/src/GNDStk/Component/src/finish.hpp +++ b/src/GNDStk/Component/src/finish.hpp @@ -48,11 +48,11 @@ Specifically, the constructors in the auto-generated classes call: Constructor from a Node: Component::finish(the Node) - Constructors involving a vector of "body text" data: + Constructors involving a vector of block data: Component::finish(the vector) Note: In the last case, we're speaking of a vector that's specifically for -body text, not a vector that might be there for a different reason. +block data, not a vector that might be there for a different reason. */ @@ -73,7 +73,7 @@ void construct(const Node &) { } // return void. We use bool, here, for technical reasons, relating to the test // used in the template finish() function (as opposed to the non-template cases) // to determine whether or not someone has provided a custom construct(). -template>> +template>> bool construct(const std::vector &) { return true; } @@ -91,7 +91,7 @@ void finish() // If hasBlockData == true (else no-op), have Component's BlockData base // get length, start, and valueType, as available, from the derived class if constexpr (hasBlockData) - body::pullFromDerived(derived()); + BLOCKDATA::pullFromDerived(derived()); // Based on the derived class' keys(), locate and sort derived-class fields // that are vectors, with vector elements that have index and/or label. @@ -110,7 +110,7 @@ void finish(const DERIVED &other) { // length, start, valueType if constexpr (hasBlockData) - body::pullFromDerived(derived()); + BLOCKDATA::pullFromDerived(derived()); // derived-class vector fields sort(); @@ -133,14 +133,14 @@ void finish(const Node &node) { // Read fields from the Node into the derived object. This applies the keys() // multi-query in the derived class, and also runs BlockData::fromNode() if - // the Node has body text, in order to get the Node's string of "body text". + // the Node has block data, in order to get the Node's string of block data. fromNode(node); if constexpr (hasBlockData) { // length, start, valueType - body::pullFromDerived(derived()); + BLOCKDATA::pullFromDerived(derived()); // make vector - body::get(); + BLOCKDATA::get(); } // derived-class vector fields @@ -160,15 +160,15 @@ void finish(const Node &node) // finish(vector) // ------------------------ -template>> +template>> void finish(const std::vector &vector) { // assign from the vector - body::operator=(vector); + BLOCKDATA::operator=(vector); // length, start, valueType: push back up to derived, // as they would have been computed above in operator=. - body::pushToDerived(derived()); + BLOCKDATA::pushToDerived(derived()); // derived-class vector fields sort(); diff --git a/src/GNDStk/Component/src/fromNode.hpp b/src/GNDStk/Component/src/fromNode.hpp index 94ef7a88f..23f98fe4c 100644 --- a/src/GNDStk/Component/src/fromNode.hpp +++ b/src/GNDStk/Component/src/fromNode.hpp @@ -53,9 +53,9 @@ void fromNode(const Node &node) ); } - // body text, a.k.a. XML "pcdata" (plain character data), if any + // block data, a.k.a. XML "pcdata" (plain character data), if any if constexpr (hasBlockData) - body::fromNode(node); + BLOCKDATA::fromNode(node); } catch (...) { log::member("Component.fromNode(Node(\"{}\"))", node.name); diff --git a/src/GNDStk/Component/src/toNode.hpp b/src/GNDStk/Component/src/toNode.hpp index 7db6577a8..14558db71 100644 --- a/src/GNDStk/Component/src/toNode.hpp +++ b/src/GNDStk/Component/src/toNode.hpp @@ -10,7 +10,7 @@ // called from within these, splits const and non-const cases, and that needs // to be preserved here. So, then, why does BlockData::toNode() have a non-const // version? The issue is that in the non-const case, BlockData::toNode() may -// need to deal with a vector (not just an original "body text" string as may +// need to deal with a vector (not just an original block data string as may // have been read into a const BlockData). And, dealing with a vector means // computing a proper length, start, and valueType while doing toNode() - and // pushing those up to the class derived from Component, as it's from that @@ -24,7 +24,7 @@ operator Node() const { try { - #include "GNDStk/Component/src/toNodeBody.hpp" + #include "GNDStk/Component/src/toNodeData.hpp" } catch (...) { log::member("Component.operator Node() const"); throw; @@ -35,7 +35,7 @@ operator Node() const operator Node() { try { - #include "GNDStk/Component/src/toNodeBody.hpp" + #include "GNDStk/Component/src/toNodeData.hpp" } catch (...) { log::member("Component.operator Node()"); throw; diff --git a/src/GNDStk/Component/src/toNodeBody.hpp b/src/GNDStk/Component/src/toNodeData.hpp similarity index 94% rename from src/GNDStk/Component/src/toNodeBody.hpp rename to src/GNDStk/Component/src/toNodeData.hpp index 8ea104ab7..8b835d618 100644 --- a/src/GNDStk/Component/src/toNodeBody.hpp +++ b/src/GNDStk/Component/src/toNodeData.hpp @@ -2,13 +2,13 @@ // 1. Initialize a Node, with the necessary name Node node(DERIVED::GNDSName()); -// 2. Body text, if applicable +// 2. Block data, if applicable if constexpr (hasBlockData) { // GNDStk uses a "text" metadatum of a "pcdata" child node for this std::string &text = node.add("pcdata").add("text","").second; // Note: the following call might compute length, start, and valueType; // so we need all of this before the upcoming writing of fields. - body::toNode(text,derived().content); + BLOCKDATA::toNode(text,derived().content); } // 3. Write fields diff --git a/src/GNDStk/Component/src/write.hpp b/src/GNDStk/Component/src/write.hpp index f9b9bd479..1b6b872e1 100644 --- a/src/GNDStk/Component/src/write.hpp +++ b/src/GNDStk/Component/src/write.hpp @@ -104,7 +104,7 @@ std::ostream &write(std::ostream &os, const int level) const // BlockData, if any if constexpr (hasBlockData) - body::write(os,level+1); + BLOCKDATA::write(os,level+1); // Indent, write footer, NO newline detail::indentString( diff --git a/src/GNDStk/Component/test/finish.test.cpp b/src/GNDStk/Component/test/finish.test.cpp index 7985c4a34..13f9322b8 100644 --- a/src/GNDStk/Component/test/finish.test.cpp +++ b/src/GNDStk/Component/test/finish.test.cpp @@ -8,7 +8,7 @@ using namespace njoy::GNDStk::core; // ----------------------------------------------------------------------------- // DerivedValue -// Has body text +// Has block data // ----------------------------------------------------------------------------- namespace test { @@ -64,7 +64,8 @@ class DerivedValue : public Component // one of the tests involves checking these struct { // Initialize these to specific values, so that we can ensure that - // Component's finish() functions properly call body::pullFromDerived() + // Component's finish() functions properly call + // BLOCKDATA::pullFromDerived() int length = 11; int start = 3; std::string valueType = "foobar"; @@ -155,7 +156,7 @@ class DerivedValue : public Component // ----------------------------------------------------------------------------- // DerivedPlain -// Does not have body text +// Does not have block data // ----------------------------------------------------------------------------- namespace test { @@ -289,7 +290,7 @@ class DerivedPlain : public Component SCENARIO("Component finish()") { - GIVEN("A component-derived class that has body text") { + GIVEN("A component-derived class that has block data") { const std::vector sorted = {{2,3,5,7,9,11,13,17}}; @@ -375,7 +376,7 @@ SCENARIO("Component finish()") { CHECK(d.get(8) == 0); CHECK(d.get(9) == 0); - // The node from which we read had body text, not child nodes, + // The node from which we read had block data, not child nodes, // and thus would give us nothing for (std::optional) indices... CHECK(d.content.indices.has_value() == false); } @@ -415,7 +416,7 @@ SCENARIO("Component finish()") { } // GIVEN - GIVEN("A component-derived class that does not have body text") { + GIVEN("A component-derived class that does not have block data") { const std::vector sorted = {{"a","bc","d","efg","hi","jklm","no","p"}}; diff --git a/src/GNDStk/Component/test/fromNode.test.cpp b/src/GNDStk/Component/test/fromNode.test.cpp index 971f174e7..056517c20 100644 --- a/src/GNDStk/Component/test/fromNode.test.cpp +++ b/src/GNDStk/Component/test/fromNode.test.cpp @@ -19,9 +19,9 @@ Component does the following: - Calls Component's fromNode() function to read known fields from the Node into the derived class object. - - If the Node has "body text," syncs certain fields in the BlockData (base + - If the Node has block data, syncs certain fields in the BlockData (base of Component) class, with fields in the derived class. Then, converts a - raw body-text string into a vector of values. + raw block data string into a vector of values. - Performs a sort() of derived-class vectors that are known to Component, and that have an index and/or a label. @@ -35,7 +35,7 @@ The tests in this file make use of a particular GNDS file with a reactionSuite. We use a prototype ReactionSuite class (with content that's pared down from what's in the full GNDS spec) that's derived from Component. -The reaction suite itself doesn't (directly) have any body text or sort-able +The reaction suite itself doesn't (directly) have any block data or sort-able fields, and doesn't have a construct(). So, our first test (1) constructs from a Node, (2) uses fromNode() to read from @@ -53,8 +53,8 @@ give different results: the former sorts, the latter doesn't. After the results from (2) are sorted, however, the two Reactions objects are the same. Finally, our third test works with Values objects. Objects of this type have -body text. Construction from Node does a get(), which takes the original, raw -body text in the Node, and makes a vector (in this case vector) from +block data. Construction from Node does a get(), which takes the original, raw +block data in the Node, and makes a vector (in this case vector) from it. fromNode() doesn't do that until, and unless, we ask for it by calling get() directly. Values objects with only raw text write differently than those with text that was processed into a vector. So, this test first ensures that the two @@ -162,7 +162,7 @@ SCENARIO("Component fromNode()") { oss2 << values2; CHECK(oss1.str() != oss2.str()); // not equal (yet) - // *** Apply get() *** to transform the raw string of body-text + // *** Apply get() *** to transform the raw string of block data // values into a vector values2.get(); oss2.str(""); diff --git a/src/GNDStk/precision.hpp b/src/GNDStk/precision.hpp index 72600a092..9dca03f2c 100644 --- a/src/GNDStk/precision.hpp +++ b/src/GNDStk/precision.hpp @@ -19,7 +19,7 @@ // reals: all of the above // in each of: // GNDStk::metadata:: -// GNDStk::data:: (in body text, i.e. XML "plain character data") +// GNDStk::data:: (in block data, i.e. XML "plain character data") // GNDStk:: // the last meaning for both metadata:: and data::. diff --git a/src/GNDStk/precision/src/detail.hpp b/src/GNDStk/precision/src/detail.hpp index e54a3148d..829af18f2 100644 --- a/src/GNDStk/precision/src/detail.hpp +++ b/src/GNDStk/precision/src/detail.hpp @@ -8,7 +8,7 @@ namespace detail { // PrecisionContext enum class PrecisionContext { metadata, // for GNDStk metadata values - data, // for "body text", a.k.a. XML "plain character data" + data, // for block data, a.k.a. XML "plain character data" general // for both of the above together }; diff --git a/src/GNDStk/precision/test/precision.test.cpp b/src/GNDStk/precision/test/precision.test.cpp index 180358cb8..84d129618 100644 --- a/src/GNDStk/precision/test/precision.test.cpp +++ b/src/GNDStk/precision/test/precision.test.cpp @@ -373,7 +373,7 @@ SCENARIO("Precision code in BlockData::get(), " // raw string to floats // ------------------------ - WHEN("We convert a raw \"body text\" string to a vector") { + WHEN("We convert a raw \"block data\" string to a vector") { // Initialize the raw string r = string; @@ -392,7 +392,7 @@ SCENARIO("Precision code in BlockData::get(), " // raw string to doubles // ------------------------ - WHEN("We convert a raw \"body text\" string to a vector") { + WHEN("We convert a raw \"block data\" string to a vector") { r = string; THEN("We get the expected result") { r.get>(); @@ -406,7 +406,7 @@ SCENARIO("Precision code in BlockData::get(), " // raw string to long doubles // ------------------------ - WHEN("We convert a raw \"body text\" string to a vector") { + WHEN("We convert a raw \"block data\" string to a vector") { r = string; THEN("We get the expected result") { r.get>(); diff --git a/src/GNDStk/precision/test/precision.test.hpp b/src/GNDStk/precision/test/precision.test.hpp index 8d80a117b..1c42a7d86 100644 --- a/src/GNDStk/precision/test/precision.test.hpp +++ b/src/GNDStk/precision/test/precision.test.hpp @@ -178,7 +178,7 @@ class Floats : public Component { } // from vector - template>> + template>> Floats(const std::vector &vector) : Component{ BlockData{}, @@ -384,7 +384,7 @@ class Doubles : public Component { } // from vector - template>> + template>> Doubles(const std::vector &vector) : Component{ BlockData{}, @@ -590,7 +590,7 @@ class Quads : public Component { } // from vector - template>> + template>> Quads(const std::vector &vector) : Component{ BlockData{}, @@ -796,7 +796,7 @@ class Reals : public Component { } // from vector - template>> + template>> Reals(const std::vector &vector) : Component{ BlockData{}, diff --git a/src/GNDStk/v1.9/containers/Values.hpp b/src/GNDStk/v1.9/containers/Values.hpp index e014fbdc0..b5285c362 100644 --- a/src/GNDStk/v1.9/containers/Values.hpp +++ b/src/GNDStk/v1.9/containers/Values.hpp @@ -189,7 +189,7 @@ class Values : public Component { } // from vector - template>> + template>> Values(const std::vector &vector) : Component{ BlockData{}, From 3d239dd44f927f580299ef75fe8bdfc8e0322484 Mon Sep 17 00:00:00 2001 From: Martin Staley Date: Tue, 21 Dec 2021 19:20:06 -0700 Subject: [PATCH 27/39] This commit requires some explanation. A class generated by our code generator currently looks something like this: ``` class Foo : public Component { // Some constructs to help with the Component base // ... struct { // Objects for metadata and child nodes } content; // ... // Getters for the objects in struct content // ... // Setters for the objects in struct content // ... // Constructors, etc. }; ``` For upcoming work, I'm considering a fundamental change to the above layout with respect to data, getters, and setters. The change would, I believe, make it easier to substantially enhance the capabilities offered by generated classes. The change - if it ultimately happens - involves, among other things, getting rid of `struct content`. In anticipation of this possible change, then, I went through the code base and tried to reduce the use of expressions like `obj.content.foo`, which assumes the existence of a data member `foo` in something called `content`. Even with the current structure of the generated classes, `obj.content.foo` can be replaced by `obj.foo()`, i.e. the getter than gets, well, `obj.content.foo`. With the possible future work, the getter (or something that replaces it) will do the moral equivalent to what it does now, but `struct content` won't be there. So, better to write `obj.foo()` where we previously wrote `obj.content.foo`. So, the purpose of the changes in this commit can be summarized as follows: (1) They don't change the meaning of the current code. (2) They help set the stage for the possible future more-substantial changes to the generated code, by reducing the reliance one `content.something` terminology all over the place. The changes, while mostly simple and easy to understand, triggered some SFINAE issues that were tricky to track down. New comments in BlockData's `detail.hpp` function explain it, if anyone cares. Also in this PR... General changes: - Some minor updates to SFINAE, on top of those discussed above. - Simplified a few things in the code generator. - Code generator updates reflect goal of using "content." less often. - Ditto for a relevant custom.hpp file. Also, consistent with the goals described above, I replaced the various uses of "content." in several test codes, by writing getters (where they weren't there already) and calling those instead. --- autogen/json2class.cpp | 27 +- src/GNDStk/BlockData/src/detail.hpp | 45 +- src/GNDStk/BlockData/src/sync.hpp | 18 +- src/GNDStk/BlockData/test/detail.test.cpp | 16 + src/GNDStk/BlockData/test/sync.test.cpp | 76 ++- src/GNDStk/BlockData/test/toNode.test.cpp | 52 +- src/GNDStk/Component/src/detail.hpp | 32 +- src/GNDStk/Component/test/Component.test.cpp | 13 +- src/GNDStk/Component/test/ctor.test.cpp | 9 +- src/GNDStk/Component/test/detail.test.cpp | 5 + src/GNDStk/Component/test/finish.test.cpp | 97 ++-- src/GNDStk/Component/test/indexnlabel.hpp | 35 +- src/GNDStk/Component/test/prototype.hpp | 462 +++++++++--------- src/GNDStk/Component/test/sort.test.cpp | 10 +- src/GNDStk/Node/src/detail.hpp | 2 +- src/GNDStk/precision/test/precision.test.hpp | 284 +++++------ src/GNDStk/v1.9/containers/Axes.hpp | 16 +- src/GNDStk/v1.9/containers/Axis.hpp | 24 +- src/GNDStk/v1.9/containers/Grid.hpp | 52 +- src/GNDStk/v1.9/containers/Link.hpp | 8 +- src/GNDStk/v1.9/containers/Regions1d.hpp | 32 +- src/GNDStk/v1.9/containers/Values.hpp | 38 +- .../v1.9/containers/Values/src/custom.hpp | 6 +- src/GNDStk/v1.9/containers/XYs1d.hpp | 52 +- src/GNDStk/v1.9/transport/CrossSection.hpp | 8 +- src/GNDStk/v1.9/transport/Reaction.hpp | 32 +- src/GNDStk/v1.9/transport/ReactionSuite.hpp | 56 +-- src/GNDStk/v1.9/transport/Reactions.hpp | 8 +- 28 files changed, 836 insertions(+), 679 deletions(-) diff --git a/autogen/json2class.cpp b/autogen/json2class.cpp index f70a84192..3091dcdfc 100644 --- a/autogen/json2class.cpp +++ b/autogen/json2class.cpp @@ -1159,26 +1159,17 @@ void writeClassSetters(writer &out, const PerClass &per) // setter // note that if type is optional, a T can still be sent out(1,"@ &@(const @ &obj)", per.clname, m.name, m.typeFull); - if (special && m.isDefaulted) - out(2,"{ BlockData::@(content.@ = obj); return *this; }", - m.name, m.name); - if (special && !m.isDefaulted) - out(2,"{ BlockData::@(@() = obj); return *this; }", - m.name, m.name); - if (!special && m.isDefaulted) - out(2,"{ content.@ = obj; return *this; }", - m.name); - if (!special && !m.isDefaulted) - out(2,"{ @() = obj; return *this; }", - m.name); + + special + ? out(2,"{ BlockData::@(@() = obj); return *this; }", m.name, m.name) + : out(2,"{ @() = obj; return *this; }", m.name); // setter, if type is Defaulted if (m.isDefaulted) { out(1,"@ &@(const std::optional<@> &obj)", per.clname, m.name, m.type); special - ? out(2,"{ BlockData::@(content.@ = obj); return *this; }", - m.name, m.name) - : out(2,"{ content.@ = obj; return *this; }", m.name); + ? out(2,"{ BlockData::@(@() = obj); return *this; }", m.name, m.name) + : out(2,"{ @() = obj; return *this; }", m.name); } } @@ -1238,15 +1229,15 @@ void writeClassCtorComponent( for (const auto &m : per.metadata) { // metadata out(","); - out(3,"content.@", m.name, false); + out(3,"this->@()", m.name, false); } for (const auto &c : per.children) { // children out(","); - out(3,"content.@", c.name, false); + out(3,"this->@()", c.name, false); } for (const auto &v : per.variants) { // variants out(","); - out(3,"content.@", v.name, false); + out(3,"this->@()", v.name, false); } out(); diff --git a/src/GNDStk/BlockData/src/detail.hpp b/src/GNDStk/BlockData/src/detail.hpp index dd5053e9e..a5adfafe7 100644 --- a/src/GNDStk/BlockData/src/detail.hpp +++ b/src/GNDStk/BlockData/src/detail.hpp @@ -32,67 +32,96 @@ using decays_t = typename decays::type; // ----------------------------------------------------------------------------- // ------------------------ -// Helpers +// has_length // ------------------------ -// has_length template struct has_length : std::false_type { }; template -struct has_length +struct has_length : std::true_type { }; +// ------------------------ // has_start +// ------------------------ + template struct has_start : std::false_type { }; template -struct has_start +struct has_start : std::true_type { }; +// ------------------------ // has_valueType +// ------------------------ + template struct has_valueType : std::false_type { }; template -struct has_valueType +struct has_valueType : std::true_type { }; +// ------------------------ // has_index +// ------------------------ + template struct has_index : std::false_type { }; template -struct has_index +struct has_index< + T, + decltype( + (void) + // Just using T{}.index() on the next line, like we do with other has_* + // classes above, can lead to an ambiguity between this specialization + // and the std::variant specialization below, arising from the fact that + // std::variant has an index() function. Hence the std::conditional_t. + std::conditional_t::value,void,T>{}.index(), + 0 + ) +> : std::true_type { }; +// for variant template struct has_index> { // for variant: does any alternative have index? static constexpr bool value = (has_index::value || ...); }; +// ------------------------ // has_label +// ------------------------ + template struct has_label : std::false_type { }; template -struct has_label +struct has_label< + T, + // std::variant doesn't have a label(), like it has an index(), but we'll + // do the same thing here, for has_label, as we do above for has_index. + // It's harmless, and if std::variant is ever given a label() function... + decltype((void)std::conditional_t::value,void,T>{}.label(),0) +> : std::true_type { }; +// for variant template struct has_label> { // for variant: does any alternative have label? static constexpr bool value = (has_label::value || ...); }; - // ------------------------ // Prefer these. // They apply std::decay, diff --git a/src/GNDStk/BlockData/src/sync.hpp b/src/GNDStk/BlockData/src/sync.hpp index c582aa063..b91dba6ff 100644 --- a/src/GNDStk/BlockData/src/sync.hpp +++ b/src/GNDStk/BlockData/src/sync.hpp @@ -6,12 +6,9 @@ template void pullFromDerived(const T &obj) { - if constexpr (detail::hasLength) - length(obj.content.length); - if constexpr (detail::hasStart) - start(obj.content.start); - if constexpr (detail::hasValueType) - valueType(obj.content.valueType); + if constexpr (detail::hasLength ) length (obj.length ()); + if constexpr (detail::hasStart ) start (obj.start ()); + if constexpr (detail::hasValueType) valueType(obj.valueType()); } // pushToDerived(derived) @@ -19,10 +16,7 @@ void pullFromDerived(const T &obj) template void pushToDerived(T &obj) const { - if constexpr (detail::hasLength) - obj.content.length = length(); - if constexpr (detail::hasStart) - obj.content.start = start(); - if constexpr (detail::hasValueType) - obj.content.valueType = valueType(); + if constexpr (detail::hasLength ) obj.length () = length (); + if constexpr (detail::hasStart ) obj.start () = start (); + if constexpr (detail::hasValueType) obj.valueType() = valueType(); } diff --git a/src/GNDStk/BlockData/test/detail.test.cpp b/src/GNDStk/BlockData/test/detail.test.cpp index 64b9cb577..702736964 100644 --- a/src/GNDStk/BlockData/test/detail.test.cpp +++ b/src/GNDStk/BlockData/test/detail.test.cpp @@ -86,6 +86,10 @@ SCENARIO("Testing various BlockData-related detail:: constructs") { const double start = 0; const std::string &valueType = bar; } content; + const int &length() const { return content.length; } + int &length() { return content.length; } + const double &start() const { return content.start; } + const std::string &valueType() const { return content.valueType; } } foo; THEN("Our SFINAE helpers detect this") { CHECK((detail::hasLength == true)); @@ -100,6 +104,8 @@ SCENARIO("Testing various BlockData-related detail:: constructs") { const double start = 0; const std::string &valueType = bar; } content; + const double &start() const { return content.start; } + const std::string &valueType() const { return content.valueType; } } foo; THEN("Our SFINAE helpers detect this") { CHECK((detail::hasLength == false)); @@ -114,6 +120,9 @@ SCENARIO("Testing various BlockData-related detail:: constructs") { int length; const std::string &valueType = bar; } content; + const int &length() const { return content.length; } + int &length() { return content.length; } + const std::string &valueType() const { return content.valueType; } } foo; THEN("Our SFINAE helpers detect this") { CHECK((detail::hasLength == true)); @@ -128,6 +137,9 @@ SCENARIO("Testing various BlockData-related detail:: constructs") { int length; const double start = 0; } content; + const int &length() const { return content.length; } + int &length() { return content.length; } + const double &start() const { return content.start; } } foo; THEN("Our SFINAE helpers detect this") { CHECK((detail::hasLength == true)); @@ -141,6 +153,8 @@ SCENARIO("Testing various BlockData-related detail:: constructs") { struct { int length; } content; + const int &length() const { return content.length; } + int &length() { return content.length; } } foo; THEN("Our SFINAE helpers detect this") { CHECK((detail::hasLength == true)); @@ -154,6 +168,7 @@ SCENARIO("Testing various BlockData-related detail:: constructs") { struct { const double start = 0; } content; + const double &start() const { return content.start; } } foo; THEN("Our SFINAE helpers detect this") { CHECK((detail::hasLength == false)); @@ -167,6 +182,7 @@ SCENARIO("Testing various BlockData-related detail:: constructs") { struct { const std::string &valueType = bar; } content; + const std::string &valueType() const { return content.valueType; } } foo; THEN("Our SFINAE helpers detect this") { CHECK((detail::hasLength == false)); diff --git a/src/GNDStk/BlockData/test/sync.test.cpp b/src/GNDStk/BlockData/test/sync.test.cpp index 54e723016..369f8394f 100644 --- a/src/GNDStk/BlockData/test/sync.test.cpp +++ b/src/GNDStk/BlockData/test/sync.test.cpp @@ -35,6 +35,8 @@ void scenario_pull() struct { int length = 10; } content; + const int &length() const { return content.length; } + int &length() { return content.length; } } derived; BlockData b; b.length(11).start(12).valueType("13"); @@ -50,6 +52,8 @@ void scenario_pull() struct { int start = 14; } content; + const int &start() const { return content.start; } + int &start() { return content.start; } } derived; BlockData b; b.length(15).start(16).valueType("17"); @@ -65,6 +69,8 @@ void scenario_pull() struct { std::string valueType = "18"; } content; + const std::string &valueType() const { return content.valueType; } + std::string &valueType() { return content.valueType; } } derived; BlockData b; b.length(19).start(20).valueType("21"); @@ -81,6 +87,10 @@ void scenario_pull() int start = 22; std::string valueType = "23"; } content; + const int &start() const { return content.start; } + int &start() { return content.start; } + const std::string &valueType() const { return content.valueType; } + std::string &valueType() { return content.valueType; } } derived; BlockData b; b.length(24).start(25).valueType("26"); @@ -97,6 +107,10 @@ void scenario_pull() int length = 27; std::string valueType = "28"; } content; + const int &length() const { return content.length; } + int &length() { return content.length; } + const std::string &valueType() const { return content.valueType; } + std::string &valueType() { return content.valueType; } } derived; BlockData b; b.length(29).start(30).valueType("31"); @@ -113,6 +127,10 @@ void scenario_pull() int length = 32; int start = 33; } content; + const int &length() const { return content.length; } + int &length() { return content.length; } + const int &start() const { return content.start; } + int &start() { return content.start; } } derived; BlockData b; b.length(34).start(35).valueType("36"); @@ -130,6 +148,12 @@ void scenario_pull() int start = 38; std::string valueType = "39"; } content; + const int &length() const { return content.length; } + int &length() { return content.length; } + const int &start() const { return content.start; } + int &start() { return content.start; } + const std::string &valueType() const { return content.valueType; } + std::string &valueType() { return content.valueType; } } derived; BlockData b; b.length(40).start(41).valueType("42"); @@ -171,11 +195,13 @@ void scenario_push() struct { int ignored = 123456; // not length, start, or valueType } content; + const int &ignored() const { return content.ignored; } + int &ignored() { return content.ignored; } } derived; BlockData b; b.length(0).start(0).valueType("0"); b.pushToDerived(derived); // should do nothing here - CHECK(derived.content.ignored == 123456); + CHECK(derived.ignored() == 123456); } // length only @@ -184,11 +210,13 @@ void scenario_push() struct { int length = 10; } content; + const int &length() const { return content.length; } + int &length() { return content.length; } } derived; BlockData b; b.length(11).start(12).valueType("13"); b.pushToDerived(derived); - CHECK(derived.content.length == 11); + CHECK(derived.length() == 11); } // start only @@ -197,11 +225,13 @@ void scenario_push() struct { int start = 14; } content; + const int &start() const { return content.start; } + int &start() { return content.start; } } derived; BlockData b; b.length(15).start(16).valueType("17"); b.pushToDerived(derived); - CHECK(derived.content.start == 16); + CHECK(derived.start() == 16); } // valueType only @@ -210,11 +240,13 @@ void scenario_push() struct { std::string valueType = "18"; } content; + const std::string &valueType() const { return content.valueType; } + std::string &valueType() { return content.valueType; } } derived; BlockData b; b.length(19).start(20).valueType("21"); b.pushToDerived(derived); - CHECK(derived.content.valueType == "21"); + CHECK(derived.valueType() == "21"); } // all but length @@ -224,12 +256,16 @@ void scenario_push() int start = 22; std::string valueType = "23"; } content; + const int &start() const { return content.start; } + int &start() { return content.start; } + const std::string &valueType() const { return content.valueType; } + std::string &valueType() { return content.valueType; } } derived; BlockData b; b.length(24).start(25).valueType("26"); b.pushToDerived(derived); - CHECK(derived.content.start == 25); - CHECK(derived.content.valueType == "26"); + CHECK(derived.start() == 25); + CHECK(derived.valueType() == "26"); } // all but start @@ -239,12 +275,16 @@ void scenario_push() int length = 27; std::string valueType = "28"; } content; + const int &length() const { return content.length; } + int &length() { return content.length; } + const std::string &valueType() const { return content.valueType; } + std::string &valueType() { return content.valueType; } } derived; BlockData b; b.length(29).start(30).valueType("31"); b.pushToDerived(derived); - CHECK(derived.content.length == 29); - CHECK(derived.content.valueType == "31"); + CHECK(derived.length() == 29); + CHECK(derived.valueType() == "31"); } // all but valueType @@ -254,12 +294,16 @@ void scenario_push() int length = 32; int start = 33; } content; + const int &length() const { return content.length; } + int &length() { return content.length; } + const int &start() const { return content.start; } + int &start() { return content.start; } } derived; BlockData b; b.length(34).start(35).valueType("36"); b.pushToDerived(derived); - CHECK(derived.content.length == 34); - CHECK(derived.content.start == 35); + CHECK(derived.length() == 34); + CHECK(derived.start() == 35); } // all three @@ -270,13 +314,19 @@ void scenario_push() int start = 38; std::string valueType = "39"; } content; + const int &length() const { return content.length; } + int &length() { return content.length; } + const int &start() const { return content.start; } + int &start() { return content.start; } + const std::string &valueType() const { return content.valueType; } + std::string &valueType() { return content.valueType; } } derived; BlockData b; b.length(40).start(41).valueType("42"); b.pushToDerived(derived); - CHECK(derived.content.length == 40); - CHECK(derived.content.start == 41); - CHECK(derived.content.valueType == "42"); + CHECK(derived.length() == 40); + CHECK(derived.start() == 41); + CHECK(derived.valueType() == "42"); } } } diff --git a/src/GNDStk/BlockData/test/toNode.test.cpp b/src/GNDStk/BlockData/test/toNode.test.cpp index bcd6e1b8a..92c13dc1f 100644 --- a/src/GNDStk/BlockData/test/toNode.test.cpp +++ b/src/GNDStk/BlockData/test/toNode.test.cpp @@ -241,12 +241,14 @@ void scenario_toNode() struct { int ignored = 12345; } content; + const int &ignored() const { return content.ignored; } + int &ignored() { return content.ignored; } } derived; BlockData b; std::string text; b = std::vector{{0,0,10,20,30,0,0,0}}; b.toNode(text,derived); // toNode doesn't care about what's *not* length/start/valueType... - CHECK(derived.content.ignored == 12345); // same as before toNode() + CHECK(derived.ignored() == 12345); // same as before toNode() } // length only @@ -255,11 +257,13 @@ void scenario_toNode() struct { int length = 0; } content; + const int &length() const { return content.length; } + int &length() { return content.length; } } derived; BlockData b; std::string text; b = std::vector{{0,0,10,20,30,0,0,0}}; b.toNode(text,derived); - CHECK(derived.content.length == 8); + CHECK(derived.length() == 8); } // start only @@ -268,11 +272,13 @@ void scenario_toNode() struct { int start = 0; } content; + const int &start() const { return content.start; } + int &start() { return content.start; } } derived; BlockData b; std::string text; b = std::vector{{0,0,10,20,30,0,0,0}}; b.toNode(text,derived); - CHECK(derived.content.start == 2); + CHECK(derived.start() == 2); } // valueType only @@ -281,11 +287,13 @@ void scenario_toNode() struct { std::string valueType = ""; } content; + const std::string &valueType() const { return content.valueType; } + std::string &valueType() { return content.valueType; } } derived; BlockData b; std::string text; b = std::vector{{0,0,10,20,30,0,0,0}}; b.toNode(text,derived); - CHECK(derived.content.valueType == "Integer32"); + CHECK(derived.valueType() == "Integer32"); } // all but length @@ -295,12 +303,16 @@ void scenario_toNode() int start = 0; std::string valueType = ""; } content; + const int &start() const { return content.start; } + int &start() { return content.start; } + const std::string &valueType() const { return content.valueType; } + std::string &valueType() { return content.valueType; } } derived; BlockData b; std::string text; b = std::vector{{0,0,10,20,30,0,0,0}}; b.toNode(text,derived); - CHECK(derived.content.start == 2); - CHECK(derived.content.valueType == "Integer32"); + CHECK(derived.start() == 2); + CHECK(derived.valueType() == "Integer32"); } // all but start @@ -310,12 +322,16 @@ void scenario_toNode() int length = 0; std::string valueType = ""; } content; + const int &length() const { return content.length; } + int &length() { return content.length; } + const std::string &valueType() const { return content.valueType; } + std::string &valueType() { return content.valueType; } } derived; BlockData b; std::string text; b = std::vector{{0,0,10,20,30,0,0,0}}; b.toNode(text,derived); - CHECK(derived.content.length == 8); - CHECK(derived.content.valueType == "Integer32"); + CHECK(derived.length() == 8); + CHECK(derived.valueType() == "Integer32"); } // all but valueType @@ -325,12 +341,16 @@ void scenario_toNode() int length = 0; int start = 0; } content; + const int &length() const { return content.length; } + int &length() { return content.length; } + const int &start() const { return content.start; } + int &start() { return content.start; } } derived; BlockData b; std::string text; b = std::vector{{0,0,10,20,30,0,0,0}}; b.toNode(text,derived); - CHECK(derived.content.length == 8); - CHECK(derived.content.start == 2); + CHECK(derived.length() == 8); + CHECK(derived.start() == 2); } // all three @@ -341,13 +361,19 @@ void scenario_toNode() int start = 0; std::string valueType = ""; } content; + const int &length() const { return content.length; } + int &length() { return content.length; } + const int &start() const { return content.start; } + int &start() { return content.start; } + const std::string &valueType() const { return content.valueType; } + std::string &valueType() { return content.valueType; } } derived; BlockData b; std::string text; b = std::vector{{0,0,10,20,30,0,0,0}}; b.toNode(text,derived); - CHECK(derived.content.length == 8); - CHECK(derived.content.start == 2); - CHECK(derived.content.valueType == "Integer32"); + CHECK(derived.length() == 8); + CHECK(derived.start() == 2); + CHECK(derived.valueType() == "Integer32"); } } } diff --git a/src/GNDStk/Component/src/detail.hpp b/src/GNDStk/Component/src/detail.hpp index 34e99b580..9350dbee5 100644 --- a/src/GNDStk/Component/src/detail.hpp +++ b/src/GNDStk/Component/src/detail.hpp @@ -758,46 +758,46 @@ bool compareRegular(const A &a, const B &b) // index? std::size_t aindex = 0; bool ahasindex = false; if constexpr (hasIndex) { - if constexpr (isOptional) { - if ((ahasindex = a.content.index.has_value())) - aindex = a.content.index.value(); + if constexpr (isOptional) { + if ((ahasindex = a.index().has_value())) + aindex = a.index().value(); } else { ahasindex = true; - aindex = a.content.index; + aindex = a.index(); } } std::size_t bindex = 0; bool bhasindex = false; if constexpr (hasIndex) { - if constexpr (isOptional) { - if ((bhasindex = b.content.index.has_value())) - bindex = b.content.index.value(); + if constexpr (isOptional) { + if ((bhasindex = b.index().has_value())) + bindex = b.index().value(); } else { bhasindex = true; - bindex = b.content.index; + bindex = b.index(); } } // label? std::string alabel = ""; bool ahaslabel = false; if constexpr (hasLabel) { - if constexpr (isOptional) { - if ((ahaslabel = a.content.label.has_value())) - alabel = a.content.label.value(); + if constexpr (isOptional) { + if ((ahaslabel = a.label().has_value())) + alabel = a.label().value(); } else { ahaslabel = true; - alabel = a.content.label; + alabel = a.label(); } } std::string blabel = ""; bool bhaslabel = false; if constexpr (hasLabel) { - if constexpr (isOptional) { - if ((bhaslabel = b.content.label.has_value())) - blabel = b.content.label.value(); + if constexpr (isOptional) { + if ((bhaslabel = b.label().has_value())) + blabel = b.label().value(); } else { bhaslabel = true; - blabel = b.content.label; + blabel = b.label(); } } diff --git a/src/GNDStk/Component/test/Component.test.cpp b/src/GNDStk/Component/test/Component.test.cpp index 1f6a6e0aa..d4d1c1870 100644 --- a/src/GNDStk/Component/test/Component.test.cpp +++ b/src/GNDStk/Component/test/Component.test.cpp @@ -71,11 +71,16 @@ class DerivedData : public Component double bar; } content; + const int &foo() const { return content.foo; } + int &foo() { return content.foo; } + const double &bar() const { return content.bar; } + double &bar() { return content.bar; } + DerivedData() : Component( BlockData{}, - content.foo, - content.bar + foo(), + bar() ) { } @@ -83,8 +88,8 @@ class DerivedData : public Component DerivedData(const Node &node) : Component( BlockData{}, - content.foo, - content.bar + foo(), + bar() ) { Component::finish(node); diff --git a/src/GNDStk/Component/test/ctor.test.cpp b/src/GNDStk/Component/test/ctor.test.cpp index 076a2c1ae..b85111548 100644 --- a/src/GNDStk/Component/test/ctor.test.cpp +++ b/src/GNDStk/Component/test/ctor.test.cpp @@ -58,13 +58,18 @@ class DerivedSomething : public Component double bar; } content; + const int &foo() const { return content.foo; } + int &foo() { return content.foo; } + const double &bar() const { return content.bar; } + double &bar() { return content.bar; } + public: DerivedSomething() : Component( BlockData{}, - content.foo, - content.bar + foo(), + bar() ) { Component::finish(); diff --git a/src/GNDStk/Component/test/detail.test.cpp b/src/GNDStk/Component/test/detail.test.cpp index 0b891b3fa..694f8cde3 100644 --- a/src/GNDStk/Component/test/detail.test.cpp +++ b/src/GNDStk/Component/test/detail.test.cpp @@ -58,6 +58,11 @@ struct FooBar { int foo; double bar; } content; + + const int &foo() const { return content.foo; } + int &foo() { return content.foo; } + const double &bar() const { return content.bar; } + double &bar() { return content.bar; } }; diff --git a/src/GNDStk/Component/test/finish.test.cpp b/src/GNDStk/Component/test/finish.test.cpp index 13f9322b8..5baa57d2e 100644 --- a/src/GNDStk/Component/test/finish.test.cpp +++ b/src/GNDStk/Component/test/finish.test.cpp @@ -18,13 +18,16 @@ struct IndexStruct { struct { std::size_t index; } content; - IndexStruct(const std::size_t i = 0) { content.index = i; } + const std::size_t &index() const { return content.index; } + std::size_t &index() { return content.index; } + + IndexStruct(const std::size_t i = 0) { index() = i; } IndexStruct(const Node &) : IndexStruct(0) { } }; inline bool operator==(const IndexStruct &one, const IndexStruct &two) { - return one.content.index == two.content.index; + return one.index() == two.index(); } @@ -76,6 +79,18 @@ class DerivedValue : public Component {{3,2,17,7,5,9,13,11}}; } content; + const int &length() const { return content.length; } + int &length() { return content.length; } + + const int &start() const { return content.start; } + int &start() { return content.start; } + + const std::string &valueType() const { return content.valueType; } + std::string &valueType() { return content.valueType; } + + const std::optional> &indices() const { return content.indices; } + std::optional> &indices() { return content.indices; } + private: // construct functions @@ -108,7 +123,7 @@ class DerivedValue : public Component DerivedValue() : Component( BlockData{}, - content.length, content.start, content.valueType, content.indices + length(), start(), valueType(), indices() ) { // finish() @@ -119,7 +134,7 @@ class DerivedValue : public Component DerivedValue(const DerivedValue &other) : Component{ other, - content.length, content.start, content.valueType, content.indices + length(), start(), valueType(), indices() }, content{other.content} { @@ -131,7 +146,7 @@ class DerivedValue : public Component DerivedValue(const Node &node) : Component{ BlockData{}, - content.length, content.start, content.valueType, content.indices + length(), start(), valueType(), indices() } { // finish(node) @@ -142,7 +157,7 @@ class DerivedValue : public Component DerivedValue(const std::vector &vec) : Component{ BlockData{}, - content.length, content.start, content.valueType, content.indices + length(), start(), valueType(), indices() } { // finish(vector) @@ -166,17 +181,20 @@ struct LabelStruct { struct { std::string label; } content; + const std::string &label() const { return content.label; } + std::string &label() { return content.label; } + // apparently need a char* ctor for initializer-list initialization to work - LabelStruct(const char *const str = "") { content.label = str; } + LabelStruct(const char *const str = "") { label() = str; } LabelStruct(const Node &node) { - content.label = node(std::string{}/Meta<>("label")); + label() = node(std::string{}/Meta<>("label")); } }; inline bool operator==(const LabelStruct &one, const LabelStruct &two) { - return one.content.label == two.content.label; + return one.label() == two.label(); } @@ -219,6 +237,15 @@ class DerivedPlain : public Component {{"bc","a","p","efg","d","hi","no","jklm"}}; } content; + const int &foo() const { return content.foo; } + int &foo() { return content.foo; } + + const double &bar() const { return content.bar; } + double &bar() { return content.bar; } + + const std::optional> &labels() const { return content.labels; } + std::optional> &labels() { return content.labels; } + private: // construct functions @@ -245,7 +272,7 @@ class DerivedPlain : public Component DerivedPlain() : Component( BlockData{}, - content.foo, content.bar, content.labels + foo(), bar(), labels() ) { // finish() @@ -256,7 +283,7 @@ class DerivedPlain : public Component DerivedPlain(const DerivedPlain &other) : Component{ other, - content.foo, content.bar, content.labels + foo(), bar(), labels() }, content{other.content} { @@ -268,7 +295,7 @@ class DerivedPlain : public Component DerivedPlain(const Node &node) : Component{ BlockData{}, - content.foo, content.bar, content.labels + foo(), bar(), labels() } { // finish(node) @@ -307,9 +334,9 @@ SCENARIO("Component finish()") { CHECK(d.valueType() == "foobar"); // Ensure that finish() did a sort() - CHECK(d.content.indices.has_value() == true); - CHECK(d.content.indices->size() == 8); - CHECK(*d.content.indices == sorted); + CHECK(d.indices().has_value() == true); + CHECK(d.indices()->size() == 8); + CHECK(*d.indices() == sorted); } // ctor: copy @@ -341,9 +368,9 @@ SCENARIO("Component finish()") { CHECK(d.valueType() == "foobar"); // Ensure that finish() did a sort() - CHECK(d.content.indices.has_value() == true); - CHECK(d.content.indices->size() == 8); - CHECK(*d.content.indices == sorted); + CHECK(d.indices().has_value() == true); + CHECK(d.indices()->size() == 8); + CHECK(*d.indices() == sorted); } // ctor: from node @@ -378,7 +405,7 @@ SCENARIO("Component finish()") { // The node from which we read had block data, not child nodes, // and thus would give us nothing for (std::optional) indices... - CHECK(d.content.indices.has_value() == false); + CHECK(d.indices().has_value() == false); } // ctor: from vector @@ -403,14 +430,14 @@ SCENARIO("Component finish()") { // And, BlockData's operator=(vector) as mentioned above should also // have changed the corresponding values back up in the derived class - CHECK(d.content.length == 3); - CHECK(d.content.start == 0); - CHECK(d.content.valueType == "Float64"); + CHECK(d.length() == 3); + CHECK(d.start() == 0); + CHECK(d.valueType() == "Float64"); // Ensure that finish() did a sort() - CHECK(d.content.indices.has_value() == true); - CHECK(d.content.indices->size() == 8); - CHECK(*d.content.indices == sorted); + CHECK(d.indices().has_value() == true); + CHECK(d.indices()->size() == 8); + CHECK(*d.indices() == sorted); } } // GIVEN @@ -426,9 +453,9 @@ SCENARIO("Component finish()") { test::DerivedPlain d; CHECK(test::construct1DerivedPlain == true); - CHECK(d.content.labels.has_value() == true); - CHECK(d.content.labels->size() == 8); - CHECK(*d.content.labels == sorted); + CHECK(d.labels().has_value() == true); + CHECK(d.labels()->size() == 8); + CHECK(*d.labels() == sorted); } // ctor: copy @@ -439,9 +466,9 @@ SCENARIO("Component finish()") { test::DerivedPlain d(dfrom); CHECK(test::construct2DerivedPlain == true); - CHECK(d.content.labels.has_value() == true); - CHECK(d.content.labels->size() == 8); - CHECK(*d.content.labels == sorted); + CHECK(d.labels().has_value() == true); + CHECK(d.labels()->size() == 8); + CHECK(*d.labels() == sorted); } // ctor: from node, case 1 @@ -455,7 +482,7 @@ SCENARIO("Component finish()") { test::DerivedPlain d(node); CHECK(test::construct3DerivedPlain == true); - CHECK(d.content.labels.has_value() == false); + CHECK(d.labels().has_value() == false); } // ctor: from node, case 2 @@ -473,10 +500,10 @@ SCENARIO("Component finish()") { test::DerivedPlain d(node); CHECK(test::construct3DerivedPlain == true); - CHECK(d.content.labels.has_value() == true); - CHECK(d.content.labels->size() == 4); + CHECK(d.labels().has_value() == true); + CHECK(d.labels()->size() == 4); CHECK(( - *d.content.labels == + *d.labels() == std::vector{{"abc","def","ghi","jkl"}} )); } diff --git a/src/GNDStk/Component/test/indexnlabel.hpp b/src/GNDStk/Component/test/indexnlabel.hpp index 07571c930..2eeb844b9 100644 --- a/src/GNDStk/Component/test/indexnlabel.hpp +++ b/src/GNDStk/Component/test/indexnlabel.hpp @@ -20,15 +20,17 @@ struct Index { std::string value; } content; - std::size_t index() const { return content.index; }; - std::string value() const { return content.value; }; + const int &index() const { return content.index; }; + int &index() { return content.index; }; + const std::string &value() const { return content.value; }; + std::string &value() { return content.value; }; Index( const int index = 0, const std::string &value = "" ) { - content.value = value; - content.index = index; + this->index() = index; + this->value() = value; } }; @@ -41,15 +43,17 @@ struct Label { std::string value; } content; - std::string label() const { return content.label; }; - std::string value() const { return content.value; }; + const std::string &label() const { return content.label; }; + std::string &label() { return content.label; }; + const std::string &value() const { return content.value; }; + std::string &value() { return content.value; }; Label( const std::string &label = "", const std::string &value = "" ) { - content.value = value; - content.label = label; + this->label() = label; + this->value() = value; } }; @@ -63,17 +67,20 @@ struct IndexLabel { std::string value; } content; - std::size_t index() const { return content.index; }; - std::string label() const { return content.label; }; - std::string value() const { return content.value; }; + const int &index() const { return content.index; }; + int &index() { return content.index; }; + const std::string &label() const { return content.label; }; + std::string &label() { return content.label; }; + const std::string &value() const { return content.value; }; + std::string &value() { return content.value; }; IndexLabel( const int index = 0, const std::string &label = "", const std::string &value = "" ) { - content.value = value; - content.index = index; - content.label = label; + this->index() = index; + this->label() = label; + this->value() = value; } }; diff --git a/src/GNDStk/Component/test/prototype.hpp b/src/GNDStk/Component/test/prototype.hpp index fcddc1e49..fd546da41 100644 --- a/src/GNDStk/Component/test/prototype.hpp +++ b/src/GNDStk/Component/test/prototype.hpp @@ -166,15 +166,15 @@ class Values : public Component { // start const auto &start() const - { return content.start.value(); } + { return content.start; } auto &start() - { return content.start.value(); } + { return content.start; } // valueType const auto &valueType() const - { return content.valueType.value(); } + { return content.valueType; } auto &valueType() - { return content.valueType.value(); } + { return content.valueType; } // ------------------------ // Setters @@ -188,15 +188,15 @@ class Values : public Component { // start(value) auto &start(const Defaulted &obj) - { BlockData::start(content.start = obj); return *this; } + { BlockData::start(start() = obj); return *this; } auto &start(const int &obj) - { BlockData::start(content.start = obj); return *this; } + { BlockData::start(start() = obj); return *this; } // valueType(value) auto &valueType(const Defaulted &obj) - { BlockData::valueType(content.valueType = obj); return *this; } + { BlockData::valueType(valueType() = obj); return *this; } auto &valueType(const std::string &obj) - { BlockData::valueType(content.valueType = obj); return *this; } + { BlockData::valueType(valueType() = obj); return *this; } // ------------------------ // Construction @@ -206,9 +206,9 @@ class Values : public Component { Values() : Component{ BlockData{}, - content.length, - content.start, - content.valueType + this->length(), + this->start(), + this->valueType() } { Component::finish(); @@ -218,9 +218,9 @@ class Values : public Component { Values(const Values &other) : Component{ other, - content.length, - content.start, - content.valueType + this->length(), + this->start(), + this->valueType() }, content{other.content} { @@ -231,9 +231,9 @@ class Values : public Component { Values(Values &&other) : Component{ other, - content.length, - content.start, - content.valueType + this->length(), + this->start(), + this->valueType() }, content{std::move(other.content)} { @@ -244,9 +244,9 @@ class Values : public Component { Values(const Node &node) : Component{ BlockData{}, - content.length, - content.start, - content.valueType + this->length(), + this->start(), + this->valueType() } { Component::finish(node); @@ -260,9 +260,9 @@ class Values : public Component { ) : Component{ BlockData{}, - content.length, - content.start, - content.valueType + this->length(), + this->start(), + this->valueType() }, content{ length, @@ -281,9 +281,9 @@ class Values : public Component { ) : Component{ BlockData{}, - content.length, - content.start, - content.valueType + this->length(), + this->start(), + this->valueType() }, content{ length, @@ -389,7 +389,7 @@ class Link : public Component { Link() : Component{ BlockData{}, - content.href + this->href() } { Component::finish(); @@ -399,7 +399,7 @@ class Link : public Component { Link(const Link &other) : Component{ other, - content.href + this->href() }, content{other.content} { @@ -410,7 +410,7 @@ class Link : public Component { Link(Link &&other) : Component{ other, - content.href + this->href() }, content{std::move(other.content)} { @@ -421,7 +421,7 @@ class Link : public Component { Link(const Node &node) : Component{ BlockData{}, - content.href + this->href() } { Component::finish(node); @@ -433,7 +433,7 @@ class Link : public Component { ) : Component{ BlockData{}, - content.href + this->href() }, content{ href @@ -541,9 +541,9 @@ class Grid : public Component { // interpolation const auto &interpolation() const - { return content.interpolation.value(); } + { return content.interpolation; } auto &interpolation() - { return content.interpolation.value(); } + { return content.interpolation; } // label const auto &label() const @@ -593,9 +593,9 @@ class Grid : public Component { // interpolation(value) auto &interpolation(const Defaulted &obj) - { content.interpolation = obj; return *this; } + { interpolation() = obj; return *this; } auto &interpolation(const enums::Interpolation &obj) - { content.interpolation = obj; return *this; } + { interpolation() = obj; return *this; } // label(value) auto &label(const std::optional &obj) @@ -615,11 +615,11 @@ class Grid : public Component { // link(value) auto &link(const std::optional &obj) - { if (obj) link_values(obj.value()); return *this; } + { if (obj) link_values() = *obj; return *this; } // values(value) auto &values(const std::optional &obj) - { if (obj) link_values(obj.value()); return *this; } + { if (obj) link_values() = *obj; return *this; } // ------------------------ // Construction @@ -629,12 +629,12 @@ class Grid : public Component { Grid() : Component{ BlockData{}, - content.index, - content.interpolation, - content.label, - content.style, - content.unit, - content.link_values + this->index(), + this->interpolation(), + this->label(), + this->style(), + this->unit(), + this->link_values() } { Component::finish(); @@ -644,12 +644,12 @@ class Grid : public Component { Grid(const Grid &other) : Component{ other, - content.index, - content.interpolation, - content.label, - content.style, - content.unit, - content.link_values + this->index(), + this->interpolation(), + this->label(), + this->style(), + this->unit(), + this->link_values() }, content{other.content} { @@ -660,12 +660,12 @@ class Grid : public Component { Grid(Grid &&other) : Component{ other, - content.index, - content.interpolation, - content.label, - content.style, - content.unit, - content.link_values + this->index(), + this->interpolation(), + this->label(), + this->style(), + this->unit(), + this->link_values() }, content{std::move(other.content)} { @@ -676,12 +676,12 @@ class Grid : public Component { Grid(const Node &node) : Component{ BlockData{}, - content.index, - content.interpolation, - content.label, - content.style, - content.unit, - content.link_values + this->index(), + this->interpolation(), + this->label(), + this->style(), + this->unit(), + this->link_values() } { Component::finish(node); @@ -698,12 +698,12 @@ class Grid : public Component { ) : Component{ BlockData{}, - content.index, - content.interpolation, - content.label, - content.style, - content.unit, - content.link_values + this->index(), + this->interpolation(), + this->label(), + this->style(), + this->unit(), + this->link_values() }, content{ index, @@ -728,12 +728,12 @@ class Grid : public Component { ) : Component{ BlockData{}, - content.index, - content.interpolation, - content.label, - content.style, - content.unit, - content.link_values + this->index(), + this->interpolation(), + this->label(), + this->style(), + this->unit(), + this->link_values() }, content{ index, @@ -866,9 +866,9 @@ class Axis : public Component { Axis() : Component{ BlockData{}, - content.index, - content.label, - content.unit + this->index(), + this->label(), + this->unit() } { Component::finish(); @@ -878,9 +878,9 @@ class Axis : public Component { Axis(const Axis &other) : Component{ other, - content.index, - content.label, - content.unit + this->index(), + this->label(), + this->unit() }, content{other.content} { @@ -891,9 +891,9 @@ class Axis : public Component { Axis(Axis &&other) : Component{ other, - content.index, - content.label, - content.unit + this->index(), + this->label(), + this->unit() }, content{std::move(other.content)} { @@ -904,9 +904,9 @@ class Axis : public Component { Axis(const Node &node) : Component{ BlockData{}, - content.index, - content.label, - content.unit + this->index(), + this->label(), + this->unit() } { Component::finish(node); @@ -920,9 +920,9 @@ class Axis : public Component { ) : Component{ BlockData{}, - content.index, - content.label, - content.unit + this->index(), + this->label(), + this->unit() }, content{ index, @@ -1094,7 +1094,7 @@ class Axes : public Component { const std::size_t index, const std::optional &obj ) { - if (obj) axis_grid(index,obj.value()); + if (obj) axis_grid(index,*obj); return *this; } @@ -1103,7 +1103,7 @@ class Axes : public Component { const std::string &label, const std::optional &obj ) { - if (obj) axis_grid(label,obj.value()); + if (obj) axis_grid(label,*obj); return *this; } @@ -1112,7 +1112,7 @@ class Axes : public Component { const std::size_t index, const std::optional &obj ) { - if (obj) axis_grid(index,obj.value()); + if (obj) axis_grid(index,*obj); return *this; } @@ -1121,7 +1121,7 @@ class Axes : public Component { const std::string &label, const std::optional &obj ) { - if (obj) axis_grid(label,obj.value()); + if (obj) axis_grid(label,*obj); return *this; } @@ -1133,8 +1133,8 @@ class Axes : public Component { Axes() : Component{ BlockData{}, - content.href, - content.axis_grid + this->href(), + this->axis_grid() } { Component::finish(); @@ -1144,8 +1144,8 @@ class Axes : public Component { Axes(const Axes &other) : Component{ other, - content.href, - content.axis_grid + this->href(), + this->axis_grid() }, content{other.content} { @@ -1156,8 +1156,8 @@ class Axes : public Component { Axes(Axes &&other) : Component{ other, - content.href, - content.axis_grid + this->href(), + this->axis_grid() }, content{std::move(other.content)} { @@ -1168,8 +1168,8 @@ class Axes : public Component { Axes(const Node &node) : Component{ BlockData{}, - content.href, - content.axis_grid + this->href(), + this->axis_grid() } { Component::finish(node); @@ -1182,8 +1182,8 @@ class Axes : public Component { ) : Component{ BlockData{}, - content.href, - content.axis_grid + this->href(), + this->axis_grid() }, content{ href, @@ -1287,9 +1287,9 @@ class XYs1d : public Component { // interpolation const auto &interpolation() const - { return content.interpolation.value(); } + { return content.interpolation; } auto &interpolation() - { return content.interpolation.value(); } + { return content.interpolation; } // label const auto &label() const @@ -1327,9 +1327,9 @@ class XYs1d : public Component { // interpolation(value) auto &interpolation(const Defaulted &obj) - { content.interpolation = obj; return *this; } + { interpolation() = obj; return *this; } auto &interpolation(const enums::Interpolation &obj) - { content.interpolation = obj; return *this; } + { interpolation() = obj; return *this; } // label(value) auto &label(const std::optional &obj) @@ -1355,12 +1355,12 @@ class XYs1d : public Component { XYs1d() : Component{ BlockData{}, - content.index, - content.interpolation, - content.label, - content.outerDomainValue, - content.axes, - content.values + this->index(), + this->interpolation(), + this->label(), + this->outerDomainValue(), + this->axes(), + this->values() } { Component::finish(); @@ -1370,12 +1370,12 @@ class XYs1d : public Component { XYs1d(const XYs1d &other) : Component{ other, - content.index, - content.interpolation, - content.label, - content.outerDomainValue, - content.axes, - content.values + this->index(), + this->interpolation(), + this->label(), + this->outerDomainValue(), + this->axes(), + this->values() }, content{other.content} { @@ -1386,12 +1386,12 @@ class XYs1d : public Component { XYs1d(XYs1d &&other) : Component{ other, - content.index, - content.interpolation, - content.label, - content.outerDomainValue, - content.axes, - content.values + this->index(), + this->interpolation(), + this->label(), + this->outerDomainValue(), + this->axes(), + this->values() }, content{std::move(other.content)} { @@ -1402,12 +1402,12 @@ class XYs1d : public Component { XYs1d(const Node &node) : Component{ BlockData{}, - content.index, - content.interpolation, - content.label, - content.outerDomainValue, - content.axes, - content.values + this->index(), + this->interpolation(), + this->label(), + this->outerDomainValue(), + this->axes(), + this->values() } { Component::finish(node); @@ -1424,12 +1424,12 @@ class XYs1d : public Component { ) : Component{ BlockData{}, - content.index, - content.interpolation, - content.label, - content.outerDomainValue, - content.axes, - content.values + this->index(), + this->interpolation(), + this->label(), + this->outerDomainValue(), + this->axes(), + this->values() }, content{ index, @@ -1454,12 +1454,12 @@ class XYs1d : public Component { ) : Component{ BlockData{}, - content.index, - content.interpolation, - content.label, - content.outerDomainValue, - content.axes, - content.values + this->index(), + this->interpolation(), + this->label(), + this->outerDomainValue(), + this->axes(), + this->values() }, content{ index, @@ -1636,10 +1636,10 @@ class Regions1d : public Component { Regions1d() : Component{ BlockData{}, - content.label, - content.outerDomainValue, - content.XYs1d, - content.axes + this->label(), + this->outerDomainValue(), + this->XYs1d(), + this->axes() } { Component::finish(); @@ -1649,10 +1649,10 @@ class Regions1d : public Component { Regions1d(const Regions1d &other) : Component{ other, - content.label, - content.outerDomainValue, - content.XYs1d, - content.axes + this->label(), + this->outerDomainValue(), + this->XYs1d(), + this->axes() }, content{other.content} { @@ -1663,10 +1663,10 @@ class Regions1d : public Component { Regions1d(Regions1d &&other) : Component{ other, - content.label, - content.outerDomainValue, - content.XYs1d, - content.axes + this->label(), + this->outerDomainValue(), + this->XYs1d(), + this->axes() }, content{std::move(other.content)} { @@ -1677,10 +1677,10 @@ class Regions1d : public Component { Regions1d(const Node &node) : Component{ BlockData{}, - content.label, - content.outerDomainValue, - content.XYs1d, - content.axes + this->label(), + this->outerDomainValue(), + this->XYs1d(), + this->axes() } { Component::finish(node); @@ -1695,10 +1695,10 @@ class Regions1d : public Component { ) : Component{ BlockData{}, - content.label, - content.outerDomainValue, - content.XYs1d, - content.axes + this->label(), + this->outerDomainValue(), + this->XYs1d(), + this->axes() }, content{ label, @@ -1855,7 +1855,7 @@ class CrossSection : public Component { const std::size_t index, const std::optional &obj ) { - if (obj) XYs1d_regions1d(index,obj.value()); + if (obj) XYs1d_regions1d(index,*obj); return *this; } @@ -1864,7 +1864,7 @@ class CrossSection : public Component { const std::string &label, const std::optional &obj ) { - if (obj) XYs1d_regions1d(label,obj.value()); + if (obj) XYs1d_regions1d(label,*obj); return *this; } @@ -1873,7 +1873,7 @@ class CrossSection : public Component { const std::size_t index, const std::optional &obj ) { - if (obj) XYs1d_regions1d(index,obj.value()); + if (obj) XYs1d_regions1d(index,*obj); return *this; } @@ -1882,7 +1882,7 @@ class CrossSection : public Component { const std::string &label, const std::optional &obj ) { - if (obj) XYs1d_regions1d(label,obj.value()); + if (obj) XYs1d_regions1d(label,*obj); return *this; } @@ -1894,7 +1894,7 @@ class CrossSection : public Component { CrossSection() : Component{ BlockData{}, - content.XYs1d_regions1d + this->XYs1d_regions1d() } { Component::finish(); @@ -1904,7 +1904,7 @@ class CrossSection : public Component { CrossSection(const CrossSection &other) : Component{ other, - content.XYs1d_regions1d + this->XYs1d_regions1d() }, content{other.content} { @@ -1915,7 +1915,7 @@ class CrossSection : public Component { CrossSection(CrossSection &&other) : Component{ other, - content.XYs1d_regions1d + this->XYs1d_regions1d() }, content{std::move(other.content)} { @@ -1926,7 +1926,7 @@ class CrossSection : public Component { CrossSection(const Node &node) : Component{ BlockData{}, - content.XYs1d_regions1d + this->XYs1d_regions1d() } { Component::finish(node); @@ -1938,7 +1938,7 @@ class CrossSection : public Component { ) : Component{ BlockData{}, - content.XYs1d_regions1d + this->XYs1d_regions1d() }, content{ XYs1d_regions1d @@ -2080,10 +2080,10 @@ class Reaction : public Component { Reaction() : Component{ BlockData{}, - content.ENDF_MT, - content.fissionGenre, - content.label, - content.crossSection + this->ENDF_MT(), + this->fissionGenre(), + this->label(), + this->crossSection() } { Component::finish(); @@ -2093,10 +2093,10 @@ class Reaction : public Component { Reaction(const Reaction &other) : Component{ other, - content.ENDF_MT, - content.fissionGenre, - content.label, - content.crossSection + this->ENDF_MT(), + this->fissionGenre(), + this->label(), + this->crossSection() }, content{other.content} { @@ -2107,10 +2107,10 @@ class Reaction : public Component { Reaction(Reaction &&other) : Component{ other, - content.ENDF_MT, - content.fissionGenre, - content.label, - content.crossSection + this->ENDF_MT(), + this->fissionGenre(), + this->label(), + this->crossSection() }, content{std::move(other.content)} { @@ -2121,10 +2121,10 @@ class Reaction : public Component { Reaction(const Node &node) : Component{ BlockData{}, - content.ENDF_MT, - content.fissionGenre, - content.label, - content.crossSection + this->ENDF_MT(), + this->fissionGenre(), + this->label(), + this->crossSection() } { Component::finish(node); @@ -2139,10 +2139,10 @@ class Reaction : public Component { ) : Component{ BlockData{}, - content.ENDF_MT, - content.fissionGenre, - content.label, - content.crossSection + this->ENDF_MT(), + this->fissionGenre(), + this->label(), + this->crossSection() }, content{ ENDF_MT, @@ -2273,7 +2273,7 @@ class Reactions : public Component { Reactions() : Component{ BlockData{}, - content.reaction + this->reaction() } { Component::finish(); @@ -2283,7 +2283,7 @@ class Reactions : public Component { Reactions(const Reactions &other) : Component{ other, - content.reaction + this->reaction() }, content{other.content} { @@ -2294,7 +2294,7 @@ class Reactions : public Component { Reactions(Reactions &&other) : Component{ other, - content.reaction + this->reaction() }, content{std::move(other.content)} { @@ -2305,7 +2305,7 @@ class Reactions : public Component { Reactions(const Node &node) : Component{ BlockData{}, - content.reaction + this->reaction() } { Component::finish(node); @@ -2317,7 +2317,7 @@ class Reactions : public Component { ) : Component{ BlockData{}, - content.reaction + this->reaction() }, content{ reaction @@ -2498,13 +2498,13 @@ class ReactionSuite : public Component { ReactionSuite() : Component{ BlockData{}, - content.evaluation, - content.format, - content.interaction, - content.projectile, - content.projectileFrame, - content.target, - content.reactions + this->evaluation(), + this->format(), + this->interaction(), + this->projectile(), + this->projectileFrame(), + this->target(), + this->reactions() } { Component::finish(); @@ -2514,13 +2514,13 @@ class ReactionSuite : public Component { ReactionSuite(const ReactionSuite &other) : Component{ other, - content.evaluation, - content.format, - content.interaction, - content.projectile, - content.projectileFrame, - content.target, - content.reactions + this->evaluation(), + this->format(), + this->interaction(), + this->projectile(), + this->projectileFrame(), + this->target(), + this->reactions() }, content{other.content} { @@ -2531,13 +2531,13 @@ class ReactionSuite : public Component { ReactionSuite(ReactionSuite &&other) : Component{ other, - content.evaluation, - content.format, - content.interaction, - content.projectile, - content.projectileFrame, - content.target, - content.reactions + this->evaluation(), + this->format(), + this->interaction(), + this->projectile(), + this->projectileFrame(), + this->target(), + this->reactions() }, content{std::move(other.content)} { @@ -2548,13 +2548,13 @@ class ReactionSuite : public Component { ReactionSuite(const Node &node) : Component{ BlockData{}, - content.evaluation, - content.format, - content.interaction, - content.projectile, - content.projectileFrame, - content.target, - content.reactions + this->evaluation(), + this->format(), + this->interaction(), + this->projectile(), + this->projectileFrame(), + this->target(), + this->reactions() } { Component::finish(node); @@ -2572,13 +2572,13 @@ class ReactionSuite : public Component { ) : Component{ BlockData{}, - content.evaluation, - content.format, - content.interaction, - content.projectile, - content.projectileFrame, - content.target, - content.reactions + this->evaluation(), + this->format(), + this->interaction(), + this->projectile(), + this->projectileFrame(), + this->target(), + this->reactions() }, content{ evaluation, diff --git a/src/GNDStk/Component/test/sort.test.cpp b/src/GNDStk/Component/test/sort.test.cpp index c81d81fa1..e7c900656 100644 --- a/src/GNDStk/Component/test/sort.test.cpp +++ b/src/GNDStk/Component/test/sort.test.cpp @@ -54,8 +54,10 @@ struct IndexLabel { } content; std::string value; - std::size_t index() const { return content.index; }; - std::string label() const { return content.label; }; + const std::size_t &index() const { return content.index; }; + std::size_t &index() { return content.index; }; + const std::string &label() const { return content.label; }; + std::string &label() { return content.label; }; IndexLabel( const int index = 0, @@ -64,8 +66,8 @@ struct IndexLabel { ) : value(value) { - content.index = index; - content.label = label; + this->index() = index; + this->label() = label; } }; */ diff --git a/src/GNDStk/Node/src/detail.hpp b/src/GNDStk/Node/src/detail.hpp index 7230a614f..1557dc2d1 100644 --- a/src/GNDStk/Node/src/detail.hpp +++ b/src/GNDStk/Node/src/detail.hpp @@ -30,7 +30,7 @@ class is_optional> { }; template -inline constexpr bool isOptional = is_optional::value; +inline constexpr bool isOptional = is_optional>::value; diff --git a/src/GNDStk/precision/test/precision.test.hpp b/src/GNDStk/precision/test/precision.test.hpp index 1c42a7d86..8e9e2112b 100644 --- a/src/GNDStk/precision/test/precision.test.hpp +++ b/src/GNDStk/precision/test/precision.test.hpp @@ -93,9 +93,9 @@ class Floats : public Component { // start(value) Floats &start(const Defaulted &obj) - { BlockData::start(content.start = obj); return *this; } + { BlockData::start(start() = obj); return *this; } Floats &start(const std::optional &obj) - { BlockData::start(content.start = obj); return *this; } + { BlockData::start(start() = obj); return *this; } // valueType(value) Floats &valueType(const std::optional &obj) @@ -109,9 +109,9 @@ class Floats : public Component { Floats() : Component{ BlockData{}, - content.length, - content.start, - content.valueType + this->length(), + this->start(), + this->valueType() } { Component::finish(); @@ -121,9 +121,9 @@ class Floats : public Component { Floats(const Floats &other) : Component{ other, - content.length, - content.start, - content.valueType + this->length(), + this->start(), + this->valueType() }, content{other.content} { @@ -134,9 +134,9 @@ class Floats : public Component { Floats(Floats &&other) : Component{ other, - content.length, - content.start, - content.valueType + this->length(), + this->start(), + this->valueType() }, content{std::move(other.content)} { @@ -147,9 +147,9 @@ class Floats : public Component { Floats(const Node &node) : Component{ BlockData{}, - content.length, - content.start, - content.valueType + this->length(), + this->start(), + this->valueType() } { Component::finish(node); @@ -164,9 +164,9 @@ class Floats : public Component { ) : Component{ BlockData{}, - content.length, - content.start, - content.valueType + this->length(), + this->start(), + this->valueType() }, content{ length, @@ -182,9 +182,9 @@ class Floats : public Component { Floats(const std::vector &vector) : Component{ BlockData{}, - content.length, - content.start, - content.valueType + this->length(), + this->start(), + this->valueType() } { Component::finish(vector); @@ -299,9 +299,9 @@ class Doubles : public Component { // start(value) Doubles &start(const Defaulted &obj) - { BlockData::start(content.start = obj); return *this; } + { BlockData::start(start() = obj); return *this; } Doubles &start(const std::optional &obj) - { BlockData::start(content.start = obj); return *this; } + { BlockData::start(start() = obj); return *this; } // valueType(value) Doubles &valueType(const std::optional &obj) @@ -315,9 +315,9 @@ class Doubles : public Component { Doubles() : Component{ BlockData{}, - content.length, - content.start, - content.valueType + this->length(), + this->start(), + this->valueType() } { Component::finish(); @@ -327,9 +327,9 @@ class Doubles : public Component { Doubles(const Doubles &other) : Component{ other, - content.length, - content.start, - content.valueType + this->length(), + this->start(), + this->valueType() }, content{other.content} { @@ -340,9 +340,9 @@ class Doubles : public Component { Doubles(Doubles &&other) : Component{ other, - content.length, - content.start, - content.valueType + this->length(), + this->start(), + this->valueType() }, content{std::move(other.content)} { @@ -353,9 +353,9 @@ class Doubles : public Component { Doubles(const Node &node) : Component{ BlockData{}, - content.length, - content.start, - content.valueType + this->length(), + this->start(), + this->valueType() } { Component::finish(node); @@ -370,9 +370,9 @@ class Doubles : public Component { ) : Component{ BlockData{}, - content.length, - content.start, - content.valueType + this->length(), + this->start(), + this->valueType() }, content{ length, @@ -388,9 +388,9 @@ class Doubles : public Component { Doubles(const std::vector &vector) : Component{ BlockData{}, - content.length, - content.start, - content.valueType + this->length(), + this->start(), + this->valueType() } { Component::finish(vector); @@ -505,9 +505,9 @@ class Quads : public Component { // start(value) Quads &start(const Defaulted &obj) - { BlockData::start(content.start = obj); return *this; } + { BlockData::start(start() = obj); return *this; } Quads &start(const std::optional &obj) - { BlockData::start(content.start = obj); return *this; } + { BlockData::start(start() = obj); return *this; } // valueType(value) Quads &valueType(const std::optional &obj) @@ -521,9 +521,9 @@ class Quads : public Component { Quads() : Component{ BlockData{}, - content.length, - content.start, - content.valueType + this->length(), + this->start(), + this->valueType() } { Component::finish(); @@ -533,9 +533,9 @@ class Quads : public Component { Quads(const Quads &other) : Component{ other, - content.length, - content.start, - content.valueType + this->length(), + this->start(), + this->valueType() }, content{other.content} { @@ -546,9 +546,9 @@ class Quads : public Component { Quads(Quads &&other) : Component{ other, - content.length, - content.start, - content.valueType + this->length(), + this->start(), + this->valueType() }, content{std::move(other.content)} { @@ -559,9 +559,9 @@ class Quads : public Component { Quads(const Node &node) : Component{ BlockData{}, - content.length, - content.start, - content.valueType + this->length(), + this->start(), + this->valueType() } { Component::finish(node); @@ -576,9 +576,9 @@ class Quads : public Component { ) : Component{ BlockData{}, - content.length, - content.start, - content.valueType + this->length(), + this->start(), + this->valueType() }, content{ length, @@ -594,9 +594,9 @@ class Quads : public Component { Quads(const std::vector &vector) : Component{ BlockData{}, - content.length, - content.start, - content.valueType + this->length(), + this->start(), + this->valueType() } { Component::finish(vector); @@ -711,9 +711,9 @@ class Reals : public Component { // start(value) Reals &start(const Defaulted &obj) - { BlockData::start(content.start = obj); return *this; } + { BlockData::start(start() = obj); return *this; } Reals &start(const std::optional &obj) - { BlockData::start(content.start = obj); return *this; } + { BlockData::start(start() = obj); return *this; } // valueType(value) Reals &valueType(const std::optional &obj) @@ -727,9 +727,9 @@ class Reals : public Component { Reals() : Component{ BlockData{}, - content.length, - content.start, - content.valueType + this->length(), + this->start(), + this->valueType() } { Component::finish(); @@ -739,9 +739,9 @@ class Reals : public Component { Reals(const Reals &other) : Component{ other, - content.length, - content.start, - content.valueType + this->length(), + this->start(), + this->valueType() }, content{other.content} { @@ -752,9 +752,9 @@ class Reals : public Component { Reals(Reals &&other) : Component{ other, - content.length, - content.start, - content.valueType + this->length(), + this->start(), + this->valueType() }, content{std::move(other.content)} { @@ -765,9 +765,9 @@ class Reals : public Component { Reals(const Node &node) : Component{ BlockData{}, - content.length, - content.start, - content.valueType + this->length(), + this->start(), + this->valueType() } { Component::finish(node); @@ -782,9 +782,9 @@ class Reals : public Component { ) : Component{ BlockData{}, - content.length, - content.start, - content.valueType + this->length(), + this->start(), + this->valueType() }, content{ length, @@ -800,9 +800,9 @@ class Reals : public Component { Reals(const std::vector &vector) : Component{ BlockData{}, - content.length, - content.start, - content.valueType + this->length(), + this->start(), + this->valueType() } { Component::finish(vector); @@ -983,39 +983,39 @@ class Numbers : public Component { // adouble(value) Numbers &adouble(const Defaulted &obj) - { content.adouble = obj; return *this; } + { adouble() = obj; return *this; } Numbers &adouble(const std::optional &obj) - { content.adouble = obj; return *this; } + { adouble() = obj; return *this; } // afloat(value) Numbers &afloat(const Defaulted &obj) - { content.afloat = obj; return *this; } + { afloat() = obj; return *this; } Numbers &afloat(const std::optional &obj) - { content.afloat = obj; return *this; } + { afloat() = obj; return *this; } // aquad(value) Numbers &aquad(const Defaulted &obj) - { content.aquad = obj; return *this; } + { aquad() = obj; return *this; } Numbers &aquad(const std::optional &obj) - { content.aquad = obj; return *this; } + { aquad() = obj; return *this; } // bdouble(value) Numbers &bdouble(const Defaulted &obj) - { content.bdouble = obj; return *this; } + { bdouble() = obj; return *this; } Numbers &bdouble(const std::optional &obj) - { content.bdouble = obj; return *this; } + { bdouble() = obj; return *this; } // bfloat(value) Numbers &bfloat(const Defaulted &obj) - { content.bfloat = obj; return *this; } + { bfloat() = obj; return *this; } Numbers &bfloat(const std::optional &obj) - { content.bfloat = obj; return *this; } + { bfloat() = obj; return *this; } // bquad(value) Numbers &bquad(const Defaulted &obj) - { content.bquad = obj; return *this; } + { bquad() = obj; return *this; } Numbers &bquad(const std::optional &obj) - { content.bquad = obj; return *this; } + { bquad() = obj; return *this; } // doubles(value) Numbers &doubles(const std::optional &obj) @@ -1041,16 +1041,16 @@ class Numbers : public Component { Numbers() : Component{ BlockData{}, - content.adouble, - content.afloat, - content.aquad, - content.bdouble, - content.bfloat, - content.bquad, - content.doubles, - content.floats, - content.quads, - content.reals + this->adouble(), + this->afloat(), + this->aquad(), + this->bdouble(), + this->bfloat(), + this->bquad(), + this->doubles(), + this->floats(), + this->quads(), + this->reals() } { Component::finish(); @@ -1060,16 +1060,16 @@ class Numbers : public Component { Numbers(const Numbers &other) : Component{ other, - content.adouble, - content.afloat, - content.aquad, - content.bdouble, - content.bfloat, - content.bquad, - content.doubles, - content.floats, - content.quads, - content.reals + this->adouble(), + this->afloat(), + this->aquad(), + this->bdouble(), + this->bfloat(), + this->bquad(), + this->doubles(), + this->floats(), + this->quads(), + this->reals() }, content{other.content} { @@ -1080,16 +1080,16 @@ class Numbers : public Component { Numbers(Numbers &&other) : Component{ other, - content.adouble, - content.afloat, - content.aquad, - content.bdouble, - content.bfloat, - content.bquad, - content.doubles, - content.floats, - content.quads, - content.reals + this->adouble(), + this->afloat(), + this->aquad(), + this->bdouble(), + this->bfloat(), + this->bquad(), + this->doubles(), + this->floats(), + this->quads(), + this->reals() }, content{std::move(other.content)} { @@ -1100,16 +1100,16 @@ class Numbers : public Component { Numbers(const Node &node) : Component{ BlockData{}, - content.adouble, - content.afloat, - content.aquad, - content.bdouble, - content.bfloat, - content.bquad, - content.doubles, - content.floats, - content.quads, - content.reals + this->adouble(), + this->afloat(), + this->aquad(), + this->bdouble(), + this->bfloat(), + this->bquad(), + this->doubles(), + this->floats(), + this->quads(), + this->reals() } { Component::finish(node); @@ -1131,16 +1131,16 @@ class Numbers : public Component { ) : Component{ BlockData{}, - content.adouble, - content.afloat, - content.aquad, - content.bdouble, - content.bfloat, - content.bquad, - content.doubles, - content.floats, - content.quads, - content.reals + this->adouble(), + this->afloat(), + this->aquad(), + this->bdouble(), + this->bfloat(), + this->bquad(), + this->doubles(), + this->floats(), + this->quads(), + this->reals() }, content{ Defaulted(defaults.adouble,adouble), diff --git a/src/GNDStk/v1.9/containers/Axes.hpp b/src/GNDStk/v1.9/containers/Axes.hpp index 77ab9159e..23eb5e590 100644 --- a/src/GNDStk/v1.9/containers/Axes.hpp +++ b/src/GNDStk/v1.9/containers/Axes.hpp @@ -217,8 +217,8 @@ class Axes : public Component { ) : Component{ BlockData{}, - content.href, - content.axis_grid + this->href(), + this->axis_grid() }, content{ href, @@ -232,8 +232,8 @@ class Axes : public Component { Axes(const Axes &other) : Component{ other.baseBlockData(), - content.href, - content.axis_grid + this->href(), + this->axis_grid() }, content{other.content} { @@ -244,8 +244,8 @@ class Axes : public Component { Axes(Axes &&other) : Component{ other.baseBlockData(), - content.href, - content.axis_grid + this->href(), + this->axis_grid() }, content{std::move(other.content)} { @@ -256,8 +256,8 @@ class Axes : public Component { Axes(const Node &node) : Component{ BlockData{}, - content.href, - content.axis_grid + this->href(), + this->axis_grid() } { Component::finish(node); diff --git a/src/GNDStk/v1.9/containers/Axis.hpp b/src/GNDStk/v1.9/containers/Axis.hpp index 003b833f3..9eec5a253 100644 --- a/src/GNDStk/v1.9/containers/Axis.hpp +++ b/src/GNDStk/v1.9/containers/Axis.hpp @@ -129,9 +129,9 @@ class Axis : public Component { ) : Component{ BlockData{}, - content.index, - content.label, - content.unit + this->index(), + this->label(), + this->unit() }, content{ index, @@ -146,9 +146,9 @@ class Axis : public Component { Axis(const Axis &other) : Component{ other.baseBlockData(), - content.index, - content.label, - content.unit + this->index(), + this->label(), + this->unit() }, content{other.content} { @@ -159,9 +159,9 @@ class Axis : public Component { Axis(Axis &&other) : Component{ other.baseBlockData(), - content.index, - content.label, - content.unit + this->index(), + this->label(), + this->unit() }, content{std::move(other.content)} { @@ -172,9 +172,9 @@ class Axis : public Component { Axis(const Node &node) : Component{ BlockData{}, - content.index, - content.label, - content.unit + this->index(), + this->label(), + this->unit() } { Component::finish(node); diff --git a/src/GNDStk/v1.9/containers/Grid.hpp b/src/GNDStk/v1.9/containers/Grid.hpp index 07ab1c195..e58c8bbab 100644 --- a/src/GNDStk/v1.9/containers/Grid.hpp +++ b/src/GNDStk/v1.9/containers/Grid.hpp @@ -159,9 +159,9 @@ class Grid : public Component { // interpolation(value) Grid &interpolation(const Defaulted &obj) - { content.interpolation = obj; return *this; } + { interpolation() = obj; return *this; } Grid &interpolation(const std::optional &obj) - { content.interpolation = obj; return *this; } + { interpolation() = obj; return *this; } // label(value) Grid &label(const std::optional &obj) @@ -209,12 +209,12 @@ class Grid : public Component { ) : Component{ BlockData{}, - content.index, - content.interpolation, - content.label, - content.style, - content.unit, - content.link_values + this->index(), + this->interpolation(), + this->label(), + this->style(), + this->unit(), + this->link_values() }, content{ index, @@ -232,12 +232,12 @@ class Grid : public Component { Grid(const Grid &other) : Component{ other.baseBlockData(), - content.index, - content.interpolation, - content.label, - content.style, - content.unit, - content.link_values + this->index(), + this->interpolation(), + this->label(), + this->style(), + this->unit(), + this->link_values() }, content{other.content} { @@ -248,12 +248,12 @@ class Grid : public Component { Grid(Grid &&other) : Component{ other.baseBlockData(), - content.index, - content.interpolation, - content.label, - content.style, - content.unit, - content.link_values + this->index(), + this->interpolation(), + this->label(), + this->style(), + this->unit(), + this->link_values() }, content{std::move(other.content)} { @@ -264,12 +264,12 @@ class Grid : public Component { Grid(const Node &node) : Component{ BlockData{}, - content.index, - content.interpolation, - content.label, - content.style, - content.unit, - content.link_values + this->index(), + this->interpolation(), + this->label(), + this->style(), + this->unit(), + this->link_values() } { Component::finish(node); diff --git a/src/GNDStk/v1.9/containers/Link.hpp b/src/GNDStk/v1.9/containers/Link.hpp index 7f06746d8..26e4047dc 100644 --- a/src/GNDStk/v1.9/containers/Link.hpp +++ b/src/GNDStk/v1.9/containers/Link.hpp @@ -99,7 +99,7 @@ class Link : public Component { ) : Component{ BlockData{}, - content.href + this->href() }, content{ href @@ -112,7 +112,7 @@ class Link : public Component { Link(const Link &other) : Component{ other.baseBlockData(), - content.href + this->href() }, content{other.content} { @@ -123,7 +123,7 @@ class Link : public Component { Link(Link &&other) : Component{ other.baseBlockData(), - content.href + this->href() }, content{std::move(other.content)} { @@ -134,7 +134,7 @@ class Link : public Component { Link(const Node &node) : Component{ BlockData{}, - content.href + this->href() } { Component::finish(node); diff --git a/src/GNDStk/v1.9/containers/Regions1d.hpp b/src/GNDStk/v1.9/containers/Regions1d.hpp index f28147400..6e0fca2c3 100644 --- a/src/GNDStk/v1.9/containers/Regions1d.hpp +++ b/src/GNDStk/v1.9/containers/Regions1d.hpp @@ -182,10 +182,10 @@ class Regions1d : public Component { ) : Component{ BlockData{}, - content.label, - content.outerDomainValue, - content.XYs1d, - content.axes + this->label(), + this->outerDomainValue(), + this->XYs1d(), + this->axes() }, content{ label, @@ -201,10 +201,10 @@ class Regions1d : public Component { Regions1d(const Regions1d &other) : Component{ other.baseBlockData(), - content.label, - content.outerDomainValue, - content.XYs1d, - content.axes + this->label(), + this->outerDomainValue(), + this->XYs1d(), + this->axes() }, content{other.content} { @@ -215,10 +215,10 @@ class Regions1d : public Component { Regions1d(Regions1d &&other) : Component{ other.baseBlockData(), - content.label, - content.outerDomainValue, - content.XYs1d, - content.axes + this->label(), + this->outerDomainValue(), + this->XYs1d(), + this->axes() }, content{std::move(other.content)} { @@ -229,10 +229,10 @@ class Regions1d : public Component { Regions1d(const Node &node) : Component{ BlockData{}, - content.label, - content.outerDomainValue, - content.XYs1d, - content.axes + this->label(), + this->outerDomainValue(), + this->XYs1d(), + this->axes() } { Component::finish(node); diff --git a/src/GNDStk/v1.9/containers/Values.hpp b/src/GNDStk/v1.9/containers/Values.hpp index b5285c362..62980584c 100644 --- a/src/GNDStk/v1.9/containers/Values.hpp +++ b/src/GNDStk/v1.9/containers/Values.hpp @@ -111,15 +111,15 @@ class Values : public Component { // start(value) Values &start(const Defaulted &obj) - { BlockData::start(content.start = obj); return *this; } + { BlockData::start(start() = obj); return *this; } Values &start(const std::optional &obj) - { BlockData::start(content.start = obj); return *this; } + { BlockData::start(start() = obj); return *this; } // valueType(value) Values &valueType(const Defaulted &obj) - { BlockData::valueType(content.valueType = obj); return *this; } + { BlockData::valueType(valueType() = obj); return *this; } Values &valueType(const std::optional &obj) - { BlockData::valueType(content.valueType = obj); return *this; } + { BlockData::valueType(valueType() = obj); return *this; } // ------------------------ // Constructors @@ -137,9 +137,9 @@ class Values : public Component { ) : Component{ BlockData{}, - content.length, - content.start, - content.valueType + this->length(), + this->start(), + this->valueType() }, content{ length, @@ -154,9 +154,9 @@ class Values : public Component { Values(const Values &other) : Component{ other.baseBlockData(), - content.length, - content.start, - content.valueType + this->length(), + this->start(), + this->valueType() }, content{other.content} { @@ -167,9 +167,9 @@ class Values : public Component { Values(Values &&other) : Component{ other.baseBlockData(), - content.length, - content.start, - content.valueType + this->length(), + this->start(), + this->valueType() }, content{std::move(other.content)} { @@ -180,9 +180,9 @@ class Values : public Component { Values(const Node &node) : Component{ BlockData{}, - content.length, - content.start, - content.valueType + this->length(), + this->start(), + this->valueType() } { Component::finish(node); @@ -193,9 +193,9 @@ class Values : public Component { Values(const std::vector &vector) : Component{ BlockData{}, - content.length, - content.start, - content.valueType + this->length(), + this->start(), + this->valueType() } { Component::finish(vector); diff --git a/src/GNDStk/v1.9/containers/Values/src/custom.hpp b/src/GNDStk/v1.9/containers/Values/src/custom.hpp index f77ea0919..6c58a1714 100644 --- a/src/GNDStk/v1.9/containers/Values/src/custom.hpp +++ b/src/GNDStk/v1.9/containers/Values/src/custom.hpp @@ -45,9 +45,9 @@ const std::vector< T >& values ) : Component{ BlockData{}, - content.length, - content.start, - content.valueType + this->length(), + this->start(), + this->valueType() } { diff --git a/src/GNDStk/v1.9/containers/XYs1d.hpp b/src/GNDStk/v1.9/containers/XYs1d.hpp index 65be739fd..578d9b4ff 100644 --- a/src/GNDStk/v1.9/containers/XYs1d.hpp +++ b/src/GNDStk/v1.9/containers/XYs1d.hpp @@ -142,9 +142,9 @@ class XYs1d : public Component { // interpolation(value) XYs1d &interpolation(const Defaulted &obj) - { content.interpolation = obj; return *this; } + { interpolation() = obj; return *this; } XYs1d &interpolation(const std::optional &obj) - { content.interpolation = obj; return *this; } + { interpolation() = obj; return *this; } // label(value) XYs1d &label(const std::optional &obj) @@ -184,12 +184,12 @@ class XYs1d : public Component { ) : Component{ BlockData{}, - content.index, - content.interpolation, - content.label, - content.outerDomainValue, - content.axes, - content.values + this->index(), + this->interpolation(), + this->label(), + this->outerDomainValue(), + this->axes(), + this->values() }, content{ index, @@ -207,12 +207,12 @@ class XYs1d : public Component { XYs1d(const XYs1d &other) : Component{ other.baseBlockData(), - content.index, - content.interpolation, - content.label, - content.outerDomainValue, - content.axes, - content.values + this->index(), + this->interpolation(), + this->label(), + this->outerDomainValue(), + this->axes(), + this->values() }, content{other.content} { @@ -223,12 +223,12 @@ class XYs1d : public Component { XYs1d(XYs1d &&other) : Component{ other.baseBlockData(), - content.index, - content.interpolation, - content.label, - content.outerDomainValue, - content.axes, - content.values + this->index(), + this->interpolation(), + this->label(), + this->outerDomainValue(), + this->axes(), + this->values() }, content{std::move(other.content)} { @@ -239,12 +239,12 @@ class XYs1d : public Component { XYs1d(const Node &node) : Component{ BlockData{}, - content.index, - content.interpolation, - content.label, - content.outerDomainValue, - content.axes, - content.values + this->index(), + this->interpolation(), + this->label(), + this->outerDomainValue(), + this->axes(), + this->values() } { Component::finish(node); diff --git a/src/GNDStk/v1.9/transport/CrossSection.hpp b/src/GNDStk/v1.9/transport/CrossSection.hpp index 5b86a214f..9f2251327 100644 --- a/src/GNDStk/v1.9/transport/CrossSection.hpp +++ b/src/GNDStk/v1.9/transport/CrossSection.hpp @@ -200,7 +200,7 @@ class CrossSection : public Component { ) : Component{ BlockData{}, - content.XYs1d_regions1d + this->XYs1d_regions1d() }, content{ XYs1d_regions1d @@ -213,7 +213,7 @@ class CrossSection : public Component { CrossSection(const CrossSection &other) : Component{ other.baseBlockData(), - content.XYs1d_regions1d + this->XYs1d_regions1d() }, content{other.content} { @@ -224,7 +224,7 @@ class CrossSection : public Component { CrossSection(CrossSection &&other) : Component{ other.baseBlockData(), - content.XYs1d_regions1d + this->XYs1d_regions1d() }, content{std::move(other.content)} { @@ -235,7 +235,7 @@ class CrossSection : public Component { CrossSection(const Node &node) : Component{ BlockData{}, - content.XYs1d_regions1d + this->XYs1d_regions1d() } { Component::finish(node); diff --git a/src/GNDStk/v1.9/transport/Reaction.hpp b/src/GNDStk/v1.9/transport/Reaction.hpp index 795623b0f..75935a6c7 100644 --- a/src/GNDStk/v1.9/transport/Reaction.hpp +++ b/src/GNDStk/v1.9/transport/Reaction.hpp @@ -149,10 +149,10 @@ class Reaction : public Component { ) : Component{ BlockData{}, - content.ENDF_MT, - content.fissionGenre, - content.label, - content.crossSection + this->ENDF_MT(), + this->fissionGenre(), + this->label(), + this->crossSection() }, content{ ENDF_MT, @@ -168,10 +168,10 @@ class Reaction : public Component { Reaction(const Reaction &other) : Component{ other.baseBlockData(), - content.ENDF_MT, - content.fissionGenre, - content.label, - content.crossSection + this->ENDF_MT(), + this->fissionGenre(), + this->label(), + this->crossSection() }, content{other.content} { @@ -182,10 +182,10 @@ class Reaction : public Component { Reaction(Reaction &&other) : Component{ other.baseBlockData(), - content.ENDF_MT, - content.fissionGenre, - content.label, - content.crossSection + this->ENDF_MT(), + this->fissionGenre(), + this->label(), + this->crossSection() }, content{std::move(other.content)} { @@ -196,10 +196,10 @@ class Reaction : public Component { Reaction(const Node &node) : Component{ BlockData{}, - content.ENDF_MT, - content.fissionGenre, - content.label, - content.crossSection + this->ENDF_MT(), + this->fissionGenre(), + this->label(), + this->crossSection() } { Component::finish(node); diff --git a/src/GNDStk/v1.9/transport/ReactionSuite.hpp b/src/GNDStk/v1.9/transport/ReactionSuite.hpp index 0fc398065..f91f87580 100644 --- a/src/GNDStk/v1.9/transport/ReactionSuite.hpp +++ b/src/GNDStk/v1.9/transport/ReactionSuite.hpp @@ -194,13 +194,13 @@ class ReactionSuite : public Component { ) : Component{ BlockData{}, - content.evaluation, - content.format, - content.interaction, - content.projectile, - content.projectileFrame, - content.target, - content.reactions + this->evaluation(), + this->format(), + this->interaction(), + this->projectile(), + this->projectileFrame(), + this->target(), + this->reactions() }, content{ evaluation, @@ -219,13 +219,13 @@ class ReactionSuite : public Component { ReactionSuite(const ReactionSuite &other) : Component{ other.baseBlockData(), - content.evaluation, - content.format, - content.interaction, - content.projectile, - content.projectileFrame, - content.target, - content.reactions + this->evaluation(), + this->format(), + this->interaction(), + this->projectile(), + this->projectileFrame(), + this->target(), + this->reactions() }, content{other.content} { @@ -236,13 +236,13 @@ class ReactionSuite : public Component { ReactionSuite(ReactionSuite &&other) : Component{ other.baseBlockData(), - content.evaluation, - content.format, - content.interaction, - content.projectile, - content.projectileFrame, - content.target, - content.reactions + this->evaluation(), + this->format(), + this->interaction(), + this->projectile(), + this->projectileFrame(), + this->target(), + this->reactions() }, content{std::move(other.content)} { @@ -253,13 +253,13 @@ class ReactionSuite : public Component { ReactionSuite(const Node &node) : Component{ BlockData{}, - content.evaluation, - content.format, - content.interaction, - content.projectile, - content.projectileFrame, - content.target, - content.reactions + this->evaluation(), + this->format(), + this->interaction(), + this->projectile(), + this->projectileFrame(), + this->target(), + this->reactions() } { Component::finish(node); diff --git a/src/GNDStk/v1.9/transport/Reactions.hpp b/src/GNDStk/v1.9/transport/Reactions.hpp index 4c740fc4b..1b112288e 100644 --- a/src/GNDStk/v1.9/transport/Reactions.hpp +++ b/src/GNDStk/v1.9/transport/Reactions.hpp @@ -134,7 +134,7 @@ class Reactions : public Component { ) : Component{ BlockData{}, - content.reaction + this->reaction() }, content{ reaction @@ -147,7 +147,7 @@ class Reactions : public Component { Reactions(const Reactions &other) : Component{ other.baseBlockData(), - content.reaction + this->reaction() }, content{other.content} { @@ -158,7 +158,7 @@ class Reactions : public Component { Reactions(Reactions &&other) : Component{ other.baseBlockData(), - content.reaction + this->reaction() }, content{std::move(other.content)} { @@ -169,7 +169,7 @@ class Reactions : public Component { Reactions(const Node &node) : Component{ BlockData{}, - content.reaction + this->reaction() } { Component::finish(node); From 2c606ea4ca18ffd55bdc8da9d5961042e74415e9 Mon Sep 17 00:00:00 2001 From: Martin Staley Date: Wed, 22 Dec 2021 21:28:43 -0700 Subject: [PATCH 28/39] Identify "special" nodes by making their names, well, special. This is a change I've wanted to do for a while. I think it's the right thing to do. See the largest change in ``primer.rst`` for a brief description of why I did this. The Core Interface's internal structure has always made use of a handful of special names, to identify certain nodes that aren't in GNDS proper, but which need to be used in order to store certain special content. Naturally, special content needs special handling. Example: what arrives through PugiXML as XML CDATA content *was* stored in GNDStk's internal structure under a child node called ``cdata``. In fact, it was in a ``text`` metadatum inside of a ``cdata`` node. Now, the node is called ``#cdata`` and the metadatum is called ``#text``. That is, each name is now prefixed with ``#``. Adding the ``#`` prefix is just a small change, but it's meant for a couple of important purposes. First, its presence allows someone who looks at GNDStk's code base to easily identify special nodes -- which, generally, need special handling, at least in regards to activities such as I/O. Second, it's always possible that a future GNDS standard (or, importantly, another format that someone might design with our code generator) might want to have a field called ``foo``, where foo is one of our handful of special names that trigger special handling. By renaming ours to ``#foo`` instead, no conflicts will arise. (And someone won't use the ``#`` themselves for the name of a field. It wouldn't work when the associated class or object is created in C++, which of course doesn't allow such a character in variable names.) I'd have liked to use ``$`` in place of ``#``, but realized right away that doing so would be problematic. Functions like ``Node.one()`` use regular-expression searches, and the ``$`` character has a special meaning in C++ regular expressions. Clearly, then, using ``$`` would lead to various problems. So, we chose what we believe is a reasonable alternative, and one that we think is as good as any other. Note that the changes in this PR, while relatively simple, were a bit more involved than just changing ``foo`` to ``#foo`` for every ``special`` name ``foo``. Where JSON is involved, for example, you'll see that the use of ``#`` sometimes necessitated changes in node order, given that the JSON library orders nodes lexicographically. Also, some strings for special node names, for example ``xml``, also have meaning for other things: ``xml`` was a special node name, but ``xml`` is also a string someone can use, in certain places, to say that they want XML format. So, some instances of the string ``xml`` are now ``#xml``, but others remain as ``xml``. --- docs/primer.rst | 40 +++++++---- docs/tutorial/employees.json | 12 ++-- src/GNDStk/Component/src/toNodeData.hpp | 4 +- src/GNDStk/Component/test/Component.test.cpp | 2 +- src/GNDStk/JSON/test/JSON.test.cpp | 34 ++++----- .../test/resources/n-069_Tm_170-covar.json | 26 +++---- src/GNDStk/Node/src/special.hpp | 8 +-- src/GNDStk/Node/test/add.test.cpp | 2 +- src/GNDStk/Node/test/sort.test.cpp | 4 +- src/GNDStk/Node/test/write.test.cpp | 4 +- src/GNDStk/Tree/src/decl.hpp | 2 +- src/GNDStk/Tree/src/has_decl.hpp | 2 +- src/GNDStk/Tree/src/has_top.hpp | 2 +- src/GNDStk/Tree/src/reset.hpp | 8 +-- src/GNDStk/Tree/src/top.hpp | 2 +- src/GNDStk/Tree/test/call.test.cpp | 2 +- src/GNDStk/Tree/test/child.test.cpp | 4 +- src/GNDStk/Tree/test/ctor.test.cpp | 14 ++-- src/GNDStk/Tree/test/decl.test.cpp | 16 ++--- src/GNDStk/Tree/test/many.test.cpp | 10 +-- src/GNDStk/Tree/test/one.test.cpp | 14 ++-- src/GNDStk/Tree/test/read.test.cpp | 70 +++++++++---------- src/GNDStk/Tree/test/reset.test.cpp | 18 ++--- .../test/resources/n-069_Tm_170-covar.json | 26 +++---- src/GNDStk/Tree/test/top.test.cpp | 4 +- src/GNDStk/Tree/test/write.test.cpp | 38 +++++----- src/GNDStk/XML/test/XML.test.cpp | 2 +- .../test/resources/n-069_Tm_170-covar.json | 26 +++---- src/GNDStk/basic/src/child.hpp | 8 +-- src/GNDStk/basic/src/meta.hpp | 2 +- src/GNDStk/common.hpp | 10 +-- src/GNDStk/common/src/detail.hpp | 10 +-- src/GNDStk/convert/src/HDF5.hpp | 2 +- src/GNDStk/convert/src/JSON.hpp | 2 +- src/GNDStk/convert/src/Tree.hpp | 10 +-- src/GNDStk/convert/src/XML.hpp | 6 +- src/GNDStk/convert/src/detail.hpp | 54 +++++++------- src/GNDStk/misc/src/child.hpp | 16 ++--- src/GNDStk/misc/src/detail.hpp | 2 +- src/GNDStk/node2type/test/node2type.test.cpp | 6 +- src/GNDStk/type2node/test/type2node.test.cpp | 8 +-- src/GNDStk/utility.hpp | 6 +- 42 files changed, 276 insertions(+), 262 deletions(-) diff --git a/docs/primer.rst b/docs/primer.rst index 3de4cfd7b..3f3c789b0 100644 --- a/docs/primer.rst +++ b/docs/primer.rst @@ -404,7 +404,7 @@ Several remarks are in order here. The comparison operator for ``Tree`` compares the two GNDS trees in an *order-agnostic* manner. GNDS fundamentally provides data in two places: nodes (think XML "elements") in its overall tree structure, and metadata (think XML -"attributes"). The GNDS standard does not, however, consider ordering to be +attributes). The GNDS standard does not, however, consider ordering to be important. One tree node's child nodes or metadata, anywhere or everywhere throughout the entire tree structure, could be reordered arbitrarily, but if each remains equivalent -- in the same respect that we consider two mathematical @@ -490,14 +490,28 @@ with what XML is able to represent. the node. For example, in HDF5 the attribute ``nodeIndex`` could be added to each child in a group. -For (1), GNDStk does the first suggested action: it groups all of a node's -attributes under a child node called ``attributes``. We consider that to be -cleaner than using an ``_attr`` suffix. - -For (2), GNDStk does exactly as illustrated: multiple elements of the same name -are suffixed with ``0``, ``1``, etc. And, then, a JSON name/value pair with the -name ``nodeName``, as suggested, is created in order to preserve the original -*unsuffixed* element's name. +For (1), GNDStk does the first suggested action (which we think is +somewhat cleaner than using an ``_attr`` suffix), but with a slight twist: +it groups a node's attributes under a child node called ``#attributes``. The +``#`` prefix is something we use in node names throughout GNDStk, if and where +the nodes so named represent special things -- with special meaning, and needing +special treatment. The extra character allows special nodes to be identified +easily, in both the GNDStk code base itself or in files produced by GNDStk. +Moreover, one could imagine that a future GNDS version might -- just might -- +have a normal node with the name ``attributes``, or with some other name that +we might wish to use for a special purpose. If and where such situations occur, +our use of a special prefix character allows for an unambiguous interpretation. +(As an aside: in principle, we'd have preferred to use the S-like dollar sign, +``$``, to inside S for "special" node. Unfortunately, ``$`` has a particular +meaning in the C++ regular-expression library. As such, ``$`` is unsuitable +for use in identifying special nodes, as our various node-finding capabilities +support the use of regular expressions.) + +For (2), GNDStk does as suggested, except again with the ``#`` terminology as +described above. Multiple elements of the same name are suffixed with ``0``, +``1``, etc. Then, a JSON name/value pair with the name ``#nodeName`` -- as +suggested, but with our ``#`` prefix -- is created. Its value preserves the +original element's name. For (3), GNDStk does nothing in particular right now. Our understanding of GNDS is that it's designed so that elements -- nodes -- can appear in any order. @@ -547,8 +561,8 @@ node. (Valid GNDS top-level nodes, per the standard, are ``reactionSuite``, about it for now. Naturally, GNDStk reverses the modifications when we *read* from a JSON file -into our internal format. Specifically: values in an ``attributes`` block are -transformed into metadata in the enclosing node, and values from ``nodeName`` +into our internal format. Specifically: values in an ``#attributes`` block are +transformed into metadata in the enclosing node, and values from ``#nodeName`` name/value pairs replace index-suffixed names. At this time, GNDStk provides no other options, such as the ``_attr`` suffix @@ -558,7 +572,7 @@ We're not aware, at the time of this writing, of the existence any official JSON-format GNDS files. If and when such files come into existence, and if such files use a different scheme than we do for addressing the issues described above, then we'll provide capabilities at least for reading those -files, and perhaps for writing them in that manner as well. +files, and perhaps for writing files in that manner as well. @@ -768,7 +782,7 @@ the top of the ``n-094_Pu_239.xml`` GNDS file: :language: xml Here, an outer ``evaluated`` node (XML "element") contains four metadata -key/value pairs (XML "attributes") and two child elements. The first child +key/value pairs (XML attributes) and two child elements. The first child element, ``temperature``, contains two metadata pairs but no further child nodes. The second child element, ``projectileEnergyDomain``, contains three metadata pairs but no further child nodes. diff --git a/docs/tutorial/employees.json b/docs/tutorial/employees.json index 37bb8442b..cdfd9ff8e 100644 --- a/docs/tutorial/employees.json +++ b/docs/tutorial/employees.json @@ -2,30 +2,30 @@ "employees": { "employee0": { "name": { - "attributes": { + "#attributes": { "first": "Doc", "last": "Jones" } }, - "nodeName": "employee" + "#nodeName": "employee" }, "employee1": { "name": { - "attributes": { + "#attributes": { "first": "Grumpy", "last": "Smith" } }, - "nodeName": "employee" + "#nodeName": "employee" }, "employee2": { "name": { - "attributes": { + "#attributes": { "first": "Happy", "last": "Earp" } }, - "nodeName": "employee" + "#nodeName": "employee" } } } \ No newline at end of file diff --git a/src/GNDStk/Component/src/toNodeData.hpp b/src/GNDStk/Component/src/toNodeData.hpp index 8b835d618..0e25bc3be 100644 --- a/src/GNDStk/Component/src/toNodeData.hpp +++ b/src/GNDStk/Component/src/toNodeData.hpp @@ -4,8 +4,8 @@ Node node(DERIVED::GNDSName()); // 2. Block data, if applicable if constexpr (hasBlockData) { - // GNDStk uses a "text" metadatum of a "pcdata" child node for this - std::string &text = node.add("pcdata").add("text","").second; + // GNDStk uses a "#text" metadatum of a "#pcdata" child node for this + std::string &text = node.add("#pcdata").add("#text","").second; // Note: the following call might compute length, start, and valueType; // so we need all of this before the upcoming writing of fields. BLOCKDATA::toNode(text,derived().content); diff --git a/src/GNDStk/Component/test/Component.test.cpp b/src/GNDStk/Component/test/Component.test.cpp index d4d1c1870..ab87dd839 100644 --- a/src/GNDStk/Component/test/Component.test.cpp +++ b/src/GNDStk/Component/test/Component.test.cpp @@ -192,7 +192,7 @@ SCENARIO("Testing GNDStk Component") { der << "{" " \"data\": {" - " \"attributes\": {" + " \"#attributes\": {" " \"foo\": \"12\"," " \"bar\": \"34.56\"" " }" diff --git a/src/GNDStk/JSON/test/JSON.test.cpp b/src/GNDStk/JSON/test/JSON.test.cpp index 1dd390a3c..0cab6cf49 100644 --- a/src/GNDStk/JSON/test/JSON.test.cpp +++ b/src/GNDStk/JSON/test/JSON.test.cpp @@ -14,7 +14,7 @@ using namespace njoy::GNDStk; static const std::string string_real_json = R"***({ "covarianceSuite": { - "attributes": { + "#attributes": { "evaluation": "ENDF/B-8.0", "format": "1.9", "projectile": "n", @@ -22,7 +22,7 @@ R"***({ }, "externalFiles": { "externalFile": { - "attributes": { + "#attributes": { "label": "reactions", "path": "n-069_Tm_170.xml" } @@ -30,30 +30,30 @@ R"***({ }, "parameterCovariances": { "parameterCovariance": { - "attributes": { + "#attributes": { "label": "resolved resonances" }, "parameterCovarianceMatrix": { + "#attributes": { + "label": "eval", + "type": "absolute" + }, "array": { - "attributes": { + "#attributes": { "compression": "diagonal", "shape": "78,78" }, "values": { - "pcdata": { - "attributes": { - "text": "0.015 0 0 0 4.5e-5 0.015 3e-2 0 0 0 1.35e-4 0.015 2e-2 0 0 0 1.5e-3 0.012 5e-2 0 0 0 1.875e-3 6e-2 5e-2 0 0 0 1.05e-4 0.015 0.1 0 0 0 6e-4 0.012 0.1 0 0 0 2.25e-4 0.012 0.2 0 0 0 5.25e-3 0.012 0.2 0 0 0 3.45e-3 0.012 0.3 0 0 0 4.5e-4 0.012 0.3 0 0 0 3e-3 0.012 0.4 0 0 0 9e-3 0.012 0.4 0 0 0 1.425e-3 0.012" + "#pcdata": { + "#attributes": { + "#text": "0.015 0 0 0 4.5e-5 0.015 3e-2 0 0 0 1.35e-4 0.015 2e-2 0 0 0 1.5e-3 0.012 5e-2 0 0 0 1.875e-3 6e-2 5e-2 0 0 0 1.05e-4 0.015 0.1 0 0 0 6e-4 0.012 0.1 0 0 0 2.25e-4 0.012 0.2 0 0 0 5.25e-3 0.012 0.2 0 0 0 3.45e-3 0.012 0.3 0 0 0 4.5e-4 0.012 0.3 0 0 0 3e-3 0.012 0.4 0 0 0 9e-3 0.012 0.4 0 0 0 1.425e-3 0.012" } } } }, - "attributes": { - "label": "eval", - "type": "absolute" - }, "parameters": { "parameterLink": { - "attributes": { + "#attributes": { "href": "$reactions#/reactionSuite/resonances/resolved/BreitWigner[@label='eval']/resonanceParameters/table", "label": "resonanceParameters", "nParameters": "78" @@ -62,7 +62,7 @@ R"***({ } }, "rowData": { - "attributes": { + "#attributes": { "href": "$reactions#/reactionSuite/resonances/resolved/BreitWigner[@label='eval']" } } @@ -70,21 +70,21 @@ R"***({ }, "styles": { "evaluated": { - "attributes": { + "#attributes": { "date": "2011-10-01", "label": "eval", "library": "ENDF/B", "version": "8.0.1" }, "projectileEnergyDomain": { - "attributes": { + "#attributes": { "max": "30000000.0", "min": "1e-05", "unit": "eV" } }, "temperature": { - "attributes": { + "#attributes": { "unit": "K", "value": "0.0" } @@ -120,7 +120,7 @@ SCENARIO("Testing GNDStk JSON") { THEN("The Tree should have only an empty declaration node") { CHECK(t.children.size() == 1); CHECK(t.has_decl()); - CHECK(t.decl().name == "json"); + CHECK(t.decl().name == "#json"); CHECK(t.decl().metadata.size() == 0); CHECK(t.decl().children.size() == 0); } diff --git a/src/GNDStk/JSON/test/resources/n-069_Tm_170-covar.json b/src/GNDStk/JSON/test/resources/n-069_Tm_170-covar.json index d23640cb5..6398790b1 100644 --- a/src/GNDStk/JSON/test/resources/n-069_Tm_170-covar.json +++ b/src/GNDStk/JSON/test/resources/n-069_Tm_170-covar.json @@ -1,6 +1,6 @@ { "covarianceSuite": { - "attributes": { + "#attributes": { "evaluation": "ENDF/B-8.0", "format": "1.9", "projectile": "n", @@ -8,7 +8,7 @@ }, "externalFiles": { "externalFile": { - "attributes": { + "#attributes": { "label": "reactions", "path": "n-069_Tm_170.xml" } @@ -16,30 +16,30 @@ }, "parameterCovariances": { "parameterCovariance": { - "attributes": { + "#attributes": { "label": "resolved resonances" }, "parameterCovarianceMatrix": { "array": { - "attributes": { + "#attributes": { "compression": "diagonal", "shape": "78,78" }, "values": { - "pcdata": { - "attributes": { - "text": "0.015 0 0 0 4.5e-5 0.015 3e-2 0 0 0 1.35e-4 0.015 2e-2 0 0 0 1.5e-3 0.012 5e-2 0 0 0 1.875e-3 6e-2 5e-2 0 0 0 1.05e-4 0.015 0.1 0 0 0 6e-4 0.012 0.1 0 0 0 2.25e-4 0.012 0.2 0 0 0 5.25e-3 0.012 0.2 0 0 0 3.45e-3 0.012 0.3 0 0 0 4.5e-4 0.012 0.3 0 0 0 3e-3 0.012 0.4 0 0 0 9e-3 0.012 0.4 0 0 0 1.425e-3 0.012" + "#pcdata": { + "#attributes": { + "#text": "0.015 0 0 0 4.5e-5 0.015 3e-2 0 0 0 1.35e-4 0.015 2e-2 0 0 0 1.5e-3 0.012 5e-2 0 0 0 1.875e-3 6e-2 5e-2 0 0 0 1.05e-4 0.015 0.1 0 0 0 6e-4 0.012 0.1 0 0 0 2.25e-4 0.012 0.2 0 0 0 5.25e-3 0.012 0.2 0 0 0 3.45e-3 0.012 0.3 0 0 0 4.5e-4 0.012 0.3 0 0 0 3e-3 0.012 0.4 0 0 0 9e-3 0.012 0.4 0 0 0 1.425e-3 0.012" } } } }, - "attributes": { + "#attributes": { "label": "eval", "type": "absolute" }, "parameters": { "parameterLink": { - "attributes": { + "#attributes": { "href": "$reactions#/reactionSuite/resonances/resolved/BreitWigner[@label='eval']/resonanceParameters/table", "label": "resonanceParameters", "nParameters": "78" @@ -48,7 +48,7 @@ } }, "rowData": { - "attributes": { + "#attributes": { "href": "$reactions#/reactionSuite/resonances/resolved/BreitWigner[@label='eval']" } } @@ -56,21 +56,21 @@ }, "styles": { "evaluated": { - "attributes": { + "#attributes": { "date": "2011-10-01", "label": "eval", "library": "ENDF/B", "version": "8.0.1" }, "projectileEnergyDomain": { - "attributes": { + "#attributes": { "max": "30000000.0", "min": "1e-05", "unit": "eV" } }, "temperature": { - "attributes": { + "#attributes": { "unit": "K", "value": "0.0" } diff --git a/src/GNDStk/Node/src/special.hpp b/src/GNDStk/Node/src/special.hpp index 777727158..1978c516f 100644 --- a/src/GNDStk/Node/src/special.hpp +++ b/src/GNDStk/Node/src/special.hpp @@ -15,7 +15,7 @@ // so we can find this content whether we're in the outer Tree/Node (above the // top-level GNDS node), or inside the top-level node, or in fact inside *any* // node from which we can drill down as above, beginning with a documentations, -// documentation, or CDATA node, or even directly to a text metadatum. +// documentation, or CDATA node, or even directly to a #text metadatum. // // Note: CDATA nodes that we've seen in available GNDS files always begin with // a newline. It's tempting, perhaps, to chuck the newline, except that (1) we @@ -149,8 +149,8 @@ const std::string &comment( std::size_t count = 0; for (auto &c : children) - if (c->name == "comment" && count++ == i) - return c->meta("text",found); + if (c->name == "#comment" && count++ == i) + return c->meta("#text",found); // not found static std::string empty; @@ -195,7 +195,7 @@ comments(bool &found = detail::default_bool) const CONTAINER container; const std::string *text; for (auto &c : children) - if (c->name == "comment" && (text = &c->meta("text",found),found)) + if (c->name == "#comment" && (text = &c->meta("#text",found),found)) container.push_back(*text); return container; } diff --git a/src/GNDStk/Node/test/add.test.cpp b/src/GNDStk/Node/test/add.test.cpp index d5b8ad701..3d5e64d1a 100644 --- a/src/GNDStk/Node/test/add.test.cpp +++ b/src/GNDStk/Node/test/add.test.cpp @@ -109,7 +109,7 @@ SCENARIO("Testing GNDStk Node add()") { auto numbers = Child< std::vector, Allow::one - >("pcdata",std::vector{})/detail::convert_pcdata_text_t{}; + >("#pcdata",std::vector{})/detail::convert_pcdata_text_t{}; auto nrepeat = Child("repeated node"); Node node1; node1.name = "aa11"; diff --git a/src/GNDStk/Node/test/sort.test.cpp b/src/GNDStk/Node/test/sort.test.cpp index f542a5262..d5a32901b 100644 --- a/src/GNDStk/Node/test/sort.test.cpp +++ b/src/GNDStk/Node/test/sort.test.cpp @@ -23,8 +23,8 @@ R"***(covarianceSuite: compression: diagonal shape: 78,78 values: - pcdata: - text: 0.015 0 0 0 4.5e-5 0.015 3e-2 0 0 0 1.35e-4 0.015 2e-2 0 0 0 1.5e-3 0.012 5e-2 0 0 0 1.875e-3 6e-2 5e-2 0 0 0 1.05e-4 0.015 0.1 0 0 0 6e-4 0.012 0.1 0 0 0 2.25e-4 0.012 0.2 0 0 0 5.25e-3 0.012 0.2 0 0 0 3.45e-3 0.012 0.3 0 0 0 4.5e-4 0.012 0.3 0 0 0 3e-3 0.012 0.4 0 0 0 9e-3 0.012 0.4 0 0 0 1.425e-3 0.012 + #pcdata: + #text: 0.015 0 0 0 4.5e-5 0.015 3e-2 0 0 0 1.35e-4 0.015 2e-2 0 0 0 1.5e-3 0.012 5e-2 0 0 0 1.875e-3 6e-2 5e-2 0 0 0 1.05e-4 0.015 0.1 0 0 0 6e-4 0.012 0.1 0 0 0 2.25e-4 0.012 0.2 0 0 0 5.25e-3 0.012 0.2 0 0 0 3.45e-3 0.012 0.3 0 0 0 4.5e-4 0.012 0.3 0 0 0 3e-3 0.012 0.4 0 0 0 9e-3 0.012 0.4 0 0 0 1.425e-3 0.012 parameters: parameterLink: href: $reactions#/reactionSuite/resonances/resolved/BreitWigner[@label='eval']/resonanceParameters/table diff --git a/src/GNDStk/Node/test/write.test.cpp b/src/GNDStk/Node/test/write.test.cpp index 032196f94..1692d4adb 100644 --- a/src/GNDStk/Node/test/write.test.cpp +++ b/src/GNDStk/Node/test/write.test.cpp @@ -43,8 +43,8 @@ R"***(covarianceSuite: shape: 78,78 compression: diagonal values: - pcdata: - text: 0.015 0 0 0 4.5e-5 0.015 3e-2 0 0 0 1.35e-4 0.015 2e-2 0 0 0 1.5e-3 0.012 5e-2 0 0 0 1.875e-3 6e-2 5e-2 0 0 0 1.05e-4 0.015 0.1 0 0 0 6e-4 0.012 0.1 0 0 0 2.25e-4 0.012 0.2 0 0 0 5.25e-3 0.012 0.2 0 0 0 3.45e-3 0.012 0.3 0 0 0 4.5e-4 0.012 0.3 0 0 0 3e-3 0.012 0.4 0 0 0 9e-3 0.012 0.4 0 0 0 1.425e-3 0.012)***"; + #pcdata: + #text: 0.015 0 0 0 4.5e-5 0.015 3e-2 0 0 0 1.35e-4 0.015 2e-2 0 0 0 1.5e-3 0.012 5e-2 0 0 0 1.875e-3 6e-2 5e-2 0 0 0 1.05e-4 0.015 0.1 0 0 0 6e-4 0.012 0.1 0 0 0 2.25e-4 0.012 0.2 0 0 0 5.25e-3 0.012 0.2 0 0 0 3.45e-3 0.012 0.3 0 0 0 4.5e-4 0.012 0.3 0 0 0 3e-3 0.012 0.4 0 0 0 9e-3 0.012 0.4 0 0 0 1.425e-3 0.012)***"; SCENARIO("Testing GNDStk Node write() and operator<<") { GIVEN("A top-level node from a tree object") { diff --git a/src/GNDStk/Tree/src/decl.hpp b/src/GNDStk/Tree/src/decl.hpp index 793fab563..be7cec129 100644 --- a/src/GNDStk/Tree/src/decl.hpp +++ b/src/GNDStk/Tree/src/decl.hpp @@ -12,7 +12,7 @@ const Node &decl() const throw std::exception{}; } for (auto &c : this->children) - if (c->name == "xml" || c->name == "json" || c->name == "hdf5") + if (c->name == "#xml" || c->name == "#json" || c->name == "#hdf5") return *c; log::error("Tree's declaration node not found"); throw std::exception{}; diff --git a/src/GNDStk/Tree/src/has_decl.hpp b/src/GNDStk/Tree/src/has_decl.hpp index 2bd6aa6d8..4240bed75 100644 --- a/src/GNDStk/Tree/src/has_decl.hpp +++ b/src/GNDStk/Tree/src/has_decl.hpp @@ -5,7 +5,7 @@ bool has_decl() const // Does the tree have something that looks like a declaration node? int count = 0; for (auto &c : this->children) - if (c->name == "xml" || c->name == "json" || c->name == "hdf5") + if (c->name == "#xml" || c->name == "#json" || c->name == "#hdf5") count++; // Ill-formed if there's more than one such node diff --git a/src/GNDStk/Tree/src/has_top.hpp b/src/GNDStk/Tree/src/has_top.hpp index 80c82d6eb..12c4775ee 100644 --- a/src/GNDStk/Tree/src/has_top.hpp +++ b/src/GNDStk/Tree/src/has_top.hpp @@ -10,7 +10,7 @@ bool has_top() const // defined as something that *doesn't* look like a declaration node? int count = 0; for (auto &c : this->children) - if (c->name != "xml" && c->name != "json" && c->name != "hdf5") + if (c->name != "#xml" && c->name != "#json" && c->name != "#hdf5") count++; // Ill-formed if there's more than one such node diff --git a/src/GNDStk/Tree/src/reset.hpp b/src/GNDStk/Tree/src/reset.hpp index 0d17decf8..b60087999 100644 --- a/src/GNDStk/Tree/src/reset.hpp +++ b/src/GNDStk/Tree/src/reset.hpp @@ -33,7 +33,7 @@ Tree &reset( clear(); try { - // Declaration node: "xml", etc. + // Declaration node: "#xml", etc. // This can specify an eventual intended file format // for the GNDS hierarchy. if (format == FileType::xml || @@ -41,15 +41,15 @@ Tree &reset( format == FileType::text ) { // xml, null, tree - add("xml"); + add("#xml"); decl().add("version", detail::sent(version ) ? version : "1.0" ); decl().add("encoding", detail::sent(encoding) ? encoding : "UTF-8"); } else if (format == FileType::json) { // json - add("json"); + add("#json"); } else if (format == FileType::hdf5) { // hdf5 - add("hdf5"); + add("#hdf5"); } else { log::error( "Internal error in Tree.reset(" + detail::keyname(kwd) + diff --git a/src/GNDStk/Tree/src/top.hpp b/src/GNDStk/Tree/src/top.hpp index a6ad51904..e57b8c096 100644 --- a/src/GNDStk/Tree/src/top.hpp +++ b/src/GNDStk/Tree/src/top.hpp @@ -12,7 +12,7 @@ const Node &top() const throw std::exception{}; } for (auto &c : this->children) - if (c->name != "xml" && c->name != "json" && c->name != "hdf5") + if (c->name != "#xml" && c->name != "#json" && c->name != "#hdf5") return *c; log::error("Tree's top-level GNDS node not found"); throw std::exception{}; diff --git a/src/GNDStk/Tree/test/call.test.cpp b/src/GNDStk/Tree/test/call.test.cpp index 3a20df864..74d4f0d1c 100644 --- a/src/GNDStk/Tree/test/call.test.cpp +++ b/src/GNDStk/Tree/test/call.test.cpp @@ -27,7 +27,7 @@ inline void convert(const NODE &node, xml_t &out) out.encoding = node.meta(encoding); } -inline const Child xml("xml"); +inline const Child xml("#xml"); // ------------------------ diff --git a/src/GNDStk/Tree/test/child.test.cpp b/src/GNDStk/Tree/test/child.test.cpp index 2dbefb630..6b08dd730 100644 --- a/src/GNDStk/Tree/test/child.test.cpp +++ b/src/GNDStk/Tree/test/child.test.cpp @@ -36,9 +36,9 @@ inline void convert(const NODE &node, xml_t &out) // keyword: my_xml_keyword // Users can write custom Child objects like this, and then use them in -// child() functions. Here, "xml" is what the keyword uses to look up nodes +// child() functions. Here, "#xml" is what the keyword uses to look up nodes // that can be converted to xml_t objects via the above convert(). -inline const Child my_xml_keyword("xml"); +inline const Child my_xml_keyword("#xml"); diff --git a/src/GNDStk/Tree/test/ctor.test.cpp b/src/GNDStk/Tree/test/ctor.test.cpp index d045c84d3..49749d206 100644 --- a/src/GNDStk/Tree/test/ctor.test.cpp +++ b/src/GNDStk/Tree/test/ctor.test.cpp @@ -125,7 +125,7 @@ SCENARIO("Testing GNDStk tree constructors") { WHEN("We call: Tree(top-level node)") { Tree t(reactionSuite); THEN("We can make various decl() and top() queries") { - CHECK(t.decl().name == "xml"); + CHECK(t.decl().name == "#xml"); CHECK(t.decl().metadata.size() == 2); CHECK(t.decl().meta("version") == "1.0"); CHECK(t.decl().meta("encoding") == "UTF-8"); @@ -139,7 +139,7 @@ SCENARIO("Testing GNDStk tree constructors") { WHEN("We call: Tree(top-level node, file format)") { Tree t(reactionSuite, FileType::json); THEN("We can make various decl() and top() queries") { - CHECK(t.decl().name == "json"); + CHECK(t.decl().name == "#json"); CHECK(t.decl().metadata.size() == 0); CHECK(t.decl().children.size() == 0); CHECK(t.top().name == "reactionSuite"); @@ -151,7 +151,7 @@ SCENARIO("Testing GNDStk tree constructors") { WHEN("We call: Tree(top-level node, file format, version)") { Tree t(covarianceSuite, FileType::null, "2.0"); THEN("We can make various decl() and top() queries") { - CHECK(t.decl().name == "xml"); + CHECK(t.decl().name == "#xml"); CHECK(t.decl().metadata.size() == 2); CHECK(t.decl().meta("version") == "2.0"); CHECK(t.decl().meta("encoding") == "UTF-8"); @@ -165,7 +165,7 @@ SCENARIO("Testing GNDStk tree constructors") { WHEN("We call: Tree(top-level node, file format, version, encoding)") { Tree t(covarianceSuite, FileType::xml, "3.0", "UTF-9"); THEN("We can make various decl() and top() queries") { - CHECK(t.decl().name == "xml"); + CHECK(t.decl().name == "#xml"); CHECK(t.decl().metadata.size() == 2); CHECK(t.decl().meta("version") == "3.0"); CHECK(t.decl().meta("encoding") == "UTF-9"); @@ -179,7 +179,7 @@ SCENARIO("Testing GNDStk tree constructors") { WHEN("We call: Tree(top-level node, string)") { Tree t(PoPs, "hdf5"); THEN("We can make various decl() and top() queries") { - CHECK(t.decl().name == "hdf5"); + CHECK(t.decl().name == "#hdf5"); CHECK(t.decl().metadata.size() == 0); CHECK(t.decl().children.size() == 0); CHECK(t.top().name == "PoPs"); @@ -191,7 +191,7 @@ SCENARIO("Testing GNDStk tree constructors") { WHEN("We call: Tree(top-level node, string, version)") { Tree t(PoPs, "text", "4.0"); THEN("We can make various decl() and top() queries") { - CHECK(t.decl().name == "xml"); + CHECK(t.decl().name == "#xml"); CHECK(t.decl().metadata.size() == 2); CHECK(t.decl().meta("version") == "4.0"); CHECK(t.decl().meta("encoding") == "UTF-8"); @@ -205,7 +205,7 @@ SCENARIO("Testing GNDStk tree constructors") { WHEN("We call: Tree(top-level node, string, version, encoding)") { Tree t(thermalScattering, "xml", "5.0", "UTF-10"); THEN("We can make various decl() and top() queries") { - CHECK(t.decl().name == "xml"); + CHECK(t.decl().name == "#xml"); CHECK(t.decl().metadata.size() == 2); CHECK(t.decl().meta("version") == "5.0"); CHECK(t.decl().meta("encoding") == "UTF-10"); diff --git a/src/GNDStk/Tree/test/decl.test.cpp b/src/GNDStk/Tree/test/decl.test.cpp index eabd61fdf..a613a8f36 100644 --- a/src/GNDStk/Tree/test/decl.test.cpp +++ b/src/GNDStk/Tree/test/decl.test.cpp @@ -9,7 +9,7 @@ SCENARIO("Testing GNDStk tree decl()") { GIVEN("A tree read from an XML file") { Tree t("n-069_Tm_170-covar.xml"); - CHECK(t.decl().name == "xml"); + CHECK(t.decl().name == "#xml"); CHECK(t.decl().metadata.size() == 2); CHECK(t.decl().meta("version") == "1.0"); CHECK(t.decl().meta("encoding") == "UTF-8"); @@ -21,7 +21,7 @@ SCENARIO("Testing GNDStk tree decl()") { WHEN("We call reset(reactionSuite)") { Tree t; t.reset(reactionSuite); - CHECK(t.decl().name == "xml"); + CHECK(t.decl().name == "#xml"); CHECK(t.decl().metadata.size() == 2); CHECK(t.decl().meta("version") == "1.0"); CHECK(t.decl().meta("encoding") == "UTF-8"); @@ -31,7 +31,7 @@ SCENARIO("Testing GNDStk tree decl()") { WHEN("We call reset(reactionSuite, FileType::json)") { Tree t; t.reset(reactionSuite, FileType::json); - CHECK(t.decl().name == "json"); + CHECK(t.decl().name == "#json"); CHECK(t.decl().metadata.size() == 0); CHECK(t.decl().children.size() == 0); } @@ -39,7 +39,7 @@ SCENARIO("Testing GNDStk tree decl()") { WHEN("We call reset(covarianceSuite, FileType::null, \"2.0\")") { Tree t; t.reset(covarianceSuite, FileType::null, "2.0"); - CHECK(t.decl().name == "xml"); + CHECK(t.decl().name == "#xml"); CHECK(t.decl().metadata.size() == 2); CHECK(t.decl().meta("version") == "2.0"); CHECK(t.decl().meta("encoding") == "UTF-8"); @@ -49,7 +49,7 @@ SCENARIO("Testing GNDStk tree decl()") { WHEN("We call reset(covarianceSuite, FileType::xml, \"3.0\", \"UTF-9\")") { Tree t; t.reset(covarianceSuite, FileType::xml, "3.0", "UTF-9"); - CHECK(t.decl().name == "xml"); + CHECK(t.decl().name == "#xml"); CHECK(t.decl().metadata.size() == 2); CHECK(t.decl().meta("version") == "3.0"); CHECK(t.decl().meta("encoding") == "UTF-9"); @@ -59,7 +59,7 @@ SCENARIO("Testing GNDStk tree decl()") { WHEN("We call reset(PoPs, \"hdf5\")") { Tree t; t.reset(PoPs, "hdf5"); - CHECK(t.decl().name == "hdf5"); + CHECK(t.decl().name == "#hdf5"); CHECK(t.decl().metadata.size() == 0); CHECK(t.decl().children.size() == 0); @@ -68,7 +68,7 @@ SCENARIO("Testing GNDStk tree decl()") { WHEN("We call reset(PoPs, \"tree\", \"4.0\")") { Tree t; t.reset(PoPs, "text", "4.0"); - CHECK(t.decl().name == "xml"); + CHECK(t.decl().name == "#xml"); CHECK(t.decl().metadata.size() == 2); CHECK(t.decl().meta("version") == "4.0"); CHECK(t.decl().meta("encoding") == "UTF-8"); @@ -78,7 +78,7 @@ SCENARIO("Testing GNDStk tree decl()") { WHEN("We call reset(thermalScattering, \"xml\", \"5.0\", \"UTF-10\")") { Tree t; t.reset(thermalScattering, "xml", "5.0", "UTF-10"); - CHECK(t.decl().name == "xml"); + CHECK(t.decl().name == "#xml"); CHECK(t.decl().metadata.size() == 2); CHECK(t.decl().meta("version") == "5.0"); CHECK(t.decl().meta("encoding") == "UTF-10"); diff --git a/src/GNDStk/Tree/test/many.test.cpp b/src/GNDStk/Tree/test/many.test.cpp index 6bf0f81a9..9e68b10e1 100644 --- a/src/GNDStk/Tree/test/many.test.cpp +++ b/src/GNDStk/Tree/test/many.test.cpp @@ -18,23 +18,23 @@ SCENARIO("Testing GNDStk Tree many()") { // the top-level GNDS node (or both if they have the same name, which // really wouldn't be a correct state of affairs). - WHEN("We look for all \"xml\" nodes") { + WHEN("We look for all \"#xml\" nodes") { // Declaration node... // const found = false; - auto cnode = c.many("xml",found); + auto cnode = c.many("#xml",found); CHECK(found); CHECK(cnode.size() == 1); - CHECK(cnode[0].name == "xml"); + CHECK(cnode[0].name == "#xml"); CHECK(cnode[0].meta("version") == "1.0"); // non-const found = false; - auto tnode = t.many("xml",found); + auto tnode = t.many("#xml",found); CHECK(found); CHECK(tnode.size() == 1); - CHECK(tnode[0].name == "xml"); + CHECK(tnode[0].name == "#xml"); CHECK(tnode[0].meta("encoding") == "UTF-8"); } diff --git a/src/GNDStk/Tree/test/one.test.cpp b/src/GNDStk/Tree/test/one.test.cpp index 1442ae639..b880e6cde 100644 --- a/src/GNDStk/Tree/test/one.test.cpp +++ b/src/GNDStk/Tree/test/one.test.cpp @@ -18,21 +18,21 @@ SCENARIO("Testing GNDStk Tree one()") { // node, or the top-level GNDS node; we consider both of those to be // a Tree's children. - WHEN("We look for an \"xml\" node") { + WHEN("We look for an \"#xml\" node") { // Declaration node... // const found = false; - auto &cnode = c.one("xml",found); + auto &cnode = c.one("#xml",found); CHECK(found); - CHECK(cnode.name == "xml"); + CHECK(cnode.name == "#xml"); CHECK(cnode.meta("version") == "1.0"); // non-const found = false; - auto &tnode = t.one("xml",found); + auto &tnode = t.one("#xml",found); CHECK(found); - CHECK(tnode.name == "xml"); + CHECK(tnode.name == "#xml"); CHECK(tnode.meta("encoding") == "UTF-8"); } @@ -70,12 +70,12 @@ SCENARIO("Testing GNDStk Tree one()") { // Illustrate that Tree's one(string) functions return references, // even when the child isn't found... - (void)&c.one("xml"); + (void)&c.one("#xml"); (void)&c.one("covarianceSuite"); (void)&c.one("foo",found); CHECK(!found); - (void)&t.one("xml"); + (void)&t.one("#xml"); (void)&t.one("covarianceSuite"); (void)&t.one("bar",found); CHECK(!found); diff --git a/src/GNDStk/Tree/test/read.test.cpp b/src/GNDStk/Tree/test/read.test.cpp index 876bf38be..bfa4d760d 100644 --- a/src/GNDStk/Tree/test/read.test.cpp +++ b/src/GNDStk/Tree/test/read.test.cpp @@ -9,7 +9,7 @@ using namespace njoy::GNDStk; // ----------------------------------------------------------------------------- static const std::string correct_tree = -R"***(: +R"***( covarianceSuite: evaluation: ENDF/B-8.0 format: 1.9 @@ -29,8 +29,8 @@ R"***(: compression: diagonal shape: 78,78 values: - pcdata: - text: 0.015 0 0 0 4.5e-5 0.015 3e-2 0 0 0 1.35e-4 0.015 2e-2 0 0 0 1.5e-3 0.012 5e-2 0 0 0 1.875e-3 6e-2 5e-2 0 0 0 1.05e-4 0.015 0.1 0 0 0 6e-4 0.012 0.1 0 0 0 2.25e-4 0.012 0.2 0 0 0 5.25e-3 0.012 0.2 0 0 0 3.45e-3 0.012 0.3 0 0 0 4.5e-4 0.012 0.3 0 0 0 3e-3 0.012 0.4 0 0 0 9e-3 0.012 0.4 0 0 0 1.425e-3 0.012 + #pcdata: + #text: 0.015 0 0 0 4.5e-5 0.015 3e-2 0 0 0 1.35e-4 0.015 2e-2 0 0 0 1.5e-3 0.012 5e-2 0 0 0 1.875e-3 6e-2 5e-2 0 0 0 1.05e-4 0.015 0.1 0 0 0 6e-4 0.012 0.1 0 0 0 2.25e-4 0.012 0.2 0 0 0 5.25e-3 0.012 0.2 0 0 0 3.45e-3 0.012 0.3 0 0 0 4.5e-4 0.012 0.3 0 0 0 3e-3 0.012 0.4 0 0 0 9e-3 0.012 0.4 0 0 0 1.425e-3 0.012 parameters: parameterLink: href: $reactions#/reactionSuite/resonances/resolved/BreitWigner[@label='eval']/resonanceParameters/table @@ -53,14 +53,14 @@ R"***(: value: 0.0)***"; static const std::string decl_xml = -R"***( - xml: +R"***(: + #xml: encoding: UTF-8 version: 1.0)***"; static const std::string decl_json = -R"***( - json:)***"; +R"***(: + #json:)***"; void compare(Tree &t, const std::string &correct) { @@ -86,13 +86,13 @@ SCENARIO("Testing GNDStk tree read() and operator>>") { WHEN("We read() one from an xml file") { const std::string filename = "n-069_Tm_170-covar.xml"; t1.read(filename); - compare(t1,correct_tree+decl_xml); + compare(t1, decl_xml + correct_tree); } WHEN("We read() one from an xml istream, specifically an ifstream") { std::ifstream ifs("n-069_Tm_170-covar.xml"); t2.read(ifs); - compare(t2,correct_tree+decl_xml); + compare(t2, decl_xml + correct_tree); } WHEN("We read() one from an xml istream, specifically a stringstream") { @@ -100,13 +100,13 @@ SCENARIO("Testing GNDStk tree read() and operator>>") { std::stringstream sstr; sstr << ifs.rdbuf(); t3.read(sstr); - compare(t3,correct_tree+decl_xml); + compare(t3, decl_xml + correct_tree); } WHEN("We stream-input one, specifically from an xml ifstream") { std::ifstream ifs("n-069_Tm_170-covar.xml"); ifs >> t4; - compare(t4,correct_tree+decl_xml); + compare(t4, decl_xml + correct_tree); } // ------------------------ @@ -116,13 +116,13 @@ SCENARIO("Testing GNDStk tree read() and operator>>") { WHEN("We read() one from a json file") { const std::string filename = "n-069_Tm_170-covar.json"; t1.read(filename); - compare(t1,correct_tree+decl_json); + compare(t1, decl_json + correct_tree); } WHEN("We read() one from a json istream, specifically an ifstream") { std::ifstream ifs("n-069_Tm_170-covar.json"); t2.read(ifs); - compare(t2,correct_tree+decl_json); + compare(t2, decl_json + correct_tree); } WHEN("We read() one from a json istream, specifically a stringstream") { @@ -130,13 +130,13 @@ SCENARIO("Testing GNDStk tree read() and operator>>") { std::stringstream sstr; sstr << ifs.rdbuf(); t3.read(sstr); - compare(t3,correct_tree+decl_json); + compare(t3, decl_json + correct_tree); } WHEN("We stream-input one, specifically from a json ifstream") { std::ifstream ifs("n-069_Tm_170-covar.json"); ifs >> t4; - compare(t4,correct_tree+decl_json); + compare(t4, decl_json + correct_tree); } } @@ -170,75 +170,75 @@ SCENARIO("Testing GNDStk tree read() and operator>>") { WHEN("We test read(filename, file format") { // xml tree.read(xfilename,FileType::null); - compare(tree,correct_tree+decl_xml); + compare(tree, decl_xml + correct_tree); tree.read(xfilename,FileType::xml ); - compare(tree,correct_tree+decl_xml); + compare(tree, decl_xml + correct_tree); // json tree.read(jfilename,FileType::null); - compare(tree,correct_tree+decl_json); + compare(tree, decl_json + correct_tree); tree.read(jfilename,FileType::json); - compare(tree,correct_tree+decl_json); + compare(tree, decl_json + correct_tree); } WHEN("We test read(filename, string") { // xml tree.read(xfilename,"" ); - compare(tree,correct_tree+decl_xml); + compare(tree, decl_xml + correct_tree); tree.read(xfilename,"null"); - compare(tree,correct_tree+decl_xml); + compare(tree, decl_xml + correct_tree); tree.read(xfilename,"xml" ); - compare(tree,correct_tree+decl_xml); + compare(tree, decl_xml + correct_tree); // json tree.read(jfilename,"" ); - compare(tree,correct_tree+decl_json); + compare(tree, decl_json + correct_tree); tree.read(jfilename,"null"); - compare(tree,correct_tree+decl_json); + compare(tree, decl_json + correct_tree); tree.read(jfilename,"json"); - compare(tree,correct_tree+decl_json); + compare(tree, decl_json + correct_tree); } WHEN("We test read(istream, file format") { // xml xifs.seekg (0,std::ios::beg); tree.read(xifs,FileType::null); - compare(tree,correct_tree+decl_xml); + compare(tree, decl_xml + correct_tree); xifs.seekg (0,std::ios::beg); tree.read(xifs,FileType::xml ); - compare(tree,correct_tree+decl_xml); + compare(tree, decl_xml + correct_tree); // json jifs.seekg (0,std::ios::beg); tree.read(jifs,FileType::null); - compare(tree,correct_tree+decl_json); + compare(tree, decl_json + correct_tree); jifs.seekg (0,std::ios::beg); tree.read(jifs,FileType::json); - compare(tree,correct_tree+decl_json); + compare(tree, decl_json + correct_tree); } WHEN("We test read(istream, string") { // xml xifs.seekg (0,std::ios::beg); tree.read(xifs,"" ); - compare(tree,correct_tree+decl_xml); + compare(tree, decl_xml + correct_tree); xifs.seekg (0,std::ios::beg); tree.read(xifs,"null"); - compare(tree,correct_tree+decl_xml); + compare(tree, decl_xml + correct_tree); xifs.seekg (0,std::ios::beg); tree.read(xifs,"xml" ); - compare(tree,correct_tree+decl_xml); + compare(tree, decl_xml + correct_tree); // json jifs.seekg (0,std::ios::beg); tree.read(jifs,"" ); - compare(tree,correct_tree+decl_json); + compare(tree, decl_json + correct_tree); jifs.seekg (0,std::ios::beg); tree.read(jifs,"null"); - compare(tree,correct_tree+decl_json); + compare(tree, decl_json + correct_tree); jifs.seekg (0,std::ios::beg); tree.read(jifs,"json"); - compare(tree,correct_tree+decl_json); + compare(tree, decl_json + correct_tree); } } } diff --git a/src/GNDStk/Tree/test/reset.test.cpp b/src/GNDStk/Tree/test/reset.test.cpp index 41d3c0f91..db1409ac3 100644 --- a/src/GNDStk/Tree/test/reset.test.cpp +++ b/src/GNDStk/Tree/test/reset.test.cpp @@ -24,7 +24,7 @@ SCENARIO("Testing GNDStk tree reset()") { t.reset(reactionSuite); THEN("Declaration- and top-level-node queries can be made") { - CHECK(t.decl().name == "xml"); + CHECK(t.decl().name == "#xml"); CHECK(t.decl().metadata.size() == 2); CHECK(t.decl().meta("version") == "1.0"); CHECK(t.decl().meta("encoding") == "UTF-8"); @@ -41,7 +41,7 @@ SCENARIO("Testing GNDStk tree reset()") { t.reset(reactionSuite, FileType::json); THEN("Declaration- and top-level-node queries can be made") { - CHECK(t.decl().name == "json"); + CHECK(t.decl().name == "#json"); CHECK(t.decl().metadata.size() == 0); CHECK(t.decl().children.size() == 0); CHECK(t.top().name == "reactionSuite"); @@ -56,7 +56,7 @@ SCENARIO("Testing GNDStk tree reset()") { t.reset(covarianceSuite, FileType::null, "2.0"); THEN("Declaration- and top-level-node queries can be made") { - CHECK(t.decl().name == "xml"); + CHECK(t.decl().name == "#xml"); CHECK(t.decl().metadata.size() == 2); CHECK(t.decl().meta("version") == "2.0"); CHECK(t.decl().meta("encoding") == "UTF-8"); @@ -73,7 +73,7 @@ SCENARIO("Testing GNDStk tree reset()") { t.reset(covarianceSuite, FileType::xml, "3.0", "UTF-9"); THEN("Declaration- and top-level-node queries can be made") { - CHECK(t.decl().name == "xml"); + CHECK(t.decl().name == "#xml"); CHECK(t.decl().metadata.size() == 2); CHECK(t.decl().meta("version") == "3.0"); CHECK(t.decl().meta("encoding") == "UTF-9"); @@ -90,7 +90,7 @@ SCENARIO("Testing GNDStk tree reset()") { t.reset(PoPs, "hdf5"); THEN("Declaration- and top-level-node queries can be made") { - CHECK(t.decl().name == "hdf5"); + CHECK(t.decl().name == "#hdf5"); CHECK(t.decl().metadata.size() == 0); CHECK(t.decl().children.size() == 0); CHECK(t.top().name == "PoPs"); @@ -106,7 +106,7 @@ SCENARIO("Testing GNDStk tree reset()") { t.reset(PoPs, "text", "4.0"); THEN("Declaration- and top-level-node queries can be made") { - CHECK(t.decl().name == "xml"); + CHECK(t.decl().name == "#xml"); CHECK(t.decl().metadata.size() == 2); CHECK(t.decl().meta("version") == "4.0"); CHECK(t.decl().meta("encoding") == "UTF-8"); @@ -118,12 +118,12 @@ SCENARIO("Testing GNDStk tree reset()") { } WHEN("We call " - "Tree.reset(thermalScattering, \"xml\", \"5.0\", \"UTF-10\")") { + "Tree.reset(thermalScattering, \"#xml\", \"5.0\", \"UTF-10\")") { Tree t; - t.reset(thermalScattering, "xml", "5.0", "UTF-10"); + t.reset(thermalScattering, "#xml", "5.0", "UTF-10"); THEN("Declaration- and top-level-node queries can be made") { - CHECK(t.decl().name == "xml"); + CHECK(t.decl().name == "#xml"); CHECK(t.decl().metadata.size() == 2); CHECK(t.decl().meta("version") == "5.0"); CHECK(t.decl().meta("encoding") == "UTF-10"); diff --git a/src/GNDStk/Tree/test/resources/n-069_Tm_170-covar.json b/src/GNDStk/Tree/test/resources/n-069_Tm_170-covar.json index d23640cb5..6398790b1 100644 --- a/src/GNDStk/Tree/test/resources/n-069_Tm_170-covar.json +++ b/src/GNDStk/Tree/test/resources/n-069_Tm_170-covar.json @@ -1,6 +1,6 @@ { "covarianceSuite": { - "attributes": { + "#attributes": { "evaluation": "ENDF/B-8.0", "format": "1.9", "projectile": "n", @@ -8,7 +8,7 @@ }, "externalFiles": { "externalFile": { - "attributes": { + "#attributes": { "label": "reactions", "path": "n-069_Tm_170.xml" } @@ -16,30 +16,30 @@ }, "parameterCovariances": { "parameterCovariance": { - "attributes": { + "#attributes": { "label": "resolved resonances" }, "parameterCovarianceMatrix": { "array": { - "attributes": { + "#attributes": { "compression": "diagonal", "shape": "78,78" }, "values": { - "pcdata": { - "attributes": { - "text": "0.015 0 0 0 4.5e-5 0.015 3e-2 0 0 0 1.35e-4 0.015 2e-2 0 0 0 1.5e-3 0.012 5e-2 0 0 0 1.875e-3 6e-2 5e-2 0 0 0 1.05e-4 0.015 0.1 0 0 0 6e-4 0.012 0.1 0 0 0 2.25e-4 0.012 0.2 0 0 0 5.25e-3 0.012 0.2 0 0 0 3.45e-3 0.012 0.3 0 0 0 4.5e-4 0.012 0.3 0 0 0 3e-3 0.012 0.4 0 0 0 9e-3 0.012 0.4 0 0 0 1.425e-3 0.012" + "#pcdata": { + "#attributes": { + "#text": "0.015 0 0 0 4.5e-5 0.015 3e-2 0 0 0 1.35e-4 0.015 2e-2 0 0 0 1.5e-3 0.012 5e-2 0 0 0 1.875e-3 6e-2 5e-2 0 0 0 1.05e-4 0.015 0.1 0 0 0 6e-4 0.012 0.1 0 0 0 2.25e-4 0.012 0.2 0 0 0 5.25e-3 0.012 0.2 0 0 0 3.45e-3 0.012 0.3 0 0 0 4.5e-4 0.012 0.3 0 0 0 3e-3 0.012 0.4 0 0 0 9e-3 0.012 0.4 0 0 0 1.425e-3 0.012" } } } }, - "attributes": { + "#attributes": { "label": "eval", "type": "absolute" }, "parameters": { "parameterLink": { - "attributes": { + "#attributes": { "href": "$reactions#/reactionSuite/resonances/resolved/BreitWigner[@label='eval']/resonanceParameters/table", "label": "resonanceParameters", "nParameters": "78" @@ -48,7 +48,7 @@ } }, "rowData": { - "attributes": { + "#attributes": { "href": "$reactions#/reactionSuite/resonances/resolved/BreitWigner[@label='eval']" } } @@ -56,21 +56,21 @@ }, "styles": { "evaluated": { - "attributes": { + "#attributes": { "date": "2011-10-01", "label": "eval", "library": "ENDF/B", "version": "8.0.1" }, "projectileEnergyDomain": { - "attributes": { + "#attributes": { "max": "30000000.0", "min": "1e-05", "unit": "eV" } }, "temperature": { - "attributes": { + "#attributes": { "unit": "K", "value": "0.0" } diff --git a/src/GNDStk/Tree/test/top.test.cpp b/src/GNDStk/Tree/test/top.test.cpp index b7853b164..e54364c1d 100644 --- a/src/GNDStk/Tree/test/top.test.cpp +++ b/src/GNDStk/Tree/test/top.test.cpp @@ -80,9 +80,9 @@ SCENARIO("Testing GNDStk Tree top()") { } } - WHEN("We call reset(thermalScattering, \"xml\", \"5.0\", \"UTF-10\")") { + WHEN("We call reset(thermalScattering, \"#xml\", \"5.0\", \"UTF-10\")") { Tree t; - t.reset(thermalScattering, "xml", "5.0", "UTF-10"); + t.reset(thermalScattering, "#xml", "5.0", "UTF-10"); THEN("We can make various top() (top-level node) queries") { CHECK(t.top().name == "thermalScattering"); CHECK(t.top().metadata.size() == 0); diff --git a/src/GNDStk/Tree/test/write.test.cpp b/src/GNDStk/Tree/test/write.test.cpp index 8df9f359d..d30c616af 100644 --- a/src/GNDStk/Tree/test/write.test.cpp +++ b/src/GNDStk/Tree/test/write.test.cpp @@ -35,7 +35,7 @@ R"***(null)***"; static const std::string string_real_tree = R"***(: - xml: + #xml: version: 1.0 encoding: UTF-8 covarianceSuite: @@ -77,8 +77,8 @@ R"***(: shape: 78,78 compression: diagonal values: - pcdata: - text: 0.015 0 0 0 4.5e-5 0.015 3e-2 0 0 0 1.35e-4 0.015 2e-2 0 0 0 1.5e-3 0.012 5e-2 0 0 0 1.875e-3 6e-2 5e-2 0 0 0 1.05e-4 0.015 0.1 0 0 0 6e-4 0.012 0.1 0 0 0 2.25e-4 0.012 0.2 0 0 0 5.25e-3 0.012 0.2 0 0 0 3.45e-3 0.012 0.3 0 0 0 4.5e-4 0.012 0.3 0 0 0 3e-3 0.012 0.4 0 0 0 9e-3 0.012 0.4 0 0 0 1.425e-3 0.012)***"; + #pcdata: + #text: 0.015 0 0 0 4.5e-5 0.015 3e-2 0 0 0 1.35e-4 0.015 2e-2 0 0 0 1.5e-3 0.012 5e-2 0 0 0 1.875e-3 6e-2 5e-2 0 0 0 1.05e-4 0.015 0.1 0 0 0 6e-4 0.012 0.1 0 0 0 2.25e-4 0.012 0.2 0 0 0 5.25e-3 0.012 0.2 0 0 0 3.45e-3 0.012 0.3 0 0 0 4.5e-4 0.012 0.3 0 0 0 3e-3 0.012 0.4 0 0 0 9e-3 0.012 0.4 0 0 0 1.425e-3 0.012)***"; @@ -123,7 +123,7 @@ R"***( static const std::string string_real_json = R"***({ "covarianceSuite": { - "attributes": { + "#attributes": { "evaluation": "ENDF/B-8.0", "format": "1.9", "projectile": "n", @@ -131,7 +131,7 @@ R"***({ }, "externalFiles": { "externalFile": { - "attributes": { + "#attributes": { "label": "reactions", "path": "n-069_Tm_170.xml" } @@ -139,30 +139,30 @@ R"***({ }, "parameterCovariances": { "parameterCovariance": { - "attributes": { + "#attributes": { "label": "resolved resonances" }, "parameterCovarianceMatrix": { + "#attributes": { + "label": "eval", + "type": "absolute" + }, "array": { - "attributes": { + "#attributes": { "compression": "diagonal", "shape": "78,78" }, "values": { - "pcdata": { - "attributes": { - "text": "0.015 0 0 0 4.5e-5 0.015 3e-2 0 0 0 1.35e-4 0.015 2e-2 0 0 0 1.5e-3 0.012 5e-2 0 0 0 1.875e-3 6e-2 5e-2 0 0 0 1.05e-4 0.015 0.1 0 0 0 6e-4 0.012 0.1 0 0 0 2.25e-4 0.012 0.2 0 0 0 5.25e-3 0.012 0.2 0 0 0 3.45e-3 0.012 0.3 0 0 0 4.5e-4 0.012 0.3 0 0 0 3e-3 0.012 0.4 0 0 0 9e-3 0.012 0.4 0 0 0 1.425e-3 0.012" + "#pcdata": { + "#attributes": { + "#text": "0.015 0 0 0 4.5e-5 0.015 3e-2 0 0 0 1.35e-4 0.015 2e-2 0 0 0 1.5e-3 0.012 5e-2 0 0 0 1.875e-3 6e-2 5e-2 0 0 0 1.05e-4 0.015 0.1 0 0 0 6e-4 0.012 0.1 0 0 0 2.25e-4 0.012 0.2 0 0 0 5.25e-3 0.012 0.2 0 0 0 3.45e-3 0.012 0.3 0 0 0 4.5e-4 0.012 0.3 0 0 0 3e-3 0.012 0.4 0 0 0 9e-3 0.012 0.4 0 0 0 1.425e-3 0.012" } } } }, - "attributes": { - "label": "eval", - "type": "absolute" - }, "parameters": { "parameterLink": { - "attributes": { + "#attributes": { "href": "$reactions#/reactionSuite/resonances/resolved/BreitWigner[@label='eval']/resonanceParameters/table", "label": "resonanceParameters", "nParameters": "78" @@ -171,7 +171,7 @@ R"***({ } }, "rowData": { - "attributes": { + "#attributes": { "href": "$reactions#/reactionSuite/resonances/resolved/BreitWigner[@label='eval']" } } @@ -179,21 +179,21 @@ R"***({ }, "styles": { "evaluated": { - "attributes": { + "#attributes": { "date": "2011-10-01", "label": "eval", "library": "ENDF/B", "version": "8.0.1" }, "projectileEnergyDomain": { - "attributes": { + "#attributes": { "max": "30000000.0", "min": "1e-05", "unit": "eV" } }, "temperature": { - "attributes": { + "#attributes": { "unit": "K", "value": "0.0" } diff --git a/src/GNDStk/XML/test/XML.test.cpp b/src/GNDStk/XML/test/XML.test.cpp index f183743f1..39042bb02 100644 --- a/src/GNDStk/XML/test/XML.test.cpp +++ b/src/GNDStk/XML/test/XML.test.cpp @@ -65,7 +65,7 @@ SCENARIO("Testing GNDStk XML") { THEN("The Tree should have only an empty declaration node") { CHECK(t.children.size() == 1); CHECK(t.has_decl()); - CHECK(t.decl().name == "xml"); + CHECK(t.decl().name == "#xml"); CHECK(t.decl().metadata.size() == 0); CHECK(t.decl().children.size() == 0); } diff --git a/src/GNDStk/XML/test/resources/n-069_Tm_170-covar.json b/src/GNDStk/XML/test/resources/n-069_Tm_170-covar.json index d23640cb5..6398790b1 100644 --- a/src/GNDStk/XML/test/resources/n-069_Tm_170-covar.json +++ b/src/GNDStk/XML/test/resources/n-069_Tm_170-covar.json @@ -1,6 +1,6 @@ { "covarianceSuite": { - "attributes": { + "#attributes": { "evaluation": "ENDF/B-8.0", "format": "1.9", "projectile": "n", @@ -8,7 +8,7 @@ }, "externalFiles": { "externalFile": { - "attributes": { + "#attributes": { "label": "reactions", "path": "n-069_Tm_170.xml" } @@ -16,30 +16,30 @@ }, "parameterCovariances": { "parameterCovariance": { - "attributes": { + "#attributes": { "label": "resolved resonances" }, "parameterCovarianceMatrix": { "array": { - "attributes": { + "#attributes": { "compression": "diagonal", "shape": "78,78" }, "values": { - "pcdata": { - "attributes": { - "text": "0.015 0 0 0 4.5e-5 0.015 3e-2 0 0 0 1.35e-4 0.015 2e-2 0 0 0 1.5e-3 0.012 5e-2 0 0 0 1.875e-3 6e-2 5e-2 0 0 0 1.05e-4 0.015 0.1 0 0 0 6e-4 0.012 0.1 0 0 0 2.25e-4 0.012 0.2 0 0 0 5.25e-3 0.012 0.2 0 0 0 3.45e-3 0.012 0.3 0 0 0 4.5e-4 0.012 0.3 0 0 0 3e-3 0.012 0.4 0 0 0 9e-3 0.012 0.4 0 0 0 1.425e-3 0.012" + "#pcdata": { + "#attributes": { + "#text": "0.015 0 0 0 4.5e-5 0.015 3e-2 0 0 0 1.35e-4 0.015 2e-2 0 0 0 1.5e-3 0.012 5e-2 0 0 0 1.875e-3 6e-2 5e-2 0 0 0 1.05e-4 0.015 0.1 0 0 0 6e-4 0.012 0.1 0 0 0 2.25e-4 0.012 0.2 0 0 0 5.25e-3 0.012 0.2 0 0 0 3.45e-3 0.012 0.3 0 0 0 4.5e-4 0.012 0.3 0 0 0 3e-3 0.012 0.4 0 0 0 9e-3 0.012 0.4 0 0 0 1.425e-3 0.012" } } } }, - "attributes": { + "#attributes": { "label": "eval", "type": "absolute" }, "parameters": { "parameterLink": { - "attributes": { + "#attributes": { "href": "$reactions#/reactionSuite/resonances/resolved/BreitWigner[@label='eval']/resonanceParameters/table", "label": "resonanceParameters", "nParameters": "78" @@ -48,7 +48,7 @@ } }, "rowData": { - "attributes": { + "#attributes": { "href": "$reactions#/reactionSuite/resonances/resolved/BreitWigner[@label='eval']" } } @@ -56,21 +56,21 @@ }, "styles": { "evaluated": { - "attributes": { + "#attributes": { "date": "2011-10-01", "label": "eval", "library": "ENDF/B", "version": "8.0.1" }, "projectileEnergyDomain": { - "attributes": { + "#attributes": { "max": "30000000.0", "min": "1e-05", "unit": "eV" } }, "temperature": { - "attributes": { + "#attributes": { "unit": "K", "value": "0.0" } diff --git a/src/GNDStk/basic/src/child.hpp b/src/GNDStk/basic/src/child.hpp index 0daa7c787..8615a9241 100644 --- a/src/GNDStk/basic/src/child.hpp +++ b/src/GNDStk/basic/src/child.hpp @@ -76,7 +76,7 @@ inline const Child bindingEnergy ("bindingEnergy" ), branching1d ("branching1d" ), branching3d ("branching3d" ), - cdata ("cdata" ), + cdata ("#cdata" ), channels ("channels" ), characteristicCrossSection ("characteristicCrossSection" ), charge ("charge" ), @@ -156,7 +156,7 @@ inline const Child parameterCovariances ("parameterCovariances" ), parameters ("parameters" ), parity ("parity" ), - pcdata ("pcdata" ), + pcdata ("#pcdata" ), photonEmissionProbabilities ("photonEmissionProbabilities" ), pids ("pids" ), polynomial1d ("polynomial1d" ), @@ -209,7 +209,7 @@ inline const Child unspecified ("unspecified" ), weightedFunctionals ("weightedFunctionals" ), widths ("widths" ), - xml ("xml" ), + xml ("#xml" ), yields ("yields" ); // ------------------------ @@ -231,7 +231,7 @@ inline const Child channel ("channel" ), chemicalElement ("chemicalElement" ), column ("column" ), - comment ("comment" ), + comment ("#comment" ), configuration ("configuration" ), conversion ("conversion" ), covariance ("covariance" ), diff --git a/src/GNDStk/basic/src/meta.hpp b/src/GNDStk/basic/src/meta.hpp index 42e252f60..a7ce43bfd 100644 --- a/src/GNDStk/basic/src/meta.hpp +++ b/src/GNDStk/basic/src/meta.hpp @@ -93,7 +93,7 @@ inline const Meta symbol ("symbol" ), symmetry ("symmetry" ), target ("target" ), - text ("text" ), + text ("#text" ), type ("type" ), types ("types" ), unit ("unit" ), diff --git a/src/GNDStk/common.hpp b/src/GNDStk/common.hpp index e21dd49ec..b333f511a 100644 --- a/src/GNDStk/common.hpp +++ b/src/GNDStk/common.hpp @@ -16,13 +16,13 @@ inline const Child< typename detail::numeric_type::type, Allow::one, detail::convert_pcdata_text_t -> numeric("pcdata"); +> numeric("#pcdata"); // shortcuts for numeric; each gives a vector -inline const auto ints = numeric/"pcdata"; -inline const auto floats = numeric/"pcdata"; -inline const auto doubles = numeric/"pcdata"; -// fixme I'm not sure why the "pcdata" name doesn't come over automatically +inline const auto ints = numeric/"#pcdata"; +inline const auto floats = numeric/"#pcdata"; +inline const auto doubles = numeric/"#pcdata"; +// fixme I'm not sure why the "#pcdata" name doesn't come over automatically // from numeric; it probably relates to order-of-initialization rules (or // lack of rules?) for variable templates. We'll figure that out sometime. // For now, the shortcuts are given the name directly, so it doesn't matter. diff --git a/src/GNDStk/common/src/detail.hpp b/src/GNDStk/common/src/detail.hpp index 38af5eeb1..db9cf2469 100644 --- a/src/GNDStk/common/src/detail.hpp +++ b/src/GNDStk/common/src/detail.hpp @@ -17,17 +17,17 @@ class convert_pcdata_text_t { // We're inside of a node that's inside of a node // that looked something like this (in XML): // 0.0 1.0 2.0 3.0 4.0 - // In GNDStk, the node has a metadatum with the key "text". + // In GNDStk, the node has a metadatum with the key "#text". // The metadatum's string value is the content: "0.0 1.0 ..." in // our example. Goal here: extract that content into the container. container.clear(); for (auto &m : node.metadata) - if (m.first == "text") { + if (m.first == "#text") { convert(m.second, container); return; } log::error( - "Could not find metadatum key \"text\" in the current Node (\"{}\")", + "Could not find metadatum key \"#text\" in the current Node (\"{}\")", node.name ); throw std::exception{}; @@ -43,8 +43,8 @@ class convert_pcdata_text_t { { try { node.clear(); - node.name = "pcdata"; - std::string &destination = node.add("text","").second; + node.name = "#pcdata"; + std::string &destination = node.add("#text","").second; convert(container, destination); } catch (...) { log::function("convert_pcdata_text_t(container,Node)"); diff --git a/src/GNDStk/convert/src/HDF5.hpp b/src/GNDStk/convert/src/HDF5.hpp index 2ca422dfa..2fedf3e25 100644 --- a/src/GNDStk/convert/src/HDF5.hpp +++ b/src/GNDStk/convert/src/HDF5.hpp @@ -40,7 +40,7 @@ inline bool convert(const Node &node, HDF5 &h, const std::string &name) bool found_top = false; for (auto &c : node.children) { - if (c->name == "xml" || c->name == "json" || c->name == "hdf5") { + if (c->name == "#xml" || c->name == "#json" || c->name == "#hdf5") { // looks like a declaration node if (found_decl) { // already seen diff --git a/src/GNDStk/convert/src/JSON.hpp b/src/GNDStk/convert/src/JSON.hpp index b0c94dc79..60618fc7c 100644 --- a/src/GNDStk/convert/src/JSON.hpp +++ b/src/GNDStk/convert/src/JSON.hpp @@ -34,7 +34,7 @@ inline bool convert(const Node &node, JSON &j) bool found_top = false; for (auto &c : node.children) { - if (c->name == "xml" || c->name == "json" || c->name == "hdf5") { + if (c->name == "#xml" || c->name == "#json" || c->name == "#hdf5") { // looks like a declaration node if (found_decl) { // already seen diff --git a/src/GNDStk/convert/src/Tree.hpp b/src/GNDStk/convert/src/Tree.hpp index 561f2fdf3..d6abf4f00 100644 --- a/src/GNDStk/convert/src/Tree.hpp +++ b/src/GNDStk/convert/src/Tree.hpp @@ -51,7 +51,7 @@ inline bool convert(const XML &x, Node &node, const bool decl) // optionally, make a boilerplate declaration node if (decl) - node.add("xml"); // <== indicates that we built the object from an XML + node.add("#xml"); // <== indicates that we built the object from an XML // empty xml document? if (x.empty()) @@ -112,7 +112,7 @@ inline bool convert(const XML &x, Node &node, const bool decl) // Retrieve any XML attributes, e.g. version and encoding if (decl) for (const pugi::xml_attribute &xattr : xnode.attributes()) - node.one("xml").add(xattr.name(), xattr.value()); + node.one("#xml").add(xattr.name(), xattr.value()); } else { // Document node // Visit the node, and its children recursively @@ -160,7 +160,7 @@ inline bool convert(const JSON &j, Node &node, const bool decl) // optionally, make a boilerplate declaration node if (decl) - node.add("json"); // <== indicates that we built the object from a JSON + node.add("#json"); // <== indicates that we built the object from a JSON // empty json document? if (j.empty()) @@ -249,7 +249,7 @@ inline bool convert(const HDF5 &h, Node &node, const bool decl) // optionally, make a boilerplate declaration node Node *const declnode = decl - ? &node.add("hdf5") // indicates that we built the object from an HDF5 + ? &node.add("#hdf5") // indicates that we built the object from an HDF5 : nullptr; // empty hdf5 document? @@ -264,7 +264,7 @@ inline bool convert(const HDF5 &h, Node &node, const bool decl) try { // if decl, then place any top-level attributes that exist, in the HDF5, - // into the Node's "hdf5" child that would have been created above + // into the Node's "#hdf5" child that would have been created above if (decl) for (auto &attrName : group.listAttributeNames()) if (!detail::hdf5attr2node(group.getAttribute(attrName),*declnode)) diff --git a/src/GNDStk/convert/src/XML.hpp b/src/GNDStk/convert/src/XML.hpp index 7f482e1f6..f4b27a610 100644 --- a/src/GNDStk/convert/src/XML.hpp +++ b/src/GNDStk/convert/src/XML.hpp @@ -20,7 +20,7 @@ inline bool convert(const Node &node, XML &x) // The way we're storing things in Tree, a declaration node might contain, // for example, the following, if the Tree was built from an XML: // - // name: "xml" + // name: "#xml" // metadata: // "version", "1.0" // "encoding", "UTF-8" @@ -29,7 +29,7 @@ inline bool convert(const Node &node, XML &x) // // or this if the Tree was built from a JSON: // - // name: "json" + // name: "#json" // metadata: // (nothing; empty vector) // children: @@ -63,7 +63,7 @@ inline bool convert(const Node &node, XML &x) bool found_top = false; for (auto &c : node.children) { - if (c->name == "xml" || c->name == "json" || c->name == "hdf5") { + if (c->name == "#xml" || c->name == "#json" || c->name == "#hdf5") { // looks like a declaration node if (found_decl) { // already seen diff --git a/src/GNDStk/convert/src/detail.hpp b/src/GNDStk/convert/src/detail.hpp index 1d673ada7..c103c9708 100644 --- a/src/GNDStk/convert/src/detail.hpp +++ b/src/GNDStk/convert/src/detail.hpp @@ -26,10 +26,10 @@ bool node2json( // ------------------------ if (suffix != "") - json["nodeName"] = nameOriginal; + json["#nodeName"] = nameOriginal; for (auto &meta : node.metadata) - json["attributes"][meta.first] = meta.second; + json["#attributes"][meta.first] = meta.second; // ------------------------ // children ==> json @@ -175,17 +175,17 @@ bool xml2node(const pugi::xml_node &xnode, NODE &node) // the nlohmann JSON library reorders everything lexicographically. if (xsub.type() == pugi::node_cdata) { - node.add("cdata").add("text", xsub.value()); + node.add("#cdata").add("#text", xsub.value()); continue; } if (xsub.type() == pugi::node_pcdata) { - node.add("pcdata").add("text", xsub.value()); + node.add("#pcdata").add("#text", xsub.value()); continue; } if (xsub.type() == pugi::node_comment) { - node.add("comment").add("text", xsub.value()); + node.add("#comment").add("#text", xsub.value()); continue; } @@ -247,10 +247,10 @@ bool json2node(const nlohmann::json::const_iterator &iter, NODE &node) if (!iter->is_object()) error_json2node("!iter->is_object()"); - // any "attributes" key (a specially-named "child node" that we use in JSON + // any "#attributes" key (a specially-named "child node" that we use in JSON // in order to identify attributes) should have been handled in the caller... - if (iter.key() == "attributes") - error_json2node("iter.key() == \"attributes\""); + if (iter.key() == "#attributes") + error_json2node("iter.key() == \"#attributes\""); // key,value ==> node name, json value to bring in node.name = iter.key(); @@ -258,11 +258,11 @@ bool json2node(const nlohmann::json::const_iterator &iter, NODE &node) // elements for (auto elem = json.begin(); elem != json.end(); ++elem) { - if (elem.key() == "nodeName") { - // nodeName? ...extract as current node's true name + if (elem.key() == "#nodeName") { + // #nodeName? ...extract as current node's true name node.name = elem->get(); - } else if (elem.key() == "attributes") { - // attributes? ...extract as current node's metadata + } else if (elem.key() == "#attributes") { + // #attributes? ...extract as current node's metadata const auto &jsub = elem.value(); for (auto attr = jsub.begin(); attr != jsub.end(); ++attr) node.add(attr.key(), attr->get()); @@ -313,9 +313,9 @@ bool node2hdf5(const NODE &node, OBJECT &h, const std::string &suffix = "") // metadata ==> file/group // ------------------------ - // nodeName if appropriate (as with JSON, allows recovery of original name) + // #nodeName if appropriate (as with JSON, allows recovery of original name) if (suffix != "") - group.createAttribute(std::string("nodeName"), nameOriginal); + group.createAttribute(std::string("#nodeName"), nameOriginal); // existing attributes for (auto &meta : node.metadata) @@ -445,7 +445,7 @@ bool dataTYPE2node(const HighFive::DataSet &data, NODE &node) if (dataSize == 1) { T scalar; data.read(scalar); - node.add("pcdata").add("text",scalar); + node.add("#pcdata").add("#text",scalar); return true; } @@ -453,7 +453,7 @@ bool dataTYPE2node(const HighFive::DataSet &data, NODE &node) std::vector vector; vector.reserve(dataSize); data.read(vector); - node.add("pcdata").add("text",vector); + node.add("#pcdata").add("#text",vector); return true; } } @@ -689,11 +689,11 @@ bool check_special(const NODE &node, const std::string &label) throw std::exception{}; } - if (node.metadata.begin()->first != "text") { + if (node.metadata.begin()->first != "#text") { log::error( "Internal error in node2xml(Node, pugi::xml_node):\n" "Ill-formed <" + label + "> node; " - "should have metadatum key \"text\", but has key \"{}\".", + "should have metadatum key \"#text\", but has key \"{}\".", node.metadata.begin()->first ); throw std::exception{}; @@ -706,8 +706,8 @@ bool check_special(const NODE &node, const std::string &label) template bool write_cdata(const NODE &node, pugi::xml_node &xnode) { - if (!check_special(node,"cdata")) return false; - xnode.append_child(pugi::node_cdata).set_value(node.meta("text").data()); + if (!check_special(node,"#cdata")) return false; + xnode.append_child(pugi::node_cdata).set_value(node.meta("#text").data()); return true; } @@ -715,8 +715,8 @@ bool write_cdata(const NODE &node, pugi::xml_node &xnode) template bool write_pcdata(const NODE &node, pugi::xml_node &xnode) { - if (!check_special(node,"pcdata")) return false; - xnode.append_child(pugi::node_pcdata).set_value(node.meta("text").data()); + if (!check_special(node,"#pcdata")) return false; + xnode.append_child(pugi::node_pcdata).set_value(node.meta("#text").data()); return true; } @@ -724,8 +724,8 @@ bool write_pcdata(const NODE &node, pugi::xml_node &xnode) template bool write_comment(const NODE &node, pugi::xml_node &xnode) { - if (!check_special(node,"comment")) return false; - xnode.append_child(pugi::node_comment).set_value(node.meta("text").data()); + if (!check_special(node,"#comment")) return false; + xnode.append_child(pugi::node_comment).set_value(node.meta("#text").data()); return true; } @@ -748,11 +748,11 @@ bool node2xml(const NODE &node, pugi::xml_node &x) for (auto &child : node.children) { try { // special element - if (child->name == "cdata") + if (child->name == "#cdata") { if (write_cdata (*child,xnode)) continue; else return false; } - if (child->name == "pcdata") + if (child->name == "#pcdata") { if (write_pcdata (*child,xnode)) continue; else return false; } - if (child->name == "comment") + if (child->name == "#comment") { if (write_comment(*child,xnode)) continue; else return false; } // typical element diff --git a/src/GNDStk/misc/src/child.hpp b/src/GNDStk/misc/src/child.hpp index 54fb786f4..da7b9a224 100644 --- a/src/GNDStk/misc/src/child.hpp +++ b/src/GNDStk/misc/src/child.hpp @@ -265,7 +265,7 @@ GNDSTK_MAKE_CHILD(void, unresolved, one); GNDSTK_MAKE_CHILD(void, unresolvedRegion, one); GNDSTK_MAKE_CHILD(void, unspecified, one); GNDSTK_MAKE_CHILD(void, weightedFunctionals, one); -GNDSTK_MAKE_CHILD(void, xml, one); +inline const Child xml("#xml"); GNDSTK_MAKE_CHILD(void, yields, one); // Allow::many cases @@ -313,25 +313,25 @@ inline const Child Double("double"); // These are where XML or (comment) material // resides. It's reasonable to extract such content into std::strings. We // then store these as nodes of those respective names, each with one metadatum -// having a key of "text" and a value containing the original content. +// having a key of "#text" and a value containing the original content. inline const Child - cdata("cdata"); + cdata("#cdata"); inline const Child - comment("comment"); + comment("#comment"); // pcdata // These are where data appearing in constructs like this: // 1.2 3.4 5.6 7.8 9.0 // reside. In that case, our internal tree structure would have a node named -// "values", which would have a child node named "pcdata", which would have a -// metadatum with a key of "text" and a value containing the original content: +// "values", which would have a child node named "#pcdata", which would have a +// metadatum with a key of "#text" and a value containing the original content: // the "1.2 ..." in the above example. Our examination of many GNDS files shows // that some pcdata nodes contain integers, while others contain doubles. We // therefore define pcdata as a Child with , so that we can access it -// in its original form and thus dig further down to its "text" metadatum, at +// in its original form and thus dig further down to its "#text" metadatum, at // which point we can decide elsewhere what's appropriate for that. (Read into // a vector of ints? A vector of doubles? Something else?) inline const Child - pcdata("pcdata"); + pcdata("#pcdata"); } // namespace child diff --git a/src/GNDStk/misc/src/detail.hpp b/src/GNDStk/misc/src/detail.hpp index 44c5e34e0..fc3fd8eff 100644 --- a/src/GNDStk/misc/src/detail.hpp +++ b/src/GNDStk/misc/src/detail.hpp @@ -8,7 +8,7 @@ class text_metadatum_to_string { template void operator()(const NODE &node, std::string &to) const { - to = node.meta("text"); + to = node.meta("#text"); } }; diff --git a/src/GNDStk/node2type/test/node2type.test.cpp b/src/GNDStk/node2type/test/node2type.test.cpp index 34f53e512..35188625e 100644 --- a/src/GNDStk/node2type/test/node2type.test.cpp +++ b/src/GNDStk/node2type/test/node2type.test.cpp @@ -39,10 +39,10 @@ SCENARIO("Testing GNDStk convert(Node,type)") { WHEN("We make a Node foo with particular content") { Node foo("foo"); - // If a Node has a "text" metadatum, then the convert(Node,container) + // If a Node has a "#text" metadatum, then the convert(Node,container) // function, where container is e.g. vector, will attempt to fill - // the container with the contents of the "text" metadatum's value. - foo.add("text","12 34 56 78 90"); + // the container with the contents of the "#text" metadatum's value. + foo.add("#text","12 34 56 78 90"); // Update, 2020-10-19. The relevant convert() functionality has been // reformulated into the detail::convert_pcdata_text_t callable object, diff --git a/src/GNDStk/type2node/test/type2node.test.cpp b/src/GNDStk/type2node/test/type2node.test.cpp index 6df6ba386..796929906 100644 --- a/src/GNDStk/type2node/test/type2node.test.cpp +++ b/src/GNDStk/type2node/test/type2node.test.cpp @@ -7,8 +7,8 @@ using namespace njoy::GNDStk; static const std::string correct_node = -R"***(pcdata: - text: 1 2.3 4.56)***"; +R"***(#pcdata: + #text: 1 2.3 4.56)***"; SCENARIO("Testing GNDStk convert(type,Node)") { @@ -28,10 +28,10 @@ SCENARIO("Testing GNDStk convert(type,Node)") { detail::convert_pcdata_text_t{}(container,n); // one way to check the Node - CHECK(n.name == "pcdata"); + CHECK(n.name == "#pcdata"); CHECK(n.metadata.size() == 1); CHECK(n.children.size() == 0); - CHECK(n.metadata[0].first == "text"); + CHECK(n.metadata[0].first == "#text"); CHECK(n.metadata[0].second == "1 2.3 4.56"); // a shorter way diff --git a/src/GNDStk/utility.hpp b/src/GNDStk/utility.hpp index 0f157c965..bb35d2f4d 100644 --- a/src/GNDStk/utility.hpp +++ b/src/GNDStk/utility.hpp @@ -56,9 +56,9 @@ inline bool sent(const std::string &string) // allowable declaration nodes inline std::set AllowedDecl = { - "xml", - "json", - "hdf5", + "#xml", + "#json", + "#hdf5", }; // noFilter From cfacec97b834615a45ab04eaf0c2e124936ade3d Mon Sep 17 00:00:00 2001 From: Martin Staley Date: Wed, 22 Dec 2021 22:48:01 -0700 Subject: [PATCH 29/39] In generated code: Remove struct defaults where it would be empty. --- autogen/json2class.cpp | 25 +++++++++++++-------- src/GNDStk/v1.9/containers/Axes.hpp | 8 ------- src/GNDStk/v1.9/containers/Axis.hpp | 8 ------- src/GNDStk/v1.9/containers/Link.hpp | 8 ------- src/GNDStk/v1.9/containers/Regions1d.hpp | 8 ------- src/GNDStk/v1.9/transport/CrossSection.hpp | 8 ------- src/GNDStk/v1.9/transport/Reaction.hpp | 8 ------- src/GNDStk/v1.9/transport/ReactionSuite.hpp | 8 ------- src/GNDStk/v1.9/transport/Reactions.hpp | 8 ------- 9 files changed, 16 insertions(+), 73 deletions(-) diff --git a/autogen/json2class.cpp b/autogen/json2class.cpp index 3091dcdfc..b60b84b96 100644 --- a/autogen/json2class.cpp +++ b/autogen/json2class.cpp @@ -1399,17 +1399,24 @@ void writeClass(PerClass &per, const InfoSpecs &specs) out(1,"using BlockData::operator=;"); // output: defaults (applicable only to metadata) - out(); - out(1,smallComment); - out(1,"// Relevant defaults"); - out(1,"// FYI for users"); - out(1,smallComment); - out(); - out(1,"static inline const struct Defaults {"); + std::size_t ndefaults = 0; for (auto &m : per.metadata) if (m.isDefaulted) - out(2,"static inline const @ @ = @;", m.type, m.name, initializer(m)); - out(1,"} defaults;"); + ++ndefaults; + if (ndefaults > 0) { + out(); + out(1,smallComment); + out(1,"// Relevant defaults"); + out(1,"// FYI for users"); + out(1,smallComment); + out(); + out(1,"static inline const struct Defaults {"); + for (auto &m : per.metadata) + if (m.isDefaulted) + out(2, "static inline const @ @ = @;", + m.type, m.name, initializer(m)); + out(1,"} defaults;"); + } // output: content (the metadata/children computed earlier) out(); diff --git a/src/GNDStk/v1.9/containers/Axes.hpp b/src/GNDStk/v1.9/containers/Axes.hpp index 23eb5e590..86cbe8654 100644 --- a/src/GNDStk/v1.9/containers/Axes.hpp +++ b/src/GNDStk/v1.9/containers/Axes.hpp @@ -62,14 +62,6 @@ class Axes : public Component { using Component::construct; - // ------------------------ - // Relevant defaults - // FYI for users - // ------------------------ - - static inline const struct Defaults { - } defaults; - // ------------------------ // Raw GNDS content // ------------------------ diff --git a/src/GNDStk/v1.9/containers/Axis.hpp b/src/GNDStk/v1.9/containers/Axis.hpp index 9eec5a253..169ed7c3d 100644 --- a/src/GNDStk/v1.9/containers/Axis.hpp +++ b/src/GNDStk/v1.9/containers/Axis.hpp @@ -54,14 +54,6 @@ class Axis : public Component { using Component::construct; - // ------------------------ - // Relevant defaults - // FYI for users - // ------------------------ - - static inline const struct Defaults { - } defaults; - // ------------------------ // Raw GNDS content // ------------------------ diff --git a/src/GNDStk/v1.9/containers/Link.hpp b/src/GNDStk/v1.9/containers/Link.hpp index 26e4047dc..3816690a6 100644 --- a/src/GNDStk/v1.9/containers/Link.hpp +++ b/src/GNDStk/v1.9/containers/Link.hpp @@ -50,14 +50,6 @@ class Link : public Component { using Component::construct; - // ------------------------ - // Relevant defaults - // FYI for users - // ------------------------ - - static inline const struct Defaults { - } defaults; - // ------------------------ // Raw GNDS content // ------------------------ diff --git a/src/GNDStk/v1.9/containers/Regions1d.hpp b/src/GNDStk/v1.9/containers/Regions1d.hpp index 6e0fca2c3..bc8cbb3bc 100644 --- a/src/GNDStk/v1.9/containers/Regions1d.hpp +++ b/src/GNDStk/v1.9/containers/Regions1d.hpp @@ -61,14 +61,6 @@ class Regions1d : public Component { using Component::construct; - // ------------------------ - // Relevant defaults - // FYI for users - // ------------------------ - - static inline const struct Defaults { - } defaults; - // ------------------------ // Raw GNDS content // ------------------------ diff --git a/src/GNDStk/v1.9/transport/CrossSection.hpp b/src/GNDStk/v1.9/transport/CrossSection.hpp index 9f2251327..d27cbe118 100644 --- a/src/GNDStk/v1.9/transport/CrossSection.hpp +++ b/src/GNDStk/v1.9/transport/CrossSection.hpp @@ -59,14 +59,6 @@ class CrossSection : public Component { using Component::construct; - // ------------------------ - // Relevant defaults - // FYI for users - // ------------------------ - - static inline const struct Defaults { - } defaults; - // ------------------------ // Raw GNDS content // ------------------------ diff --git a/src/GNDStk/v1.9/transport/Reaction.hpp b/src/GNDStk/v1.9/transport/Reaction.hpp index 75935a6c7..0af499ae9 100644 --- a/src/GNDStk/v1.9/transport/Reaction.hpp +++ b/src/GNDStk/v1.9/transport/Reaction.hpp @@ -60,14 +60,6 @@ class Reaction : public Component { using Component::construct; - // ------------------------ - // Relevant defaults - // FYI for users - // ------------------------ - - static inline const struct Defaults { - } defaults; - // ------------------------ // Raw GNDS content // ------------------------ diff --git a/src/GNDStk/v1.9/transport/ReactionSuite.hpp b/src/GNDStk/v1.9/transport/ReactionSuite.hpp index f91f87580..1e9317ee4 100644 --- a/src/GNDStk/v1.9/transport/ReactionSuite.hpp +++ b/src/GNDStk/v1.9/transport/ReactionSuite.hpp @@ -66,14 +66,6 @@ class ReactionSuite : public Component { using Component::construct; - // ------------------------ - // Relevant defaults - // FYI for users - // ------------------------ - - static inline const struct Defaults { - } defaults; - // ------------------------ // Raw GNDS content // ------------------------ diff --git a/src/GNDStk/v1.9/transport/Reactions.hpp b/src/GNDStk/v1.9/transport/Reactions.hpp index 1b112288e..18db8d667 100644 --- a/src/GNDStk/v1.9/transport/Reactions.hpp +++ b/src/GNDStk/v1.9/transport/Reactions.hpp @@ -53,14 +53,6 @@ class Reactions : public Component { using Component::construct; - // ------------------------ - // Relevant defaults - // FYI for users - // ------------------------ - - static inline const struct Defaults { - } defaults; - // ------------------------ // Raw GNDS content // ------------------------ From 502588b0c068c818a6cc7b1a8ec6279c5f28c3e7 Mon Sep 17 00:00:00 2001 From: Martin Staley Date: Fri, 7 Jan 2022 17:04:37 -0700 Subject: [PATCH 30/39] Remove unused built-in Meta and Child objects. For quite some time, GNDStk's Core Interface had a large number of `Meta` and `Child` objects in its `basic::` and `misc::` namespaces. This was set up prior to us making our current plan: to have GNDStk Standard Interfaces for GNDS 2.0, etc. Going forward, we anticipate that each Standard Interface will have all necessary `Meta` and `Child` objects built for it automatically, by our code generator, when our code generator generates the Standard Interface's classes. That means we need to keep only the current `Meta` and `Child` objects that happen to be used in existing test codes. Or, in a few instances, elsewhere in the Core Interface. Future work (not included right now) will consist of phasing out any remaining uses of these objects in Core Interface code. (Where that happens, we'll just make `Meta` or `Child` objects directly where they're needed.) Then, finally, we'll move any remaining `Meta` and `Child` objects - ones that are used in the test suite - into non-Core-Interface files that would be included only in test-suite code. --- src/GNDStk/basic/src/child.hpp | 302 +++++------------------------- src/GNDStk/basic/src/meta.hpp | 111 +---------- src/GNDStk/common.hpp | 4 +- src/GNDStk/misc/src/child.hpp | 326 ++------------------------------- src/GNDStk/misc/src/meta.hpp | 122 +----------- 5 files changed, 74 insertions(+), 791 deletions(-) diff --git a/src/GNDStk/basic/src/child.hpp b/src/GNDStk/basic/src/child.hpp index 8615a9241..39b93ac59 100644 --- a/src/GNDStk/basic/src/child.hpp +++ b/src/GNDStk/basic/src/child.hpp @@ -3,283 +3,65 @@ namespace child { // ----------------------------------------------------------------------------- // Child -// -// The list below was auto-generated by a code we wrote that looked for all -// elements in every existing XML-format GNDS file that we had, and guessed, -// based on what it saw, if the element should be formulated as an Allow::one -// or an Allow::many. We then tweaked the auto-generated list just a bit; for -// example, to change "double" to "Double". At some point we'll probably want -// to tweak it more, based on a careful study of the GNDS specs. // ----------------------------------------------------------------------------- // Note: a Child will retrieve an element in its original form // in the GNDS tree: as (a const or non-const reference to) a Node. +// ------------------------ +// Some top-level nodes, +// per LLNL-TR-774621-DRAFT +// ------------------------ -// ----------------------------------------------------------------------------- -// Allowable top-level nodes, per LLNL-TR-774621-DRAFT -// ----------------------------------------------------------------------------- - -inline const auto - PoPs = Child("PoPs"); -inline const auto - reactionSuite = Child("reactionSuite"); -inline const auto - covarianceSuite = Child("covarianceSuite"); -inline const auto - thermalScattering = Child("thermalScattering"); -inline const auto - fissionFragmentData = Child("fissionFragmentData"); - - - -// ----------------------------------------------------------------------------- -// General elements -// ----------------------------------------------------------------------------- +inline const Child PoPs("PoPs"); +inline const Child reactionSuite("reactionSuite"); // ------------------------ // With Allow::one // ------------------------ inline const Child - BreitWigner ("BreitWigner" ), - CoulombPlusNuclearElastic ("CoulombPlusNuclearElastic" ), - DebyeWaller ("DebyeWaller" ), - EFH ("EFH" ), - EFL ("EFL" ), - ENDFconversionFlags ("ENDFconversionFlags" ), - Js ("Js" ), - KalbachMann ("KalbachMann" ), - Ls ("Ls" ), - MadlandNix ("MadlandNix" ), - NBodyPhaseSpace ("NBodyPhaseSpace" ), - Q ("Q" ), - RMatrix ("RMatrix" ), - RutherfordScattering ("RutherfordScattering" ), - S_alpha_beta ("S_alpha_beta" ), - S_table ("S_table" ), - T_M ("T_M" ), - T_effective ("T_effective" ), - U ("U" ), - aliases ("aliases" ), - angular ("angular" ), - angularEnergy ("angularEnergy" ), - angularTwoBody ("angularTwoBody" ), - applicationData ("applicationData" ), - array ("array" ), - atomic ("atomic" ), - averageEnergies ("averageEnergies" ), - averageProductEnergy ("averageProductEnergy" ), - axes ("axes" ), - background ("background" ), - baryons ("baryons" ), - bindingEnergy ("bindingEnergy" ), - branching1d ("branching1d" ), - branching3d ("branching3d" ), - cdata ("#cdata" ), - channels ("channels" ), - characteristicCrossSection ("characteristicCrossSection" ), - charge ("charge" ), - chemicalElements ("chemicalElements" ), - coherentElastic ("coherentElastic" ), - coherentPhotonScattering ("coherentPhotonScattering" ), - columnData ("columnData" ), - columnHeaders ("columnHeaders" ), - configurations ("configurations" ), - constant1d ("constant1d" ), - continuum ("continuum" ), - covarianceSections ("covarianceSections" ), - crossSection ("crossSection" ), - crossSections ("crossSections" ), - cutoffEnergy ("cutoffEnergy" ), - data ("data" ), - decayData ("decayData" ), - decayModes ("decayModes" ), - decayPath ("decayPath" ), - delayedBetaEnergy ("delayedBetaEnergy" ), - delayedGammaEnergy ("delayedGammaEnergy" ), - delayedNeutronKE ("delayedNeutronKE" ), - discreteGamma ("discreteGamma" ), - distribution ("distribution" ), - documentation ("documentation" ), - documentations ("documentations" ), - Double ("double" ), - doubleDifferentialCrossSection ("doubleDifferentialCrossSection" ), - durations ("durations" ), - e_critical ("e_critical" ), - e_max ("e_max" ), - energy ("energy" ), - energyAngular ("energyAngular" ), - evaporation ("evaporation" ), - externalFiles ("externalFiles" ), - f ("f" ), - fastRegion ("fastRegion" ), - fissionComponents ("fissionComponents" ), - fissionEnergyReleased ("fissionEnergyReleased" ), - freeAtomCrossSection ("freeAtomCrossSection" ), - g ("g" ), - gaugeBosons ("gaugeBosons" ), - generalEvaporation ("generalEvaporation" ), - gridded2d ("gridded2d" ), - gridded3d ("gridded3d" ), - halflife ("halflife" ), - hardSphereRadius ("hardSphereRadius" ), - imaginaryAnomalousFactor ("imaginaryAnomalousFactor" ), - imaginaryInterferenceTerm ("imaginaryInterferenceTerm" ), - incoherentElastic ("incoherentElastic" ), - incoherentInelastic ("incoherentInelastic" ), - incoherentPhotonScattering ("incoherentPhotonScattering" ), - incompleteReactions ("incompleteReactions" ), - institution ("institution" ), - intensity ("intensity" ), - internalConversionCoefficients ("internalConversionCoefficients" ), - internalPairFormationCoefficient("internalPairFormationCoefficient"), - isotopes ("isotopes" ), - isotropic2d ("isotropic2d" ), - leptons ("leptons" ), - levelSpacing ("levelSpacing" ), - link ("link" ), - listOfCovariances ("listOfCovariances" ), - mass ("mass" ), - mixed ("mixed" ), - multiplicities ("multiplicities" ), - multiplicity ("multiplicity" ), - neutrinoEnergy ("neutrinoEnergy" ), - nonNeutrinoEnergy ("nonNeutrinoEnergy" ), - nuclearAmplitudeExpansion ("nuclearAmplitudeExpansion" ), - nuclearPlusInterference ("nuclearPlusInterference" ), - nuclearTerm ("nuclearTerm" ), - nucleus ("nucleus" ), - nuclides ("nuclides" ), - orphanProducts ("orphanProducts" ), - outputChannel ("outputChannel" ), - parameterCovariances ("parameterCovariances" ), - parameters ("parameters" ), - parity ("parity" ), - pcdata ("#pcdata" ), - photonEmissionProbabilities ("photonEmissionProbabilities" ), - pids ("pids" ), - polynomial1d ("polynomial1d" ), - positronEmissionIntensity ("positronEmissionIntensity" ), - primaryGamma ("primaryGamma" ), - probability ("probability" ), - productYields ("productYields" ), - productions ("productions" ), - products ("products" ), - projectileEnergyDomain ("projectileEnergyDomain" ), - promptGammaEnergy ("promptGammaEnergy" ), - promptNeutronKE ("promptNeutronKE" ), - promptProductKE ("promptProductKE" ), - r ("r" ), - reactions ("reactions" ), - realAnomalousFactor ("realAnomalousFactor" ), - realInterferenceTerm ("realInterferenceTerm" ), - recoil ("recoil" ), - reference ("reference" ), - regions2d ("regions2d" ), - resolved ("resolved" ), - resolvedRegion ("resolvedRegion" ), - resonanceParameters ("resonanceParameters" ), - resonanceReactions ("resonanceReactions" ), - resonances ("resonances" ), - resonancesWithBackground ("resonancesWithBackground" ), - rowData ("rowData" ), - scatteringAtoms ("scatteringAtoms" ), - scatteringFactor ("scatteringFactor" ), - scatteringRadius ("scatteringRadius" ), - simpleMaxwellianFission ("simpleMaxwellianFission" ), - spectra ("spectra" ), - spin ("spin" ), - spinGroups ("spinGroups" ), - standard ("standard" ), - string ("string" ), - styles ("styles" ), - summands ("summands" ), - sums ("sums" ), - table ("table" ), - tabulatedWidths ("tabulatedWidths" ), - temperature ("temperature" ), - theta ("theta" ), - time ("time" ), - totalEnergy ("totalEnergy" ), - uncertainty ("uncertainty" ), - uncorrelated ("uncorrelated" ), - unresolved ("unresolved" ), - unresolvedRegion ("unresolvedRegion" ), - unspecified ("unspecified" ), - weightedFunctionals ("weightedFunctionals" ), - widths ("widths" ), - xml ("#xml" ), - yields ("yields" ); + RMatrix ("RMatrix" ), + angularTwoBody ("angularTwoBody" ), + axes ("axes" ), + cdata ("#cdata" ), + chemicalElements ("chemicalElements" ), + crossSection ("crossSection" ), + data ("data" ), + distribution ("distribution" ), + documentation ("documentation" ), + documentations ("documentations" ), + Double ("double" ), + gaugeBosons ("gaugeBosons" ), + mass ("mass" ), + outputChannel ("outputChannel" ), + pcdata ("#pcdata" ), + products ("products" ), + reactions ("reactions" ), + regions2d ("regions2d" ), + resolved ("resolved" ), + resonanceParameters("resonanceParameters"), + resonances ("resonances" ), + spin ("spin" ), + spinGroups ("spinGroups" ), + styles ("styles" ), + table ("table" ), + temperature ("temperature" ); // ------------------------ // With Allow::many // ------------------------ inline const Child - J ("J" ), - L ("L" ), - Legendre ("Legendre" ), - XYs1d ("XYs1d" ), - XYs2d ("XYs2d" ), - XYs3d ("XYs3d" ), - add ("add" ), - averageEnergy ("averageEnergy" ), - averageParameterCovariance ("averageParameterCovariance" ), - axis ("axis" ), - baryon ("baryon" ), - channel ("channel" ), - chemicalElement ("chemicalElement" ), - column ("column" ), - comment ("#comment" ), - configuration ("configuration" ), - conversion ("conversion" ), - covariance ("covariance" ), - covarianceMatrix ("covarianceMatrix" ), - crossSectionReconstructed ("crossSectionReconstructed" ), - crossSectionSum ("crossSectionSum" ), - decay ("decay" ), - decayMode ("decayMode" ), - discrete ("discrete" ), - duration ("duration" ), - evaluated ("evaluated" ), - externalFile ("externalFile" ), - fissionComponent ("fissionComponent" ), - fraction ("fraction" ), - gaugeBoson ("gaugeBoson" ), - grid ("grid" ), - integer ("integer" ), - isotope ("isotope" ), - lepton ("lepton" ), - metaStable ("metaStable" ), - multiplicitySum ("multiplicitySum" ), - nuclide ("nuclide" ), - parameterCovariance ("parameterCovariance" ), - parameterCovarianceMatrix ("parameterCovarianceMatrix" ), - parameterLink ("parameterLink" ), - product ("product" ), - production ("production" ), - productYield ("productYield" ), - reaction ("reaction" ), - regions1d ("regions1d" ), - resonanceReaction ("resonanceReaction" ), - scatteringAtom ("scatteringAtom" ), - section ("section" ), - shell ("shell" ), - shortRangeSelfScalingVariance ("shortRangeSelfScalingVariance" ), - spectrum ("spectrum" ), - spinGroup ("spinGroup" ), - sum ("sum" ), - summand ("summand" ), - values ("values" ), - weighted ("weighted" ), - width ("width" ); - -// fixme Probably redo this entire file based on Standard Interface experience -// fixme Same with misc:: namespace entries, assuming we keep misc:: -// Additional ones I've encountered while writing the Standard Interface -inline const Child interval("interval"); -inline const Child confidenceIntervals("confidenceIntervals"); -inline const Child logNormal("logNormal"); + XYs1d ("XYs1d" ), + axis ("axis" ), + chemicalElement("chemicalElement"), + evaluated ("evaluated" ), + fraction ("fraction" ), + gaugeBoson ("gaugeBoson" ), + product ("product" ), + reaction ("reaction" ), + spinGroup ("spinGroup" ), + values ("values" ); } // namespace child diff --git a/src/GNDStk/basic/src/meta.hpp b/src/GNDStk/basic/src/meta.hpp index a7ce43bfd..ffa445781 100644 --- a/src/GNDStk/basic/src/meta.hpp +++ b/src/GNDStk/basic/src/meta.hpp @@ -12,107 +12,14 @@ namespace meta { inline const Meta - A ("A" ), - ENDF_MFMT ("ENDF_MFMT" ), - ENDF_MT ("ENDF_MT" ), - L ("L" ), - MAT ("MAT" ), - Z ("Z" ), - approximation ("approximation" ), - asymmetric ("asymmetric" ), - boundaryCondition ("boundaryCondition" ), - calculateChannelRadius ("calculateChannelRadius" ), - calculatePenetrability ("calculatePenetrability" ), - calculatedAtThermal ("calculatedAtThermal" ), - channelSpin ("channelSpin" ), - coefficient ("coefficient" ), - columnIndex ("columnIndex" ), - columns ("columns" ), - complete ("complete" ), - compression ("compression" ), - constant ("constant" ), - crossTerm ("crossTerm" ), - date ("date" ), - decayRate ("decayRate" ), - degreesOfFreedom ("degreesOfFreedom" ), - dependenceOnProcessedGroupWidth("dependenceOnProcessedGroupWidth"), - derivedFrom ("derivedFrom" ), - domainMax ("domainMax" ), - domainMin ("domainMin" ), - domainUnit ("domainUnit" ), - ejectile ("ejectile" ), - electronNumber ("electronNumber" ), - eliminated ("eliminated" ), - emissionMode ("emissionMode" ), - encoding ("encoding" ), - evaluation ("evaluation" ), - final ("final" ), - fissionGenre ("fissionGenre" ), - flags ("flags" ), - format ("format" ), - functionalForm ("functionalForm" ), - generation ("generation" ), - genre ("genre" ), - href ("href" ), - id ("id" ), - identicalParticles ("identicalParticles" ), - index ("index" ), - initial ("initial" ), - interpolation ("interpolation" ), - interpolationQualifier ("interpolationQualifier" ), - label ("label" ), - length ("length" ), - library ("library" ), - lowerIndex ("lowerIndex" ), - material ("material" ), - matrixStartIndex ("matrixStartIndex" ), - max ("max" ), - metaStableIndex ("metaStableIndex" ), - min ("min" ), - mode ("mode" ), - muCutoff ("muCutoff" ), - nParameters ("nParameters" ), - name ("name" ), - numberOfProducts ("numberOfProducts" ), - numberPerMolecule ("numberPerMolecule" ), - parity ("parity" ), - path ("path" ), - pid ("pid" ), - process ("process" ), - productFrame ("productFrame" ), - projectile ("projectile" ), - projectileFrame ("projectileFrame" ), - resonanceReaction ("resonanceReaction" ), - rows ("rows" ), - shape ("shape" ), - spin ("spin" ), - start ("start" ), - style ("style" ), - subshell ("subshell" ), - supportsAngularReconstruction ("supportsAngularReconstruction" ), - symbol ("symbol" ), - symmetry ("symmetry" ), - target ("target" ), - text ("#text" ), - type ("type" ), - types ("types" ), - unit ("unit" ), - useForSelfShieldingOnly ("useForSelfShieldingOnly" ), - value ("value" ), - valueType ("valueType" ), - version ("version" ); - -// fixme Probably redo this entire file based on Standard Interface experience -// fixme Same with misc:: namespace entries, assuming we keep misc:: -// Additional ones I've encountered while writing the Standard Interface -inline const Meta - confidence ("confidence" ), - lower ("lower" ), - upper ("upper" ), - offset ("offset" ), - permutation ("permutation" ), - storageOrder("storageOrder"), - sep ("sep" ), - outerDomainValue("outerDomainValue"); + ENDF_MT ("ENDF_MT" ), + index ("index" ), + label ("label" ), + projectile("projectile"), + symbol ("symbol" ), + text ("#text" ), + unit ("unit" ), + value ("value" ), + version ("version" ); } // namespace meta diff --git a/src/GNDStk/common.hpp b/src/GNDStk/common.hpp index b333f511a..00567c056 100644 --- a/src/GNDStk/common.hpp +++ b/src/GNDStk/common.hpp @@ -19,12 +19,10 @@ inline const Child< > numeric("#pcdata"); // shortcuts for numeric; each gives a vector -inline const auto ints = numeric/"#pcdata"; -inline const auto floats = numeric/"#pcdata"; +inline const auto floats = numeric/"#pcdata"; inline const auto doubles = numeric/"#pcdata"; // fixme I'm not sure why the "#pcdata" name doesn't come over automatically // from numeric; it probably relates to order-of-initialization rules (or // lack of rules?) for variable templates. We'll figure that out sometime. -// For now, the shortcuts are given the name directly, so it doesn't matter. } // namespace common diff --git a/src/GNDStk/misc/src/child.hpp b/src/GNDStk/misc/src/child.hpp index da7b9a224..447331f28 100644 --- a/src/GNDStk/misc/src/child.hpp +++ b/src/GNDStk/misc/src/child.hpp @@ -1,337 +1,45 @@ namespace child { -// ----------------------------------------------------------------------------- -// Allowable top-level nodes, per LLNL-TR-774621-DRAFT -// ----------------------------------------------------------------------------- - -inline const auto - PoPs = Child("PoPs"); -inline const auto - reactionSuite = Child("reactionSuite"); -inline const auto - covarianceSuite = Child("covarianceSuite"); -inline const auto - thermalScattering = Child("thermalScattering"); -inline const auto - fissionFragmentData = Child("fissionFragmentData"); - - +// ------------------------ +// Some top-level nodes, +// per LLNL-TR-774621-DRAFT +// ------------------------ -// ----------------------------------------------------------------------------- -// Child Objects -// ----------------------------------------------------------------------------- +inline const Child PoPs ("PoPs"); +inline const Child reactionSuite ("reactionSuite"); +inline const Child covarianceSuite ("covarianceSuite"); +inline const Child thermalScattering("thermalScattering"); // ------------------------ -// one + many pair -// constructs +// Misc. Child Objects // ------------------------ -GNDSTK_MAKE_CHILD(void, averageEnergies, one); -GNDSTK_MAKE_CHILD(void, averageEnergy, many); - GNDSTK_MAKE_CHILD(void, axes, one); GNDSTK_MAKE_CHILD(void, axis, many); - -GNDSTK_MAKE_CHILD(void, baryons, one); -GNDSTK_MAKE_CHILD(void, baryon, many); - -GNDSTK_MAKE_CHILD(void, channels, one); -GNDSTK_MAKE_CHILD(void, channel, many); - GNDSTK_MAKE_CHILD(void, chemicalElements, one); GNDSTK_MAKE_CHILD(void, chemicalElement, many); - -GNDSTK_MAKE_CHILD(void, configurations, one); -GNDSTK_MAKE_CHILD(void, configuration, many); - -GNDSTK_MAKE_CHILD(void, decayModes, one); -GNDSTK_MAKE_CHILD(void, decayMode, many); - -GNDSTK_MAKE_CHILD(void, durations, one); -GNDSTK_MAKE_CHILD(void, duration, many); - -GNDSTK_MAKE_CHILD(void, externalFiles, one); -GNDSTK_MAKE_CHILD(void, externalFile, many); - -GNDSTK_MAKE_CHILD(void, fissionComponents, one); -GNDSTK_MAKE_CHILD(void, fissionComponent, many); - -GNDSTK_MAKE_CHILD(void, gaugeBosons, one); -GNDSTK_MAKE_CHILD(void, gaugeBoson, many); - GNDSTK_MAKE_CHILD(void, isotopes, one); GNDSTK_MAKE_CHILD(void, isotope, many); - -GNDSTK_MAKE_CHILD(void, Js, one); -GNDSTK_MAKE_CHILD(void, J, many); - -GNDSTK_MAKE_CHILD(void, leptons, one); -GNDSTK_MAKE_CHILD(void, lepton, many); - GNDSTK_MAKE_CHILD(void, nuclides, one); -GNDSTK_MAKE_CHILD(void, nuclide, many); - -GNDSTK_MAKE_CHILD(void, productions, one); -// The GNDS manual says: -// production: [optional, must appear one time] -// but we think that that's wrong. It actually does appear more than once -// in some parent nodes in some GNDS files. We think the manual makes the -// same mistake at least two more times - with and . -// Both sometimes appear multiple times under a single parent in some GNDS -// files, but the manual says "must appear one time" for both. (The manual -// says "must appear at least one time" elsewhere, for things that can -// appear multiple times under a single parent.) -GNDSTK_MAKE_CHILD(void, production, many); - -GNDSTK_MAKE_CHILD(void, products, one); -GNDSTK_MAKE_CHILD(void, product, many); - -GNDSTK_MAKE_CHILD(void, productYields, one); -GNDSTK_MAKE_CHILD(void, productYield, many); - GNDSTK_MAKE_CHILD(void, reactions, one); GNDSTK_MAKE_CHILD(void, reaction, many); - -GNDSTK_MAKE_CHILD(void, resonanceReactions, one); -GNDSTK_MAKE_CHILD(void, resonanceReaction, many); - -GNDSTK_MAKE_CHILD(void, scatteringAtoms, one); -GNDSTK_MAKE_CHILD(void, scatteringAtom, many); - -GNDSTK_MAKE_CHILD(void, spectra, one); -GNDSTK_MAKE_CHILD(void, spectrum, many); - -GNDSTK_MAKE_CHILD(void, spinGroups, one); -GNDSTK_MAKE_CHILD(void, spinGroup, many); - -GNDSTK_MAKE_CHILD(void, widths, one); -GNDSTK_MAKE_CHILD(void, width, many); - -GNDSTK_MAKE_CHILD(void, sums, one); -GNDSTK_MAKE_CHILD(void, sum, many); - -GNDSTK_MAKE_CHILD(void, Ls, one); -GNDSTK_MAKE_CHILD(void, L, many); - -GNDSTK_MAKE_CHILD(void, summands, one); -GNDSTK_MAKE_CHILD(void, summand, many); - - -// ------------------------ -// Others, not paired -// as above -// ------------------------ - -// fixme -// Do more sorting/categorization -// Some may actually be singular/plural pairs - -// Allow::one cases -GNDSTK_MAKE_CHILD(void, aliases, one); -GNDSTK_MAKE_CHILD(void, angular, one); -GNDSTK_MAKE_CHILD(void, angularEnergy, one); -GNDSTK_MAKE_CHILD(void, angularTwoBody, one); -GNDSTK_MAKE_CHILD(void, applicationData, one); -GNDSTK_MAKE_CHILD(void, array, one); -GNDSTK_MAKE_CHILD(void, atomic, one); -GNDSTK_MAKE_CHILD(void, averageProductEnergy, one); -GNDSTK_MAKE_CHILD(void, background, one); -GNDSTK_MAKE_CHILD(void, bindingEnergy, one); -GNDSTK_MAKE_CHILD(void, branching1d, one); -GNDSTK_MAKE_CHILD(void, branching3d, one); -GNDSTK_MAKE_CHILD(void, BreitWigner, one); -GNDSTK_MAKE_CHILD(void, characteristicCrossSection, one); -GNDSTK_MAKE_CHILD(void, charge, one); -GNDSTK_MAKE_CHILD(void, coherentElastic, one); -GNDSTK_MAKE_CHILD(void, coherentPhotonScattering, one); -GNDSTK_MAKE_CHILD(void, columnData, one); -GNDSTK_MAKE_CHILD(void, columnHeaders, one); -GNDSTK_MAKE_CHILD(void, constant1d, one); -GNDSTK_MAKE_CHILD(void, continuum, one); -GNDSTK_MAKE_CHILD(void, CoulombPlusNuclearElastic, one); -GNDSTK_MAKE_CHILD(void, covarianceSections, one); GNDSTK_MAKE_CHILD(void, crossSection, one); -GNDSTK_MAKE_CHILD(void, crossSections, one); -GNDSTK_MAKE_CHILD(void, cutoffEnergy, one); -GNDSTK_MAKE_CHILD(void, data, one); -GNDSTK_MAKE_CHILD(void, DebyeWaller, one); -GNDSTK_MAKE_CHILD(void, decayData, one); -GNDSTK_MAKE_CHILD(void, decayPath, one); -GNDSTK_MAKE_CHILD(void, delayedBetaEnergy, one); -GNDSTK_MAKE_CHILD(void, delayedGammaEnergy, one); -GNDSTK_MAKE_CHILD(void, delayedNeutronKE, one); -GNDSTK_MAKE_CHILD(void, discreteGamma, one); -GNDSTK_MAKE_CHILD(void, distribution, one); -GNDSTK_MAKE_CHILD(void, documentation, one); -GNDSTK_MAKE_CHILD(void, documentations, one); -GNDSTK_MAKE_CHILD(void, doubleDifferentialCrossSection, one); -GNDSTK_MAKE_CHILD(void, e_critical, one); -GNDSTK_MAKE_CHILD(void, EFH, one); -GNDSTK_MAKE_CHILD(void, EFL, one); -GNDSTK_MAKE_CHILD(void, e_max, one); -GNDSTK_MAKE_CHILD(void, ENDFconversionFlags, one); -GNDSTK_MAKE_CHILD(void, energy, one); -GNDSTK_MAKE_CHILD(void, energyAngular, one); -GNDSTK_MAKE_CHILD(void, evaporation, one); -GNDSTK_MAKE_CHILD(void, f, one); -GNDSTK_MAKE_CHILD(void, fastRegion, one); -GNDSTK_MAKE_CHILD(void, fissionEnergyReleased, one); -GNDSTK_MAKE_CHILD(void, freeAtomCrossSection, one); -GNDSTK_MAKE_CHILD(void, g, one); -GNDSTK_MAKE_CHILD(void, generalEvaporation, one); -GNDSTK_MAKE_CHILD(void, gridded2d, one); -GNDSTK_MAKE_CHILD(void, gridded3d, one); -GNDSTK_MAKE_CHILD(void, halflife, one); -GNDSTK_MAKE_CHILD(void, hardSphereRadius, one); -GNDSTK_MAKE_CHILD(void, imaginaryAnomalousFactor, one); -GNDSTK_MAKE_CHILD(void, imaginaryInterferenceTerm, one); -GNDSTK_MAKE_CHILD(void, incoherentElastic, one); -GNDSTK_MAKE_CHILD(void, incoherentInelastic, one); -GNDSTK_MAKE_CHILD(void, incoherentPhotonScattering, one); -GNDSTK_MAKE_CHILD(void, incompleteReactions, one); -GNDSTK_MAKE_CHILD(void, institution, one); -GNDSTK_MAKE_CHILD(void, intensity, one); -GNDSTK_MAKE_CHILD(void, internalConversionCoefficients, one); -GNDSTK_MAKE_CHILD(void, internalPairFormationCoefficient, one); -GNDSTK_MAKE_CHILD(void, isotropic2d, one); -GNDSTK_MAKE_CHILD(void, KalbachMann, one); -GNDSTK_MAKE_CHILD(void, levelSpacing, one); -GNDSTK_MAKE_CHILD(void, link, one); -GNDSTK_MAKE_CHILD(void, listOfCovariances, one); -GNDSTK_MAKE_CHILD(void, MadlandNix, one); -GNDSTK_MAKE_CHILD(void, mass, one); -GNDSTK_MAKE_CHILD(void, mixed, one); -GNDSTK_MAKE_CHILD(void, multiplicities, one); -GNDSTK_MAKE_CHILD(void, multiplicity, one); -GNDSTK_MAKE_CHILD(void, NBodyPhaseSpace, one); -GNDSTK_MAKE_CHILD(void, neutrinoEnergy, one); -GNDSTK_MAKE_CHILD(void, nonNeutrinoEnergy, one); -GNDSTK_MAKE_CHILD(void, nuclearAmplitudeExpansion, one); -GNDSTK_MAKE_CHILD(void, nuclearPlusInterference, one); -GNDSTK_MAKE_CHILD(void, nuclearTerm, one); -GNDSTK_MAKE_CHILD(void, nucleus, one); -GNDSTK_MAKE_CHILD(void, orphanProducts, one); -GNDSTK_MAKE_CHILD(void, outputChannel, one); -GNDSTK_MAKE_CHILD(void, parameterCovariances, one); -GNDSTK_MAKE_CHILD(void, parameters, one); -GNDSTK_MAKE_CHILD(void, parity, one); -GNDSTK_MAKE_CHILD(void, photonEmissionProbabilities, one); -GNDSTK_MAKE_CHILD(void, pids, one); -GNDSTK_MAKE_CHILD(void, polynomial1d, one); -GNDSTK_MAKE_CHILD(void, positronEmissionIntensity, one); -GNDSTK_MAKE_CHILD(void, primaryGamma, one); -GNDSTK_MAKE_CHILD(void, probability, one); -GNDSTK_MAKE_CHILD(void, projectileEnergyDomain, one); -GNDSTK_MAKE_CHILD(void, promptGammaEnergy, one); -GNDSTK_MAKE_CHILD(void, promptNeutronKE, one); -GNDSTK_MAKE_CHILD(void, promptProductKE, one); -GNDSTK_MAKE_CHILD(void, Q, one); -GNDSTK_MAKE_CHILD(void, r, one); -GNDSTK_MAKE_CHILD(void, realAnomalousFactor, one); -GNDSTK_MAKE_CHILD(void, realInterferenceTerm, one); -GNDSTK_MAKE_CHILD(void, recoil, one); -GNDSTK_MAKE_CHILD(void, reference, one); -GNDSTK_MAKE_CHILD(void, regions2d, one); -GNDSTK_MAKE_CHILD(void, resolved, one); -GNDSTK_MAKE_CHILD(void, resolvedRegion, one); -GNDSTK_MAKE_CHILD(void, resonanceParameters, one); -GNDSTK_MAKE_CHILD(void, resonances, one); -GNDSTK_MAKE_CHILD(void, resonancesWithBackground, one); -GNDSTK_MAKE_CHILD(void, RMatrix, one); -GNDSTK_MAKE_CHILD(void, rowData, one); -GNDSTK_MAKE_CHILD(void, RutherfordScattering, one); -GNDSTK_MAKE_CHILD(void, S_alpha_beta, one); -GNDSTK_MAKE_CHILD(void, scatteringFactor, one); -GNDSTK_MAKE_CHILD(void, scatteringRadius, one); -GNDSTK_MAKE_CHILD(void, simpleMaxwellianFission, one); -GNDSTK_MAKE_CHILD(void, spin, one); -GNDSTK_MAKE_CHILD(void, S_table, one); -GNDSTK_MAKE_CHILD(void, standard, one); -GNDSTK_MAKE_CHILD(void, string, one); GNDSTK_MAKE_CHILD(void, styles, one); -GNDSTK_MAKE_CHILD(void, table, one); -GNDSTK_MAKE_CHILD(void, tabulatedWidths, one); -GNDSTK_MAKE_CHILD(void, T_effective, one); GNDSTK_MAKE_CHILD(void, temperature, one); -GNDSTK_MAKE_CHILD(void, theta, one); -GNDSTK_MAKE_CHILD(void, time, one); -GNDSTK_MAKE_CHILD(void, T_M, one); -GNDSTK_MAKE_CHILD(void, totalEnergy, one); -GNDSTK_MAKE_CHILD(void, U, one); -GNDSTK_MAKE_CHILD(void, uncertainty, one); -GNDSTK_MAKE_CHILD(void, uncorrelated, one); -GNDSTK_MAKE_CHILD(void, unresolved, one); -GNDSTK_MAKE_CHILD(void, unresolvedRegion, one); -GNDSTK_MAKE_CHILD(void, unspecified, one); -GNDSTK_MAKE_CHILD(void, weightedFunctionals, one); inline const Child xml("#xml"); -GNDSTK_MAKE_CHILD(void, yields, one); - -// Allow::many cases -GNDSTK_MAKE_CHILD(void, add, many); -GNDSTK_MAKE_CHILD(void, averageParameterCovariance, many); -GNDSTK_MAKE_CHILD(void, column, many); -GNDSTK_MAKE_CHILD(void, conversion, many); -GNDSTK_MAKE_CHILD(void, covariance, many); -GNDSTK_MAKE_CHILD(void, covarianceMatrix, many); -GNDSTK_MAKE_CHILD(void, crossSectionReconstructed, many); -GNDSTK_MAKE_CHILD(void, crossSectionSum, many); -GNDSTK_MAKE_CHILD(void, decay, many); -GNDSTK_MAKE_CHILD(void, discrete, many); GNDSTK_MAKE_CHILD(void, evaluated, many); -GNDSTK_MAKE_CHILD(void, fraction, many); -GNDSTK_MAKE_CHILD(void, grid, many); -GNDSTK_MAKE_CHILD(void, integer, many); -GNDSTK_MAKE_CHILD(void, Legendre, many); -GNDSTK_MAKE_CHILD(void, metaStable, many); -GNDSTK_MAKE_CHILD(void, multiplicitySum, many); -GNDSTK_MAKE_CHILD(void, parameterCovariance, many); -GNDSTK_MAKE_CHILD(void, parameterCovarianceMatrix, many); -GNDSTK_MAKE_CHILD(void, parameterLink, many); -GNDSTK_MAKE_CHILD(void, regions1d, many); -GNDSTK_MAKE_CHILD(void, section, many); -GNDSTK_MAKE_CHILD(void, shell, many); -GNDSTK_MAKE_CHILD(void, shortRangeSelfScalingVariance, many); -GNDSTK_MAKE_CHILD(void, values, many); -GNDSTK_MAKE_CHILD(void, weighted, many); GNDSTK_MAKE_CHILD(void, XYs1d, many); -GNDSTK_MAKE_CHILD(void, XYs2d, many); -GNDSTK_MAKE_CHILD(void, XYs3d, many); - +// ------------------------ +// cdata +// ------------------------ -// ----------------------------------------------------------------------------- -// Some special cases -// ----------------------------------------------------------------------------- - -// Double -// Not called double, for obvious reasons. -inline const Child Double("double"); - -// cdata, comment -// These are where XML or (comment) material -// resides. It's reasonable to extract such content into std::strings. We -// then store these as nodes of those respective names, each with one metadatum -// having a key of "#text" and a value containing the original content. -inline const Child +// This is where XML (comment) material resides. It's reasonable +// to extract such content into std::strings. We then store these in nodes of +// name #cdata, each with one metadatum having a key of "#text" and a value +// containing the original content. +inline const Child cdata("#cdata"); -inline const Child - comment("#comment"); - -// pcdata -// These are where data appearing in constructs like this: -// 1.2 3.4 5.6 7.8 9.0 -// reside. In that case, our internal tree structure would have a node named -// "values", which would have a child node named "#pcdata", which would have a -// metadatum with a key of "#text" and a value containing the original content: -// the "1.2 ..." in the above example. Our examination of many GNDS files shows -// that some pcdata nodes contain integers, while others contain doubles. We -// therefore define pcdata as a Child with , so that we can access it -// in its original form and thus dig further down to its "#text" metadatum, at -// which point we can decide elsewhere what's appropriate for that. (Read into -// a vector of ints? A vector of doubles? Something else?) -inline const Child - pcdata("#pcdata"); } // namespace child diff --git a/src/GNDStk/misc/src/meta.hpp b/src/GNDStk/misc/src/meta.hpp index 99004b9cc..dd4d28405 100644 --- a/src/GNDStk/misc/src/meta.hpp +++ b/src/GNDStk/misc/src/meta.hpp @@ -1,142 +1,30 @@ namespace meta { -// ----------------------------------------------------------------------------- -// Meta Objects -// ----------------------------------------------------------------------------- - -// bool -GNDSTK_MAKE_META(bool, calculateChannelRadius); -GNDSTK_MAKE_META(bool, calculatedAtThermal); -GNDSTK_MAKE_META(bool, calculatePenetrability); -GNDSTK_MAKE_META(bool, identicalParticles); -GNDSTK_MAKE_META(bool, supportsAngularReconstruction); -GNDSTK_MAKE_META(bool, useForSelfShieldingOnly); -GNDSTK_MAKE_META(bool, complete); +// ------------------------ +// Misc. Meta Objects +// ------------------------ // int GNDSTK_MAKE_META(int, A); -GNDSTK_MAKE_META(int, columnIndex); -GNDSTK_MAKE_META(int, columns); GNDSTK_MAKE_META(int, ENDF_MT); -GNDSTK_MAKE_META(int, index); -GNDSTK_MAKE_META(int, L); -GNDSTK_MAKE_META(int, lowerIndex); -GNDSTK_MAKE_META(int, MAT); -GNDSTK_MAKE_META(int, matrixStartIndex); -GNDSTK_MAKE_META(int, metaStableIndex); -GNDSTK_MAKE_META(int, nParameters); -GNDSTK_MAKE_META(int, numberOfProducts); -GNDSTK_MAKE_META(int, numberPerMolecule); -GNDSTK_MAKE_META(int, parity); -GNDSTK_MAKE_META(int, rows); -GNDSTK_MAKE_META(int, Z); // double -GNDSTK_MAKE_META(double, coefficient); -GNDSTK_MAKE_META(double, domainMax); -GNDSTK_MAKE_META(double, domainMin); -GNDSTK_MAKE_META(double, electronNumber); GNDSTK_MAKE_META(double, format); -GNDSTK_MAKE_META(double, max); -GNDSTK_MAKE_META(double, min); -GNDSTK_MAKE_META(double, muCutoff); // string -GNDSTK_MAKE_META(std::string, approximation); -GNDSTK_MAKE_META(std::string, asymmetric); -GNDSTK_MAKE_META(std::string, boundaryCondition); -GNDSTK_MAKE_META(std::string, compression); -GNDSTK_MAKE_META(std::string, crossTerm); -GNDSTK_MAKE_META(std::string, dependenceOnProcessedGroupWidth); -GNDSTK_MAKE_META(std::string, derivedFrom); -GNDSTK_MAKE_META(std::string, domainUnit); -GNDSTK_MAKE_META(std::string, ejectile); -GNDSTK_MAKE_META(std::string, eliminated); -GNDSTK_MAKE_META(std::string, emissionMode); GNDSTK_MAKE_META(std::string, encoding); -GNDSTK_MAKE_META(std::string, ENDF_MFMT); GNDSTK_MAKE_META(std::string, evaluation); -GNDSTK_MAKE_META(std::string, final); // is a C++ *contextual* keyword; so OK -GNDSTK_MAKE_META(std::string, fissionGenre); -GNDSTK_MAKE_META(std::string, flags); -GNDSTK_MAKE_META(std::string, functionalForm); -GNDSTK_MAKE_META(std::string, generation); -GNDSTK_MAKE_META(std::string, genre); -GNDSTK_MAKE_META(std::string, href); GNDSTK_MAKE_META(std::string, id); -GNDSTK_MAKE_META(std::string, initial); -GNDSTK_MAKE_META(std::string, interpolation); -GNDSTK_MAKE_META(std::string, interpolationQualifier); GNDSTK_MAKE_META(std::string, label); -GNDSTK_MAKE_META(std::string, library); -GNDSTK_MAKE_META(std::string, material); -GNDSTK_MAKE_META(std::string, mode); -GNDSTK_MAKE_META(std::string, name); -GNDSTK_MAKE_META(std::string, path); -GNDSTK_MAKE_META(std::string, pid); -GNDSTK_MAKE_META(std::string, process); -GNDSTK_MAKE_META(std::string, productFrame); GNDSTK_MAKE_META(std::string, projectile); GNDSTK_MAKE_META(std::string, projectileFrame); -GNDSTK_MAKE_META(std::string, resonanceReaction); -GNDSTK_MAKE_META(std::string, shape); -GNDSTK_MAKE_META(std::string, style); -GNDSTK_MAKE_META(std::string, subshell); GNDSTK_MAKE_META(std::string, symbol); -GNDSTK_MAKE_META(std::string, symmetry); GNDSTK_MAKE_META(std::string, target); -GNDSTK_MAKE_META(std::string, type); GNDSTK_MAKE_META(std::string, unit); GNDSTK_MAKE_META(std::string, version); -GNDSTK_MAKE_META(std::string, valueType); -GNDSTK_MAKE_META(std::string, date); -GNDSTK_MAKE_META(std::string, decayRate); // always has double and "1/s"? - - - -// ----------------------------------------------------------------------------- -// Meta Objects -// Special cases -// ----------------------------------------------------------------------------- - -// ------------------------ -// Variant cases; comma in -// variant<,> prevents use -// of the macro -// ------------------------ - -// constant -inline const Meta> -constant("constant"); - -// degreesOfFreedom -// I'd have expected an int for this, always, but some of the GNDS files have -// a non-integral double. Perhaps we could arrange to always read as a double. -inline const Meta> -degreesOfFreedom("degreesOfFreedom"); - -// value -inline const Meta> -value("value"); - -// [ids]value -// Shorthands for specific cases. -// Prefixes {i,d,s} mean {int,double,string}. -inline const Meta ivalue("value"); -inline const Meta dvalue("value"); -inline const Meta svalue("value"); - -// channelSpin -// This actually looks to me like it's always either an int, or some kind -// of fraction, so figure out something clever in place of variant. Perhaps -// a rational-number class? -inline const Meta> -channelSpin("channelSpin"); -// spin -// Same remark as for channelSpin. -inline const Meta> -spin("spin"); +// value, as double +inline const Meta dvalue("value"); } // namespace meta From 78ffbbf872de7a01005c26828f6535ad32387e37 Mon Sep 17 00:00:00 2001 From: Martin Staley Date: Tue, 18 Jan 2022 17:37:49 -0700 Subject: [PATCH 31/39] Block data "truncate" feature. I implemented a useful feature that was requested by a user. When using Component's prettyprinter, previously block data were *all* printed. For example, if a block of data had 1000 elements, then all 1000 elements were printed by the prettyprinter. Now, we provide a user-settable variable, `GNDStk::truncate`. A negative value for this variable means: print all block-data elements, just like we did before. The default is `-1`, so printing all elements is the default. If `GNDStk::truncate` is `0` or positive, it means: print at most that number of elements. Whenever fewer elements are printed than exist, a comment to that effect is emitted. The comments mentions how many values actually exist, as that information may be important to someone to know. I also updated BlockData's `write.test.cpp` so that it tests the new feature, and I made some miscellaneous cosmetic changes to that file as well. Finally (and this is related to Component's prettyprinting, so this PR seemed like a good place to do it), I removed the `GNDStk::across` alias to `GNDStk::columns`. I'd had it, previously, because there was a `columns` in another namespace, and I wanted to provide something that worked even in the face of multiple `using` directives. The other `columns` disappeared, however, in an earlier PR in which we got rid of most `Meta` and `Child` objects. --- src/GNDStk/BlockData/src/detail.hpp | 26 ++ src/GNDStk/BlockData/src/write.hpp | 63 +++-- src/GNDStk/BlockData/test/write.test.cpp | 338 ++++++++++++++++++----- src/GNDStk/Component/src/detail.hpp | 26 -- src/GNDStk/utility.hpp | 16 +- 5 files changed, 339 insertions(+), 130 deletions(-) diff --git a/src/GNDStk/BlockData/src/detail.hpp b/src/GNDStk/BlockData/src/detail.hpp index a5adfafe7..c4169e3dd 100644 --- a/src/GNDStk/BlockData/src/detail.hpp +++ b/src/GNDStk/BlockData/src/detail.hpp @@ -196,4 +196,30 @@ auto getBounds(const std::vector &vec) return bnd; } + + +// ----------------------------------------------------------------------------- +// colorize_*(text) +// ----------------------------------------------------------------------------- + +#define gndstkPaste(one,two) one ## two +#define gndstkColorFun(part) \ + inline std::string gndstkPaste(colorize_,part)(const std::string &text) \ + { \ + return GNDStk::color && colors::part != "" \ + ? colors::part + text + colors::reset \ + : text; \ + } + + // colorize_label() etc. + gndstkColorFun(label) + gndstkColorFun(colon) + gndstkColorFun(component) + gndstkColorFun(brace) + gndstkColorFun(bracket) + gndstkColorFun(comment) + +#undef gndstkColorFun +#undef gndstkPaste + } // namespace detail diff --git a/src/GNDStk/BlockData/src/write.hpp b/src/GNDStk/BlockData/src/write.hpp index 98dbb4a64..40266703b 100644 --- a/src/GNDStk/BlockData/src/write.hpp +++ b/src/GNDStk/BlockData/src/write.hpp @@ -1,7 +1,7 @@ // ----------------------------------------------------------------------------- // write -// To an ostream (not to a Node; that a different thing) +// To an ostream, generally as part of Component's prettyprinting. // ----------------------------------------------------------------------------- std::ostream &write(std::ostream &os, const int level) const @@ -11,17 +11,19 @@ std::ostream &write(std::ostream &os, const int level) const (active() == Active::vector && size() == 0)) return os; + // Coloring? + const bool coloring = GNDStk::color && GNDStk::colors::value != ""; + // ------------------------ // If string is active // ------------------------ if (active() == Active::string) { - // write the string exactly as-is, without our column formatting + // Write the string exactly as-is, without our column formatting // or any indentation; then also write a newline - GNDStk::color && GNDStk::colors::value != "" - ? os << colors::value << rawstring << colors::reset - : os << rawstring; - return os << std::endl; + return coloring + ? os << colors::value << rawstring << colors::reset << std::endl + : os << rawstring << std::endl; } // ------------------------ @@ -29,38 +31,45 @@ std::ostream &write(std::ostream &os, const int level) const // ------------------------ // Indentation (string, with some number of spaces) - const auto indent = std::string(GNDStk::indent*level,' '); + const std::string indent(GNDStk::indent*level,' '); const auto writeLambda = - [&os,&indent](auto &&alt) + [&os,&indent,coloring](auto &&alt) { - std::size_t count = 0; using T = std::decay_t; + const std::size_t size = alt.size(); + const std::size_t end = (GNDStk::truncate < 0) + ? size + : std::min(size,std::size_t(GNDStk::truncate)); - // use our column formatting - for (auto &element : alt) { - count == 0 - ? os << indent - : GNDStk::across == 0 || count % GNDStk::across != 0 - ? os << ' ' - : os << '\n' << indent; + // Print, using our column formatting + for (std::size_t i = 0; i < end; ++i) { + const T &element = alt[i]; - if (GNDStk::color && GNDStk::colors::value != "") - os << colors::value; + // value's whitespace prefix + i == 0 + ? os << indent // at the very beginning, or... + : GNDStk::columns == 0 || i % GNDStk::columns != 0 + ? os << ' ' // still on the current line, or... + : os << '\n' << indent; // starting the next line + // value + using namespace detail; + if (coloring) os << colors::value; if constexpr (std::is_floating_point_v) - os << detail::Precision< - detail::PrecisionContext::data, - T - >{}.write(element); + os << Precision{}.write(element); else os << element; - - if (GNDStk::color && GNDStk::colors::value != "") - os << colors::reset; - - count++; + if (coloring) os << colors::reset; }; + + // If applicable, print a message saying the data were truncated + if (end < size) { + if (end > 0) + os << '\n'; + os << indent << detail::colorize_comment( + "// truncated; total #values == " + std::to_string(size)); + } }; if constexpr (runtime) diff --git a/src/GNDStk/BlockData/test/write.test.cpp b/src/GNDStk/BlockData/test/write.test.cpp index 14f773a39..0ebf10d1d 100644 --- a/src/GNDStk/BlockData/test/write.test.cpp +++ b/src/GNDStk/BlockData/test/write.test.cpp @@ -6,221 +6,421 @@ using namespace njoy::GNDStk::core; // ----------------------------------------------------------------------------- -// Scenario: raw string +// Scenario: raw string is active // ----------------------------------------------------------------------------- -// Helper +// Helper: scenario_write_string_active template void scenario_write_string_active() { + // string is active, but empty GIVEN("A BlockData with an empty raw string") { WHEN("BlockData.write() is called") { THEN("Nothing is printed") { BlockData b; - b = std::vector{{'a','b','c'}}; - b.string(""); // should make string (not vector) active + b.string(""); + + // with no indentation std::ostringstream oss; b.write(oss,0); CHECK(oss.str() == ""); - // same (nothing printed) if indentation is non-0 + // the same (nothing is printed) even if indentation is nonzero + oss.str(""); b.write(oss,2); CHECK(oss.str() == ""); } } } + // string is active, and contains values GIVEN("A BlockData with a non-empty raw string") { WHEN("BlockData.write() is called") { THEN("The raw string and a newline are printed") { BlockData b; - b = std::vector{{'a','b','c'}}; - b.string("foo bar"); // should make string (not vector) active + b.string("foo bar baz"); + // with no indentation std::ostringstream oss; b.write(oss,0); - CHECK(oss.str() == "foo bar\n"); + CHECK(oss.str() == "foo bar baz\n"); - // indentation isn't applied when the raw string is active + // the same, even if indentation is nonzero; indentation isn't + // applied when the raw string (as opposed to the ) is active oss.str(""); b.write(oss,2); - CHECK(oss.str() == "foo bar\n"); + CHECK(oss.str() == "foo bar baz\n"); } } } } // For DATATYPE == void -SCENARIO("BlockData write(), when the raw string is active") { +SCENARIO("BlockData write(), when the raw string is active") +{ scenario_write_string_active(); } -// For DATATYPE != void -SCENARIO("BlockData write(), when the raw string is active") { - scenario_write_string_active(); +// For DATATYPE == double +SCENARIO("BlockData write(), when the raw string is active") +{ + scenario_write_string_active(); } // ----------------------------------------------------------------------------- -// Scenario: vector +// Scenario: vector is active // ----------------------------------------------------------------------------- -// Helper -template -void scenario_write_vector_active() +SCENARIO("BlockData write(), when a vector is active") { + // vector is active, but empty GIVEN("A BlockData with an empty vector") { WHEN("BlockData.write() is called") { THEN("Nothing is printed") { BlockData b; - b.string("should be ignored"); // because vector is forthcoming... b = std::vector{}; + + // with no indentation std::ostringstream oss; b.write(oss,0); CHECK(oss.str() == ""); - // same (nothing printed) if indentation is non-0 + // the same (nothing is printed) even if indentation is nonzero + oss.str(""); b.write(oss,2); CHECK(oss.str() == ""); } } } + // vector is active, and contains values GIVEN("A BlockData with a non-empty vector") { WHEN("BlockData.write() is called") { THEN("The vector and a newline are printed") { BlockData b; - b.string("should be ignored"); // because vector is forthcoming... - b = std::vector{{2,3,5,7,11,13,17,19,21,23}}; + b = std::vector{{2, 3, 5, 7, 11, 13, 17, 19, 21, 23}}; std::ostringstream oss; // Cases: - // indent: 0, 3 (number of spaces per indentation level) - // across: 0, 1, 2, 5, 10, 11 (note that 10 == vector size) - // level: 0, 1, 2 (indentation level) - // Note: across == 0 ==> unlimited. + // indent: 0, 3 (number of spaces per indentation level) + // columns: 0, 1, 2, 5, 10, 11 (note that 10 == vector size) + // level: 0, 1, 2 (indentation level) + // Note: columns == 0 ==> unlimited. // Lots of cases, but we want to check that our pretty-printing // functionality works perfectly, and doesn't do anything that's - // unexpected around "boundaries" like across==10 with 10 values. + // unexpected around "boundaries" like columns==10 with 10 values. - oss.str(""); indent = 0; across = 0; b.write(oss,0); + oss.str(""); indent = 0; columns = 0; b.write(oss,0); CHECK(oss.str() == "2 3 5 7 11 13 17 19 21 23\n"); - oss.str(""); indent = 0; across = 0; b.write(oss,1); + oss.str(""); indent = 0; columns = 0; b.write(oss,1); CHECK(oss.str() == "2 3 5 7 11 13 17 19 21 23\n"); - oss.str(""); indent = 0; across = 0; b.write(oss,2); + oss.str(""); indent = 0; columns = 0; b.write(oss,2); CHECK(oss.str() == "2 3 5 7 11 13 17 19 21 23\n"); - oss.str(""); indent = 0; across = 1; b.write(oss,0); + oss.str(""); indent = 0; columns = 1; b.write(oss,0); CHECK(oss.str() == "2\n3\n5\n7\n11\n13\n17\n19\n21\n23\n"); - oss.str(""); indent = 0; across = 1; b.write(oss,1); + oss.str(""); indent = 0; columns = 1; b.write(oss,1); CHECK(oss.str() == "2\n3\n5\n7\n11\n13\n17\n19\n21\n23\n"); - oss.str(""); indent = 0; across = 1; b.write(oss,2); + oss.str(""); indent = 0; columns = 1; b.write(oss,2); CHECK(oss.str() == "2\n3\n5\n7\n11\n13\n17\n19\n21\n23\n"); - oss.str(""); indent = 0; across = 2; b.write(oss,0); + oss.str(""); indent = 0; columns = 2; b.write(oss,0); CHECK(oss.str() == "2 3\n5 7\n11 13\n17 19\n21 23\n"); - oss.str(""); indent = 0; across = 2; b.write(oss,1); + oss.str(""); indent = 0; columns = 2; b.write(oss,1); CHECK(oss.str() == "2 3\n5 7\n11 13\n17 19\n21 23\n"); - oss.str(""); indent = 0; across = 2; b.write(oss,2); + oss.str(""); indent = 0; columns = 2; b.write(oss,2); CHECK(oss.str() == "2 3\n5 7\n11 13\n17 19\n21 23\n"); - oss.str(""); indent = 0; across = 5; b.write(oss,0); + oss.str(""); indent = 0; columns = 5; b.write(oss,0); CHECK(oss.str() == "2 3 5 7 11\n13 17 19 21 23\n"); - oss.str(""); indent = 0; across = 5; b.write(oss,1); + oss.str(""); indent = 0; columns = 5; b.write(oss,1); CHECK(oss.str() == "2 3 5 7 11\n13 17 19 21 23\n"); - oss.str(""); indent = 0; across = 5; b.write(oss,2); + oss.str(""); indent = 0; columns = 5; b.write(oss,2); CHECK(oss.str() == "2 3 5 7 11\n13 17 19 21 23\n"); - oss.str(""); indent = 0; across = 10; b.write(oss,0); + oss.str(""); indent = 0; columns = 10; b.write(oss,0); CHECK(oss.str() == "2 3 5 7 11 13 17 19 21 23\n"); - oss.str(""); indent = 0; across = 10; b.write(oss,1); + oss.str(""); indent = 0; columns = 10; b.write(oss,1); CHECK(oss.str() == "2 3 5 7 11 13 17 19 21 23\n"); - oss.str(""); indent = 0; across = 10; b.write(oss,2); + oss.str(""); indent = 0; columns = 10; b.write(oss,2); CHECK(oss.str() == "2 3 5 7 11 13 17 19 21 23\n"); - oss.str(""); indent = 0; across = 11; b.write(oss,0); + oss.str(""); indent = 0; columns = 11; b.write(oss,0); CHECK(oss.str() == "2 3 5 7 11 13 17 19 21 23\n"); - oss.str(""); indent = 0; across = 11; b.write(oss,1); + oss.str(""); indent = 0; columns = 11; b.write(oss,1); CHECK(oss.str() == "2 3 5 7 11 13 17 19 21 23\n"); - oss.str(""); indent = 0; across = 11; b.write(oss,2); + oss.str(""); indent = 0; columns = 11; b.write(oss,2); CHECK(oss.str() == "2 3 5 7 11 13 17 19 21 23\n"); - oss.str(""); indent = 3; across = 0; b.write(oss,0); + oss.str(""); indent = 3; columns = 0; b.write(oss,0); CHECK(oss.str() == "2 3 5 7 11 13 17 19 21 23\n"); - oss.str(""); indent = 3; across = 0; b.write(oss,1); + oss.str(""); indent = 3; columns = 0; b.write(oss,1); CHECK(oss.str() == " 2 3 5 7 11 13 17 19 21 23\n"); - oss.str(""); indent = 3; across = 0; b.write(oss,2); + oss.str(""); indent = 3; columns = 0; b.write(oss,2); CHECK(oss.str() == " 2 3 5 7 11 13 17 19 21 23\n"); - oss.str(""); indent = 3; across = 1; b.write(oss,0); + oss.str(""); indent = 3; columns = 1; b.write(oss,0); CHECK(oss.str() == "2\n3\n5\n7\n11\n13\n17\n19\n21\n23\n"); - oss.str(""); indent = 3; across = 1; b.write(oss,1); + oss.str(""); indent = 3; columns = 1; b.write(oss,1); CHECK(oss.str() == " 2\n 3\n 5\n 7\n 11\n 13\n 17\n 19\n 21\n 23\n"); - oss.str(""); indent = 3; across = 1; b.write(oss,2); + oss.str(""); indent = 3; columns = 1; b.write(oss,2); CHECK(oss.str() == " 2\n 3\n 5\n 7\n 11\n 13\n 17\n 19\n 21\n 23\n"); - oss.str(""); indent = 3; across = 2; b.write(oss,0); + oss.str(""); indent = 3; columns = 2; b.write(oss,0); CHECK(oss.str() == "2 3\n5 7\n11 13\n17 19\n21 23\n"); - oss.str(""); indent = 3; across = 2; b.write(oss,1); + oss.str(""); indent = 3; columns = 2; b.write(oss,1); CHECK(oss.str() == " 2 3\n 5 7\n 11 13\n 17 19\n 21 23\n"); - oss.str(""); indent = 3; across = 2; b.write(oss,2); + oss.str(""); indent = 3; columns = 2; b.write(oss,2); CHECK(oss.str() == " 2 3\n 5 7\n 11 13\n 17 19\n 21 23\n"); - oss.str(""); indent = 3; across = 5; b.write(oss,0); + oss.str(""); indent = 3; columns = 5; b.write(oss,0); CHECK(oss.str() == "2 3 5 7 11\n13 17 19 21 23\n"); - oss.str(""); indent = 3; across = 5; b.write(oss,1); + oss.str(""); indent = 3; columns = 5; b.write(oss,1); CHECK(oss.str() == " 2 3 5 7 11\n 13 17 19 21 23\n"); - oss.str(""); indent = 3; across = 5; b.write(oss,2); + oss.str(""); indent = 3; columns = 5; b.write(oss,2); CHECK(oss.str() == " 2 3 5 7 11\n 13 17 19 21 23\n"); - oss.str(""); indent = 3; across = 10; b.write(oss,0); + oss.str(""); indent = 3; columns = 10; b.write(oss,0); CHECK(oss.str() == "2 3 5 7 11 13 17 19 21 23\n"); - oss.str(""); indent = 3; across = 10; b.write(oss,1); + oss.str(""); indent = 3; columns = 10; b.write(oss,1); CHECK(oss.str() == " 2 3 5 7 11 13 17 19 21 23\n"); - oss.str(""); indent = 3; across = 10; b.write(oss,2); + oss.str(""); indent = 3; columns = 10; b.write(oss,2); CHECK(oss.str() == " 2 3 5 7 11 13 17 19 21 23\n"); - oss.str(""); indent = 3; across = 11; b.write(oss,0); + oss.str(""); indent = 3; columns = 11; b.write(oss,0); CHECK(oss.str() == "2 3 5 7 11 13 17 19 21 23\n"); - oss.str(""); indent = 3; across = 11; b.write(oss,1); + oss.str(""); indent = 3; columns = 11; b.write(oss,1); CHECK(oss.str() == " 2 3 5 7 11 13 17 19 21 23\n"); - oss.str(""); indent = 3; across = 11; b.write(oss,2); + oss.str(""); indent = 3; columns = 11; b.write(oss,2); CHECK(oss.str() == " 2 3 5 7 11 13 17 19 21 23\n"); } } } } -// For DATATYPE == void -SCENARIO("BlockData write(), when a vector is active") { - scenario_write_vector_active(); + + +// ----------------------------------------------------------------------------- +// Scenario: vector is active; test GNDStk::truncate +// ----------------------------------------------------------------------------- + +// Helper: test_truncate +template +void test_truncate( + const BlockData &b, + const int indent, + const std::size_t columns, + const int level, + const long truncate, + const std::string &want +) { + njoy::GNDStk::indent = indent; + njoy::GNDStk::columns = columns; + njoy::GNDStk::truncate = truncate; + + std::ostringstream oss; + b.write(oss,level); + + std::cout << "test_truncate:" << std::endl; + std::cout << oss.str() << std::endl; + + CHECK(oss.str() == want); } -// For DATATYPE != void -SCENARIO("BlockData write(), when a vector is active") { - scenario_write_vector_active(); +SCENARIO("BlockData write(), vector, trying GNDStk::truncate") +{ + // vector is active, but empty + GIVEN("A BlockData with an empty vector") { + WHEN("BlockData.write() is called") { + THEN("Nothing is printed") { + BlockData b; + b = std::vector{}; + + using njoy::GNDStk::truncate; + for (truncate = -10; truncate <= 10; ++truncate) { + // with no indentation + std::ostringstream oss; + b.write(oss,0); + CHECK(oss.str() == ""); + + // the same (nothing is printed) even if indentation is nonzero + oss.str(""); + b.write(oss,2); + CHECK(oss.str() == ""); + } + } + } + } + + // vector is active, and contains values + GIVEN("A BlockData with a non-empty vector") { + WHEN("BlockData.write() is called") { + THEN("The vector and a newline are printed") { + BlockData b; + b = std::vector{{2.3, 5.7, 11.13, 17.19, 21.23}}; + + // Cases: + // indent: 3 (number of spaces per indentation level) + // columns: 0, 2, 3 (0 means unlimited) + // level: 0, 1, 2 (indentation level) + // truncate: -1, 0, 1, 2, 3 (-1 means none; print all values) + // Lots of cases; we want pretty-printing to be perfect. + + test_truncate(b, 3, 0, 0, -1, + "2.3 5.7 11.13 17.19 21.23\n"); + test_truncate(b, 3, 0, 0, +0, + "// truncated; total #values == 5\n"); + test_truncate(b, 3, 0, 0, +1, + "2.3\n" + "// truncated; total #values == 5\n"); + test_truncate(b, 3, 0, 0, +2, + "2.3 5.7\n" + "// truncated; total #values == 5\n"); + test_truncate(b, 3, 0, 0, +3, + "2.3 5.7 11.13\n" + "// truncated; total #values == 5\n"); + test_truncate(b, 3, 0, 1, -1, + " 2.3 5.7 11.13 17.19 21.23\n"); + test_truncate(b, 3, 0, 1, +0, + " // truncated; total #values == 5\n"); + test_truncate(b, 3, 0, 1, +1, + " 2.3\n" + " // truncated; total #values == 5\n"); + test_truncate(b, 3, 0, 1, +2, + " 2.3 5.7\n" + " // truncated; total #values == 5\n"); + test_truncate(b, 3, 0, 1, +3, + " 2.3 5.7 11.13\n" + " // truncated; total #values == 5\n"); + test_truncate(b, 3, 0, 2, -1, + " 2.3 5.7 11.13 17.19 21.23\n"); + test_truncate(b, 3, 0, 2, +0, + " // truncated; total #values == 5\n"); + test_truncate(b, 3, 0, 2, +1, + " 2.3\n" + " // truncated; total #values == 5\n"); + test_truncate(b, 3, 0, 2, +2, + " 2.3 5.7\n" + " // truncated; total #values == 5\n"); + test_truncate(b, 3, 0, 2, +3, + " 2.3 5.7 11.13\n" + " // truncated; total #values == 5\n"); + test_truncate(b, 3, 2, 0, -1, + "2.3 5.7\n" + "11.13 17.19\n" + "21.23\n"); + test_truncate(b, 3, 2, 0, +0, + "// truncated; total #values == 5\n"); + test_truncate(b, 3, 2, 0, +1, + "2.3\n" + "// truncated; total #values == 5\n"); + test_truncate(b, 3, 2, 0, +2, + "2.3 5.7\n" + "// truncated; total #values == 5\n"); + test_truncate(b, 3, 2, 0, +3, + "2.3 5.7\n" + "11.13\n" + "// truncated; total #values == 5\n"); + test_truncate(b, 3, 2, 1, -1, + " 2.3 5.7\n" + " 11.13 17.19\n" + " 21.23\n"); + test_truncate(b, 3, 2, 1, +0, + " // truncated; total #values == 5\n"); + test_truncate(b, 3, 2, 1, +1, + " 2.3\n" + " // truncated; total #values == 5\n"); + test_truncate(b, 3, 2, 1, +2, + " 2.3 5.7\n" + " // truncated; total #values == 5\n"); + test_truncate(b, 3, 2, 1, +3, + " 2.3 5.7\n" + " 11.13\n" + " // truncated; total #values == 5\n"); + test_truncate(b, 3, 2, 2, -1, + " 2.3 5.7\n" + " 11.13 17.19\n" + " 21.23\n"); + test_truncate(b, 3, 2, 2, +0, + " // truncated; total #values == 5\n"); + test_truncate(b, 3, 2, 2, +1, + " 2.3\n" + " // truncated; total #values == 5\n"); + test_truncate(b, 3, 2, 2, +2, + " 2.3 5.7\n" + " // truncated; total #values == 5\n"); + test_truncate(b, 3, 2, 2, +3, + " 2.3 5.7\n" + " 11.13\n" + " // truncated; total #values == 5\n"); + test_truncate(b, 3, 3, 0, -1, + "2.3 5.7 11.13\n" + "17.19 21.23\n"); + test_truncate(b, 3, 3, 0, +0, + "// truncated; total #values == 5\n"); + test_truncate(b, 3, 3, 0, +1, + "2.3\n" + "// truncated; total #values == 5\n"); + test_truncate(b, 3, 3, 0, +2, + "2.3 5.7\n" + "// truncated; total #values == 5\n"); + test_truncate(b, 3, 3, 0, +3, + "2.3 5.7 11.13\n" + "// truncated; total #values == 5\n"); + test_truncate(b, 3, 3, 1, -1, + " 2.3 5.7 11.13\n" + " 17.19 21.23\n"); + test_truncate(b, 3, 3, 1, +0, + " // truncated; total #values == 5\n"); + test_truncate(b, 3, 3, 1, +1, + " 2.3\n" + " // truncated; total #values == 5\n"); + test_truncate(b, 3, 3, 1, +2, + " 2.3 5.7\n" + " // truncated; total #values == 5\n"); + test_truncate(b, 3, 3, 1, +3, + " 2.3 5.7 11.13\n" + " // truncated; total #values == 5\n"); + test_truncate(b, 3, 3, 2, -1, + " 2.3 5.7 11.13\n" + " 17.19 21.23\n"); + test_truncate(b, 3, 3, 2, +0, + " // truncated; total #values == 5\n"); + test_truncate(b, 3, 3, 2, +1, + " 2.3\n" + " // truncated; total #values == 5\n"); + test_truncate(b, 3, 3, 2, +2, + " 2.3 5.7\n" + " // truncated; total #values == 5\n"); + test_truncate(b, 3, 3, 2, +3, + " 2.3 5.7 11.13\n" + " // truncated; total #values == 5\n"); + } + } + } } diff --git a/src/GNDStk/Component/src/detail.hpp b/src/GNDStk/Component/src/detail.hpp index 9350dbee5..4c20ef7a1 100644 --- a/src/GNDStk/Component/src/detail.hpp +++ b/src/GNDStk/Component/src/detail.hpp @@ -5,32 +5,6 @@ class Component; namespace detail { -// ----------------------------------------------------------------------------- -// colorize_*(text) -// ----------------------------------------------------------------------------- - -#define gndstkPaste(one,two) one ## two -#define gndstkColorFun(part) \ - inline std::string gndstkPaste(colorize_,part)(const std::string &text) \ - { \ - return GNDStk::color && colors::part != "" \ - ? colors::part + text + colors::reset \ - : text; \ - } - - // colorize_label() etc. - gndstkColorFun(label) - gndstkColorFun(colon) - gndstkColorFun(component) - gndstkColorFun(brace) - gndstkColorFun(bracket) - gndstkColorFun(comment) - -#undef gndstkColorFun -#undef gndstkPaste - - - // ----------------------------------------------------------------------------- // Functions: miscellaneous // ----------------------------------------------------------------------------- diff --git a/src/GNDStk/utility.hpp b/src/GNDStk/utility.hpp index bb35d2f4d..513b0100d 100644 --- a/src/GNDStk/utility.hpp +++ b/src/GNDStk/utility.hpp @@ -166,15 +166,15 @@ inline std::string diagnostic( inline bool comments = true; // For printing. -// When writing a Component with its generic write() function (or its stream -// output, which uses write()), AND the Component is based on a BlockData with -// hasBlockData == true, values will be printed with GNDStk::columns across. -// "columns" is aliased to "across" for convenience, because, at the time of -// this writing, GNDStk has a Meta<> object, named "columns", which would also -// be in scope if the core namespace is used. So, a user might prefer to use -// the name "across". +// When writing a Component with its generic write() function (or with its +// stream output, which uses its generic write()), and if the Component is +// based on a BlockData with hasBlockData == true, then data will be printed +// using GNDStk::columns columns. If the data array's size is large, a user +// may want to limit the total number of printed values. This can be done +// with the truncate value. A value < 0 means unlimited; all other values, +// including 0, mean print no more than that number of values. inline std::size_t columns = 4; -inline std::size_t &across = columns; +inline long truncate = -1; From 88de64b2e32ae72957e21e06bf7d9237183c9193 Mon Sep 17 00:00:00 2001 From: Martin Staley Date: Wed, 19 Jan 2022 17:33:25 -0700 Subject: [PATCH 32/39] Simple commit: limit lines to 80 characters in many places. We're generally trying to limit source-code lines to 80 characters or less in length. This isn't an absolute requirement, but, in keeping with the idea, I reformatted longer lines here and there in the hpp and cpp files throughout the code base, where doing so made sense. Sometimes, such codes have string literals (as with `R"..."`) with lines of more than 80 characters. Those I left as-is; the lines in question are supposed to be precisely the way they are. Also, for now, I didn't reformat long lines in other types of files. That includes, for example, various `CMakeLists.txt` files throughout GNDStk. Building very slightly on an earlier PR, I also made a small change to the `GNDStk::columns` variable, so that it would be more consistent, in terms of usage, with the related `GNDStk::truncate` variable. This has nothing to do with 80+ character lines, but was a simple change, so I decided to include it here. As usual, I modified a few comments and made small cosmetic changes in a few places. --- autogen/json2class.cpp | 3 +- src/GNDStk/BlockData/src/get.hpp | 3 +- src/GNDStk/BlockData/src/write.hpp | 5 +- src/GNDStk/BlockData/test/get.test.cpp | 14 ++- src/GNDStk/BlockData/test/toNode.test.cpp | 12 +- src/GNDStk/BlockData/test/types.test.cpp | 30 ++--- src/GNDStk/BlockData/test/write.test.cpp | 21 +++- src/GNDStk/Component/test/detail.test.cpp | 62 +++++----- src/GNDStk/Component/test/finish.test.cpp | 12 +- src/GNDStk/Component/test/getter.test.cpp | 108 ++++++++++++------ src/GNDStk/Component/test/prototype.hpp | 24 ++-- src/GNDStk/Tree/test/decl.test.cpp | 3 +- src/GNDStk/Tree/test/top.test.cpp | 3 +- src/GNDStk/common/src/detail.hpp | 3 +- .../enums/Encoding/test/Encoding.test.cpp | 3 +- src/GNDStk/enums/Frame/test/Frame.test.cpp | 9 +- .../enums/GridStyle/test/GridStyle.test.cpp | 15 ++- src/GNDStk/enums/Interaction.hpp | 18 ++- .../Interaction/test/Interaction.test.cpp | 21 ++-- .../Interpolation/test/Interpolation.test.cpp | 27 +++-- .../StorageOrder/test/StorageOrder.test.cpp | 9 +- src/GNDStk/precision/test/precision.test.hpp | 54 ++++++--- src/GNDStk/utility.hpp | 21 ++-- .../v1.9/containers/Axes/test/Axes.test.cpp | 7 +- .../v1.9/containers/Axis/src/custom.hpp | 42 ++++--- .../Regions1d/test/Regions1d.test.cpp | 18 +-- .../v1.9/containers/XYs1d/test/XYs1d.test.cpp | 9 +- 27 files changed, 355 insertions(+), 201 deletions(-) diff --git a/autogen/json2class.cpp b/autogen/json2class.cpp index b60b84b96..02f86641c 100644 --- a/autogen/json2class.cpp +++ b/autogen/json2class.cpp @@ -2348,7 +2348,8 @@ void filePythonClass(const InfoSpecs &specs, const PerClass &per) for ( const auto& dataTypeName : dataTypesNames ) { out(2,".def_property_readonly("); out(3,"\"@\",", dataTypeName.second); - out(3,"[] (const Component &self) { return self.@(); },", dataTypeName.second); + out(3,"[] (const Component &self) { return self.@(); },", + dataTypeName.second); out(3,"Component::documentation(\"@\").data()", dataTypeName.second); out(2,")"); } diff --git a/src/GNDStk/BlockData/src/get.hpp b/src/GNDStk/BlockData/src/get.hpp index 2b41893e8..e149376aa 100644 --- a/src/GNDStk/BlockData/src/get.hpp +++ b/src/GNDStk/BlockData/src/get.hpp @@ -326,7 +326,8 @@ std::enable_if_t< // These trigger a complete rebuild of the vector, if it isn't already of type // vector for the given T. This is intentional, in order to provide maximum // flexibility. However, be aware of it, for the sake of efficiency! In general, -// when using a BlockData object, we recommend sticking with one underlying type. +// when using a BlockData object, we recommend sticking with one underlying +// type, not dynamically changing from one type to another. // For DATATYPE != void (so that we have a vector): // T == DATATYPE is required, so that returning an element of the diff --git a/src/GNDStk/BlockData/src/write.hpp b/src/GNDStk/BlockData/src/write.hpp index 40266703b..a3bc88b5d 100644 --- a/src/GNDStk/BlockData/src/write.hpp +++ b/src/GNDStk/BlockData/src/write.hpp @@ -49,8 +49,9 @@ std::ostream &write(std::ostream &os, const int level) const // value's whitespace prefix i == 0 ? os << indent // at the very beginning, or... - : GNDStk::columns == 0 || i % GNDStk::columns != 0 - ? os << ' ' // still on the current line, or... + : GNDStk::columns <= 0 || + i % std::size_t(std::abs(GNDStk::columns)) != 0 + ? os << ' ' // still on the current line, or... : os << '\n' << indent; // starting the next line // value diff --git a/src/GNDStk/BlockData/test/get.test.cpp b/src/GNDStk/BlockData/test/get.test.cpp index ea9a430ff..d74bc331e 100644 --- a/src/GNDStk/BlockData/test/get.test.cpp +++ b/src/GNDStk/BlockData/test/get.test.cpp @@ -194,7 +194,7 @@ void scenario_get_template_n() // ------------------------ // 0 elements in string - { BlockData b; b.start(0).length(0).string(""); /* no elements */ } + { BlockData b; b.start(0).length(0).string(""); } { BlockData b; b.start(0).length(4).string(""); CHECK(b.template get(1) == 0); } { BlockData b; b.start(1).length(5).string(""); @@ -227,7 +227,7 @@ void scenario_get_template_n() // ------------------------ // 0 elements in string - { BlockData b; b.start(0).length(0).string(""); /* no elements */ } + { BlockData b; b.start(0).length(0).string(""); } { BlockData b; b.start(0).length(4).string(""); CHECK(b.template get(1) == 0); } { BlockData b; b.start(1).length(5).string(""); @@ -260,7 +260,7 @@ void scenario_get_template_n() // ------------------------ // 0 elements in string - { BlockData b; b.start(0).length(0).string(""); /* no elements */ } + { BlockData b; b.start(0).length(0).string(""); } { BlockData b; b.start(0).length(4).string(""); CHECK(b.template get(1) == ""); } { BlockData b; b.start(1).length(5).string(""); @@ -293,7 +293,7 @@ void scenario_get_template_n() // ------------------------ // 0 elements in string - { BlockData b; b.start(0).length(0).string(""); /* no elements */ } + { BlockData b; b.start(0).length(0).string(""); } { BlockData b; b.start(0).length(4).string(""); CHECK(b.template get(1) == 0); } { BlockData b; b.start(1).length(5).string(""); @@ -679,14 +679,16 @@ void scenario_get_named() } // For BlockData -SCENARIO("BlockData type-specific get functions: doubles() etc.") { +SCENARIO("BlockData type-specific get functions: " + "doubles() etc.") { GIVEN("A BlockData object") { scenario_get_named(); } } // For BlockData -SCENARIO("BlockData type-specific get functions: doubles() etc.") { +SCENARIO("BlockData type-specific get functions: " + "doubles() etc.") { GIVEN("A BlockData object") { scenario_get_named(); } diff --git a/src/GNDStk/BlockData/test/toNode.test.cpp b/src/GNDStk/BlockData/test/toNode.test.cpp index 92c13dc1f..b0ca7ed68 100644 --- a/src/GNDStk/BlockData/test/toNode.test.cpp +++ b/src/GNDStk/BlockData/test/toNode.test.cpp @@ -287,7 +287,8 @@ void scenario_toNode() struct { std::string valueType = ""; } content; - const std::string &valueType() const { return content.valueType; } + const std::string &valueType() const + { return content.valueType; } std::string &valueType() { return content.valueType; } } derived; BlockData b; std::string text; @@ -305,7 +306,8 @@ void scenario_toNode() } content; const int &start() const { return content.start; } int &start() { return content.start; } - const std::string &valueType() const { return content.valueType; } + const std::string &valueType() const + { return content.valueType; } std::string &valueType() { return content.valueType; } } derived; BlockData b; std::string text; @@ -324,7 +326,8 @@ void scenario_toNode() } content; const int &length() const { return content.length; } int &length() { return content.length; } - const std::string &valueType() const { return content.valueType; } + const std::string &valueType() const + { return content.valueType; } std::string &valueType() { return content.valueType; } } derived; BlockData b; std::string text; @@ -365,7 +368,8 @@ void scenario_toNode() int &length() { return content.length; } const int &start() const { return content.start; } int &start() { return content.start; } - const std::string &valueType() const { return content.valueType; } + const std::string &valueType() const + { return content.valueType; } std::string &valueType() { return content.valueType; } } derived; BlockData b; std::string text; diff --git a/src/GNDStk/BlockData/test/types.test.cpp b/src/GNDStk/BlockData/test/types.test.cpp index 64cf88dab..9bfdae5ea 100644 --- a/src/GNDStk/BlockData/test/types.test.cpp +++ b/src/GNDStk/BlockData/test/types.test.cpp @@ -26,91 +26,91 @@ SCENARIO("BlockData data types") { } vs scalars; - THEN("Transformation to vector, and access, work") { + THEN("Transforming to vector, and access, work") { vectors = std::vector(10,"a"); scalars = std::get>(vectors)[0]; CHECK(std::get(scalars) == "a"); } - THEN("Transformation to vector, and access, work") { + THEN("Transforming to vector, and access, work") { vectors = std::vector(10,'b'); scalars = std::get>(vectors)[0]; CHECK(std::get(scalars) == 'b'); } - THEN("Transformation to vector, and access, work") { + THEN("Transforming to vector, and access, work") { vectors = std::vector(10,-100); scalars = std::get>(vectors)[0]; CHECK(std::get(scalars) == -100); } - THEN("Transformation to vector, and access, work") { + THEN("Transforming to vector, and access, work") { vectors = std::vector(10,-200); scalars = std::get>(vectors)[0]; CHECK(std::get(scalars) == -200); } - THEN("Transformation to vector, and access, work") { + THEN("Transforming to vector, and access, work") { vectors = std::vector(10,-300); scalars = std::get>(vectors)[0]; CHECK(std::get(scalars) == -300); } - THEN("Transformation to vector, and access, work") { + THEN("Transforming to vector, and access, work") { vectors = std::vector(10,-400); scalars = std::get>(vectors)[0]; CHECK(std::get(scalars) == -400); } - THEN("Transformation to vector, and access, work") { + THEN("Transforming to vector, and access, work") { vectors = std::vector(10,-500); scalars = std::get>(vectors)[0]; CHECK(std::get(scalars) == -500); } - THEN("Transformation to vector, and access, work") { + THEN("Transforming to vector, and access, work") { vectors = std::vector(10,100); scalars = std::get>(vectors)[0]; CHECK(std::get(scalars) == 100); } - THEN("Transformation to vector, and access, work") { + THEN("Transforming to vector, and access, work") { vectors = std::vector(10,200); scalars = std::get>(vectors)[0]; CHECK(std::get(scalars) == 200); } - THEN("Transformation to vector, and access, work") { + THEN("Transforming to vector, and access, work") { vectors = std::vector(10,300); scalars = std::get>(vectors)[0]; CHECK(std::get(scalars) == 300); } - THEN("Transformation to vector, and access, work") { + THEN("Transforming to vector, and access, work") { vectors = std::vector(10,400); scalars = std::get>(vectors)[0]; CHECK(std::get(scalars) == 400); } - THEN("Transformation to vector, and access, work") { + THEN("Transforming to vector, and access, work") { vectors = std::vector(10,500); scalars = std::get>(vectors)[0]; CHECK(std::get(scalars) == 500); } - THEN("Transformation to vector, and access, work") { + THEN("Transforming to vector, and access, work") { vectors = std::vector(10,-1.2f); scalars = std::get>(vectors)[0]; CHECK(std::get(scalars) == -1.2f); } - THEN("Transformation to vector, and access, work") { + THEN("Transforming to vector, and access, work") { vectors = std::vector(10,3.4); scalars = std::get>(vectors)[0]; CHECK(std::get(scalars) == 3.4); } - THEN("Transformation to vector, and access, work") { + THEN("Transforming to vector, and access, work") { vectors = std::vector(10,-5.6); scalars = std::get>(vectors)[0]; CHECK(std::get(scalars) == -5.6); diff --git a/src/GNDStk/BlockData/test/write.test.cpp b/src/GNDStk/BlockData/test/write.test.cpp index 0ebf10d1d..80a2b3007 100644 --- a/src/GNDStk/BlockData/test/write.test.cpp +++ b/src/GNDStk/BlockData/test/write.test.cpp @@ -106,7 +106,7 @@ SCENARIO("BlockData write(), when a vector is active") // indent: 0, 3 (number of spaces per indentation level) // columns: 0, 1, 2, 5, 10, 11 (note that 10 == vector size) // level: 0, 1, 2 (indentation level) - // Note: columns == 0 ==> unlimited. + // Note: columns <= 0 means unlimited: so, all values on one line. // Lots of cases, but we want to check that our pretty-printing // functionality works perfectly, and doesn't do anything that's // unexpected around "boundaries" like columns==10 with 10 values. @@ -178,19 +178,29 @@ SCENARIO("BlockData write(), when a vector is active") CHECK(oss.str() == "2\n3\n5\n7\n11\n13\n17\n19\n21\n23\n"); oss.str(""); indent = 3; columns = 1; b.write(oss,1); - CHECK(oss.str() == " 2\n 3\n 5\n 7\n 11\n 13\n 17\n 19\n 21\n 23\n"); + CHECK(oss.str() == + " 2\n 3\n 5\n 7\n 11\n" + " 13\n 17\n 19\n 21\n 23\n"); oss.str(""); indent = 3; columns = 1; b.write(oss,2); - CHECK(oss.str() == " 2\n 3\n 5\n 7\n 11\n 13\n 17\n 19\n 21\n 23\n"); + CHECK(oss.str() == + " 2\n 3\n 5\n 7\n 11\n" + " 13\n 17\n 19\n 21\n 23\n"); oss.str(""); indent = 3; columns = 2; b.write(oss,0); CHECK(oss.str() == "2 3\n5 7\n11 13\n17 19\n21 23\n"); oss.str(""); indent = 3; columns = 2; b.write(oss,1); - CHECK(oss.str() == " 2 3\n 5 7\n 11 13\n 17 19\n 21 23\n"); + CHECK( + oss.str() == + " 2 3\n 5 7\n 11 13\n 17 19\n 21 23\n" + ); oss.str(""); indent = 3; columns = 2; b.write(oss,2); - CHECK(oss.str() == " 2 3\n 5 7\n 11 13\n 17 19\n 21 23\n"); + CHECK( + oss.str() == + " 2 3\n 5 7\n 11 13\n 17 19\n 21 23\n" + ); oss.str(""); indent = 3; columns = 5; b.write(oss,0); CHECK(oss.str() == "2 3 5 7 11\n13 17 19 21 23\n"); @@ -291,6 +301,7 @@ SCENARIO("BlockData write(), vector, trying GNDStk::truncate") // truncate: -1, 0, 1, 2, 3 (-1 means none; print all values) // Lots of cases; we want pretty-printing to be perfect. + // Integral parameters below are: indent, columns, level, truncate test_truncate(b, 3, 0, 0, -1, "2.3 5.7 11.13 17.19 21.23\n"); test_truncate(b, 3, 0, 0, +0, diff --git a/src/GNDStk/Component/test/detail.test.cpp b/src/GNDStk/Component/test/detail.test.cpp index 694f8cde3..1d5573d2f 100644 --- a/src/GNDStk/Component/test/detail.test.cpp +++ b/src/GNDStk/Component/test/detail.test.cpp @@ -503,11 +503,13 @@ SCENARIO("Testing Component detail:: writeComponentPart()") { oss.str(""); writeComponentPart(oss, level=2, def, "label", maxlen=0); - CHECK(oss.str() == " label : // defaulted; is its default (2.72)"); + CHECK(oss.str() == + " label : // defaulted; is its default (2.72)"); oss.str(""); writeComponentPart(oss, level=2, def, "label", maxlen=10); - CHECK(oss.str() == " label : // defaulted; is its default (2.72)"); + CHECK(oss.str() == + " label : // defaulted; is its default (2.72)"); oss.str(""); writeComponentPart(oss, level=2, def, "", maxlen=0); @@ -663,13 +665,14 @@ SCENARIO("Testing Component detail:: getter() functions") { GIVEN("A vector of objects that have both index and label") { // look for specific index THEN("getter() based on index works properly") { - CHECK((detail::getter(vec,0,"name","class","field").value() == "0a")); - CHECK((detail::getter(vec,1,"name","class","field").value() == "1b")); - CHECK((detail::getter(vec,2,"name","class","field").value() == "2c")); - CHECK((detail::getter(vec,3,"name","class","field").value() == "3d")); - CHECK((detail::getter(vec,4,"name","class","field").value() == "4e")); + using detail::getter; + CHECK((getter(vec, 0, "name", "class", "field").value() == "0a")); + CHECK((getter(vec, 1, "name", "class", "field").value() == "1b")); + CHECK((getter(vec, 2, "name", "class", "field").value() == "2c")); + CHECK((getter(vec, 3, "name", "class", "field").value() == "3d")); + CHECK((getter(vec, 4, "name", "class", "field").value() == "4e")); try { - detail::getter(vec,100,"name","class","field"); + getter(vec, 100, "name", "class", "field"); // the above should throw, so we shouldn't get here... CHECK(false); } catch (...) { @@ -678,13 +681,14 @@ SCENARIO("Testing Component detail:: getter() functions") { // look for specific label THEN("getter() based on label works properly") { - CHECK((detail::getter(vec,"a","name","class","field").value() == "0a")); - CHECK((detail::getter(vec,"b","name","class","field").value() == "1b")); - CHECK((detail::getter(vec,"c","name","class","field").value() == "2c")); - CHECK((detail::getter(vec,"d","name","class","field").value() == "3d")); - CHECK((detail::getter(vec,"e","name","class","field").value() == "4e")); + using detail::getter; + CHECK((getter(vec, "a", "name", "class", "field").value() == "0a")); + CHECK((getter(vec, "b", "name", "class", "field").value() == "1b")); + CHECK((getter(vec, "c", "name", "class", "field").value() == "2c")); + CHECK((getter(vec, "d", "name", "class", "field").value() == "3d")); + CHECK((getter(vec, "e", "name", "class", "field").value() == "4e")); try { - detail::getter(vec,"z","name","class","field"); + getter(vec, "z", "name", "class", "field"); // the above should throw, so we shouldn't get here... CHECK(false); } catch (...) { @@ -703,13 +707,14 @@ SCENARIO("Testing Component detail:: getter() functions") { // look for specific index THEN("getter() based on index works properly") { - CHECK((detail::getter(opt,0UL,"name","class","field").value() == "0a")); - CHECK((detail::getter(opt,1UL,"name","class","field").value() == "1b")); - CHECK((detail::getter(opt,2UL,"name","class","field").value() == "2c")); - CHECK((detail::getter(opt,3UL,"name","class","field").value() == "3d")); - CHECK((detail::getter(opt,4UL,"name","class","field").value() == "4e")); + using detail::getter; + CHECK((getter(opt, 0UL, "name", "class", "field").value() == "0a")); + CHECK((getter(opt, 1UL, "name", "class", "field").value() == "1b")); + CHECK((getter(opt, 2UL, "name", "class", "field").value() == "2c")); + CHECK((getter(opt, 3UL, "name", "class", "field").value() == "3d")); + CHECK((getter(opt, 4UL, "name", "class", "field").value() == "4e")); try { - detail::getter(opt,100UL,"name","class","field"); + getter(opt, 100UL, "name", "class", "field"); // the above should throw, so we shouldn't get here... CHECK(false); } catch (...) { @@ -718,13 +723,14 @@ SCENARIO("Testing Component detail:: getter() functions") { // look for specific label THEN("getter() based on label works properly") { - CHECK((detail::getter(opt,"a","name","class","field").value() == "0a")); - CHECK((detail::getter(opt,"b","name","class","field").value() == "1b")); - CHECK((detail::getter(opt,"c","name","class","field").value() == "2c")); - CHECK((detail::getter(opt,"d","name","class","field").value() == "3d")); - CHECK((detail::getter(opt,"e","name","class","field").value() == "4e")); + using detail::getter; + CHECK((getter(opt, "a", "name", "class", "field").value() == "0a")); + CHECK((getter(opt, "b", "name", "class", "field").value() == "1b")); + CHECK((getter(opt, "c", "name", "class", "field").value() == "2c")); + CHECK((getter(opt, "d", "name", "class", "field").value() == "3d")); + CHECK((getter(opt, "e", "name", "class", "field").value() == "4e")); try { - detail::getter(opt,"z","name","class","field"); + getter(opt, "z", "name", "class", "field"); // the above should throw, so we shouldn't get here... CHECK(false); } catch (...) { @@ -744,7 +750,7 @@ SCENARIO("Testing Component detail:: getter() functions") { // look for specific index THEN("getter() based on index works properly") { try { - detail::getter(opt,0,"name","class","field"); + detail::getter(opt, 0, "name", "class", "field"); // the above should throw, so we shouldn't get here... CHECK(false); } catch (...) { @@ -754,7 +760,7 @@ SCENARIO("Testing Component detail:: getter() functions") { // look for specific label THEN("getter() based on label works properly") { try { - detail::getter(opt,"a","name","class","field"); + detail::getter(opt, "a", "name", "class", "field"); // the above should throw, so we shouldn't get here... CHECK(false); } catch (...) { diff --git a/src/GNDStk/Component/test/finish.test.cpp b/src/GNDStk/Component/test/finish.test.cpp index 5baa57d2e..092faeef3 100644 --- a/src/GNDStk/Component/test/finish.test.cpp +++ b/src/GNDStk/Component/test/finish.test.cpp @@ -88,8 +88,10 @@ class DerivedValue : public Component const std::string &valueType() const { return content.valueType; } std::string &valueType() { return content.valueType; } - const std::optional> &indices() const { return content.indices; } - std::optional> &indices() { return content.indices; } + const std::optional> &indices() const + { return content.indices; } + std::optional> &indices() + { return content.indices; } private: @@ -243,8 +245,10 @@ class DerivedPlain : public Component const double &bar() const { return content.bar; } double &bar() { return content.bar; } - const std::optional> &labels() const { return content.labels; } - std::optional> &labels() { return content.labels; } + const std::optional> &labels() const + { return content.labels; } + std::optional> &labels() + { return content.labels; } private: diff --git a/src/GNDStk/Component/test/getter.test.cpp b/src/GNDStk/Component/test/getter.test.cpp index a36fe4c15..95855922b 100644 --- a/src/GNDStk/Component/test/getter.test.cpp +++ b/src/GNDStk/Component/test/getter.test.cpp @@ -98,15 +98,24 @@ class TestGetter : public Component CHECK( getter(vecIndexLabel,7,"vecIndexLabel").value() == "7 (seven)" ); // re: vecIndexLabel, lookup by label - CHECK( getter(vecIndexLabel,"five","vecIndexLabel").index() == 5 ); - CHECK( getter(vecIndexLabel,"five","vecIndexLabel").label() == "five" ); - CHECK( getter(vecIndexLabel,"five","vecIndexLabel").value() == "5 (five)" ); - CHECK( getter(vecIndexLabel,"six","vecIndexLabel").index() == 6 ); - CHECK( getter(vecIndexLabel,"six","vecIndexLabel").label() == "six" ); - CHECK( getter(vecIndexLabel,"six","vecIndexLabel").value() == "6 (six)" ); - CHECK( getter(vecIndexLabel,"seven","vecIndexLabel").index() == 7 ); - CHECK( getter(vecIndexLabel,"seven","vecIndexLabel").label() == "seven" ); - CHECK( getter(vecIndexLabel,"seven","vecIndexLabel").value() == "7 (seven)" ); + CHECK( getter(vecIndexLabel,"five","vecIndexLabel").index() + == 5 ); + CHECK( getter(vecIndexLabel,"five","vecIndexLabel").label() + == "five" ); + CHECK( getter(vecIndexLabel,"five","vecIndexLabel").value() + == "5 (five)" ); + CHECK( getter(vecIndexLabel,"six","vecIndexLabel").index() + == 6 ); + CHECK( getter(vecIndexLabel,"six","vecIndexLabel").label() + == "six" ); + CHECK( getter(vecIndexLabel,"six","vecIndexLabel").value() + == "6 (six)" ); + CHECK( getter(vecIndexLabel,"seven","vecIndexLabel").index() + == 7 ); + CHECK( getter(vecIndexLabel,"seven","vecIndexLabel").label() + == "seven" ); + CHECK( getter(vecIndexLabel,"seven","vecIndexLabel").value() + == "7 (seven)" ); } // non-const @@ -156,27 +165,36 @@ class TestGetter : public Component IndexLabel{ 11, "eleven", "11 (eleven)" }; // verify the new value - CHECK( getter(vecIndexLabel,11,"vecIndexLabel").index() == 11 ); - CHECK( getter(vecIndexLabel,11,"vecIndexLabel").label() == "eleven" ); - CHECK( getter(vecIndexLabel,11,"vecIndexLabel").value() == "11 (eleven)" ); + CHECK( getter(vecIndexLabel,11,"vecIndexLabel").index() + == 11 ); + CHECK( getter(vecIndexLabel,11,"vecIndexLabel").label() + == "eleven" ); + CHECK( getter(vecIndexLabel,11,"vecIndexLabel").value() + == "11 (eleven)" ); // ------------------------ // re: vecIndexLabel, lookup by label // ------------------------ // verify an existing value - CHECK( getter(vecIndexLabel,"six","vecIndexLabel").index() == 6 ); - CHECK( getter(vecIndexLabel,"six","vecIndexLabel").label() == "six" ); - CHECK( getter(vecIndexLabel,"six","vecIndexLabel").value() == "6 (six)" ); + CHECK( getter(vecIndexLabel,"six","vecIndexLabel").index() + == 6 ); + CHECK( getter(vecIndexLabel,"six","vecIndexLabel").label() + == "six" ); + CHECK( getter(vecIndexLabel,"six","vecIndexLabel").value() + == "6 (six)" ); // change getter(vecIndexLabel,"six","vecIndexLabel") = IndexLabel{ 13, "thirteen", "13 (thirteen)" }; // verify new value - CHECK( getter(vecIndexLabel,"thirteen","vecIndexLabel").index() == 13); - CHECK( getter(vecIndexLabel,"thirteen","vecIndexLabel").label() == "thirteen" ); - CHECK( getter(vecIndexLabel,"thirteen","vecIndexLabel").value() == "13 (thirteen)" ); + CHECK( getter(vecIndexLabel,"thirteen","vecIndexLabel").index() + == 13); + CHECK( getter(vecIndexLabel,"thirteen","vecIndexLabel").label() + == "thirteen" ); + CHECK( getter(vecIndexLabel,"thirteen","vecIndexLabel").value() + == "13 (thirteen)" ); } // ------------------------ @@ -223,14 +241,20 @@ class TestGetter : public Component CHECK( getter