Logo ROOT  
Reference Guide
 
Loading...
Searching...
No Matches
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/RConfig.hxx>
21#include <ROOT/RError.hxx>
22#include <ROOT/RNTupleUtil.hxx>
23
24#include <Byteswap.h>
25#include <TError.h>
26
27#include <cstring> // for memcpy
28#include <cstdint>
29#include <memory>
30#include <string>
31#include <type_traits>
32#include <typeinfo>
33
34#ifndef R__LITTLE_ENDIAN
35#ifdef R__BYTESWAP
36// `R__BYTESWAP` is defined in RConfig.hxx for little-endian architectures; undefined otherwise
37#define R__LITTLE_ENDIAN 1
38#else
39#define R__LITTLE_ENDIAN 0
40#endif
41#endif /* R__LITTLE_ENDIAN */
42
43namespace {
44
45// In this namespace, common routines are defined for element packing and unpacking of ints and floats.
46// The following conversions and encodings exist:
47//
48// - Byteswap: on big endian machines, ints and floats are byte-swapped to the little endian on-disk format
49// - Cast: in-memory values can be stored in narrower on-disk columns. Currently without bounds checks.
50// For instance, for Double32_t, an in-memory double value is stored as a float on disk.
51// - Split: rearranges the bytes of an array of elements such that all the first bytes are stored first,
52// followed by all the second bytes, etc. This often clusters similar values, e.g. all the zero bytes
53// for arrays of small integers.
54// - Delta: Delta encoding stores on disk the delta to the previous element. This is useful for offsets,
55// because it transforms potentially large offset values into small deltas, which are then better
56// suited for split encoding.
57// - Zigzag: Zigzag encoding is used on signed integers only. It maps x to 2x if x is positive and to -(2x+1) if
58// x is negative. For series of positive and negative values of small absolute value, it will produce
59// a bit pattern that is favorable for split encoding.
60//
61// Encodings/conversions can be fused:
62//
63// - Delta/Zigzag + Splitting (there is no only-delta/zigzag encoding)
64// - (Delta/Zigzag + ) Splitting + Casting
65// - Everything + Byteswap
66
67/// \brief Copy and byteswap `count` elements of size `N` from `source` to `destination`.
68///
69/// Used on big-endian architectures for packing/unpacking elements whose column type requires
70/// a little-endian on-disk representation.
71template <std::size_t N>
72static void CopyBswap(void *destination, const void *source, std::size_t count)
73{
74 auto dst = reinterpret_cast<typename RByteSwap<N>::value_type *>(destination);
75 auto src = reinterpret_cast<const typename RByteSwap<N>::value_type *>(source);
76 for (std::size_t i = 0; i < count; ++i) {
77 dst[i] = RByteSwap<N>::bswap(src[i]);
78 }
79}
80
81/// Casts T to one of the ints used in RByteSwap and back to its original type, which may be float or double
82#if R__LITTLE_ENDIAN == 0
83template <typename T>
84void ByteSwapIfNecessary(T &value)
85{
86 constexpr auto N = sizeof(T);
87 using bswap_value_type = typename RByteSwap<N>::value_type;
88 void *valuePtr = &value;
89 auto swapped = RByteSwap<N>::bswap(*reinterpret_cast<bswap_value_type *>(valuePtr));
90 *reinterpret_cast<bswap_value_type *>(valuePtr) = swapped;
91}
92#else
93#define ByteSwapIfNecessary(x) ((void)0)
94#endif
95
96/// \brief Pack `count` elements into narrower (or wider) type
97///
98/// Used to convert in-memory elements to smaller column types of comatible types
99/// (e.g., double to float, int64 to int32). Takes care of byte swap if necessary.
100template <typename DestT, typename SourceT>
101static void CastPack(void *destination, const void *source, std::size_t count)
102{
103 static_assert(std::is_convertible_v<SourceT, DestT>);
104 auto dst = reinterpret_cast<DestT *>(destination);
105 auto src = reinterpret_cast<const SourceT *>(source);
106 for (std::size_t i = 0; i < count; ++i) {
107 dst[i] = src[i];
108 ByteSwapIfNecessary(dst[i]);
109 }
110}
111
112/// \brief Unpack `count` on-disk elements into wider (or narrower) in-memory array
113///
114/// Used to convert on-disk elements to larger C++ types of comatible types
115/// (e.g., float to double, int32 to int64). Takes care of byte swap if necessary.
116template <typename DestT, typename SourceT>
117static void CastUnpack(void *destination, const void *source, std::size_t count)
118{
119 auto dst = reinterpret_cast<DestT *>(destination);
120 auto src = reinterpret_cast<const SourceT *>(source);
121 for (std::size_t i = 0; i < count; ++i) {
122 SourceT val = src[i];
123 ByteSwapIfNecessary(val);
124 dst[i] = val;
125 }
126}
127
128/// \brief Split encoding of elements, possibly into narrower column
129///
130/// Used to first cast and then split-encode in-memory values to the on-disk column. Swap bytes if necessary.
131template <typename DestT, typename SourceT>
132static void CastSplitPack(void *destination, const void *source, std::size_t count)
133{
134 constexpr std::size_t N = sizeof(DestT);
135 auto splitArray = reinterpret_cast<char *>(destination);
136 auto src = reinterpret_cast<const SourceT *>(source);
137 for (std::size_t i = 0; i < count; ++i) {
138 DestT val = src[i];
139 ByteSwapIfNecessary(val);
140 for (std::size_t b = 0; b < N; ++b) {
141 splitArray[b * count + i] = reinterpret_cast<const char *>(&val)[b];
142 }
143 }
144}
145
146/// \brief Reverse split encoding of elements
147///
148/// Used to first unsplit a column, possibly storing elements in wider C++ types. Swaps bytes if necessary
149template <typename DestT, typename SourceT>
150static void CastSplitUnpack(void *destination, const void *source, std::size_t count)
151{
152 constexpr std::size_t N = sizeof(SourceT);
153 auto dst = reinterpret_cast<DestT *>(destination);
154 auto splitArray = reinterpret_cast<const char *>(source);
155 for (std::size_t i = 0; i < count; ++i) {
156 SourceT val = 0;
157 for (std::size_t b = 0; b < N; ++b) {
158 reinterpret_cast<char *>(&val)[b] = splitArray[b * count + i];
159 }
160 ByteSwapIfNecessary(val);
161 dst[i] = val;
162 }
163}
164
165/// \brief Packing of columns with delta + split encoding
166///
167/// Apply split encoding to delta-encoded values, currently used only for index columns
168template <typename DestT, typename SourceT>
169static void CastDeltaSplitPack(void *destination, const void *source, std::size_t count)
170{
171 constexpr std::size_t N = sizeof(DestT);
172 auto src = reinterpret_cast<const SourceT *>(source);
173 auto splitArray = reinterpret_cast<char *>(destination);
174 for (std::size_t i = 0; i < count; ++i) {
175 DestT val = (i == 0) ? src[0] : src[i] - src[i - 1];
176 ByteSwapIfNecessary(val);
177 for (std::size_t b = 0; b < N; ++b) {
178 splitArray[b * count + i] = reinterpret_cast<char *>(&val)[b];
179 }
180 }
181}
182
183/// \brief Unsplit and unwind delta encoding
184///
185/// Unsplit a column and reverse the delta encoding, currently used only for index columns
186template <typename DestT, typename SourceT>
187static void CastDeltaSplitUnpack(void *destination, const void *source, std::size_t count)
188{
189 constexpr std::size_t N = sizeof(SourceT);
190 auto splitArray = reinterpret_cast<const char *>(source);
191 auto dst = reinterpret_cast<DestT *>(destination);
192 for (std::size_t i = 0; i < count; ++i) {
193 SourceT val = 0;
194 for (std::size_t b = 0; b < N; ++b) {
195 reinterpret_cast<char *>(&val)[b] = splitArray[b * count + i];
196 }
197 ByteSwapIfNecessary(val);
198 dst[i] = (i == 0) ? val : dst[i - 1] + val;
199 }
200}
201
202/// \brief Packing of columns with zigzag + split encoding
203///
204/// Apply split encoding to zigzag-encoded values, used for signed integers
205template <typename DestT, typename SourceT>
206static void CastZigzagSplitPack(void *destination, const void *source, std::size_t count)
207{
208 using UDestT = std::make_unsigned_t<DestT>;
209 constexpr std::size_t kNBitsDestT = sizeof(DestT) * 8;
210 constexpr std::size_t N = sizeof(DestT);
211 auto src = reinterpret_cast<const SourceT *>(source);
212 auto splitArray = reinterpret_cast<char *>(destination);
213 for (std::size_t i = 0; i < count; ++i) {
214 UDestT val = (static_cast<DestT>(src[i]) << 1) ^ (static_cast<DestT>(src[i]) >> (kNBitsDestT - 1));
215 ByteSwapIfNecessary(val);
216 for (std::size_t b = 0; b < N; ++b) {
217 splitArray[b * count + i] = reinterpret_cast<char *>(&val)[b];
218 }
219 }
220}
221
222/// \brief Unsplit and unwind zigzag encoding
223///
224/// Unsplit a column and reverse the zigzag encoding, used for signed integer columns
225template <typename DestT, typename SourceT>
226static void CastZigzagSplitUnpack(void *destination, const void *source, std::size_t count)
227{
228 using USourceT = std::make_unsigned_t<SourceT>;
229 constexpr std::size_t N = sizeof(SourceT);
230 auto splitArray = reinterpret_cast<const char *>(source);
231 auto dst = reinterpret_cast<DestT *>(destination);
232 for (std::size_t i = 0; i < count; ++i) {
233 USourceT val = 0;
234 for (std::size_t b = 0; b < N; ++b) {
235 reinterpret_cast<char *>(&val)[b] = splitArray[b * count + i];
236 }
237 ByteSwapIfNecessary(val);
238 dst[i] = static_cast<SourceT>((val >> 1) ^ -(static_cast<SourceT>(val) & 1));
239 }
240}
241
242} // anonymous namespace
243
244namespace ROOT {
245namespace Experimental {
246
247namespace Detail {
248
249// clang-format off
250/**
251\class ROOT::Experimental::Detail::RColumnElementBase
252\ingroup NTuple
253\brief A column element encapsulates the translation between basic C++ types and their column representation.
254
255Usually the on-disk element should map bitwise to the in-memory element. Sometimes that's not the case
256though, for instance on big endian platforms or for bools.
257
258There is a template specialization for every valid pair of C++ type and column representation.
259These specialized child classes are responsible for overriding `Pack()` / `Unpack()` for packing / unpacking elements
260as appropriate.
261*/
262// clang-format on
264protected:
265 /// Size of the C++ value that corresponds to the on-disk element
266 std::size_t fSize;
267
268 explicit RColumnElementBase(std::size_t size) : fSize(size) {}
269
270public:
271 RColumnElementBase(const RColumnElementBase& other) = default;
275 virtual ~RColumnElementBase() = default;
276
277 /// If CppT == void, use the default C++ type for the given column type
278 template <typename CppT = void>
279 static std::unique_ptr<RColumnElementBase> Generate(EColumnType type);
280 static std::size_t GetBitsOnStorage(EColumnType type);
281 static std::string GetTypeName(EColumnType type);
282
283 /// Derived, typed classes tell whether the on-storage layout is bitwise identical to the memory layout
284 virtual bool IsMappable() const { R__ASSERT(false); return false; }
285 virtual std::size_t GetBitsOnStorage() const { R__ASSERT(false); return 0; }
286
287 /// If the on-storage layout and the in-memory layout differ, packing creates an on-disk page from an in-memory page
288 virtual void Pack(void *destination, void *source, std::size_t count) const
289 {
290 std::memcpy(destination, source, count);
291 }
292
293 /// If the on-storage layout and the in-memory layout differ, unpacking creates a memory page from an on-storage page
294 virtual void Unpack(void *destination, void *source, std::size_t count) const
295 {
296 std::memcpy(destination, source, count);
297 }
298
299 std::size_t GetSize() const { return fSize; }
300 std::size_t GetPackedSize(std::size_t nElements = 1U) const { return (nElements * GetBitsOnStorage() + 7) / 8; }
301};
302
303/**
304 * Base class for columns whose on-storage representation is little-endian.
305 * The implementation of `Pack` and `Unpack` takes care of byteswap if the memory page is big-endian.
306 */
307template <typename CppT>
309protected:
310 explicit RColumnElementLE(std::size_t size) : RColumnElementBase(size) {}
311
312public:
313 static constexpr bool kIsMappable = (R__LITTLE_ENDIAN == 1);
314
315 void Pack(void *dst, void *src, std::size_t count) const final
316 {
317#if R__LITTLE_ENDIAN == 1
318 RColumnElementBase::Pack(dst, src, count);
319#else
320 CopyBswap<sizeof(CppT)>(dst, src, count);
321#endif
322 }
323 void Unpack(void *dst, void *src, std::size_t count) const final
324 {
325#if R__LITTLE_ENDIAN == 1
326 RColumnElementBase::Unpack(dst, src, count);
327#else
328 CopyBswap<sizeof(CppT)>(dst, src, count);
329#endif
330 }
331}; // class RColumnElementLE
332
333/**
334 * Base class for columns storing elements of wider in-memory types,
335 * such as 64bit in-memory offsets to Index32 columns.
336 */
337template <typename CppT, typename NarrowT>
339protected:
341
342public:
343 static constexpr bool kIsMappable = false;
344
345 void Pack(void *dst, void *src, std::size_t count) const final { CastPack<NarrowT, CppT>(dst, src, count); }
346 void Unpack(void *dst, void *src, std::size_t count) const final { CastUnpack<CppT, NarrowT>(dst, src, count); }
347}; // class RColumnElementCastLE
348
349/**
350 * Base class for split columns whose on-storage representation is little-endian.
351 * The implementation of `Pack` and `Unpack` takes care of splitting and, if necessary, byteswap.
352 * As part of the splitting, can also narrow down the type to NarrowT.
353 */
354template <typename CppT, typename NarrowT>
356protected:
358
359public:
360 static constexpr bool kIsMappable = false;
361
362 void Pack(void *dst, void *src, std::size_t count) const final { CastSplitPack<NarrowT, CppT>(dst, src, count); }
363 void Unpack(void *dst, void *src, std::size_t count) const final { CastSplitUnpack<CppT, NarrowT>(dst, src, count); }
364}; // class RColumnElementSplitLE
365
366/**
367 * Base class for delta + split columns (index columns) whose on-storage representation is little-endian.
368 * The implementation of `Pack` and `Unpack` takes care of splitting and, if necessary, byteswap.
369 * As part of the encoding, can also narrow down the type to NarrowT.
370 */
371template <typename CppT, typename NarrowT>
373protected:
375
376public:
377 static constexpr bool kIsMappable = false;
378
379 void Pack(void *dst, void *src, std::size_t count) const final
380 {
381 CastDeltaSplitPack<NarrowT, CppT>(dst, src, count);
382 }
383 void Unpack(void *dst, void *src, std::size_t count) const final
384 {
385 CastDeltaSplitUnpack<CppT, NarrowT>(dst, src, count);
386 }
387}; // class RColumnElementDeltaSplitLE
388
389/**
390 * Base class for zigzag + split columns (signed integer columns) whose on-storage representation is little-endian.
391 * The implementation of `Pack` and `Unpack` takes care of splitting and, if necessary, byteswap.
392 * The NarrowT target type should be an signed integer, which can be smaller than the CppT source type.
393 */
394template <typename CppT, typename NarrowT>
396protected:
398
399public:
400 static constexpr bool kIsMappable = false;
401
402 void Pack(void *dst, void *src, std::size_t count) const final
403 {
404 CastZigzagSplitPack<NarrowT, CppT>(dst, src, count);
405 }
406 void Unpack(void *dst, void *src, std::size_t count) const final
407 {
408 CastZigzagSplitUnpack<CppT, NarrowT>(dst, src, count);
409 }
410}; // class RColumnElementZigzagSplitLE
411
412////////////////////////////////////////////////////////////////////////////////
413// Pairs of C++ type and column type, like float and EColumnType::kReal32
414////////////////////////////////////////////////////////////////////////////////
415
416////////////////////////////////////////////////////////////////////////////////
417// Part 1: C++ type --> unknown column type
418////////////////////////////////////////////////////////////////////////////////
419
420template <typename CppT, EColumnType ColumnT = EColumnType::kUnknown>
422public:
424 {
425 throw RException(R__FAIL(std::string("internal error: no column mapping for this C++ type: ") +
426 typeid(CppT).name() + " --> " + GetTypeName(ColumnT)));
427 }
428};
429
430template <>
432public:
433 static constexpr std::size_t kSize = sizeof(bool);
435};
436
437template <>
439public:
440 static constexpr std::size_t kSize = sizeof(char);
442};
443
444template <>
445class RColumnElement<std::int8_t, EColumnType::kUnknown> : public RColumnElementBase {
446public:
447 static constexpr std::size_t kSize = sizeof(std::int8_t);
448 RColumnElement() : RColumnElementBase(kSize) {}
449};
450
451template <>
452class RColumnElement<std::uint8_t, EColumnType::kUnknown> : public RColumnElementBase {
453public:
454 static constexpr std::size_t kSize = sizeof(std::uint8_t);
455 RColumnElement() : RColumnElementBase(kSize) {}
456};
457
458template <>
459class RColumnElement<std::int16_t, EColumnType::kUnknown> : public RColumnElementBase {
460public:
461 static constexpr std::size_t kSize = sizeof(std::int16_t);
463};
464
465template <>
466class RColumnElement<std::uint16_t, EColumnType::kUnknown> : public RColumnElementBase {
467public:
468 static constexpr std::size_t kSize = sizeof(std::uint16_t);
470};
471
472template <>
473class RColumnElement<std::int32_t, EColumnType::kUnknown> : public RColumnElementBase {
474public:
475 static constexpr std::size_t kSize = sizeof(std::int32_t);
477};
478
479template <>
480class RColumnElement<std::uint32_t, EColumnType::kUnknown> : public RColumnElementBase {
481public:
482 static constexpr std::size_t kSize = sizeof(std::uint32_t);
484};
485
486template <>
487class RColumnElement<std::int64_t, EColumnType::kUnknown> : public RColumnElementBase {
488public:
489 static constexpr std::size_t kSize = sizeof(std::int64_t);
491};
492
493template <>
494class RColumnElement<std::uint64_t, EColumnType::kUnknown> : public RColumnElementBase {
495public:
496 static constexpr std::size_t kSize = sizeof(std::uint64_t);
498};
499
500template <>
502public:
503 static constexpr std::size_t kSize = sizeof(float);
505};
506
507template <>
509public:
510 static constexpr std::size_t kSize = sizeof(double);
512};
513
514template <>
516public:
517 static constexpr std::size_t kSize = sizeof(ClusterSize_t);
519};
520
521template <>
523public:
524 static constexpr std::size_t kSize = sizeof(RColumnSwitch);
526};
527
528////////////////////////////////////////////////////////////////////////////////
529// Part 2: C++ type --> supported column representations,
530// ordered by C++ type
531////////////////////////////////////////////////////////////////////////////////
532
533template <>
535public:
536 static constexpr bool kIsMappable = false;
537 static constexpr std::size_t kSize = sizeof(ROOT::Experimental::RColumnSwitch);
538 static constexpr std::size_t kBitsOnStorage = 64;
540 bool IsMappable() const final { return kIsMappable; }
541 std::size_t GetBitsOnStorage() const final { return kBitsOnStorage; }
542
543 void Pack(void *dst, void *src, std::size_t count) const final
544 {
545 auto srcArray = reinterpret_cast<ROOT::Experimental::RColumnSwitch *>(src);
546 auto uint64Array = reinterpret_cast<std::uint64_t *>(dst);
547 for (std::size_t i = 0; i < count; ++i) {
548 uint64Array[i] =
549 (static_cast<std::uint64_t>(srcArray[i].GetTag()) << 44) | (srcArray[i].GetIndex() & 0x0fffffffffff);
550#if R__LITTLE_ENDIAN == 0
551 uint64Array[i] = RByteSwap<8>::bswap(uint64Array[i]);
552#endif
553 }
554 }
555
556 void Unpack(void *dst, void *src, std::size_t count) const final
557 {
558 auto uint64Array = reinterpret_cast<std::uint64_t *>(src);
559 auto dstArray = reinterpret_cast<ROOT::Experimental::RColumnSwitch *>(dst);
560 for (std::size_t i = 0; i < count; ++i) {
561#if R__LITTLE_ENDIAN == 1
562 const auto value = uint64Array[i];
563#else
564 const auto value = RByteSwap<8>::bswap(uint64Array[i]);
565#endif
567 ClusterSize_t{static_cast<RClusterSize::ValueType>(value & 0x0fffffffffff)}, (value >> 44));
568 }
569 }
570};
571
572template <>
574public:
575 static constexpr bool kIsMappable = false;
576 static constexpr std::size_t kSize = sizeof(bool);
577 static constexpr std::size_t kBitsOnStorage = 1;
579 bool IsMappable() const final { return kIsMappable; }
580 std::size_t GetBitsOnStorage() const final { return kBitsOnStorage; }
581
582 void Pack(void *dst, void *src, std::size_t count) const final;
583 void Unpack(void *dst, void *src, std::size_t count) const final;
584};
585
586#define __RCOLUMNELEMENT_SPEC_BODY(CppT, BaseT, BitsOnStorage) \
587 static constexpr std::size_t kSize = sizeof(CppT); \
588 static constexpr std::size_t kBitsOnStorage = BitsOnStorage; \
589 RColumnElement() : BaseT(kSize) {} \
590 bool IsMappable() const final \
591 { \
592 return kIsMappable; \
593 } \
594 std::size_t GetBitsOnStorage() const final \
595 { \
596 return kBitsOnStorage; \
597 }
598/// These macros are used to declare `RColumnElement` template specializations below. Additional arguments can be used
599/// to forward template parameters to the base class, e.g.
600/// ```
601/// DECLARE_RCOLUMNELEMENT_SPEC(std::int64_t, EColumnType::kInt32, 32,
602/// RColumnElementCastLE, <std::int64_t, std::int32_t>);
603/// ```
604#define DECLARE_RCOLUMNELEMENT_SPEC(CppT, ColumnT, BitsOnStorage, BaseT, ...) \
605 template <> \
606 class RColumnElement<CppT, ColumnT> : public BaseT __VA_ARGS__ { \
607 public: \
608 __RCOLUMNELEMENT_SPEC_BODY(CppT, BaseT, BitsOnStorage) \
609 }
610#define DECLARE_RCOLUMNELEMENT_SPEC_SIMPLE(CppT, ColumnT, BitsOnStorage) \
611 template <> \
612 class RColumnElement<CppT, ColumnT> : public RColumnElementBase { \
613 public: \
614 static constexpr bool kIsMappable = true; \
615 __RCOLUMNELEMENT_SPEC_BODY(CppT, RColumnElementBase, BitsOnStorage) \
616 }
617
620
624
628
629DECLARE_RCOLUMNELEMENT_SPEC(std::int16_t, EColumnType::kInt16, 16, RColumnElementLE, <std::int16_t>);
630DECLARE_RCOLUMNELEMENT_SPEC(std::int16_t, EColumnType::kUInt16, 16, RColumnElementLE, <std::int16_t>);
632 <std::int16_t, std::int16_t>);
634 <std::int16_t, std::uint16_t>);
635
636DECLARE_RCOLUMNELEMENT_SPEC(std::uint16_t, EColumnType::kUInt16, 16, RColumnElementLE, <std::uint16_t>);
637DECLARE_RCOLUMNELEMENT_SPEC(std::uint16_t, EColumnType::kInt16, 16, RColumnElementLE, <std::uint16_t>);
639 <std::uint16_t, std::uint16_t>);
641 <std::uint16_t, std::int16_t>);
642
643DECLARE_RCOLUMNELEMENT_SPEC(std::int32_t, EColumnType::kInt32, 32, RColumnElementLE, <std::int32_t>);
644DECLARE_RCOLUMNELEMENT_SPEC(std::int32_t, EColumnType::kUInt32, 32, RColumnElementLE, <std::int32_t>);
646 <std::int32_t, std::int32_t>);
648 <std::int32_t, std::uint32_t>);
649
650DECLARE_RCOLUMNELEMENT_SPEC(std::uint32_t, EColumnType::kUInt32, 32, RColumnElementLE, <std::uint32_t>);
651DECLARE_RCOLUMNELEMENT_SPEC(std::uint32_t, EColumnType::kInt32, 32, RColumnElementLE, <std::uint32_t>);
653 <std::uint32_t, std::uint32_t>);
655 <std::uint32_t, std::int32_t>);
656
657DECLARE_RCOLUMNELEMENT_SPEC(std::int64_t, EColumnType::kInt64, 64, RColumnElementLE, <std::int64_t>);
658DECLARE_RCOLUMNELEMENT_SPEC(std::int64_t, EColumnType::kUInt64, 64, RColumnElementLE, <std::int64_t>);
660 <std::int64_t, std::int64_t>);
662 <std::int64_t, std::uint64_t>);
663DECLARE_RCOLUMNELEMENT_SPEC(std::int64_t, EColumnType::kInt32, 32, RColumnElementCastLE, <std::int64_t, std::int32_t>);
665 <std::int64_t, std::uint32_t>);
667 <std::int64_t, std::int32_t>);
669 <std::int64_t, std::uint32_t>);
670
671DECLARE_RCOLUMNELEMENT_SPEC(std::uint64_t, EColumnType::kUInt64, 64, RColumnElementLE, <std::uint64_t>);
672DECLARE_RCOLUMNELEMENT_SPEC(std::uint64_t, EColumnType::kInt64, 64, RColumnElementLE, <std::uint64_t>);
674 <std::uint64_t, std::uint64_t>);
676 <std::uint64_t, std::int64_t>);
677
680
685
688 <std::uint64_t, std::uint32_t>);
690 <std::uint64_t, std::uint64_t>);
692 <std::uint64_t, std::uint32_t>);
693
694template <typename CppT>
695std::unique_ptr<RColumnElementBase> RColumnElementBase::Generate(EColumnType type)
696{
697 switch (type) {
698 case EColumnType::kIndex64: return std::make_unique<RColumnElement<CppT, EColumnType::kIndex64>>();
699 case EColumnType::kIndex32: return std::make_unique<RColumnElement<CppT, EColumnType::kIndex32>>();
700 case EColumnType::kSwitch: return std::make_unique<RColumnElement<CppT, EColumnType::kSwitch>>();
701 case EColumnType::kByte: return std::make_unique<RColumnElement<CppT, EColumnType::kByte>>();
702 case EColumnType::kChar: return std::make_unique<RColumnElement<CppT, EColumnType::kChar>>();
703 case EColumnType::kBit: return std::make_unique<RColumnElement<CppT, EColumnType::kBit>>();
704 case EColumnType::kReal64: return std::make_unique<RColumnElement<CppT, EColumnType::kReal64>>();
705 case EColumnType::kReal32: return std::make_unique<RColumnElement<CppT, EColumnType::kReal32>>();
706 case EColumnType::kInt64: return std::make_unique<RColumnElement<CppT, EColumnType::kInt64>>();
707 case EColumnType::kUInt64: return std::make_unique<RColumnElement<CppT, EColumnType::kUInt64>>();
708 case EColumnType::kInt32: return std::make_unique<RColumnElement<CppT, EColumnType::kInt32>>();
709 case EColumnType::kUInt32: return std::make_unique<RColumnElement<CppT, EColumnType::kUInt32>>();
710 case EColumnType::kInt16: return std::make_unique<RColumnElement<CppT, EColumnType::kInt16>>();
711 case EColumnType::kUInt16: return std::make_unique<RColumnElement<CppT, EColumnType::kUInt16>>();
712 case EColumnType::kInt8: return std::make_unique<RColumnElement<CppT, EColumnType::kInt8>>();
713 case EColumnType::kUInt8: return std::make_unique<RColumnElement<CppT, EColumnType::kUInt8>>();
714 case EColumnType::kSplitIndex64: return std::make_unique<RColumnElement<CppT, EColumnType::kSplitIndex64>>();
715 case EColumnType::kSplitIndex32: return std::make_unique<RColumnElement<CppT, EColumnType::kSplitIndex32>>();
716 case EColumnType::kSplitReal64: return std::make_unique<RColumnElement<CppT, EColumnType::kSplitReal64>>();
717 case EColumnType::kSplitReal32: return std::make_unique<RColumnElement<CppT, EColumnType::kSplitReal32>>();
718 case EColumnType::kSplitInt64: return std::make_unique<RColumnElement<CppT, EColumnType::kSplitInt64>>();
719 case EColumnType::kSplitUInt64: return std::make_unique<RColumnElement<CppT, EColumnType::kSplitUInt64>>();
720 case EColumnType::kSplitInt32: return std::make_unique<RColumnElement<CppT, EColumnType::kSplitInt32>>();
721 case EColumnType::kSplitUInt32: return std::make_unique<RColumnElement<CppT, EColumnType::kSplitUInt32>>();
722 case EColumnType::kSplitInt16: return std::make_unique<RColumnElement<CppT, EColumnType::kSplitInt16>>();
723 case EColumnType::kSplitUInt16: return std::make_unique<RColumnElement<CppT, EColumnType::kSplitUInt16>>();
724 default: R__ASSERT(false);
725 }
726 // never here
727 return nullptr;
728}
729
730template <>
731std::unique_ptr<RColumnElementBase> RColumnElementBase::Generate<void>(EColumnType type);
732
733} // namespace Detail
734} // namespace Experimental
735} // namespace ROOT
736
737#endif
#define R__LITTLE_ENDIAN
#define DECLARE_RCOLUMNELEMENT_SPEC_SIMPLE(CppT, ColumnT, BitsOnStorage)
#define DECLARE_RCOLUMNELEMENT_SPEC(CppT, ColumnT, BitsOnStorage, BaseT,...)
These macros are used to declare RColumnElement template specializations below.
#define R__FAIL(msg)
Short-hand to return an RResult<T> in an error state; the RError is implicitly converted into RResult...
Definition RError.hxx:303
#define b(i)
Definition RSha256.hxx:100
size_t size(const MatrixT &matrix)
retrieve the size of a square matrix
#define R__ASSERT(e)
Definition TError.h:118
#define N
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void value
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t src
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t Float_t Float_t Int_t Int_t UInt_t UInt_t Rectangle_t Int_t Int_t Window_t TString Int_t GCValues_t GetPrimarySelectionOwner GetDisplay GetScreen GetColormap GetNativeEvent const char const char dpyName wid window const char font_name cursor keysym reg const char only_if_exist regb h Point_t winding char text const char depth char const char Int_t count const char ColorStruct_t color const char Pixmap_t Pixmap_t PictureAttributes_t attr const char char ret_data h unsigned char height h Atom_t Int_t ULong_t ULong_t unsigned char prop_list Atom_t Atom_t Atom_t Time_t type
char name[80]
Definition TGX11.cxx:110
@ kSize
Definition TStructNode.h:26
A column element encapsulates the translation between basic C++ types and their column representation...
virtual void Pack(void *destination, void *source, std::size_t count) const
If the on-storage layout and the in-memory layout differ, packing creates an on-disk page from an in-...
RColumnElementBase(RColumnElementBase &&other)=default
virtual bool IsMappable() const
Derived, typed classes tell whether the on-storage layout is bitwise identical to the memory layout.
std::size_t GetPackedSize(std::size_t nElements=1U) const
RColumnElementBase(const RColumnElementBase &other)=default
RColumnElementBase & operator=(const RColumnElementBase &other)=delete
std::size_t fSize
Size of the C++ value that corresponds to the on-disk element.
static std::string GetTypeName(EColumnType type)
virtual void Unpack(void *destination, void *source, std::size_t count) const
If the on-storage layout and the in-memory layout differ, unpacking creates a memory page from an on-...
static std::unique_ptr< RColumnElementBase > Generate(EColumnType type)
If CppT == void, use the default C++ type for the given column type.
Base class for columns storing elements of wider in-memory types, such as 64bit in-memory offsets to ...
void Pack(void *dst, void *src, std::size_t count) const final
If the on-storage layout and the in-memory layout differ, packing creates an on-disk page from an in-...
void Unpack(void *dst, void *src, std::size_t count) const final
If the on-storage layout and the in-memory layout differ, unpacking creates a memory page from an on-...
Base class for delta + split columns (index columns) whose on-storage representation is little-endian...
void Unpack(void *dst, void *src, std::size_t count) const final
If the on-storage layout and the in-memory layout differ, unpacking creates a memory page from an on-...
void Pack(void *dst, void *src, std::size_t count) const final
If the on-storage layout and the in-memory layout differ, packing creates an on-disk page from an in-...
Base class for columns whose on-storage representation is little-endian.
void Pack(void *dst, void *src, std::size_t count) const final
If the on-storage layout and the in-memory layout differ, packing creates an on-disk page from an in-...
void Unpack(void *dst, void *src, std::size_t count) const final
If the on-storage layout and the in-memory layout differ, unpacking creates a memory page from an on-...
Base class for split columns whose on-storage representation is little-endian.
void Pack(void *dst, void *src, std::size_t count) const final
If the on-storage layout and the in-memory layout differ, packing creates an on-disk page from an in-...
void Unpack(void *dst, void *src, std::size_t count) const final
If the on-storage layout and the in-memory layout differ, unpacking creates a memory page from an on-...
Base class for zigzag + split columns (signed integer columns) whose on-storage representation is lit...
void Pack(void *dst, void *src, std::size_t count) const final
If the on-storage layout and the in-memory layout differ, packing creates an on-disk page from an in-...
void Unpack(void *dst, void *src, std::size_t count) const final
If the on-storage layout and the in-memory layout differ, unpacking creates a memory page from an on-...
void Pack(void *dst, void *src, std::size_t count) const final
If the on-storage layout and the in-memory layout differ, packing creates an on-disk page from an in-...
bool IsMappable() const final
Derived, typed classes tell whether the on-storage layout is bitwise identical to the memory layout.
void Unpack(void *dst, void *src, std::size_t count) const final
If the on-storage layout and the in-memory layout differ, unpacking creates a memory page from an on-...
void Unpack(void *dst, void *src, std::size_t count) const final
If the on-storage layout and the in-memory layout differ, unpacking creates a memory page from an on-...
void Pack(void *dst, void *src, std::size_t count) const final
If the on-storage layout and the in-memory layout differ, packing creates an on-disk page from an in-...
bool IsMappable() const final
Derived, typed classes tell whether the on-storage layout is bitwise identical to the memory layout.
Holds the index and the tag of a kSwitch column.
Base class for all ROOT issued exceptions.
Definition RError.hxx:78
RClusterSize ClusterSize_t
This file contains a specialised ROOT message handler to test for diagnostic in unit tests.
Helper templated class for swapping bytes; specializations for N={2,4,8} are provided below.
Definition Byteswap.h:124
Wrap the integer in a struct in order to avoid template specialization clash with std::uint32_t.