Logo ROOT  
Reference Guide
RField.cxx
Go to the documentation of this file.
1/// \file RField.cxx
2/// \ingroup NTuple ROOT7
3/// \author Jakob Blomer <jblomer@cern.ch>
4/// \date 2018-10-15
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#include <ROOT/RColumn.hxx>
17#include <ROOT/RColumnModel.hxx>
18#include <ROOT/REntry.hxx>
19#include <ROOT/RError.hxx>
20#include <ROOT/RField.hxx>
21#include <ROOT/RFieldValue.hxx>
23#include <ROOT/RLogger.hxx>
24#include <ROOT/RNTuple.hxx>
25#include <ROOT/RNTupleModel.hxx>
26
27#include <TBaseClass.h>
28#include <TClass.h>
29#include <TClassEdit.h>
30#include <TCollection.h>
31#include <TDataMember.h>
32#include <TError.h>
33#include <TList.h>
34#include <TRealData.h>
35
36#include <algorithm>
37#include <cctype> // for isspace
38#include <cstdint>
39#include <cstdlib> // for malloc, free
40#include <cstring> // for memset
41#include <exception>
42#include <iostream>
43#include <new> // hardware_destructive_interference_size
44#include <type_traits>
45#include <unordered_map>
46
47namespace {
48
49static const std::unordered_map<std::string_view, std::string_view> typeTranslationMap{
50 {"Bool_t", "bool"},
51 {"Float_t", "float"},
52 {"Double_t", "double"},
53 {"string", "std::string"},
54
55 {"Char_t", "char"},
56 {"int8_t", "std::int8_t"},
57 {"signed char", "char"},
58 {"UChar_t", "std::uint8_t"},
59 {"unsigned char", "std::uint8_t"},
60 {"uint8_t", "std::uint8_t"},
61
62 {"Short_t", "std::int16_t"},
63 {"int16_t", "std::int16_t"},
64 {"short", "std::int16_t"},
65 {"UShort_t", "std::uint16_t"},
66 {"unsigned short", "std::uint16_t"},
67 {"uint16_t", "std::uint16_t"},
68
69 {"Int_t", "std::int32_t"},
70 {"int32_t", "std::int32_t"},
71 {"int", "std::int32_t"},
72 {"UInt_t", "std::uint32_t"},
73 {"unsigned", "std::uint32_t"},
74 {"unsigned int", "std::uint32_t"},
75 {"uint32_t", "std::uint32_t"},
76
77 {"Long_t", "std::int64_t"},
78 {"Long64_t", "std::int64_t"},
79 {"int64_t", "std::int64_t"},
80 {"long", "std::int64_t"},
81 {"ULong64_t", "std::uint64_t"},
82 {"unsigned long", "std::uint64_t"},
83 {"uint64_t", "std::uint64_t"}
84};
85
86/// Used in CreateField() in order to get the comma-separated list of template types
87/// E.g., gets {"int", "std::variant<double,int>"} from "int,std::variant<double,int>"
88std::vector<std::string> TokenizeTypeList(std::string templateType) {
89 std::vector<std::string> result;
90 if (templateType.empty())
91 return result;
92
93 const char *eol = templateType.data() + templateType.length();
94 const char *typeBegin = templateType.data();
95 const char *typeCursor = templateType.data();
96 unsigned int nestingLevel = 0;
97 while (typeCursor != eol) {
98 switch (*typeCursor) {
99 case '<':
100 ++nestingLevel;
101 break;
102 case '>':
103 --nestingLevel;
104 break;
105 case ',':
106 if (nestingLevel == 0) {
107 result.push_back(std::string(typeBegin, typeCursor - typeBegin));
108 typeBegin = typeCursor + 1;
109 }
110 break;
111 }
112 typeCursor++;
113 }
114 result.push_back(std::string(typeBegin, typeCursor - typeBegin));
115 return result;
116}
117
118std::string GetNormalizedType(const std::string &typeName) {
119 std::string normalizedType(
121 /*mode=*/2).c_str()));
122
123 auto translatedType = typeTranslationMap.find(normalizedType);
124 if (translatedType != typeTranslationMap.end())
125 normalizedType = translatedType->second;
126
127 if (normalizedType.substr(0, 7) == "vector<") normalizedType = "std::" + normalizedType;
128 if (normalizedType.substr(0, 6) == "array<") normalizedType = "std::" + normalizedType;
129 if (normalizedType.substr(0, 8) == "variant<") normalizedType = "std::" + normalizedType;
130 if (normalizedType.substr(0, 5) == "pair<") normalizedType = "std::" + normalizedType;
131 if (normalizedType.substr(0, 6) == "tuple<") normalizedType = "std::" + normalizedType;
132
133 return normalizedType;
134}
135
136/// Retrieve the addresses of the data members of a generic RVec from a pointer to the beginning of the RVec object.
137/// Returns pointers to fBegin, fSize and fCapacity in a std::tuple.
138std::tuple<void **, std::int32_t *, std::int32_t *> GetRVecDataMembers(void *rvecPtr)
139{
140 void **begin = reinterpret_cast<void **>(rvecPtr);
141 // int32_t fSize is the second data member (after 1 void*)
142 std::int32_t *size = reinterpret_cast<std::int32_t *>(begin + 1);
143 R__ASSERT(*size >= 0);
144 // int32_t fCapacity is the third data member (1 int32_t after fSize)
145 std::int32_t *capacity = size + 1;
146 R__ASSERT(*capacity >= -1);
147 return {begin, size, capacity};
148}
149
150} // anonymous namespace
151
152
153//------------------------------------------------------------------------------
154
155
157 std::string_view name, std::string_view type, ENTupleStructure structure, bool isSimple, std::size_t nRepetitions)
158 : fName(name), fType(type), fStructure(structure), fNRepetitions(nRepetitions), fIsSimple(isSimple),
159 fParent(nullptr), fPrincipalColumn(nullptr)
160{
161}
162
164{
165}
166
168ROOT::Experimental::Detail::RFieldBase::Create(const std::string &fieldName, const std::string &typeName)
169{
170 std::string normalizedType(GetNormalizedType(typeName));
171 if (normalizedType.empty())
172 return R__FAIL("no type name specified for Field " + fieldName);
173
174 std::unique_ptr<ROOT::Experimental::Detail::RFieldBase> result;
175
176 if (normalizedType == "ROOT::Experimental::ClusterSize_t") {
177 result = std::make_unique<RField<ClusterSize_t>>(fieldName);
178 } else if (normalizedType == "bool") {
179 result = std::make_unique<RField<bool>>(fieldName);
180 } else if (normalizedType == "char") {
181 result = std::make_unique<RField<char>>(fieldName);
182 } else if (normalizedType == "std::int8_t") {
183 result = std::make_unique<RField<std::int8_t>>(fieldName);
184 } else if (normalizedType == "std::uint8_t") {
185 result = std::make_unique<RField<std::uint8_t>>(fieldName);
186 } else if (normalizedType == "std::int16_t") {
187 result = std::make_unique<RField<std::int16_t>>(fieldName);
188 } else if (normalizedType == "std::uint16_t") {
189 result = std::make_unique<RField<std::uint16_t>>(fieldName);
190 } else if (normalizedType == "std::int32_t") {
191 result = std::make_unique<RField<std::int32_t>>(fieldName);
192 } else if (normalizedType == "std::uint32_t") {
193 result = std::make_unique<RField<std::uint32_t>>(fieldName);
194 } else if (normalizedType == "std::int64_t") {
195 result = std::make_unique<RField<std::int64_t>>(fieldName);
196 } else if (normalizedType == "std::uint64_t") {
197 result = std::make_unique<RField<std::uint64_t>>(fieldName);
198 } else if (normalizedType == "float") {
199 result = std::make_unique<RField<float>>(fieldName);
200 } else if (normalizedType == "double") {
201 result = std::make_unique<RField<double>>(fieldName);
202 } else if (normalizedType == "std::string") {
203 result = std::make_unique<RField<std::string>>(fieldName);
204 } else if (normalizedType == "std::vector<bool>") {
205 result = std::make_unique<RField<std::vector<bool>>>(fieldName);
206 } else if (normalizedType.substr(0, 12) == "std::vector<") {
207 std::string itemTypeName = normalizedType.substr(12, normalizedType.length() - 13);
208 auto itemField = Create("_0", itemTypeName);
209 result = std::make_unique<RVectorField>(fieldName, itemField.Unwrap());
210 } else if (normalizedType.substr(0, 19) == "ROOT::VecOps::RVec<") {
211 std::string itemTypeName = normalizedType.substr(19, normalizedType.length() - 20);
212 auto itemField = Create("_0", itemTypeName);
213 result = std::make_unique<RRVecField>(fieldName, itemField.Unwrap());
214 } else if (normalizedType.substr(0, 11) == "std::array<") {
215 auto arrayDef = TokenizeTypeList(normalizedType.substr(11, normalizedType.length() - 12));
216 R__ASSERT(arrayDef.size() == 2);
217 auto arrayLength = std::stoi(arrayDef[1]);
218 auto itemField = Create(GetNormalizedType(arrayDef[0]), arrayDef[0]);
219 result = std::make_unique<RArrayField>(fieldName, itemField.Unwrap(), arrayLength);
220 }
221 if (normalizedType.substr(0, 13) == "std::variant<") {
222 auto innerTypes = TokenizeTypeList(normalizedType.substr(13, normalizedType.length() - 14));
223 std::vector<RFieldBase *> items;
224 for (unsigned int i = 0; i < innerTypes.size(); ++i) {
225 items.emplace_back(Create("_" + std::to_string(i), innerTypes[i]).Unwrap().release());
226 }
227 result = std::make_unique<RVariantField>(fieldName, items);
228 }
229 if (normalizedType.substr(0, 10) == "std::pair<") {
230 auto innerTypes = TokenizeTypeList(normalizedType.substr(10, normalizedType.length() - 11));
231 if (innerTypes.size() != 2)
232 return R__FAIL("the type list for std::pair must have exactly two elements");
233 std::array<std::unique_ptr<RFieldBase>, 2> items{Create("_0", innerTypes[0]).Unwrap(),
234 Create("_1", innerTypes[1]).Unwrap()};
235 result = std::make_unique<RPairField>(fieldName, items);
236 }
237 if (normalizedType.substr(0, 11) == "std::tuple<") {
238 auto innerTypes = TokenizeTypeList(normalizedType.substr(11, normalizedType.length() - 12));
239 std::vector<std::unique_ptr<RFieldBase>> items;
240 for (unsigned int i = 0; i < innerTypes.size(); ++i) {
241 items.emplace_back(Create("_" + std::to_string(i), innerTypes[i]).Unwrap());
242 }
243 result = std::make_unique<RTupleField>(fieldName, items);
244 }
245 // TODO: create an RCollectionField?
246 if (normalizedType == ":Collection:")
247 result = std::make_unique<RField<ClusterSize_t>>(fieldName);
248
249 if (!result) {
250 auto cl = TClass::GetClass(normalizedType.c_str());
251 if (cl != nullptr) {
252 result = std::make_unique<RClassField>(fieldName, normalizedType);
253 }
254 }
255
256 if (result)
257 return result;
258 return R__FAIL(std::string("Field ") + fieldName + " has unknown type " + normalizedType);
259}
260
263{
264 if (fieldName == "") {
265 return R__FAIL("name cannot be empty string \"\"");
266 } else if (fieldName.find(".") != std::string::npos) {
267 return R__FAIL("name '" + std::string(fieldName) + "' cannot contain dot characters '.'");
268 }
269 return RResult<void>::Success();
270}
271
272std::unique_ptr<ROOT::Experimental::Detail::RFieldBase>
274{
275 auto clone = CloneImpl(newName);
276 clone->fOnDiskId = fOnDiskId;
277 clone->fDescription = fDescription;
278 return clone;
279}
280
282{
283 R__ASSERT(false && "A non-simple RField must implement its own AppendImpl");
284 return 0;
285}
286
289 RFieldValue* /*value*/)
290{
291 R__ASSERT(false);
292}
293
295{
296 void *where = malloc(GetValueSize());
297 R__ASSERT(where != nullptr);
298 return GenerateValue(where);
299}
300
302{
303 if (!dtorOnly)
304 free(value.GetRawPtr());
305}
306
307std::vector<ROOT::Experimental::Detail::RFieldValue>
309{
310 return std::vector<RFieldValue>();
311}
312
314 std::unique_ptr<ROOT::Experimental::Detail::RFieldBase> child)
315{
316 child->fParent = this;
317 fSubFields.emplace_back(std::move(child));
318}
319
320
321std::vector<ROOT::Experimental::Detail::RFieldBase *> ROOT::Experimental::Detail::RFieldBase::GetSubFields() const
322{
323 std::vector<RFieldBase *> result;
324 for (const auto &f : fSubFields) {
325 result.emplace_back(f.get());
326 }
327 return result;
328}
329
330
332{
333 for (auto& column : fColumns) {
334 column->Flush();
335 }
336}
337
338
340 const std::vector<EColumnType> &requestedTypes, unsigned int columnIndex, const RNTupleDescriptor &desc)
341{
342 R__ASSERT(!requestedTypes.empty());
343 auto columnId = desc.FindColumnId(fOnDiskId, columnIndex);
344 if (columnId == kInvalidDescriptorId) {
345 throw RException(R__FAIL("Column missing: column #" + std::to_string(columnIndex) +
346 " for field " + fName));
347 }
348
349 const auto &columnDesc = desc.GetColumnDescriptor(columnId);
350 for (auto type : requestedTypes) {
351 if (type == columnDesc.GetModel().GetType())
352 return type;
353 }
354 throw RException(R__FAIL(
355 "On-disk type `" + RColumnElementBase::GetTypeName(columnDesc.GetModel().GetType()) +
356 "` of column #" + std::to_string(columnIndex) + " for field `" + fName +
357 "` is not convertible to the requested type" + [&]{
358 std::string typeStr = requestedTypes.size() > 1 ? "s " : " ";
359 for (std::size_t i = 0; i < requestedTypes.size(); i++) {
360 typeStr += "`" + RColumnElementBase::GetTypeName(requestedTypes[i]) + "`";
361 if (i != requestedTypes.size() - 1) {
362 typeStr += ", ";
363 }
364 }
365 return typeStr;
366 }()
367 ));
368 return columnDesc.GetModel().GetType();
369}
370
371
373{
374 R__ASSERT(fColumns.empty());
375 GenerateColumnsImpl();
376 if (!fColumns.empty())
377 fPrincipalColumn = fColumns[0].get();
378 for (auto& column : fColumns)
379 column->Connect(fOnDiskId, &pageSink);
380}
381
382
384{
385 R__ASSERT(fColumns.empty());
386 {
387 const auto descriptorGuard = pageSource.GetSharedDescriptorGuard();
388 GenerateColumnsImpl(descriptorGuard.GetRef());
389 }
390 if (!fColumns.empty())
391 fPrincipalColumn = fColumns[0].get();
392 for (auto& column : fColumns)
393 column->Connect(fOnDiskId, &pageSource);
394}
395
396
398{
399 visitor.VisitField(*this);
400}
401
402
404{
405 if (fSubFields.empty()) return RSchemaIterator(this, -1);
406 return RSchemaIterator(this->fSubFields[0].get(), 0);
407}
408
409
411{
412 return RSchemaIterator(this, -1);
413}
414
415
416//-----------------------------------------------------------------------------
417
418
420{
421 auto itr = fStack.rbegin();
422 if (!itr->fFieldPtr->fSubFields.empty()) {
423 fStack.emplace_back(Position(itr->fFieldPtr->fSubFields[0].get(), 0));
424 return;
425 }
426
427 unsigned int nextIdxInParent = ++(itr->fIdxInParent);
428 while (nextIdxInParent >= itr->fFieldPtr->fParent->fSubFields.size()) {
429 if (fStack.size() == 1) {
430 itr->fFieldPtr = itr->fFieldPtr->fParent;
431 itr->fIdxInParent = -1;
432 return;
433 }
434 fStack.pop_back();
435 itr = fStack.rbegin();
436 nextIdxInParent = ++(itr->fIdxInParent);
437 }
438 itr->fFieldPtr = itr->fFieldPtr->fParent->fSubFields[nextIdxInParent].get();
439}
440
441
442//------------------------------------------------------------------------------
443
444
445std::unique_ptr<ROOT::Experimental::Detail::RFieldBase>
447{
448 auto result = std::make_unique<RFieldZero>();
449 for (auto &f : fSubFields)
450 result->Attach(f->Clone(f->GetName()));
451 return result;
452}
453
454
456{
457 visitor.VisitFieldZero(*this);
458}
459
460
461//------------------------------------------------------------------------------
462
463
465{
466 RColumnModel model(EColumnType::kIndex, true /* isSorted*/);
467 fColumns.emplace_back(std::unique_ptr<Detail::RColumn>(
468 Detail::RColumn::Create<ClusterSize_t, EColumnType::kIndex>(model, 0)));
469}
470
472{
473 EnsureColumnType({EColumnType::kIndex}, 0, desc);
474 GenerateColumnsImpl();
475}
476
478{
479 visitor.VisitClusterSizeField(*this);
480}
481
482//------------------------------------------------------------------------------
483
485{
486 RColumnModel model(EColumnType::kChar, false /* isSorted*/);
487 fColumns.emplace_back(std::unique_ptr<Detail::RColumn>(Detail::RColumn::Create<
488 char, EColumnType::kChar>(model, 0)));
489}
490
492{
493 EnsureColumnType({EColumnType::kChar}, 0, desc);
494 GenerateColumnsImpl();
495}
496
498{
499 visitor.VisitCharField(*this);
500}
501
502//------------------------------------------------------------------------------
503
505{
506 RColumnModel model(EColumnType::kInt8, false /* isSorted*/);
507 fColumns.emplace_back(std::unique_ptr<Detail::RColumn>(Detail::RColumn::Create<
508 std::int8_t, EColumnType::kInt8>(model, 0)));
509}
510
511void ROOT::Experimental::RField<std::int8_t>::GenerateColumnsImpl(const RNTupleDescriptor &desc)
512{
513 EnsureColumnType({EColumnType::kInt8}, 0, desc);
514 GenerateColumnsImpl();
515}
516
517void ROOT::Experimental::RField<std::int8_t>::AcceptVisitor(Detail::RFieldVisitor &visitor) const
518{
519 visitor.VisitInt8Field(*this);
520}
521
522//------------------------------------------------------------------------------
523
525{
526 RColumnModel model(EColumnType::kInt8, false /* isSorted*/);
527 fColumns.emplace_back(std::unique_ptr<Detail::RColumn>(Detail::RColumn::Create<
528 std::uint8_t, EColumnType::kInt8>(model, 0)));
529}
530
532{
533 EnsureColumnType({EColumnType::kInt8}, 0, desc);
534 GenerateColumnsImpl();
535}
536
537void ROOT::Experimental::RField<std::uint8_t>::AcceptVisitor(Detail::RFieldVisitor &visitor) const
538{
539 visitor.VisitUInt8Field(*this);
540}
541
542//------------------------------------------------------------------------------
543
544
546{
547 RColumnModel model(EColumnType::kBit, false /* isSorted*/);
548 fColumns.emplace_back(std::unique_ptr<Detail::RColumn>(
549 Detail::RColumn::Create<bool, EColumnType::kBit>(model, 0)));
550}
551
553{
554 EnsureColumnType({EColumnType::kBit}, 0, desc);
555 GenerateColumnsImpl();
556}
557
559{
560 visitor.VisitBoolField(*this);
561}
562
563//------------------------------------------------------------------------------
564
565
567{
568 RColumnModel model(EColumnType::kReal32, false /* isSorted*/);
569 fColumns.emplace_back(std::unique_ptr<Detail::RColumn>(
570 Detail::RColumn::Create<float, EColumnType::kReal32>(model, 0)));
571}
572
574{
575 EnsureColumnType({EColumnType::kReal32}, 0, desc);
576 GenerateColumnsImpl();
577}
578
580{
581 visitor.VisitFloatField(*this);
582}
583
584
585//------------------------------------------------------------------------------
586
588{
589 RColumnModel model(EColumnType::kReal64, false /* isSorted*/);
590 fColumns.emplace_back(std::unique_ptr<Detail::RColumn>(
591 Detail::RColumn::Create<double, EColumnType::kReal64>(model, 0)));
592}
593
595{
596 EnsureColumnType({EColumnType::kReal64}, 0, desc);
597 GenerateColumnsImpl();
598}
599
601{
602 visitor.VisitDoubleField(*this);
603}
604
605//------------------------------------------------------------------------------
606
608{
609 RColumnModel model(EColumnType::kInt16, false /* isSorted*/);
610 fColumns.emplace_back(std::unique_ptr<Detail::RColumn>(Detail::RColumn::Create<
611 std::int16_t, EColumnType::kInt16>(model, 0)));
612}
613
615{
616 EnsureColumnType({EColumnType::kInt16}, 0, desc);
617 GenerateColumnsImpl();
618}
619
620void ROOT::Experimental::RField<std::int16_t>::AcceptVisitor(Detail::RFieldVisitor &visitor) const
621{
622 visitor.VisitInt16Field(*this);
623}
624
625//------------------------------------------------------------------------------
626
628{
629 RColumnModel model(EColumnType::kInt16, false /* isSorted*/);
630 fColumns.emplace_back(std::unique_ptr<Detail::RColumn>(Detail::RColumn::Create<
631 std::uint16_t, EColumnType::kInt16>(model, 0)));
632}
633
635{
636 EnsureColumnType({EColumnType::kInt16}, 0, desc);
637 GenerateColumnsImpl();
638}
639
640void ROOT::Experimental::RField<std::uint16_t>::AcceptVisitor(Detail::RFieldVisitor &visitor) const
641{
642 visitor.VisitUInt16Field(*this);
643}
644
645//------------------------------------------------------------------------------
646
648{
649 RColumnModel model(EColumnType::kInt32, false /* isSorted*/);
650 fColumns.emplace_back(std::unique_ptr<Detail::RColumn>(Detail::RColumn::Create<
651 std::int32_t, EColumnType::kInt32>(model, 0)));
652}
653
655{
656 EnsureColumnType({EColumnType::kInt32}, 0, desc);
657 GenerateColumnsImpl();
658}
659
660void ROOT::Experimental::RField<std::int32_t>::AcceptVisitor(Detail::RFieldVisitor &visitor) const
661{
662 visitor.VisitIntField(*this);
663}
664
665//------------------------------------------------------------------------------
666
668{
669 RColumnModel model(EColumnType::kInt32, false /* isSorted*/);
670 fColumns.emplace_back(std::unique_ptr<Detail::RColumn>(
671 Detail::RColumn::Create<std::uint32_t, EColumnType::kInt32>(model, 0)));
672}
673
675{
676 EnsureColumnType({EColumnType::kInt32}, 0, desc);
677 GenerateColumnsImpl();
678}
679
680void ROOT::Experimental::RField<std::uint32_t>::AcceptVisitor(Detail::RFieldVisitor &visitor) const
681{
682 visitor.VisitUInt32Field(*this);
683}
684
685//------------------------------------------------------------------------------
686
688{
689 RColumnModel model(EColumnType::kInt64, false /* isSorted*/);
690 fColumns.emplace_back(std::unique_ptr<Detail::RColumn>(
691 Detail::RColumn::Create<std::uint64_t, EColumnType::kInt64>(model, 0)));
692}
693
695{
696 EnsureColumnType({EColumnType::kInt64}, 0, desc);
697 GenerateColumnsImpl();
698}
699
700void ROOT::Experimental::RField<std::uint64_t>::AcceptVisitor(Detail::RFieldVisitor &visitor) const
701{
702 visitor.VisitUInt64Field(*this);
703}
704
705//------------------------------------------------------------------------------
706
708{
709 RColumnModel model(EColumnType::kInt64, false /* isSorted*/);
710 fColumns.emplace_back(std::unique_ptr<Detail::RColumn>(
711 Detail::RColumn::Create<std::int64_t, EColumnType::kInt64>(model, 0)));
712}
713
715{
716 auto type = EnsureColumnType({EColumnType::kInt64, EColumnType::kInt32}, 0, desc);
717 RColumnModel model(type, false /* isSorted*/);
718 if (type == EColumnType::kInt64) {
719 fColumns.emplace_back(std::unique_ptr<Detail::RColumn>(
720 Detail::RColumn::Create<std::int64_t, EColumnType::kInt64>(model, 0)));
721 } else {
722 fColumns.emplace_back(std::unique_ptr<Detail::RColumn>(
723 Detail::RColumn::Create<std::int64_t, EColumnType::kInt32>(model, 0)));
724 }
725}
726
727void ROOT::Experimental::RField<std::int64_t>::AcceptVisitor(Detail::RFieldVisitor &visitor) const
728{
729 visitor.VisitInt64Field(*this);
730}
731
732//------------------------------------------------------------------------------
733
735{
736 RColumnModel modelIndex(EColumnType::kIndex, true /* isSorted*/);
737 fColumns.emplace_back(std::unique_ptr<Detail::RColumn>(
738 Detail::RColumn::Create<ClusterSize_t, EColumnType::kIndex>(modelIndex, 0)));
739
740 RColumnModel modelChars(EColumnType::kChar, false /* isSorted*/);
741 fColumns.emplace_back(std::unique_ptr<Detail::RColumn>(
742 Detail::RColumn::Create<char, EColumnType::kChar>(modelChars, 1)));
743}
744
745void ROOT::Experimental::RField<std::string>::GenerateColumnsImpl(const RNTupleDescriptor &desc)
746{
747 EnsureColumnType({EColumnType::kIndex}, 0, desc);
748 EnsureColumnType({EColumnType::kChar}, 1, desc);
749 GenerateColumnsImpl();
750}
751
753{
754 auto typedValue = value.Get<std::string>();
755 auto length = typedValue->length();
756 Detail::RColumnElement<char> elemChars(const_cast<char*>(typedValue->data()));
757 fColumns[1]->AppendV(elemChars, length);
758 fIndex += length;
759 fColumns[0]->Append(fElemIndex);
760 return length + sizeof(fElemIndex);
761}
762
765{
766 auto typedValue = value->Get<std::string>();
767 RClusterIndex collectionStart;
768 ClusterSize_t nChars;
769 fPrincipalColumn->GetCollectionInfo(globalIndex, &collectionStart, &nChars);
770 if (nChars == 0) {
771 typedValue->clear();
772 } else {
773 typedValue->resize(nChars);
774 Detail::RColumnElement<char> elemChars(const_cast<char*>(typedValue->data()));
775 fColumns[1]->ReadV(collectionStart, nChars, &elemChars);
776 }
777}
778
780{
781 fIndex = 0;
782}
783
784void ROOT::Experimental::RField<std::string>::AcceptVisitor(Detail::RFieldVisitor &visitor) const
785{
786 visitor.VisitStringField(*this);
787}
788
789//------------------------------------------------------------------------------
790
791
793 : RClassField(fieldName, className, TClass::GetClass(std::string(className).c_str()))
794{
795}
796
798 : ROOT::Experimental::Detail::RFieldBase(fieldName, className, ENTupleStructure::kRecord, false /* isSimple */)
799 , fClass(classp)
800{
801 if (fClass == nullptr) {
802 throw RException(R__FAIL("RField: no I/O support for type " + std::string(className)));
803 }
804 // Avoid accidentally supporting std types through TClass.
806 throw RException(R__FAIL(std::string(className) + " is not supported"));
807 }
808
809 int i = 0;
811 TClass *c = baseClass->GetClassPointer();
812 auto subField = Detail::RFieldBase::Create(std::string(kPrefixInherited) + "_" + std::to_string(i),
813 c->GetName()).Unwrap();
814 Attach(std::move(subField),
815 RSubFieldInfo{kBaseClass, static_cast<std::size_t>(baseClass->GetDelta())});
816 i++;
817 }
819 // Skip members explicitly marked as transient by user comment
820 if (!dataMember->IsPersistent())
821 continue;
822 // Skip, for instance, unscoped enum constants defined in the class
823 if (dataMember->Property() & kIsStatic)
824 continue;
825 auto subField = Detail::RFieldBase::Create(dataMember->GetName(), dataMember->GetFullTypeName()).Unwrap();
826 Attach(std::move(subField),
827 RSubFieldInfo{kDataMember, static_cast<std::size_t>(dataMember->GetOffset())});
828 }
829}
830
831void ROOT::Experimental::RClassField::Attach(std::unique_ptr<Detail::RFieldBase> child, RSubFieldInfo info)
832{
833 fMaxAlignment = std::max(fMaxAlignment, child->GetAlignment());
834 fSubFieldsInfo.push_back(info);
835 RFieldBase::Attach(std::move(child));
836}
837
838std::unique_ptr<ROOT::Experimental::Detail::RFieldBase>
840{
841 return std::unique_ptr<RClassField>(new RClassField(newName, GetType(), fClass));
842}
843
845 std::size_t nbytes = 0;
846 for (unsigned i = 0; i < fSubFields.size(); i++) {
847 auto memberValue = fSubFields[i]->CaptureValue(value.Get<unsigned char>() + fSubFieldsInfo[i].fOffset);
848 nbytes += fSubFields[i]->Append(memberValue);
849 }
850 return nbytes;
851}
852
854{
855 for (unsigned i = 0; i < fSubFields.size(); i++) {
856 auto memberValue = fSubFields[i]->CaptureValue(value->Get<unsigned char>() + fSubFieldsInfo[i].fOffset);
857 fSubFields[i]->Read(globalIndex, &memberValue);
858 }
859}
860
862{
863 for (unsigned i = 0; i < fSubFields.size(); i++) {
864 auto memberValue = fSubFields[i]->CaptureValue(value->Get<unsigned char>() + fSubFieldsInfo[i].fOffset);
865 fSubFields[i]->Read(clusterIndex, &memberValue);
866 }
867}
868
870{
871}
872
874{
875}
876
878{
879 return Detail::RFieldValue(true /* captureFlag */, this, fClass->New(where));
880}
881
883{
884 fClass->Destructor(value.GetRawPtr(), true /* dtorOnly */);
885 if (!dtorOnly)
886 free(value.GetRawPtr());
887}
888
890{
891 return Detail::RFieldValue(true /* captureFlat */, this, where);
892}
893
894
895std::vector<ROOT::Experimental::Detail::RFieldValue>
897{
898 std::vector<Detail::RFieldValue> result;
899 for (unsigned i = 0; i < fSubFields.size(); i++) {
900 auto memberValue = fSubFields[i]->CaptureValue(value.Get<unsigned char>() + fSubFieldsInfo[i].fOffset);
901 result.emplace_back(memberValue);
902 }
903 return result;
904}
905
906
908{
909 return fClass->GetClassSize();
910}
911
913{
914 visitor.VisitClassField(*this);
915}
916
917//------------------------------------------------------------------------------
918
920 std::vector<std::unique_ptr<Detail::RFieldBase>> &&itemFields,
921 const std::vector<std::size_t> &offsets, std::string_view typeName)
922 : ROOT::Experimental::Detail::RFieldBase(fieldName, typeName, ENTupleStructure::kRecord, false /* isSimple */),
923 fOffsets(offsets)
924{
925 for (auto &item : itemFields) {
926 fMaxAlignment = std::max(fMaxAlignment, item->GetAlignment());
927 fSize += GetItemPadding(fSize, item->GetAlignment()) + item->GetValueSize();
928 Attach(std::move(item));
929 }
930}
931
933 std::vector<std::unique_ptr<Detail::RFieldBase>> &&itemFields)
934 : ROOT::Experimental::Detail::RFieldBase(fieldName, "", ENTupleStructure::kRecord, false /* isSimple */)
935{
936 for (auto &item : itemFields) {
937 fSize += GetItemPadding(fSize, item->GetAlignment());
938 fOffsets.push_back(fSize);
939 fMaxAlignment = std::max(fMaxAlignment, item->GetAlignment());
940 fSize += item->GetValueSize();
941 Attach(std::move(item));
942 }
943 // Trailing padding: although this is implementation-dependent, most add enough padding to comply with the
944 // requirements of the type with strictest alignment
946}
947
949 std::vector<std::unique_ptr<Detail::RFieldBase>> &itemFields)
950 : ROOT::Experimental::RRecordField(fieldName, std::move(itemFields))
951{
952}
953
954std::size_t ROOT::Experimental::RRecordField::GetItemPadding(std::size_t baseOffset, std::size_t itemAlignment) const
955{
956 if (itemAlignment > 1) {
957 auto remainder = baseOffset % itemAlignment;
958 if (remainder != 0)
959 return itemAlignment - remainder;
960 }
961 return 0;
962}
963
964std::unique_ptr<ROOT::Experimental::Detail::RFieldBase>
966{
967 std::vector<std::unique_ptr<Detail::RFieldBase>> cloneItems;
968 for (auto &item : fSubFields)
969 cloneItems.emplace_back(item->Clone(item->GetName()));
970 return std::unique_ptr<RRecordField>(new RRecordField(newName, std::move(cloneItems), fOffsets, GetType()));
971}
972
974 std::size_t nbytes = 0;
975 for (unsigned i = 0; i < fSubFields.size(); ++i) {
976 auto memberValue = fSubFields[i]->CaptureValue(value.Get<unsigned char>() + fOffsets[i]);
977 nbytes += fSubFields[i]->Append(memberValue);
978 }
979 return nbytes;
980}
981
983{
984 for (unsigned i = 0; i < fSubFields.size(); ++i) {
985 auto memberValue = fSubFields[i]->CaptureValue(value->Get<unsigned char>() + fOffsets[i]);
986 fSubFields[i]->Read(globalIndex, &memberValue);
987 }
988}
989
991{
992 for (unsigned i = 0; i < fSubFields.size(); ++i) {
993 auto memberValue = fSubFields[i]->CaptureValue(value->Get<unsigned char>() + fOffsets[i]);
994 fSubFields[i]->Read(clusterIndex, &memberValue);
995 }
996}
997
999{
1000 for (unsigned i = 0; i < fSubFields.size(); ++i) {
1001 fSubFields[i]->GenerateValue(static_cast<unsigned char *>(where) + fOffsets[i]);
1002 }
1003 return Detail::RFieldValue(true /* captureFlag */, this, where);
1004}
1005
1007{
1008 for (unsigned i = 0; i < fSubFields.size(); ++i) {
1009 auto memberValue = fSubFields[i]->CaptureValue(value.Get<unsigned char>() + fOffsets[i]);
1010 fSubFields[i]->DestroyValue(memberValue, true /* dtorOnly */);
1011 }
1012
1013 if (!dtorOnly)
1014 free(value.GetRawPtr());
1015}
1016
1018{
1019 return Detail::RFieldValue(true /* captureFlag */, this, where);
1020}
1021
1022
1023std::vector<ROOT::Experimental::Detail::RFieldValue>
1025{
1026 std::vector<Detail::RFieldValue> result;
1027 for (unsigned i = 0; i < fSubFields.size(); ++i) {
1028 result.emplace_back(fSubFields[i]->CaptureValue(value.Get<unsigned char>() + fOffsets[i]));
1029 }
1030 return result;
1031}
1032
1033
1035{
1036 visitor.VisitRecordField(*this);
1037}
1038
1039//------------------------------------------------------------------------------
1040
1041
1043 std::string_view fieldName, std::unique_ptr<Detail::RFieldBase> itemField)
1044 : ROOT::Experimental::Detail::RFieldBase(
1045 fieldName, "std::vector<" + itemField->GetType() + ">", ENTupleStructure::kCollection, false /* isSimple */)
1046 , fItemSize(itemField->GetValueSize()), fNWritten(0)
1047{
1048 Attach(std::move(itemField));
1049}
1050
1051std::unique_ptr<ROOT::Experimental::Detail::RFieldBase>
1053{
1054 auto newItemField = fSubFields[0]->Clone(fSubFields[0]->GetName());
1055 return std::make_unique<RVectorField>(newName, std::move(newItemField));
1056}
1057
1059 auto typedValue = value.Get<std::vector<char>>();
1060 R__ASSERT((typedValue->size() % fItemSize) == 0);
1061 std::size_t nbytes = 0;
1062 auto count = typedValue->size() / fItemSize;
1063 for (unsigned i = 0; i < count; ++i) {
1064 auto itemValue = fSubFields[0]->CaptureValue(typedValue->data() + (i * fItemSize));
1065 nbytes += fSubFields[0]->Append(itemValue);
1066 }
1067 Detail::RColumnElement<ClusterSize_t> elemIndex(&fNWritten);
1068 fNWritten += count;
1069 fColumns[0]->Append(elemIndex);
1070 return nbytes + sizeof(elemIndex);
1071}
1072
1074{
1075 auto typedValue = value->Get<std::vector<char>>();
1076
1077 ClusterSize_t nItems;
1078 RClusterIndex collectionStart;
1079 fPrincipalColumn->GetCollectionInfo(globalIndex, &collectionStart, &nItems);
1080
1081 auto oldNItems = typedValue->size() / fItemSize;
1082 for (std::size_t i = nItems; i < oldNItems; ++i) {
1083 auto itemValue = fSubFields[0]->CaptureValue(typedValue->data() + (i * fItemSize));
1084 fSubFields[0]->DestroyValue(itemValue, true /* dtorOnly */);
1085 }
1086 typedValue->resize(nItems * fItemSize);
1087 for (std::size_t i = oldNItems; i < nItems; ++i) {
1088 fSubFields[0]->GenerateValue(typedValue->data() + (i * fItemSize));
1089 }
1090
1091 for (std::size_t i = 0; i < nItems; ++i) {
1092 auto itemValue = fSubFields[0]->CaptureValue(typedValue->data() + (i * fItemSize));
1093 fSubFields[0]->Read(collectionStart + i, &itemValue);
1094 }
1095}
1096
1098{
1099 RColumnModel modelIndex(EColumnType::kIndex, true /* isSorted*/);
1100 fColumns.emplace_back(std::unique_ptr<Detail::RColumn>(
1101 Detail::RColumn::Create<ClusterSize_t, EColumnType::kIndex>(modelIndex, 0)));
1102}
1103
1105{
1106 EnsureColumnType({EColumnType::kIndex}, 0, desc);
1107 GenerateColumnsImpl();
1108}
1109
1111{
1112 return Detail::RFieldValue(this, reinterpret_cast<std::vector<char>*>(where));
1113}
1114
1116{
1117 auto vec = static_cast<std::vector<char>*>(value.GetRawPtr());
1118 R__ASSERT((vec->size() % fItemSize) == 0);
1119 auto nItems = vec->size() / fItemSize;
1120 for (unsigned i = 0; i < nItems; ++i) {
1121 auto itemValue = fSubFields[0]->CaptureValue(vec->data() + (i * fItemSize));
1122 fSubFields[0]->DestroyValue(itemValue, true /* dtorOnly */);
1123 }
1124 vec->~vector();
1125 if (!dtorOnly)
1126 free(vec);
1127}
1128
1130{
1131 return Detail::RFieldValue(true /* captureFlag */, this, where);
1132}
1133
1134std::vector<ROOT::Experimental::Detail::RFieldValue>
1136{
1137 auto vec = static_cast<std::vector<char>*>(value.GetRawPtr());
1138 R__ASSERT((vec->size() % fItemSize) == 0);
1139 auto nItems = vec->size() / fItemSize;
1140 std::vector<Detail::RFieldValue> result;
1141 for (unsigned i = 0; i < nItems; ++i) {
1142 result.emplace_back(fSubFields[0]->CaptureValue(vec->data() + (i * fItemSize)));
1143 }
1144 return result;
1145}
1146
1148{
1149 fNWritten = 0;
1150}
1151
1153{
1154 visitor.VisitVectorField(*this);
1155}
1156
1157
1158//------------------------------------------------------------------------------
1159
1160ROOT::Experimental::RRVecField::RRVecField(std::string_view fieldName, std::unique_ptr<Detail::RFieldBase> itemField)
1161 : ROOT::Experimental::Detail::RFieldBase(fieldName, "ROOT::VecOps::RVec<" + itemField->GetType() + ">",
1162 ENTupleStructure::kCollection, false /* isSimple */),
1163 fItemSize(itemField->GetValueSize()), fNWritten(0)
1164{
1165 Attach(std::move(itemField));
1166 fValueSize = EvalValueSize(); // requires fSubFields to be populated
1167}
1168
1169std::unique_ptr<ROOT::Experimental::Detail::RFieldBase>
1171{
1172 auto newItemField = fSubFields[0]->Clone(fSubFields[0]->GetName());
1173 return std::make_unique<RRVecField>(newName, std::move(newItemField));
1174}
1175
1177{
1178 auto [beginPtr, sizePtr, _] = GetRVecDataMembers(value.GetRawPtr());
1179
1180 std::size_t nbytes = 0;
1181 char *begin = reinterpret_cast<char *>(*beginPtr); // for pointer arithmetics
1182 for (std::int32_t i = 0; i < *sizePtr; ++i) {
1183 auto elementValue = fSubFields[0]->CaptureValue(begin + i * fItemSize);
1184 nbytes += fSubFields[0]->Append(elementValue);
1185 }
1186
1187 Detail::RColumnElement<ClusterSize_t> elemIndex(&fNWritten);
1188 fNWritten += *sizePtr;
1189 fColumns[0]->Append(elemIndex);
1190 return nbytes + sizeof(elemIndex);
1191}
1192
1194{
1195 // TODO as a performance optimization, we could assign values to elements of the inline buffer:
1196 // if size < inline buffer size: we save one allocation here and usage of the RVec skips a pointer indirection
1197
1198 auto [beginPtr, sizePtr, capacityPtr] = GetRVecDataMembers(value->GetRawPtr());
1199
1200 // Read collection info for this entry
1201 ClusterSize_t nItems;
1202 RClusterIndex collectionStart;
1203 fPrincipalColumn->GetCollectionInfo(globalIndex, &collectionStart, &nItems);
1204 char *begin = reinterpret_cast<char *>(*beginPtr); // for pointer arithmetics
1205 const std::size_t oldSize = *sizePtr;
1206
1207 // Destroy excess elements, if any
1208 for (std::size_t i = nItems; i < oldSize; ++i) {
1209 auto itemValue = fSubFields[0]->CaptureValue(begin + (i * fItemSize));
1210 fSubFields[0]->DestroyValue(itemValue, true /* dtorOnly */);
1211 }
1212
1213 // Resize RVec (capacity and size)
1214 if (std::int32_t(nItems) > *capacityPtr) { // must reallocate
1215 // Destroy old elements: useless work for trivial types, but in case the element type's constructor
1216 // allocates memory we need to release it here to avoid memleaks (e.g. if this is an RVec<RVec<int>>)
1217 for (std::size_t i = 0u; i < oldSize; ++i) {
1218 auto itemValue = fSubFields[0]->CaptureValue(begin + (i * fItemSize));
1219 fSubFields[0]->DestroyValue(itemValue, true /* dtorOnly */);
1220 }
1221
1222 // TODO Increment capacity by a factor rather than just enough to fit the elements.
1223 free(*beginPtr);
1224 // We trust that malloc returns a buffer with large enough alignment.
1225 // This might not be the case if T in RVec<T> is over-aligned.
1226 *beginPtr = malloc(nItems * fItemSize);
1227 R__ASSERT(*beginPtr != nullptr);
1228 begin = reinterpret_cast<char *>(*beginPtr);
1229 *capacityPtr = nItems;
1230
1231 // Placement new for elements that were already there before the resize
1232 for (std::size_t i = 0u; i < oldSize; ++i)
1233 fSubFields[0]->GenerateValue(begin + (i * fItemSize));
1234 }
1235 *sizePtr = nItems;
1236
1237 // Placement new for new elements, if any
1238 for (std::size_t i = oldSize; i < nItems; ++i)
1239 fSubFields[0]->GenerateValue(begin + (i * fItemSize));
1240
1241 // Read the new values into the collection elements
1242 for (std::size_t i = 0; i < nItems; ++i) {
1243 auto itemValue = fSubFields[0]->CaptureValue(begin + (i * fItemSize));
1244 fSubFields[0]->Read(collectionStart + i, &itemValue);
1245 }
1246}
1247
1249{
1250 RColumnModel modelIndex(EColumnType::kIndex, true /* isSorted*/);
1251 fColumns.emplace_back(
1252 std::unique_ptr<Detail::RColumn>(Detail::RColumn::Create<ClusterSize_t, EColumnType::kIndex>(modelIndex, 0)));
1253}
1254
1256{
1257 EnsureColumnType({EColumnType::kIndex}, 0, desc);
1258 GenerateColumnsImpl();
1259}
1260
1262{
1263 // initialize data members fBegin, fSize, fCapacity
1264 // currently the inline buffer is left uninitialized
1265 void **beginPtr = new (where)(void *)(nullptr);
1266 std::int32_t *sizePtr = new (reinterpret_cast<void *>(beginPtr + 1)) std::int32_t(0);
1267 new (sizePtr + 1) std::int32_t(0);
1268
1269 return Detail::RFieldValue(/*captureTag*/ true, this, where);
1270}
1271
1273{
1274 auto [beginPtr, sizePtr, capacityPtr] = GetRVecDataMembers(value.GetRawPtr());
1275
1276 char *begin = reinterpret_cast<char *>(*beginPtr); // for pointer arithmetics
1277 for (std::int32_t i = 0; i < *sizePtr; ++i) {
1278 auto elementValue = fSubFields[0]->CaptureValue(begin + i * fItemSize);
1279 fSubFields[0]->DestroyValue(elementValue, true /* dtorOnly */);
1280 }
1281
1282 // figure out if we are in the small state, i.e. begin == &inlineBuffer
1283 // there might be padding between fCapacity and the inline buffer, so we compute it here
1284 constexpr auto dataMemberSz = sizeof(void *) + 2 * sizeof(std::int32_t);
1285 const auto alignOfT = fSubFields[0]->GetAlignment();
1286 auto paddingMiddle = dataMemberSz % alignOfT;
1287 if (paddingMiddle != 0)
1288 paddingMiddle = alignOfT - paddingMiddle;
1289 const bool isSmall = (reinterpret_cast<void *>(begin) == (beginPtr + dataMemberSz + paddingMiddle));
1290
1291 const bool owns = (*capacityPtr != -1);
1292 if (!isSmall && owns)
1293 free(begin);
1294
1295 if (!dtorOnly)
1296 free(beginPtr);
1297}
1298
1300{
1301 return Detail::RFieldValue(true /* captureFlag */, this, where);
1302}
1303
1304std::vector<ROOT::Experimental::Detail::RFieldValue>
1306{
1307 auto [beginPtr, sizePtr, _] = GetRVecDataMembers(value.GetRawPtr());
1308
1309 std::vector<Detail::RFieldValue> result;
1310 char *begin = reinterpret_cast<char *>(*beginPtr); // for pointer arithmetics
1311 for (std::int32_t i = 0; i < *sizePtr; ++i) {
1312 auto elementValue = fSubFields[0]->CaptureValue(begin + i * fItemSize);
1313 result.emplace_back(std::move(elementValue));
1314 }
1315 return result;
1316}
1317
1319{
1320 // the size of an RVec<T> is the size of its 4 data-members + optional padding:
1321 //
1322 // data members:
1323 // - void *fBegin
1324 // - int32_t fSize
1325 // - int32_t fCapacity
1326 // - the char[] inline storage, which is aligned like T
1327 //
1328 // padding might be present:
1329 // - between fCapacity and the char[] buffer aligned like T
1330 // - after the char[] buffer
1331
1332 constexpr auto dataMemberSz = sizeof(void *) + 2 * sizeof(std::int32_t);
1333 const auto alignOfT = fSubFields[0]->GetAlignment();
1334 const auto sizeOfT = fSubFields[0]->GetValueSize();
1335
1336 // mimic the logic of RVecInlineStorageSize, but at runtime
1337 const auto inlineStorageSz = [&] {
1338#ifdef R__HAS_HARDWARE_INTERFERENCE_SIZE
1339 // hardware_destructive_interference_size is a C++17 feature but many compilers do not implement it yet
1340 constexpr unsigned cacheLineSize = std::hardware_destructive_interference_size;
1341#else
1342 constexpr unsigned cacheLineSize = 64u;
1343#endif
1344 const unsigned elementsPerCacheLine = (cacheLineSize - dataMemberSz) / sizeOfT;
1345 constexpr unsigned maxInlineByteSize = 1024;
1346 const unsigned nElements =
1347 elementsPerCacheLine >= 8 ? elementsPerCacheLine : (sizeOfT * 8 > maxInlineByteSize ? 0 : 8);
1348 return nElements * sizeOfT;
1349 }();
1350
1351 // compute padding between first 3 datamembers and inline buffer
1352 // (there should be no padding between the first 3 data members)
1353 auto paddingMiddle = dataMemberSz % alignOfT;
1354 if (paddingMiddle != 0)
1355 paddingMiddle = alignOfT - paddingMiddle;
1356
1357 // padding at the end of the object
1358 const auto alignOfRVecT = GetAlignment();
1359 auto paddingEnd = (dataMemberSz + paddingMiddle + inlineStorageSz) % alignOfRVecT;
1360 if (paddingEnd != 0)
1361 paddingEnd = alignOfRVecT - paddingEnd;
1362
1363 return dataMemberSz + inlineStorageSz + paddingMiddle + paddingEnd;
1364}
1365
1367{
1368 return fValueSize;
1369}
1370
1372{
1373 // the alignment of an RVec<T> is the largest among the alignments of its data members
1374 // (including the inline buffer which has the same alignment as the RVec::value_type)
1375 return std::max({alignof(void *), alignof(std::int32_t), fSubFields[0]->GetAlignment()});
1376}
1377
1379{
1380 fNWritten = 0;
1381}
1382
1384{
1385 visitor.VisitRVecField(*this);
1386}
1387
1388//------------------------------------------------------------------------------
1389
1391 : ROOT::Experimental::Detail::RFieldBase(name, "std::vector<bool>", ENTupleStructure::kCollection,
1392 false /* isSimple */)
1393{
1394 Attach(std::make_unique<RField<bool>>("_0"));
1395}
1396
1397std::size_t ROOT::Experimental::RField<std::vector<bool>>::AppendImpl(const Detail::RFieldValue& value) {
1398 auto typedValue = value.Get<std::vector<bool>>();
1399 auto count = typedValue->size();
1400 for (unsigned i = 0; i < count; ++i) {
1401 bool bval = (*typedValue)[i];
1402 auto itemValue = fSubFields[0]->CaptureValue(&bval);
1403 fSubFields[0]->Append(itemValue);
1404 }
1405 Detail::RColumnElement<ClusterSize_t> elemIndex(&fNWritten);
1406 fNWritten += count;
1407 fColumns[0]->Append(elemIndex);
1408 return count + sizeof(elemIndex);
1409}
1410
1411void ROOT::Experimental::RField<std::vector<bool>>::ReadGlobalImpl(NTupleSize_t globalIndex, Detail::RFieldValue* value)
1412{
1413 auto typedValue = value->Get<std::vector<bool>>();
1414
1415 ClusterSize_t nItems;
1416 RClusterIndex collectionStart;
1417 fPrincipalColumn->GetCollectionInfo(globalIndex, &collectionStart, &nItems);
1418
1419 typedValue->resize(nItems);
1420 for (unsigned i = 0; i < nItems; ++i) {
1421 bool bval;
1422 auto itemValue = fSubFields[0]->GenerateValue(&bval);
1423 fSubFields[0]->Read(collectionStart + i, &itemValue);
1424 (*typedValue)[i] = bval;
1425 }
1426}
1427
1428void ROOT::Experimental::RField<std::vector<bool>>::GenerateColumnsImpl()
1429{
1430 RColumnModel modelIndex(EColumnType::kIndex, true /* isSorted*/);
1431 fColumns.emplace_back(std::unique_ptr<Detail::RColumn>(
1432 Detail::RColumn::Create<ClusterSize_t, EColumnType::kIndex>(modelIndex, 0)));
1433}
1434
1435void ROOT::Experimental::RField<std::vector<bool>>::GenerateColumnsImpl(const RNTupleDescriptor &desc)
1436{
1437 EnsureColumnType({EColumnType::kIndex}, 0, desc);
1438 GenerateColumnsImpl();
1439}
1440
1441std::vector<ROOT::Experimental::Detail::RFieldValue>
1442ROOT::Experimental::RField<std::vector<bool>>::SplitValue(const Detail::RFieldValue& value) const
1443{
1444 const static bool trueValue = true;
1445 const static bool falseValue = false;
1446
1447 auto typedValue = value.Get<std::vector<bool>>();
1448 auto count = typedValue->size();
1449 std::vector<Detail::RFieldValue> result;
1450 for (unsigned i = 0; i < count; ++i) {
1451 if ((*typedValue)[i])
1452 result.emplace_back(fSubFields[0]->CaptureValue(const_cast<bool *>(&trueValue)));
1453 else
1454 result.emplace_back(fSubFields[0]->CaptureValue(const_cast<bool *>(&falseValue)));
1455 }
1456 return result;
1457}
1458
1459
1460void ROOT::Experimental::RField<std::vector<bool>>::DestroyValue(const Detail::RFieldValue& value, bool dtorOnly)
1461{
1462 auto vec = static_cast<std::vector<bool>*>(value.GetRawPtr());
1463 vec->~vector();
1464 if (!dtorOnly)
1465 free(vec);
1466}
1467
1468void ROOT::Experimental::RField<std::vector<bool>>::AcceptVisitor(Detail::RFieldVisitor &visitor) const
1469{
1470 visitor.VisitVectorBoolField(*this);
1471}
1472
1473
1474//------------------------------------------------------------------------------
1475
1476
1478 std::string_view fieldName, std::unique_ptr<Detail::RFieldBase> itemField, std::size_t arrayLength)
1479 : ROOT::Experimental::Detail::RFieldBase(
1480 fieldName, "std::array<" + itemField->GetType() + "," + std::to_string(arrayLength) + ">",
1481 ENTupleStructure::kLeaf, false /* isSimple */, arrayLength)
1482 , fItemSize(itemField->GetValueSize()), fArrayLength(arrayLength)
1483{
1484 Attach(std::move(itemField));
1485}
1486
1487std::unique_ptr<ROOT::Experimental::Detail::RFieldBase>
1489{
1490 auto newItemField = fSubFields[0]->Clone(fSubFields[0]->GetName());
1491 return std::make_unique<RArrayField>(newName, std::move(newItemField), fArrayLength);
1492}
1493
1495 std::size_t nbytes = 0;
1496 auto arrayPtr = value.Get<unsigned char>();
1497 for (unsigned i = 0; i < fArrayLength; ++i) {
1498 auto itemValue = fSubFields[0]->CaptureValue(arrayPtr + (i * fItemSize));
1499 nbytes += fSubFields[0]->Append(itemValue);
1500 }
1501 return nbytes;
1502}
1503
1505{
1506 auto arrayPtr = value->Get<unsigned char>();
1507 for (unsigned i = 0; i < fArrayLength; ++i) {
1508 auto itemValue = fSubFields[0]->GenerateValue(arrayPtr + (i * fItemSize));
1509 fSubFields[0]->Read(globalIndex * fArrayLength + i, &itemValue);
1510 }
1511}
1512
1514{
1515 auto arrayPtr = value->Get<unsigned char>();
1516 for (unsigned i = 0; i < fArrayLength; ++i) {
1517 auto itemValue = fSubFields[0]->GenerateValue(arrayPtr + (i * fItemSize));
1518 fSubFields[0]->Read(RClusterIndex(clusterIndex.GetClusterId(), clusterIndex.GetIndex() * fArrayLength + i),
1519 &itemValue);
1520 }
1521}
1522
1524{
1525}
1526
1528{
1529}
1530
1532{
1533 auto arrayPtr = reinterpret_cast<unsigned char *>(where);
1534 for (unsigned i = 0; i < fArrayLength; ++i) {
1535 fSubFields[0]->GenerateValue(arrayPtr + (i * fItemSize));
1536 }
1537 return Detail::RFieldValue(true /* captureFlag */, this, where);
1538}
1539
1541{
1542 auto arrayPtr = value.Get<unsigned char>();
1543 for (unsigned i = 0; i < fArrayLength; ++i) {
1544 auto itemValue = fSubFields[0]->CaptureValue(arrayPtr + (i * fItemSize));
1545 fSubFields[0]->DestroyValue(itemValue, true /* dtorOnly */);
1546 }
1547 if (!dtorOnly)
1548 free(arrayPtr);
1549}
1550
1552{
1553 return Detail::RFieldValue(true /* captureFlag */, this, where);
1554}
1555
1556std::vector<ROOT::Experimental::Detail::RFieldValue>
1558{
1559 auto arrayPtr = value.Get<unsigned char>();
1560 std::vector<Detail::RFieldValue> result;
1561 for (unsigned i = 0; i < fArrayLength; ++i) {
1562 auto itemValue = fSubFields[0]->CaptureValue(arrayPtr + (i * fItemSize));
1563 result.emplace_back(itemValue);
1564 }
1565 return result;
1566}
1567
1569{
1570 visitor.VisitArrayField(*this);
1571}
1572
1573//------------------------------------------------------------------------------
1574
1575std::string ROOT::Experimental::RVariantField::GetTypeList(const std::vector<Detail::RFieldBase *> &itemFields)
1576{
1577 std::string result;
1578 for (size_t i = 0; i < itemFields.size(); ++i) {
1579 result += itemFields[i]->GetType() + ",";
1580 }
1581 R__ASSERT(!result.empty()); // there is always at least one variant
1582 result.pop_back(); // remove trailing comma
1583 return result;
1584}
1585
1587 std::string_view fieldName, const std::vector<Detail::RFieldBase *> &itemFields)
1588 : ROOT::Experimental::Detail::RFieldBase(fieldName,
1589 "std::variant<" + GetTypeList(itemFields) + ">", ENTupleStructure::kVariant, false /* isSimple */)
1590{
1591 auto nFields = itemFields.size();
1592 R__ASSERT(nFields > 0);
1593 fNWritten.resize(nFields, 0);
1594 for (unsigned int i = 0; i < nFields; ++i) {
1595 fMaxItemSize = std::max(fMaxItemSize, itemFields[i]->GetValueSize());
1596 fMaxAlignment = std::max(fMaxAlignment, itemFields[i]->GetAlignment());
1597 Attach(std::unique_ptr<Detail::RFieldBase>(itemFields[i]));
1598 }
1600}
1601
1602std::unique_ptr<ROOT::Experimental::Detail::RFieldBase>
1604{
1605 auto nFields = fSubFields.size();
1606 std::vector<Detail::RFieldBase *> itemFields;
1607 for (unsigned i = 0; i < nFields; ++i) {
1608 // TODO(jblomer): use unique_ptr in RVariantField constructor
1609 itemFields.emplace_back(fSubFields[i]->Clone(fSubFields[i]->GetName()).release());
1610 }
1611 return std::make_unique<RVariantField>(newName, itemFields);
1612}
1613
1614std::uint32_t ROOT::Experimental::RVariantField::GetTag(void *variantPtr) const
1615{
1616 auto index = *(reinterpret_cast<char *>(variantPtr) + fTagOffset);
1617 return (index < 0) ? 0 : index + 1;
1618}
1619
1620void ROOT::Experimental::RVariantField::SetTag(void *variantPtr, std::uint32_t tag) const
1621{
1622 auto index = reinterpret_cast<char *>(variantPtr) + fTagOffset;
1623 *index = static_cast<char>(tag - 1);
1624}
1625
1627{
1628 auto tag = GetTag(value.GetRawPtr());
1629 std::size_t nbytes = 0;
1630 auto index = 0;
1631 if (tag > 0) {
1632 auto itemValue = fSubFields[tag - 1]->CaptureValue(value.GetRawPtr());
1633 nbytes += fSubFields[tag - 1]->Append(itemValue);
1634 index = fNWritten[tag - 1]++;
1635 }
1636 RColumnSwitch varSwitch(ClusterSize_t(index), tag);
1637 Detail::RColumnElement<RColumnSwitch> elemSwitch(&varSwitch);
1638 fColumns[0]->Append(elemSwitch);
1639 return nbytes + sizeof(RColumnSwitch);
1640}
1641
1643{
1644 RClusterIndex variantIndex;
1645 std::uint32_t tag;
1646 fPrincipalColumn->GetSwitchInfo(globalIndex, &variantIndex, &tag);
1647 R__ASSERT(tag > 0); // TODO(jblomer): deal with invalid variants
1648
1649 auto itemValue = fSubFields[tag - 1]->GenerateValue(value->GetRawPtr());
1650 fSubFields[tag - 1]->Read(variantIndex, &itemValue);
1651 SetTag(value->GetRawPtr(), tag);
1652}
1653
1655{
1656 RColumnModel modelSwitch(EColumnType::kSwitch, false);
1657 fColumns.emplace_back(std::unique_ptr<Detail::RColumn>(
1658 Detail::RColumn::Create<RColumnSwitch, EColumnType::kSwitch>(modelSwitch, 0)));
1659}
1660
1662{
1663 EnsureColumnType({EColumnType::kSwitch}, 0, desc);
1664 GenerateColumnsImpl();
1665}
1666
1668{
1669 memset(where, 0, GetValueSize());
1670 fSubFields[0]->GenerateValue(where);
1671 SetTag(where, 1);
1672 return Detail::RFieldValue(this, reinterpret_cast<unsigned char *>(where));
1673}
1674
1676{
1677 auto variantPtr = value.GetRawPtr();
1678 auto tag = GetTag(variantPtr);
1679 if (tag > 0) {
1680 auto itemValue = fSubFields[tag - 1]->CaptureValue(variantPtr);
1681 fSubFields[tag - 1]->DestroyValue(itemValue, true /* dtorOnly */);
1682 }
1683 if (!dtorOnly)
1684 free(variantPtr);
1685}
1686
1688{
1689 return Detail::RFieldValue(true /* captureFlag */, this, where);
1690}
1691
1693{
1694 return fMaxItemSize + fMaxAlignment; // TODO: fix for more than 255 items
1695}
1696
1698{
1699 std::fill(fNWritten.begin(), fNWritten.end(), 0);
1700}
1701
1702//------------------------------------------------------------------------------
1703
1704std::string ROOT::Experimental::RPairField::RPairField::GetTypeList(
1705 const std::array<std::unique_ptr<Detail::RFieldBase>, 2> &itemFields)
1706{
1707 return itemFields[0]->GetType() + "," + itemFields[1]->GetType();
1708}
1709
1711 std::array<std::unique_ptr<Detail::RFieldBase>, 2> &&itemFields,
1712 const std::array<std::size_t, 2> &offsets)
1713 : ROOT::Experimental::RRecordField(fieldName, std::move(itemFields), offsets,
1714 "std::pair<" + GetTypeList(itemFields) + ">")
1715{
1716}
1717
1719 std::array<std::unique_ptr<Detail::RFieldBase>, 2> &itemFields)
1720 : ROOT::Experimental::RRecordField(fieldName, std::move(itemFields), {},
1721 "std::pair<" + GetTypeList(itemFields) + ">")
1722{
1723 // ISO C++ does not guarantee any specific layout for `std::pair`; query TClass for the member offsets
1724 fClass = TClass::GetClass(GetType().c_str());
1725 if (!fClass)
1726 throw RException(R__FAIL("cannot get type information for " + GetType()));
1727 fSize = fClass->Size();
1728 fOffsets[0] = fClass->GetDataMember("first")->GetOffset();
1729 fOffsets[1] = fClass->GetDataMember("second")->GetOffset();
1730}
1731
1732std::unique_ptr<ROOT::Experimental::Detail::RFieldBase>
1734{
1735 std::array<std::unique_ptr<Detail::RFieldBase>, 2> items{fSubFields[0]->Clone(fSubFields[0]->GetName()),
1736 fSubFields[1]->Clone(fSubFields[1]->GetName())};
1737
1738 std::unique_ptr<RPairField> result(new RPairField(newName, std::move(items), {fOffsets[0], fOffsets[1]}));
1739 result->fClass = fClass;
1740 return result;
1741}
1742
1744{
1745 return Detail::RFieldValue(true /* captureFlag */, this, fClass->New(where));
1746}
1747
1749{
1750 fClass->Destructor(value.GetRawPtr(), true /* dtorOnly */);
1751 if (!dtorOnly)
1752 free(value.GetRawPtr());
1753}
1754
1755//------------------------------------------------------------------------------
1756
1757std::string ROOT::Experimental::RTupleField::RTupleField::GetTypeList(
1758 const std::vector<std::unique_ptr<Detail::RFieldBase>> &itemFields)
1759{
1760 std::string result;
1761 if (itemFields.empty())
1762 throw RException(R__FAIL("the type list for std::tuple must have at least one element"));
1763 for (size_t i = 0; i < itemFields.size(); ++i) {
1764 result += itemFields[i]->GetType() + ",";
1765 }
1766 result.pop_back(); // remove trailing comma
1767 return result;
1768}
1769
1771 std::vector<std::unique_ptr<Detail::RFieldBase>> &&itemFields,
1772 const std::vector<std::size_t> &offsets)
1773 : ROOT::Experimental::RRecordField(fieldName, std::move(itemFields), offsets,
1774 "std::tuple<" + GetTypeList(itemFields) + ">")
1775{
1776}
1777
1779 std::vector<std::unique_ptr<Detail::RFieldBase>> &itemFields)
1780 : ROOT::Experimental::RRecordField(fieldName, std::move(itemFields), {},
1781 "std::tuple<" + GetTypeList(itemFields) + ">")
1782{
1783 fClass = TClass::GetClass(GetType().c_str());
1784 if (!fClass)
1785 throw RException(R__FAIL("cannot get type information for " + GetType()));
1786 fSize = fClass->Size();
1787
1788 // ISO C++ does not guarantee neither specific layout nor member names for `std::tuple`. However, most
1789 // implementations including libstdc++ (gcc), libc++ (llvm), and MSVC name members as `_0`, `_1`, ..., `_N-1`,
1790 // following the order of the type list.
1791 // Use TClass to get their offsets; in case a particular `std::tuple` implementation does not define such
1792 // members, the assertion below will fail.
1793 for (unsigned i = 0; i < fSubFields.size(); ++i) {
1794 std::string memberName("_" + std::to_string(i));
1795 auto member = fClass->GetRealData(memberName.c_str());
1796 if (!member)
1797 throw RException(R__FAIL(memberName + ": no such member"));
1798 fOffsets.push_back(member->GetThisOffset());
1799 }
1800}
1801
1802std::unique_ptr<ROOT::Experimental::Detail::RFieldBase>
1804{
1805 std::vector<std::unique_ptr<Detail::RFieldBase>> items;
1806 for (const auto &item : fSubFields)
1807 items.push_back(item->Clone(item->GetName()));
1808
1809 std::unique_ptr<RTupleField> result(new RTupleField(newName, std::move(items), fOffsets));
1810 result->fClass = fClass;
1811 return result;
1812}
1813
1815{
1816 return Detail::RFieldValue(true /* captureFlag */, this, fClass->New(where));
1817}
1818
1820{
1821 fClass->Destructor(value.GetRawPtr(), true /* dtorOnly */);
1822 if (!dtorOnly)
1823 free(value.GetRawPtr());
1824}
1825
1826//------------------------------------------------------------------------------
1827
1830 std::shared_ptr<RCollectionNTupleWriter> collectionNTuple,
1831 std::unique_ptr<RNTupleModel> collectionModel)
1832 : RFieldBase(name, "", ENTupleStructure::kCollection, true /* isSimple */)
1833 , fCollectionNTuple(collectionNTuple)
1834{
1835 for (unsigned i = 0; i < collectionModel->GetFieldZero()->fSubFields.size(); ++i) {
1836 auto& subField = collectionModel->GetFieldZero()->fSubFields[i];
1837 Attach(std::move(subField));
1838 }
1839 SetDescription(collectionModel->GetDescription());
1840}
1841
1842
1844{
1845 RColumnModel modelIndex(EColumnType::kIndex, true /* isSorted*/);
1846 fColumns.emplace_back(std::unique_ptr<Detail::RColumn>(
1847 Detail::RColumn::Create<ClusterSize_t, EColumnType::kIndex>(modelIndex, 0)));
1848}
1849
1851{
1852 EnsureColumnType({EColumnType::kIndex}, 0, desc);
1853 GenerateColumnsImpl();
1854}
1855
1856
1857std::unique_ptr<ROOT::Experimental::Detail::RFieldBase>
1859{
1860 auto result = std::make_unique<RCollectionField>(newName, fCollectionNTuple, RNTupleModel::Create());
1861 for (auto& f : fSubFields) {
1862 auto clone = f->Clone(f->GetName());
1863 result->Attach(std::move(clone));
1864 }
1865 return result;
1866}
1867
1868
1870 *fCollectionNTuple->GetOffsetPtr() = 0;
1871}
size_t fSize
size_t fValueSize
Cppyy::TCppType_t fClass
#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:291
ROOT::Experimental::RField< T > RField
#define f(i)
Definition: RSha256.hxx:104
#define c(i)
Definition: RSha256.hxx:101
size_t size(const MatrixT &matrix)
retrieve the size of a square matrix
@ kIsStatic
Definition: TDictionary.h:80
@ kIsDefinedInStd
Definition: TDictionary.h:98
#define R__ASSERT(e)
Definition: TError.h:118
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 result
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t index
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 length
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 child
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 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
#define _(A, B)
Definition: cfortran.h:108
#define free
Definition: civetweb.c:1539
#define malloc
Definition: civetweb.c:1536
static std::string GetTypeName(EColumnType type)
Pairs of C++ type and column type, like float and EColumnType::kReal32.
static RColumn * Create(const RColumnModel &model, std::uint32_t index)
Definition: RColumn.hxx:103
Iterates over the sub tree of fields in depth-first search order.
Definition: RField.hxx:129
void Advance()
Given that the iterator points to a valid field which is not the end iterator, go to the next field i...
Definition: RField.cxx:419
std::vector< std::unique_ptr< RFieldBase > > fSubFields
Collections and classes own sub fields.
Definition: RField.hxx:94
RFieldBase(std::string_view name, std::string_view type, ENTupleStructure structure, bool isSimple, std::size_t nRepetitions=0)
The constructor creates the underlying column objects and connects them to either a sink or a source.
Definition: RField.cxx:156
virtual void DestroyValue(const RFieldValue &value, bool dtorOnly=false)
Releases the resources acquired during GenerateValue (memory and constructor) This implementation wor...
Definition: RField.cxx:301
void ConnectPageSink(RPageSink &pageSink)
Fields and their columns live in the void until connected to a physical page storage.
Definition: RField.cxx:372
ROOT::Experimental::EColumnType EnsureColumnType(const std::vector< EColumnType > &requestedTypes, unsigned int columnIndex, const RNTupleDescriptor &desc)
Throws an exception if the column given by fOnDiskId and the columnIndex in the provided descriptor i...
Definition: RField.cxx:339
void Flush() const
Ensure that all received items are written from page buffers to the storage.
Definition: RField.cxx:331
virtual void CommitCluster()
Perform housekeeping tasks for global to cluster-local index translation.
Definition: RField.hxx:229
void SetDescription(std::string_view description)
Definition: RField.hxx:244
virtual std::vector< RFieldValue > SplitValue(const RFieldValue &value) const
Creates the list of direct child values given a value for this field.
Definition: RField.cxx:308
static RResult< void > EnsureValidFieldName(std::string_view fieldName)
Check whether a given string is a valid field name.
Definition: RField.cxx:262
static RResult< std::unique_ptr< RFieldBase > > Create(const std::string &fieldName, const std::string &typeName)
Factory method to resurrect a field from the stored on-disk type information.
Definition: RField.cxx:168
void ConnectPageSource(RPageSource &pageSource)
Definition: RField.cxx:383
virtual std::size_t AppendImpl(const RFieldValue &value)
Operations on values of complex types, e.g.
Definition: RField.cxx:281
std::unique_ptr< RFieldBase > Clone(std::string_view newName) const
Copies the field and its sub fields using a possibly new name and a new, unconnected set of columns.
Definition: RField.cxx:273
virtual void AcceptVisitor(RFieldVisitor &visitor) const
Definition: RField.cxx:397
virtual void ReadGlobalImpl(NTupleSize_t globalIndex, RFieldValue *value)
Definition: RField.cxx:287
void Attach(std::unique_ptr< Detail::RFieldBase > child)
Add a new subfield to the list of nested fields.
Definition: RField.cxx:313
std::vector< RFieldBase * > GetSubFields() const
Definition: RField.cxx:321
RFieldValue GenerateValue()
Generates an object of the field type and allocates new initialized memory according to the type.
Definition: RField.cxx:294
Abstract base class for classes implementing the visitor design pattern.
virtual void VisitBoolField(const RField< bool > &field)
virtual void VisitFieldZero(const RFieldZero &field)
virtual void VisitRVecField(const RRVecField &field)
virtual void VisitField(const Detail::RFieldBase &field)=0
virtual void VisitDoubleField(const RField< double > &field)
virtual void VisitCharField(const RField< char > &field)
virtual void VisitArrayField(const RArrayField &field)
virtual void VisitClassField(const RClassField &field)
virtual void VisitRecordField(const RRecordField &field)
virtual void VisitVectorField(const RVectorField &field)
virtual void VisitFloatField(const RField< float > &field)
Abstract interface to write data into an ntuple.
Abstract interface to read data from an ntuple.
const RSharedDescriptorGuard GetSharedDescriptorGuard() const
Takes the read lock for the descriptor.
The available trivial, native content types of a column.
std::vector< Detail::RFieldValue > SplitValue(const Detail::RFieldValue &value) const final
Creates the list of direct child values given a value for this field.
Definition: RField.cxx:1557
Detail::RFieldValue CaptureValue(void *where) final
Creates a value from a memory location with an already constructed object.
Definition: RField.cxx:1551
void ReadInClusterImpl(const RClusterIndex &clusterIndex, Detail::RFieldValue *value) final
Definition: RField.cxx:1513
void ReadGlobalImpl(NTupleSize_t globalIndex, Detail::RFieldValue *value) final
Definition: RField.cxx:1504
RArrayField(std::string_view fieldName, std::unique_ptr< Detail::RFieldBase > itemField, std::size_t arrayLength)
Definition: RField.cxx:1477
void AcceptVisitor(Detail::RFieldVisitor &visitor) const final
Definition: RField.cxx:1568
void GenerateColumnsImpl() final
Creates the backing columns corresponsing to the field type for writing.
Definition: RField.cxx:1523
void DestroyValue(const Detail::RFieldValue &value, bool dtorOnly=false) final
Releases the resources acquired during GenerateValue (memory and constructor) This implementation wor...
Definition: RField.cxx:1540
std::size_t AppendImpl(const Detail::RFieldValue &value) final
Operations on values of complex types, e.g.
Definition: RField.cxx:1494
std::unique_ptr< Detail::RFieldBase > CloneImpl(std::string_view newName) const final
Called by Clone(), which additionally copies the on-disk ID.
Definition: RField.cxx:1488
The field for a class with dictionary.
Definition: RField.hxx:288
Detail::RFieldValue CaptureValue(void *where) final
Creates a value from a memory location with an already constructed object.
Definition: RField.cxx:889
static constexpr const char * kPrefixInherited
Prefix used in the subfield names generated for base classes.
Definition: RField.hxx:299
size_t GetValueSize() const override
The number of bytes taken by a value of the appropriate type.
Definition: RField.cxx:907
void Attach(std::unique_ptr< Detail::RFieldBase > child, RSubFieldInfo info)
Definition: RField.cxx:831
std::vector< Detail::RFieldValue > SplitValue(const Detail::RFieldValue &value) const final
Creates the list of direct child values given a value for this field.
Definition: RField.cxx:896
std::unique_ptr< Detail::RFieldBase > CloneImpl(std::string_view newName) const final
Called by Clone(), which additionally copies the on-disk ID.
Definition: RField.cxx:839
std::size_t AppendImpl(const Detail::RFieldValue &value) final
Operations on values of complex types, e.g.
Definition: RField.cxx:844
void AcceptVisitor(Detail::RFieldVisitor &visitor) const override
Definition: RField.cxx:912
void ReadInClusterImpl(const RClusterIndex &clusterIndex, Detail::RFieldValue *value) final
Definition: RField.cxx:861
void GenerateColumnsImpl() final
Creates the backing columns corresponsing to the field type for writing.
Definition: RField.cxx:869
RClassField(std::string_view fieldName, std::string_view className, TClass *classp)
Definition: RField.cxx:797
void ReadGlobalImpl(NTupleSize_t globalIndex, Detail::RFieldValue *value) final
Definition: RField.cxx:853
void DestroyValue(const Detail::RFieldValue &value, bool dtorOnly=false) final
Releases the resources acquired during GenerateValue (memory and constructor) This implementation wor...
Definition: RField.cxx:882
Addresses a column element or field item relative to a particular cluster, instead of a global NTuple...
Definition: RNTupleUtil.hxx:87
DescriptorId_t GetClusterId() const
ClusterSize_t::ValueType GetIndex() const
void CommitCluster() final
Perform housekeeping tasks for global to cluster-local index translation.
Definition: RField.cxx:1869
void GenerateColumnsImpl() final
Creates the backing columns corresponsing to the field type for writing.
Definition: RField.cxx:1843
RCollectionField(std::string_view name, std::shared_ptr< RCollectionNTupleWriter > collectionNTuple, std::unique_ptr< RNTupleModel > collectionModel)
Definition: RField.cxx:1828
std::unique_ptr< Detail::RFieldBase > CloneImpl(std::string_view newName) const final
Called by Clone(), which additionally copies the on-disk ID.
Definition: RField.cxx:1858
Holds the static meta-data of a column in a tree.
Holds the index and the tag of a kSwitch column.
Definition: RNTupleUtil.hxx:66
Base class for all ROOT issued exceptions.
Definition: RError.hxx:114
A field translates read and write calls from/to underlying columns to/from tree values.
void AcceptVisitor(Detail::RFieldVisitor &visitor) const final
Definition: RField.cxx:455
std::unique_ptr< Detail::RFieldBase > CloneImpl(std::string_view newName) const
Called by Clone(), which additionally copies the on-disk ID.
Definition: RField.cxx:446
Classes with dictionaries that can be inspected by TClass.
Definition: RField.hxx:537
The on-storage meta-data of an ntuple.
const RColumnDescriptor & GetColumnDescriptor(DescriptorId_t columnId) const
DescriptorId_t FindColumnId(DescriptorId_t fieldId, std::uint32_t columnIndex) const
static std::unique_ptr< RNTupleModel > Create()
The generic field for std::pair<T1, T2> types.
Definition: RField.hxx:591
std::unique_ptr< Detail::RFieldBase > CloneImpl(std::string_view newName) const override
Called by Clone(), which additionally copies the on-disk ID.
Definition: RField.cxx:1733
void DestroyValue(const Detail::RFieldValue &value, bool dtorOnly=false) override
Releases the resources acquired during GenerateValue (memory and constructor) This implementation wor...
Definition: RField.cxx:1748
RPairField(std::string_view fieldName, std::array< std::unique_ptr< Detail::RFieldBase >, 2 > &&itemFields, const std::array< std::size_t, 2 > &offsets)
Definition: RField.cxx:1710
Detail::RFieldValue CaptureValue(void *where) override
Creates a value from a memory location with an already constructed object.
Definition: RField.cxx:1299
std::size_t EvalValueSize() const
Evaluate the constant returned by GetValueSize.
Definition: RField.cxx:1318
void DestroyValue(const Detail::RFieldValue &value, bool dtorOnly=false) override
Releases the resources acquired during GenerateValue (memory and constructor) This implementation wor...
Definition: RField.cxx:1272
RRVecField(std::string_view fieldName, std::unique_ptr< Detail::RFieldBase > itemField)
Definition: RField.cxx:1160
void CommitCluster() final
Perform housekeeping tasks for global to cluster-local index translation.
Definition: RField.cxx:1378
void ReadGlobalImpl(NTupleSize_t globalIndex, Detail::RFieldValue *value) override
Definition: RField.cxx:1193
void AcceptVisitor(Detail::RFieldVisitor &visitor) const final
Definition: RField.cxx:1383
size_t GetAlignment() const override
For many types, the alignment requirement is equal to the size; otherwise override.
Definition: RField.cxx:1371
std::unique_ptr< Detail::RFieldBase > CloneImpl(std::string_view newName) const override
Called by Clone(), which additionally copies the on-disk ID.
Definition: RField.cxx:1170
size_t GetValueSize() const override
The number of bytes taken by a value of the appropriate type.
Definition: RField.cxx:1366
std::size_t AppendImpl(const Detail::RFieldValue &value) override
Operations on values of complex types, e.g.
Definition: RField.cxx:1176
std::vector< Detail::RFieldValue > SplitValue(const Detail::RFieldValue &value) const final
Creates the list of direct child values given a value for this field.
Definition: RField.cxx:1305
void GenerateColumnsImpl() final
Creates the backing columns corresponsing to the field type for writing.
Definition: RField.cxx:1248
The field for an untyped record.
Definition: RField.hxx:336
std::unique_ptr< Detail::RFieldBase > CloneImpl(std::string_view newName) const override
Called by Clone(), which additionally copies the on-disk ID.
Definition: RField.cxx:965
std::vector< std::size_t > fOffsets
Definition: RField.hxx:340
std::size_t AppendImpl(const Detail::RFieldValue &value) final
Operations on values of complex types, e.g.
Definition: RField.cxx:973
RRecordField(std::string_view fieldName, std::vector< std::unique_ptr< Detail::RFieldBase > > &&itemFields, const std::vector< std::size_t > &offsets, std::string_view typeName="")
Definition: RField.cxx:919
std::size_t GetItemPadding(std::size_t baseOffset, std::size_t itemAlignment) const
Definition: RField.cxx:954
void ReadGlobalImpl(NTupleSize_t globalIndex, Detail::RFieldValue *value) final
Definition: RField.cxx:982
Detail::RFieldValue CaptureValue(void *where) final
Creates a value from a memory location with an already constructed object.
Definition: RField.cxx:1017
std::vector< Detail::RFieldValue > SplitValue(const Detail::RFieldValue &value) const final
Creates the list of direct child values given a value for this field.
Definition: RField.cxx:1024
void DestroyValue(const Detail::RFieldValue &value, bool dtorOnly=false) override
Releases the resources acquired during GenerateValue (memory and constructor) This implementation wor...
Definition: RField.cxx:1006
void ReadInClusterImpl(const RClusterIndex &clusterIndex, Detail::RFieldValue *value) final
Definition: RField.cxx:990
void AcceptVisitor(Detail::RFieldVisitor &visitor) const final
Definition: RField.cxx:1034
RResult<void> has no data member and no Inspect() method but instead a Success() factory method.
Definition: RError.hxx:257
The class is used as a return type for operations that can fail; wraps a value of type T or an RError...
Definition: RError.hxx:195
The generic field for std::tuple<Ts...> types.
Definition: RField.hxx:614
std::unique_ptr< Detail::RFieldBase > CloneImpl(std::string_view newName) const override
Called by Clone(), which additionally copies the on-disk ID.
Definition: RField.cxx:1803
RTupleField(std::string_view fieldName, std::vector< std::unique_ptr< Detail::RFieldBase > > &&itemFields, const std::vector< std::size_t > &offsets)
Definition: RField.cxx:1770
void DestroyValue(const Detail::RFieldValue &value, bool dtorOnly=false) override
Releases the resources acquired during GenerateValue (memory and constructor) This implementation wor...
Definition: RField.cxx:1819
std::size_t AppendImpl(const Detail::RFieldValue &value) final
Operations on values of complex types, e.g.
Definition: RField.cxx:1626
size_t GetValueSize() const final
The number of bytes taken by a value of the appropriate type.
Definition: RField.cxx:1692
void DestroyValue(const Detail::RFieldValue &value, bool dtorOnly=false) final
Releases the resources acquired during GenerateValue (memory and constructor) This implementation wor...
Definition: RField.cxx:1675
std::vector< ClusterSize_t::ValueType > fNWritten
Definition: RField.hxx:504
size_t fTagOffset
In the std::variant memory layout, at which byte number is the index stored.
Definition: RField.hxx:503
void SetTag(void *variantPtr, std::uint32_t tag) const
Definition: RField.cxx:1620
void GenerateColumnsImpl() final
Creates the backing columns corresponsing to the field type for writing.
Definition: RField.cxx:1654
std::uint32_t GetTag(void *variantPtr) const
Extracts the index from an std::variant and transforms it into the 1-based index used for the switch ...
Definition: RField.cxx:1614
static std::string GetTypeList(const std::vector< Detail::RFieldBase * > &itemFields)
Definition: RField.cxx:1575
RVariantField(std::string_view fieldName, const std::vector< Detail::RFieldBase * > &itemFields)
Definition: RField.cxx:1586
void ReadGlobalImpl(NTupleSize_t globalIndex, Detail::RFieldValue *value) final
Definition: RField.cxx:1642
size_t GetAlignment() const final
For many types, the alignment requirement is equal to the size; otherwise override.
Definition: RField.hxx:530
Detail::RFieldValue CaptureValue(void *where) final
Creates a value from a memory location with an already constructed object.
Definition: RField.cxx:1687
std::unique_ptr< Detail::RFieldBase > CloneImpl(std::string_view newName) const final
Called by Clone(), which additionally copies the on-disk ID.
Definition: RField.cxx:1603
void CommitCluster() final
Perform housekeeping tasks for global to cluster-local index translation.
Definition: RField.cxx:1697
Detail::RFieldValue CaptureValue(void *where) override
Creates a value from a memory location with an already constructed object.
Definition: RField.cxx:1129
void CommitCluster() final
Perform housekeeping tasks for global to cluster-local index translation.
Definition: RField.cxx:1147
std::unique_ptr< Detail::RFieldBase > CloneImpl(std::string_view newName) const final
Called by Clone(), which additionally copies the on-disk ID.
Definition: RField.cxx:1052
void AcceptVisitor(Detail::RFieldVisitor &visitor) const final
Definition: RField.cxx:1152
std::vector< Detail::RFieldValue > SplitValue(const Detail::RFieldValue &value) const final
Creates the list of direct child values given a value for this field.
Definition: RField.cxx:1135
void ReadGlobalImpl(NTupleSize_t globalIndex, Detail::RFieldValue *value) final
Definition: RField.cxx:1073
void GenerateColumnsImpl() final
Creates the backing columns corresponsing to the field type for writing.
Definition: RField.cxx:1097
RVectorField(std::string_view fieldName, std::unique_ptr< Detail::RFieldBase > itemField)
Definition: RField.cxx:1042
void DestroyValue(const Detail::RFieldValue &value, bool dtorOnly=false) final
Releases the resources acquired during GenerateValue (memory and constructor) This implementation wor...
Definition: RField.cxx:1115
std::size_t AppendImpl(const Detail::RFieldValue &value) final
Operations on values of complex types, e.g.
Definition: RField.cxx:1058
TClass instances represent classes, structs and namespaces in the ROOT type system.
Definition: TClass.h:80
TList * GetListOfDataMembers(Bool_t load=kTRUE)
Return list containing the TDataMembers of a class.
Definition: TClass.cxx:3759
TList * GetListOfBases()
Return list containing the TBaseClass(es) of a class.
Definition: TClass.cxx:3625
Long_t Property() const override
Returns the properties of the TClass as a bit field stored as a Long_t value.
Definition: TClass.cxx:6075
static TClass * GetClass(const char *name, Bool_t load=kTRUE, Bool_t silent=kFALSE)
Static method returning pointer to TClass of the specified class name.
Definition: TClass.cxx:2969
RVec< PromoteTypes< T0, T1 > > remainder(const T0 &x, const RVec< T1 > &v)
Definition: RVec.hxx:1742
basic_string_view< char > string_view
std::uint64_t NTupleSize_t
Integer type long enough to hold the maximum number of entries in a column.
Definition: RNTupleUtil.hxx:47
RClusterSize ClusterSize_t
Definition: RNTupleUtil.hxx:62
ENTupleStructure
The fields in the ntuple model tree can carry different structural information about the type system.
Definition: RNTupleUtil.hxx:37
constexpr DescriptorId_t kInvalidDescriptorId
Definition: RNTupleUtil.hxx:84
clang::QualType GetNormalizedType(const clang::QualType &type, const cling::Interpreter &interpreter, const TNormalizedCtxt &normCtxt)
Return the type normalized for ROOT, keeping only the ROOT opaque typedef (Double32_t,...
This file contains a specialised ROOT message handler to test for diagnostic in unit tests.
TClass * GetClass(T *)
Definition: TClass.h:658
Type GetType(const std::string &Name)
Definition: Systematics.cxx:34
std::string ResolveTypedef(const char *tname, bool resolveAll=false)
std::string CleanType(const char *typeDesc, int mode=0, const char **tail=0)
Cleanup type description, redundant blanks removed and redundant tail ignored return *tail = pointer ...
fill
Definition: fit1_py.py:6
Wrap the 32bit integer in a struct in order to avoid template specialization clash with std::uint32_t...
Definition: RNTupleUtil.hxx:50
Definition: civetweb.c:1856