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//
58// Encodings/conversions can be fused:
59//
60// - Delta + Splitting (there is no only-delta encoding)
61// - (Delta + ) Splitting + Casting
62// - Everything + Byteswap
63
64/// \brief Copy and byteswap `count` elements of size `N` from `source` to `destination`.
65///
66/// Used on big-endian architectures for packing/unpacking elements whose column type requires
67/// a little-endian on-disk representation.
68template <std::size_t N>
69static void CopyBswap(void *destination, const void *source, std::size_t count)
70{
71 auto dst = reinterpret_cast<typename RByteSwap<N>::value_type *>(destination);
72 auto src = reinterpret_cast<const typename RByteSwap<N>::value_type *>(source);
73 for (std::size_t i = 0; i < count; ++i) {
74 dst[i] = RByteSwap<N>::bswap(src[i]);
75 }
76}
77
78/// Casts T to one of the ints used in RByteSwap and back to its original type, which may be float or double
79#if R__LITTLE_ENDIAN == 0
80template <typename T>
81void ByteSwapIfNecessary(T &value)
82{
83 constexpr auto N = sizeof(T);
84 using bswap_value_type = typename RByteSwap<N>::value_type;
85 void *valuePtr = &value;
86 auto swapped = RByteSwap<N>::bswap(*reinterpret_cast<bswap_value_type *>(valuePtr));
87 *reinterpret_cast<bswap_value_type *>(valuePtr) = swapped;
88}
89#else
90#define ByteSwapIfNecessary(x) ((void)0)
91#endif
92
93/// \brief Pack `count` elements into narrower (or wider) type
94///
95/// Used to convert in-memory elements to smaller column types of comatible types
96/// (e.g., double to float, int64 to int32). Takes care of byte swap if necessary.
97template <typename DestT, typename SourceT>
98static void CastPack(void *destination, const void *source, std::size_t count)
99{
100 static_assert(std::is_convertible_v<SourceT, DestT>);
101 auto dst = reinterpret_cast<DestT *>(destination);
102 auto src = reinterpret_cast<const SourceT *>(source);
103 for (std::size_t i = 0; i < count; ++i) {
104 dst[i] = src[i];
105 ByteSwapIfNecessary(dst[i]);
106 }
107}
108
109/// \brief Unpack `count` on-disk elements into wider (or narrower) in-memory array
110///
111/// Used to convert on-disk elements to larger C++ types of comatible types
112/// (e.g., float to double, int32 to int64). Takes care of byte swap if necessary.
113template <typename DestT, typename SourceT>
114static void CastUnpack(void *destination, const void *source, std::size_t count)
115{
116 auto dst = reinterpret_cast<DestT *>(destination);
117 auto src = reinterpret_cast<const SourceT *>(source);
118 for (std::size_t i = 0; i < count; ++i) {
119 SourceT val = src[i];
120 ByteSwapIfNecessary(val);
121 dst[i] = val;
122 }
123}
124
125/// \brief Split encoding of elements, possibly into narrower column
126///
127/// Used to first cast and then split-encode in-memory values to the on-disk column. Swap bytes if necessary.
128template <typename DestT, typename SourceT>
129static void CastSplitPack(void *destination, const void *source, std::size_t count)
130{
131 constexpr std::size_t N = sizeof(DestT);
132 auto splitArray = reinterpret_cast<char *>(destination);
133 auto src = reinterpret_cast<const SourceT *>(source);
134 for (std::size_t i = 0; i < count; ++i) {
135 DestT val = src[i];
136 ByteSwapIfNecessary(val);
137 for (std::size_t b = 0; b < N; ++b) {
138 splitArray[b * count + i] = reinterpret_cast<const char *>(&val)[b];
139 }
140 }
141}
142
143/// \brief Reverse split encoding of elements
144///
145/// Used to first unsplit a column, possibly storing elements in wider C++ types. Swaps bytes if necessary
146template <typename DestT, typename SourceT>
147static void CastSplitUnpack(void *destination, const void *source, std::size_t count)
148{
149 constexpr std::size_t N = sizeof(SourceT);
150 auto dst = reinterpret_cast<DestT *>(destination);
151 auto splitArray = reinterpret_cast<const char *>(source);
152 for (std::size_t i = 0; i < count; ++i) {
153 SourceT val = 0;
154 for (std::size_t b = 0; b < N; ++b) {
155 reinterpret_cast<char *>(&val)[b] = splitArray[b * count + i];
156 }
157 ByteSwapIfNecessary(val);
158 dst[i] = val;
159 }
160}
161
162/// \brief Packing of columns with delta + split encoding
163///
164/// Apply split encoding to delta-encoded values, currently used only for index columns
165template <typename DestT, typename SourceT>
166static void CastDeltaSplitPack(void *destination, const void *source, std::size_t count)
167{
168 constexpr std::size_t N = sizeof(DestT);
169 auto src = reinterpret_cast<const SourceT *>(source);
170 auto splitArray = reinterpret_cast<char *>(destination);
171 for (std::size_t i = 0; i < count; ++i) {
172 DestT val = (i == 0) ? src[0] : src[i] - src[i - 1];
173 ByteSwapIfNecessary(val);
174 for (std::size_t b = 0; b < N; ++b) {
175 splitArray[b * count + i] = reinterpret_cast<char *>(&val)[b];
176 }
177 }
178}
179
180/// \brief Unsplit and unwind delta encoding
181///
182/// Unsplit a column and reverse the delta encoding, currently used only for index columns
183template <typename DestT, typename SourceT>
184static void CastDeltaSplitUnpack(void *destination, const void *source, std::size_t count)
185{
186 constexpr std::size_t N = sizeof(SourceT);
187 auto splitArray = reinterpret_cast<const char *>(source);
188 auto dst = reinterpret_cast<DestT *>(destination);
189 for (std::size_t i = 0; i < count; ++i) {
190 SourceT val = 0;
191 for (std::size_t b = 0; b < N; ++b) {
192 reinterpret_cast<char *>(&val)[b] = splitArray[b * count + i];
193 }
194 ByteSwapIfNecessary(val);
195 dst[i] = (i == 0) ? val : dst[i - 1] + val;
196 }
197}
198
199} // anonymous namespace
200
201namespace ROOT {
202namespace Experimental {
203
204namespace Detail {
205
206// clang-format off
207/**
208\class ROOT::Experimental::Detail::RColumnElement
209\ingroup NTuple
210\brief A column element points either to the content of an RFieldValue or into a memory mapped page.
211
212The content pointed to by fRawContent can be a single element or the first element of an array.
213Usually the on-disk element should map bitwise to the in-memory element. Sometimes that's not the case
214though, for instance on big endian platforms and for exotic physical columns like 8 bit float.
215
216This class does not provide protection around the raw pointer, fRawContent has to be managed correctly
217by the user of this class.
218*/
219// clang-format on
221protected:
222 /// Points to valid C++ data, either a single value or an array of values
224 /// Size of the C++ value pointed to by fRawContent (not necessarily equal to the on-disk element size)
225 std::size_t fSize;
226
227public:
229 : fRawContent(nullptr)
230 , fSize(0)
231 {}
232 RColumnElementBase(void *rawContent, std::size_t size) : fRawContent(rawContent), fSize(size)
233 {}
234 RColumnElementBase(const RColumnElementBase &elemArray, std::size_t at)
235 : fRawContent(static_cast<unsigned char *>(elemArray.fRawContent) + elemArray.fSize * at)
236 , fSize(elemArray.fSize)
237 {}
238 RColumnElementBase(const RColumnElementBase& other) = default;
242 virtual ~RColumnElementBase() = default;
243
244 /// If CppT == void, use the default C++ type for the given column type
245 template <typename CppT = void>
246 static std::unique_ptr<RColumnElementBase> Generate(EColumnType type);
247 static std::size_t GetBitsOnStorage(EColumnType type);
248 static std::string GetTypeName(EColumnType type);
249
250 /// Write one or multiple column elements into destination
251 void WriteTo(void *destination, std::size_t count) const {
252 std::memcpy(destination, fRawContent, fSize * count);
253 }
254
255 /// Set the column element or an array of elements from the memory location source
256 void ReadFrom(void *source, std::size_t count) {
257 std::memcpy(fRawContent, source, fSize * count);
258 }
259
260 /// Derived, typed classes tell whether the on-storage layout is bitwise identical to the memory layout
261 virtual bool IsMappable() const { R__ASSERT(false); return false; }
262 virtual std::size_t GetBitsOnStorage() const { R__ASSERT(false); return 0; }
263
264 /// If the on-storage layout and the in-memory layout differ, packing creates an on-disk page from an in-memory page
265 virtual void Pack(void *destination, void *source, std::size_t count) const
266 {
267 std::memcpy(destination, source, count);
268 }
269
270 /// If the on-storage layout and the in-memory layout differ, unpacking creates a memory page from an on-storage page
271 virtual void Unpack(void *destination, void *source, std::size_t count) const
272 {
273 std::memcpy(destination, source, count);
274 }
275
276 void *GetRawContent() const { return fRawContent; }
277 std::size_t GetSize() const { return fSize; }
278 std::size_t GetPackedSize(std::size_t nElements) const { return (nElements * GetBitsOnStorage() + 7) / 8; }
279};
280
281/**
282 * Base class for columns whose on-storage representation is little-endian.
283 * The implementation of `Pack` and `Unpack` takes care of byteswap if the memory page is big-endian.
284 */
285template <typename CppT>
287public:
288 static constexpr bool kIsMappable = (R__LITTLE_ENDIAN == 1);
289 RColumnElementLE(void *rawContent, std::size_t size) : RColumnElementBase(rawContent, size) {}
290
291 void Pack(void *dst, void *src, std::size_t count) const final
292 {
293#if R__LITTLE_ENDIAN == 1
294 RColumnElementBase::Pack(dst, src, count);
295#else
296 CopyBswap<sizeof(CppT)>(dst, src, count);
297#endif
298 }
299 void Unpack(void *dst, void *src, std::size_t count) const final
300 {
301#if R__LITTLE_ENDIAN == 1
302 RColumnElementBase::Unpack(dst, src, count);
303#else
304 CopyBswap<sizeof(CppT)>(dst, src, count);
305#endif
306 }
307}; // class RColumnElementLE
308
309/**
310 * Base class for columns storing elements of wider in-memory types,
311 * such as 64bit in-memory offsets to Index32 columns.
312 */
313template <typename CppT, typename NarrowT>
315public:
316 static constexpr bool kIsMappable = false;
317 RColumnElementCastLE(void *rawContent, std::size_t size) : RColumnElementBase(rawContent, size) {}
318
319 void Pack(void *dst, void *src, std::size_t count) const final { CastPack<NarrowT, CppT>(dst, src, count); }
320 void Unpack(void *dst, void *src, std::size_t count) const final { CastUnpack<CppT, NarrowT>(dst, src, count); }
321}; // class RColumnElementCastLE
322
323/**
324 * Base class for split columns whose on-storage representation is little-endian.
325 * The implementation of `Pack` and `Unpack` takes care of splitting and, if necessary, byteswap.
326 * As part of the splitting, can also narrow down the type to NarrowT.
327 */
328template <typename CppT, typename NarrowT>
330public:
331 static constexpr bool kIsMappable = false;
332 RColumnElementSplitLE(void *rawContent, std::size_t size) : RColumnElementBase(rawContent, size) {}
333
334 void Pack(void *dst, void *src, std::size_t count) const final { CastSplitPack<NarrowT, CppT>(dst, src, count); }
335 void Unpack(void *dst, void *src, std::size_t count) const final { CastSplitUnpack<CppT, NarrowT>(dst, src, count); }
336}; // class RColumnElementSplitLE
337
338/**
339 * Base class for delta + split columns (index columns) whose on-storage representation is little-endian.
340 * The implementation of `Pack` and `Unpack` takes care of splitting and, if necessary, byteswap.
341 * As part of the encoding, can also narrow down the type to NarrowT.
342 */
343template <typename CppT, typename NarrowT>
345public:
346 static constexpr bool kIsMappable = false;
347 RColumnElementDeltaSplitLE(void *rawContent, std::size_t size) : RColumnElementBase(rawContent, size) {}
348
349 void Pack(void *dst, void *src, std::size_t count) const final
350 {
351 CastDeltaSplitPack<NarrowT, CppT>(dst, src, count);
352 }
353 void Unpack(void *dst, void *src, std::size_t count) const final
354 {
355 CastDeltaSplitUnpack<CppT, NarrowT>(dst, src, count);
356 }
357}; // class RColumnElementDeltaSplitLE
358
359////////////////////////////////////////////////////////////////////////////////
360// Pairs of C++ type and column type, like float and EColumnType::kReal32
361////////////////////////////////////////////////////////////////////////////////
362
363////////////////////////////////////////////////////////////////////////////////
364// Part 1: C++ type --> unknown column type
365////////////////////////////////////////////////////////////////////////////////
366
367template <typename CppT, EColumnType ColumnT = EColumnType::kUnknown>
369public:
370 explicit RColumnElement(CppT* value) : RColumnElementBase(value, sizeof(CppT))
371 {
372 throw RException(R__FAIL(std::string("internal error: no column mapping for this C++ type: ") +
373 typeid(CppT).name() + " --> " + GetTypeName(ColumnT)));
374 }
375};
376
377template <>
379public:
380 static constexpr std::size_t kSize = sizeof(bool);
382};
383
384template <>
386public:
387 static constexpr std::size_t kSize = sizeof(char);
389};
390
391template <>
392class RColumnElement<std::int8_t, EColumnType::kUnknown> : public RColumnElementBase {
393public:
394 static constexpr std::size_t kSize = sizeof(std::int8_t);
395 explicit RColumnElement(std::int8_t *value) : RColumnElementBase(value, kSize) {}
396};
397
398template <>
399class RColumnElement<std::uint8_t, EColumnType::kUnknown> : public RColumnElementBase {
400public:
401 static constexpr std::size_t kSize = sizeof(std::uint8_t);
402 explicit RColumnElement(std::uint8_t *value) : RColumnElementBase(value, kSize) {}
403};
404
405template <>
406class RColumnElement<std::int16_t, EColumnType::kUnknown> : public RColumnElementBase {
407public:
408 static constexpr std::size_t kSize = sizeof(std::int16_t);
409 explicit RColumnElement(std::int16_t *value) : RColumnElementBase(value, kSize) {}
410};
411
412template <>
413class RColumnElement<std::uint16_t, EColumnType::kUnknown> : public RColumnElementBase {
414public:
415 static constexpr std::size_t kSize = sizeof(std::uint16_t);
416 explicit RColumnElement(std::uint16_t *value) : RColumnElementBase(value, kSize) {}
417};
418
419template <>
420class RColumnElement<std::int32_t, EColumnType::kUnknown> : public RColumnElementBase {
421public:
422 static constexpr std::size_t kSize = sizeof(std::int32_t);
423 explicit RColumnElement(std::int32_t *value) : RColumnElementBase(value, kSize) {}
424};
425
426template <>
427class RColumnElement<std::uint32_t, EColumnType::kUnknown> : public RColumnElementBase {
428public:
429 static constexpr std::size_t kSize = sizeof(std::uint32_t);
430 explicit RColumnElement(std::uint32_t *value) : RColumnElementBase(value, kSize) {}
431};
432
433template <>
434class RColumnElement<std::int64_t, EColumnType::kUnknown> : public RColumnElementBase {
435public:
436 static constexpr std::size_t kSize = sizeof(std::int64_t);
437 explicit RColumnElement(std::int64_t *value) : RColumnElementBase(value, kSize) {}
438};
439
440template <>
441class RColumnElement<std::uint64_t, EColumnType::kUnknown> : public RColumnElementBase {
442public:
443 static constexpr std::size_t kSize = sizeof(std::uint64_t);
444 explicit RColumnElement(std::uint64_t *value) : RColumnElementBase(value, kSize) {}
445};
446
447template <>
449public:
450 static constexpr std::size_t kSize = sizeof(float);
452};
453
454template <>
456public:
457 static constexpr std::size_t kSize = sizeof(double);
459};
460
461template <>
463public:
464 static constexpr std::size_t kSize = sizeof(ClusterSize_t);
466};
467
468template <>
470public:
471 static constexpr std::size_t kSize = sizeof(RColumnSwitch);
473};
474
475////////////////////////////////////////////////////////////////////////////////
476// Part 2: C++ type --> supported column representations,
477// ordered by C++ type
478////////////////////////////////////////////////////////////////////////////////
479
480template <>
482public:
483 static constexpr bool kIsMappable = false;
484 static constexpr std::size_t kSize = sizeof(bool);
485 static constexpr std::size_t kBitsOnStorage = 1;
487 bool IsMappable() const final { return kIsMappable; }
488 std::size_t GetBitsOnStorage() const final { return kBitsOnStorage; }
489
490 void Pack(void *dst, void *src, std::size_t count) const final;
491 void Unpack(void *dst, void *src, std::size_t count) const final;
492};
493
494template <>
496public:
497 static constexpr bool kIsMappable = true;
498 static constexpr std::size_t kSize = sizeof(char);
499 static constexpr std::size_t kBitsOnStorage = kSize * 8;
501 bool IsMappable() const final { return kIsMappable; }
502 std::size_t GetBitsOnStorage() const final { return kBitsOnStorage; }
503};
504
505template <>
507public:
508 static constexpr bool kIsMappable = true;
509 static constexpr std::size_t kSize = sizeof(char);
510 static constexpr std::size_t kBitsOnStorage = kSize * 8;
512 bool IsMappable() const final { return kIsMappable; }
513 std::size_t GetBitsOnStorage() const final { return kBitsOnStorage; }
514};
515
516template <>
517class RColumnElement<std::int8_t, EColumnType::kInt8> : public RColumnElementBase {
518public:
519 static constexpr bool kIsMappable = true;
520 static constexpr std::size_t kSize = sizeof(std::int8_t);
521 static constexpr std::size_t kBitsOnStorage = kSize * 8;
522 explicit RColumnElement(std::int8_t *value) : RColumnElementBase(value, kSize) {}
523 bool IsMappable() const final { return kIsMappable; }
524 std::size_t GetBitsOnStorage() const final { return kBitsOnStorage; }
525};
526
527template <>
528class RColumnElement<std::int8_t, EColumnType::kByte> : public RColumnElementBase {
529public:
530 static constexpr bool kIsMappable = true;
531 static constexpr std::size_t kSize = sizeof(std::int8_t);
532 static constexpr std::size_t kBitsOnStorage = kSize * 8;
533 explicit RColumnElement(std::int8_t *value) : RColumnElementBase(value, kSize) {}
534 bool IsMappable() const final { return kIsMappable; }
535 std::size_t GetBitsOnStorage() const final { return kBitsOnStorage; }
536};
537
538template <>
539class RColumnElement<std::uint8_t, EColumnType::kInt8> : public RColumnElementBase {
540public:
541 static constexpr bool kIsMappable = true;
542 static constexpr std::size_t kSize = sizeof(std::uint8_t);
543 static constexpr std::size_t kBitsOnStorage = kSize * 8;
544 explicit RColumnElement(std::uint8_t *value) : RColumnElementBase(value, kSize) {}
545 bool IsMappable() const final { return kIsMappable; }
546 std::size_t GetBitsOnStorage() const final { return kBitsOnStorage; }
547};
548
549template <>
550class RColumnElement<std::uint8_t, EColumnType::kByte> : public RColumnElementBase {
551public:
552 static constexpr bool kIsMappable = true;
553 static constexpr std::size_t kSize = sizeof(std::uint8_t);
554 static constexpr std::size_t kBitsOnStorage = kSize * 8;
555 explicit RColumnElement(std::uint8_t *value) : RColumnElementBase(value, kSize) {}
556 bool IsMappable() const final { return kIsMappable; }
557 std::size_t GetBitsOnStorage() const final { return kBitsOnStorage; }
558};
559
560template <>
561class RColumnElement<std::int16_t, EColumnType::kInt16> : public RColumnElementLE<std::int16_t> {
562public:
563 static constexpr std::size_t kSize = sizeof(std::int16_t);
564 static constexpr std::size_t kBitsOnStorage = kSize * 8;
565 explicit RColumnElement(std::int16_t *value) : RColumnElementLE(value, kSize) {}
566 bool IsMappable() const final { return kIsMappable; }
567 std::size_t GetBitsOnStorage() const final { return kBitsOnStorage; }
568};
569
570template <>
571class RColumnElement<std::int16_t, EColumnType::kSplitInt16>
572 : public RColumnElementSplitLE<std::int16_t, std::int16_t> {
573public:
574 static constexpr std::size_t kSize = sizeof(std::int16_t);
575 static constexpr std::size_t kBitsOnStorage = kSize * 8;
576 explicit RColumnElement(std::int16_t *value) : RColumnElementSplitLE(value, kSize) {}
577 bool IsMappable() const final { return kIsMappable; }
578 std::size_t GetBitsOnStorage() const final { return kBitsOnStorage; }
579};
580
581template <>
582class RColumnElement<std::uint16_t, EColumnType::kInt16> : public RColumnElementLE<std::uint16_t> {
583public:
584 static constexpr std::size_t kSize = sizeof(std::uint16_t);
585 static constexpr std::size_t kBitsOnStorage = kSize * 8;
586 explicit RColumnElement(std::uint16_t *value) : RColumnElementLE(value, kSize) {}
587 bool IsMappable() const final { return kIsMappable; }
588 std::size_t GetBitsOnStorage() const final { return kBitsOnStorage; }
589};
590
591template <>
592class RColumnElement<std::uint16_t, EColumnType::kSplitInt16>
593 : public RColumnElementSplitLE<std::uint16_t, std::uint16_t> {
594public:
595 static constexpr std::size_t kSize = sizeof(std::uint16_t);
596 static constexpr std::size_t kBitsOnStorage = kSize * 8;
597 explicit RColumnElement(std::uint16_t *value) : RColumnElementSplitLE(value, kSize) {}
598 bool IsMappable() const final { return kIsMappable; }
599 std::size_t GetBitsOnStorage() const final { return kBitsOnStorage; }
600};
601
602template <>
603class RColumnElement<std::int32_t, EColumnType::kInt32> : public RColumnElementLE<std::int32_t> {
604public:
605 static constexpr std::size_t kSize = sizeof(std::int32_t);
606 static constexpr std::size_t kBitsOnStorage = kSize * 8;
607 explicit RColumnElement(std::int32_t *value) : RColumnElementLE(value, kSize) {}
608 bool IsMappable() const final { return kIsMappable; }
609 std::size_t GetBitsOnStorage() const final { return kBitsOnStorage; }
610};
611
612template <>
613class RColumnElement<std::int32_t, EColumnType::kSplitInt32>
614 : public RColumnElementSplitLE<std::int32_t, std::int32_t> {
615public:
616 static constexpr std::size_t kSize = sizeof(std::int32_t);
617 static constexpr std::size_t kBitsOnStorage = kSize * 8;
618 explicit RColumnElement(std::int32_t *value) : RColumnElementSplitLE(value, kSize) {}
619 bool IsMappable() const final { return kIsMappable; }
620 std::size_t GetBitsOnStorage() const final { return kBitsOnStorage; }
621};
622
623template <>
624class RColumnElement<std::uint32_t, EColumnType::kInt32> : public RColumnElementLE<std::uint32_t> {
625public:
626 static constexpr std::size_t kSize = sizeof(std::uint32_t);
627 static constexpr std::size_t kBitsOnStorage = kSize * 8;
628 explicit RColumnElement(std::uint32_t *value) : RColumnElementLE(value, kSize) {}
629 bool IsMappable() const final { return kIsMappable; }
630 std::size_t GetBitsOnStorage() const final { return kBitsOnStorage; }
631};
632
633template <>
634class RColumnElement<std::uint32_t, EColumnType::kSplitInt32>
635 : public RColumnElementSplitLE<std::uint32_t, std::uint32_t> {
636public:
637 static constexpr std::size_t kSize = sizeof(std::uint32_t);
638 static constexpr std::size_t kBitsOnStorage = kSize * 8;
639 explicit RColumnElement(std::uint32_t *value) : RColumnElementSplitLE(value, kSize) {}
640 bool IsMappable() const final { return kIsMappable; }
641 std::size_t GetBitsOnStorage() const final { return kBitsOnStorage; }
642};
643
644template <>
645class RColumnElement<std::int64_t, EColumnType::kInt64> : public RColumnElementLE<std::int64_t> {
646public:
647 static constexpr std::size_t kSize = sizeof(std::int64_t);
648 static constexpr std::size_t kBitsOnStorage = kSize * 8;
649 explicit RColumnElement(std::int64_t *value) : RColumnElementLE(value, kSize) {}
650 bool IsMappable() const final { return kIsMappable; }
651 std::size_t GetBitsOnStorage() const final { return kBitsOnStorage; }
652};
653
654template <>
655class RColumnElement<std::int64_t, EColumnType::kSplitInt64>
656 : public RColumnElementSplitLE<std::int64_t, std::int64_t> {
657public:
658 static constexpr std::size_t kSize = sizeof(std::int64_t);
659 static constexpr std::size_t kBitsOnStorage = kSize * 8;
660 explicit RColumnElement(std::int64_t *value) : RColumnElementSplitLE(value, kSize) {}
661 bool IsMappable() const final { return kIsMappable; }
662 std::size_t GetBitsOnStorage() const final { return kBitsOnStorage; }
663};
664
665template <>
666class RColumnElement<std::int64_t, EColumnType::kInt32> : public RColumnElementCastLE<std::int64_t, std::int32_t> {
667public:
668 static constexpr std::size_t kSize = sizeof(std::int64_t);
669 static constexpr std::size_t kBitsOnStorage = 32;
670 explicit RColumnElement(std::int64_t *value) : RColumnElementCastLE(value, kSize) {}
671 bool IsMappable() const final { return kIsMappable; }
672 std::size_t GetBitsOnStorage() const final { return kBitsOnStorage; }
673};
674
675template <>
676class RColumnElement<std::int64_t, EColumnType::kSplitInt32>
677 : public RColumnElementSplitLE<std::int64_t, std::int32_t> {
678public:
679 static constexpr std::size_t kSize = sizeof(std::int64_t);
680 static constexpr std::size_t kBitsOnStorage = 32;
681 explicit RColumnElement(std::int64_t *value) : RColumnElementSplitLE(value, kSize) {}
682 bool IsMappable() const final { return kIsMappable; }
683 std::size_t GetBitsOnStorage() const final { return kBitsOnStorage; }
684};
685
686template <>
687class RColumnElement<std::uint64_t, EColumnType::kInt64> : public RColumnElementLE<std::uint64_t> {
688public:
689 static constexpr std::size_t kSize = sizeof(std::uint64_t);
690 static constexpr std::size_t kBitsOnStorage = kSize * 8;
691 explicit RColumnElement(std::uint64_t *value) : RColumnElementLE(value, kSize) {}
692 bool IsMappable() const final { return kIsMappable; }
693 std::size_t GetBitsOnStorage() const final { return kBitsOnStorage; }
694};
695
696template <>
697class RColumnElement<std::uint64_t, EColumnType::kSplitInt64>
698 : public RColumnElementSplitLE<std::uint64_t, std::uint64_t> {
699public:
700 static constexpr std::size_t kSize = sizeof(std::uint64_t);
701 static constexpr std::size_t kBitsOnStorage = kSize * 8;
702 explicit RColumnElement(std::uint64_t *value) : RColumnElementSplitLE(value, kSize) {}
703 bool IsMappable() const final { return kIsMappable; }
704 std::size_t GetBitsOnStorage() const final { return kBitsOnStorage; }
705};
706
707template <>
708class RColumnElement<float, EColumnType::kReal32> : public RColumnElementLE<float> {
709public:
710 static constexpr std::size_t kSize = sizeof(float);
711 static constexpr std::size_t kBitsOnStorage = kSize * 8;
713 bool IsMappable() const final { return kIsMappable; }
714 std::size_t GetBitsOnStorage() const final { return kBitsOnStorage; }
715};
716
717template <>
718class RColumnElement<float, EColumnType::kSplitReal32> : public RColumnElementSplitLE<float, float> {
719public:
720 static constexpr std::size_t kSize = sizeof(float);
721 static constexpr std::size_t kBitsOnStorage = kSize * 8;
723 bool IsMappable() const final { return kIsMappable; }
724 std::size_t GetBitsOnStorage() const final { return kBitsOnStorage; }
725};
726
727template <>
729public:
730 static constexpr std::size_t kSize = sizeof(double);
731 static constexpr std::size_t kBitsOnStorage = kSize * 8;
733 bool IsMappable() const final { return kIsMappable; }
734 std::size_t GetBitsOnStorage() const final { return kBitsOnStorage; }
735};
736
737template <>
739public:
740 static constexpr std::size_t kSize = sizeof(double);
741 static constexpr std::size_t kBitsOnStorage = kSize * 8;
743 bool IsMappable() const final { return kIsMappable; }
744 std::size_t GetBitsOnStorage() const final { return kBitsOnStorage; }
745};
746
747template <>
749public:
750 static constexpr std::size_t kSize = sizeof(ClusterSize_t);
751 static constexpr std::size_t kBitsOnStorage = 64;
753 bool IsMappable() const final { return kIsMappable; }
754 std::size_t GetBitsOnStorage() const final { return kBitsOnStorage; }
755};
756
757template <>
758class RColumnElement<ClusterSize_t, EColumnType::kIndex32> : public RColumnElementCastLE<std::uint64_t, std::uint32_t> {
759public:
760 static constexpr std::size_t kSize = sizeof(ClusterSize_t);
761 static constexpr std::size_t kBitsOnStorage = 32;
763 bool IsMappable() const final { return kIsMappable; }
764 std::size_t GetBitsOnStorage() const final { return kBitsOnStorage; }
765};
766
767template <>
769 : public RColumnElementDeltaSplitLE<std::uint64_t, std::uint64_t> {
770public:
771 static constexpr std::size_t kSize = sizeof(ClusterSize_t);
772 static constexpr std::size_t kBitsOnStorage = 64;
774 bool IsMappable() const final { return kIsMappable; }
775 std::size_t GetBitsOnStorage() const final { return kBitsOnStorage; }
776};
777
778template <>
780 : public RColumnElementDeltaSplitLE<std::uint64_t, std::uint32_t> {
781public:
782 static constexpr std::size_t kSize = sizeof(ClusterSize_t);
783 static constexpr std::size_t kBitsOnStorage = 32;
785 bool IsMappable() const final { return kIsMappable; }
786 std::size_t GetBitsOnStorage() const final { return kBitsOnStorage; }
787};
788
789template <>
791public:
792 static constexpr bool kIsMappable = false;
793 static constexpr std::size_t kSize = sizeof(ROOT::Experimental::RColumnSwitch);
794 static constexpr std::size_t kBitsOnStorage = 64;
796 bool IsMappable() const final { return kIsMappable; }
797 std::size_t GetBitsOnStorage() const final { return kBitsOnStorage; }
798
799 void Pack(void *dst, void *src, std::size_t count) const final
800 {
801 auto srcArray = reinterpret_cast<ROOT::Experimental::RColumnSwitch *>(src);
802 auto uint64Array = reinterpret_cast<std::uint64_t *>(dst);
803 for (std::size_t i = 0; i < count; ++i) {
804 uint64Array[i] =
805 (static_cast<std::uint64_t>(srcArray[i].GetTag()) << 44) | (srcArray[i].GetIndex() & 0x0fffffffffff);
806#if R__LITTLE_ENDIAN == 0
807 uint64Array[i] = RByteSwap<8>::bswap(uint64Array[i]);
808#endif
809 }
810 }
811
812 void Unpack(void *dst, void *src, std::size_t count) const final
813 {
814 auto uint64Array = reinterpret_cast<std::uint64_t *>(src);
815 auto dstArray = reinterpret_cast<ROOT::Experimental::RColumnSwitch *>(dst);
816 for (std::size_t i = 0; i < count; ++i) {
817#if R__LITTLE_ENDIAN == 1
818 const auto value = uint64Array[i];
819#else
820 const auto value = RByteSwap<8>::bswap(uint64Array[i]);
821#endif
823 ClusterSize_t{static_cast<RClusterSize::ValueType>(value & 0x0fffffffffff)}, (value >> 44));
824 }
825 }
826};
827
828template <typename CppT>
829std::unique_ptr<RColumnElementBase> RColumnElementBase::Generate(EColumnType type)
830{
831 switch (type) {
832 case EColumnType::kIndex64: return std::make_unique<RColumnElement<CppT, EColumnType::kIndex64>>(nullptr);
833 case EColumnType::kIndex32: return std::make_unique<RColumnElement<CppT, EColumnType::kIndex32>>(nullptr);
834 case EColumnType::kSwitch: return std::make_unique<RColumnElement<CppT, EColumnType::kSwitch>>(nullptr);
835 case EColumnType::kByte: return std::make_unique<RColumnElement<CppT, EColumnType::kByte>>(nullptr);
836 case EColumnType::kChar: return std::make_unique<RColumnElement<CppT, EColumnType::kChar>>(nullptr);
837 case EColumnType::kBit: return std::make_unique<RColumnElement<CppT, EColumnType::kBit>>(nullptr);
838 case EColumnType::kReal64: return std::make_unique<RColumnElement<CppT, EColumnType::kReal64>>(nullptr);
839 case EColumnType::kReal32: return std::make_unique<RColumnElement<CppT, EColumnType::kReal32>>(nullptr);
840 case EColumnType::kInt64: return std::make_unique<RColumnElement<CppT, EColumnType::kInt64>>(nullptr);
841 case EColumnType::kInt32: return std::make_unique<RColumnElement<CppT, EColumnType::kInt32>>(nullptr);
842 case EColumnType::kInt16: return std::make_unique<RColumnElement<CppT, EColumnType::kInt16>>(nullptr);
843 case EColumnType::kInt8: return std::make_unique<RColumnElement<CppT, EColumnType::kInt8>>(nullptr);
844 case EColumnType::kSplitIndex64: return std::make_unique<RColumnElement<CppT, EColumnType::kSplitIndex64>>(nullptr);
845 case EColumnType::kSplitIndex32: return std::make_unique<RColumnElement<CppT, EColumnType::kSplitIndex32>>(nullptr);
846 case EColumnType::kSplitReal64: return std::make_unique<RColumnElement<CppT, EColumnType::kSplitReal64>>(nullptr);
847 case EColumnType::kSplitReal32: return std::make_unique<RColumnElement<CppT, EColumnType::kSplitReal32>>(nullptr);
848 case EColumnType::kSplitInt64: return std::make_unique<RColumnElement<CppT, EColumnType::kSplitInt64>>(nullptr);
849 case EColumnType::kSplitInt32: return std::make_unique<RColumnElement<CppT, EColumnType::kSplitInt32>>(nullptr);
850 case EColumnType::kSplitInt16: return std::make_unique<RColumnElement<CppT, EColumnType::kSplitInt16>>(nullptr);
851 default: R__ASSERT(false);
852 }
853 // never here
854 return nullptr;
855}
856
857template <>
858std::unique_ptr<RColumnElementBase> RColumnElementBase::Generate<void>(EColumnType type);
859
860} // namespace Detail
861} // namespace Experimental
862} // namespace ROOT
863
864#endif
#define R__LITTLE_ENDIAN
#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
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-...
void WriteTo(void *destination, std::size_t count) const
Write one or multiple column elements into destination.
RColumnElementBase(RColumnElementBase &&other)=default
virtual bool IsMappable() const
Derived, typed classes tell whether the on-storage layout is bitwise identical to the memory layout.
void * fRawContent
Points to valid C++ data, either a single value or an array of values.
RColumnElementBase(void *rawContent, std::size_t size)
RColumnElementBase(const RColumnElementBase &other)=default
RColumnElementBase & operator=(const RColumnElementBase &other)=delete
std::size_t fSize
Size of the C++ value pointed to by fRawContent (not necessarily equal to the on-disk element size)
static std::string GetTypeName(EColumnType type)
void ReadFrom(void *source, std::size_t count)
Set the column element or an array of elements from the memory location source.
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-...
RColumnElementBase(const RColumnElementBase &elemArray, std::size_t at)
std::size_t GetPackedSize(std::size_t nElements) const
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-...
RColumnElementCastLE(void *rawContent, std::size_t size)
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-...
RColumnElementDeltaSplitLE(void *rawContent, std::size_t size)
Base class for columns whose on-storage representation is little-endian.
RColumnElementLE(void *rawContent, std::size_t size)
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.
RColumnElementSplitLE(void *rawContent, std::size_t size)
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-...
bool IsMappable() const final
Derived, typed classes tell whether the on-storage layout is bitwise identical to the memory layout.
bool IsMappable() const final
Derived, typed classes tell whether the on-storage layout is bitwise identical to the memory layout.
bool IsMappable() const final
Derived, typed classes tell whether the on-storage layout is bitwise identical to the memory layout.
bool IsMappable() const final
Derived, typed classes tell whether the on-storage layout is bitwise identical to the memory layout.
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.
bool IsMappable() const final
Derived, typed classes tell whether the on-storage layout is bitwise identical to the memory layout.
bool IsMappable() const final
Derived, typed classes tell whether the on-storage layout is bitwise identical to the memory layout.
bool IsMappable() const final
Derived, typed classes tell whether the on-storage layout is bitwise identical to the memory layout.
bool IsMappable() const final
Derived, typed classes tell whether the on-storage layout is bitwise identical to the memory layout.
bool IsMappable() const final
Derived, typed classes tell whether the on-storage layout is bitwise identical to the memory layout.
bool IsMappable() const final
Derived, typed classes tell whether the on-storage layout is bitwise identical to the memory layout.
A column element points either to the content of an RFieldValue or into a memory mapped page.
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.