From 216223e1695bfd2a8f54569ffe80130bd2b83f5c Mon Sep 17 00:00:00 2001 From: Thomas Madlener Date: Mon, 13 Apr 2026 21:56:29 +0200 Subject: [PATCH 1/4] Extract common members into a common base Members related to file version and datamodels contained in files are the same for all readers and some commonly available member functions are also shared across all readers. --- include/podio/RNTupleReader.h | 43 +----------------- include/podio/ROOTReader.h | 42 +---------------- include/podio/SIOReader.h | 44 +----------------- include/podio/utilities/ReaderCommon.h | 62 ++++++++++++++++++++++++++ 4 files changed, 68 insertions(+), 123 deletions(-) create mode 100644 include/podio/utilities/ReaderCommon.h diff --git a/include/podio/RNTupleReader.h b/include/podio/RNTupleReader.h index 80b731b3e..38969925b 100644 --- a/include/podio/RNTupleReader.h +++ b/include/podio/RNTupleReader.h @@ -2,8 +2,7 @@ #define PODIO_RNTUPLEREADER_H #include "podio/ROOTFrameData.h" -#include "podio/podioVersion.h" -#include "podio/utilities/DatamodelRegistryIOHelpers.h" +#include "podio/utilities/ReaderCommon.h" #include "podio/utilities/RootHelpers.h" #include @@ -32,7 +31,7 @@ namespace root_compat { /// /// The RNTupleReader provides the data as ROOTFrameData from which a podio::Frame /// can be constructed. It can be used to read files written by the RNTupleWriter. -class RNTupleReader { +class RNTupleReader : public ReaderCommon { public: RNTupleReader() = default; @@ -103,41 +102,6 @@ class RNTupleReader { /// @returns The number of entries that are available for the category unsigned getEntries(std::string_view name) const; - /// Get the build version of podio that has been used to write the current - /// file - /// - /// @returns The podio build version - podio::version::Version currentFileVersion() const { - return m_fileVersion; - } - - /// Get the (build) version of a datamodel that has been used to write the - /// current file - /// - /// @param name The name of the datamodel - /// - /// @returns The (build) version of the datamodel if available or an empty - /// optional - std::optional currentFileVersion(std::string_view name) const { - return m_datamodelHolder.getDatamodelVersion(name); - } - - /// Get the datamodel definition for the given name - /// - /// @param name The name of the datamodel - /// - /// @returns The high level definition of the datamodel in JSON format - const std::string_view getDatamodelDefinition(std::string_view name) const { - return m_datamodelHolder.getDatamodelDefinition(name); - } - - /// Get all names of the datamodels that are available from this reader - /// - /// @returns The names of the datamodels - std::vector getAvailableDatamodels() const { - return m_datamodelHolder.getAvailableDatamodels(); - } - private: /** * Initialize the given category by filling the maps with metadata information @@ -152,9 +116,6 @@ class RNTupleReader { std::unique_ptr m_metadata{}; - podio::version::Version m_fileVersion{}; - DatamodelDefinitionHolder m_datamodelHolder{}; - std::unordered_map>> m_readers{}; std::unordered_map> m_metadata_readers{}; std::vector m_filenames{}; diff --git a/include/podio/ROOTReader.h b/include/podio/ROOTReader.h index f59c2941d..be32bcb9d 100644 --- a/include/podio/ROOTReader.h +++ b/include/podio/ROOTReader.h @@ -2,8 +2,7 @@ #define PODIO_ROOTREADER_H #include "podio/ROOTFrameData.h" -#include "podio/podioVersion.h" -#include "podio/utilities/DatamodelRegistryIOHelpers.h" +#include "podio/utilities/ReaderCommon.h" #include "podio/utilities/ReaderUtils.h" #include "podio/utilities/RootHelpers.h" @@ -46,7 +45,7 @@ struct CollectionReadBuffers; /// /// The ROOTReader provides the data as ROOTFrameData from which a podio::Frame /// can be constructed. It can be used to read files written by the ROOTWriter. -class ROOTReader { +class ROOTReader : public ReaderCommon { public: ROOTReader() = default; @@ -112,45 +111,11 @@ class ROOTReader { /// @returns The number of entries that are available for the category unsigned getEntries(std::string_view name) const; - /// Get the build version of podio that has been used to write the current - /// file - /// - /// @returns The podio build version - podio::version::Version currentFileVersion() const { - return m_fileVersion; - } - - /// Get the (build) version of a datamodel that has been used to write the - /// current file - /// - /// @param name The name of the datamodel - /// - /// @returns The (build) version of the datamodel if available or an empty - /// optional - std::optional currentFileVersion(std::string_view name) const { - return m_datamodelHolder.getDatamodelVersion(name); - } - /// Get the names of all the available Frame categories in the current file(s). /// /// @returns The names of the available categories from the file std::vector getAvailableCategories() const; - /// Get the datamodel definition for the given name - /// - /// @param name The name of the datamodel - /// - /// @returns The high level definition of the datamodel in JSON format - const std::string_view getDatamodelDefinition(std::string_view name) const { - return m_datamodelHolder.getDatamodelDefinition(name); - } - - /// Get all names of the datamodels that are available from this reader - /// - /// @returns The names of the datamodels - std::vector getAvailableDatamodels() const { - return m_datamodelHolder.getAvailableDatamodels(); - } std::optional> getSizeStats(std::string_view category); private: @@ -201,9 +166,6 @@ class ROOTReader { std::unique_ptr m_metaChain{nullptr}; ///< The metadata tree std::unordered_map m_categories{}; ///< All categories std::vector m_availCategories{}; ///< All available categories from this file - - podio::version::Version m_fileVersion{0, 0, 0}; - DatamodelDefinitionHolder m_datamodelHolder{}; }; } // namespace podio diff --git a/include/podio/SIOReader.h b/include/podio/SIOReader.h index e91ee2e46..51fdefad9 100644 --- a/include/podio/SIOReader.h +++ b/include/podio/SIOReader.h @@ -3,8 +3,7 @@ #include "podio/SIOBlock.h" #include "podio/SIOFrameData.h" -#include "podio/podioVersion.h" -#include "podio/utilities/DatamodelRegistryIOHelpers.h" +#include "podio/utilities/ReaderCommon.h" #include @@ -22,7 +21,7 @@ class CollectionIDTable; /// /// The SIOReader provides the data as SIOFrameData from which a podio::Frame /// can be constructed. It can be used to read files written by the SIOWriter. -class SIOReader { +class SIOReader : public ReaderCommon { public: /// Create an SIOReader @@ -83,46 +82,11 @@ class SIOReader { /// @param filename The path to the file to read from void openFile(const std::string& filename); - /// Get the build version of podio that has been used to write the current - /// file - /// - /// @returns The podio build version - podio::version::Version currentFileVersion() const { - return m_fileVersion; - } - - /// Get the (build) version of a datamodel that has been used to write the - /// current file - /// - /// @param name The name of the datamodel - /// - /// @returns The (build) version of the datamodel if available or an empty - /// optional - std::optional currentFileVersion(std::string_view name) const { - return m_datamodelHolder.getDatamodelVersion(name); - } - /// Get the names of all the available Frame categories in the current file. /// /// @returns The names of the available categores from the file std::vector getAvailableCategories() const; - /// Get the datamodel definition for the given name - /// - /// @param name The name of the datamodel - /// - /// @returns The high level definition of the datamodel in JSON format - const std::string_view getDatamodelDefinition(std::string_view name) const { - return m_datamodelHolder.getDatamodelDefinition(name); - } - - /// Get all names of the datamodels that are available from this reader - /// - /// @returns The names of the datamodels - std::vector getAvailableDatamodels() const { - return m_datamodelHolder.getAvailableDatamodels(); - } - private: void readPodioHeader(); @@ -138,10 +102,6 @@ class SIOReader { /// Table of content record where starting points of named entries can be read from SIOFileTOCRecord m_tocRecord{}; - /// The podio version that has been used to write the file - podio::version::Version m_fileVersion{0}; - - DatamodelDefinitionHolder m_datamodelHolder{}; }; } // namespace podio diff --git a/include/podio/utilities/ReaderCommon.h b/include/podio/utilities/ReaderCommon.h new file mode 100644 index 000000000..31698e358 --- /dev/null +++ b/include/podio/utilities/ReaderCommon.h @@ -0,0 +1,62 @@ +#ifndef PODIO_UTILITIES_READERCOMMON_H +#define PODIO_UTILITIES_READERCOMMON_H + +#include "podio/podioVersion.h" +#include "podio/utilities/DatamodelRegistryIOHelpers.h" + +#include +#include +#include +#include + +namespace podio { + +/// Common base class for podio reader classes providing the shared members and +/// functionality related to the file version and the datamodel definitions. +/// +/// The population of the members is left to the derived reader classes. +class ReaderCommon { +public: + /// Get the build version of podio that has been used to write the current + /// file + /// + /// @returns The podio build version + podio::version::Version currentFileVersion() const { + return m_fileVersion; + } + + /// Get the (build) version of a datamodel that has been used to write the + /// current file + /// + /// @param name The name of the datamodel + /// + /// @returns The (build) version of the datamodel if available or an empty + /// optional + std::optional currentFileVersion(std::string_view name) const { + return m_datamodelHolder.getDatamodelVersion(name); + } + + /// Get the datamodel definition for the given name + /// + /// @param name The name of the datamodel + /// + /// @returns The high level definition of the datamodel in JSON format + const std::string_view getDatamodelDefinition(std::string_view name) const { + return m_datamodelHolder.getDatamodelDefinition(name); + } + + /// Get all names of the datamodels that are available from this reader + /// + /// @returns The names of the datamodels + std::vector getAvailableDatamodels() const { + return m_datamodelHolder.getAvailableDatamodels(); + } + +protected: + podio::version::Version m_fileVersion{}; + DatamodelDefinitionHolder m_datamodelHolder{}; +}; + +} // namespace podio + +#endif // PODIO_UTILITIES_READERCOMMON_H From b113abf5783020ff157b94f894376c69d221addd Mon Sep 17 00:00:00 2001 From: Thomas Madlener Date: Mon, 13 Apr 2026 22:16:53 +0200 Subject: [PATCH 2/4] Make sure common functionality still shows up properly in documentation --- doc/Doxyfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/Doxyfile b/doc/Doxyfile index d0cb5066a..9599ed292 100644 --- a/doc/Doxyfile +++ b/doc/Doxyfile @@ -155,7 +155,7 @@ ALWAYS_DETAILED_SEC = NO # operators of the base classes will not be shown. # The default value is: NO. -INLINE_INHERITED_MEMB = NO +INLINE_INHERITED_MEMB = YES # If the FULL_PATH_NAMES tag is set to YES, doxygen will prepend the full path # before files name in the file list and in the header files. If set to NO the From b29e87ca4f5fa49b7e8f9455904c0ea9cf2e82a1 Mon Sep 17 00:00:00 2001 From: Juan Miguel Carceller Date: Mon, 27 Jul 2026 09:33:01 +0200 Subject: [PATCH 3/4] Make getAvailableCategories() also part of the common reader --- include/podio/RNTupleReader.h | 7 ------- include/podio/ROOTReader.h | 6 ------ include/podio/SIOReader.h | 5 ----- include/podio/utilities/ReaderCommon.h | 13 +++++++++++++ src/RNTupleReader.cc | 9 --------- src/ROOTReader.cc | 13 ++----------- src/SIOReader.cc | 20 ++++++++++---------- 7 files changed, 25 insertions(+), 48 deletions(-) diff --git a/include/podio/RNTupleReader.h b/include/podio/RNTupleReader.h index 38969925b..2aafa63ec 100644 --- a/include/podio/RNTupleReader.h +++ b/include/podio/RNTupleReader.h @@ -90,11 +90,6 @@ class RNTupleReader : public ReaderCommon { std::unique_ptr readEntry(std::string_view name, const unsigned entry, const std::vector& collsToRead = {}); - /// Get the names of all the available Frame categories in the current file(s). - /// - /// @returns The names of the available categores from the file - std::vector getAvailableCategories() const; - /// Get the number of entries for the given name /// /// @param name The name of the category @@ -131,8 +126,6 @@ class RNTupleReader : public ReaderCommon { /// Map each category to the collections that have been written and are available std::unordered_map> m_collectionInfo{}; - std::vector m_availableCategories{}; - std::unordered_map> m_idTables{}; }; diff --git a/include/podio/ROOTReader.h b/include/podio/ROOTReader.h index be32bcb9d..128690089 100644 --- a/include/podio/ROOTReader.h +++ b/include/podio/ROOTReader.h @@ -111,11 +111,6 @@ class ROOTReader : public ReaderCommon { /// @returns The number of entries that are available for the category unsigned getEntries(std::string_view name) const; - /// Get the names of all the available Frame categories in the current file(s). - /// - /// @returns The names of the available categories from the file - std::vector getAvailableCategories() const; - std::optional> getSizeStats(std::string_view category); private: @@ -165,7 +160,6 @@ class ROOTReader : public ReaderCommon { std::unique_ptr m_metaChain{nullptr}; ///< The metadata tree std::unordered_map m_categories{}; ///< All categories - std::vector m_availCategories{}; ///< All available categories from this file }; } // namespace podio diff --git a/include/podio/SIOReader.h b/include/podio/SIOReader.h index 51fdefad9..714123c95 100644 --- a/include/podio/SIOReader.h +++ b/include/podio/SIOReader.h @@ -82,11 +82,6 @@ class SIOReader : public ReaderCommon { /// @param filename The path to the file to read from void openFile(const std::string& filename); - /// Get the names of all the available Frame categories in the current file. - /// - /// @returns The names of the available categores from the file - std::vector getAvailableCategories() const; - private: void readPodioHeader(); diff --git a/include/podio/utilities/ReaderCommon.h b/include/podio/utilities/ReaderCommon.h index 31698e358..3729a6951 100644 --- a/include/podio/utilities/ReaderCommon.h +++ b/include/podio/utilities/ReaderCommon.h @@ -52,9 +52,22 @@ class ReaderCommon { return m_datamodelHolder.getAvailableDatamodels(); } + /// Get the names of all the available Frame categories in the current file(s). + /// + /// @returns The names of the available categories from the file + std::vector getAvailableCategories() const { + std::vector categories; + categories.reserve(m_availableCategories.size()); + for (const auto& category : m_availableCategories) { + categories.emplace_back(category); + } + return categories; + } + protected: podio::version::Version m_fileVersion{}; DatamodelDefinitionHolder m_datamodelHolder{}; + std::vector m_availableCategories{}; }; } // namespace podio diff --git a/src/RNTupleReader.cc b/src/RNTupleReader.cc index 4466ecddc..f30149fe3 100644 --- a/src/RNTupleReader.cc +++ b/src/RNTupleReader.cc @@ -129,15 +129,6 @@ unsigned RNTupleReader::getEntries(std::string_view name) const { return 0; } -std::vector RNTupleReader::getAvailableCategories() const { - std::vector cats; - cats.reserve(m_availableCategories.size()); - for (const auto& cat : m_availableCategories) { - cats.emplace_back(cat); - } - return cats; -} - std::unique_ptr RNTupleReader::readNextEntry(std::string_view category, const std::vector& collsToRead) { return readEntry(category, m_entries[category], collsToRead); diff --git a/src/ROOTReader.cc b/src/ROOTReader.cc index 65aaa7429..4ee68ccaa 100644 --- a/src/ROOTReader.cc +++ b/src/ROOTReader.cc @@ -331,8 +331,8 @@ void ROOTReader::openFiles(const std::vector& filenames) { // Do some work up front for setting up categories and setup all the chains // and record the available categories. The rest of the setup follows on // demand when the category is first read - m_availCategories = ::podio::getAvailableCategories(m_metaChain.get()); - for (const auto& cat : m_availCategories) { + m_availableCategories = ::podio::getAvailableCategories(m_metaChain.get()); + for (const auto& cat : m_availableCategories) { const auto [it, _] = m_categories.try_emplace(cat, std::make_unique(cat.c_str())); for (const auto& fn : filenames) { it->second.chain->Add(fn.c_str()); @@ -348,15 +348,6 @@ unsigned ROOTReader::getEntries(std::string_view name) const { return 0; } -std::vector ROOTReader::getAvailableCategories() const { - std::vector cats; - cats.reserve(m_categories.size()); - for (const auto& [cat, _] : m_categories) { - cats.emplace_back(cat); - } - return cats; -} - std::tuple, std::vector> createCollectionBranchesIndexBased(TChain* chain, const podio::CollectionIDTable& idTable, const std::vector& collInfo) { diff --git a/src/SIOReader.cc b/src/SIOReader.cc index 32c10e2fb..cac3d3a3c 100644 --- a/src/SIOReader.cc +++ b/src/SIOReader.cc @@ -22,6 +22,16 @@ void SIOReader::openFile(const std::string& filename) { // NOTE: reading TOC record first because that jumps back to the start of the file! readFileTOCRecord(); + // Filter the available records from the TOC to remove records that are + // stored, but use reserved record names for podio meta data + const auto recordNames = m_tocRecord.getRecordNames(); + m_availableCategories.clear(); + m_availableCategories.reserve(recordNames.size()); + for (const auto recordName : recordNames) { + if (recordName != sio_helpers::SIOEDMDefinitionName) { + m_availableCategories.emplace_back(recordName); + } + } readPodioHeader(); readEDMDefinitions(); // Potentially could do this lazily } @@ -57,16 +67,6 @@ std::unique_ptr SIOReader::readEntry(std::string_view name, const return readNextEntry(name, collsToRead); } -std::vector SIOReader::getAvailableCategories() const { - // Filter the available records from the TOC to remove records that are - // stored, but use reserved record names for podio meta data - auto recordNames = m_tocRecord.getRecordNames(); - recordNames.erase(std::remove_if(recordNames.begin(), recordNames.end(), - [](const auto& elem) { return elem == sio_helpers::SIOEDMDefinitionName; }), - recordNames.end()); - return recordNames; -} - unsigned SIOReader::getEntries(std::string_view name) const { return m_tocRecord.getNRecords(name); } From 6a95a38eb73091ac70c982cae47b53f4c7b761d0 Mon Sep 17 00:00:00 2001 From: Juan Miguel Carceller Date: Mon, 27 Jul 2026 09:53:59 +0200 Subject: [PATCH 4/4] Use the range constructor --- include/podio/utilities/ReaderCommon.h | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/include/podio/utilities/ReaderCommon.h b/include/podio/utilities/ReaderCommon.h index 3729a6951..faf44c7f3 100644 --- a/include/podio/utilities/ReaderCommon.h +++ b/include/podio/utilities/ReaderCommon.h @@ -56,12 +56,7 @@ class ReaderCommon { /// /// @returns The names of the available categories from the file std::vector getAvailableCategories() const { - std::vector categories; - categories.reserve(m_availableCategories.size()); - for (const auto& category : m_availableCategories) { - categories.emplace_back(category); - } - return categories; + return std::vector(m_availableCategories.cbegin(), m_availableCategories.cend()); } protected: