Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-09-04 09:21:27

0001 #ifndef PODIO_USERDATACOLLECTION_H
0002 #define PODIO_USERDATACOLLECTION_H
0003 
0004 #include "podio/CollectionBase.h"
0005 #include "podio/CollectionBuffers.h"
0006 #include "podio/DatamodelRegistry.h"
0007 #include "podio/SchemaEvolution.h"
0008 #include "podio/detail/Pythonizations.h"
0009 #include "podio/utilities/TypeHelpers.h"
0010 
0011 #define PODIO_ADD_USER_TYPE(type)                                                                                      \
0012   template <>                                                                                                          \
0013   consteval const char* userDataTypeName<type>() {                                                                     \
0014     return #type;                                                                                                      \
0015   }                                                                                                                    \
0016   template <>                                                                                                          \
0017   consteval const char* userDataCollTypeName<type>() {                                                                 \
0018     return "podio::UserDataCollection<" #type ">";                                                                     \
0019   }
0020 
0021 namespace podio {
0022 
0023 /// tuple of basic types supported in user vector
0024 using SupportedUserDataTypes =
0025     std::tuple<float, double, int8_t, int16_t, int32_t, int64_t, uint8_t, uint16_t, uint32_t, uint64_t>;
0026 
0027 /// Alias template to be used to enable template specializations only for the types listed in the
0028 /// SupportedUserDataTypes list
0029 /// EnableIfSupportedUserType is kept because cppyy does not seem to like
0030 /// when UsedDataCollection is used with the concept
0031 template <typename T>
0032 concept SupportedUserDataType = detail::isInTuple<T, SupportedUserDataTypes>;
0033 template <typename T>
0034 using EnableIfSupportedUserType = std::enable_if_t<detail::isInTuple<T, SupportedUserDataTypes>>;
0035 
0036 /// helper template to provide readable type names for basic types with macro
0037 /// PODIO_ADD_USER_TYPE(type)
0038 template <SupportedUserDataType BasicType>
0039 consteval const char* userDataTypeName();
0040 
0041 /// Helper template to provide the fully qualified name of a UserDataCollection.
0042 /// Implementations are populated by the PODIO_ADD_USER_TYPE macro.
0043 template <SupportedUserDataType BasicType>
0044 consteval const char* userDataCollTypeName();
0045 
0046 PODIO_ADD_USER_TYPE(float)
0047 PODIO_ADD_USER_TYPE(double)
0048 
0049 PODIO_ADD_USER_TYPE(int8_t)
0050 PODIO_ADD_USER_TYPE(int16_t)
0051 PODIO_ADD_USER_TYPE(int32_t)
0052 PODIO_ADD_USER_TYPE(int64_t)
0053 PODIO_ADD_USER_TYPE(uint8_t)
0054 PODIO_ADD_USER_TYPE(uint16_t)
0055 PODIO_ADD_USER_TYPE(uint32_t)
0056 PODIO_ADD_USER_TYPE(uint64_t)
0057 
0058 /// Collection of basic types for additional user data not defined in the EDM.
0059 /// The data is stored in an std::vector<basic_type>. Supported are all basic
0060 /// types supported in PODIO, i.e. float, double and 8-64 bit fixed size signed
0061 /// and unsigned integers - @see SupportedUserDataTypes.
0062 ///
0063 /// @author F.Gaede, DESY
0064 /// @date Sep 2021
0065 template <typename BasicType, typename = EnableIfSupportedUserType<BasicType>>
0066 class UserDataCollection : public CollectionBase {
0067 
0068 private:
0069   std::vector<BasicType> _vec{};
0070   // Pointer to the actual storage, necessary for I/O. In order to have
0071   // simpler move-semantics this will be set and properly initialized on
0072   // demand during the call to getBuffers
0073   std::vector<BasicType>* _vecPtr{nullptr};
0074   uint32_t m_collectionID{0};
0075   CollRefCollection m_refCollections{};
0076   VectorMembersInfo m_vecmem_info{};
0077 
0078 public:
0079   using value_type = typename std::vector<BasicType>::value_type;
0080   using mutable_type = value_type;
0081   using const_iterator = typename std::vector<BasicType>::const_iterator;
0082   using iterator = typename std::vector<BasicType>::iterator;
0083   using difference_type = typename std::vector<BasicType>::difference_type;
0084   using size_type = typename std::vector<BasicType>::size_type;
0085   using const_reverse_iterator = typename std::vector<BasicType>::const_reverse_iterator;
0086   using reverse_iterator = typename std::vector<BasicType>::reverse_iterator;
0087 
0088   UserDataCollection() = default;
0089   /// Constructor from an existing vector (which will be moved from!)
0090   UserDataCollection(std::vector<BasicType>&& vec) : _vec(std::move(vec)) {
0091   }
0092   UserDataCollection(const UserDataCollection&) = delete;
0093   UserDataCollection& operator=(const UserDataCollection&) = delete;
0094   UserDataCollection(UserDataCollection&&) = default;
0095   UserDataCollection& operator=(UserDataCollection&&) = default;
0096   ~UserDataCollection() override = default;
0097 #if defined(__cpp_lib_containers_ranges)
0098   /// Constructor to enable construction via std::ranges::to. See @ref from
0099   template <detail::RangeConvertibleTo<BasicType> R>
0100   UserDataCollection(std::from_range_t, R&& range) : UserDataCollection() {
0101     _vec = detail::to_vector<BasicType>(std::forward<R>(range));
0102   }
0103 #endif
0104 
0105   /// Construct a UserDataCollection from a range of values
0106   ///
0107   /// @param range A range of values that can convert to BasicType
0108   ///
0109   /// @returns a UserDataCollection populated with the values from the input
0110   ///          range
0111   template <detail::RangeConvertibleTo<BasicType> R>
0112   static UserDataCollection from(R&& range) {
0113     UserDataCollection coll;
0114     coll._vec = detail::to_vector<BasicType>(std::forward<R>(range));
0115     return coll;
0116   }
0117 
0118   /// The schema version of UserDataCollections
0119   static constexpr SchemaVersionT schemaVersion = 1;
0120 
0121   static constexpr std::string_view typeName = userDataCollTypeName<BasicType>();
0122   static constexpr std::string_view valueTypeName = userDataTypeName<BasicType>();
0123   static constexpr std::string_view dataTypeName = userDataTypeName<BasicType>();
0124 
0125   /// prepare buffers for serialization
0126   void prepareForWrite() const override {
0127   }
0128 
0129   /// re-create collection from buffers after read
0130   void prepareAfterRead() override {
0131   }
0132 
0133   /// initialize references after read
0134   bool setReferences(const ICollectionProvider*) override {
0135     return true;
0136   }
0137 
0138   /// set collection ID
0139   void setID(uint32_t id) override {
0140     m_collectionID = id;
0141   }
0142 
0143   /// get collection ID
0144   uint32_t getID() const override {
0145     return m_collectionID;
0146   }
0147 
0148   /// Get the collection buffers for this collection
0149   podio::CollectionWriteBuffers getBuffers() override {
0150     _vecPtr = &_vec; // Set the pointer to the correct internal vector
0151     return {&_vecPtr, _vecPtr, &m_refCollections, &m_vecmem_info};
0152   }
0153 
0154   /// check if the collection has a valid ID
0155   bool hasID() const override {
0156     return getID() != static_cast<uint32_t>(podio::ObjectID::untracked) &&
0157         getID() != static_cast<uint32_t>(podio::ObjectID::invalid);
0158   }
0159 
0160   [[deprecated("isValid will be removed, use hasID() if you want to check if it has an ID, otherwise assume the "
0161                "collection is valid")]]
0162   bool isValid() const override {
0163     return hasID();
0164   }
0165 
0166   /// number of elements in the collection
0167   size_t size() const override {
0168     return _vec.size();
0169   }
0170 
0171   /// maximal number of elements in the collection
0172   size_t max_size() const override {
0173     return _vec.max_size();
0174   }
0175 
0176   /// Is the collection empty
0177   bool empty() const override {
0178     return _vec.empty();
0179   }
0180 
0181   /// fully qualified type name
0182   const std::string_view getTypeName() const override {
0183     return typeName;
0184   }
0185 
0186   /// fully qualified type name of elements - with namespace
0187   const std::string_view getValueTypeName() const override {
0188     return valueTypeName;
0189   }
0190 
0191   /// fully qualified type name of stored POD elements - with namespace
0192   const std::string_view getDataTypeName() const override {
0193     return dataTypeName;
0194   }
0195 
0196   /// Cppyy protocol to setup the pythonizations for this class. Not to be called directly.
0197   static void __cppyy_pythonize__(PyObject* klass, const std::string& name) {
0198     podio::detail::pythonizations::pythonize_subscript(klass, name);
0199   }
0200 
0201   /// clear the collection and all internal states
0202   void clear() override {
0203     _vec.clear();
0204   }
0205 
0206   /// check if this collection is a subset collection - no subset possible
0207   bool isSubsetCollection() const override {
0208     return false;
0209   }
0210 
0211   /// declare this collection to be a subset collection - no effect
0212   void setSubsetCollection(bool) override {
0213   }
0214 
0215   /// The schema version is fixed manually
0216   SchemaVersionT getSchemaVersion() const final {
0217     return schemaVersion;
0218   }
0219 
0220   /// Print this collection to the passed stream
0221   void print(std::ostream& os = std::cout, bool flush = true) const override {
0222     os << "[";
0223     if (!_vec.empty()) {
0224       os << _vec[0];
0225       for (size_t i = 1; i < _vec.size(); ++i) {
0226         os << ", " << _vec[i];
0227       }
0228     }
0229     os << "]";
0230 
0231     if (flush) {
0232       os.flush(); // Necessary for python
0233     }
0234   }
0235 
0236   size_t getDatamodelRegistryIndex() const override {
0237     return DatamodelRegistry::NoDefinitionNecessary;
0238   }
0239 
0240   // ----- some wrappers for std::vector and access to the complete std::vector (if really needed)
0241 
0242   typename std::vector<BasicType>::reference create() {
0243     return _vec.emplace_back();
0244   }
0245 
0246   iterator begin() {
0247     return _vec.begin();
0248   }
0249   iterator end() {
0250     return _vec.end();
0251   }
0252   const_iterator begin() const {
0253     return _vec.begin();
0254   }
0255   const_iterator end() const {
0256     return _vec.end();
0257   }
0258   const_iterator cbegin() const {
0259     return _vec.cbegin();
0260   }
0261   const_iterator cend() const {
0262     return _vec.cend();
0263   }
0264   // reverse iterators
0265   reverse_iterator rbegin() {
0266     return _vec.rbegin();
0267   }
0268   const_reverse_iterator rbegin() const {
0269     return _vec.rbegin();
0270   }
0271   const_reverse_iterator crbegin() const {
0272     return _vec.crbegin();
0273   }
0274   reverse_iterator rend() {
0275     return _vec.rend();
0276   }
0277   const_reverse_iterator rend() const {
0278     return _vec.rend();
0279   }
0280   const_reverse_iterator crend() const {
0281     return _vec.crend();
0282   }
0283 
0284   typename std::vector<BasicType>::reference operator[](size_t idx) {
0285     return _vec[idx];
0286   }
0287   typename std::vector<BasicType>::const_reference operator[](size_t idx) const {
0288     return _vec[idx];
0289   }
0290 
0291   typename std::vector<BasicType>::reference at(size_t idx) {
0292     return _vec.at(idx);
0293   }
0294   typename std::vector<BasicType>::const_reference at(size_t idx) const {
0295     return _vec.at(idx);
0296   }
0297 
0298   void resize(size_t count) {
0299     _vec.resize(count);
0300   }
0301   void push_back(const BasicType& value) {
0302     _vec.push_back(value);
0303   }
0304 
0305   /// access to the actual data vector
0306   typename std::vector<BasicType>& vec() {
0307     return _vec;
0308   }
0309 
0310   /// const access to the actual data vector
0311   const typename std::vector<BasicType>& vec() const {
0312     return _vec;
0313   }
0314 };
0315 
0316 using UserDataCollectionTypes = decltype(std::apply(
0317     []<typename... Ts>(Ts...) { return utils::TypeList<UserDataCollection<Ts>...>{}; }, SupportedUserDataTypes{}));
0318 
0319 // don't make this macro public as it should only be used internally here...
0320 #undef PODIO_ADD_USER_TYPE
0321 
0322 template <SupportedUserDataType BasicType>
0323 std::ostream& operator<<(std::ostream& o, const podio::UserDataCollection<BasicType>& coll) {
0324   coll.print(o);
0325   return o;
0326 }
0327 
0328 // This is needed to avoid triggering opening every library in LD_LIBRARY_PATH
0329 // until it's fixed in ROOT. See https://github.com/root-project/root/issues/18489
0330 // and https://github.com/AIDASoft/podio/issues/770
0331 #if defined(__clang__)
0332   #pragma clang diagnostic push
0333   #pragma clang diagnostic ignored "-Wunknown-warning-option"
0334   #pragma clang diagnostic ignored "-Wdeprecated-redundant-constexpr-static-def"
0335   #pragma clang diagnostic ignored "-Wdeprecated"
0336 template <typename BasicType, typename U>
0337 constexpr std::string_view UserDataCollection<BasicType, U>::typeName;
0338 template <typename BasicType, typename U>
0339 constexpr std::string_view UserDataCollection<BasicType, U>::valueTypeName;
0340 template <typename BasicType, typename U>
0341 constexpr std::string_view UserDataCollection<BasicType, U>::dataTypeName;
0342   #pragma clang diagnostic pop
0343 #elif defined(__GNUC__)
0344   #pragma GCC diagnostic push
0345   #pragma GCC diagnostic ignored "-Wdeprecated"
0346 template <typename BasicType, typename U>
0347 constexpr std::string_view UserDataCollection<BasicType, U>::typeName;
0348 template <typename BasicType, typename U>
0349 constexpr std::string_view UserDataCollection<BasicType, U>::valueTypeName;
0350 template <typename BasicType, typename U>
0351 constexpr std::string_view UserDataCollection<BasicType, U>::dataTypeName;
0352   #pragma GCC diagnostic pop
0353 #endif
0354 
0355 } // namespace podio
0356 
0357 #endif