Logo ROOT   6.30.04
Reference Guide
 All Namespaces Files Pages
RColumnElement.hxx
Go to the documentation of this file.
1 /// \file ROOT/RColumnElement.hxx
2 /// \ingroup NTuple ROOT7
3 /// \author Jakob Blomer <jblomer@cern.ch>
4 /// \date 2018-10-09
5 /// \warning This is part of the ROOT 7 prototype! It will change without notice. It might trigger earthquakes. Feedback
6 /// is welcome!
7 
8 /*************************************************************************
9  * Copyright (C) 1995-2019, Rene Brun and Fons Rademakers. *
10  * All rights reserved. *
11  * *
12  * For the licensing terms see $ROOTSYS/LICENSE. *
13  * For the list of contributors see $ROOTSYS/README/CREDITS. *
14  *************************************************************************/
15 
16 #ifndef ROOT7_RColumnElement
17 #define ROOT7_RColumnElement
18 
19 #include <ROOT/RColumnModel.hxx>
20 #include <ROOT/RNTupleUtil.hxx>
21 
22 #include <TError.h>
23 
24 #include <cstring> // for memcpy
25 #include <cstdint>
26 #include <type_traits>
27 
28 namespace ROOT {
29 namespace Experimental {
30 
31 namespace Detail {
32 
33 // clang-format off
34 /**
35 \class ROOT::Experimental::Detail::RColumnElement
36 \ingroup NTuple
37 \brief A column element points either to the content of an RFieldValue or into a memory mapped page.
38 
39 The content pointed to by fRawContent can be a single element or the first element of an array.
40 Usually the on-disk element should map bitwise to the in-memory element. Sometimes that's not the case
41 though, for instance on big endian platforms and for exotic physical columns like 8 bit float.
42 
43 This class does not provide protection around the raw pointer, fRawContent has to be managed correctly
44 by the user of this class.
45 */
46 // clang-format on
47 class RColumnElementBase {
48 protected:
49  /// Points to valid C++ data, either a single value or an array of values
50  void* fRawContent;
51  /// Size of the C++ value pointed to by fRawContent (not necessarily equal to the on-disk element size)
52  std::size_t fSize;
53 
54 public:
55  RColumnElementBase()
56  : fRawContent(nullptr)
57  , fSize(0)
58  {}
59  RColumnElementBase(void *rawContent, std::size_t size) : fRawContent(rawContent), fSize(size)
60  {}
61  RColumnElementBase(const RColumnElementBase &elemArray, std::size_t at)
62  : fRawContent(static_cast<unsigned char *>(elemArray.fRawContent) + elemArray.fSize * at)
63  , fSize(elemArray.fSize)
64  {}
65  RColumnElementBase(const RColumnElementBase& other) = default;
66  RColumnElementBase(RColumnElementBase&& other) = default;
67  RColumnElementBase& operator =(const RColumnElementBase& other) = delete;
68  RColumnElementBase& operator =(RColumnElementBase&& other) = default;
69  virtual ~RColumnElementBase() = default;
70 
71  static RColumnElementBase Generate(EColumnType type);
72 
73  /// Write one or multiple column elements into destination
74  void WriteTo(void *destination, std::size_t count) const {
75  std::memcpy(destination, fRawContent, fSize * count);
76  }
77 
78  /// Set the column element or an array of elements from the memory location source
79  void ReadFrom(void *source, std::size_t count) {
80  std::memcpy(fRawContent, source, fSize * count);
81  }
82 
83  /// Derived, typed classes tell whether the on-storage layout is bitwise identical to the memory layout
84  virtual bool IsMappable() const { R__ASSERT(false); return false; }
85  virtual std::size_t GetBitsOnStorage() const { R__ASSERT(false); return 0; }
86 
87  /// If the on-storage layout and the in-memory layout differ, packing creates an on-disk page from an in-memory page
88  virtual void Pack(void *destination, void *source, std::size_t count) const
89  {
90  std::memcpy(destination, source, count);
91  }
92 
93  /// If the on-storage layout and the in-memory layout differ, unpacking creates a memory page from an on-storage page
94  virtual void Unpack(void *destination, void *source, std::size_t count) const
95  {
96  std::memcpy(destination, source, count);
97  }
98 
99  void *GetRawContent() const { return fRawContent; }
100  std::size_t GetSize() const { return fSize; }
101 };
102 
103 /**
104  * Pairs of C++ type and column type, like float and EColumnType::kReal32
105  */
106 template <typename CppT, EColumnType ColumnT>
107 class RColumnElement : public RColumnElementBase {
108 public:
109  explicit RColumnElement(CppT* value) : RColumnElementBase(value, sizeof(CppT))
110  {
111  // Do not allow this template to be instantiated unless there is a specialization. The assert needs to depend
112  // on the template type or else the static_assert will always fire.
113  static_assert(sizeof(CppT) != sizeof(CppT), "No column mapping for this C++ type");
114  }
115 };
116 
117 
118 template <>
119 class RColumnElement<float, EColumnType::kReal32> : public RColumnElementBase {
120 public:
121  static constexpr bool kIsMappable = true;
122  static constexpr std::size_t kSize = sizeof(float);
123  static constexpr std::size_t kBitsOnStorage = kSize * 8;
124  explicit RColumnElement(float *value) : RColumnElementBase(value, kSize) {}
125  bool IsMappable() const final { return kIsMappable; }
126  std::size_t GetBitsOnStorage() const final { return kBitsOnStorage; }
127 };
128 
129 template <>
130 class RColumnElement<double, EColumnType::kReal64> : public RColumnElementBase {
131 public:
132  static constexpr bool kIsMappable = true;
133  static constexpr std::size_t kSize = sizeof(double);
134  static constexpr std::size_t kBitsOnStorage = kSize * 8;
135  explicit RColumnElement(double *value) : RColumnElementBase(value, kSize) {}
136  bool IsMappable() const final { return kIsMappable; }
137  std::size_t GetBitsOnStorage() const final { return kBitsOnStorage; }
138 };
139 
140 template <>
141 class RColumnElement<std::uint8_t, EColumnType::kByte> : public RColumnElementBase {
142 public:
143  static constexpr bool kIsMappable = true;
144  static constexpr std::size_t kSize = sizeof(std::uint8_t);
145  static constexpr std::size_t kBitsOnStorage = kSize * 8;
146  explicit RColumnElement(std::uint8_t *value) : RColumnElementBase(value, kSize) {}
147  bool IsMappable() const final { return kIsMappable; }
148  std::size_t GetBitsOnStorage() const final { return kBitsOnStorage; }
149 };
150 
151 template <>
152 class RColumnElement<std::int32_t, EColumnType::kInt32> : public RColumnElementBase {
153 public:
154  static constexpr bool kIsMappable = true;
155  static constexpr std::size_t kSize = sizeof(std::int32_t);
156  static constexpr std::size_t kBitsOnStorage = kSize * 8;
157  explicit RColumnElement(std::int32_t *value) : RColumnElementBase(value, kSize) {}
158  bool IsMappable() const final { return kIsMappable; }
159  std::size_t GetBitsOnStorage() const final { return kBitsOnStorage; }
160 };
161 
162 template <>
163 class RColumnElement<std::uint32_t, EColumnType::kInt32> : public RColumnElementBase {
164 public:
165  static constexpr bool kIsMappable = true;
166  static constexpr std::size_t kSize = sizeof(std::uint32_t);
167  static constexpr std::size_t kBitsOnStorage = kSize * 8;
168  explicit RColumnElement(std::uint32_t *value) : RColumnElementBase(value, kSize) {}
169  bool IsMappable() const final { return kIsMappable; }
170  std::size_t GetBitsOnStorage() const final { return kBitsOnStorage; }
171 };
172 
173 template <>
174 class RColumnElement<std::int64_t, EColumnType::kInt64> : public RColumnElementBase {
175 public:
176  static constexpr bool kIsMappable = true;
177  static constexpr std::size_t kSize = sizeof(std::int64_t);
178  static constexpr std::size_t kBitsOnStorage = kSize * 8;
179  explicit RColumnElement(std::int64_t *value) : RColumnElementBase(value, kSize) {}
180  bool IsMappable() const final { return kIsMappable; }
181  std::size_t GetBitsOnStorage() const final { return kBitsOnStorage; }
182 };
183 
184 template <>
185 class RColumnElement<std::uint64_t, EColumnType::kInt64> : public RColumnElementBase {
186 public:
187  static constexpr bool kIsMappable = true;
188  static constexpr std::size_t kSize = sizeof(std::uint64_t);
189  static constexpr std::size_t kBitsOnStorage = kSize * 8;
190  explicit RColumnElement(std::uint64_t *value) : RColumnElementBase(value, kSize) {}
191  bool IsMappable() const final { return kIsMappable; }
192  std::size_t GetBitsOnStorage() const final { return kBitsOnStorage; }
193 };
194 
195 template <>
196 class RColumnElement<ClusterSize_t, EColumnType::kIndex> : public RColumnElementBase {
197 public:
198  static constexpr bool kIsMappable = true;
199  static constexpr std::size_t kSize = sizeof(ROOT::Experimental::ClusterSize_t);
200  static constexpr std::size_t kBitsOnStorage = kSize * 8;
201  explicit RColumnElement(ClusterSize_t *value) : RColumnElementBase(value, kSize) {}
202  bool IsMappable() const final { return kIsMappable; }
203  std::size_t GetBitsOnStorage() const final { return kBitsOnStorage; }
204 };
205 
206 template <>
207 class RColumnElement<RColumnSwitch, EColumnType::kSwitch> : public RColumnElementBase {
208 public:
209  static constexpr bool kIsMappable = true;
210  static constexpr std::size_t kSize = sizeof(ROOT::Experimental::RColumnSwitch);
211  static constexpr std::size_t kBitsOnStorage = kSize * 8;
212  explicit RColumnElement(RColumnSwitch *value) : RColumnElementBase(value, kSize) {}
213  bool IsMappable() const final { return kIsMappable; }
214  std::size_t GetBitsOnStorage() const final { return kBitsOnStorage; }
215 };
216 
217 template <>
218 class RColumnElement<char, EColumnType::kByte> : public RColumnElementBase {
219 public:
220  static constexpr bool kIsMappable = true;
221  static constexpr std::size_t kSize = sizeof(char);
222  static constexpr std::size_t kBitsOnStorage = kSize * 8;
223  explicit RColumnElement(char *value) : RColumnElementBase(value, kSize) {}
224  bool IsMappable() const final { return kIsMappable; }
225  std::size_t GetBitsOnStorage() const final { return kBitsOnStorage; }
226 };
227 
228 template <>
229 class RColumnElement<bool, EColumnType::kBit> : public RColumnElementBase {
230 public:
231  static constexpr bool kIsMappable = false;
232  static constexpr std::size_t kSize = sizeof(bool);
233  static constexpr std::size_t kBitsOnStorage = 1;
234  explicit RColumnElement(bool *value) : RColumnElementBase(value, kSize) {}
235  bool IsMappable() const final { return kIsMappable; }
236  std::size_t GetBitsOnStorage() const final { return kBitsOnStorage; }
237 
238  void Pack(void *dst, void *src, std::size_t count) const final;
239  void Unpack(void *dst, void *src, std::size_t count) const final;
240 };
241 
242 } // namespace Detail
243 } // namespace Experimental
244 } // namespace ROOT
245 
246 #endif