Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-09-16 09:08:27

0001 /// \file ROOT/RColumnElementBase.hxx
0002 /// \ingroup NTuple
0003 /// \author Jakob Blomer <jblomer@cern.ch>
0004 /// \date 2018-10-09
0005 
0006 /*************************************************************************
0007  * Copyright (C) 1995-2019, Rene Brun and Fons Rademakers.               *
0008  * All rights reserved.                                                  *
0009  *                                                                       *
0010  * For the licensing terms see $ROOTSYS/LICENSE.                         *
0011  * For the list of contributors see $ROOTSYS/README/CREDITS.             *
0012  *************************************************************************/
0013 
0014 #ifndef ROOT_RColumnElementBase
0015 #define ROOT_RColumnElementBase
0016 
0017 #include "RtypesCore.h"
0018 #include <ROOT/RError.hxx>
0019 #include <ROOT/RFloat16.hxx>
0020 #include <ROOT/RNTupleUtil.hxx>
0021 
0022 #include <Byteswap.h>
0023 #include <TError.h>
0024 
0025 #include <cstring> // for memcpy
0026 #include <cstddef> // for std::byte
0027 #include <cstdint>
0028 #include <memory>
0029 #include <optional>
0030 #include <string>
0031 #include <type_traits>
0032 #include <typeindex>
0033 #include <typeinfo>
0034 #include <utility>
0035 
0036 namespace ROOT::Internal {
0037 
0038 // clang-format off
0039 /**
0040 \class ROOT::Internal::RColumnElementBase
0041 \ingroup NTuple
0042 \brief A column element encapsulates the translation between basic C++ types and their column representation.
0043 
0044 Usually the on-disk element should map bitwise to the in-memory element. Sometimes that's not the case
0045 though, for instance on big endian platforms or for bools.
0046 
0047 There is a template specialization for every valid pair of C++ type and column representation.
0048 These specialized child classes are responsible for overriding `Pack()` / `Unpack()` for packing / unpacking elements
0049 as appropriate.
0050 */
0051 // clang-format on
0052 class RColumnElementBase {
0053 protected:
0054    /// Size of the C++ value that corresponds to the on-disk element
0055    std::size_t fSize;
0056    std::size_t fBitsOnStorage;
0057    /// This is only meaningful for column elements that support it (e.g. Real32Quant)
0058    std::optional<std::pair<double, double>> fValueRange = std::nullopt;
0059 
0060    explicit RColumnElementBase(std::size_t size, std::size_t bitsOnStorage = 0)
0061       : fSize(size), fBitsOnStorage(bitsOnStorage ? bitsOnStorage : 8 * size)
0062    {
0063    }
0064 
0065 public:
0066    /// Every concrete RColumnElement type is identified by its on-disk type (column type) and the
0067    /// in-memory C++ type, given by a type index.
0068    struct RIdentifier {
0069       std::type_index fInMemoryType = std::type_index(typeid(void));
0070       ROOT::ENTupleColumnType fOnDiskType = ROOT::ENTupleColumnType::kUnknown;
0071 
0072       bool operator==(const RIdentifier &other) const
0073       {
0074          return this->fInMemoryType == other.fInMemoryType && this->fOnDiskType == other.fOnDiskType;
0075       }
0076 
0077       bool operator!=(const RIdentifier &other) const { return !(*this == other); }
0078    };
0079 
0080    RColumnElementBase(const RColumnElementBase &other) = default;
0081    RColumnElementBase(RColumnElementBase &&other) = default;
0082    RColumnElementBase &operator=(const RColumnElementBase &other) = delete;
0083    RColumnElementBase &operator=(RColumnElementBase &&other) = default;
0084    virtual ~RColumnElementBase() = default;
0085 
0086    /// If CppT == void, use the default C++ type for the given column type
0087    template <typename CppT = void>
0088    static std::unique_ptr<RColumnElementBase> Generate(ROOT::ENTupleColumnType type);
0089    static const char *GetColumnTypeName(ROOT::ENTupleColumnType type);
0090    /// Most types have a fixed on-disk bit width. Some low-precision column types
0091    /// have a range of possible bit widths. Return the minimum and maximum allowed
0092    /// bit size per type.
0093    static std::pair<std::uint16_t, std::uint16_t> GetValidBitRange(ROOT::ENTupleColumnType type);
0094 
0095    /// Derived, typed classes tell whether the on-storage layout is bitwise identical to the memory layout
0096    virtual bool IsMappable() const
0097    {
0098       R__ASSERT(false);
0099       return false;
0100    }
0101 
0102    virtual void SetBitsOnStorage(std::size_t bitsOnStorage)
0103    {
0104       if (bitsOnStorage != fBitsOnStorage)
0105          throw RException(R__FAIL(std::string("internal error: cannot change bit width of this column type")));
0106    }
0107 
0108    virtual void SetValueRange(double, double)
0109    {
0110       throw RException(R__FAIL(std::string("internal error: cannot change value range of this column type")));
0111    }
0112 
0113    /// If the on-storage layout and the in-memory layout differ, packing creates an on-disk page from an in-memory page
0114    virtual void Pack(void *destination, const void *source, std::size_t count) const
0115    {
0116       std::memcpy(destination, source, count);
0117    }
0118 
0119    /// If the on-storage layout and the in-memory layout differ, unpacking creates a memory page from an on-storage page
0120    virtual void Unpack(void *destination, const void *source, std::size_t count) const
0121    {
0122       std::memcpy(destination, source, count);
0123    }
0124 
0125    std::size_t GetSize() const { return fSize; }
0126    std::size_t GetBitsOnStorage() const { return fBitsOnStorage; }
0127    std::optional<std::pair<double, double>> GetValueRange() const { return fValueRange; }
0128    std::size_t GetPackedSize(std::size_t nElements = 1U) const { return (nElements * fBitsOnStorage + 7) / 8; }
0129 
0130    virtual RIdentifier GetIdentifier() const = 0;
0131 }; // class RColumnElementBase
0132 
0133 struct RTestFutureColumn {
0134    std::uint32_t dummy;
0135 };
0136 
0137 std::unique_ptr<RColumnElementBase>
0138 GenerateColumnElement(std::type_index inMemoryType, ROOT::ENTupleColumnType onDiskType);
0139 
0140 std::unique_ptr<RColumnElementBase> GenerateColumnElement(const RColumnElementBase::RIdentifier &elementId);
0141 
0142 template <typename CppT>
0143 std::unique_ptr<RColumnElementBase> RColumnElementBase::Generate(ROOT::ENTupleColumnType onDiskType)
0144 {
0145    return GenerateColumnElement(std::type_index(typeid(CppT)), onDiskType);
0146 }
0147 
0148 template <>
0149 std::unique_ptr<RColumnElementBase> RColumnElementBase::Generate<void>(ROOT::ENTupleColumnType onDiskType);
0150 
0151 } // namespace ROOT::Internal
0152 
0153 #endif