Logo ROOT  
Reference Guide
 
Loading...
Searching...
No Matches
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 <TClass.h>
28#include <TCollection.h>
29#include <TDataMember.h>
30#include <TError.h>
31#include <TList.h>
32
33#include <algorithm>
34#include <cctype> // for isspace
35#include <cstdlib> // for malloc, free
36#include <cstring> // for memset
37#include <exception>
38#include <iostream>
39#include <type_traits>
40#include <unordered_map>
41
42namespace {
43
44/// Used in CreateField() in order to get the comma-separated list of template types
45/// E.g., gets {"int", "std::variant<double,int>"} from "int,std::variant<double,int>"
46std::vector<std::string> TokenizeTypeList(std::string templateType) {
47 std::vector<std::string> result;
48 if (templateType.empty())
49 return result;
50
51 const char *eol = templateType.data() + templateType.length();
52 const char *typeBegin = templateType.data();
53 const char *typeCursor = templateType.data();
54 unsigned int nestingLevel = 0;
55 while (typeCursor != eol) {
56 switch (*typeCursor) {
57 case '<':
58 ++nestingLevel;
59 break;
60 case '>':
61 --nestingLevel;
62 break;
63 case ',':
64 if (nestingLevel == 0) {
65 result.push_back(std::string(typeBegin, typeCursor - typeBegin));
66 typeBegin = typeCursor + 1;
67 }
68 break;
69 }
70 typeCursor++;
71 }
72 result.push_back(std::string(typeBegin, typeCursor - typeBegin));
73 return result;
74}
75
76/// Remove leading and trailing white spaces
77std::string Trim(const std::string &raw) {
78 if (raw.empty()) return "";
79
80 unsigned start_pos = 0;
81 for (; (start_pos < raw.length()) && (raw[start_pos] == ' ' || raw[start_pos] == '\t'); ++start_pos) { }
82
83 unsigned end_pos = raw.length() - 1; // at least one character in raw
84 for (; (end_pos >= start_pos) && (raw[end_pos] == ' ' || raw[end_pos] == '\t'); --end_pos) { }
85
86 return raw.substr(start_pos, end_pos - start_pos + 1);
87}
88
89std::string GetNormalizedType(const std::string &typeName) {
90 std::string normalizedType(Trim(typeName));
91
92 // TODO(jblomer): use a type translation map
93 if (normalizedType == "Bool_t") normalizedType = "bool";
94 if (normalizedType == "Float_t") normalizedType = "float";
95 if (normalizedType == "Double_t") normalizedType = "double";
96 if (normalizedType == "UChar_t") normalizedType = "std::uint8_t";
97 if (normalizedType == "unsigned char") normalizedType = "std::uint8_t";
98 if (normalizedType == "uint8_t") normalizedType = "std::uint8_t";
99 if (normalizedType == "Int_t") normalizedType = "std::int32_t";
100 if (normalizedType == "int") normalizedType = "std::int32_t";
101 if (normalizedType == "int32_t") normalizedType = "std::int32_t";
102 if (normalizedType == "unsigned") normalizedType = "std::uint32_t";
103 if (normalizedType == "unsigned int") normalizedType = "std::uint32_t";
104 if (normalizedType == "UInt_t") normalizedType = "std::uint32_t";
105 if (normalizedType == "uint32_t") normalizedType = "std::uint32_t";
106 if (normalizedType == "ULong64_t") normalizedType = "std::uint64_t";
107 if (normalizedType == "uint64_t") normalizedType = "std::uint64_t";
108 if (normalizedType == "string") normalizedType = "std::string";
109 if (normalizedType.substr(0, 7) == "vector<") normalizedType = "std::" + normalizedType;
110 if (normalizedType.substr(0, 6) == "array<") normalizedType = "std::" + normalizedType;
111 if (normalizedType.substr(0, 8) == "variant<") normalizedType = "std::" + normalizedType;
112
113 return normalizedType;
114}
115
116} // anonymous namespace
117
119{
120 if (field.fColumns.empty())
121 field.GenerateColumnsImpl();
122 for (auto& column : field.fColumns)
123 column->Connect(fieldId, &pageStorage);
124}
125
126
128 DescriptorId_t fieldId, RPageSource &pageSource, RFieldBase &field)
129{
130 Connect(fieldId, pageSource, field);
131 std::unordered_map<const RFieldBase *, DescriptorId_t> field2Id;
132 field2Id[&field] = fieldId;
133 for (auto &f : field) {
134 auto subFieldId = pageSource.GetDescriptor().FindFieldId(f.GetName(), field2Id[f.GetParent()]);
135 Detail::RFieldFuse::Connect(subFieldId, pageSource, f);
136 field2Id[&f] = subFieldId;
137 }
138}
139
140
141//------------------------------------------------------------------------------
142
143
145 std::string_view name, std::string_view type, ENTupleStructure structure, bool isSimple, std::size_t nRepetitions)
146 : fName(name), fType(type), fStructure(structure), fNRepetitions(nRepetitions), fIsSimple(isSimple),
147 fParent(nullptr), fPrincipalColumn(nullptr)
148{
149}
150
152{
153}
154
156ROOT::Experimental::Detail::RFieldBase::Create(const std::string &fieldName, const std::string &typeName)
157{
158 std::string normalizedType(GetNormalizedType(typeName));
159 if (normalizedType.empty())
160 return R__FAIL("no type name specified for Field " + fieldName);
161
162 std::unique_ptr<ROOT::Experimental::Detail::RFieldBase> result;
163
164 if (normalizedType == "ROOT::Experimental::ClusterSize_t") {
165 result = std::make_unique<RField<ClusterSize_t>>(fieldName);
166 } else if (normalizedType == "bool") {
167 result = std::make_unique<RField<bool>>(fieldName);
168 } else if (normalizedType == "std::uint8_t") {
169 result = std::make_unique<RField<std::uint8_t>>(fieldName);
170 } else if (normalizedType == "std::int32_t") {
171 result = std::make_unique<RField<std::int32_t>>(fieldName);
172 } else if (normalizedType == "std::uint32_t") {
173 result = std::make_unique<RField<std::uint32_t>>(fieldName);
174 } else if (normalizedType == "std::uint64_t") {
175 result = std::make_unique<RField<std::uint64_t>>(fieldName);
176 } else if (normalizedType == "float") {
177 result = std::make_unique<RField<float>>(fieldName);
178 } else if (normalizedType == "double") {
179 result = std::make_unique<RField<double>>(fieldName);
180 } else if (normalizedType == "std::string") {
181 result = std::make_unique<RField<std::string>>(fieldName);
182 } else if (normalizedType == "std::vector<bool>") {
183 result = std::make_unique<RField<std::vector<bool>>>(fieldName);
184 } else if (normalizedType.substr(0, 12) == "std::vector<") {
185 std::string itemTypeName = normalizedType.substr(12, normalizedType.length() - 13);
186 auto itemField = Create(GetNormalizedType(itemTypeName), itemTypeName);
187 result = std::make_unique<RVectorField>(fieldName, itemField.Unwrap());
188 } else if (normalizedType == "ROOT::VecOps::RVec<bool>") {
189 result = std::make_unique<RField<ROOT::VecOps::RVec<bool>>>(fieldName);
190 } else if (normalizedType.substr(0, 19) == "ROOT::VecOps::RVec<") {
191 // For the time being, we silently read RVec fields as std::vector
192 std::string itemTypeName = normalizedType.substr(19, normalizedType.length() - 20);
193 auto itemField = Create(GetNormalizedType(itemTypeName), itemTypeName);
194 result = std::make_unique<RVectorField>(fieldName, itemField.Unwrap());
195 } else if (normalizedType.substr(0, 11) == "std::array<") {
196 auto arrayDef = TokenizeTypeList(normalizedType.substr(11, normalizedType.length() - 12));
197 R__ASSERT(arrayDef.size() == 2);
198 auto arrayLength = std::stoi(arrayDef[1]);
199 auto itemField = Create(GetNormalizedType(arrayDef[0]), arrayDef[0]);
200 result = std::make_unique<RArrayField>(fieldName, itemField.Unwrap(), arrayLength);
201 }
202#if __cplusplus >= 201703L
203 if (normalizedType.substr(0, 13) == "std::variant<") {
204 auto innerTypes = TokenizeTypeList(normalizedType.substr(13, normalizedType.length() - 14));
205 std::vector<RFieldBase *> items;
206 for (unsigned int i = 0; i < innerTypes.size(); ++i) {
207 items.emplace_back(Create("variant" + std::to_string(i), innerTypes[i]).Unwrap().release());
208 }
209 result = std::make_unique<RVariantField>(fieldName, items);
210 }
211#endif
212 // TODO: create an RCollectionField?
213 if (normalizedType == ":Collection:")
214 result = std::make_unique<RField<ClusterSize_t>>(fieldName);
215
216 if (!result) {
217 auto cl = TClass::GetClass(normalizedType.c_str());
218 if (cl != nullptr) {
219 result = std::make_unique<RClassField>(fieldName, normalizedType);
220 }
221 }
222
223 if (result)
224 return result;
225 return R__FAIL(std::string("Field ") + fieldName + " has unknown type " + normalizedType);
226}
227
230{
231 if (fieldName == "") {
232 return R__FAIL("name cannot be empty string \"\"");
233 } else if (fieldName.find(".") != std::string::npos) {
234 return R__FAIL("name '" + std::string(fieldName) + "' cannot contain dot characters '.'");
235 }
236 return RResult<void>::Success();
237}
238
240 R__ASSERT(false);
241}
242
245 RFieldValue* /*value*/)
246{
247 R__ASSERT(false);
248}
249
251{
252 void *where = malloc(GetValueSize());
253 R__ASSERT(where != nullptr);
254 return GenerateValue(where);
255}
256
258{
259 if (!dtorOnly)
260 free(value.GetRawPtr());
261}
262
263std::vector<ROOT::Experimental::Detail::RFieldValue>
265{
266 return std::vector<RFieldValue>();
267}
268
270 std::unique_ptr<ROOT::Experimental::Detail::RFieldBase> child)
271{
272 child->fParent = this;
273 fSubFields.emplace_back(std::move(child));
274}
275
276
277std::vector<const ROOT::Experimental::Detail::RFieldBase *>
279{
280 std::vector<const RFieldBase *> result;
281 for (const auto &f : fSubFields) {
282 result.emplace_back(f.get());
283 }
284 return result;
285}
286
287
289{
290 for (auto& column : fColumns) {
291 column->Flush();
292 }
293}
294
295
297{
298 visitor.VisitField(*this);
299}
300
301
303{
304 if (fSubFields.empty()) return RSchemaIterator(this, -1);
305 return RSchemaIterator(this->fSubFields[0].get(), 0);
306}
307
308
310{
311 return RSchemaIterator(this, -1);
312}
313
314
315//-----------------------------------------------------------------------------
316
317
319{
320 auto itr = fStack.rbegin();
321 if (!itr->fFieldPtr->fSubFields.empty()) {
322 fStack.emplace_back(Position(itr->fFieldPtr->fSubFields[0].get(), 0));
323 return;
324 }
325
326 unsigned int nextIdxInParent = ++(itr->fIdxInParent);
327 while (nextIdxInParent >= itr->fFieldPtr->fParent->fSubFields.size()) {
328 if (fStack.size() == 1) {
329 itr->fFieldPtr = itr->fFieldPtr->fParent;
330 itr->fIdxInParent = -1;
331 return;
332 }
333 fStack.pop_back();
334 itr = fStack.rbegin();
335 nextIdxInParent = ++(itr->fIdxInParent);
336 }
337 itr->fFieldPtr = itr->fFieldPtr->fParent->fSubFields[nextIdxInParent].get();
338}
339
340
341//------------------------------------------------------------------------------
342
343
344std::unique_ptr<ROOT::Experimental::Detail::RFieldBase>
345ROOT::Experimental::RFieldZero::Clone(std::string_view /*newName*/) const
346{
347 auto result = std::make_unique<RFieldZero>();
348 for (auto &f : fSubFields)
349 result->Attach(f->Clone(f->GetName()));
350 return result;
351}
352
353
354std::unique_ptr<ROOT::Experimental::REntry> ROOT::Experimental::RFieldZero::GenerateEntry() const
355{
356 auto entry = std::make_unique<REntry>();
357 for (auto& f : fSubFields) {
358 entry->AddValue(f->GenerateValue());
359 }
360 return entry;
361}
362
364{
365 visitor.VisitFieldZero(*this);
366}
367
368
369//------------------------------------------------------------------------------
370
371
373{
374 RColumnModel model(EColumnType::kIndex, true /* isSorted*/);
375 fColumns.emplace_back(std::unique_ptr<Detail::RColumn>(
376 Detail::RColumn::Create<ClusterSize_t, EColumnType::kIndex>(model, 0)));
377 fPrincipalColumn = fColumns[0].get();
378}
379
381{
382 visitor.VisitClusterSizeField(*this);
383}
384
385//------------------------------------------------------------------------------
386
388{
389 RColumnModel model(EColumnType::kByte, false /* isSorted*/);
390 fColumns.emplace_back(std::unique_ptr<Detail::RColumn>(Detail::RColumn::Create<
391 std::uint8_t, EColumnType::kByte>(model, 0)));
392 fPrincipalColumn = fColumns[0].get();
393}
394
395void ROOT::Experimental::RField<std::uint8_t>::AcceptVisitor(Detail::RFieldVisitor &visitor) const
396{
397 visitor.VisitUInt8Field(*this);
398}
399
400//------------------------------------------------------------------------------
401
402
404{
405 RColumnModel model(EColumnType::kBit, false /* isSorted*/);
406 fColumns.emplace_back(std::unique_ptr<Detail::RColumn>(
407 Detail::RColumn::Create<bool, EColumnType::kBit>(model, 0)));
408 fPrincipalColumn = fColumns[0].get();
409}
410
412{
413 visitor.VisitBoolField(*this);
414}
415
416//------------------------------------------------------------------------------
417
418
420{
421 RColumnModel model(EColumnType::kReal32, false /* isSorted*/);
422 fColumns.emplace_back(std::unique_ptr<Detail::RColumn>(
423 Detail::RColumn::Create<float, EColumnType::kReal32>(model, 0)));
424 fPrincipalColumn = fColumns[0].get();
425}
426
428{
429 visitor.VisitFloatField(*this);
430}
431
432
433//------------------------------------------------------------------------------
434
436{
437 RColumnModel model(EColumnType::kReal64, false /* isSorted*/);
438 fColumns.emplace_back(std::unique_ptr<Detail::RColumn>(
439 Detail::RColumn::Create<double, EColumnType::kReal64>(model, 0)));
440 fPrincipalColumn = fColumns[0].get();
441}
442
444{
445 visitor.VisitDoubleField(*this);
446}
447
448//------------------------------------------------------------------------------
449
451{
452 RColumnModel model(EColumnType::kInt32, false /* isSorted*/);
453 fColumns.emplace_back(std::unique_ptr<Detail::RColumn>(Detail::RColumn::Create<
454 std::int32_t, EColumnType::kInt32>(model, 0)));
455 fPrincipalColumn = fColumns[0].get();
456}
457
458void ROOT::Experimental::RField<std::int32_t>::AcceptVisitor(Detail::RFieldVisitor &visitor) const
459{
460 visitor.VisitIntField(*this);
461}
462
463//------------------------------------------------------------------------------
464
466{
467 RColumnModel model(EColumnType::kInt32, false /* isSorted*/);
468 fColumns.emplace_back(std::unique_ptr<Detail::RColumn>(
469 Detail::RColumn::Create<std::uint32_t, EColumnType::kInt32>(model, 0)));
470 fPrincipalColumn = fColumns[0].get();
471}
472
473void ROOT::Experimental::RField<std::uint32_t>::AcceptVisitor(Detail::RFieldVisitor &visitor) const
474{
475 visitor.VisitUInt32Field(*this);
476}
477
478//------------------------------------------------------------------------------
479
481{
482 RColumnModel model(EColumnType::kInt64, false /* isSorted*/);
483 fColumns.emplace_back(std::unique_ptr<Detail::RColumn>(
484 Detail::RColumn::Create<std::uint64_t, EColumnType::kInt64>(model, 0)));
485 fPrincipalColumn = fColumns[0].get();
486}
487
488void ROOT::Experimental::RField<std::uint64_t>::AcceptVisitor(Detail::RFieldVisitor &visitor) const
489{
490 visitor.VisitUInt64Field(*this);
491}
492
493//------------------------------------------------------------------------------
494
495
497{
498 RColumnModel modelIndex(EColumnType::kIndex, true /* isSorted*/);
499 fColumns.emplace_back(std::unique_ptr<Detail::RColumn>(
500 Detail::RColumn::Create<ClusterSize_t, EColumnType::kIndex>(modelIndex, 0)));
501
502 RColumnModel modelChars(EColumnType::kByte, false /* isSorted*/);
503 fColumns.emplace_back(std::unique_ptr<Detail::RColumn>(
504 Detail::RColumn::Create<char, EColumnType::kByte>(modelChars, 1)));
505 fPrincipalColumn = fColumns[0].get();
506}
507
509{
510 auto typedValue = value.Get<std::string>();
511 auto length = typedValue->length();
512 Detail::RColumnElement<char, EColumnType::kByte> elemChars(const_cast<char*>(typedValue->data()));
513 fColumns[1]->AppendV(elemChars, length);
514 fIndex += length;
515 fColumns[0]->Append(fElemIndex);
516}
517
520{
521 auto typedValue = value->Get<std::string>();
522 RClusterIndex collectionStart;
523 ClusterSize_t nChars;
524 fPrincipalColumn->GetCollectionInfo(globalIndex, &collectionStart, &nChars);
525 if (nChars == 0) {
526 typedValue->clear();
527 } else {
528 typedValue->resize(nChars);
529 Detail::RColumnElement<char, EColumnType::kByte> elemChars(const_cast<char*>(typedValue->data()));
530 fColumns[1]->ReadV(collectionStart, nChars, &elemChars);
531 }
532}
533
535{
536 fIndex = 0;
537}
538
539void ROOT::Experimental::RField<std::string>::AcceptVisitor(Detail::RFieldVisitor &visitor) const
540{
541 visitor.VisitStringField(*this);
542}
543
544//------------------------------------------------------------------------------
545
546
547ROOT::Experimental::RClassField::RClassField(std::string_view fieldName, std::string_view className)
548 : ROOT::Experimental::Detail::RFieldBase(fieldName, className, ENTupleStructure::kRecord, false /* isSimple */)
549 , fClass(TClass::GetClass(std::string(className).c_str()))
550{
551 if (fClass == nullptr) {
552 throw std::runtime_error("RField: no I/O support for type " + std::string(className));
553 }
555 while (auto dataMember = static_cast<TDataMember *>(next())) {
556 //printf("Now looking at %s %s\n", dataMember->GetName(), dataMember->GetFullTypeName());
557 auto subField = Detail::RFieldBase::Create(dataMember->GetName(), dataMember->GetFullTypeName()).Unwrap();
558 fMaxAlignment = std::max(fMaxAlignment, subField->GetAlignment());
559 Attach(std::move(subField));
560 }
561}
562
563std::unique_ptr<ROOT::Experimental::Detail::RFieldBase>
564ROOT::Experimental::RClassField::Clone(std::string_view newName) const
565{
566 return std::make_unique<RClassField>(newName, GetType());
567}
568
570 TIter next(fClass->GetListOfDataMembers());
571 unsigned i = 0;
572 while (auto dataMember = static_cast<TDataMember *>(next())) {
573 auto memberValue = fSubFields[i]->CaptureValue(value.Get<unsigned char>() + dataMember->GetOffset());
574 fSubFields[i]->Append(memberValue);
575 i++;
576 }
577}
578
580{
581 TIter next(fClass->GetListOfDataMembers());
582 unsigned i = 0;
583 while (auto dataMember = static_cast<TDataMember *>(next())) {
584 auto memberValue = fSubFields[i]->GenerateValue(value->Get<unsigned char>() + dataMember->GetOffset());
585 fSubFields[i]->Read(globalIndex, &memberValue);
586 i++;
587 }
588}
589
591{
592 TIter next(fClass->GetListOfDataMembers());
593 unsigned i = 0;
594 while (auto dataMember = static_cast<TDataMember *>(next())) {
595 auto memberValue = fSubFields[i]->GenerateValue(value->Get<unsigned char>() + dataMember->GetOffset());
596 fSubFields[i]->Read(clusterIndex, &memberValue);
597 i++;
598 }
599}
600
602{
603}
604
606{
607 return Detail::RFieldValue(true /* captureFlag */, this, fClass->New(where));
608}
609
611{
612 fClass->Destructor(value.GetRawPtr(), true /* dtorOnly */);
613 if (!dtorOnly)
614 free(value.GetRawPtr());
615}
616
618{
619 return Detail::RFieldValue(true /* captureFlat */, this, where);
620}
621
622
623std::vector<ROOT::Experimental::Detail::RFieldValue>
625{
626 TIter next(fClass->GetListOfDataMembers());
627 unsigned i = 0;
628 std::vector<Detail::RFieldValue> result;
629 while (auto dataMember = static_cast<TDataMember *>(next())) {
630 auto memberValue = fSubFields[i]->CaptureValue(value.Get<unsigned char>() + dataMember->GetOffset());
631 result.emplace_back(memberValue);
632 i++;
633 }
634 return result;
635}
636
637
639{
640 return fClass->GetClassSize();
641}
642
644{
645 visitor.VisitClassField(*this);
646}
647
648//------------------------------------------------------------------------------
649
650
652 std::string_view fieldName, std::unique_ptr<Detail::RFieldBase> itemField)
653 : ROOT::Experimental::Detail::RFieldBase(
654 fieldName, "std::vector<" + itemField->GetType() + ">", ENTupleStructure::kCollection, false /* isSimple */)
655 , fItemSize(itemField->GetValueSize()), fNWritten(0)
656{
657 Attach(std::move(itemField));
658}
659
660std::unique_ptr<ROOT::Experimental::Detail::RFieldBase>
661ROOT::Experimental::RVectorField::Clone(std::string_view newName) const
662{
663 auto newItemField = fSubFields[0]->Clone(fSubFields[0]->GetName());
664 return std::make_unique<RVectorField>(newName, std::move(newItemField));
665}
666
668 auto typedValue = value.Get<std::vector<char>>();
669 R__ASSERT((typedValue->size() % fItemSize) == 0);
670 auto count = typedValue->size() / fItemSize;
671 for (unsigned i = 0; i < count; ++i) {
672 auto itemValue = fSubFields[0]->CaptureValue(typedValue->data() + (i * fItemSize));
673 fSubFields[0]->Append(itemValue);
674 }
676 fNWritten += count;
677 fColumns[0]->Append(elemIndex);
678}
679
681{
682 auto typedValue = value->Get<std::vector<char>>();
683
684 ClusterSize_t nItems;
685 RClusterIndex collectionStart;
686 fPrincipalColumn->GetCollectionInfo(globalIndex, &collectionStart, &nItems);
687
688 typedValue->resize(nItems * fItemSize);
689 for (unsigned i = 0; i < nItems; ++i) {
690 auto itemValue = fSubFields[0]->GenerateValue(typedValue->data() + (i * fItemSize));
691 fSubFields[0]->Read(collectionStart + i, &itemValue);
692 }
693}
694
696{
697 RColumnModel modelIndex(EColumnType::kIndex, true /* isSorted*/);
698 fColumns.emplace_back(std::unique_ptr<Detail::RColumn>(
699 Detail::RColumn::Create<ClusterSize_t, EColumnType::kIndex>(modelIndex, 0)));
700 fPrincipalColumn = fColumns[0].get();
701}
702
704{
705 return Detail::RFieldValue(this, reinterpret_cast<std::vector<char>*>(where));
706}
707
709{
710 auto vec = static_cast<std::vector<char>*>(value.GetRawPtr());
711 R__ASSERT((vec->size() % fItemSize) == 0);
712 auto nItems = vec->size() / fItemSize;
713 for (unsigned i = 0; i < nItems; ++i) {
714 auto itemValue = fSubFields[0]->CaptureValue(vec->data() + (i * fItemSize));
715 fSubFields[0]->DestroyValue(itemValue, true /* dtorOnly */);
716 }
717 vec->~vector();
718 if (!dtorOnly)
719 free(vec);
720}
721
723{
724 return Detail::RFieldValue(true /* captureFlag */, this, where);
725}
726
727std::vector<ROOT::Experimental::Detail::RFieldValue>
729{
730 auto vec = static_cast<std::vector<char>*>(value.GetRawPtr());
731 R__ASSERT((vec->size() % fItemSize) == 0);
732 auto nItems = vec->size() / fItemSize;
733 std::vector<Detail::RFieldValue> result;
734 for (unsigned i = 0; i < nItems; ++i) {
735 result.emplace_back(fSubFields[0]->CaptureValue(vec->data() + (i * fItemSize)));
736 }
737 return result;
738}
739
741{
742 fNWritten = 0;
743}
744
746{
747 visitor.VisitVectorField(*this);
748}
749
750
751//------------------------------------------------------------------------------
752
753
754ROOT::Experimental::RField<std::vector<bool>>::RField(std::string_view name)
755 : ROOT::Experimental::Detail::RFieldBase(name, "std::vector<bool>", ENTupleStructure::kCollection,
756 false /* isSimple */)
757{
758 Attach(std::make_unique<RField<bool>>("bool"));
759}
760
761void ROOT::Experimental::RField<std::vector<bool>>::AppendImpl(const Detail::RFieldValue& value) {
762 auto typedValue = value.Get<std::vector<bool>>();
763 auto count = typedValue->size();
764 for (unsigned i = 0; i < count; ++i) {
765 bool bval = (*typedValue)[i];
766 auto itemValue = fSubFields[0]->CaptureValue(&bval);
767 fSubFields[0]->Append(itemValue);
768 }
769 Detail::RColumnElement<ClusterSize_t, EColumnType::kIndex> elemIndex(&fNWritten);
770 fNWritten += count;
771 fColumns[0]->Append(elemIndex);
772}
773
774void ROOT::Experimental::RField<std::vector<bool>>::ReadGlobalImpl(NTupleSize_t globalIndex, Detail::RFieldValue* value)
775{
776 auto typedValue = value->Get<std::vector<bool>>();
777
778 ClusterSize_t nItems;
779 RClusterIndex collectionStart;
780 fPrincipalColumn->GetCollectionInfo(globalIndex, &collectionStart, &nItems);
781
782 typedValue->resize(nItems);
783 for (unsigned i = 0; i < nItems; ++i) {
784 bool bval;
785 auto itemValue = fSubFields[0]->GenerateValue(&bval);
786 fSubFields[0]->Read(collectionStart + i, &itemValue);
787 (*typedValue)[i] = bval;
788 }
789}
790
791void ROOT::Experimental::RField<std::vector<bool>>::GenerateColumnsImpl()
792{
793 RColumnModel modelIndex(EColumnType::kIndex, true /* isSorted*/);
794 fColumns.emplace_back(std::unique_ptr<Detail::RColumn>(
795 Detail::RColumn::Create<ClusterSize_t, EColumnType::kIndex>(modelIndex, 0)));
796 fPrincipalColumn = fColumns[0].get();
797}
798
799std::vector<ROOT::Experimental::Detail::RFieldValue>
800ROOT::Experimental::RField<std::vector<bool>>::SplitValue(const Detail::RFieldValue& value) const
801{
802 const static bool trueValue = true;
803 const static bool falseValue = false;
804
805 auto typedValue = value.Get<std::vector<bool>>();
806 auto count = typedValue->size();
807 std::vector<Detail::RFieldValue> result;
808 for (unsigned i = 0; i < count; ++i) {
809 if ((*typedValue)[i])
810 result.emplace_back(fSubFields[0]->CaptureValue(const_cast<bool *>(&trueValue)));
811 else
812 result.emplace_back(fSubFields[0]->CaptureValue(const_cast<bool *>(&falseValue)));
813 }
814 return result;
815}
816
817
818void ROOT::Experimental::RField<std::vector<bool>>::DestroyValue(const Detail::RFieldValue& value, bool dtorOnly)
819{
820 auto vec = static_cast<std::vector<bool>*>(value.GetRawPtr());
821 vec->~vector();
822 if (!dtorOnly)
823 free(vec);
824}
825
826void ROOT::Experimental::RField<std::vector<bool>>::AcceptVisitor(Detail::RFieldVisitor &visitor) const
827{
828 visitor.VisitVectorBoolField(*this);
829}
830
831
832//------------------------------------------------------------------------------
833
834
836 std::string_view fieldName, std::unique_ptr<Detail::RFieldBase> itemField, std::size_t arrayLength)
837 : ROOT::Experimental::Detail::RFieldBase(
838 fieldName, "std::array<" + itemField->GetType() + "," + std::to_string(arrayLength) + ">",
839 ENTupleStructure::kLeaf, false /* isSimple */, arrayLength)
840 , fItemSize(itemField->GetValueSize()), fArrayLength(arrayLength)
841{
842 Attach(std::move(itemField));
843}
844
845std::unique_ptr<ROOT::Experimental::Detail::RFieldBase>
846ROOT::Experimental::RArrayField::Clone(std::string_view newName) const
847{
848 auto newItemField = fSubFields[0]->Clone(fSubFields[0]->GetName());
849 return std::make_unique<RArrayField>(newName, std::move(newItemField), fArrayLength);
850}
851
853 auto arrayPtr = value.Get<unsigned char>();
854 for (unsigned i = 0; i < fArrayLength; ++i) {
855 auto itemValue = fSubFields[0]->CaptureValue(arrayPtr + (i * fItemSize));
856 fSubFields[0]->Append(itemValue);
857 }
858}
859
861{
862 auto arrayPtr = value->Get<unsigned char>();
863 for (unsigned i = 0; i < fArrayLength; ++i) {
864 auto itemValue = fSubFields[0]->GenerateValue(arrayPtr + (i * fItemSize));
865 fSubFields[0]->Read(globalIndex * fArrayLength + i, &itemValue);
866 }
867}
868
870{
871 auto arrayPtr = value->Get<unsigned char>();
872 for (unsigned i = 0; i < fArrayLength; ++i) {
873 auto itemValue = fSubFields[0]->GenerateValue(arrayPtr + (i * fItemSize));
874 fSubFields[0]->Read(RClusterIndex(clusterIndex.GetClusterId(), clusterIndex.GetIndex() * fArrayLength + i),
875 &itemValue);
876 }
877}
878
880{
881}
882
884{
885 auto arrayPtr = reinterpret_cast<unsigned char *>(where);
886 for (unsigned i = 0; i < fArrayLength; ++i) {
887 fSubFields[0]->GenerateValue(arrayPtr + (i * fItemSize));
888 }
889 return Detail::RFieldValue(true /* captureFlag */, this, where);
890}
891
893{
894 auto arrayPtr = value.Get<unsigned char>();
895 for (unsigned i = 0; i < fArrayLength; ++i) {
896 auto itemValue = fSubFields[0]->CaptureValue(arrayPtr + (i * fItemSize));
897 fSubFields[0]->DestroyValue(itemValue, true /* dtorOnly */);
898 }
899 if (!dtorOnly)
900 free(arrayPtr);
901}
902
904{
905 return Detail::RFieldValue(true /* captureFlag */, this, where);
906}
907
908std::vector<ROOT::Experimental::Detail::RFieldValue>
910{
911 auto arrayPtr = value.Get<unsigned char>();
912 std::vector<Detail::RFieldValue> result;
913 for (unsigned i = 0; i < fArrayLength; ++i) {
914 auto itemValue = fSubFields[0]->CaptureValue(arrayPtr + (i * fItemSize));
915 result.emplace_back(itemValue);
916 }
917 return result;
918}
919
921{
922 visitor.VisitArrayField(*this);
923}
924
925//------------------------------------------------------------------------------
926
927#if __cplusplus >= 201703L
928std::string ROOT::Experimental::RVariantField::GetTypeList(const std::vector<Detail::RFieldBase *> &itemFields)
929{
930 std::string result;
931 for (size_t i = 0; i < itemFields.size(); ++i) {
932 result += itemFields[i]->GetType() + ",";
933 }
934 R__ASSERT(!result.empty()); // there is always at least one variant
935 result.pop_back(); // remove trailing comma
936 return result;
937}
938
939ROOT::Experimental::RVariantField::RVariantField(
940 std::string_view fieldName, const std::vector<Detail::RFieldBase *> &itemFields)
941 : ROOT::Experimental::Detail::RFieldBase(fieldName,
942 "std::variant<" + GetTypeList(itemFields) + ">", ENTupleStructure::kVariant, false /* isSimple */)
943{
944 auto nFields = itemFields.size();
945 R__ASSERT(nFields > 0);
946 fNWritten.resize(nFields, 0);
947 for (unsigned int i = 0; i < nFields; ++i) {
948 fMaxItemSize = std::max(fMaxItemSize, itemFields[i]->GetValueSize());
949 fMaxAlignment = std::max(fMaxAlignment, itemFields[i]->GetAlignment());
950 Attach(std::unique_ptr<Detail::RFieldBase>(itemFields[i]));
951 }
952 fTagOffset = (fMaxItemSize < fMaxAlignment) ? fMaxAlignment : fMaxItemSize;
953}
954
955std::unique_ptr<ROOT::Experimental::Detail::RFieldBase>
956ROOT::Experimental::RVariantField::Clone(std::string_view newName) const
957{
958 auto nFields = fSubFields.size();
959 std::vector<Detail::RFieldBase *> itemFields;
960 for (unsigned i = 0; i < nFields; ++i) {
961 // TODO(jblomer): use unique_ptr in RVariantField constructor
962 itemFields.emplace_back(fSubFields[i]->Clone(fSubFields[i]->GetName()).release());
963 }
964 return std::make_unique<RVariantField>(newName, itemFields);
965}
966
967std::uint32_t ROOT::Experimental::RVariantField::GetTag(void *variantPtr) const
968{
969 auto index = *(reinterpret_cast<char *>(variantPtr) + fTagOffset);
970 return (index < 0) ? 0 : index + 1;
971}
972
973void ROOT::Experimental::RVariantField::SetTag(void *variantPtr, std::uint32_t tag) const
974{
975 auto index = reinterpret_cast<char *>(variantPtr) + fTagOffset;
976 *index = static_cast<char>(tag - 1);
977}
978
979void ROOT::Experimental::RVariantField::AppendImpl(const Detail::RFieldValue& value)
980{
981 auto tag = GetTag(value.GetRawPtr());
982 auto index = 0;
983 if (tag > 0) {
984 auto itemValue = fSubFields[tag - 1]->CaptureValue(value.GetRawPtr());
985 fSubFields[tag - 1]->Append(itemValue);
986 index = fNWritten[tag - 1]++;
987 }
988 RColumnSwitch varSwitch(ClusterSize_t(index), tag);
989 Detail::RColumnElement<RColumnSwitch, EColumnType::kSwitch> elemSwitch(&varSwitch);
990 fColumns[0]->Append(elemSwitch);
991}
992
993void ROOT::Experimental::RVariantField::ReadGlobalImpl(NTupleSize_t globalIndex, Detail::RFieldValue *value)
994{
995 RClusterIndex variantIndex;
996 std::uint32_t tag;
997 fPrincipalColumn->GetSwitchInfo(globalIndex, &variantIndex, &tag);
998 R__ASSERT(tag > 0); // TODO(jblomer): deal with invalid variants
999
1000 auto itemValue = fSubFields[tag - 1]->GenerateValue(value->GetRawPtr());
1001 fSubFields[tag - 1]->Read(variantIndex, &itemValue);
1002 SetTag(value->GetRawPtr(), tag);
1003}
1004
1005void ROOT::Experimental::RVariantField::GenerateColumnsImpl()
1006{
1007 RColumnModel modelSwitch(EColumnType::kSwitch, false);
1008 fColumns.emplace_back(std::unique_ptr<Detail::RColumn>(
1009 Detail::RColumn::Create<RColumnSwitch, EColumnType::kSwitch>(modelSwitch, 0)));
1010 fPrincipalColumn = fColumns[0].get();
1011}
1012
1013ROOT::Experimental::Detail::RFieldValue ROOT::Experimental::RVariantField::GenerateValue(void *where)
1014{
1015 memset(where, 0, GetValueSize());
1016 fSubFields[0]->GenerateValue(where);
1017 SetTag(where, 1);
1018 return Detail::RFieldValue(this, reinterpret_cast<unsigned char *>(where));
1019}
1020
1021void ROOT::Experimental::RVariantField::DestroyValue(const Detail::RFieldValue& value, bool dtorOnly)
1022{
1023 auto variantPtr = value.GetRawPtr();
1024 auto tag = GetTag(variantPtr);
1025 if (tag > 0) {
1026 auto itemValue = fSubFields[tag - 1]->CaptureValue(variantPtr);
1027 fSubFields[tag - 1]->DestroyValue(itemValue, true /* dtorOnly */);
1028 }
1029 if (!dtorOnly)
1030 free(variantPtr);
1031}
1032
1033ROOT::Experimental::Detail::RFieldValue ROOT::Experimental::RVariantField::CaptureValue(void *where)
1034{
1035 return Detail::RFieldValue(true /* captureFlag */, this, where);
1036}
1037
1038size_t ROOT::Experimental::RVariantField::GetValueSize() const
1039{
1040 return fMaxItemSize + fMaxAlignment; // TODO: fix for more than 255 items
1041}
1042
1043void ROOT::Experimental::RVariantField::CommitCluster()
1044{
1045 std::fill(fNWritten.begin(), fNWritten.end(), 0);
1046}
1047#endif
1048
1049
1050//------------------------------------------------------------------------------
1051
1052
1054 std::string_view name,
1055 std::shared_ptr<RCollectionNTuple> collectionNTuple,
1056 std::unique_ptr<RNTupleModel> collectionModel)
1057 : RFieldBase(name, ":Collection:", ENTupleStructure::kCollection, true /* isSimple */)
1058 , fCollectionNTuple(collectionNTuple)
1059{
1060 for (unsigned i = 0; i < collectionModel->GetFieldZero()->fSubFields.size(); ++i) {
1061 auto& subField = collectionModel->GetFieldZero()->fSubFields[i];
1062 Attach(std::move(subField));
1063 }
1064}
1065
1066
1068{
1069 RColumnModel modelIndex(EColumnType::kIndex, true /* isSorted*/);
1070 fColumns.emplace_back(std::unique_ptr<Detail::RColumn>(
1071 Detail::RColumn::Create<ClusterSize_t, EColumnType::kIndex>(modelIndex, 0)));
1072 fPrincipalColumn = fColumns[0].get();
1073}
1074
1075
1076std::unique_ptr<ROOT::Experimental::Detail::RFieldBase>
1077ROOT::Experimental::RCollectionField::Clone(std::string_view /*newName*/) const
1078{
1079 // TODO(jblomer)
1080 return nullptr;
1081 //auto result = new RCollectionField(newName, fCollectionNTuple, RNTupleModel::Create());
1082 //for (auto& f : fSubFields) {
1083 // // switch the name prefix for the new parent name
1084 // std::string cloneName = std::string(newName) + f->GetName().substr(GetName().length());
1085 // auto clone = f->Clone(cloneName);
1086 // result->Attach(std::unique_ptr<RFieldBase>(clone));
1087 //}
1088 //return result;
1089}
1090
1092 *fCollectionNTuple->GetOffsetPtr() = 0;
1093}
1094
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:292
#define f(i)
Definition RSha256.hxx:104
#define R__ASSERT(e)
Definition TError.h:120
char name[80]
Definition TGX11.cxx:110
int type
Definition TGX11.cxx:121
#define free
Definition civetweb.c:1539
#define malloc
Definition civetweb.c:1536
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:70
Iterates over the sub tree of fields in depth-first search order.
Definition RField.hxx:114
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:318
virtual void GenerateColumnsImpl()=0
Creates the backing columns corresponsing to the field type and name.
std::vector< std::unique_ptr< RFieldBase > > fSubFields
Collections and classes own sub fields.
Definition RField.hxx:91
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:144
virtual void DestroyValue(const RFieldValue &value, bool dtorOnly=false)
Releases the resources acquired during GenerateValue (memory and constructor) This implementation wor...
Definition RField.cxx:257
friend class ROOT::Experimental::RCollectionField
Definition RField.hxx:75
void Flush() const
Ensure that all received items are written from page buffers to the storage.
Definition RField.cxx:288
virtual void CommitCluster()
Perform housekeeping tasks for global to cluster-local index translation.
Definition RField.hxx:213
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:264
static RResult< void > EnsureValidFieldName(std::string_view fieldName)
Check whether a given string is a valid field name.
Definition RField.cxx:229
virtual void AppendImpl(const RFieldValue &value)
Operations on values of complex types, e.g.
Definition RField.cxx:239
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:156
virtual void AcceptVisitor(RFieldVisitor &visitor) const
Definition RField.cxx:296
std::vector< const RFieldBase * > GetSubFields() const
Definition RField.cxx:278
virtual void ReadGlobalImpl(NTupleSize_t globalIndex, RFieldValue *value)
Definition RField.cxx:243
std::vector< std::unique_ptr< RColumn > > fColumns
The columns are connected either to a sink or to a source (not to both); they are owned by the field.
Definition RField.hxx:99
void Attach(std::unique_ptr< Detail::RFieldBase > child)
Add a new subfield to the list of nested fields.
Definition RField.cxx:269
RFieldValue GenerateValue()
Generates an object of the field type and allocates new initialized memory according to the type.
Definition RField.cxx:250
static void ConnectRecursively(DescriptorId_t fieldId, RPageSource &pageSource, RFieldBase &field)
Connect the field columns and all sub field columns.
Definition RField.cxx:127
static void Connect(DescriptorId_t fieldId, RPageStorage &pageStorage, RFieldBase &field)
Definition RField.cxx:118
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 VisitField(const Detail::RFieldBase &field)=0
virtual void VisitDoubleField(const RField< double > &field)
virtual void VisitArrayField(const RArrayField &field)
virtual void VisitClassField(const RClassField &field)
virtual void VisitVectorField(const RVectorField &field)
virtual void VisitFloatField(const RField< float > &field)
Abstract interface to read data from an ntuple.
const RNTupleDescriptor & GetDescriptor() const
Common functionality of an ntuple storage for both reading and writing.
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:909
Detail::RFieldValue CaptureValue(void *where) final
Creates a value from a memory location with an already constructed object.
Definition RField.cxx:903
void ReadInClusterImpl(const RClusterIndex &clusterIndex, Detail::RFieldValue *value) final
Definition RField.cxx:869
void ReadGlobalImpl(NTupleSize_t globalIndex, Detail::RFieldValue *value) final
Definition RField.cxx:860
RArrayField(std::string_view fieldName, std::unique_ptr< Detail::RFieldBase > itemField, std::size_t arrayLength)
Definition RField.cxx:835
void AcceptVisitor(Detail::RFieldVisitor &visitor) const final
Definition RField.cxx:920
void GenerateColumnsImpl() final
Creates the backing columns corresponsing to the field type and name.
Definition RField.cxx:879
size_t GetValueSize() const final
The number of bytes taken by a value of the appropriate type.
Definition RField.hxx:366
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:892
void AppendImpl(const Detail::RFieldValue &value) final
Operations on values of complex types, e.g.
Definition RField.cxx:852
std::unique_ptr< Detail::RFieldBase > Clone(std::string_view newName) const final
Definition RField.cxx:846
size_t GetAlignment() const final
For many types, the alignment requirement is equal to the size; otherwise override.
Definition RField.hxx:367
Detail::RFieldValue CaptureValue(void *where) final
Creates a value from a memory location with an already constructed object.
Definition RField.cxx:617
size_t GetValueSize() const override
The number of bytes taken by a value of the appropriate type.
Definition RField.cxx:638
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:624
std::unique_ptr< Detail::RFieldBase > Clone(std::string_view newName) const final
Definition RField.cxx:564
void AcceptVisitor(Detail::RFieldVisitor &visitor) const override
Definition RField.cxx:643
void AppendImpl(const Detail::RFieldValue &value) final
Operations on values of complex types, e.g.
Definition RField.cxx:569
void ReadInClusterImpl(const RClusterIndex &clusterIndex, Detail::RFieldValue *value) final
Definition RField.cxx:590
RClassField(std::string_view fieldName, std::string_view className)
Definition RField.cxx:547
void GenerateColumnsImpl() final
Creates the backing columns corresponsing to the field type and name.
Definition RField.cxx:601
void ReadGlobalImpl(NTupleSize_t globalIndex, Detail::RFieldValue *value) final
Definition RField.cxx:579
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:610
Addresses a column element or field item relative to a particular cluster, instead of a global NTuple...
DescriptorId_t GetClusterId() const
ClusterSize_t::ValueType GetIndex() const
std::unique_ptr< Detail::RFieldBase > Clone(std::string_view newName) const final
Definition RField.cxx:1077
void CommitCluster() final
Perform housekeeping tasks for global to cluster-local index translation.
Definition RField.cxx:1091
void GenerateColumnsImpl() final
Creates the backing columns corresponsing to the field type and name.
Definition RField.cxx:1067
Holds the static meta-data of a column in a tree.
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:363
std::unique_ptr< REntry > GenerateEntry() const
Generates managed values for the top-level sub fields.
Definition RField.cxx:354
std::unique_ptr< Detail::RFieldBase > Clone(std::string_view newName) const
Definition RField.cxx:345
Classes with dictionaries that can be inspected by TClass.
Definition RField.hxx:412
DescriptorId_t FindFieldId(std::string_view fieldName, DescriptorId_t parentId) const
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:196
Detail::RFieldValue CaptureValue(void *where) override
Creates a value from a memory location with an already constructed object.
Definition RField.cxx:722
void CommitCluster() final
Perform housekeeping tasks for global to cluster-local index translation.
Definition RField.cxx:740
void AcceptVisitor(Detail::RFieldVisitor &visitor) const final
Definition RField.cxx:745
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:728
void ReadGlobalImpl(NTupleSize_t globalIndex, Detail::RFieldValue *value) final
Definition RField.cxx:680
std::unique_ptr< Detail::RFieldBase > Clone(std::string_view newName) const final
Definition RField.cxx:661
void AppendImpl(const Detail::RFieldValue &value) final
Operations on values of complex types, e.g.
Definition RField.cxx:667
void GenerateColumnsImpl() final
Creates the backing columns corresponsing to the field type and name.
Definition RField.cxx:695
RVectorField(std::string_view fieldName, std::unique_ptr< Detail::RFieldBase > itemField)
Definition RField.cxx:651
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:708
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:3747
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:2957
All ROOT classes may have RTTI (run time type identification) support added.
Definition TDataMember.h:31
std::uint64_t NTupleSize_t
Integer type long enough to hold the maximum number of entries in a column.
RClusterSize ClusterSize_t
ENTupleStructure
The fields in the ntuple model tree can carry different structural information about the type system.
std::uint64_t DescriptorId_t
Distriniguishes elements of the same type within a descriptor, e.g. different fields.
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,...
tbb::task_arena is an alias of tbb::interface7::task_arena, which doesn't allow to forward declare tb...
TClass * GetClass(T *)
Definition TClass.h:658
Wrap the 32bit integer in a struct in order to avoid template specialization clash with std::uint32_t...